SameBoy/BootROMs/sgb_boot.asm

236 lines
3.9 KiB
NASM

; SameBoy SGB bootstrap ROM
include "sameboot.inc"
SECTION "BootCode", ROM0[$0000]
Start:
; Init stack pointer
ld sp, $FFFE
; Clear memory VRAM
ld hl, _VRAM
xor a
.clearVRAMLoop
ldi [hl], a
bit 5, h
jr z, .clearVRAMLoop
; Init Audio
ld a, AUDENA_ON
ldh [rNR52], a
assert AUDENA_ON == AUDLEN_DUTY_50
ldh [rNR11], a
ld a, $F3
ldh [rNR12], a ; Envelope $F, decreasing, sweep $3
ldh [rNR51], a ; Channels 1+2+3+4 left, channels 1+2 right
ld a, $77
ldh [rNR50], a ; Volume $7, left and right
; Init BG palette to white
ld a, %00_00_00_00
ldh [rBGP], a
; Load logo from ROM.
; A nibble represents a 4-pixels line, 2 bytes represent a 4x4 tile, scaled to 8x8.
; Tiles are ordered left to right, top to bottom.
ld de, NintendoLogo
ld hl, _VRAM + $10 ; This is where we load the tiles in VRAM
.loadLogoLoop
ld a, [de] ; Read 2 rows
ld b, a
call DoubleBitsAndWriteRow
call DoubleBitsAndWriteRow
inc de
ld a, e
xor LOW(NintendoLogoEnd)
jr nz, .loadLogoLoop
; Load trademark symbol
ld de, TrademarkSymbol
ld c, TrademarkSymbolEnd - TrademarkSymbol
.loadTrademarkSymbolLoop:
ld a, [de]
inc de
ldi [hl], a
inc hl
dec c
jr nz, .loadTrademarkSymbolLoop
; Set up tilemap
ld a, $19 ; Trademark symbol tile ID
ld [_SCRN0 + 8 * SCRN_VX_B + 16], a ; ... put in the superscript position
ld hl, _SCRN0 + 9 * SCRN_VX_B + 15 ; Bottom right corner of the logo
ld c, 12 ; Tiles in a logo row
.tilemapLoop
dec a
jr z, .tilemapDone
ldd [hl], a
dec c
jr nz, .tilemapLoop
ld l, $0F ; Jump to top row
jr .tilemapLoop
.tilemapDone
; Turn on LCD
ld a, LCDCF_ON | LCDCF_BLK01 | LCDCF_BGON
ldh [rLCDC], a
ld a, $F1 ; Packet magic, increases by 2 for every packet
ldh [hCommand], a
ld hl, NintendoLogo ; Header start
xor a
ld c, a ; JOYP
.sendCommand
xor a
ldh [c], a
ld a, $30
ldh [c], a
ldh a, [hCommand]
call SendByte
push hl
ld b, 14
ld d, 0
.checksumLoop
call ReadHeaderByte
add d
ld d, a
dec b
jr nz, .checksumLoop
; Send checksum
call SendByte
pop hl
ld b, 14
.sendLoop
call ReadHeaderByte
call SendByte
dec b
jr nz, .sendLoop
; Done bit
ld a, $20
ldh [c], a
ld a, $30
ldh [c], a
; Wait 4 frames
ld e, 4
ld a, 1
ldh [rIE], a
xor a
.waitLoop
ldh [rIF], a
halt
nop
dec e
jr nz, .waitLoop
ldh [rIE], a
; Update command
ldh a, [hCommand]
add 2
ldh [hCommand], a
ld a, $58
cp l
jr nz, .sendCommand
; Write to sound registers for DMG compatibility
ld c, LOW(rNR13)
ld a, $C1
ldh [c], a
inc c
ld a, $7
ldh [c], a
; Init BG palette
ld a, %11_11_11_00
ldh [rBGP], a
; Set registers to match the original SGB boot
IF DEF(SGB2)
ld a, BOOTUP_A_MGB
ELSE
ld a, BOOTUP_A_DMG
ENDC
ld hl, $C060
; Boot the game
jp BootGame
ReadHeaderByte:
ld a, $4F
cp l
jr c, .zero
ld a, [hli]
ret
.zero:
inc hl
xor a
ret
SendByte:
ld e, a
ld d, 8
.loop
ld a, $10
rr e
jr c, .zeroBit
add a ; 10 -> 20
.zeroBit
ldh [c], a
ld a, $30
ldh [c], a
dec d
ret z
jr .loop
DoubleBitsAndWriteRow:
; Double the most significant 4 bits, b is shifted by 4
ld a, 4
ld c, 0
.doubleCurrentBit
sla b
push af
rl c
pop af
rl c
dec a
jr nz, .doubleCurrentBit
ld a, c
; Write as two rows
ldi [hl], a
inc hl
ldi [hl], a
inc hl
ret
TrademarkSymbol:
pusho
opt b.X
db %..XXXX..
db %.X....X.
db %X.XXX..X
db %X.X..X.X
db %X.XXX..X
db %X.X..X.X
db %.X....X.
db %..XXXX..
popo
TrademarkSymbolEnd:
SECTION "BootGame", ROM0[$00FE]
BootGame:
ldh [rBANK], a
SECTION "HRAM", HRAM[_HRAM]
hCommand:
ds 1