Merge pull request #2808 from DavidHaywood/131117

pgm2 - add yshrink for sprites
This commit is contained in:
MetalliC 2017-11-16 16:49:32 +02:00 committed by GitHub
commit 4409ea615b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -264,6 +264,9 @@ private:
bitmap_ind16 m_sprite_bitmap;
void skip_sprite_chunk(int &palette_offset, uint32_t maskdata, int flipy);
void draw_sprite_chunk(const rectangle &cliprect, int &palette_offset, int x, int realy, int flipx, int flipy, int sizex, int xdraw, int pal, uint32_t maskdata);
void draw_sprite_line(const rectangle &cliprect, int &mask_offset, int &palette_offset, int x, int realy, int flipx, int flipy, int sizex, int pal, int zoomybit);
void draw_sprites(screen_device &screen, const rectangle &cliprect, uint32_t* spriteram);
void copy_sprites_from_bitmap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int pri);
@ -336,8 +339,13 @@ static ADDRESS_MAP_START( pgm2_map, AS_PROGRAM, 32, pgm2_state )
AM_RANGE(0x300a0000, 0x300a07ff) AM_RAM_DEVWRITE("tx_palette", palette_device, write) AM_SHARE("tx_palette")
AM_RANGE(0x300c0000, 0x300c01ff) AM_RAM AM_SHARE("sp_zoom") // sprite zoom table?
AM_RANGE(0x300e0000, 0x300e03bf) AM_RAM AM_SHARE("lineram") // linescroll - 0x3bf is enough bytes for 240 lines if each rowscroll value was 8 bytes, but each row is 4, so only half of this is used? or tx can do it too (unlikely, as orl2 writes 256 lines of data) maybe just bad mem check bounds on orleg2, it reports pass even if it fails the first byte!
AM_RANGE(0x300c0000, 0x300c01ff) AM_RAM AM_SHARE("sp_zoom") // sprite zoom table - it uploads the same data 4x, maybe xshrink,xgrow,yshrink,ygrow or just redundant mirrors
/* linescroll ram - it clears to 0x3bf on startup which is enough bytes for 240 lines if each rowscroll value was 8 bytes, but each row is 4,
so only half of this is used? or tx can do it too (unlikely, as orl2 writes 256 lines of data) maybe just bad mem check bounds on orleg2.
It reports pass even if it fails the first byte but if the first byte passes it attempts to test 0x10000 bytes, which is far too big so
what is the real size? */
AM_RANGE(0x300e0000, 0x300e03ff) AM_RAM AM_SHARE("lineram") AM_MIRROR(0x000fc00)
AM_RANGE(0x30100000, 0x301000ff) AM_RAM // unknown
@ -457,83 +465,9 @@ static INPUT_PORTS_START( pgm2 )
INPUT_PORTS_END
void pgm2_state::draw_sprites(screen_device &screen, const rectangle &cliprect, uint32_t* spriteram)
inline void pgm2_state::draw_sprite_chunk(const rectangle &cliprect, int &palette_offset, int x, int realy, int flipx, int flipy, int sizex, int xdraw, int pal, uint32_t maskdata)
{
m_sprite_bitmap.fill(0x8000, cliprect);
int endoflist = -1;
// printf("frame\n");
for (int i = 0;i < 0x2000 / 4;i++)
{
if (spriteram[i] == 0x80000000)
{
endoflist = i;
break;
}
}
if (endoflist != -1)
{
uint16_t* dstptr_bitmap;
for (int i = 0; i < endoflist-2; i += 4)
{
//printf("sprite with %08x %08x %08x %08x\n", spriteram[i + 0], spriteram[i + 1], spriteram[i + 2], spriteram[i + 3]);
int x = (spriteram[i + 0] & 0x000007ff) >> 0;
int y = (spriteram[i + 0] & 0x003ff800) >> 11;
int pal = (spriteram[i + 0] & 0x0fc00000) >> 22;
int pri = (spriteram[i + 0] & 0x80000000) >> 31;
int sizex = (spriteram[i + 1] & 0x0000003f) >> 0;
int sizey = (spriteram[i + 1] & 0x00007fc0) >> 6;
int flipx = (spriteram[i + 1] & 0x00800000) >> 23;
int flipy = (spriteram[i + 1] & 0x80000000) >> 31; // more of a 'reverse entire drawing' flag than y-flip, but used for that purpose
//int zoomx = (spriteram[i + 1] & 0x001f0000) >> 16;
//int zoomy = (spriteram[i + 1] & 0x1f000000) >> 24;
int mask_offset = (spriteram[i + 2]<<1);
int palette_offset = (spriteram[i + 3]);
if (x & 0x400) x -=0x800;
if (y & 0x400) y -=0x800;
if (flipy)
mask_offset -= 2;
mask_offset &= 0x3ffffff;
palette_offset &= 0x7ffffff;
pal |= (pri << 6); // encode priority with the palette for manual mixing later
for (int ydraw = 0; ydraw < sizey;ydraw++)
{
int realy = ydraw + y;
for (int xdraw = 0; xdraw < sizex;xdraw++)
{
uint32_t maskdata = m_sprites_mask[mask_offset+0] << 24;
maskdata |= m_sprites_mask[mask_offset+1] << 16;
maskdata |= m_sprites_mask[mask_offset+2] << 8;
maskdata |= m_sprites_mask[mask_offset+3] << 0;
if (flipy)
{
mask_offset -= 4;
}
else if (!flipy)
{
mask_offset += 4;
}
mask_offset &= 0x3ffffff;
for (int xchunk = 0;xchunk < 32;xchunk++)
for (int xchunk = 0; xchunk < 32; xchunk++)
{
int realx, pix;
@ -565,7 +499,7 @@ void pgm2_state::draw_sprites(screen_device &screen, const rectangle &cliprect,
uint16_t pendat = pix + (pal * 0x40);
dstptr_bitmap = &m_sprite_bitmap.pix16(realy);
uint16_t* dstptr_bitmap = &m_sprite_bitmap.pix16(realy);
dstptr_bitmap[realx] = pendat;
}
@ -582,6 +516,143 @@ void pgm2_state::draw_sprites(screen_device &screen, const rectangle &cliprect,
palette_offset &= 0x7ffffff;
}
}
}
inline void pgm2_state::skip_sprite_chunk(int &palette_offset, uint32_t maskdata, int flipy)
{
int bits = population_count_32(maskdata);
if (!flipy)
{
palette_offset+=bits;
}
else
{
palette_offset-=bits;
}
palette_offset &= 0x7ffffff;
}
inline void pgm2_state::draw_sprite_line(const rectangle &cliprect, int &mask_offset, int &palette_offset, int x, int realy, int flipx, int flipy, int sizex, int pal, int zoomybit)
{
for (int xdraw = 0; xdraw < sizex; xdraw++)
{
uint32_t maskdata = m_sprites_mask[mask_offset + 0] << 24;
maskdata |= m_sprites_mask[mask_offset + 1] << 16;
maskdata |= m_sprites_mask[mask_offset + 2] << 8;
maskdata |= m_sprites_mask[mask_offset + 3] << 0;
if (flipy)
{
mask_offset -= 4;
}
else if (!flipy)
{
mask_offset += 4;
}
mask_offset &= 0x3ffffff;
if (zoomybit) draw_sprite_chunk(cliprect, palette_offset, x, realy, flipx, flipy, sizex, xdraw, pal, maskdata);
else skip_sprite_chunk(palette_offset, maskdata, flipy);
}
}
void pgm2_state::draw_sprites(screen_device &screen, const rectangle &cliprect, uint32_t* spriteram)
{
m_sprite_bitmap.fill(0x8000, cliprect);
int endoflist = -1;
//printf("frame\n");
for (int i = 0;i < 0x2000 / 4;i++)
{
if (spriteram[i] == 0x80000000)
{
endoflist = i;
break;
}
}
if (endoflist != -1)
{
for (int i = 0; i < endoflist-2; i += 4)
{
//printf("sprite with %08x %08x %08x %08x\n", spriteram[i + 0], spriteram[i + 1], spriteram[i + 2], spriteram[i + 3]);
int x = (spriteram[i + 0] & 0x000007ff) >> 0;
int y = (spriteram[i + 0] & 0x003ff800) >> 11;
int pal = (spriteram[i + 0] & 0x0fc00000) >> 22;
int pri = (spriteram[i + 0] & 0x80000000) >> 31;
//int unk0 = (spriteram[i + 0] & 0x70000000) >> 0;
int sizex = (spriteram[i + 1] & 0x0000003f) >> 0;
int sizey = (spriteram[i + 1] & 0x00007fc0) >> 6;
int flipx = (spriteram[i + 1] & 0x00800000) >> 23;
int flipy = (spriteram[i + 1] & 0x80000000) >> 31; // more of a 'reverse entire drawing' flag than y-flip, but used for that purpose
//int zoomx = (spriteram[i + 1] & 0x001f0000) >> 16;
//int growx = (spriteram[i + 1] & 0x00200000) >> 21;
int zoomy = (spriteram[i + 1] & 0x1f000000) >> 24;
int growy = (spriteram[i + 1] & 0x20000000) >> 29;
//int unk1 = (spriteram[i + 1] & 0x40408000) >> 0;
//if (unk0 || unk1)
// printf("unused bits set unk0 %08x unk1 %08x\n", unk0, unk1);
int mask_offset = (spriteram[i + 2]<<1);
int palette_offset = (spriteram[i + 3]);
uint32_t zoomy_bits = m_sp_zoom[zoomy];
if (x & 0x400) x -=0x800;
if (y & 0x400) y -=0x800;
if (flipy)
mask_offset -= 2;
mask_offset &= 0x3ffffff;
palette_offset &= 0x7ffffff;
pal |= (pri << 6); // encode priority with the palette for manual mixing later
int realy = y;
int sourceline = 0;
for (int ydraw = 0; ydraw < sizey;sourceline++)
{
int zoomy_bit = (zoomy_bits >> (sourceline & 0x1f)) & 1;
// store these for when we need to draw a line twice
uint32_t pre_palette_offset = palette_offset;
uint32_t pre_mask_offset = mask_offset;
if (!growy) // skipping lines
{
draw_sprite_line(cliprect, mask_offset, palette_offset, x, realy, flipx, flipy, sizex, pal, zoomy_bit);
if (zoomy_bit) realy++;
ydraw++;
}
else // doubling lines
{
draw_sprite_line(cliprect, mask_offset, palette_offset, x, realy, flipx, flipy, sizex, pal, 1);
realy++;
if (zoomy_bit)
{
palette_offset = pre_palette_offset;
mask_offset = pre_mask_offset;
}
else ydraw++;
}
}
}