mirror of https://github.com/LIJI32/SameBoy.git
197 lines
3.5 KiB
NASM
197 lines
3.5 KiB
NASM
; SameBoy DMG 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
|
|
ld a, %01_01_01_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
|
|
|
|
ld a, 30
|
|
ldh [rSCY], a
|
|
|
|
; Turn on LCD
|
|
ld a, LCDCF_ON | LCDCF_BLK01 | LCDCF_BGON
|
|
ldh [rLCDC], a
|
|
|
|
ld d, LOW(-119)
|
|
ld c, 15
|
|
|
|
.animate
|
|
call WaitFrame
|
|
ld a, d
|
|
sra a
|
|
sra a
|
|
ldh [rSCY], a
|
|
ld a, d
|
|
add c
|
|
ld d, a
|
|
ld a, c
|
|
cp 8
|
|
jr nz, .noPaletteChange
|
|
ld a, %10_10_10_00
|
|
ldh [rBGP], a
|
|
.noPaletteChange
|
|
dec c
|
|
jr nz, .animate
|
|
ld a, %11_11_11_00
|
|
ldh [rBGP], a
|
|
|
|
; Play first sound
|
|
ld a, $83
|
|
call PlaySound
|
|
ld b, 5
|
|
call WaitBFrames
|
|
; Play second sound
|
|
ld a, $C1
|
|
call PlaySound
|
|
|
|
|
|
|
|
; Wait ~1 second
|
|
ld b, 60
|
|
call WaitBFrames
|
|
|
|
; Set registers to match the original DMG boot
|
|
IF DEF(MGB)
|
|
lb hl, BOOTUP_A_MGB, %10110000
|
|
ELSE
|
|
lb hl, BOOTUP_A_DMG, %10110000
|
|
ENDC
|
|
push hl
|
|
pop af
|
|
ld hl, HeaderChecksum
|
|
lb bc, 0, LOW(rNR13) ; $0013
|
|
lb de, 0, $D8 ; $00D8
|
|
|
|
; Boot the game
|
|
jp BootGame
|
|
|
|
|
|
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
|
|
|
|
WaitFrame:
|
|
push hl
|
|
ld hl, rIF
|
|
res 0, [hl]
|
|
.wait
|
|
bit 0, [hl]
|
|
jr z, .wait
|
|
pop hl
|
|
ret
|
|
|
|
WaitBFrames:
|
|
call WaitFrame
|
|
dec b
|
|
jr nz, WaitBFrames
|
|
ret
|
|
|
|
PlaySound:
|
|
ldh [rNR13], a
|
|
ld a, AUDHIGH_RESTART | $7
|
|
ldh [rNR14], a
|
|
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 ; unmap boot ROM
|