ISSOtm

(Tentative) Optimized DMG VRAM copy

Jul 19th, 2018
110
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