SHARE
TWEET

(Tentative) Optimized DMG VRAM copy

ISSOtm Jul 19th, 2018 (edited) 96 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; Remember to pass the -d flag to RGBLINK!
  2. ; This enables DMG mode, removes VRAM and WRAM banks.
  3. ; It's more convenient.
  4.  
  5. SECTION "Frame buffer tiles", VRAM[$8000]
  6. vFrameBufferTiles::
  7.     ds 1180 tiles ; 180 tiles
  8. ; Note: the copy will overshoot slightly, but that shouldn't be a problem
  9.  
  10. ; Remember to fill tile $FF with either black or white, and letterbox using that
  11. ; You don't *have* to use tile $FF, but it's a good pick, I guess?
  12.  
  13.  
  14. (...)
  15.  
  16.  
  17. SECTION "Frame buffer tiles", WRAM0,ALIGN[8]
  18.  
  19. wFrameBufferTiles::
  20.     ds 180 * 16 ; 180 tiles
  21. wFrameBufferTilesEnd::
  22. ; The copy will also overshoot here, but overreading shouldn't be a big deal :P
  23.  
  24. (...)
  25.  
  26. SECTION "SP buffer", WRAM0
  27.  
  28. wSPBuffer::
  29.     ds 2
  30.  
  31.  
  32. (...)
  33.  
  34.  
  35. SECTION "Transfer vars", HRAM
  36.  
  37. ; Set to 0 to transfer frame buffer
  38. hDoUpdate::
  39.     ds 1
  40. ; Position of VRAM transfer
  41. hHBlankTransferLow::
  42.     ds 1
  43.  
  44.  
  45. (...)
  46.  
  47.  
  48. SECTION "Init", ROM0
  49.     (...)
  50.  
  51.     ld a, %11110000
  52.     ldh [rBGP], a
  53.     xor a
  54.     ldh [rSCX], a ; This is important!
  55.     ld a, STATF_LYC | STATF_MODE00
  56.     ldh [rSTAT], a
  57.  
  58.     (...)
  59.  
  60.     ; Make sure you clear OAM before turning the screen on!
  61.     xor a
  62.     ld hl, $FEA0
  63. .clearOAM
  64.     ld [hl], a
  65.     dec l
  66.     jr nz, .clearOAM
  67.     ld [hl], a
  68.  
  69.     (...)
  70.  
  71.     ; When turning the screen on
  72.     ld a, LCDCF_ON | LCDCF_BG8000 | LCDCF_BGON ; Do NOT use the window or sprites
  73.     ldh [rLCDC], a
  74.  
  75.     (...)
  76.  
  77.  
  78. (...)
  79.  
  80.  
  81. ; VBlank is 1140 cycles
  82. ; 6 for dispatch (including the interrupted instruction finishing)
  83. ; 32 overhead
  84. ; = 1102 left
  85. ; 9 per 2 bytes transferred, therefore...
  86. BYTES_PER_VBLANK equ 244 ; Make sure this is even!!
  87.  
  88. ; HBlank is 71 cycles
  89. ; 6 for dispatch (same)
  90. ; 48 overhead (up to `inc [hl]`)
  91. ; -1 due to letterboxing leniency
  92. ; = 18 left
  93. ; 5 bytes per byte transferred, -1 for last one
  94. ; Therefore...
  95. BYTES_PER_HBLANK equ 3
  96.  
  97. SECTION "Interrupt handlers", ROM0[$0032]
  98.  
  99. LYCHandler:
  100.     ; Toggle the palette to switch between bitplanes
  101.     ldh a, [rBGP]
  102.     xor %00111100
  103.     ldh [rBGP], a
  104.     ; Move LYC to lower part of the screen to toggle palette back (during letterboxing)
  105.     ; This also makes the next handler behave as a Mode 0 int, since LY != LYC
  106.     ; Otherwise things would... break...
  107.     ldh a, [rLYC]
  108.     xor 72 ^ (72 + 32)
  109.     ldh [rLYC], a
  110.     jp PerformUpscaling
  111.  
  112. VBlankHandler: ; @0040
  113.     push af
  114.     push hl
  115.     ld hl, vFrameBufferTiles
  116.     jp TransferTiles
  117.  
  118. STATHandler: ; @0048
  119.     push af
  120.     push hl
  121.     ldh a, [rSTAT]
  122.     bit 2, a
  123.     jr nz, LYCHandler
  124.  
  125.     ; HBlank handler: transfer bytes!
  126.     push de
  127.  
  128.     ; Move to next transfer unit
  129.     ; Assumes the initial value has been offset so the first transfer starts where correct
  130.     ldh a, [hHBlankTransferLow]
  131.     ; Check if transfer has completed
  132.     cp LOW(wFrameBufferTilesEnd)
  133.     jr nc, PerformUpscaling
  134.     ; Move to next unit
  135.     add a, BYTES_PER_HBLANK
  136.     ldh [hHBlankTransferLow], a
  137.     ; Set up regs
  138.     ld l, a
  139.     ld h, HIGH(wFrameBufferTiles)
  140.     ld e, a
  141.     ld d, HIGH(vFrameBufferTiles)
  142.  
  143. REPT BYTES_PER_HBLANK - 1
  144.     ld a, [hli]
  145.     ld [de], a
  146.     inc e
  147. ENDR
  148.     ld a, [hli]
  149.     ld [de], a
  150.  
  151.     pop de
  152.  
  153. PerformUpscaling:
  154.     ; Perform hardware upscaling:
  155.     ; Increment SCY every other scanline to render it twice
  156.     ldh a, [rLY]
  157.     rra ; Shift parity bit into carry
  158.     jr c, .dontShift
  159.     ld hl, rSCY
  160.     dec [hl]
  161. .dontShift
  162.  
  163.     ; Restore regs and exit
  164.     pop hl
  165.     pop af
  166.     reti
  167.  
  168. TransferTiles:
  169.     push de
  170.     ; Check if updating needs to be done
  171.     ldh a, [hDoUpdate]
  172.     and a
  173.     jp nz, .noUpdate
  174.     ; Save SP 'cause we gonna trash it
  175.     ld [wSPBuffer], sp
  176.  
  177. REPT BYTES_PER_VBLANK / 2
  178.     pop de
  179.     ld a, e
  180.     ld [hli], a
  181.     ld a, d
  182.     ld [hli], a
  183. ENDR
  184.  
  185.     ; Restore SP
  186.     ld sp, wSPBuffer
  187.     pop hl
  188.     ld sp, hl
  189.     ld a, BYTES_PER_VBLANK - BYTES_PER_HBLANK
  190.     ldh [hHBlankTransferLow], a
  191.     ldh [hDoUpdate], a ; Recycle value to signify update done
  192.  
  193. .noUpdate
  194.     ; Allow the STAT interrupt to trigger and perform upscaling normally
  195.     ei
  196.  
  197.     ; Restore regs and exit
  198.     pop de
  199.     pop hl
  200.     pop af
  201.     ret
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top