Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; Remember to pass the -d flag to RGBLINK!
- ; This enables DMG mode, removes VRAM and WRAM banks.
- ; It's more convenient.
- SECTION "Frame buffer tiles", VRAM[$8000]
- vFrameBufferTiles::
- ds 1180 tiles ; 180 tiles
- ; Note: the copy will overshoot slightly, but that shouldn't be a problem
- ; Remember to fill tile $FF with either black or white, and letterbox using that
- ; You don't *have* to use tile $FF, but it's a good pick, I guess?
- (...)
- SECTION "Frame buffer tiles", WRAM0,ALIGN[8]
- wFrameBufferTiles::
- ds 180 * 16 ; 180 tiles
- wFrameBufferTilesEnd::
- ; The copy will also overshoot here, but overreading shouldn't be a big deal :P
- (...)
- SECTION "SP buffer", WRAM0
- wSPBuffer::
- ds 2
- (...)
- SECTION "Transfer vars", HRAM
- ; Set to 0 to transfer frame buffer
- hDoUpdate::
- ds 1
- ; Position of VRAM transfer
- hHBlankTransferLow::
- ds 1
- (...)
- SECTION "Init", ROM0
- (...)
- ld a, %11110000
- ldh [rBGP], a
- xor a
- ldh [rSCX], a ; This is important!
- ld a, STATF_LYC | STATF_MODE00
- ldh [rSTAT], a
- (...)
- ; Make sure you clear OAM before turning the screen on!
- xor a
- ld hl, $FEA0
- .clearOAM
- ld [hl], a
- dec l
- jr nz, .clearOAM
- ld [hl], a
- (...)
- ; When turning the screen on
- ld a, LCDCF_ON | LCDCF_BG8000 | LCDCF_BGON ; Do NOT use the window or sprites
- ldh [rLCDC], a
- (...)
- (...)
- ; VBlank is 1140 cycles
- ; 6 for dispatch (including the interrupted instruction finishing)
- ; 32 overhead
- ; = 1102 left
- ; 9 per 2 bytes transferred, therefore...
- BYTES_PER_VBLANK equ 244 ; Make sure this is even!!
- ; HBlank is 71 cycles
- ; 6 for dispatch (same)
- ; 48 overhead (up to `inc [hl]`)
- ; -1 due to letterboxing leniency
- ; = 18 left
- ; 5 bytes per byte transferred, -1 for last one
- ; Therefore...
- BYTES_PER_HBLANK equ 3
- SECTION "Interrupt handlers", ROM0[$0032]
- LYCHandler:
- ; Toggle the palette to switch between bitplanes
- ldh a, [rBGP]
- xor %00111100
- ldh [rBGP], a
- ; Move LYC to lower part of the screen to toggle palette back (during letterboxing)
- ; This also makes the next handler behave as a Mode 0 int, since LY != LYC
- ; Otherwise things would... break...
- ldh a, [rLYC]
- xor 72 ^ (72 + 32)
- ldh [rLYC], a
- jp PerformUpscaling
- VBlankHandler: ; @0040
- push af
- push hl
- ld hl, vFrameBufferTiles
- jp TransferTiles
- STATHandler: ; @0048
- push af
- push hl
- ldh a, [rSTAT]
- bit 2, a
- jr nz, LYCHandler
- ; HBlank handler: transfer bytes!
- push de
- ; Move to next transfer unit
- ; Assumes the initial value has been offset so the first transfer starts where correct
- ldh a, [hHBlankTransferLow]
- ; Check if transfer has completed
- cp LOW(wFrameBufferTilesEnd)
- jr nc, PerformUpscaling
- ; Move to next unit
- add a, BYTES_PER_HBLANK
- ldh [hHBlankTransferLow], a
- ; Set up regs
- ld l, a
- ld h, HIGH(wFrameBufferTiles)
- ld e, a
- ld d, HIGH(vFrameBufferTiles)
- REPT BYTES_PER_HBLANK - 1
- ld a, [hli]
- ld [de], a
- inc e
- ENDR
- ld a, [hli]
- ld [de], a
- pop de
- PerformUpscaling:
- ; Perform hardware upscaling:
- ; Increment SCY every other scanline to render it twice
- ldh a, [rLY]
- rra ; Shift parity bit into carry
- jr c, .dontShift
- ld hl, rSCY
- dec [hl]
- .dontShift
- ; Restore regs and exit
- pop hl
- pop af
- reti
- TransferTiles:
- push de
- ; Check if updating needs to be done
- ldh a, [hDoUpdate]
- and a
- jp nz, .noUpdate
- ; Save SP 'cause we gonna trash it
- ld [wSPBuffer], sp
- REPT BYTES_PER_VBLANK / 2
- pop de
- ld a, e
- ld [hli], a
- ld a, d
- ld [hli], a
- ENDR
- ; Restore SP
- ld sp, wSPBuffer
- pop hl
- ld sp, hl
- ld a, BYTES_PER_VBLANK - BYTES_PER_HBLANK
- ldh [hHBlankTransferLow], a
- ldh [hDoUpdate], a ; Recycle value to signify update done
- .noUpdate
- ; Allow the STAT interrupt to trigger and perform upscaling normally
- ei
- ; Restore regs and exit
- pop de
- pop hl
- pop af
- ret
Advertisement
Add Comment
Please, Sign In to add comment