View Page Source

Back to Page
Revision 2 (current)
Edited by adelikat on 6/9/2019 7:37 PM
First of all, C002AB is multiplication routine. It takes m23*m24 and stores it in m26-27 (2 bytes). C002E2 is the division routine.

Here's how the RNG works:

The RNG is stored in 7E0038-7E003B.

The RNG is modified by functions like these (not exhaustive):

Address C00342
STA $23
REP #$20
LDA $3A
EOR #$8020
STA $3A
LDA $38
ASL A
ASL A
CLC
ADC $38
ADC $3A
STA $38
SEP #$20
XBA
STA $24
JSR $02AB [[multiplication]]
LDA $27
RTS

Translation:
(16 bits)
m23:=A AND 0xFF
m3A:=m3A XOR 0x8020
A:=4*m38 AND 0xFFFF
A:=A+m38
if A>0xFFFF then C:=1 else C:=0
m38:=(A+m3A+C) AND 0xFFFF
m24:=m38 >> 8
m26:=m23*m24
return (m26 >> 8)  [[A]]

The function calculates a random number between 0 and (A AND 0xFF)-1. We'll call this function rand(X), for a random number between 0 and X-1.

All jumps to this routine use "JSR $0342"

!!Encounters

Address C02A89
LDA #$FA
JSR $0342 [[rand]]
CMP #$96
BCS $18 [[3]]
CMP #$8E
BCC $02 [[1]]
BRA $08 [[2]]
[[1]]
CMP #$32
BCS $0E [[3]]
CMP #$2A
BCC $0A [[3]]
[[2]]
LDA #$01
STA $07F9
LDA #$06
STA $07EA
[[3]]
RTS

Translation:
A:=rand(250)
if 142<=A<150 or 42<=A<50 then [[encounter]]

This determines encounters.

!!Pre-emptive attack on encounter

Address C086DC
LDA $07F9
CMP #$02
BEQ $12 [[1]]
LDA #$C8
JSR $0342 [[rand]]
LDX #$0002
CMP #$BE
BCS $06
DEX
CMP #$AA
BCS $01
DEX
[[1]]
TXA
STA $159A
BEQ $0D
RTS

Translation:
if m7F9==2 [[boss battle]] then Type:=0 exit
A:=rand(200)
if 190<=A<200 then Type:=2 exit
if 170<=A<190 then Type:=1 exit
Type:=0

Type 0: no pre-empt
Type 1: ally pre-empt
Type 2: enemy pre-empt

The function determines whether or not a pre-empt occurs. If an ally pre-empt occurs, all allies get a free round to attack first. If an enemy pre-empt occurs, all enemies get a free round to attack first. Boss battles cannot have pre-empts.

!!Accuracy of physical attacks

Address C08B9D
LDA $12,x
AND #$00FF
PHA
LDX $15A1
LDA $12,x
AND #$00FF
ADC #$0028
SEC
SBC $01,s [[push value]]
BCS $03 [[1]]
LDA #$0000
[[1]]
STA $2C
PLA
SEP #$20
LDA #$05
STA $30
JSR $02E2 [[division m32:=int(m2C/m30)]]
INC $32
INC $32
LDA $32
JSR $0342
DEC $32
CMP $32
BCC $09 [[2]]
LDX $15B0
LDA $35,x
ORA #$10
STA $35,x
[[2]]
RTS

Translation:

A:=DefAgl AND 0xFF
S:=A
A:=AtkAgl AND 0xFF
A:=A+40
A:=A-S
if A<0 then A:=0
m2C:=A
m30:=5
m32:=int(m2C/m30)+2
A:=rand(m32)
if A==m32-1 then [[attack miss]] else [[attack hit]]


!!Another RNG-related routine

Address C00363
STY $2A
REP #$20
LDA $38
ASL A
ASL A
CLC
ADC $38
ADC $3A
STA $38
STA $24
SEP #$20
JSR $025F [[multiplication]]
LDY $28
RTS

Y:=m2A AND 0xFFFF
A:=4*m38 AND 0xFFFF
A:=A+m38
if A>0xFFFF then C:=1 else C:=0
m38:=(A+m3A+C) AND 0xFFFF
m24:=m38
return m24*Y >> 16 [[Y]]

This is another rng-modifying function. The only difference between this function and rand(X) is that address m3A does not XOR by 0x8020, and that the multiplication uses 16-bits of RNG, rather than 8-bit.
Call this function rand2(Y)

!!Initial damage routine

Address C08BDB
REP #$20
STZ $0554
LDA $054E [[atk]]
SEC
SBC $0550 [[def]]
BCS $06 [[1]]
LDY #$0001
JMP $8C1F [[4]]
[[1]]
STA $2A
SEP #$20
LDA #$0A
STA $24
LDA $15AB
BIT #$80
BNE $02 [[2]]
LSR $24
[[2]]
JSR $0288 [[multiplication  m26:=m2A(16bit)*m24]]
LDA #$00
XBA
LDA $24
TAY
LDX $26
STX $0554
BEQ $0B   [[3]]
STX $2C
LDA #$0A
STA $30
JSR $02E2 [[division m32:=int(m2C/m30)]]
LDY $32
[[3]]
JSR $0363 [[rand2]]
INY
[[4]]
LDX $15B0
REP #$21
TYA
ADC $0554
STA $0554
CMP #$270F
BCC $03 [[5]]
LDA #$270F
[[5]]
STA $0554
SEP #$20
RTS

Translation:
m554:=0
A:=m54E [[atk]]
A:=A-m550 [[def]]
if A<0 then Damage:=1 exit
m2A:=A
if [[enemy attack]] then m24:=5 else m24:=10
m26:=m24*m2A
if m26==0 then Damage:=rand2(m24)+1 exit
m554:=m26
m2C:=m26
m30:=10
Y:=int(m2C/m30)
m554:=m554+rand2(Y)+1
if m554>9999 then m554:=9999
Damage:=m554

This routine calculates the initial damage. This is the final damage if it is magic/item attack. If it is physical attack, there may be critical hit applied later.

This routine only executes if the attack does not miss.

!!Magic damage (attack value)

Address C0964C
LDX $15A1
LDA $13,X
JSR $97D1 [[?]]
REP #$20
AND #$00FF
PHA
LDA $0546
AND #$00FF
CLC
ADC $01,S [[push value]]
STA $054E
LSR A
CLC
ADC $054E
STA $054E
PLA
SEP #$20
RTS

Translation:


S:=Wisdom [[cannot exceed 255]]
A:=m546  [[basepower of spell/item]] [[cannot exceed 255]]
A:=A+S
A:=A+int(A/2)
AtkValue:=A

This routine calculates the attack value of a spell/item.

!! Critical hit

Address C08A69
LDA #$1E
STA $02
LDA $159E [[?]]
BIT #$80
BEQ $02 [[1]]
ASL $02
[[1]]
LDX $15A1
LDA $3C,X
LSR A
BCC $02 [[2]]
LSR $02
[[2]]
LDA $02
JSR $0342 [[RAND]]
LSR $02
CMP $02
BNE $1C [[4]]
REP #$20
LDA $0554 [[DMG]]
ASL A
ADC $0554 [[DMG]]
CMP #$270F
BCC $03 [[3]]
LDA #$270F
[[3]]
STA $0554
SEP #$20
LDA #$00
JSR $AAD2 [[GREATEST ATTACK?]]
RTS
[[4]]
LDA #$14
STA $02
LDA $159E
BIT #$80
BEQ $02[[5]]
ASL $02
[[5]]
LDX $15A1
LDA $3C,X
LSR A
LSR A
BCC $02[[6]]
LSR $02
[[6]]
LDA $02
JSR $0342 [[RAND]]
LSR $02
CMP $02
BNE $18 [[8]]
REP #$20
LDA $0054 [[DMG]]
ASL A
CMP #$270F
BCC $03 [[7]]
LDA #$270F
[[7]]
STA $0554
SEP #$20
LDA #$01
JSR $AAD2 [[CRUSHING ATTACK?]]
[[8]]
RTS

Translation:

m2:=30
if [[unknown thing]] then m2:=2*m2
if [[modifier]] then m2:=int(m2/2)
A:=rand(m2)
if A==int(m2/2) then m554:=max(3*m554,9999) exit [[greatest attack]]
m2:=20
if [[unknown thing]] then m2:=2*m2
if [[modifier2]] then m2:=int(m2/2)
A:=rand(m2)
if A==int(m2/2) then m554:=max(2*m554,9999) exit [[crushing attack]]

This routine first determines whether an attack is a GREATEST ATTACK (1/30 probability). If it is, damage is multiplied by 3, max damage 9999. If an attack is not a GREATEST ATTACK, the routine determines whether an attack is a CRUSHING ATTACK (1/20 probability). If so, damage is multiplied by 2.

This routine only executes if the attack does not miss. The CRUSHING ATTACK part only executes if the attack is not a GREATEST ATTACK.