SHARE
TWEET

Game Boy CRC16 routine

ISSOtm Oct 13th, 2018 (edited) 110 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; Context:
  2. ; - CRCs are stored little-endian starting at $0150
  3. ; - One CRC is computed per ROM bank
  4. ; - Assumes at most 256 ROM banks
  5. ; - Switches to an invalid ROM bank at the end, but it's harmless since the ROM is not accessed
  6. ; - Uses `rst bankswitch` to switch ROM banks, but that can be replaced with whatever you want
  7. ; - Uses $D000 - $D1FF as precomputation tables, but you can move this anywhere (storing it in ROM is probably a bad idea)
  8. ; - Stores results at $C000 - $C0XX; for ROM bank $RR, the byte at $C0RR will be set to 0 if the CRC check succeeded, or be set to $AF if the check failed
  9. ; - Clobbers every register known to mankind
  10.  
  11. wCRCSuccess   equ $C000
  12. wCRCLowTable  equ $D000
  13. wCRCHighTable equ $D100
  14.  
  15. CRCs          equ $0150
  16. CRCsEnd       equ $0150 + 2 * NB_ROM_BANKS
  17.  
  18.  
  19.     ; Perform CRC verification
  20. CRC_POLYNOM   equ $1021
  21.  
  22.     ; Compute CRC table to speed up later calculations
  23.     ld de, wCRCHighTable
  24. .computeCRCTable
  25.     ld h, e
  26.     ld l, 0
  27.     ld c, 8
  28. .bitLoop
  29.     add hl, hl
  30.     jr nc, .bitClear
  31.     ld a, l
  32.     xor LOW(CRC_POLYNOM)
  33.     ld l, a
  34.     ld a, h
  35.     xor HIGH(CRC_POLYNOM)
  36.     ld h, a
  37. .bitClear
  38.     dec c
  39.     jr nz, .bitLoop
  40.     dec d
  41.     ld a, l
  42.     ld [de], a
  43.     inc d
  44.     ld a, h
  45.     ld [de], a
  46.     inc e
  47.     jr nz, .computeCRCTable
  48.  
  49.     ld hl, $0000
  50.     ld c, l ; ld c, 0 ; Low byte of pointer to result
  51. .CRCLoop
  52.     ld b, $FF ; CRC low
  53.     ld e, b ; lb de, HIGH(wCRCHighTable), $FF ; CRC high & pointer to table
  54.     jr .feedByte ; Skip "skip hack"
  55. .skipBytes
  56.     ld l, LOW(CRCsEnd)
  57. .feedByte
  58.     ; Update CRC in `eb`
  59.     ld a, [hli]
  60.     xor e      ; XOR with high byte
  61.     ld e, a    ; Store back
  62.     dec d      ; Switch to low byte table
  63.     ld a, [de] ; Get low byte mask
  64.     xor b      ; XOR with low byte
  65.     ld b, a    ; Store back
  66.     inc d      ; Switch to high byte table
  67.     ld a, [de] ; Get high byte mask
  68.     xor e      ; XOR with high byte
  69.     ld e, a    ; Store back
  70.     ; Check if we should skip
  71.     ld a, h
  72.     dec a
  73.     ld a, l
  74.     jr nz, .dontSkipBytes
  75.     cp LOW($014E)
  76.     jr z, .skipBytes
  77. .dontSkipBytes
  78.     ; Check if reached end of a bank
  79.     and a
  80.     jr nz, .feedByte
  81.     ld a, h
  82.     and %111111
  83.     jr nz, .feedByte
  84.     ; Now check if the CRC matches
  85.     ; Get pointer to current
  86.     ld a, c
  87.     add a, LOW(CRCs) >> 1
  88.     add a, a
  89.     ld l, a
  90.     adc a, HIGH(CRCs)
  91.     sub l
  92.     ld h, a
  93.     ld a, [hli]
  94.     cp b
  95.     jr nz, .CRCFail
  96.     ld a, [hli]
  97.     cp e
  98.     jr z, .CRCSuccess
  99. .CRCFail
  100.     db $3E ; ld a, $AF
  101. .CRCSuccess
  102.     xor a
  103.     ld b, HIGH(wCRCSuccess)
  104.     ld [bc], a
  105.     ; Prepare next bank
  106.     ld hl, $4000
  107.     inc c
  108.     ld a, c
  109.     rst bankswitch ; Will switch to a bad bank on last iter, but that's not a problem.
  110.     ; ld a, c
  111.     cp NB_ROM_BANKS
  112.     jr nz, .CRCLoop
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top