Hello guys.
I’ve been tinkering with the VDP to simulate a linear frame buffer, and here are the thoughts I'd like to share with you.
A full 320×224 would be too costly to push every frame, but 128×112 is small enough (128 x 112 x 4bpp =57 344 b, 57344 / 8 =7 168 B) to be copied from RAM to VRAM during VBlank.
The VDP wants to fetch by tiles, but we want linear pixel addresses. To fake this, I alternate Plane A and Plane B every 8 pixels:
Plane A holds the tiles in even columns,
Plane B holds them in odd columns,
The other plane is filled with tile #0 (transparent).
Each plane has a vertical scroll offset per column, so:
Plane A columns are shifted by 0,2,4… lines,
Plane B columns are shifted by 1,3,5… lines.
Example
line 0:
Pixels 0–7: Plane A, tile #400, row 0 → addresses 12800–12803
Pixels 8–15: Plane B, tile #400, row 1 → addresses 12804–12807
Pixels 16–23: Plane A, tile #400, row 2 → addresses 12808–12811
…
Pixels 56-63 : Plane B, tile #400, row 7 → addresses 12828 - 12831
Pixels 64-71 : Plane A, tile #401, row 0 → addresses 12832 - 12835
…
Pixels 124-127 : Plane B, tile #401, row 7 → addresses 12860 - 12863
line 1:
Pixels 0-7 : Plane A, tile #402, row 0 → adresses 12864 - 12867
Pixels 8-5 : Plane B, tile #402, row 1 → adresses 12868 - 12871
…
For line 0 I use tiles 400 and 401,
for line 1 I use 402 and 403,
…
for line 111, I use tiles 622 and 623
Here are the tilemaps:
tilemapA : 400, 0, 400, 0, 400, 0, 400, 0, 401, 0, 401, 0, 401, 0, 401, 0, 402, 0, 402, …
tilemapB : 0, 400, 0, 400, 0, 400, 0, 400, 0, 401, 0, 401, 0, 401, 0, 401, 0, 402, 0, …
Here is the VScroll table (A, B interleaved). Here, we use the 2-cell mode, whose deltas I hope are kept during full screen VScoll:
0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7
NB: the tiles 0 don't need to be scrolled, so we could have:
0,x,x,1,2,x,x,3,4,x,x,5,6,x,x,7,0,x,x,1,2,x,x,3,4,x,x,5,6,x,x,7
The secret sauce is here.
Let's say we want to align this frame buffer vertically (56 empty lines, 112 lines of frame buffer, 56 empty lines).
During the leading V_Blank of the image we are about to display, we copy the frame buffer from the RAM to the VRAM. We set the VScoll to scroll the whole screen. We also ask for the next H_INT to be thrown on (the end of) line 54.
From lines 0 to 54, we display nothing (blank or an empty part of the tilemap).
Starting at line 55 (or, quitting the line 54), we set the VScroll accordingly (eg, 0, 0) and/or we enable the display. We also ask the H_INT to be thrown on each and every line. We display the first line of the tilemap. In our example, we use the whole tiles 400 and 401 to display the first line of the frame buffer. And then, for the whole screen (and the next line), we scroll vertically 8 pixels.
Then, starting for the line 56, we display the next line of the tilemap, that is the whole tiles 402 and 403. And then, for the whole screen, we scroll vertically 8 more pixels.
… and so on.
Starting for the line 111, we display the last line of the tilemap (tiles 622 and 623). And then, for the whole screen, we scroll vertically 8 more pixels. If we don't do that, from lines 112 to 119, the bottom of the tiles 622 and 623 will be displayed and that will be a mess. We can also stop bothering waiting for the next H_INT and quietly wait for the next V_INT.
So, programmatically?
V_INT:
DMA 7168B from RAM to VRAM
next H_INT = 54
set full screen VScroll
vScrollA = -8, vScrollB = -8 ; a row that don't have any tiles. Or disable the display
rte
H_INT:
vScrollA += 8, vScrollB += 8
next H_INT = 1
if (lineNumber >= 111) {
vScrollA = -8, vScrollB = -8 ; a row that don't have any tiles. Or disable the display
next H_INT = 255 ; Won't get called again
}
rte
AND, I think the scroll area should be 32 x 128, to allow such big vScroll offsets.
I don't have the time to code it right now, but I think it should work.
NB1 : shiru once stated this very idea : viewtopic.php?p=1848#p1848
NB2 : At 128 x 112, this is a small frame buffer. But even with this small frame buffer, there are less than 8 cycles per pixel, at 60fps.
I don't know what you could do with this. But I guess there's a reason why I have done so little in this area, and others have done - much! - more.
Linear Frame Buffer
Moderator: BigEvilCorporation