mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
sms, improve vdp (sprite collision, hcounter latch)
This commit is contained in:
parent
646be42e9d
commit
cc1547e8cd
2 changed files with 49 additions and 16 deletions
47
pico/mode4.c
47
pico/mode4.c
|
@ -20,6 +20,30 @@ static int skip_next_line;
|
||||||
static int screen_offset, line_offset;
|
static int screen_offset, line_offset;
|
||||||
|
|
||||||
|
|
||||||
|
/* sprite collision detection */
|
||||||
|
static int CollisionDetect(u8 *mb, u16 sx, unsigned int pack, int zoomed)
|
||||||
|
{
|
||||||
|
static u8 morton[16] = { 0x00,0x03,0x0c,0x0f,0x30,0x33,0x3c,0x3f,
|
||||||
|
0xc0,0xc3,0xcc,0xcf,0xf0,0xf3,0xfc,0xff };
|
||||||
|
u8 *mp = mb + (sx>>3);
|
||||||
|
unsigned col, m;
|
||||||
|
// create a pixel bitmap of the sprite pixels from the 4 bitplanes in pack
|
||||||
|
pack = ((pack | (pack>>16)) | ((pack | (pack>>16))>>8)) & 0xff;
|
||||||
|
if (zoomed) pack = morton[pack&0x0f] | (morton[(pack>>4)&0x0f] << 8);
|
||||||
|
// get the corresponding data from the sprite map
|
||||||
|
m = mp[0] | (mp[1]<<8);
|
||||||
|
if (zoomed) m |= (mp[2]<<16);
|
||||||
|
// collision if bits in pixel bitmap overlap bits in sprite map
|
||||||
|
col = m & (pack<<(sx&7));
|
||||||
|
// update sprite map data with our pixel bitmap
|
||||||
|
m |= pack<<(sx&7);
|
||||||
|
mp[0] = m, mp[1] = m>>8;
|
||||||
|
if (zoomed) mp[2] = m>>16;
|
||||||
|
// invisible overscan area, not tested for collision
|
||||||
|
mb[0] = mb[33] = 0;
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mode 4 */
|
/* Mode 4 */
|
||||||
/*========*/
|
/*========*/
|
||||||
|
|
||||||
|
@ -115,6 +139,7 @@ static void TileDoubleSprM4(int sx, unsigned int pack, int pal)
|
||||||
static void DrawSpritesM4(int scanline)
|
static void DrawSpritesM4(int scanline)
|
||||||
{
|
{
|
||||||
struct PicoVideo *pv = &Pico.video;
|
struct PicoVideo *pv = &Pico.video;
|
||||||
|
unsigned char mb[256/8+2] = {0};
|
||||||
unsigned int sprites_addr[8];
|
unsigned int sprites_addr[8];
|
||||||
unsigned int sprites_x[8];
|
unsigned int sprites_x[8];
|
||||||
unsigned int pack;
|
unsigned int pack;
|
||||||
|
@ -122,7 +147,7 @@ static void DrawSpritesM4(int scanline)
|
||||||
int xoff = 8; // relative to HighCol, which is (screen - 8)
|
int xoff = 8; // relative to HighCol, which is (screen - 8)
|
||||||
int sprite_base, addr_mask;
|
int sprite_base, addr_mask;
|
||||||
int zoomed = pv->reg[1] & 0x1; // zoomed sprites, e.g. Earthworm Jim
|
int zoomed = pv->reg[1] & 0x1; // zoomed sprites, e.g. Earthworm Jim
|
||||||
int i, s, h;
|
int i, s, h, m;
|
||||||
|
|
||||||
if (pv->reg[0] & 8)
|
if (pv->reg[0] & 8)
|
||||||
xoff = 0;
|
xoff = 0;
|
||||||
|
@ -160,16 +185,16 @@ static void DrawSpritesM4(int scanline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// really half-assed but better than nothing
|
|
||||||
if (s > 1)
|
|
||||||
pv->status |= SR_C;
|
|
||||||
|
|
||||||
// now draw all sprites backwards
|
// now draw all sprites backwards
|
||||||
|
m = 0;
|
||||||
for (--s; s >= 0; s--) {
|
for (--s; s >= 0; s--) {
|
||||||
pack = CPU_LE2(*(u32 *)(PicoMem.vram + sprites_addr[s]));
|
pack = CPU_LE2(*(u32 *)(PicoMem.vram + sprites_addr[s]));
|
||||||
if (zoomed) TileDoubleSprM4(sprites_x[s], pack, 0x10);
|
if (zoomed) TileDoubleSprM4(sprites_x[s], pack, 0x10);
|
||||||
else TileNormSprM4(sprites_x[s], pack, 0x10);
|
else TileNormSprM4(sprites_x[s], pack, 0x10);
|
||||||
|
if (!m) m = CollisionDetect(mb, sprites_x[s], pack, zoomed);
|
||||||
}
|
}
|
||||||
|
if (m)
|
||||||
|
pv->status |= SR_C;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cells_dx, tilex_ty merged to reduce register pressure
|
// cells_dx, tilex_ty merged to reduce register pressure
|
||||||
|
@ -345,6 +370,7 @@ static void TileDoubleSprM2(u16 sx, unsigned int pack, int pal)
|
||||||
static void DrawSpritesM2(int scanline)
|
static void DrawSpritesM2(int scanline)
|
||||||
{
|
{
|
||||||
struct PicoVideo *pv = &Pico.video;
|
struct PicoVideo *pv = &Pico.video;
|
||||||
|
unsigned char mb[256/8+2] = {0};
|
||||||
unsigned int sprites_addr[4];
|
unsigned int sprites_addr[4];
|
||||||
unsigned int sprites_x[4];
|
unsigned int sprites_x[4];
|
||||||
unsigned int pack;
|
unsigned int pack;
|
||||||
|
@ -352,7 +378,7 @@ static void DrawSpritesM2(int scanline)
|
||||||
int xoff = 8; // relative to HighCol, which is (screen - 8)
|
int xoff = 8; // relative to HighCol, which is (screen - 8)
|
||||||
int sprite_base, addr_mask;
|
int sprite_base, addr_mask;
|
||||||
int zoomed = pv->reg[1] & 0x1; // zoomed sprites
|
int zoomed = pv->reg[1] & 0x1; // zoomed sprites
|
||||||
int i, s, h;
|
int i, s, h, m;
|
||||||
|
|
||||||
xoff += line_offset;
|
xoff += line_offset;
|
||||||
|
|
||||||
|
@ -388,11 +414,8 @@ static void DrawSpritesM2(int scanline)
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// really half-assed but better than nothing
|
|
||||||
if (s > 1)
|
|
||||||
pv->status |= SR_C;
|
|
||||||
|
|
||||||
// now draw all sprites backwards
|
// now draw all sprites backwards
|
||||||
|
m = 0;
|
||||||
for (--s; s >= 0; s--) {
|
for (--s; s >= 0; s--) {
|
||||||
int x, c, w = (zoomed ? 16: 8);
|
int x, c, w = (zoomed ? 16: 8);
|
||||||
i = sprites_x[s];
|
i = sprites_x[s];
|
||||||
|
@ -404,13 +427,17 @@ static void DrawSpritesM2(int scanline)
|
||||||
pack = PicoMem.vramb[MEM_LE2(sprites_addr[s])];
|
pack = PicoMem.vramb[MEM_LE2(sprites_addr[s])];
|
||||||
if (zoomed) TileDoubleSprM2(x, pack, c);
|
if (zoomed) TileDoubleSprM2(x, pack, c);
|
||||||
else TileNormSprM2(x, pack, c);
|
else TileNormSprM2(x, pack, c);
|
||||||
|
if (!m) m = CollisionDetect(mb, x, pack, zoomed);
|
||||||
}
|
}
|
||||||
if((pv->reg[1] & 0x2) && (x+=w) > 0) {
|
if((pv->reg[1] & 0x2) && (x+=w) > 0) {
|
||||||
pack = PicoMem.vramb[MEM_LE2(sprites_addr[s]+0x10)];
|
pack = PicoMem.vramb[MEM_LE2(sprites_addr[s]+0x10)];
|
||||||
if (zoomed) TileDoubleSprM2(x, pack, c);
|
if (zoomed) TileDoubleSprM2(x, pack, c);
|
||||||
else TileNormSprM2(x, pack, c);
|
else TileNormSprM2(x, pack, c);
|
||||||
|
if (!m) m = CollisionDetect(mb, x, pack, zoomed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (m)
|
||||||
|
pv->status |= SR_C;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw the background into a scanline; cells, dx, tilex, ty merged to reduce registers */
|
/* Draw the background into a scanline; cells, dx, tilex, ty merged to reduce registers */
|
||||||
|
|
18
pico/sms.c
18
pico/sms.c
|
@ -22,6 +22,7 @@ extern void YM2413_dataWrite(unsigned data);
|
||||||
|
|
||||||
static unsigned short ymflag = 0xffff;
|
static unsigned short ymflag = 0xffff;
|
||||||
static u8 vdp_buffer;
|
static u8 vdp_buffer;
|
||||||
|
static u8 vdp_hlatch;
|
||||||
|
|
||||||
static unsigned char vdp_data_read(void)
|
static unsigned char vdp_data_read(void)
|
||||||
{
|
{
|
||||||
|
@ -156,12 +157,8 @@ static unsigned char z80_sms_in(unsigned short a)
|
||||||
elprintf(EL_HVCNT, "V counter read: %02x", d);
|
elprintf(EL_HVCNT, "V counter read: %02x", d);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x41: /* H counter, TODO: latched by toggle of pad TH line */
|
case 0x41: /* H counter */
|
||||||
// 171 slots per scanline of 228 clocks, runs from 0x85-0x93,0xe9-0x84
|
d = vdp_hlatch;
|
||||||
#define CYC2SLOT (256 * 171/228) // cycles to slot factor in Q8
|
|
||||||
d = 228-z80_cyclesLeft;
|
|
||||||
if (d <= 19) d = (( d * CYC2SLOT)>>8) + 0x85;
|
|
||||||
else d = (((d-20) * CYC2SLOT)>>8) + 0xe9;
|
|
||||||
elprintf(EL_HVCNT, "H counter read: %02x", d);
|
elprintf(EL_HVCNT, "H counter read: %02x", d);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -218,6 +215,15 @@ static void z80_sms_out(unsigned short a, unsigned char d)
|
||||||
switch (a)
|
switch (a)
|
||||||
{
|
{
|
||||||
case 0x01:
|
case 0x01:
|
||||||
|
// latch hcounter if one of the TH lines is switched to 1
|
||||||
|
if ((Pico.ms.io_ctl ^ d) & d & 0xa0) {
|
||||||
|
unsigned c = 228-z80_cyclesLeft;
|
||||||
|
// 171 slots per scanline of 228 clocks, runs from 0xf4-0x93,0xe9-0xf3
|
||||||
|
// this matches h counter tables in SMSVDPTest
|
||||||
|
c = (((c+2) * ((171<<8)/228))>>8)-1 + 0xf4; // Q8 to avoid dividing
|
||||||
|
if (c > 0x193) c += 0xe9-0x93-1;
|
||||||
|
vdp_hlatch = (u8)c;
|
||||||
|
}
|
||||||
Pico.ms.io_ctl = d;
|
Pico.ms.io_ctl = d;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue