TASVideos

Tool-assisted game movies
When human skills are just not enough

Game Resources / SNES / Magic Knight Rayearth / RNG

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.


Combined RSS Feed
GameResources/SNES/MagicKnightRayearth/RNG last edited by FractalFusion on 2011-12-06 08:31:06
Page info and history | Latest diff | List referrers | View Source