If you appreciate the work done within the wiki, please consider supporting The Cutting Room Floor on Patreon. Thanks for all your support!

Notes:Magic Jewelry

From The Cutting Room Floor
Jump to navigation Jump to search

This page contains notes for the game Magic Jewelry.

Anti-piracy

CHR Checksum

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.

PRG Checksum

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