Jump to navigation Jump to search
This page contains notes for the game Magic Jewelry.
The following is the CHR checksum that occurs when a new game is started.
- Tile bitmaps are stored at $0000-$1FFF in the PPU's address map.
- Magic Jewelry only uses $0000-$0FFF for graphics, so this routine only checks $0000-$0FFF.
- The expected checksum is hardcoded into this routine.
$E510:A2 00 LDX #$00 $E512:8E 06 20 STX $2006 ; Set PPU address to $0000 $E515:8E 06 20 STX $2006 $E518:8E F5 05 STX $05F5 ; This address will hold LSB of the calculated checksum $E51B:8E F6 05 STX $05F6 ; And this, the MSB $E51E:A0 10 LDY #$10 $E520:AD 07 20 LDA $2007 ; The NES requires a dummy read before you start reading from the PPU $E523:18 CLC $E524:AD 07 20 LDA $2007 ; Read a byte of graphics data (PPU automatically advances to next byte after this) $E527:6D F5 05 ADC $05F5 ; Add it to the LSB of the current total $E52A:8D F5 05 STA $05F5 ; Store updated LSB $E52D:A9 00 LDA #$00 $E52F:6D F6 05 ADC $05F6 ; Add carry to MSB $E532:8D F6 05 STA $05F6 ; Store updated MSB $E535:CA DEX $E536:D0 EB BNE $E523 ; Loop 256 times $E538:88 DEY $E539:D0 E8 BNE $E523 ; Loop 16 times (loop runs a total of 256 * 16 = 4096 times) $E53B:AD F5 05 LDA $05F5 ; Compare the LSB of the calculated checksum $E53E:C9 14 CMP #$14 ; with the expected value $E540:D0 07 BNE $E549 ; If the LSB doesn't match, die $E542:AD F6 05 LDA $05F6 : Do the same for the MSB $E545:C9 11 CMP #$11 $E547:F0 01 BEQ $E54A ; If the MSB does match, don't die $E549:60 RTS ; Uh oh! CPU jumps to $0000, executes garbage, and crashes.
The following is the PRG checksum routine that occurs during a level up.
- Magic Jewelry's code is only 8k, and runs in $E000-$FFFF of the NES's address space.
- At $E000 is the 16-bit checksum that the game is expecting. If the actual calculated checksum does not match this value, the check fails and the program purposely crashes.
- This checksum routine only actually checks $E002-$FDFF. $FE00-$FFFF may be reserved for bootstrap code, which can vary from multicart to multicart.
$E767:A9 20 LDA #$20 ; Initialize ram for checksum $E769:85 02 STA $0002 $E76B:A0 00 LDY #$00 $E76D:84 00 STY $0000 $E76F:8C F3 05 STY $05F3 $E772:8C F4 05 STY $05F4 $E775:98 TYA $E776:38 SEC $E777:E5 02 SBC $0002 $E779:85 01 STA $0001 ; = $E0 $E77B:E6 00 INC $0000 $E77D:E6 00 INC $0000 ; $00-$01 is a pointer to E002 now $E77F:18 CLC $E780:AD F3 05 LDA $05F3 $E783:71 00 ADC ($00),Y ; Add a byte from ROM to the total $E785:8D F3 05 STA $05F3 $E788:AD F4 05 LDA $05F4 $E78B:69 00 ADC #$00 ; Add carry to the MSB of the total $E78D:8D F4 05 STA $05F4 $E790:18 CLC $E791:A5 00 LDA $0000 $E793:69 01 ADC #$01 ; Update pointer to the next byte in ROM $E795:85 00 STA $0000 $E797:A5 01 LDA $0001 $E799:69 00 ADC #$00 ; Add carry to MSB $E79B:85 01 STA $0001 $E79D:18 CLC $E79E:69 02 ADC #$02 ; Stop reading bytes when we get to $FE00 $E7A0:90 DD BCC $E77F $E7A2:AD F3 05 LDA $05F3 ; Compare the LSB of the total $E7A5:4D 00 E0 EOR $E000 ; against its expected value $E7A8:D0 0B BNE $E7B5 ; Die if it doesn't match $E7AA:AD F4 05 LDA $05F4 ; Same, but with the MSB $E7AD:4D 01 E0 EOR $E001 $E7B0:D0 03 BNE $E7B5 ; Die if it doesn't match $E7B2:4C 8B E5 JMP $E58B ; Checksum matched, don't die $E7B5:60 RTS ; Same as CHR; jumps to $0000, CPU crashes after trying to execute garbage