Merge branch 'bootrom-2bpp'
This commit is contained in:
commit
8f69703726
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 479 B |
@ -6,14 +6,12 @@ Start:
|
|||||||
ld sp, $fffe
|
ld sp, $fffe
|
||||||
|
|
||||||
; Clear memory VRAM
|
; Clear memory VRAM
|
||||||
ld hl, $8000
|
call ClearMemoryPage8000
|
||||||
call ClearMemoryPage
|
|
||||||
ld a, 2
|
ld a, 2
|
||||||
ld c, $70
|
ld c, $70
|
||||||
ld [c], a
|
ld [c], a
|
||||||
; Clear RAM Bank 2 (Like the original boot ROM
|
; Clear RAM Bank 2 (Like the original boot ROM)
|
||||||
ld h, $D0
|
ld h, $D0
|
||||||
xor a
|
|
||||||
call ClearMemoryPage
|
call ClearMemoryPage
|
||||||
ld [c], a
|
ld [c], a
|
||||||
|
|
||||||
@ -22,15 +20,6 @@ Start:
|
|||||||
; Clear title checksum
|
; Clear title checksum
|
||||||
ldh [TitleChecksum], a
|
ldh [TitleChecksum], a
|
||||||
|
|
||||||
; Clear OAM
|
|
||||||
ld h, $fe
|
|
||||||
ld c, $a0
|
|
||||||
.clearOAMLoop
|
|
||||||
ldi [hl], a
|
|
||||||
dec c
|
|
||||||
jr nz, .clearOAMLoop
|
|
||||||
|
|
||||||
; Init Audio
|
|
||||||
ld a, $80
|
ld a, $80
|
||||||
ldh [$26], a
|
ldh [$26], a
|
||||||
ldh [$11], a
|
ldh [$11], a
|
||||||
@ -39,8 +28,23 @@ Start:
|
|||||||
ldh [$25], a
|
ldh [$25], a
|
||||||
ld a, $77
|
ld a, $77
|
||||||
ldh [$24], a
|
ldh [$24], a
|
||||||
|
ld hl, $FF30
|
||||||
|
; Init waveform
|
||||||
|
ld c, $10
|
||||||
|
.waveformLoop
|
||||||
|
ldi [hl], a
|
||||||
|
cpl
|
||||||
|
dec c
|
||||||
|
jr nz, .waveformLoop
|
||||||
|
|
||||||
call InitWaveform
|
|
||||||
|
; Clear OAM
|
||||||
|
ld h, $fe
|
||||||
|
ld c, $a0
|
||||||
|
.clearOAMLoop
|
||||||
|
ldi [hl], a
|
||||||
|
dec c
|
||||||
|
jr nz, .clearOAMLoop
|
||||||
|
|
||||||
; Init BG palette
|
; Init BG palette
|
||||||
ld a, $fc
|
ld a, $fc
|
||||||
@ -67,9 +71,7 @@ Start:
|
|||||||
; Clear the second VRAM bank
|
; Clear the second VRAM bank
|
||||||
ld a, 1
|
ld a, 1
|
||||||
ldh [$4F], a
|
ldh [$4F], a
|
||||||
xor a
|
call ClearMemoryPage8000
|
||||||
ld hl, $8000
|
|
||||||
call ClearMemoryPage
|
|
||||||
call LoadTileset
|
call LoadTileset
|
||||||
|
|
||||||
ld b, 3
|
ld b, 3
|
||||||
@ -87,20 +89,24 @@ ELSE
|
|||||||
|
|
||||||
.tilemapRowLoop
|
.tilemapRowLoop
|
||||||
|
|
||||||
|
call .write_with_palette
|
||||||
|
|
||||||
|
; Repeat the 3 tiles common between E and B. This saves 27 bytes after
|
||||||
|
; compression, with a cost of 17 bytes of code.
|
||||||
push af
|
push af
|
||||||
; Switch to second VRAM Bank
|
sub $20
|
||||||
ld a, 1
|
sub $3
|
||||||
ldh [$4F], a
|
jr nc, .notspecial
|
||||||
ld [hl], 8
|
add $20
|
||||||
; Switch to back first VRAM Bank
|
call .write_with_palette
|
||||||
xor a
|
dec c
|
||||||
ldh [$4F], a
|
.notspecial
|
||||||
pop af
|
pop af
|
||||||
ldi [hl], a
|
|
||||||
add d
|
add d ; d = 3 for SameBoy logo, d = 1 for Nintendo logo
|
||||||
dec c
|
dec c
|
||||||
jr nz, .tilemapRowLoop
|
jr nz, .tilemapRowLoop
|
||||||
sub 47
|
sub 44
|
||||||
push de
|
push de
|
||||||
ld de, $10
|
ld de, $10
|
||||||
add hl, de
|
add hl, de
|
||||||
@ -116,6 +122,19 @@ ELSE
|
|||||||
ld l, $a7
|
ld l, $a7
|
||||||
ld bc, $0107
|
ld bc, $0107
|
||||||
jr .tilemapRowLoop
|
jr .tilemapRowLoop
|
||||||
|
|
||||||
|
.write_with_palette
|
||||||
|
push af
|
||||||
|
; Switch to second VRAM Bank
|
||||||
|
ld a, 1
|
||||||
|
ldh [$4F], a
|
||||||
|
ld [hl], 8
|
||||||
|
; Switch to back first VRAM Bank
|
||||||
|
xor a
|
||||||
|
ldh [$4F], a
|
||||||
|
pop af
|
||||||
|
ldi [hl], a
|
||||||
|
ret
|
||||||
.endTilemap
|
.endTilemap
|
||||||
ENDC
|
ENDC
|
||||||
|
|
||||||
@ -125,38 +144,40 @@ ENDC
|
|||||||
ld hl, BgPalettes
|
ld hl, BgPalettes
|
||||||
xor a
|
xor a
|
||||||
.expandPalettesLoop:
|
.expandPalettesLoop:
|
||||||
IF !DEF(FAST)
|
|
||||||
cpl
|
cpl
|
||||||
ENDC
|
|
||||||
; One white
|
; One white
|
||||||
ldi [hl], a
|
ld [hli], a
|
||||||
ldi [hl], a
|
ld [hli], a
|
||||||
|
|
||||||
IF DEF(FAST)
|
; Mixed with white
|
||||||
; 3 more whites
|
|
||||||
ldi [hl], a
|
|
||||||
ldi [hl], a
|
|
||||||
ldi [hl], a
|
|
||||||
ldi [hl], a
|
|
||||||
ldi [hl], a
|
|
||||||
ldi [hl], a
|
|
||||||
ELSE
|
|
||||||
; The actual color
|
|
||||||
ld a, [de]
|
ld a, [de]
|
||||||
inc de
|
inc e
|
||||||
ldi [hl], a
|
or $20
|
||||||
|
ld b, a
|
||||||
|
|
||||||
ld a, [de]
|
ld a, [de]
|
||||||
inc de
|
dec e
|
||||||
ldi [hl], a
|
or $84
|
||||||
|
rra
|
||||||
|
rr b
|
||||||
|
ld [hl], b
|
||||||
|
inc l
|
||||||
|
ld [hli], a
|
||||||
|
|
||||||
|
; One black
|
||||||
|
xor a
|
||||||
|
ld [hli], a
|
||||||
|
ld [hli], a
|
||||||
|
|
||||||
|
; One color
|
||||||
|
ld a, [de]
|
||||||
|
inc e
|
||||||
|
ld [hli], a
|
||||||
|
ld a, [de]
|
||||||
|
inc e
|
||||||
|
ld [hli], a
|
||||||
|
|
||||||
xor a
|
xor a
|
||||||
; Two blacks
|
|
||||||
ldi [hl], a
|
|
||||||
ldi [hl], a
|
|
||||||
ldi [hl], a
|
|
||||||
ldi [hl], a
|
|
||||||
ENDC
|
|
||||||
|
|
||||||
dec c
|
dec c
|
||||||
jr nz, .expandPalettesLoop
|
jr nz, .expandPalettesLoop
|
||||||
|
|
||||||
@ -170,8 +191,10 @@ ENDC
|
|||||||
IF !DEF(FAST)
|
IF !DEF(FAST)
|
||||||
call DoIntroAnimation
|
call DoIntroAnimation
|
||||||
|
|
||||||
|
ld a, 45
|
||||||
|
ldh [WaitLoopCounter], a
|
||||||
; Wait ~0.75 seconds
|
; Wait ~0.75 seconds
|
||||||
ld b, 45
|
ld b, a
|
||||||
call WaitBFrames
|
call WaitBFrames
|
||||||
|
|
||||||
; Play first sound
|
; Play first sound
|
||||||
@ -183,10 +206,6 @@ IF !DEF(FAST)
|
|||||||
ld a, $c1
|
ld a, $c1
|
||||||
call PlaySound
|
call PlaySound
|
||||||
|
|
||||||
; Wait ~0.5 seconds
|
|
||||||
ld a, 30
|
|
||||||
ldh [WaitLoopCounter], a
|
|
||||||
|
|
||||||
.waitLoop
|
.waitLoop
|
||||||
call GetInputPaletteIndex
|
call GetInputPaletteIndex
|
||||||
call WaitFrame
|
call WaitFrame
|
||||||
@ -198,6 +217,9 @@ ELSE
|
|||||||
call PlaySound
|
call PlaySound
|
||||||
ENDC
|
ENDC
|
||||||
call Preboot
|
call Preboot
|
||||||
|
IF DEF(AGB)
|
||||||
|
ld b, 1
|
||||||
|
ENDC
|
||||||
|
|
||||||
; Will be filled with NOPs
|
; Will be filled with NOPs
|
||||||
|
|
||||||
@ -206,7 +228,6 @@ BootGame:
|
|||||||
ldh [$50], a
|
ldh [$50], a
|
||||||
|
|
||||||
SECTION "MoreStuff", ROM0[$200]
|
SECTION "MoreStuff", ROM0[$200]
|
||||||
|
|
||||||
; Game Palettes Data
|
; Game Palettes Data
|
||||||
TitleChecksums:
|
TitleChecksums:
|
||||||
db $00 ; Default
|
db $00 ; Default
|
||||||
@ -510,29 +531,30 @@ Palettes:
|
|||||||
dw $4778, $3290, $1D87, $0861 ; DMG LCD
|
dw $4778, $3290, $1D87, $0861 ; DMG LCD
|
||||||
|
|
||||||
KeyCombinationPalettes
|
KeyCombinationPalettes
|
||||||
db 1 ; Right
|
db 1 * 3 ; Right
|
||||||
db 48 ; Left
|
db 48 * 3 ; Left
|
||||||
db 5 ; Up
|
db 5 * 3 ; Up
|
||||||
db 8 ; Down
|
db 8 * 3 ; Down
|
||||||
db 0 ; Right + A
|
db 0 * 3 ; Right + A
|
||||||
db 40 ; Left + A
|
db 40 * 3 ; Left + A
|
||||||
db 43 ; Up + A
|
db 43 * 3 ; Up + A
|
||||||
db 3 ; Down + A
|
db 3 * 3 ; Down + A
|
||||||
db 6 ; Right + B
|
db 6 * 3 ; Right + B
|
||||||
db 7 ; Left + B
|
db 7 * 3 ; Left + B
|
||||||
db 28 ; Up + B
|
db 28 * 3 ; Up + B
|
||||||
db 49 ; Down + B
|
db 49 * 3 ; Down + B
|
||||||
; SameBoy "Exclusives"
|
; SameBoy "Exclusives"
|
||||||
db 51 ; Right + A + B
|
db 51 * 3 ; Right + A + B
|
||||||
db 52 ; Left + A + B
|
db 52 * 3 ; Left + A + B
|
||||||
db 53 ; Up + A + B
|
db 53 * 3 ; Up + A + B
|
||||||
db 54 ; Down + A + B
|
db 54 * 3 ; Down + A + B
|
||||||
|
|
||||||
TrademarkSymbol:
|
TrademarkSymbol:
|
||||||
db $3c,$42,$b9,$a5,$b9,$a5,$42,$3c
|
db $3c,$42,$b9,$a5,$b9,$a5,$42,$3c
|
||||||
|
|
||||||
SameBoyLogo:
|
SameBoyLogo:
|
||||||
incbin "SameBoyLogo.pb8"
|
incbin "SameBoyLogo.pb12"
|
||||||
|
|
||||||
|
|
||||||
AnimationColors:
|
AnimationColors:
|
||||||
dw $7FFF ; White
|
dw $7FFF ; White
|
||||||
@ -545,9 +567,6 @@ AnimationColors:
|
|||||||
dw $7102 ; Blue
|
dw $7102 ; Blue
|
||||||
AnimationColorsEnd:
|
AnimationColorsEnd:
|
||||||
|
|
||||||
DMGPalettes:
|
|
||||||
dw $7FFF, $32BF, $00D0, $0000
|
|
||||||
|
|
||||||
; Helper Functions
|
; Helper Functions
|
||||||
DoubleBitsAndWriteRowTwice:
|
DoubleBitsAndWriteRowTwice:
|
||||||
call .twice
|
call .twice
|
||||||
@ -594,8 +613,11 @@ PlaySound:
|
|||||||
ldh [$14], a
|
ldh [$14], a
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
ClearMemoryPage8000:
|
||||||
|
ld hl, $8000
|
||||||
; Clear from HL to HL | 0x2000
|
; Clear from HL to HL | 0x2000
|
||||||
ClearMemoryPage:
|
ClearMemoryPage:
|
||||||
|
xor a
|
||||||
ldi [hl], a
|
ldi [hl], a
|
||||||
bit 5, h
|
bit 5, h
|
||||||
jr z, ClearMemoryPage
|
jr z, ClearMemoryPage
|
||||||
@ -634,30 +656,28 @@ ReadCGBLogoHalfTile:
|
|||||||
ld a, e
|
ld a, e
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; LoadTileset using PB8 codec, 2019 Damian Yerrick
|
; LoadTileset using PB12 codec, 2020 Jakub Kądziołka
|
||||||
;
|
; (based on PB8 codec, 2019 Damian Yerrick)
|
||||||
; The logo is compressed using PB8, a form of RLE with unary-coded
|
|
||||||
; run lengths. Each block representing 8 bytes consists of a control
|
|
||||||
; byte, where each bit (MSB to LSB) is 0 for literal or 1 for repeat
|
|
||||||
; previous, followed by the literals in that block.
|
|
||||||
|
|
||||||
SameBoyLogo_dst = $8080
|
SameBoyLogo_dst = $8080
|
||||||
SameBoyLogo_length = (128 * 24) / 64
|
SameBoyLogo_length = (128 * 24) / 64
|
||||||
|
|
||||||
LoadTileset:
|
LoadTileset:
|
||||||
ld hl, SameBoyLogo
|
ld hl, SameBoyLogo
|
||||||
ld de, SameBoyLogo_dst
|
ld de, SameBoyLogo_dst - 1
|
||||||
ld c, SameBoyLogo_length
|
ld c, SameBoyLogo_length
|
||||||
.pb8BlockLoop:
|
.refill
|
||||||
; Register map for PB8 decompression
|
; Register map for PB12 decompression
|
||||||
; HL: source address in boot ROM
|
; HL: source address in boot ROM
|
||||||
; DE: destination address in VRAM
|
; DE: destination address in VRAM
|
||||||
; A: Current literal value
|
; A: Current literal value
|
||||||
; B: Repeat bits, terminated by 1000...
|
; B: Repeat bits, terminated by 1000...
|
||||||
; C: Number of 8-byte blocks left in this block
|
|
||||||
; Source address in HL lets the repeat bits go straight to B,
|
; Source address in HL lets the repeat bits go straight to B,
|
||||||
; bypassing A and avoiding spilling registers to the stack.
|
; bypassing A and avoiding spilling registers to the stack.
|
||||||
ld b, [hl]
|
ld b, [hl]
|
||||||
|
dec b
|
||||||
|
jr z, .sameboyLogoEnd
|
||||||
|
inc b
|
||||||
inc hl
|
inc hl
|
||||||
|
|
||||||
; Shift a 1 into lower bit of shift value. Once this bit
|
; Shift a 1 into lower bit of shift value. Once this bit
|
||||||
@ -665,26 +685,53 @@ LoadTileset:
|
|||||||
scf
|
scf
|
||||||
rl b
|
rl b
|
||||||
|
|
||||||
.pb8BitLoop:
|
.loop
|
||||||
; If not a repeat, load a literal byte
|
; If not a repeat, load a literal byte
|
||||||
jr c,.pb8Repeat
|
jr c, .simple_repeat
|
||||||
ld a, [hli]
|
|
||||||
.pb8Repeat:
|
|
||||||
; Decompressed data uses colors 0 and 1, so write once, inc twice
|
|
||||||
ld [de], a
|
|
||||||
inc de
|
|
||||||
inc de
|
|
||||||
sla b
|
sla b
|
||||||
jr nz, .pb8BitLoop
|
jr c, .shifty_repeat
|
||||||
|
ld a, [hli]
|
||||||
dec c
|
jr .got_byte
|
||||||
jr nz, .pb8BlockLoop
|
.shifty_repeat
|
||||||
|
sla b
|
||||||
; End PB8 decoding. The rest uses HL as the destination
|
jr nz, .no_refill_during_shift
|
||||||
ld h, d
|
ld b, [hl] ; see above. Also, no, factoring it out into a callable
|
||||||
ld l, e
|
inc hl ; routine doesn't save bytes, even with conditional calls
|
||||||
|
scf
|
||||||
|
rl b
|
||||||
|
.no_refill_during_shift
|
||||||
|
ld c, a
|
||||||
|
jr nc, .shift_left
|
||||||
|
srl a
|
||||||
|
db $fe ; eat the add a with cp d8
|
||||||
|
.shift_left
|
||||||
|
add a
|
||||||
|
sla b
|
||||||
|
jr c, .go_and
|
||||||
|
or c
|
||||||
|
db $fe ; eat the and c with cp d8
|
||||||
|
.go_and
|
||||||
|
and c
|
||||||
|
jr .got_byte
|
||||||
|
.simple_repeat
|
||||||
|
sla b
|
||||||
|
jr c, .got_byte
|
||||||
|
; far repeat
|
||||||
|
dec de
|
||||||
|
ld a, [de]
|
||||||
|
inc de
|
||||||
|
.got_byte
|
||||||
|
inc de
|
||||||
|
ld [de], a
|
||||||
|
sla b
|
||||||
|
jr nz, .loop
|
||||||
|
jr .refill
|
||||||
|
|
||||||
|
; End PB12 decoding. The rest uses HL as the destination
|
||||||
.sameboyLogoEnd
|
.sameboyLogoEnd
|
||||||
|
ld h, d
|
||||||
|
ld l, $80
|
||||||
|
|
||||||
; Copy (unresized) ROM logo
|
; Copy (unresized) ROM logo
|
||||||
ld de, $104
|
ld de, $104
|
||||||
.CGBROMLogoLoop
|
.CGBROMLogoLoop
|
||||||
@ -711,29 +758,6 @@ ReadTrademarkSymbol:
|
|||||||
jr nz, .loadTrademarkSymbolLoop
|
jr nz, .loadTrademarkSymbolLoop
|
||||||
ret
|
ret
|
||||||
|
|
||||||
LoadObjPalettes:
|
|
||||||
ld c, $6A
|
|
||||||
jr LoadPalettes
|
|
||||||
|
|
||||||
LoadBGPalettes64:
|
|
||||||
ld d, 64
|
|
||||||
|
|
||||||
LoadBGPalettes:
|
|
||||||
ld e, 0
|
|
||||||
ld c, $68
|
|
||||||
|
|
||||||
LoadPalettes:
|
|
||||||
ld a, $80
|
|
||||||
or e
|
|
||||||
ld [c], a
|
|
||||||
inc c
|
|
||||||
.loop
|
|
||||||
ld a, [hli]
|
|
||||||
ld [c], a
|
|
||||||
dec d
|
|
||||||
jr nz, .loop
|
|
||||||
ret
|
|
||||||
|
|
||||||
DoIntroAnimation:
|
DoIntroAnimation:
|
||||||
; Animate the intro
|
; Animate the intro
|
||||||
ld a, 1
|
ld a, 1
|
||||||
@ -771,30 +795,75 @@ IF !DEF(FAST)
|
|||||||
.fadeLoop
|
.fadeLoop
|
||||||
ld c, 32 ; 32 colors to fade
|
ld c, 32 ; 32 colors to fade
|
||||||
ld hl, BgPalettes
|
ld hl, BgPalettes
|
||||||
|
push hl
|
||||||
.frameLoop
|
.frameLoop
|
||||||
push bc
|
push bc
|
||||||
call BrightenColor
|
|
||||||
|
; Brighten Color
|
||||||
|
ld a, [hli]
|
||||||
|
ld e, a
|
||||||
|
ld a, [hld]
|
||||||
|
ld d, a
|
||||||
|
; RGB(1,1,1)
|
||||||
|
ld bc, $421
|
||||||
|
|
||||||
|
; Is blue maxed?
|
||||||
|
ld a, e
|
||||||
|
and $1F
|
||||||
|
cp $1F
|
||||||
|
jr nz, .blueNotMaxed
|
||||||
|
dec c
|
||||||
|
.blueNotMaxed
|
||||||
|
|
||||||
|
; Is green maxed?
|
||||||
|
ld a, e
|
||||||
|
cp $E0
|
||||||
|
jr c, .greenNotMaxed
|
||||||
|
ld a, d
|
||||||
|
and $3
|
||||||
|
cp $3
|
||||||
|
jr nz, .greenNotMaxed
|
||||||
|
res 5, c
|
||||||
|
.greenNotMaxed
|
||||||
|
|
||||||
|
; Is red maxed?
|
||||||
|
ld a, d
|
||||||
|
and $7C
|
||||||
|
cp $7C
|
||||||
|
jr nz, .redNotMaxed
|
||||||
|
res 2, b
|
||||||
|
.redNotMaxed
|
||||||
|
|
||||||
|
; add de, bc
|
||||||
|
; ld [hli], de
|
||||||
|
ld a, e
|
||||||
|
add c
|
||||||
|
ld [hli], a
|
||||||
|
ld a, d
|
||||||
|
adc b
|
||||||
|
ld [hli], a
|
||||||
pop bc
|
pop bc
|
||||||
|
|
||||||
dec c
|
dec c
|
||||||
jr nz, .frameLoop
|
jr nz, .frameLoop
|
||||||
|
|
||||||
call WaitFrame
|
call WaitFrame
|
||||||
call WaitFrame
|
pop hl
|
||||||
ld hl, BgPalettes
|
|
||||||
call LoadBGPalettes64
|
call LoadBGPalettes64
|
||||||
|
call WaitFrame
|
||||||
dec b
|
dec b
|
||||||
jr nz, .fadeLoop
|
jr nz, .fadeLoop
|
||||||
ENDC
|
ENDC
|
||||||
|
ld a, 1
|
||||||
call ClearVRAMViaHDMA
|
call ClearVRAMViaHDMA
|
||||||
; Select the first bank
|
call _ClearVRAMViaHDMA
|
||||||
xor a
|
call ClearVRAMViaHDMA ; A = $40, so it's bank 0
|
||||||
ldh [$4F], a
|
ld a, $ff
|
||||||
cpl
|
|
||||||
ldh [$00], a
|
ldh [$00], a
|
||||||
call ClearVRAMViaHDMA
|
|
||||||
|
|
||||||
; Final values for CGB mode
|
; Final values for CGB mode
|
||||||
ld de, $ff56
|
ld d, a
|
||||||
|
ld e, c
|
||||||
ld l, $0d
|
ld l, $0d
|
||||||
|
|
||||||
ld a, [$143]
|
ld a, [$143]
|
||||||
@ -818,7 +887,7 @@ IF DEF(AGB)
|
|||||||
ld c, a
|
ld c, a
|
||||||
add a, $11
|
add a, $11
|
||||||
ld h, c
|
ld h, c
|
||||||
ld b, 1
|
; B is set to 1 after ret
|
||||||
ELSE
|
ELSE
|
||||||
; Set registers to match the original CGB boot
|
; Set registers to match the original CGB boot
|
||||||
; AF = $1180, C = 0
|
; AF = $1180, C = 0
|
||||||
@ -836,6 +905,14 @@ ENDC
|
|||||||
ld a, $1
|
ld a, $1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
GetKeyComboPalette:
|
||||||
|
ld hl, KeyCombinationPalettes - 1 ; Return value is 1-based, 0 means nothing down
|
||||||
|
ld c ,a
|
||||||
|
ld b, 0
|
||||||
|
add hl, bc
|
||||||
|
ld a, [hl]
|
||||||
|
ret
|
||||||
|
|
||||||
EmulateDMG:
|
EmulateDMG:
|
||||||
ld a, 1
|
ld a, 1
|
||||||
ldh [$6C], a ; DMG Emulation
|
ldh [$6C], a ; DMG Emulation
|
||||||
@ -847,11 +924,7 @@ EmulateDMG:
|
|||||||
ldh a, [InputPalette]
|
ldh a, [InputPalette]
|
||||||
and a
|
and a
|
||||||
jr z, .nothingDown
|
jr z, .nothingDown
|
||||||
ld hl, KeyCombinationPalettes - 1 ; Return value is 1-based, 0 means nothing down
|
call GetKeyComboPalette
|
||||||
ld c ,a
|
|
||||||
ld b, 0
|
|
||||||
add hl, bc
|
|
||||||
ld a, [hl]
|
|
||||||
jr .paletteFromKeys
|
jr .paletteFromKeys
|
||||||
.nothingDown
|
.nothingDown
|
||||||
ld a, b
|
ld a, b
|
||||||
@ -860,8 +933,7 @@ EmulateDMG:
|
|||||||
call LoadPalettesFromIndex
|
call LoadPalettesFromIndex
|
||||||
ld a, 4
|
ld a, 4
|
||||||
; Set the final values for DMG mode
|
; Set the final values for DMG mode
|
||||||
ld d, 0
|
ld de, 8
|
||||||
ld e, $8
|
|
||||||
ld l, $7c
|
ld l, $7c
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@ -934,16 +1006,15 @@ GetPaletteIndex:
|
|||||||
xor a
|
xor a
|
||||||
ret
|
ret
|
||||||
|
|
||||||
LoadPalettesFromIndex: ; a = index of combination
|
GetPaletteCombo:
|
||||||
ld b, a
|
|
||||||
; Multiply by 3
|
|
||||||
add b
|
|
||||||
add b
|
|
||||||
|
|
||||||
ld hl, PaletteCombinations
|
ld hl, PaletteCombinations
|
||||||
ld b, 0
|
ld b, 0
|
||||||
ld c, a
|
ld c, a
|
||||||
add hl, bc
|
add hl, bc
|
||||||
|
ret
|
||||||
|
|
||||||
|
LoadPalettesFromIndex: ; a = index of combination
|
||||||
|
call GetPaletteCombo
|
||||||
|
|
||||||
; Obj Palettes
|
; Obj Palettes
|
||||||
ld e, 0
|
ld e, 0
|
||||||
@ -955,7 +1026,8 @@ LoadPalettesFromIndex: ; a = index of combination
|
|||||||
ld c, a
|
ld c, a
|
||||||
add hl, bc
|
add hl, bc
|
||||||
ld d, 8
|
ld d, 8
|
||||||
call LoadObjPalettes
|
ld c, $6A
|
||||||
|
call LoadPalettes
|
||||||
pop hl
|
pop hl
|
||||||
bit 3, e
|
bit 3, e
|
||||||
jr nz, .loadBGPalette
|
jr nz, .loadBGPalette
|
||||||
@ -969,76 +1041,39 @@ LoadPalettesFromIndex: ; a = index of combination
|
|||||||
ld c, a
|
ld c, a
|
||||||
add hl, bc
|
add hl, bc
|
||||||
ld d, 8
|
ld d, 8
|
||||||
jp LoadBGPalettes
|
jr LoadBGPalettes
|
||||||
|
|
||||||
BrightenColor:
|
LoadBGPalettes64:
|
||||||
|
ld d, 64
|
||||||
|
|
||||||
|
LoadBGPalettes:
|
||||||
|
ld e, 0
|
||||||
|
ld c, $68
|
||||||
|
|
||||||
|
LoadPalettes:
|
||||||
|
ld a, $80
|
||||||
|
or e
|
||||||
|
ld [c], a
|
||||||
|
inc c
|
||||||
|
.loop
|
||||||
ld a, [hli]
|
ld a, [hli]
|
||||||
ld e, a
|
ld [c], a
|
||||||
ld a, [hld]
|
dec d
|
||||||
ld d, a
|
jr nz, .loop
|
||||||
; RGB(1,1,1)
|
|
||||||
ld bc, $421
|
|
||||||
|
|
||||||
; Is blue maxed?
|
|
||||||
ld a, e
|
|
||||||
and $1F
|
|
||||||
cp $1F
|
|
||||||
jr nz, .blueNotMaxed
|
|
||||||
res 0, c
|
|
||||||
.blueNotMaxed
|
|
||||||
|
|
||||||
; Is green maxed?
|
|
||||||
ld a, e
|
|
||||||
and $E0
|
|
||||||
cp $E0
|
|
||||||
jr nz, .greenNotMaxed
|
|
||||||
ld a, d
|
|
||||||
and $3
|
|
||||||
cp $3
|
|
||||||
jr nz, .greenNotMaxed
|
|
||||||
res 5, c
|
|
||||||
.greenNotMaxed
|
|
||||||
|
|
||||||
; Is red maxed?
|
|
||||||
ld a, d
|
|
||||||
and $7C
|
|
||||||
cp $7C
|
|
||||||
jr nz, .redNotMaxed
|
|
||||||
res 2, b
|
|
||||||
.redNotMaxed
|
|
||||||
|
|
||||||
; Add de to bc
|
|
||||||
push hl
|
|
||||||
ld h, d
|
|
||||||
ld l, e
|
|
||||||
add hl, bc
|
|
||||||
ld d, h
|
|
||||||
ld e, l
|
|
||||||
pop hl
|
|
||||||
|
|
||||||
ld a, e
|
|
||||||
ld [hli], a
|
|
||||||
ld a, d
|
|
||||||
ld [hli], a
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
ClearVRAMViaHDMA:
|
ClearVRAMViaHDMA:
|
||||||
ld hl, $FF51
|
ldh [$4F], a
|
||||||
|
ld hl, HDMAData
|
||||||
; Src
|
_ClearVRAMViaHDMA:
|
||||||
ld a, $88
|
ld c, $51
|
||||||
ld [hli], a
|
ld b, 5
|
||||||
xor a
|
.loop
|
||||||
ld [hli], a
|
ld a, [hli]
|
||||||
|
ldh [c], a
|
||||||
; Dest
|
inc c
|
||||||
ld a, $98
|
dec b
|
||||||
ld [hli], a
|
jr nz, .loop
|
||||||
ld a, $A0
|
|
||||||
ld [hli], a
|
|
||||||
|
|
||||||
; Do it
|
|
||||||
ld [hl], $12
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
GetInputPaletteIndex:
|
GetInputPaletteIndex:
|
||||||
@ -1077,24 +1112,12 @@ GetInputPaletteIndex:
|
|||||||
; Slide into change Animation Palette
|
; Slide into change Animation Palette
|
||||||
|
|
||||||
ChangeAnimationPalette:
|
ChangeAnimationPalette:
|
||||||
push af
|
|
||||||
push hl
|
|
||||||
push bc
|
push bc
|
||||||
push de
|
push de
|
||||||
ld hl, KeyCombinationPalettes - 1 ; Input palettes are 1-based, 0 means nothing down
|
call GetKeyComboPalette
|
||||||
ld c ,a
|
call GetPaletteCombo
|
||||||
ld b, 0
|
inc l
|
||||||
add hl, bc
|
inc l
|
||||||
ld a, [hl]
|
|
||||||
ld b, a
|
|
||||||
; Multiply by 3
|
|
||||||
add b
|
|
||||||
add b
|
|
||||||
|
|
||||||
ld hl, PaletteCombinations + 2; Background Palette
|
|
||||||
ld b, 0
|
|
||||||
ld c, a
|
|
||||||
add hl, bc
|
|
||||||
ld a, [hl]
|
ld a, [hl]
|
||||||
ld hl, Palettes + 1
|
ld hl, Palettes + 1
|
||||||
ld b, 0
|
ld b, 0
|
||||||
@ -1108,47 +1131,73 @@ ChangeAnimationPalette:
|
|||||||
.isWhite
|
.isWhite
|
||||||
push af
|
push af
|
||||||
ld a, [hli]
|
ld a, [hli]
|
||||||
|
|
||||||
push hl
|
push hl
|
||||||
ld hl, BgPalettes ; First color, all palette
|
ld hl, BgPalettes ; First color, all palettes
|
||||||
|
call ReplaceColorInAllPalettes
|
||||||
|
ld l, LOW(BgPalettes + 2) ; Second color, all palettes
|
||||||
call ReplaceColorInAllPalettes
|
call ReplaceColorInAllPalettes
|
||||||
pop hl
|
pop hl
|
||||||
ldh [BgPalettes + 2], a ; Second color, first palette
|
ldh [BgPalettes + 6], a ; Fourth color, first palette
|
||||||
|
|
||||||
ld a, [hli]
|
ld a, [hli]
|
||||||
push hl
|
push hl
|
||||||
ld hl, BgPalettes + 1 ; First color, all palette
|
ld hl, BgPalettes + 1 ; First color, all palettes
|
||||||
|
call ReplaceColorInAllPalettes
|
||||||
|
ld l, LOW(BgPalettes + 3) ; Second color, all palettes
|
||||||
call ReplaceColorInAllPalettes
|
call ReplaceColorInAllPalettes
|
||||||
pop hl
|
pop hl
|
||||||
ldh [BgPalettes + 3], a ; Second color, first palette
|
ldh [BgPalettes + 7], a ; Fourth color, first palette
|
||||||
|
|
||||||
pop af
|
pop af
|
||||||
jr z, .isNotWhite
|
jr z, .isNotWhite
|
||||||
inc hl
|
inc hl
|
||||||
inc hl
|
inc hl
|
||||||
.isNotWhite
|
.isNotWhite
|
||||||
|
; Mixing code by ISSOtm
|
||||||
|
ldh a, [BgPalettes + 7 * 8 + 2]
|
||||||
|
and ~$21
|
||||||
|
ld b, a
|
||||||
ld a, [hli]
|
ld a, [hli]
|
||||||
ldh [BgPalettes + 7 * 8 + 2], a ; Second color, 7th palette
|
and ~$21
|
||||||
|
add a, b
|
||||||
|
ld b, a
|
||||||
|
ld a, [BgPalettes + 7 * 8 + 3]
|
||||||
|
res 2, a ; and ~$04, but not touching carry
|
||||||
|
ld c, [hl]
|
||||||
|
res 2, c ; and ~$04, but not touching carry
|
||||||
|
adc a, c
|
||||||
|
rra ; Carry sort of "extends" the accumulator, we're bringing that bit back home
|
||||||
|
ld [BgPalettes + 7 * 8 + 3], a
|
||||||
|
ld a, b
|
||||||
|
rra
|
||||||
|
ld [BgPalettes + 7 * 8 + 2], a
|
||||||
|
dec l
|
||||||
|
|
||||||
ld a, [hli]
|
ld a, [hli]
|
||||||
ldh [BgPalettes + 7 * 8 + 3], a ; Second color, 7th palette
|
ldh [BgPalettes + 7 * 8 + 6], a ; Fourth color, 7th palette
|
||||||
|
ld a, [hli]
|
||||||
|
ldh [BgPalettes + 7 * 8 + 7], a ; Fourth color, 7th palette
|
||||||
|
|
||||||
ld a, [hli]
|
ld a, [hli]
|
||||||
ldh [BgPalettes + 4], a ; Third color, first palette
|
ldh [BgPalettes + 4], a ; Third color, first palette
|
||||||
ld a, [hl]
|
ld a, [hli]
|
||||||
ldh [BgPalettes + 5], a ; Third color, first palette
|
ldh [BgPalettes + 5], a ; Third color, first palette
|
||||||
|
|
||||||
|
|
||||||
call WaitFrame
|
call WaitFrame
|
||||||
ld hl, BgPalettes
|
ld hl, BgPalettes
|
||||||
call LoadBGPalettes64
|
call LoadBGPalettes64
|
||||||
; Delay the wait loop while the user is selecting a palette
|
; Delay the wait loop while the user is selecting a palette
|
||||||
ld a, 30
|
ld a, 45
|
||||||
ldh [WaitLoopCounter], a
|
ldh [WaitLoopCounter], a
|
||||||
pop de
|
pop de
|
||||||
pop bc
|
pop bc
|
||||||
pop hl
|
|
||||||
pop af
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
ReplaceColorInAllPalettes:
|
ReplaceColorInAllPalettes:
|
||||||
ld de, 8
|
ld de, 8
|
||||||
ld c, 8
|
ld c, e
|
||||||
.loop
|
.loop
|
||||||
ld [hl], a
|
ld [hl], a
|
||||||
add hl, de
|
add hl, de
|
||||||
@ -1159,7 +1208,7 @@ ReplaceColorInAllPalettes:
|
|||||||
LoadDMGTilemap:
|
LoadDMGTilemap:
|
||||||
push af
|
push af
|
||||||
call WaitFrame
|
call WaitFrame
|
||||||
ld a,$19 ; Trademark symbol
|
ld a, $19 ; Trademark symbol
|
||||||
ld [$9910], a ; ... put in the superscript position
|
ld [$9910], a ; ... put in the superscript position
|
||||||
ld hl,$992f ; Bottom right corner of the logo
|
ld hl,$992f ; Bottom right corner of the logo
|
||||||
ld c,$c ; Tiles in a logo row
|
ld c,$c ; Tiles in a logo row
|
||||||
@ -1169,27 +1218,20 @@ LoadDMGTilemap:
|
|||||||
ldd [hl], a
|
ldd [hl], a
|
||||||
dec c
|
dec c
|
||||||
jr nz, .tilemapLoop
|
jr nz, .tilemapLoop
|
||||||
ld l,$0f ; Jump to top row
|
ld l, $0f ; Jump to top row
|
||||||
jr .tilemapLoop
|
jr .tilemapLoop
|
||||||
.tilemapDone
|
.tilemapDone
|
||||||
pop af
|
pop af
|
||||||
ret
|
ret
|
||||||
|
|
||||||
InitWaveform:
|
HDMAData:
|
||||||
ld hl, $FF30
|
db $88, $00, $98, $A0, $12
|
||||||
; Init waveform
|
db $88, $00, $80, $00, $40
|
||||||
xor a
|
|
||||||
ld c, $10
|
|
||||||
.waveformLoop
|
|
||||||
ldi [hl], a
|
|
||||||
cpl
|
|
||||||
dec c
|
|
||||||
jr nz, .waveformLoop
|
|
||||||
ret
|
|
||||||
|
|
||||||
SECTION "ROMMax", ROM0[$900]
|
BootEnd:
|
||||||
; Prevent us from overflowing
|
IF BootEnd > $900
|
||||||
ds 1
|
FAIL "BootROM overflowed: {BootEnd}"
|
||||||
|
ENDC
|
||||||
|
|
||||||
SECTION "HRAM", HRAM[$FF80]
|
SECTION "HRAM", HRAM[$FF80]
|
||||||
TitleChecksum:
|
TitleChecksum:
|
||||||
|
95
BootROMs/pb12.c
Normal file
95
BootROMs/pb12.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
void opts(uint8_t byte, uint8_t *options)
|
||||||
|
{
|
||||||
|
*(options++) = byte | ((byte << 1) & 0xff);
|
||||||
|
*(options++) = byte & (byte << 1);
|
||||||
|
*(options++) = byte | ((byte >> 1) & 0xff);
|
||||||
|
*(options++) = byte & (byte >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
static uint8_t source[0x4000];
|
||||||
|
size_t size = read(STDIN_FILENO, &source, sizeof(source));
|
||||||
|
unsigned pos = 0;
|
||||||
|
assert(size <= 0x4000);
|
||||||
|
while (size && source[size - 1] == 0) {
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *literals = NULL;
|
||||||
|
size_t literals_size = 0;
|
||||||
|
unsigned bits = 0;
|
||||||
|
unsigned control = 0;
|
||||||
|
unsigned prev[2] = {-1, -1}; // Unsigned to allow "not set" values
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
uint8_t byte = 0;
|
||||||
|
if (pos == size){
|
||||||
|
if (bits == 0) break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
byte = source[pos++];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (byte == prev[0] || byte == prev[1]) {
|
||||||
|
bits += 2;
|
||||||
|
control <<= 1;
|
||||||
|
control |= 1;
|
||||||
|
control <<= 1;
|
||||||
|
if (byte == prev[1]) {
|
||||||
|
control |= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bits += 2;
|
||||||
|
control <<= 2;
|
||||||
|
uint8_t options[4];
|
||||||
|
opts(prev[1], options);
|
||||||
|
bool found = false;
|
||||||
|
for (unsigned i = 0; i < 4; i++) {
|
||||||
|
if (options[i] == byte) {
|
||||||
|
// 01 = modify
|
||||||
|
control |= 1;
|
||||||
|
|
||||||
|
bits += 2;
|
||||||
|
control <<= 2;
|
||||||
|
control |= i;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
literals = realloc(literals, literals_size++);
|
||||||
|
literals[literals_size - 1] = byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev[0] = prev[1];
|
||||||
|
prev[1] = byte;
|
||||||
|
if (bits >= 8) {
|
||||||
|
uint8_t outctl = control >> (bits - 8);
|
||||||
|
assert(outctl != 1);
|
||||||
|
write(STDOUT_FILENO, &outctl, 1);
|
||||||
|
write(STDOUT_FILENO, literals, literals_size);
|
||||||
|
bits -= 8;
|
||||||
|
control &= (1 << bits) - 1;
|
||||||
|
literals_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t end_byte = 1;
|
||||||
|
write(STDOUT_FILENO, &end_byte, 1);
|
||||||
|
|
||||||
|
if (literals) {
|
||||||
|
free(literals);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
341
BootROMs/pb8.c
341
BootROMs/pb8.c
@ -1,341 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
PB8 compressor and decompressor
|
|
||||||
|
|
||||||
Copyright 2019 Damian Yerrick
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
// For setting stdin/stdout to binary mode
|
|
||||||
#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
|
|
||||||
#include <unistd.h>
|
|
||||||
#define fd_isatty isatty
|
|
||||||
#elif defined (_WIN32)
|
|
||||||
#include <io.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#define fd_isatty _isatty
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
; The logo is compressed using PB8, a form of RLE with unary-coded
|
|
||||||
; run lengths. Each block representing 8 bytes consists of a control
|
|
||||||
; byte, where each bit (MSB to LSB) is 0 for literal or 1 for repeat
|
|
||||||
; previous, followed by the literals in that block.
|
|
||||||
|
|
||||||
SameBoyLogo_dst = $8080
|
|
||||||
SameBoyLogo_length = (128 * 24) / 64
|
|
||||||
|
|
||||||
LoadTileset:
|
|
||||||
ld hl, SameBoyLogo
|
|
||||||
ld de, SameBoyLogo_dst
|
|
||||||
ld c, SameBoyLogo_length
|
|
||||||
.pb8BlockLoop:
|
|
||||||
; Register map for PB8 decompression
|
|
||||||
; HL: source address in boot ROM
|
|
||||||
; DE: destination address in VRAM
|
|
||||||
; A: Current literal value
|
|
||||||
; B: Repeat bits, terminated by 1000...
|
|
||||||
; C: Number of 8-byte blocks left in this block
|
|
||||||
; Source address in HL lets the repeat bits go straight to B,
|
|
||||||
; bypassing A and avoiding spilling registers to the stack.
|
|
||||||
ld b, [hl]
|
|
||||||
inc hl
|
|
||||||
|
|
||||||
; Shift a 1 into lower bit of shift value. Once this bit
|
|
||||||
; reaches the carry, B becomes 0 and the byte is over
|
|
||||||
scf
|
|
||||||
rl b
|
|
||||||
|
|
||||||
.pb8BitLoop:
|
|
||||||
; If not a repeat, load a literal byte
|
|
||||||
jr c,.pb8Repeat
|
|
||||||
ld a, [hli]
|
|
||||||
.pb8Repeat:
|
|
||||||
; Decompressed data uses colors 0 and 1, so write once, inc twice
|
|
||||||
ld [de], a
|
|
||||||
inc de
|
|
||||||
inc de
|
|
||||||
sla b
|
|
||||||
jr nz, .pb8BitLoop
|
|
||||||
|
|
||||||
dec c
|
|
||||||
jr nz, .pb8BlockLoop
|
|
||||||
ret
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Compressor and decompressor *************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compresses an input stream to PB8 data on an output stream.
|
|
||||||
* @param infp input stream
|
|
||||||
* @param outfp output stream
|
|
||||||
* @param blocklength size of an independent input block in bytes
|
|
||||||
* @return 0 for reaching infp end of file, or EOF for error
|
|
||||||
*/
|
|
||||||
int pb8(FILE *infp, FILE *outfp, size_t blocklength)
|
|
||||||
{
|
|
||||||
blocklength >>= 3; // convert bytes to blocks
|
|
||||||
assert(blocklength > 0);
|
|
||||||
while (1) {
|
|
||||||
int last_byte = EOF; // value that never occurs in a file
|
|
||||||
for (size_t blkleft = blocklength; blkleft > 0; --blkleft) {
|
|
||||||
unsigned int control_byte = 0x0001;
|
|
||||||
unsigned char literals[8];
|
|
||||||
size_t nliterals = 0;
|
|
||||||
while (control_byte < 0x100) {
|
|
||||||
int c = fgetc(infp);
|
|
||||||
if (c == EOF) break;
|
|
||||||
|
|
||||||
control_byte <<= 1;
|
|
||||||
if (c == last_byte) {
|
|
||||||
control_byte |= 0x01;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
literals[nliterals++] = last_byte = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (control_byte > 1) {
|
|
||||||
// Fill partial block with repeats
|
|
||||||
while (control_byte < 0x100) {
|
|
||||||
control_byte = (control_byte << 1) | 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write control byte and check for write failure
|
|
||||||
int ok = fputc(control_byte & 0xFF, outfp);
|
|
||||||
if (ok == EOF) return EOF;
|
|
||||||
size_t ok2 = fwrite(literals, 1, nliterals, outfp);
|
|
||||||
if (ok2 < nliterals) return EOF;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If finished, return success or failure
|
|
||||||
if (ferror(infp) || ferror(outfp)) return EOF;
|
|
||||||
if (feof(infp)) return 0;
|
|
||||||
} // End 8-byte block
|
|
||||||
} // End packet, resetting last_byte
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decompresses PB8 data on an input stream to an output stream.
|
|
||||||
* @param infp input stream
|
|
||||||
* @param outfp output stream
|
|
||||||
* @return 0 for reaching infp end of file, or EOF for error
|
|
||||||
*/
|
|
||||||
int unpb8(FILE *infp, FILE *outfp)
|
|
||||||
{
|
|
||||||
int last_byte = 0;
|
|
||||||
while (1) {
|
|
||||||
int control_byte = fgetc(infp);
|
|
||||||
if (control_byte == EOF) {
|
|
||||||
return feof(infp) ? 0 : EOF;
|
|
||||||
}
|
|
||||||
control_byte &= 0xFF;
|
|
||||||
for (size_t bytesleft = 8; bytesleft > 0; --bytesleft) {
|
|
||||||
if (!(control_byte & 0x80)) {
|
|
||||||
last_byte = fgetc(infp);
|
|
||||||
if (last_byte == EOF) return EOF; // read error
|
|
||||||
}
|
|
||||||
control_byte <<= 1;
|
|
||||||
int ok = fputc(last_byte, outfp);
|
|
||||||
if (ok == EOF) return EOF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* CLI frontend ****************************************************/
|
|
||||||
|
|
||||||
static inline void set_fd_binary(unsigned int fd)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
_setmode(fd, _O_BINARY);
|
|
||||||
#else
|
|
||||||
(void) fd;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *usage_msg =
|
|
||||||
"usage: pb8 [-d] [-l blocklength] [infile [outfile]]\n"
|
|
||||||
"Compresses a file using RLE with unary run and literal lengths.\n"
|
|
||||||
"\n"
|
|
||||||
"options:\n"
|
|
||||||
" -d decompress\n"
|
|
||||||
" -l blocklength allow RLE packets to span up to blocklength\n"
|
|
||||||
" input bytes (multiple of 8; default 8)\n"
|
|
||||||
" -h, -?, --help show this usage page\n"
|
|
||||||
" --version show copyright info\n"
|
|
||||||
"\n"
|
|
||||||
"If infile is - or missing, it is standard input.\n"
|
|
||||||
"If outfile is - or missing, it is standard output.\n"
|
|
||||||
"You cannot compress to or decompress from a terminal.\n"
|
|
||||||
;
|
|
||||||
static const char *version_msg =
|
|
||||||
"PB8 compressor (C version) v0.01\n"
|
|
||||||
"Copyright 2019 Damian Yerrick <https://pineight.com/contact/>\n"
|
|
||||||
"This software is provided 'as-is', without any express or implied\n"
|
|
||||||
"warranty.\n"
|
|
||||||
;
|
|
||||||
static const char *toomanyfilenames_msg =
|
|
||||||
"pb8: too many filenames; try pb8 --help\n";
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
const char *infilename = NULL;
|
|
||||||
const char *outfilename = NULL;
|
|
||||||
bool decompress = false;
|
|
||||||
size_t blocklength = 8;
|
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i) {
|
|
||||||
if (argv[i][0] == '-' && argv[i][1] != 0) {
|
|
||||||
if (!strcmp(argv[i], "--help")) {
|
|
||||||
fputs(usage_msg, stdout);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!strcmp(argv[i], "--version")) {
|
|
||||||
fputs(version_msg, stdout);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -t1 or -t 1
|
|
||||||
int argtype = argv[i][1];
|
|
||||||
switch (argtype) {
|
|
||||||
case 'h':
|
|
||||||
case '?':
|
|
||||||
fputs(usage_msg, stdout);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case 'd':
|
|
||||||
decompress = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'l': {
|
|
||||||
const char *argvalue = argv[i][2] ? argv[i] + 2 : argv[++i];
|
|
||||||
const char *endptr = NULL;
|
|
||||||
|
|
||||||
unsigned long tvalue = strtoul(argvalue, (char **)&endptr, 10);
|
|
||||||
if (endptr == argvalue || tvalue == 0 || tvalue > SIZE_MAX) {
|
|
||||||
fprintf(stderr, "pb8: block length %s not a positive integer\n",
|
|
||||||
argvalue);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
if (tvalue % 8 != 0) {
|
|
||||||
fprintf(stderr, "pb8: block length %s not a multiple of 8\n",
|
|
||||||
argvalue);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
blocklength = tvalue;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "pb8: unknown option -%c\n", argtype);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!infilename) {
|
|
||||||
infilename = argv[i];
|
|
||||||
}
|
|
||||||
else if (!outfilename) {
|
|
||||||
outfilename = argv[i];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fputs(toomanyfilenames_msg, stderr);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (infilename && !strcmp(infilename, "-")) {
|
|
||||||
infilename = NULL;
|
|
||||||
}
|
|
||||||
if (!infilename && decompress && fd_isatty(0)) {
|
|
||||||
fputs("pb8: cannot decompress from terminal; try redirecting stdin\n",
|
|
||||||
stderr);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
if (outfilename && !strcmp(outfilename, "-")) {
|
|
||||||
outfilename = NULL;
|
|
||||||
}
|
|
||||||
if (!outfilename && !decompress && fd_isatty(1)) {
|
|
||||||
fputs("pb8: cannot compress to terminal; try redirecting stdout or pb8 --help\n",
|
|
||||||
stderr);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *infp = NULL;
|
|
||||||
if (infilename) {
|
|
||||||
infp = fopen(infilename, "rb");
|
|
||||||
if (!infp) {
|
|
||||||
fprintf(stderr, "pb8: error opening %s ", infilename);
|
|
||||||
perror("for reading");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
infp = stdin;
|
|
||||||
set_fd_binary(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *outfp = NULL;
|
|
||||||
if (outfilename) {
|
|
||||||
outfp = fopen(outfilename, "wb");
|
|
||||||
if (!outfp) {
|
|
||||||
fprintf(stderr, "pb8: error opening %s ", outfilename);
|
|
||||||
perror("for writing");
|
|
||||||
fclose(infp);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
outfp = stdout;
|
|
||||||
set_fd_binary(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int compfailed = 0;
|
|
||||||
int has_ferror = 0;
|
|
||||||
if (decompress) {
|
|
||||||
compfailed = unpb8(infp, outfp);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
compfailed = pb8(infp, outfp, blocklength);
|
|
||||||
}
|
|
||||||
fflush(outfp);
|
|
||||||
if (ferror(infp)) {
|
|
||||||
fprintf(stderr, "pb8: error reading %s\n",
|
|
||||||
infilename ? infilename : "<stdin>");
|
|
||||||
has_ferror = EOF;
|
|
||||||
}
|
|
||||||
fclose(infp);
|
|
||||||
if (ferror(outfp)) {
|
|
||||||
fprintf(stderr, "pb8: error writing %s\n",
|
|
||||||
outfilename ? outfilename : "<stdout>");
|
|
||||||
has_ferror = EOF;
|
|
||||||
}
|
|
||||||
fclose(outfp);
|
|
||||||
|
|
||||||
if (compfailed && !has_ferror) {
|
|
||||||
fputs("pb8: unknown compression failure\n", stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (compfailed || has_ferror) ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
||||||
}
|
|
16
Makefile
16
Makefile
@ -20,7 +20,7 @@ else
|
|||||||
EXESUFFIX:=
|
EXESUFFIX:=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PB8_COMPRESS := build/pb8$(EXESUFFIX)
|
PB12_COMPRESS := build/pb12$(EXESUFFIX)
|
||||||
|
|
||||||
ifeq ($(PLATFORM),Darwin)
|
ifeq ($(PLATFORM),Darwin)
|
||||||
DEFAULT := cocoa
|
DEFAULT := cocoa
|
||||||
@ -382,21 +382,21 @@ $(BIN)/SDL/Shaders: Shaders
|
|||||||
|
|
||||||
# Boot ROMs
|
# Boot ROMs
|
||||||
|
|
||||||
$(OBJ)/%.1bpp: %.png
|
$(OBJ)/%.2bpp: %.png
|
||||||
-@$(MKDIR) -p $(dir $@)
|
-@$(MKDIR) -p $(dir $@)
|
||||||
rgbgfx -d 1 -h -o $@ $<
|
rgbgfx -h -u -o $@ $<
|
||||||
|
|
||||||
$(OBJ)/BootROMs/SameBoyLogo.pb8: $(OBJ)/BootROMs/SameBoyLogo.1bpp $(PB8_COMPRESS)
|
$(OBJ)/BootROMs/SameBoyLogo.pb12: $(OBJ)/BootROMs/SameBoyLogo.2bpp $(PB12_COMPRESS)
|
||||||
$(realpath $(PB8_COMPRESS)) -l 384 $< $@
|
$(PB12_COMPRESS) < $< > $@
|
||||||
|
|
||||||
$(PB8_COMPRESS): BootROMs/pb8.c
|
$(PB12_COMPRESS): BootROMs/pb12.c
|
||||||
$(CC) $< -o $@
|
$(CC) -Wall -Werror $< -o $@
|
||||||
|
|
||||||
$(BIN)/BootROMs/agb_boot.bin: BootROMs/cgb_boot.asm
|
$(BIN)/BootROMs/agb_boot.bin: BootROMs/cgb_boot.asm
|
||||||
$(BIN)/BootROMs/cgb_boot_fast.bin: BootROMs/cgb_boot.asm
|
$(BIN)/BootROMs/cgb_boot_fast.bin: BootROMs/cgb_boot.asm
|
||||||
$(BIN)/BootROMs/sgb2_boot: BootROMs/sgb_boot.asm
|
$(BIN)/BootROMs/sgb2_boot: BootROMs/sgb_boot.asm
|
||||||
|
|
||||||
$(BIN)/BootROMs/%.bin: BootROMs/%.asm $(OBJ)/BootROMs/SameBoyLogo.pb8
|
$(BIN)/BootROMs/%.bin: BootROMs/%.asm $(OBJ)/BootROMs/SameBoyLogo.pb12
|
||||||
-@$(MKDIR) -p $(dir $@)
|
-@$(MKDIR) -p $(dir $@)
|
||||||
rgbasm -i $(OBJ)/BootROMs/ -i BootROMs/ -o $@.tmp $<
|
rgbasm -i $(OBJ)/BootROMs/ -i BootROMs/ -o $@.tmp $<
|
||||||
rgblink -o $@.tmp2 $@.tmp
|
rgblink -o $@.tmp2 $@.tmp
|
||||||
|
Loading…
Reference in New Issue
Block a user