Author Topic: cast timer / menu bug  (Read 1233 times)

Praetarius5018

  • Octomammoth
  • *
  • Posts: 23
    • View Profile
cast timer / menu bug
« on: June 01, 2015, 12:00:50 PM »
Not a 100% perfect thing, but so far it seems to work.

some background information
$7E:2040 - pointer to 1st hero (e.g. F060)
$7E:2042 - pointer to 2nd hero
$7E:2044 - pointer to 3rd hero
$7E:2046 - pointer to 1st enemy
$7E:2048 - pointer to 2nd enemy
$7E:204A - pointer to 3rd enemy

all of these have a pointer that tells them if they are present:
+$04, non-0 means is on screen, e.g. 7F:F064

+$5B, e.g. 7F:F0BB - is 0 while you can act
   1 in ring menu, 2 in main menu, 1 or 2 while casting or spell animation runs or during events
   1 or 2 during map transition, anything higher means world map - so we should do nothing then

+$8A, e.g. 7F:F0EA, has the flag if anyone is in the menu, AND $04 tells us that

and last there's +$57 (2 bytes), e.g. 7F:F0B7, which is the pointer to the timer of the current action

those timer objects are 16 bytes each
00, 01 - tells us the next timer in the list (the whole thing should be a ordered list, it isn't)
02, 03 - (unknown)
04, 05 - time stamp in frames when the action is to be executed
06, 07 - original duration from start of timer until its execution
08, 09 - if 0 the timer is active, non-0 means the timer is stopped and this value is the remaining duration after resuming
0A, 0B - (unknown)
0C..0F - identifies the type of action


7F00C6 (2 bytes) holds the current time stamp in frames and gets updated exactly once per frame there:
Code: [Select]
$C0/CC63 C2 30       REP #$30                A:0000 X:000A Y:1CC0 P:envmxdIZC
$C0/CC65 EE C6 00    INC $00C6  [$7F:00C6]   A:0000 X:000A Y:1CC0 P:envmxdIZC

instead put a JSL to some free space and put there:
Code: [Select]
C2 30 REP #$30
48 PHA
DA PHX
5A PHY
AD C6 00 LDA $00C6 [$7F:00C6]
29 07 00 AND #$07 <- run only once every 8th frame
C9 07 00 CMP #$07
D0 04 BNE 04
22 xy xyxy JSL <- run tick updater
7A PLY
FA PLX
68 PLA
EE C6 00 INC $00C6  [$7F:00C6]
6B RTL

tick updater:
Code: [Select]
A2 40 20 LDX #$2040
A0 06 00 LDY #$06
===LOOP START===
DA PHX
5A PHY
BF 00 00 7E LDA 7E0000, x
F0 2D BEQ <- no one there, skip checks
===checks start===
AA TAX
BD 04 00 LDA $0004,x[$7F:F064] - 0 while not present
F0 27 BEQ <- was 0, go to checks end
BD 5B 00 LDA $0004,x[$7F:F0BB] - 2 while casting, >> 2 while on world map
29 FF 00 AND #$00FF
C9 10 00 CMP #$10
90 04 BCC <- $10 or more, go to end of entire function
--go to end--
7A PLY
FA PLX
80 21 BRA
--else--
C9 02 00 CMP #$02 <- 2 = casts a spell right now, go to update timer
90 04 BCC
--go to update timer--
7A PLY
FA PLX
80 19 BRA
--else--
BD 8A 00 LDA $0004,x[$7F:F0EA] - 4 is set while in menu, 1 seems to be movement related; enemies can have non-sensical values here sometimes... D255
29 05 00 AND #$05
C9 04 00 CMP #$04
D0 04 BNE <- was not set, go to checks end
---go to update timer--
7A PLY
FA PLX
80 0A BRA
===checks end===
7A PLY
FA PLX
E8 INX
E8 INX
88 DEY
F0 02 BEQ leave loop if 0
80 C2 BRA go to start of loop
===LOOP END===
6B RTL
===update timers===
A2 40 20 LDX #$2040
A0 03 00 LDY #$03
===START UPDATE LOOP===
DA PHX
5A PHY
BF 00 00 7E LDA 7E0000, x
F0 23 BEQ <- no one there, skip
===CHECK===
A8 TAY
BE 57 00 LDX $0057,y[$7F:F0B7] <- pointer to spell data
F0 1D BEQ
BD 0E 00 LDA $000E,x[$7F:19BE] <- timer type, 21D3 is spell preparation
EA EA EA
C9 D3 21 CMP #$21D3
D0 12 BNE
BD 0C 00 LDA $000C,x[$7F:19BC] <- timer type, D064 is spell
C9 64 D0 CMP #$D064
D0 0A BNE
BD 04 00 LDA $0004,x[$7F:19F4]
18 CLC
69 08 00 ADC #$0008
9D 04 00 STA $0008,x[$7F:19F4]
===END CHECK===
7A PLY
FA PLX
E8 INX
E8 INX
88 DEY
F0 02 BEQ leave loop if 0
80 CC BRA go to start of loop
===END UPDATE LOOP===
===end update timers===
6B RTL


I run this only every 8 frame because I've put a few more changes in that routine (e.g. passive MP regeneration)

edit: added check against false menu positive
« Last Edit: June 13, 2015, 07:57:45 AM by Praetarius5018 »