Nothing
This commit is contained in:
@@ -25,12 +25,29 @@ errorret_t displaySaturnInit(void) {
|
|||||||
VDP2_TVMD_HORZ_NORMAL_A,
|
VDP2_TVMD_HORZ_NORMAL_A,
|
||||||
VDP2_TVMD_VERT_224
|
VDP2_TVMD_VERT_224
|
||||||
);
|
);
|
||||||
vdp2_tvmd_display_set();
|
|
||||||
|
/* Back-screen color shown where no VDP1/VDP2 plane draws a pixel.
|
||||||
|
* MSB=1 so VDP2 treats it as direct RGB in mixed-color mode. */
|
||||||
|
vdp2_scrn_back_color_set(
|
||||||
|
VDP2_VRAM_ADDR(3, 0x01FFFE),
|
||||||
|
RGB1555(1, 0, 3, 15)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Sprite priority 0 → invisible in VDP2. Set slot 0 to priority 6 so
|
||||||
|
* VDP1 pixels are composited above the back-screen. */
|
||||||
|
vdp2_sprite_priority_set(0, 6);
|
||||||
|
|
||||||
/* Disable all NBG/RBG scroll planes; game content drawn entirely via VDP1. */
|
/* Disable all NBG/RBG scroll planes; game content drawn entirely via VDP1. */
|
||||||
vdp2_scrn_display_set(VDP2_SCRN_DISP_NONE);
|
vdp2_scrn_display_set(VDP2_SCRN_DISP_NONE);
|
||||||
|
|
||||||
|
vdp2_tvmd_display_set();
|
||||||
|
|
||||||
errorChain(renderSaturnInit());
|
errorChain(renderSaturnInit());
|
||||||
|
|
||||||
|
/* Commit all VDP2 shadow registers to hardware before the first frame. */
|
||||||
|
vdp2_sync();
|
||||||
|
vdp2_sync_wait();
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +62,12 @@ errorret_t displaySaturnSwap(void) {
|
|||||||
vdp1_sync();
|
vdp1_sync();
|
||||||
vdp2_sync();
|
vdp2_sync();
|
||||||
vdp2_sync_wait();
|
vdp2_sync_wait();
|
||||||
|
/* Wait for VDP1's VBlank-OUT handler to complete. In auto mode VDP1 begins
|
||||||
|
* rendering at VBlank-IN; vdp2_sync_wait() returns shortly after that point,
|
||||||
|
* while VDP1 is still reading from VDP1 VRAM. vdp1_sync_wait() blocks until
|
||||||
|
* VBlank-OUT, by which time VDP1 has finished and swapped framebuffers. This
|
||||||
|
* prevents the next frame's DMA from overwriting VDP1 VRAM mid-render. */
|
||||||
|
vdp1_sync_wait();
|
||||||
DISPLAY.whichBuffer ^= 1;
|
DISPLAY.whichBuffer ^= 1;
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,6 +85,16 @@ _Static_assert(sizeof(saturncmd_t) == sizeof(vdp1_cmdt_t),
|
|||||||
#define SATURNCMD_PMOD_RGB_DIRECT (5u << 3) /* RGB1555 in COLR, no palette */
|
#define SATURNCMD_PMOD_RGB_DIRECT (5u << 3) /* RGB1555 in COLR, no palette */
|
||||||
#define SATURNCMD_PMOD_SPD (0x0040u) /* do not skip index 0 */
|
#define SATURNCMD_PMOD_SPD (0x0040u) /* do not skip index 0 */
|
||||||
#define SATURNCMD_PMOD_ECD (0x0080u) /* end-code disable */
|
#define SATURNCMD_PMOD_ECD (0x0080u) /* end-code disable */
|
||||||
|
/* Bit 15 of PMOD: forces the MSB of every pixel written to the VDP1 framebuffer
|
||||||
|
* to 1. In VDP2 mixed-color mode (SPCLMD=1, set by vdp1_env_default_set), a
|
||||||
|
* framebuffer pixel with MSB=1 is treated as a direct RGB555 color; MSB=0 is a
|
||||||
|
* CRAM palette index. Always set this for direct-color drawing. */
|
||||||
|
#define SATURNCMD_PMOD_MSB (0x8000u)
|
||||||
|
|
||||||
|
/* Last 16-word-aligned CRAM slot (word 2032 of 2048): reserved for the clear
|
||||||
|
* polygon color. Placed well above any texture palette range (max 8 × 256
|
||||||
|
* = 2048 words, but we only have a handful of textures in practice). */
|
||||||
|
#define SATURN_CLEAR_CRAM_ADDR (0x07F0u)
|
||||||
|
|
||||||
/* ---- Texture table ------------------------------------------------------- */
|
/* ---- Texture table ------------------------------------------------------- */
|
||||||
|
|
||||||
@@ -118,15 +128,23 @@ static float saturnViewTgtX = 0.0f, saturnViewTgtY = 0.0f, saturnViewTgtZ = 0.0f
|
|||||||
|
|
||||||
/* ---- Helpers ------------------------------------------------------------- */
|
/* ---- Helpers ------------------------------------------------------------- */
|
||||||
|
|
||||||
/* Convert color_t RGBA → VDP1/VDP2 RGB1555. */
|
/* Convert color_t RGBA → VDP1/VDP2 RGB1555 (no MSB).
|
||||||
|
* Saturn RGB1555: bit[15]=MSB, bits[14:10]=R, bits[9:5]=G, bits[4:0]=B. */
|
||||||
static uint16_t toRGB1555(color_t c) {
|
static uint16_t toRGB1555(color_t c) {
|
||||||
return (uint16_t)(
|
return (uint16_t)(
|
||||||
((uint16_t)(c.b >> 3) << 10) |
|
((uint16_t)(c.r >> 3) << 10) |
|
||||||
((uint16_t)(c.g >> 3) << 5) |
|
((uint16_t)(c.g >> 3) << 5) |
|
||||||
((uint16_t)(c.r >> 3))
|
((uint16_t)(c.b >> 3))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert color_t → RGB1555 with bit[15]=1 (direct-color flag).
|
||||||
|
* For VDP1 polygon CMDCOLR: bit[15]=1 tells VDP1 to use the color as direct
|
||||||
|
* RGB555 rather than a CRAM palette index. */
|
||||||
|
static uint16_t toRGB1555Direct(color_t c) {
|
||||||
|
return 0x8000u | toRGB1555(c);
|
||||||
|
}
|
||||||
|
|
||||||
/* Write palette into VDP2 CRAM at the texture's slot.
|
/* Write palette into VDP2 CRAM at the texture's slot.
|
||||||
* CRAM is mapped at 0x25F00000. Each 256-entry slot = 512 bytes. */
|
* CRAM is mapped at 0x25F00000. Each 256-entry slot = 512 bytes. */
|
||||||
static void uploadPalette(saturntexentry_t *e) {
|
static void uploadPalette(saturntexentry_t *e) {
|
||||||
@@ -368,8 +386,8 @@ errorret_t renderSaturnFlush(ropbuffer_t *buf) {
|
|||||||
sc = &saturnCmdBuf[0];
|
sc = &saturnCmdBuf[0];
|
||||||
memoryZero(sc, sizeof(saturncmd_t));
|
memoryZero(sc, sizeof(saturncmd_t));
|
||||||
sc->ctrl = SATURNCMD_CTRL_SYSCLIP;
|
sc->ctrl = SATURNCMD_CTRL_SYSCLIP;
|
||||||
sc->xb = (int16_t)(DUSK_DISPLAY_WIDTH - 1);
|
sc->xc = (int16_t)(DUSK_DISPLAY_WIDTH - 1);
|
||||||
sc->yb = (int16_t)(DUSK_DISPLAY_HEIGHT - 1);
|
sc->yc = (int16_t)(DUSK_DISPLAY_HEIGHT - 1);
|
||||||
|
|
||||||
/* [1] User clip – mirrors full screen; disabled per-command by default. */
|
/* [1] User clip – mirrors full screen; disabled per-command by default. */
|
||||||
sc = &saturnCmdBuf[1];
|
sc = &saturnCmdBuf[1];
|
||||||
@@ -394,14 +412,20 @@ errorret_t renderSaturnFlush(ropbuffer_t *buf) {
|
|||||||
switch(op) {
|
switch(op) {
|
||||||
case ROP_CLEAR: {
|
case ROP_CLEAR: {
|
||||||
const ropclear_t *c = (const ropclear_t *)hdr;
|
const ropclear_t *c = (const ropclear_t *)hdr;
|
||||||
/* Fill the entire screen with a solid RGB polygon.
|
/* VDP1 polygon CM=0: CMDCOLR is a CRAM word address (16-aligned),
|
||||||
* RGB direct mode (PMOD = SATURNCMD_PMOD_RGB_DIRECT) places the
|
* not a direct color value. Write the desired RGB1555 color into our
|
||||||
* RGB1555 color in COLR directly — no palette lookup required. */
|
* reserved CRAM slot so VDP1 reads it during rasterization.
|
||||||
|
* PMOD MSB_ENABLE then ORs bit[15]=1 into the framebuffer pixel so
|
||||||
|
* VDP2 (SPCLMD=1) treats it as direct RGB555 rather than a palette
|
||||||
|
* index. */
|
||||||
|
volatile uint16_t *cram = (volatile uint16_t *)0x25F00000;
|
||||||
|
cram[SATURN_CLEAR_CRAM_ADDR] = toRGB1555(c->color);
|
||||||
|
|
||||||
saturncmd_t *poly = allocCmd();
|
saturncmd_t *poly = allocCmd();
|
||||||
if(poly) {
|
if(poly) {
|
||||||
poly->ctrl = SATURNCMD_CTRL_POLYGON;
|
poly->ctrl = SATURNCMD_CTRL_POLYGON;
|
||||||
poly->pmod = SATURNCMD_PMOD_RGB_DIRECT;
|
poly->pmod = SATURNCMD_PMOD_MSB | SATURNCMD_PMOD_ECD | SATURNCMD_PMOD_SPD;
|
||||||
poly->colr = toRGB1555(c->color);
|
poly->colr = SATURN_CLEAR_CRAM_ADDR;
|
||||||
poly->xa = 0;
|
poly->xa = 0;
|
||||||
poly->ya = 0;
|
poly->ya = 0;
|
||||||
poly->xb = (int16_t)(DUSK_DISPLAY_WIDTH - 1);
|
poly->xb = (int16_t)(DUSK_DISPLAY_WIDTH - 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user