git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

BootROMs/cgb_boot.asm

      1 ; SameBoy CGB bootstrap ROM
      2 
      3 include "sameboot.inc"
      4 
      5 SECTION "BootCode", ROM0[$0000]
      6 Start:
      7 ; Init stack pointer
      8     ld sp, $FFFE
      9 
     10 ; Clear memory VRAM
     11     call ClearMemoryVRAM
     12 
     13 ; Clear OAM
     14     ld h, HIGH(_OAMRAM)
     15     ld c, sizeof_OAM_ATTRS * OAM_COUNT
     16 .clearOAMLoop
     17     ldi [hl], a
     18     dec c
     19     jr nz, .clearOAMLoop
     20 
     21 IF !DEF(CGB0)
     22 ; Init waveform
     23     ld c, 16
     24     ld hl, _AUD3WAVERAM
     25 .waveformLoop
     26     ldi [hl], a
     27     cpl
     28     dec c
     29     jr nz, .waveformLoop
     30 ENDC
     31 
     32 ; Clear chosen input palette
     33     ldh [hInputPalette], a
     34 ; Clear title checksum
     35     ldh [hTitleChecksum], a
     36 
     37 ; Init Audio
     38     ld a, AUDENA_ON
     39     ldh [rNR52], a
     40     assert AUDENA_ON == AUDLEN_DUTY_50
     41     ldh [rNR11], a
     42     ld a, $F3
     43     ldh [rNR12], a ; Envelope $F, decreasing, sweep $3
     44     ldh [rNR51], a ; Channels 1+2+3+4 left, channels 1+2 right
     45     ld a, $77
     46     ldh [rNR50], a ; Volume $7, left and right
     47 
     48 ; Init BG palette
     49     ld a, %11_11_11_00
     50     ldh [rBGP], a
     51 
     52 ; Load logo from ROM.
     53 ; A nibble represents a 4-pixels line, 2 bytes represent a 4x4 tile, scaled to 8x8.
     54 ; Tiles are ordered left to right, top to bottom.
     55 ; These tiles are not used, but are required for DMG compatibility. This is done
     56 ; by the original CGB Boot ROM as well.
     57     ld de, NintendoLogo
     58     ld hl, _VRAM + $10 ; This is where we load the tiles in VRAM
     59 
     60 .loadLogoLoop
     61     ld a, [de] ; Read 2 rows
     62     ld b, a
     63     call DoubleBitsAndWriteRowTwice
     64     inc de
     65     ld a, e
     66     cp LOW(NintendoLogoEnd)
     67     jr nz, .loadLogoLoop
     68     call ReadTrademarkSymbol
     69 
     70 ; Clear the second VRAM bank
     71     ld a, 1
     72     ldh [rVBK], a
     73     call ClearMemoryVRAM
     74     call LoadTileset
     75 
     76     ld b, 3
     77 IF DEF(FAST)
     78     xor a
     79     ldh [rVBK], a
     80 ELSE
     81 ; Load Tilemap
     82     ld hl, _SCRN0 + 6 * SCRN_VX_B + 2
     83     ld d, 3
     84     ld a, 8
     85 
     86 .tilemapLoop
     87     ld c, 16
     88 
     89 .tilemapRowLoop
     90 
     91     call .write_with_palette
     92 
     93     ; Repeat the 3 tiles common between E and B. This saves 27 bytes after
     94     ; compression, with a cost of 17 bytes of code.
     95     push af
     96     sub $20
     97     sub $3
     98     jr nc, .notspecial
     99     add $20
    100     call .write_with_palette
    101     dec c
    102 .notspecial
    103     pop af
    104 
    105     add d ; d = 3 for SameBoy logo, d = 1 for Nintendo logo
    106     dec c
    107     jr nz, .tilemapRowLoop
    108     sub 44
    109     push de
    110     ld de, $10
    111     add hl, de
    112     pop de
    113     dec b
    114     jr nz, .tilemapLoop
    115 
    116     dec d
    117     jr z, .endTilemap
    118     dec d
    119 
    120     ld a, $38
    121     ld l, $A7
    122     lb bc, 1, 7 ; $0107
    123     jr .tilemapRowLoop
    124 
    125 .write_with_palette
    126     push af
    127     ; Switch to second VRAM Bank
    128     ld a, 1
    129     ldh [rVBK], a
    130     ld [hl], 8
    131     ; Switch to back first VRAM Bank
    132     xor a
    133     ldh [rVBK], a
    134     pop af
    135     ldi [hl], a
    136     ret
    137 .endTilemap
    138 ENDC
    139 
    140     ; Expand Palettes
    141     ld de, AnimationColors
    142     ld c, 8
    143     ld hl, hBgPalettes
    144     xor a
    145 .expandPalettesLoop:
    146     cpl
    147     ; One white
    148     ld [hli], a
    149     ld [hli], a
    150 
    151     ; Mixed with white
    152     ld a, [de]
    153     inc e
    154     or $20
    155     ld b, a
    156 
    157     ld a, [de]
    158     dec e
    159     or $84
    160     rra
    161     rr b
    162     ld [hl], b
    163     inc l
    164     ld [hli], a
    165 
    166     ; One black
    167     xor a
    168     ld [hli], a
    169     ld [hli], a
    170 
    171     ; One color
    172     ld a, [de]
    173     inc e
    174     ld [hli], a
    175     ld a, [de]
    176     inc e
    177     ld [hli], a
    178 
    179     xor a
    180     dec c
    181     jr nz, .expandPalettesLoop
    182 
    183     call LoadPalettesFromHRAM
    184 
    185     ; Turn on LCD
    186     ld a, LCDCF_ON | LCDCF_BLK01 | LCDCF_BGON
    187     ldh [rLCDC], a
    188 
    189 IF !DEF(FAST)
    190     call DoIntroAnimation
    191 
    192     ld a, 48 ; frames to wait after playing the chime
    193     ldh [hWaitLoopCounter], a
    194     ld b, 4 ; frames to wait before playing the chime
    195     call WaitBFrames
    196 
    197     ; Play first sound
    198     ld a, $83
    199     call PlaySound
    200     ld b, 5
    201     call WaitBFrames
    202     ; Play second sound
    203     ld a, $C1
    204     call PlaySound
    205 
    206 .waitLoop
    207     call GetInputPaletteIndex
    208     call WaitFrame
    209     ld hl, hWaitLoopCounter
    210     dec [hl]
    211     jr nz, .waitLoop
    212 ELSE
    213     ld a, $C1
    214     call PlaySound
    215 ENDC
    216     call Preboot
    217 IF DEF(AGB)
    218     inc b
    219 ENDC
    220     jr BootGame
    221 
    222 HDMAData:
    223 MACRO hdma_data ; source, destination, length
    224     db HIGH(\1), LOW(\1)
    225     db HIGH(\2), LOW(\2)
    226     db (\3)
    227 ENDM
    228     hdma_data _RAMBANK, _SCRN0 + 5 * SCRN_VX_B + 0, 18
    229     hdma_data _RAMBANK, _VRAM, 64
    230 
    231 SECTION "BootGame", ROM0[$00FE]
    232 BootGame:
    233     ldh [rBANK], a ; unmap boot ROM
    234 
    235 SECTION "BootData", ROM0[$0200]
    236 ; Game Palettes Data
    237 TitleChecksums:
    238     db $00 ; Default
    239     db $88 ; ALLEY WAY
    240     db $16 ; YAKUMAN
    241     db $36 ; BASEBALL, (Game and Watch 2)
    242     db $D1 ; TENNIS
    243     db $DB ; TETRIS
    244     db $F2 ; QIX
    245     db $3C ; DR.MARIO
    246     db $8C ; RADARMISSION
    247     db $92 ; F1RACE
    248     db $3D ; YOSSY NO TAMAGO
    249     db $5C ;
    250     db $58 ; X
    251     db $C9 ; MARIOLAND2
    252     db $3E ; YOSSY NO COOKIE
    253     db $70 ; ZELDA
    254     db $1D ;
    255     db $59 ;
    256     db $69 ; TETRIS FLASH
    257     db $19 ; DONKEY KONG
    258     db $35 ; MARIO'S PICROSS
    259     db $A8 ;
    260     db $14 ; POKEMON RED, (GAMEBOYCAMERA G)
    261     db $AA ; POKEMON GREEN
    262     db $75 ; PICROSS 2
    263     db $95 ; YOSSY NO PANEPON
    264     db $99 ; KIRAKIRA KIDS
    265     db $34 ; GAMEBOY GALLERY
    266     db $6F ; POCKETCAMERA
    267     db $15 ;
    268     db $FF ; BALLOON KID
    269     db $97 ; KINGOFTHEZOO
    270     db $4B ; DMG FOOTBALL
    271     db $90 ; WORLD CUP
    272     db $17 ; OTHELLO
    273     db $10 ; SUPER RC PRO-AM
    274     db $39 ; DYNABLASTER
    275     db $F7 ; BOY AND BLOB GB2
    276     db $F6 ; MEGAMAN
    277     db $A2 ; STAR WARS-NOA
    278     db $49 ;
    279     db $4E ; WAVERACE
    280     db $43 ;
    281     db $68 ; LOLO2
    282     db $E0 ; YOSHI'S COOKIE
    283     db $8B ; MYSTIC QUEST
    284     db $F0 ;
    285     db $CE ; TOPRANKINGTENNIS
    286     db $0C ; MANSELL
    287     db $29 ; MEGAMAN3
    288     db $E8 ; SPACE INVADERS
    289     db $B7 ; GAME&WATCH
    290     db $86 ; DONKEYKONGLAND95
    291     db $9A ; ASTEROIDS/MISCMD
    292     db $52 ; STREET FIGHTER 2
    293     db $01 ; DEFENDER/JOUST
    294     db $9D ; KILLERINSTINCT95
    295     db $71 ; TETRIS BLAST
    296     db $9C ; PINOCCHIO
    297     db $BD ;
    298     db $5D ; BA.TOSHINDEN
    299     db $6D ; NETTOU KOF 95
    300     db $67 ;
    301     db $3F ; TETRIS PLUS
    302     db $6B ; DONKEYKONGLAND 3
    303 ; For these games, the 4th letter is taken into account
    304 FirstChecksumWithDuplicate:
    305     ; Let's play hangman!
    306     db $B3 ; ???[B]????????
    307     db $46 ; SUP[E]R MARIOLAND
    308     db $28 ; GOL[F]
    309     db $A5 ; SOL[A]RSTRIKER
    310     db $C6 ; GBW[A]RS
    311     db $D3 ; KAE[R]UNOTAMENI
    312     db $27 ; ???[B]????????
    313     db $61 ; POK[E]MON BLUE
    314     db $18 ; DON[K]EYKONGLAND
    315     db $66 ; GAM[E]BOY GALLERY2
    316     db $6A ; DON[K]EYKONGLAND 2
    317     db $BF ; KID[ ]ICARUS
    318     db $0D ; TET[R]IS2
    319     db $F4 ; ???[-]????????
    320     db $B3 ; MOG[U]RANYA
    321     db $46 ; ???[R]????????
    322     db $28 ; GAL[A]GA&GALAXIAN
    323     db $A5 ; BT2[R]AGNAROKWORLD
    324     db $C6 ; KEN[ ]GRIFFEY JR
    325     db $D3 ; ???[I]????????
    326     db $27 ; MAG[N]ETIC SOCCER
    327     db $61 ; VEG[A]S STAKES
    328     db $18 ; ???[I]????????
    329     db $66 ; MIL[L]I/CENTI/PEDE
    330     db $6A ; MAR[I]O & YOSHI
    331     db $BF ; SOC[C]ER
    332     db $0D ; POK[E]BOM
    333     db $F4 ; G&W[ ]GALLERY
    334     db $B3 ; TET[R]IS ATTACK
    335 ChecksumsEnd:
    336 
    337 PalettePerChecksum:
    338 MACRO palette_index ; palette[, flags]
    339     IF _NARG == 1
    340         db (\1)
    341     ELSE
    342         db (\1) | (\2) ; flag $80 means game requires DMG boot tilemap
    343     ENDC
    344 ENDM
    345     palette_index  0 ; Default Palette
    346     palette_index  4 ; ALLEY WAY
    347     palette_index  5 ; YAKUMAN
    348     palette_index 35 ; BASEBALL, (Game and Watch 2)
    349     palette_index 34 ; TENNIS
    350     palette_index  3 ; TETRIS
    351     palette_index 31 ; QIX
    352     palette_index 15 ; DR.MARIO
    353     palette_index 10 ; RADARMISSION
    354     palette_index  5 ; F1RACE
    355     palette_index 19 ; YOSSY NO TAMAGO
    356     palette_index 36 ;
    357     palette_index  7, $80 ; X
    358     palette_index 37 ; MARIOLAND2
    359     palette_index 30 ; YOSSY NO COOKIE
    360     palette_index 44 ; ZELDA
    361     palette_index 21 ;
    362     palette_index 32 ;
    363     palette_index 31 ; TETRIS FLASH
    364     palette_index 20 ; DONKEY KONG
    365     palette_index  5 ; MARIO'S PICROSS
    366     palette_index 33 ;
    367     palette_index 13 ; POKEMON RED, (GAMEBOYCAMERA G)
    368     palette_index 14 ; POKEMON GREEN
    369     palette_index  5 ; PICROSS 2
    370     palette_index 29 ; YOSSY NO PANEPON
    371     palette_index  5 ; KIRAKIRA KIDS
    372     palette_index 18 ; GAMEBOY GALLERY
    373     palette_index  9 ; POCKETCAMERA
    374     palette_index  3 ;
    375     palette_index  2 ; BALLOON KID
    376     palette_index 26 ; KINGOFTHEZOO
    377     palette_index 25 ; DMG FOOTBALL
    378     palette_index 25 ; WORLD CUP
    379     palette_index 41 ; OTHELLO
    380     palette_index 42 ; SUPER RC PRO-AM
    381     palette_index 26 ; DYNABLASTER
    382     palette_index 45 ; BOY AND BLOB GB2
    383     palette_index 42 ; MEGAMAN
    384     palette_index 45 ; STAR WARS-NOA
    385     palette_index 36 ;
    386     palette_index 38 ; WAVERACE
    387     palette_index 26, $80 ;
    388     palette_index 42 ; LOLO2
    389     palette_index 30 ; YOSHI'S COOKIE
    390     palette_index 41 ; MYSTIC QUEST
    391     palette_index 34 ;
    392     palette_index 34 ; TOPRANKINGTENNIS
    393     palette_index  5 ; MANSELL
    394     palette_index 42 ; MEGAMAN3
    395     palette_index  6 ; SPACE INVADERS
    396     palette_index  5 ; GAME&WATCH
    397     palette_index 33 ; DONKEYKONGLAND95
    398     palette_index 25 ; ASTEROIDS/MISCMD
    399     palette_index 42 ; STREET FIGHTER 2
    400     palette_index 42 ; DEFENDER/JOUST
    401     palette_index 40 ; KILLERINSTINCT95
    402     palette_index  2 ; TETRIS BLAST
    403     palette_index 16 ; PINOCCHIO
    404     palette_index 25 ;
    405     palette_index 42 ; BA.TOSHINDEN
    406     palette_index 42 ; NETTOU KOF 95
    407     palette_index  5 ;
    408     palette_index  0 ; TETRIS PLUS
    409     palette_index 39 ; DONKEYKONGLAND 3
    410     palette_index 36 ;
    411     palette_index 22 ; SUPER MARIOLAND
    412     palette_index 25 ; GOLF
    413     palette_index  6 ; SOLARSTRIKER
    414     palette_index 32 ; GBWARS
    415     palette_index 12 ; KAERUNOTAMENI
    416     palette_index 36 ;
    417     palette_index 11 ; POKEMON BLUE
    418     palette_index 39 ; DONKEYKONGLAND
    419     palette_index 18 ; GAMEBOY GALLERY2
    420     palette_index 39 ; DONKEYKONGLAND 2
    421     palette_index 24 ; KID ICARUS
    422     palette_index 31 ; TETRIS2
    423     palette_index 50 ;
    424     palette_index 17 ; MOGURANYA
    425     palette_index 46 ;
    426     palette_index  6 ; GALAGA&GALAXIAN
    427     palette_index 27 ; BT2RAGNAROKWORLD
    428     palette_index  0 ; KEN GRIFFEY JR
    429     palette_index 47 ;
    430     palette_index 41 ; MAGNETIC SOCCER
    431     palette_index 41 ; VEGAS STAKES
    432     palette_index  0 ;
    433     palette_index  0 ; MILLI/CENTI/PEDE
    434     palette_index 19 ; MARIO & YOSHI
    435     palette_index 34 ; SOCCER
    436     palette_index 23 ; POKEBOM
    437     palette_index 18 ; G&W GALLERY
    438     palette_index 29 ; TETRIS ATTACK
    439 
    440 Dups4thLetterArray:
    441     db "BEFAARBEKEK R-URAR INAILICE R"
    442 
    443 ; We assume the last three arrays fit in the same $100 byte page!
    444 
    445 PaletteCombinations:
    446 MACRO palette_comb ; Obj0, Obj1, Bg
    447     db (\1) * 8, (\2) * 8, (\3) *8
    448 ENDM
    449 MACRO raw_palette_comb ; Obj0, Obj1, Bg
    450     db (\1) * 2, (\2) * 2, (\3) * 2
    451 ENDM
    452     palette_comb  4,  4, 29 ;  0, Right + A
    453     palette_comb 18, 18, 18 ;  1, Right
    454     palette_comb 20, 20, 20 ;  2
    455     palette_comb 24, 24, 24 ;  3, Down + A
    456     palette_comb  9,  9,  9 ;  4
    457     palette_comb  0,  0,  0 ;  5, Up
    458     palette_comb 27, 27, 27 ;  6, Right + B
    459     palette_comb  5,  5,  5 ;  7, Left + B
    460     palette_comb 12, 12, 12 ;  8, Down
    461     palette_comb 26, 26, 26 ;  9
    462     palette_comb 16,  8,  8 ; 10
    463     palette_comb  4, 28, 28 ; 11
    464     palette_comb  4,  2,  2 ; 12
    465     palette_comb  3,  4,  4 ; 13
    466     palette_comb  4, 29, 29 ; 14
    467     palette_comb 28,  4, 28 ; 15
    468     palette_comb  2, 17,  2 ; 16
    469     palette_comb 16, 16,  8 ; 17
    470     palette_comb  4,  4,  7 ; 18
    471     palette_comb  4,  4, 18 ; 19
    472     palette_comb  4,  4, 20 ; 20
    473     palette_comb 19, 19,  9 ; 21
    474     raw_palette_comb 4 * 4 - 1, 4 * 4 - 1, 11 * 4 ; 22
    475     palette_comb 17, 17,  2 ; 23
    476     palette_comb  4,  4,  2 ; 24
    477     palette_comb  4,  4,  3 ; 25
    478     palette_comb 28, 28,  0 ; 26
    479     palette_comb  3,  3,  0 ; 27
    480     palette_comb  0,  0,  1 ; 28, Up + B
    481     palette_comb 18, 22, 18 ; 29
    482     palette_comb 20, 22, 20 ; 30
    483     palette_comb 24, 22, 24 ; 31
    484     palette_comb 16, 22,  8 ; 32
    485     palette_comb 17,  4, 13 ; 33
    486     raw_palette_comb 28 * 4 - 1, 0 * 4, 14 * 4 ; 34
    487     raw_palette_comb 28 * 4 - 1, 4 * 4, 15 * 4 ; 35
    488     raw_palette_comb 19 * 4, 23 * 4 - 1, 9 * 4 ; 36
    489     palette_comb 16, 28, 10 ; 37
    490     palette_comb  4, 23, 28 ; 38
    491     palette_comb 17, 22,  2 ; 39
    492     palette_comb  4,  0,  2 ; 40, Left + A
    493     palette_comb  4, 28,  3 ; 41
    494     palette_comb 28,  3,  0 ; 42
    495     palette_comb  3, 28,  4 ; 43, Up + A
    496     palette_comb 21, 28,  4 ; 44
    497     palette_comb  3, 28,  0 ; 45
    498     palette_comb 25,  3, 28 ; 46
    499     palette_comb  0, 28,  8 ; 47
    500     palette_comb  4,  3, 28 ; 48, Left
    501     palette_comb 28,  3,  6 ; 49, Down + B
    502     palette_comb  4, 28, 29 ; 50
    503     ; SameBoy "Exclusives"
    504     palette_comb 30, 30, 30 ; 51, Right + A + B, CGA
    505     palette_comb 31, 31, 31 ; 52, Left + A + B, DMG LCD
    506     palette_comb 28,  4,  1 ; 53, Up + A + B
    507     palette_comb  0,  0,  2 ; 54, Down + A + B
    508 
    509 Palettes:
    510     dw $7FFF, $32BF, $00D0, $0000 ;  0
    511     dw $639F, $4279, $15B0, $04CB ;  1
    512     dw $7FFF, $6E31, $454A, $0000 ;  2
    513     dw $7FFF, $1BEF, $0200, $0000 ;  3
    514     dw $7FFF, $421F, $1CF2, $0000 ;  4
    515     dw $7FFF, $5294, $294A, $0000 ;  5
    516     dw $7FFF, $03FF, $012F, $0000 ;  6
    517     dw $7FFF, $03EF, $01D6, $0000 ;  7
    518     dw $7FFF, $42B5, $3DC8, $0000 ;  8
    519     dw $7E74, $03FF, $0180, $0000 ;  9
    520     dw $67FF, $77AC, $1A13, $2D6B ; 10
    521     dw $7ED6, $4BFF, $2175, $0000 ; 11
    522     dw $53FF, $4A5F, $7E52, $0000 ; 12
    523     dw $4FFF, $7ED2, $3A4C, $1CE0 ; 13
    524     dw $03ED, $7FFF, $255F, $0000 ; 14
    525     dw $036A, $021F, $03FF, $7FFF ; 15
    526     dw $7FFF, $01DF, $0112, $0000 ; 16
    527     dw $231F, $035F, $00F2, $0009 ; 17
    528     dw $7FFF, $03EA, $011F, $0000 ; 18
    529     dw $299F, $001A, $000C, $0000 ; 19
    530     dw $7FFF, $027F, $001F, $0000 ; 20
    531     dw $7FFF, $03E0, $0206, $0120 ; 21
    532     dw $7FFF, $7EEB, $001F, $7C00 ; 22
    533     dw $7FFF, $3FFF, $7E00, $001F ; 23
    534     dw $7FFF, $03FF, $001F, $0000 ; 24
    535     dw $03FF, $001F, $000C, $0000 ; 25
    536     dw $7FFF, $033F, $0193, $0000 ; 26
    537     dw $0000, $4200, $037F, $7FFF ; 27
    538     dw $7FFF, $7E8C, $7C00, $0000 ; 28
    539     dw $7FFF, $1BEF, $6180, $0000 ; 29
    540     ; SameBoy "Exclusives"
    541     dw $7FFF, $7FEA, $7D5F, $0000 ; 30, CGA 1
    542     dw $4778, $3290, $1D87, $0861 ; 31, DMG LCD
    543 
    544 KeyCombinationPalettes:
    545 MACRO palette_comb_id ; PaletteCombinations ID
    546     db (\1) * 3
    547 ENDM
    548     palette_comb_id  1 ;  1, Right
    549     palette_comb_id 48 ;  2, Left
    550     palette_comb_id  5 ;  3, Up
    551     palette_comb_id  8 ;  4, Down
    552     palette_comb_id  0 ;  5, Right + A
    553     palette_comb_id 40 ;  6, Left + A
    554     palette_comb_id 43 ;  7, Up + A
    555     palette_comb_id  3 ;  8, Down + A
    556     palette_comb_id  6 ;  9, Right + B
    557     palette_comb_id  7 ; 10, Left + B
    558     palette_comb_id 28 ; 11, Up + B
    559     palette_comb_id 49 ; 12, Down + B
    560     ; SameBoy "Exclusives"
    561     palette_comb_id 51 ; 13, Right + A + B
    562     palette_comb_id 52 ; 14, Left + A + B
    563     palette_comb_id 53 ; 15, Up + A + B
    564     palette_comb_id 54 ; 16, Down + A + B
    565 
    566 TrademarkSymbol:
    567     pusho
    568     opt b.X
    569     db %..XXXX..
    570     db %.X....X.
    571     db %X.XXX..X
    572     db %X.X..X.X
    573     db %X.XXX..X
    574     db %X.X..X.X
    575     db %.X....X.
    576     db %..XXXX..
    577     popo
    578 TrademarkSymbolEnd:
    579 
    580 SameBoyLogo:
    581     incbin "SameBoyLogo.pb12"
    582 
    583 
    584 AnimationColors:
    585     dw $7FFF ; White
    586     dw $774F ; Cyan
    587     dw $22C7 ; Green
    588     dw $039F ; Yellow
    589     dw $017D ; Orange
    590     dw $241D ; Red
    591     dw $6D38 ; Purple
    592 IF DEF(AGB)
    593     dw $6D60 ; Blue
    594 ELSE
    595     dw $5500 ; Blue
    596 ENDC
    597 
    598 AnimationColorsEnd:
    599 
    600 ; Helper Functions
    601 DoubleBitsAndWriteRowTwice:
    602     call .twice
    603 .twice
    604 ; Double the most significant 4 bits, b is shifted by 4
    605     ld a, 4
    606     ld c, 0
    607 .doubleCurrentBit
    608     sla b
    609     push af
    610     rl c
    611     pop af
    612     rl c
    613     dec a
    614     jr nz, .doubleCurrentBit
    615     ld a, c
    616 ; Write as two rows
    617     ldi [hl], a
    618     inc hl
    619     ldi [hl], a
    620     inc hl
    621     ret
    622 
    623 WaitFrame:
    624     push hl
    625     ld hl, rIF
    626     res 0, [hl]
    627 .wait
    628     bit 0, [hl]
    629     jr z, .wait
    630     pop hl
    631     ret
    632 
    633 WaitBFrames:
    634     call GetInputPaletteIndex
    635     call WaitFrame
    636     dec b
    637     jr nz, WaitBFrames
    638     ret
    639 
    640 PlaySound:
    641     ldh [rNR13], a
    642     ld a, $87
    643     ldh [rNR14], a
    644     ret
    645 
    646 ClearMemoryVRAM:
    647     ld hl, _VRAM
    648 ; Clear from HL to HL | 0x2000
    649 ClearMemoryPage:
    650     xor a
    651     ldi [hl], a
    652     bit 5, h
    653     jr z, ClearMemoryPage
    654     ret
    655 
    656 ReadTwoTileLines:
    657     call ReadTileLine
    658 ; c = $F0 for even lines, $0F for odd lines.
    659 ReadTileLine:
    660     ld a, [de]
    661     and c
    662     ld b, a
    663     inc e
    664     inc e
    665     ld a, [de]
    666     dec e
    667     dec e
    668     and c
    669     swap a
    670     or b
    671     bit 0, c
    672     jr z, .dontSwap
    673     swap a
    674 .dontSwap
    675     inc hl
    676     ldi [hl], a
    677     swap c
    678     ret
    679 
    680 
    681 ReadCGBLogoHalfTile:
    682     call .do_twice
    683 .do_twice
    684     call ReadTwoTileLines
    685     inc e
    686     ld a, e
    687     ret
    688 
    689 ; LoadTileset using PB12 codec, 2020 Jakub Kądziołka
    690 ; (based on PB8 codec, 2019 Damian Yerrick)
    691 
    692 LoadTileset:
    693     ld hl, SameBoyLogo         ; source
    694     ld de, _VRAM + $80 - 1     ; destination
    695     ld c, (128 * 24) / (8 * 8) ; length
    696 .refill
    697     ; Register map for PB12 decompression
    698     ; HL: source address in boot ROM
    699     ; DE: destination address in VRAM
    700     ; A: Current literal value
    701     ; B: Repeat bits, terminated by 1000...
    702     ; Source address in HL lets the repeat bits go straight to B,
    703     ; bypassing A and avoiding spilling registers to the stack.
    704     ld b, [hl]
    705     dec b
    706     jr z, .sameboyLogoEnd
    707     inc b
    708     inc hl
    709 
    710     ; Shift a 1 into lower bit of shift value.  Once this bit
    711     ; reaches the carry, B becomes 0 and the byte is over
    712     scf
    713     rl b
    714 
    715 .loop
    716     ; If not a repeat, load a literal byte
    717     jr c, .simple_repeat
    718     sla b
    719     jr c, .shifty_repeat
    720     ld a, [hli]
    721     jr .got_byte
    722 .shifty_repeat
    723     sla b
    724     jr nz, .no_refill_during_shift
    725     ld b, [hl] ; see above. Also, no, factoring it out into a callable
    726     inc hl ; routine doesn't save bytes, even with conditional calls
    727     scf
    728     rl b
    729 .no_refill_during_shift
    730     ld c, a
    731     jr nc, .shift_left
    732     srl a
    733     db $FE ; eat the `add a` with `cp d8`
    734 .shift_left
    735     add a
    736     sla b
    737     jr c, .go_and
    738     or c
    739     db $FE ; eat the `and c` with `cp d8`
    740 .go_and
    741     and c
    742     jr .got_byte
    743 .simple_repeat
    744     sla b
    745     jr c, .got_byte
    746     ; far repeat
    747     dec de
    748     ld a, [de]
    749     inc de
    750 .got_byte
    751     inc de
    752     ld [de], a
    753     sla b
    754     jr nz, .loop
    755     jr .refill
    756 
    757 ; End PB12 decoding.  The rest uses HL as the destination
    758 .sameboyLogoEnd
    759     ld h, d
    760     ld l, $80
    761 
    762 ; Copy (unresized) ROM logo
    763     ld de, NintendoLogo
    764 .CGBROMLogoLoop
    765     ld c, $F0
    766     call ReadCGBLogoHalfTile
    767     add a, 22
    768     ld e, a
    769     call ReadCGBLogoHalfTile
    770     sub a, 22
    771     ld e, a
    772     cp $1C
    773     jr nz, .CGBROMLogoLoop
    774     inc hl
    775     ; fallthrough
    776 ReadTrademarkSymbol:
    777     ld de, TrademarkSymbol
    778     ld c, TrademarkSymbolEnd - TrademarkSymbol
    779 .loadTrademarkSymbolLoop:
    780     ld a, [de]
    781     inc de
    782     ldi [hl], a
    783     inc hl
    784     dec c
    785     jr nz, .loadTrademarkSymbolLoop
    786     ret
    787 
    788 DoIntroAnimation:
    789     ; Animate the intro
    790     ld a, 1
    791     ldh [rVBK], a
    792     ld d, 26
    793 .animationLoop
    794     ld b, 2
    795     call WaitBFrames
    796     ld hl, _SCRN0 + 6 * SCRN_VX_B + 0
    797     ld c, 3 ; Row count
    798 .loop
    799     ld a, [hl]
    800     cp $F ; Already blue
    801     jr z, .nextTile
    802     inc [hl]
    803     and $7
    804     jr z, .nextLine ; Changed a white tile, go to next line
    805 .nextTile
    806     inc hl
    807     jr .loop
    808 .nextLine
    809     ld a, l
    810     or $1F
    811     ld l, a
    812     inc hl
    813     dec c
    814     jr nz, .loop
    815     dec d
    816     jr nz, .animationLoop
    817     ret
    818 
    819 Preboot:
    820 IF !DEF(FAST)
    821     ld b, 32 ; 32 times to fade
    822 .fadeLoop
    823     ld c, (hBgPalettesEnd - hBgPalettes) / 2 ; 32 colors to fade
    824     ld hl, hBgPalettes
    825 .frameLoop
    826     push bc
    827 
    828     ; Brighten Color
    829     ld a, [hli]
    830     ld e, a
    831     ld a, [hld]
    832     ld d, a
    833     ; RGB(1,1,1)
    834     ld bc, $0421
    835 
    836    ; Is blue maxed?
    837     ld a, e
    838     and $1F
    839     cp $1F
    840     jr nz, .blueNotMaxed
    841     dec c
    842 .blueNotMaxed
    843 
    844     ; Is green maxed?
    845     ld a, e
    846     cp $E0
    847     jr c, .greenNotMaxed
    848     ld a, d
    849     and $3
    850     cp $3
    851     jr nz, .greenNotMaxed
    852     res 5, c
    853 .greenNotMaxed
    854 
    855     ; Is red maxed?
    856     ld a, d
    857     and $7C
    858     cp $7C
    859     jr nz, .redNotMaxed
    860     res 2, b
    861 .redNotMaxed
    862 
    863     ld a, e
    864     add c
    865     ld [hli], a
    866     ld a, d
    867     adc b
    868     ld [hli], a
    869     pop bc
    870 
    871     dec c
    872     jr nz, .frameLoop
    873 
    874     call WaitFrame
    875     call LoadPalettesFromHRAM
    876     call WaitFrame
    877     dec b
    878     jr nz, .fadeLoop
    879 ENDC
    880     ld a, 2
    881     ldh [rSVBK], a
    882     ; Clear RAM Bank 2 (Like the original boot ROM)
    883     ld hl, _RAMBANK
    884     call ClearMemoryPage
    885     inc a
    886     call ClearVRAMViaHDMA
    887     call _ClearVRAMViaHDMA
    888     call ClearVRAMViaHDMA ; A = $40, so it's bank 0
    889     xor a
    890     ldh [rSVBK], a
    891     cpl
    892     ldh [rJOYP], a
    893 
    894     ; Final values for CGB mode
    895     ld d, a
    896     ld e, c
    897     ld l, $0D
    898 
    899     ld a, [CGBFlag]
    900     bit 7, a
    901     call z, EmulateDMG
    902     bit 7, a
    903 
    904     ldh [rKEY0], a ; write CGB compatibility byte, CGB mode
    905     ldh a, [hTitleChecksum]
    906     ld b, a
    907 
    908     jr z, .skipDMGForCGBCheck
    909     ldh a, [hInputPalette]
    910     and a
    911     jr nz, .emulateDMGForCGBGame
    912 .skipDMGForCGBCheck
    913 IF DEF(AGB)
    914     ; Set registers to match the original AGB-CGB boot
    915     ; AF = $1100, C = 0
    916     xor a
    917     ld c, a
    918     add a, BOOTUP_A_CGB
    919     ld h, c
    920     ; B is set to BOOTUP_B_AGB (1) after ret
    921 ELSE
    922     ; Set registers to match the original CGB boot
    923     ; AF = $1180, C = 0
    924     xor a
    925     ld c, a
    926     ld a, BOOTUP_A_CGB
    927     ld h, c
    928     ; B is set to the title checksum (BOOTUP_B_CGB, 0)
    929 ENDC
    930     ret
    931 
    932 .emulateDMGForCGBGame
    933     call EmulateDMG
    934     ldh [rKEY0], a ; write $04, DMG emulation mode
    935     ld a, $1
    936     ret
    937 
    938 GetKeyComboPalette:
    939     ld hl, KeyCombinationPalettes - 1 ; Return value is 1-based, 0 means nothing down
    940     ld c, a
    941     ld b, 0
    942     add hl, bc
    943     ld a, [hl]
    944     ret
    945 
    946 EmulateDMG:
    947     ld a, 1
    948     ldh [rOPRI], a ; DMG Emulation sprite priority
    949     call GetPaletteIndex
    950     bit 7, a
    951     call nz, LoadDMGTilemap
    952     res 7, a
    953     ld b, a
    954     add b
    955     add b
    956     ld b, a
    957     ldh a, [hInputPalette]
    958     and a
    959     jr z, .nothingDown
    960     call GetKeyComboPalette
    961     jr .paletteFromKeys
    962 .nothingDown
    963     ld a, b
    964 .paletteFromKeys
    965     call WaitFrame
    966     call LoadPalettesFromIndex
    967     ld a, 4
    968     ; Set the final values for DMG mode
    969     ld de, 8
    970     ld l, $7C
    971     ret
    972 
    973 GetPaletteIndex:
    974     ld hl, OldLicenseeCode
    975     ld a, [hl]
    976     cp $33
    977     jr z, .newLicensee
    978     dec a ; 1 = Nintendo
    979     jr nz, .notNintendo
    980     jr .doChecksum
    981 .newLicensee
    982     ld l, LOW(NewLicenseeCode)
    983     ld a, [hli]
    984     cp $30 ; ASCII '0'
    985     jr nz, .notNintendo
    986     ld a, [hl]
    987     cp $31 ; ASCII '1'
    988     jr nz, .notNintendo
    989 
    990 .doChecksum
    991     ld l, LOW(Title)
    992     ld c, 16
    993     xor a
    994 .checksumLoop
    995     add [hl]
    996     inc l
    997     dec c
    998     jr nz, .checksumLoop
    999     ldh [hTitleChecksum], a
   1000     ld b, a
   1001 
   1002     ; c = 0
   1003     ld hl, TitleChecksums
   1004 
   1005 .searchLoop
   1006     ld a, l
   1007     sub LOW(ChecksumsEnd) ; use sub to zero out a
   1008     ret z
   1009     ld a, [hli]
   1010     cp b
   1011     jr nz, .searchLoop
   1012 
   1013     ; We might have a match, Do duplicate/4th letter check
   1014     ld a, l
   1015     sub FirstChecksumWithDuplicate - TitleChecksums + 1
   1016     jr c, .match ; Does not have a duplicate, must be a match!
   1017     ; Has a duplicate; check 4th letter
   1018     push hl
   1019     ld a, l
   1020     add Dups4thLetterArray - FirstChecksumWithDuplicate - 1 ; -1 since hl was incremented
   1021     ld l, a
   1022     ld a, [hl]
   1023     pop hl
   1024     ld c, a
   1025     ld a, [Title + 3] ; Get 4th letter
   1026     cp c
   1027     jr nz, .searchLoop ; Not a match, continue
   1028 
   1029 .match
   1030     ld a, l
   1031     add PalettePerChecksum - TitleChecksums - 1; -1 since hl was incremented
   1032     ld l, a
   1033     ld a, b
   1034     ldh [hTitleChecksum], a
   1035     ld a, [hl]
   1036     ret
   1037 
   1038 .notNintendo
   1039     xor a
   1040     ret
   1041 
   1042 ; optimizations in callers rely on this returning with b = 0
   1043 GetPaletteCombo:
   1044     ld hl, PaletteCombinations
   1045     ld b, 0
   1046     ld c, a
   1047     add hl, bc
   1048     ret
   1049 
   1050 LoadPalettesFromIndex: ; a = index of combination
   1051     call GetPaletteCombo
   1052 
   1053     ; Obj Palettes
   1054     ld e, 0
   1055 .loadObjPalette
   1056     ld a, [hli]
   1057     push hl
   1058     ld hl, Palettes
   1059     ; b is already 0
   1060     ld c, a
   1061     add hl, bc
   1062     ld d, 4 * 2
   1063     ld c, LOW(rOBPI)
   1064     call LoadPalettes
   1065     pop hl
   1066     bit OAMB_BANK1, e
   1067     jr nz, .loadBGPalette
   1068     ld e, OAMF_BANK1
   1069     jr .loadObjPalette
   1070 .loadBGPalette
   1071     ;BG Palette
   1072     ld c, [hl]
   1073     ; b is already 0
   1074     ld hl, Palettes
   1075     add hl, bc
   1076     ld d, 8
   1077     jr LoadBGPalettes
   1078 
   1079 LoadPalettesFromHRAM:
   1080     ld hl, hBgPalettes
   1081     ld d, hBgPalettesEnd - hBgPalettes
   1082 LoadBGPalettes:
   1083     ld e, 0
   1084     ld c, LOW(rBGPI)
   1085 LoadPalettes:
   1086     ld a, $80
   1087     or e
   1088     ldh [c], a
   1089     inc c
   1090 .loop
   1091     ld a, [hli]
   1092     ldh [c], a
   1093     dec d
   1094     jr nz, .loop
   1095     ret
   1096 
   1097 ClearVRAMViaHDMA:
   1098     ldh [rVBK], a
   1099     ld hl, HDMAData
   1100 _ClearVRAMViaHDMA:
   1101     call WaitFrame ; Wait for vblank
   1102     ld c, LOW(rHDMA1)
   1103     ld b, 5
   1104 .loop
   1105     ld a, [hli]
   1106     ldh [c], a
   1107     inc c
   1108     dec b
   1109     jr nz, .loop
   1110     ret
   1111 
   1112 ; clobbers AF and HL
   1113 GetInputPaletteIndex:
   1114     ld a, P1F_GET_DPAD
   1115     ldh [rJOYP], a
   1116     ldh a, [rJOYP]
   1117     cpl
   1118     and $F
   1119     ret z ; No direction keys pressed, no palette
   1120 
   1121     ld l, 0
   1122 .directionLoop
   1123     inc l
   1124     rra
   1125     jr nc, .directionLoop
   1126 
   1127     ; c = 1: Right, 2: Left, 3: Up, 4: Down
   1128 
   1129     ld a, P1F_GET_BTN
   1130     ldh [rJOYP], a
   1131     ldh a, [rJOYP]
   1132     cpl
   1133     rla
   1134     rla
   1135     and $C
   1136     add l
   1137     ld l, a
   1138     ldh a, [hInputPalette]
   1139     cp l
   1140     ret z ; No change, don't load
   1141     ld a, l
   1142     ldh [hInputPalette], a
   1143     ; Slide into change Animation Palette
   1144 
   1145 ChangeAnimationPalette:
   1146     push bc
   1147     push de
   1148     call GetKeyComboPalette
   1149     call GetPaletteCombo
   1150     inc l
   1151     inc l
   1152     ld c, [hl]
   1153     ld hl, Palettes + 1
   1154     add hl, bc
   1155     ld a, [hld]
   1156     cp $7F ; Is white color?
   1157     jr nz, .isWhite
   1158     inc hl
   1159     inc hl
   1160 .isWhite
   1161     push af
   1162     ld a, [hli]
   1163 
   1164     push hl
   1165     ld hl, hBgPalettes ; First color, all palettes
   1166     call ReplaceColorInAllPalettes
   1167     ld l, LOW(hBgPalettes + 2)  ; Second color, all palettes
   1168     call ReplaceColorInAllPalettes
   1169     pop hl
   1170     ldh [hBgPalettes + 6], a ; Fourth color, first palette
   1171 
   1172     ld a, [hli]
   1173     push hl
   1174     ld hl, hBgPalettes + 1 ; First color, all palettes
   1175     call ReplaceColorInAllPalettes
   1176     ld l, LOW(hBgPalettes + 3) ; Second color, all palettes
   1177     call ReplaceColorInAllPalettes
   1178     pop hl
   1179     ldh [hBgPalettes + 7], a ; Fourth color, first palette
   1180 
   1181     pop af
   1182     jr z, .isNotWhite
   1183     inc hl
   1184     inc hl
   1185 .isNotWhite
   1186     ; Mixing code by ISSOtm
   1187     ldh a, [hBgPalettes + 7 * 8 + 2]
   1188     and ~$21
   1189     ld b, a
   1190     ld a, [hli]
   1191     and ~$21
   1192     add a, b
   1193     ld b, a
   1194     ld a, [hBgPalettes + 7 * 8 + 3]
   1195     res 2, a ; and ~$04, but not touching carry
   1196     ld c, [hl]
   1197     res 2, c ; and ~$04, but not touching carry
   1198     adc a, c
   1199     rra ; Carry sort of "extends" the accumulator, we're bringing that bit back home
   1200     ld [hBgPalettes + 7 * 8 + 3], a
   1201     ld a, b
   1202     rra
   1203     ld [hBgPalettes + 7 * 8 + 2], a
   1204     dec l
   1205 
   1206     ld a, [hli]
   1207     ldh [hBgPalettes + 7 * 8 + 6], a ; Fourth color, 7th palette
   1208     ld a, [hli]
   1209     ldh [hBgPalettes + 7 * 8 + 7], a ; Fourth color, 7th palette
   1210 
   1211     ld a, [hli]
   1212     ldh [hBgPalettes + 4], a ; Third color, first palette
   1213     ld a, [hli]
   1214     ldh [hBgPalettes + 5], a ; Third color, first palette
   1215 
   1216 
   1217     call WaitFrame
   1218     call LoadPalettesFromHRAM
   1219     ; Delay the wait loop while the user is selecting a palette
   1220     ld a, 48
   1221     ldh [hWaitLoopCounter], a
   1222     pop de
   1223     pop bc
   1224     ret
   1225 
   1226 ReplaceColorInAllPalettes:
   1227     ld de, 8
   1228     ld c, e
   1229 .loop
   1230     ld [hl], a
   1231     add hl, de
   1232     dec c
   1233     jr nz, .loop
   1234     ret
   1235 
   1236 LoadDMGTilemap:
   1237     push af
   1238     call WaitFrame
   1239     ld a, $19                           ; Trademark symbol tile ID
   1240     ld [_SCRN0 + 8 * SCRN_VX_B + 16], a ; ... put in the superscript position
   1241     ld hl, _SCRN0 + 9 * SCRN_VX_B + 15  ; Bottom right corner of the logo
   1242     ld c, 12                            ; Tiles in a logo row
   1243 .tilemapLoop
   1244     dec a
   1245     jr z, .tilemapDone
   1246     ldd [hl], a
   1247     dec c
   1248     jr nz, .tilemapLoop
   1249     ld l, $0F ; Jump to top row
   1250     jr .tilemapLoop
   1251 .tilemapDone
   1252     pop af
   1253     ret
   1254 
   1255 BootEnd:
   1256 IF BootEnd > $0900
   1257     FAIL "BootROM overflowed: {BootEnd}"
   1258 ENDC
   1259     ds $100 + $800 - @ ; Ensure that the ROM is padded up to standard size.
   1260 
   1261 SECTION "HRAM", HRAM[_HRAM]
   1262 hTitleChecksum:
   1263     ds 1
   1264 hBgPalettes:
   1265     ds 8 * 4 * 2
   1266 hBgPalettesEnd:
   1267 hInputPalette:
   1268     ds 1
   1269 hWaitLoopCounter:
   1270     ds 1

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.