ZELDA 3 - Time + Day/Night v1.1 - by JaSp

View previous topic View next topic Go down

Re: ZELDA 3 - Time + Day/Night v1.1 - by JaSp

Post by qwertymodo on Mon 9 May 2016 - 18:35

JaSp wrote:
ZELDA3 TIME + DAY/NIGHT SYSTEM v1.1
===================================
Made by
JaSp
Thanks to
MathOnNapkins' "ZeldaFlow" document and help
Euclid's status bar explanations and help
d4s' help
Byuu's xkas assembler
Geiger's Snes9x Debugger
FuSoYa's zcompress utility

Last update : September, 6 2006
-----------------------------
History:
--------
v2.0:
*Major improvement: complete system re-write. The night effect works on the palettes now, and it works in all situations : layers, mosaic, HDMA warping, sub-areas...
v1.1:
*fixed the pause and save dialog box problems, time no longer increases when a dialog box is openned
v1.0:
*first release

/!\ The IPS PATCH is for an US headered ROM whereas /!\
/!\ the ASM PATCH is for an US headerless ROM       /!\

This archive contains :
=======================
*readme_z3 time system.txt this readme file
*z3_time+daynight_source.asm source asm file for use with an assembler on a unheadered Zelda3 ROM
*Zelda3 Time&DayNight_v2.ips ips patch to apply to a headered Zelda3 ROM
*ZeldaGFX.bin graphics file for use with zcompress (http://fusoya.panicus.org/zelda/index.html) containing the "Time-" graphics for HUD

So, what is it ?
================
This patch adds a time control (hours/minutes) to "Zelda 3 : A link to the Past", with a Day/Night handler using this new time feature.
A time indicator has been added to the status bar, showing the hours and minutes. The format is as 24-hour clock, that means from 00:00 to 23:59.
The Day/Night works as follow : on each hour, the palette is updated and changed according to 3 tables telling how many units to substract from the original palette color.
The color units to substract are editable within the ASM source file.
The system is currently set so that 12 real-life minutes correspond to 24 in-game hours, according that the game runs at 60 fps (1 minute in the game = 0.5 real second).
This is also editable within the ASM patch.

Code:
lorom

;/!\ Patch designed for a HEADERLESS Zelda3 US ROM /!\
;-----------------------------------------------
; ZELDA 3 - Time + Day/Night handling code v2.0
;  by JaSp
;
;Last update: September, 6 2006
;
; This patch just adds a timer and a day/night
; handling system.
; Take a look at the readme for further details.
;
; If you have any questions or bug reports :
; jaspile(at)hotmail.com
;
;Thanks to
;  MathOnNapkins' "ZeldaFlow" document & Help
;  Euclid's status bar explanations & Help
;  d4s' Help
;  Geiger's Snes9x Debugger
;  FuSoYa's zcompress utility
;-----------------------------------------------


;-----------------------------------------------
;----------------[ Time system ]----------------
;-----------------------------------------------

; tiles locations on HUD (status bar)
!hud_min_low = $7EC79E
!hud_min_high = $7EC79C
!hud_hours_low = $7EC798
!hud_hours_high = $7EC796
!hud_template = $0DFF07

org !hud_template

 db $10,$24,$11,$24,$12,$24,$90,$24,$90,$24,$13,$24,$90,$24,$90,$24 ;HUD Template(adjusts timer's color)
 
org $068361

 jsl $1CFF30 ;originally JSL $09B06E, executed every frame

org $1CFF30

 jsr counter_preroutine
 ldx #$00
debut:
 ldy #$00
 lda $7EE000,x
debut2:
 cmp #$0A
 bmi draw
 sbc #$0A
 iny
 bra debut2

draw:
 adc #$90
 cpx #$01
 beq minutes_low
 sta !hud_hours_low
 bra 04

minutes_low:
 sta !hud_min_low
 tya
 clc
 adc #$90
 cpx #$01
 beq minutes_high
 sta !hud_hours_high
 bra 04

minutes_high:
 sta !hud_min_high
 inx
 cpx #$02
 bmi debut
 jsl $09B06E
 rtl

;--------------------------------

counter_preroutine:
 lda $10 ;checks current event in game
 cmp #$07 ;dungeon/building?
 beq counter_increasing
 cmp #$09 ;overworld?
 beq overworld
 cmp #$0B
 beq overworld ;sub-area ? (under the bridge; zora domain...)
 cmp #$0E ;dialog box?
 beq dialog
 rts

overworld:
 lda $11
 cmp #$23 ;hdma transfer? (warping)
 bne mosaic
mosaic:
 cmp #$0D ;mosaic ?
 bmi counter_increasing
 rts

dialog:
 lda $11 ;which kind of dialog? (to prevent the counter from increasing if save menu or item menu openned)
 cmp #$02 ;NPC/signs speech
 beq counter_increasing
 rts

counter_increasing:
 lda $1A
 and #$05 ;change value (1,3,5,7,F,1F,3F,7F,FF) to have different time speed, #$3F is almost 1 sec = 1 game minute
 beq increase_minutes
end:
 rts

increase_minutes:
 lda $7EE001
 inc a
 sta $7EE001
 cmp #$3C ; minutes = #60 ?
 bpl increase_hours
 rts

increase_hours:
 lda #$00
 sta $7EE001
 lda $7EE000
 inc a
 sta $7EE000
 cmp #$18 ; hours = #24 ?
 bpl reset_hours

 lda $1B ;check indoors/outdoors
 beq outdoors0
 rts
outdoors0:
 jsl rom_to_buff ;update buffer palette
 jsl buff_to_eff ;update effective palette
 lda $8C
 cmp #$9F ;rain layer ?
 beq skip_bg_updt0
 jsl $0BFE70 ;update background color
 bra inc_hours_end
 
skip_bg_updt0: ;prevent the sub layer from disappearing ($1D zeroed)
 jsl $0BFE72
inc_hours_end:
 rts

reset_hours:
 lda #$00
 sta $7EE000

 lda $1B ;check indoors/outdoors
 beq outdoors1
 rts
outdoors1:
 jsl rom_to_buff
 jsl buff_to_eff
 lda $8C
 cmp #$9F ;rain layer ?
 beq skip_bg_updt1
 jsl $0BFE70 ;update background color
 bra reset_end
 
skip_bg_updt1: ;prevent the sub layer from disappearing ($1D zeroed)
 jsl $0BFE72
reset_end:
 rts
;-----------------------------------------------
;----[ Day / Night system * palette effect ]----
;-----------------------------------------------

!blue_value = $7EE010
!green_value = $7EE012
!red_value = $7EE014

!temp_value = $7EE016
!pal_color = $7EE018
!x_reg = $08


org $02FF70 ; free space on bank $02

buff_to_eff:
 jsr $C769 ; $02:C65F -> palette buffer to effective routine
 rtl
rom_to_buff:
 jsr $AAF4 ; $02:AAF4 -> change buffer palette of trees,houses,rivers,etc.
 jsr $C692 ; $02:C692 -> rom to palette buffer for other colors
 rtl

; part of rom pal to buffer routine
;$1B/EF61 9F 00 C3 7E STA $7EC300,x[$7E:C422]
;$1B/EF3D 9F 00 C3 7E STA $7EC300,x[$7E:C412]
;$1B/EF84 9F 00 C3 7E STA $7EC300,x[$7E:C4B2]


org $1BEF3D
 jsl new_palette_load
org $1BEF61
 jsl new_palette_load
org $1BEF84
 jsl new_palette_load



org $0EEE25 ; free space

new_palette_load:

 sta !pal_color

 cpx #$0041
 bpl title_check
 sta $7EC300,x
 rtl
title_check:
 lda $10
 and #$00FF
 cmp #$0002 ; title or file select screen ?
 bpl outin_check
 lda !pal_color
 sta $7EC300,x
 rtl
outin_check:
 lda $1B
 and #$00FF
 beq outdoors2
 lda !pal_color
 sta $7EC300,x
 rtl

outdoors2:
 phx
 jsl color_sub_effect
 plx
 sta $7EC300,x
 rtl

;--------------------------------

color_sub_effect:
 lda $7EE000 ; lda #hours
 and #$00FF
 clc
 adc $7EE000 ; #hours * 2
 and #$00FF
 tax


do_blue:
 LDA !pal_color
 AND #$7C00
 STA !blue_value
 SEC
 SBC blue_table,x ; substract amount to blue field based on a table
 STA !temp_value
 AND #$7C00 ; mask out everything except the blue bits
 CMP !temp_value ; overflow ?
 BEQ no_blue_sign_change
blue_sign_change:
 LDA #$0400 ; lda smallest blue value
no_blue_sign_change:
 STA !blue_value

do_green:
 LDA !pal_color
 AND #$03E0
 STA !green_value
 SEC
 SBC green_table,x ; substract amount to blue field based on a table
 STA !temp_value
 AND #$03E0 ; mask out everything except the green bits
 CMP !temp_value ; overflow ?
 BEQ no_green_sign_change
green_sign_change:
 LDA #$0020 ; lda smallest green value
 no_green_sign_change:
 STA !green_value
 
do_red:
 LDA !pal_color
 AND #$001F
 STA !red_value
 SEC
 SBC red_table,x ; substract amount to red field based on a table
 STA !temp_value
 AND #$001F ; mask out everything except the red bits
 CMP !temp_value ; overflow ?
 BEQ no_red_sign_change
red_sign_change:
 LDA #$0001 ; lda smallest red value
no_red_sign_change:
 STA !red_value

 LDA !blue_value
 ORA !green_value
 ORA !red_value
 
 rtl


; color_sub_tables : 24 * 2 bytes each = 48 bytes (2 bytes = 1 color sub for each hour)


blue_table:
 dw $1000, $1000, $1000, $1000, $1000, $1000, $1000, $0800, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0400, $0800, $0800, $0800, $1000, $1000, $1000

green_table:
 dw $0100, $0100, $0100, $0100, $0100, $00C0, $0080, $0040, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0020, $0040, $0080, $00C0, $0100, $0100, $0100

red_table:
 dw $0008, $0008, $0008, $0008, $0008, $0006, $0004, $0002, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0002, $0004, $0006, $0008, $0008


background_fix:
 beq no_effect ;branch if A=#$0000 (transparent bg)
 jsl color_sub_effect
no_effect:
 sta $7EC500
 sta $7EC300
 sta $7EC540
 sta $7EC340
 rtl


subareas_fix:
 sta !pal_color
 phx
 jsl color_sub_effect
 plx
 STA $7EC300
 STA $7EC340
 rtl


thunder_fix:
 STA $7EC570,x
 LDA $F507,y
 sta !pal_color
 phx
 jsl color_sub_effect
 plx
 STA $7EC590,x ; 17 bytes instead of 7
 LDA $F515,y
 sta !pal_color
 phx
 jsl color_sub_effect
 plx
 STA $7EC5E0,x ; 17 bytes instead of 7
 LDA $F523,y
 sta !pal_color
 phx
 jsl color_sub_effect
 plx
 STA $7EC5F0,x ; 17 bytes instead of 7
 rts


gloves_fix:
 sta !pal_color
 lda $1B
 and #$00FF
 beq outdoors3
 lda !pal_color
 STA $7EC4FA
 rtl
outdoors3:
 phx
 jsl color_sub_effect
 plx
 STA $7EC4FA
 rtl



; $0BFE70 -> background color loading routine
;Background color write fix - 16 bytes
;$0B/FEB6 8F 00 C5 7E STA $7EC500
;$0B/FEBA 8F 00 C3 7E STA $7EC300
;$0B/FEBE 8F 40 C5 7E STA $7EC540
;$0B/FEC2 8F 40 C3 7E STA $7EC340

org $0BFEB6

 sta !pal_color
 jsl background_fix
 nop #8

; Subareas background color fix (under the bridge; zora...)
;$0E/D601 8F 00 C3 7E STA $7EC300[$7E:C300]
;$0E/D605 8F 40 C3 7E STA $7EC340[$7E:C340]

org $0ED601

 jsl subareas_fix

;--------------------------------

; Death Mountain thunder routine:
;$0E/F5F1 B9 EB F4    LDA $F4EB,y[$0E:F4EB]
;$0E/F5F4 9F 60 C5 7E STA $7EC560,x[$7E:C562]
;$0E/F5F8 B9 F9 F4    LDA $F4F9,y[$0E:F4F9]
;$0E/F5FB 9F 70 C5 7E STA $7EC570,x[$7E:C572]
;$0E/F5FF B9 07 F5    LDA $F507,y[$0E:F507]
;$0E/F602 9F 90 C5 7E STA $7EC590,x[$7E:C592]
;$0E/F606 B9 15 F5    LDA $F515,y[$0E:F515]
;$0E/F609 9F E0 C5 7E STA $7EC5E0,x[$7E:C5E2]
;$0E/F60D B9 23 F5    LDA $F523,y[$0E:F523]
;$0E/F610 9F F0 C5 7E STA $7EC5F0,x[$7E:C5F2]
;
; 35 bytes



org $0EF5F1

 LDA $F4EB,y
 sta !pal_color
 phx
 jsl color_sub_effect
 plx
 STA $7EC560,x
 LDA $F4F9,y
 sta !pal_color
 phx
 jsl color_sub_effect
 plx
 jsr thunder_fix ; (jsr since it's from bank $0E)
 nop #2

;--------------------------------
 
; Gloves color loading routine
;$1B/EE1B C2 30       REP #$30                
;$1B/EE1D AF 54 F3 7E LDA $7EF354[$7E:F354]  
;$1B/EE21 29 FF 00    AND #$00FF              
;$1B/EE24 F0 0F       BEQ $0F    [$EE35]      
;$1B/EE26 3A          DEC A                  
;$1B/EE27 0A          ASL A                  
;$1B/EE28 AA          TAX                    
;$1B/EE29 BF F5 ED 1B LDA $1BEDF5,x[$1B:EDF7]
;$1B/EE2D 8F FA C4 7E STA $7EC4FA[$7E:C4FA]  
;$1B/EE31 8F FA C6 7E STA $7EC6FA[$7E:C6FA]  
;$1B/EE35 E2 30       SEP #$30                
;$1B/EE37 E6 15       INC $15    [$00:0015]  
;$1B/EE39 6B          RTL                    

org $1BEE2D

 jsl gloves_fix
How to use it for my custom asm hacks ?
=======================================
RAM Addresses :
Hours $7EE000
Minutes $7EE001

How does the ASM source file work ?
===================================
This file is for use with an assembler, I used xkas (http://byuu.cinnamonpirate.com/?page=utils) so it is fully compatible with this assembler.
The code is quite commented, though you may only want to just change the counter_increasing value (to have faster/slower minutes) or the color_sub_tables.
Here is a little help for the units to substract with the tables :

val BLUE GREEN RED
----------------------------
00 0000 0000 0000
01 0400 0020 0001
02 0800 0040 0002
03 0C00 0060 0003
04 1000 0080 0004
05 1400 00A0 0005
06 1800 00C0 0006
07 1C00 00E0 0007
08 2000 0100 0008
09 2400 0120 0009
0A 2800 0140 000A
0B 2C00 0160 000B
0C 3000 0180 000C
0D 3400 01A0 000D
0E 3800 01C0 000E
0F 3C00 01E0 000F
10 4000 0200 0010
11 4400 0220 0011
12 4800 0240 0012
13 4C00 0260 0013
14 5000 0280 0014
15 5400 02A0 0015
16 5800 02C0 0016
17 5C00 02E0 0017
18 6000 0300 0018
19 6400 0320 0019
1A 6800 0340 001A
1B 6C00 0360 001B
1C 7000 0380 001C
1D 7400 03A0 001D
1E 7800 03C0 001E
1F 7C00 03E0 001F

I prefer to work with hex editors
=================================
Time speed control is at 0xE8198 (headered ROM), current value is 1F.
Change it to a value as 1,3,5,7,F,1F,3F,7F,FF to keep it increasing periodically.
Color tables :
Blue is at 0x770EA
Green is at 0x7711A
Red is at 0x7714A
Two bytes per color (low byte, high byte*), 24 colors per table. Use the table above for help.
* example : 34 12 in hex will be $1234 in the game.


Contact Informations
====================
E-mail/MSN : jaspile@hotmail.com (be sure to mention a related object for your mail)
Homepage (currently only for my SMB3 hack) : http://klikechange.free.fr/smb3-sud/

You are allowed to share this patch or link it anywhere, as long as the archive isn't modified and that you don't say you made it.
You are allowed to release a modified version of the asm source if you don't claim the whole code as your own.
When used in hack, credit is recommended though not necessary.

Here's the link to the patch: https://www.dropbox.com/s/oe5x8w9d0yr5ra8/Z3-Time%26DayNight-FINAL.zip

2 small changes to this patch:

First, a minor bug fix.  If you get turned into a bunny indoors by the golden star sprite, or use Ether, the palette transformation is applied to Link's sprite based on the current time of day, most noticeable at night because it makes him appear dark.  The fix is to check if you're indoors before applying the palette transform.  I figured this out for PW, but I'm not 100% sure which subroutines are which in PW vs the original patch here, so I'll just link to the PW fix, and leave it as an exercise to the reader to apply the fix properly.

https://www.zeldix.net/t1087-parallel-worlds-indoor-night-palette-glitch-fix

Essentially, before one of the jsl color_sub_effect subroutine calls (or even before all of them, just to be safe, but in PW I only ended up needing to apply it to one), check the value of $1B.  0=outdoors, call color_sub_effect, 1=indoors, don't call it.

Second, I wanted to add the ability to manually set the time that you exit the church for the first time, for consistency's sake.  Personally, I chose to set the time to 04:30 for PW (so it's dark as you walk out, but the first palette change occurs very soon after exiting, to be more noticeable to the player), but this is easily changed.  The easiest place to set this is right at the point where the game progress indicator is set to $02, which is actually right as Zelda walks to her place in the sanctuary, so time progresses during the discussion in the sanctuary, but it's good enough.

Code:
seek($05EDE6)
    jsl reset_clock

Code:
seek($2483D0) // This is the location I used for PW, can be relocated to any free space
reset_clock:
    lda #$04 // hours: $00-$17
    sta $7EE000
    lda #$20 // minutes: $00-$3B
    sta $7EE001
    jml $00FC62
avatar
qwertymodo



Since : 2014-10-21

Back to top Go down

Re: ZELDA 3 - Time + Day/Night v1.1 - by JaSp

Post by Puzzledude on Tue 10 May 2016 - 7:02

qwerty, do you know, how to turn this ASM off, ie NOP it out. I'm just asking, since sometimes in a night mode in a combo of the forest (or other) overlay the game is way to dark.
And I've never seen PW with this feature turned off.
avatar
Puzzledude



Since : 2012-06-20

Back to top Go down

Re: ZELDA 3 - Time + Day/Night v1.1 - by JaSp

Post by qwertymodo on Tue 10 May 2016 - 10:08

It's not as simple as NOPing out code, unfortunately. However, I did manage to do the legwork to figure out how to force time to stop during part 0 and 1 so it doesn't end up looking like day time in the middle of the rain storm. I could probably do something similar with the overlays, but I'd have to figure out how to save and restore the actual time when you leave.

In PW, if you wanted to just completely disable it, probably the easiest way would be to overwrite at $24816C with

Code:
lda $7EE018
sta $7EC300,x
rtl

But I haven't tested it. I have a feeling it might just make it always night instead, because the "midnight" palette is the one used at index 0 of the lookup table in PW (I changed this in 1.2 so when you load your game, it starts at "noon" instead). And if you were to rotate the lookup table, like I did, then you'd end up with it being full daylight during part 0, which would be weird. So it would probably require a more complicated approach.
avatar
qwertymodo



Since : 2014-10-21

Back to top Go down

Re: ZELDA 3 - Time + Day/Night v1.1 - by JaSp

Post by qwertymodo on Mon 13 Jun 2016 - 13:29

Looks like I actually went ahead and just made everything harder for myself for no real reason.  No need to rotate the color palette in PW, I just accidentally overwrote the subroutine responsible for setting the time when you load your save file.  Derp.

However, I would like to change the time that it sets.  In PW, when you load your save file, it sets the clock to 10:00.  To set it to 12:00 instead, change

Code:
0x03FE0E: $0A -> $0C
avatar
qwertymodo



Since : 2014-10-21

Back to top Go down

Re: ZELDA 3 - Time + Day/Night v1.1 - by JaSp

Post by Trovsky on Mon 13 Jun 2016 - 13:50

Good job qwertymodo. Keep up the good work.

Trovsky
Blacksmith
Blacksmith

Since : 2014-04-10

Back to top Go down

Re: ZELDA 3 - Time + Day/Night v1.1 - by JaSp

Post by zorazer0 on Sat 25 Jun 2016 - 17:51

I'd love to see this updated honestly, I ADORE this idea.. but it makes the cycle way too fast, each day/night is about 30 seconds, maybe 10
avatar
zorazer0
Cucumber
Cucumber

Since : 2014-04-08

Back to top Go down

View previous topic View next topic Back to top


 
Permissions in this forum:
You cannot reply to topics in this forum