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.

GameResources/SNES/MagicKnightRayearth/RNG last edited by adelikat on 6/9/2019 7:37 PM