Skip to content
This repository has been archived by the owner on Mar 24, 2024. It is now read-only.

Commit

Permalink
PCE: Working on fixing sprite priority not always respected
Browse files Browse the repository at this point in the history
  • Loading branch information
ducalex authored and kbeckmann committed Jan 11, 2021
1 parent 8a524e1 commit 6885cad
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 110 deletions.
226 changes: 117 additions & 109 deletions huexpress-go/components/huexpress/engine/gfx.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,93 @@ tile2pixel(int no)
}


/*****************************************************************************
Function: draw_tiles
Description: draw tiles on screen
Parameters: int Y1,int Y2 (lines to draw between)
Return: nothing
*****************************************************************************/
FAST_INLINE void
draw_tiles(int Y1, int Y2, int scroll_x, int scroll_y)
{
const uint8_t _bg_w[] = { 32, 64, 128, 128 };
const uint8_t _bg_h[] = { 32, 64 };

uint8_t bg_w = _bg_w[(IO_VDC_REG[MWR].W >> 4) & 3]; // Bits 5-4 select the width
uint8_t bg_h = _bg_h[(IO_VDC_REG[MWR].W >> 6) & 1]; // Bit 6 selects the height

int XW, no, x, y, h, offset;
uint8_t *PP, *PAL, *P, *C;
uint32_t *C2;

if (Y1 == 0) {
TRACE_GFX("\n=================================================\n");
}

TRACE_GFX("Rendering lines %3d - %3d\tScroll: (%3d,%3d)\n", Y1, Y2, scroll_x, scroll_y);

y = Y1 + scroll_y;
offset = y & 7;
h = 8 - offset;
if (h > Y2 - Y1)
h = Y2 - Y1;
y >>= 3;

PP = (screen_buffer + XBUF_WIDTH * Y1) - (scroll_x & 7);
XW = IO_VDC_SCREEN_WIDTH / 8 + 1;

for (int Line = Y1; Line < Y2; y++) {
x = scroll_x / 8;
y &= bg_h - 1;
for (int X1 = 0; X1 < XW; X1++, x++, PP += 8) {
x &= bg_w - 1;

no = ((uint16_t*)VRAM)[x + y * bg_w];

PAL = &Palette[(no >> 8) & 0x1F0];

// PCE has max of 2048 tiles
no &= 0x7FF;

if (TILE_CACHE[no] == 0) {
tile2pixel(no);
}

C2 = OBJ_CACHE + (no * 8 + offset);
C = VRAM + (no * 32 + offset * 2);
P = PP;
for (int i = 0; i < h; i++, P += XBUF_WIDTH, C2++, C += 2) {
uint32_t J, L;

J = C[0] | C[1] | C[16] | C[17];

if (!J)
continue;

L = C2[0];
if (J & 0x80) P[0] = PAL(1);
if (J & 0x40) P[1] = PAL(3);
if (J & 0x20) P[2] = PAL(5);
if (J & 0x10) P[3] = PAL(7);
if (J & 0x08) P[4] = PAL(0);
if (J & 0x04) P[5] = PAL(2);
if (J & 0x02) P[6] = PAL(4);
if (J & 0x01) P[7] = PAL(6);
}
}
Line += h;
PP += XBUF_WIDTH * h - XW * 8;
offset = 0;
h = Y2 - Line;
if (h > 8)
h = 8;
}
}


/*****************************************************************************
Function: draw_sprite
Expand All @@ -107,11 +194,14 @@ tile2pixel(int no)
*****************************************************************************/
FAST_INLINE void
draw_sprite(int offset, uint16_t *C, uint32_t *C2, uint8_t *PAL, int h, int inc,
uint8_t pr, bool hflip, bool update_mask)
draw_sprite(size_t offset, uint16_t *C, uint32_t *C2, int h, int inc, uint8_t pr, uint16_t attr)
{
uint8_t *P = screen_buffer + offset;
uint8_t *M = SPM + offset;
uint8_t *PAL = &Palette[256 + ((attr & 0xF) << 4)];

bool priority = attr & 0x80;
bool hflip = attr & H_FLIP;

for (int i = 0; i < h; i++, C = (uint16_t*)((uint8_t*)C + inc),
C2 += inc, P += XBUF_WIDTH, M += XBUF_WIDTH) {
Expand Down Expand Up @@ -165,7 +255,7 @@ draw_sprite(int offset, uint16_t *C, uint32_t *C2, uint8_t *PAL, int h, int inc,
if ((J & 0x01) && M[15] <= pr) P[15] = PAL(6);
}

if (update_mask) {
if (priority == 0) {
if (hflip) {
M[15] = (J & 0x8000) ? pr : 0;
M[14] = (J & 0x4000) ? pr : 0;
Expand Down Expand Up @@ -207,93 +297,6 @@ draw_sprite(int offset, uint16_t *C, uint32_t *C2, uint8_t *PAL, int h, int inc,
}


/*****************************************************************************
Function: draw_tiles
Description: draw tiles on screen
Parameters: int Y1,int Y2 (lines to draw between)
Return: nothing
*****************************************************************************/
FAST_INLINE void
draw_tiles(int Y1, int Y2, int scroll_x, int scroll_y)
{
const uint8_t _bg_w[] = { 32, 64, 128, 128 };
const uint8_t _bg_h[] = { 32, 64 };

uint8_t bg_w = _bg_w[(IO_VDC_REG[MWR].W >> 4) & 3]; // Bits 5-4 select the width
uint8_t bg_h = _bg_h[(IO_VDC_REG[MWR].W >> 6) & 1]; // Bit 6 selects the height

int XW, no, x, y, h, offset;
uint8_t *PP, *PAL, *P, *C;
uint32_t *C2;

if (Y1 == 0) {
TRACE_GFX("\n=================================================\n");
}

TRACE_GFX("Rendering lines %3d - %3d\tScroll: (%3d,%3d)\n", Y1, Y2, scroll_x, scroll_y);

y = Y1 + scroll_y;
offset = y & 7;
h = 8 - offset;
if (h > Y2 - Y1)
h = Y2 - Y1;
y >>= 3;

PP = (screen_buffer + XBUF_WIDTH * Y1) - (scroll_x & 7);
XW = IO_VDC_SCREEN_WIDTH / 8 + 1;

for (int Line = Y1; Line < Y2; y++) {
x = scroll_x / 8;
y &= bg_h - 1;
for (int X1 = 0; X1 < XW; X1++, x++, PP += 8) {
x &= bg_w - 1;

no = ((uint16_t*)VRAM)[x + y * bg_w];

PAL = &Palette[(no >> 8) & 0x1F0];

// PCE has max of 2048 tiles
no &= 0x7FF;

if (TILE_CACHE[no] == 0) {
tile2pixel(no);
}

C2 = OBJ_CACHE + (no * 8 + offset);
C = VRAM + (no * 32 + offset * 2);
P = PP;
for (int i = 0; i < h; i++, P += XBUF_WIDTH, C2++, C += 2) {
uint32_t J, L;

J = C[0] | C[1] | C[16] | C[17];

if (!J)
continue;

L = C2[0];
if (J & 0x80) P[0] = PAL(1);
if (J & 0x40) P[1] = PAL(3);
if (J & 0x20) P[2] = PAL(5);
if (J & 0x10) P[3] = PAL(7);
if (J & 0x08) P[4] = PAL(0);
if (J & 0x04) P[5] = PAL(2);
if (J & 0x02) P[6] = PAL(4);
if (J & 0x01) P[7] = PAL(6);
}
}
Line += h;
PP += XBUF_WIDTH * h - XW * 8;
offset = 0;
h = Y2 - Line;
if (h > 8)
h = 8;
}
}


/*****************************************************************************
Function: draw_sprites
Expand All @@ -305,26 +308,26 @@ draw_tiles(int Y1, int Y2, int scroll_x, int scroll_y)
*****************************************************************************/
FAST_INLINE void
draw_sprites(int Y1, int Y2, bool bg)
draw_sprites(int Y1, int Y2, int priority)
{
sprite_t *spr = (sprite_t *)SPRAM + 63;

for (int n = 0; n < 64; n++, spr--) {
int spr_bg = (spr->atr >> 7) & 1;
int spr_pr = (spr->attr >> 7) & 1;

if (spr_bg != bg)
if (spr_pr != priority)
continue;

int y = (spr->y & 1023) - 64;
int x = (spr->x & 1023) - 32;
int cgx = (spr->atr >> 8) & 1;
int cgy = (spr->atr >> 12) & 3;
int no = (spr->no & 2047); // 4095 for supergraphx
int cgx = (spr->attr >> 8) & 1;
int cgy = (spr->attr >> 12) & 3;
int no = (spr->no & 0x7FF);
int pos = XBUF_WIDTH * y + x;
int inc = 2;

TRACE_GFX("Sprite 0x%02X : X = %d, Y = %d, atr = 0x%04X, no = 0x%03X\n",
n, x, y, spr->atr, (unsigned int)no);
n, x, y, spr->attr, no);

cgy |= cgy >> 1;
no = (no >> 1) & ~(cgy * 2 + cgx);
Expand All @@ -344,11 +347,10 @@ draw_sprites(int Y1, int Y2, bool bg)
i++;
}

uint8_t *PAL = &Palette[256 + ((spr->atr & 15) << 4)];
uint8_t *C = VRAM + (no * 128);
uint32_t *C2 = OBJ_CACHE + (no * 32);

if (spr->atr & V_FLIP) {
if (spr->attr & V_FLIP) {
inc = -2;
C += 15 * 2 + cgy * 256;
C2 += (15 * 2 + cgy * 64);
Expand All @@ -357,8 +359,8 @@ draw_sprites(int Y1, int Y2, bool bg)
for (int i = 0, y_sum = 0; i <= cgy; i++, y_sum += 16) {
int h = 16;
int t = Y1 - y - y_sum;
int pri = (sprite_usespbg || !spr_bg) ? n : 0xFF;
int hflip = (spr->atr & H_FLIP) ? 1 : 0;
int pri = (sprite_usespbg || priority == 0) ? n : 0xFF;
int hflip = (spr->attr & H_FLIP) ? 1 : 0;

if (t > 0) {
C += t * inc;
Expand All @@ -375,16 +377,14 @@ draw_sprites(int Y1, int Y2, bool bg)
pos + (hflip ? cgx - j : j) * 16,
(uint16_t*)(C + j * 128),
C2 + j * 32,
PAL,
h,
inc,
pri,
hflip,
!spr_bg
spr->attr
);
}

if (!bg)
if (!priority)
sprite_usespbg = 1;

pos += h * XBUF_WIDTH;
Expand All @@ -404,16 +404,16 @@ sprite_hit_check(void)
sprite_t *spr = (sprite_t *)SPRAM;
int x0 = spr->x;
int y0 = spr->y;
int w0 = (((spr->atr >> 8) & 1) + 1) * 16;
int h0 = (((spr->atr >> 12) & 3) + 1) * 16;
int w0 = (((spr->attr >> 8) & 1) + 1) * 16;
int h0 = (((spr->attr >> 12) & 3) + 1) * 16;

spr++;

for (int i = 1; i < 64; i++, spr++) {
int x = spr->x;
int y = spr->y;
int w = (((spr->atr >> 8) & 1) + 1) * 16;
int h = (((spr->atr >> 12) & 3) + 1) * 16;
int w = (((spr->attr >> 8) & 1) + 1) * 16;
int h = (((spr->attr >> 12) & 3) + 1) * 16;
if ((x < x0 + w0) && (x + w > x0) && (y < y0 + h0) && (y + h > y0))
return 1;
}
Expand Down Expand Up @@ -446,14 +446,22 @@ render_lines(int min_line, int max_line)
return;
}

// This is needed for accurate emulation but it slows things down considerably...
// for (int i = min_line; i <= max_line; i++) {
// memset(SPM + i * XBUF_WIDTH, 0, 320);
// }

// Sprites with priority 0 are drawn behind the tiles
if (gfx_context.control & 0x40) {
draw_sprites(min_line, max_line, 0);
}

// Draw the background tiles
if (gfx_context.control & 0x80) {
draw_tiles(min_line, max_line, gfx_context.scroll_x, gfx_context.scroll_y);
}

// Draw regular sprites
if (gfx_context.control & 0x40) {
draw_sprites(min_line, max_line, 1);
}
Expand Down
2 changes: 1 addition & 1 deletion huexpress-go/components/huexpress/engine/gfx.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ typedef struct {
short no;

/* Attributes */
short atr;
short attr;
/*
* bit 0-4 : number of the palette to be used
* bit 7 : background sprite
Expand Down

0 comments on commit 6885cad

Please sign in to comment.