mirror of
https://github.com/holub/mame
synced 2025-07-04 17:38:08 +03:00
Radica 6502: some hacks to improve the video, (#3074)
* Radica 6502: some hacks to improve the video, lack of test cases / makes these tricky to figure out properly * at least these aren't *my* bugs.. (nw)
This commit is contained in:
parent
0f59e5b720
commit
c97f56c83f
@ -128,6 +128,7 @@
|
||||
|
||||
|
||||
Flaws (NOT emulation bugs, happen on hardware):
|
||||
--
|
||||
|
||||
In QIX the sprites lag behind the line drawing, so you see the line infront of your player until you stop moving
|
||||
|
||||
@ -137,6 +138,19 @@
|
||||
|
||||
Colony 7 has a typo in the instructions
|
||||
|
||||
The fake 'colour band' effect does not apply to the thruster (and several other elements) in Lunar Rescue
|
||||
|
||||
Enemies in Phoenix are rendered above the score panel
|
||||
|
||||
The 200pt right facing bird on the Phoenix score table is corrupt
|
||||
|
||||
Uncertain (to check)
|
||||
|
||||
Space Invaders seems to be using a darker than expected palette, there are lighter colours in the palette but
|
||||
they don't seem to be used. It's difficult to judge from hardware videos, although it definitely isn't as
|
||||
white as the menu, so this might also be a non-bug.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -306,6 +320,8 @@ private:
|
||||
void handle_sound_1_w(int which, int offset, uint8_t data);
|
||||
uint8_t handle_sound_1_r(int which, int offset);
|
||||
|
||||
bool get_tile_data(int base, int drawpri, int& tile, int &attr, int &unk2);
|
||||
void draw_tilemaps(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int drawpri);
|
||||
void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
};
|
||||
|
||||
@ -325,14 +341,15 @@ void radica_6502_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap
|
||||
|
||||
/*
|
||||
Sprites
|
||||
AA yy xx ?? XX YY aa bb
|
||||
AA yy xx cc XX YY aa bb
|
||||
|
||||
yy = y position
|
||||
xx = x position
|
||||
XX = texture x start
|
||||
YY = texture y start
|
||||
aa = same as final param on tiles?
|
||||
aa = same as unk2 on tiles
|
||||
bb = sometimes set in invaders
|
||||
cc = same as attr on tiles (colour / priority?)
|
||||
|
||||
AA = attributes
|
||||
e--- fFsS
|
||||
@ -349,23 +366,60 @@ void radica_6502_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap
|
||||
uint8_t x = m_spriteram[i + 2];
|
||||
uint8_t y = m_spriteram[i + 1];
|
||||
|
||||
/*
|
||||
Space Invaders draws the player base with this specific y value before the start of each life
|
||||
and expects it to NOT wrap around. There are no high priority tiles or anything else to hide
|
||||
and it doesn't appear on real hardware.
|
||||
|
||||
it's possible sprites don't wrap around at all (but then you couldn't have smooth entry at the
|
||||
top of the screen - there are no extra y co-ordinate bits. However there would have been easier
|
||||
ways to hide this tho as there are a bunch of unseen lines at the bottom of the screen anyway!
|
||||
|
||||
needs further investigation.
|
||||
*/
|
||||
if (y==255)
|
||||
continue;
|
||||
|
||||
uint8_t tex_x = m_spriteram[i + 4];
|
||||
uint8_t tex_y = m_spriteram[i + 5];
|
||||
|
||||
uint8_t attrs = m_spriteram[i + 0];
|
||||
uint8_t flags = m_spriteram[i + 0];
|
||||
uint8_t attr = m_spriteram[i + 3];
|
||||
uint8_t unk2 = m_spriteram[i + 6];
|
||||
|
||||
if (!(attrs & 0x80))
|
||||
|
||||
//int priority = attr & 0x0f;
|
||||
int colour = attr & 0xf0;
|
||||
|
||||
// ? game select has this set to 0xff, but clearly doesn't want the palette to change!
|
||||
// while in Space Invaders this has to be palette for the UFO to be red.
|
||||
if (colour & 0x80)
|
||||
colour = 0;
|
||||
|
||||
int transpen = 0;
|
||||
|
||||
/* HACK - how is this calculated
|
||||
phoenix and the game select need it like this
|
||||
it isn't a simple case of unk2 being transpen either because Qix has some elements set to 0x07
|
||||
where the transpen needs to be 0x00 and Space Invaders has it set to 0x04
|
||||
it could be a global register rather than something in the spritelist?
|
||||
*/
|
||||
if ((attr == 0xff) && (unk2 == 0xff))
|
||||
transpen = 0xff;
|
||||
|
||||
|
||||
if (!(flags & 0x80))
|
||||
continue;
|
||||
|
||||
int sizex = 8;
|
||||
int sizey = 8;
|
||||
|
||||
if (attrs & 0x01)
|
||||
if (flags & 0x01)
|
||||
{
|
||||
sizex = 16;
|
||||
}
|
||||
|
||||
if (attrs & 0x02)
|
||||
if (flags & 0x02)
|
||||
{
|
||||
sizey = 16;
|
||||
}
|
||||
@ -376,7 +430,7 @@ void radica_6502_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap
|
||||
{
|
||||
uint16_t* row;
|
||||
|
||||
if (attrs & 0x08) // guess flipy
|
||||
if (flags & 0x08) // guess flipy
|
||||
{
|
||||
row = &bitmap.pix16((y + (sizey - 1 - yy)) & 0xff);
|
||||
}
|
||||
@ -387,20 +441,20 @@ void radica_6502_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap
|
||||
|
||||
for (int xx = 0; xx < sizex; xx++)
|
||||
{
|
||||
int realaddr = base + ((tex_x+xx)&0xff);
|
||||
realaddr += ((tex_y+yy)&0xff) * 256;
|
||||
int realaddr = base + ((tex_x + xx) & 0xff);
|
||||
realaddr += ((tex_y + yy) & 0xff) * 256;
|
||||
|
||||
uint8_t pix = fullbankspace.read_byte(realaddr);
|
||||
|
||||
if (pix)
|
||||
if (pix != transpen)
|
||||
{
|
||||
if (attrs & 0x04) // flipx
|
||||
if (flags & 0x04) // flipx
|
||||
{
|
||||
row[(x + (sizex - 1 - xx)) & 0xff] = pix;// + attr;
|
||||
row[(x + (sizex - 1 - xx)) & 0xff] = (pix + ((colour & 0x70) << 1)) & 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
row[(x + xx) & 0xff] = pix;// + attr;
|
||||
row[(x + xx) & 0xff] = (pix + ((colour & 0x70) << 1)) & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -418,6 +472,160 @@ double hue2rgb(double p, double q, double t)
|
||||
return p;
|
||||
}
|
||||
|
||||
// a hacky mess for now
|
||||
bool radica_6502_state::get_tile_data(int base, int drawpri, int& tile, int &attr, int &unk2)
|
||||
{
|
||||
tile = m_vram[base * 4] + (m_vram[(base * 4) + 1] << 8);
|
||||
|
||||
// these seem to be the basically the same as attr/unk2 in the sprites, which also make
|
||||
// very little sense.
|
||||
attr = m_vram[(base * 4) + 2];
|
||||
unk2 = m_vram[(base * 4) + 3];
|
||||
|
||||
/* hack for phoenix title screens.. the have attr set to 0x3f which change the colour bank in ways we don't want
|
||||
and also by our interpretation of 0x0f bits sets the tiles to priority over sprites (although in this case
|
||||
that might tbe ok, because it looks like the sprites also have that set */
|
||||
if (unk2 == 0x07)
|
||||
attr = 0;
|
||||
|
||||
int priority = attr & 0x0f;
|
||||
|
||||
// likely wrong
|
||||
if ((drawpri == 0 && priority == 0x0f) || (drawpri == 1 && priority != 0x0f))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
void radica_6502_state::draw_tilemaps(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int drawpri)
|
||||
{
|
||||
/* this doesn't handle 8x8 4bpp, haven't seen it used
|
||||
nor is there support for horizontal scrolling etc.
|
||||
for the same reasons
|
||||
*/
|
||||
|
||||
int scroll = (m_bg_scroll[1] << 8) | m_bg_scroll[0];
|
||||
address_space& fullbankspace = m_bank->space(AS_PROGRAM);
|
||||
|
||||
if (m_5027_data & 0x40) // 16x16 tiles
|
||||
{
|
||||
int startrow = (scroll >> 4) & 0x1f;
|
||||
|
||||
for (int y = 0; y < 16; y++)
|
||||
{
|
||||
for (int x = 0; x < 16; x++)
|
||||
{
|
||||
int realstartrow = (startrow + y);
|
||||
|
||||
if (realstartrow >= 28)
|
||||
realstartrow -= 28;
|
||||
|
||||
int base = (((realstartrow + y) & 0x1f) * 8) + x;
|
||||
|
||||
int tile,attr,unk2;
|
||||
|
||||
if (!get_tile_data(base, drawpri, tile,attr,unk2))
|
||||
continue;
|
||||
|
||||
int colour = attr & 0xf0;
|
||||
|
||||
if (m_5027_data & 0x20) // 4bpp mode
|
||||
{
|
||||
tile = (tile & 0xf) + ((tile & ~0xf) * 16);
|
||||
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
tile = (tile & 0xf) + ((tile & ~0xf) * 16);
|
||||
tile <<= 1;
|
||||
|
||||
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
int drawline = (y * 16) + i;
|
||||
drawline -= scroll & 0xf;
|
||||
|
||||
if ((drawline >= 0) && (drawline < 256))
|
||||
{
|
||||
uint16_t* row = &bitmap.pix16(drawline);
|
||||
|
||||
if (m_5027_data & 0x20) // 4bpp
|
||||
{
|
||||
for (int xx = 0; xx < 16; xx += 2)
|
||||
{
|
||||
int realaddr = ((tile + i * 16) << 3) + (xx >> 1);
|
||||
uint8_t pix = fullbankspace.read_byte(realaddr);
|
||||
row[x * 16 + xx + 0] = ((pix & 0xf0) >> 4) + colour;
|
||||
row[x * 16 + xx + 1] = ((pix & 0x0f) >> 0) + colour;
|
||||
}
|
||||
}
|
||||
else // 8bpp
|
||||
{
|
||||
for (int xx = 0; xx < 16; xx++)
|
||||
{
|
||||
int realaddr = ((tile + i * 32) << 3) + xx;
|
||||
uint8_t pix = fullbankspace.read_byte(realaddr);
|
||||
row[x * 16 + xx] = (pix + ((colour & 0x70) << 1)) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // 8x8 tiles
|
||||
{
|
||||
// Phoenix scrolling actually skips a pixel, jumping from 0x001 to 0x1bf, scroll 0x000 isn't used, maybe it has other meanings?
|
||||
|
||||
int startrow = (scroll >> 3) & 0x3f;
|
||||
|
||||
for (int y = 0; y < 32; y++)
|
||||
{
|
||||
for (int x = 0; x < 32; x++)
|
||||
{
|
||||
int realstartrow = (startrow + y);
|
||||
|
||||
if (realstartrow >= 56)
|
||||
realstartrow -= 56;
|
||||
|
||||
int base = (((realstartrow) & 0x3f) * 32) + x;
|
||||
|
||||
int tile,attr,unk2;
|
||||
|
||||
if (!get_tile_data(base, drawpri, tile,attr,unk2))
|
||||
continue;
|
||||
|
||||
int colour = attr & 0xf0;
|
||||
|
||||
tile = (tile & 0x1f) + ((tile & ~0x1f) * 8);
|
||||
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
int drawline = (y * 8) + i;
|
||||
drawline -= scroll & 0x7;
|
||||
|
||||
if ((drawline >= 0) && (drawline < 256))
|
||||
{
|
||||
uint16_t* row = &bitmap.pix16(drawline);
|
||||
|
||||
for (int xx = 0; xx < 8; xx++)
|
||||
{
|
||||
int realaddr = ((tile + i * 32) << 3) + xx;
|
||||
uint8_t pix = fullbankspace.read_byte(realaddr);
|
||||
row[x * 8 + xx] = (pix + ((colour & 0x70) << 1)) & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t radica_6502_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
bitmap.fill(0, cliprect);
|
||||
@ -457,119 +665,10 @@ uint32_t radica_6502_state::screen_update(screen_device &screen, bitmap_ind16 &b
|
||||
m_palette->set_pen_color(index, r_real, g_real, b_real);
|
||||
}
|
||||
|
||||
// Tilemaps
|
||||
|
||||
int scroll = (m_bg_scroll[1] << 8) | m_bg_scroll[0];
|
||||
address_space& fullbankspace = m_bank->space(AS_PROGRAM);
|
||||
|
||||
if (m_5027_data & 0x40) // 16x16 tiles
|
||||
{
|
||||
int startrow = (scroll >> 4) & 0x1f;
|
||||
|
||||
for (int y = 0; y < 16; y++)
|
||||
{
|
||||
for (int x = 0; x < 16; x++)
|
||||
{
|
||||
int realstartrow = (startrow + y);
|
||||
|
||||
if (realstartrow >= 28)
|
||||
realstartrow -= 28;
|
||||
|
||||
int base = (((realstartrow + y)&0x1f)*8)+x;
|
||||
int tile = m_vram[base * 4] + (m_vram[(base * 4)+1] << 8);
|
||||
int attr = m_vram[(base * 4)+ 2];
|
||||
|
||||
if (m_5027_data & 0x20) // 4bpp mode
|
||||
{
|
||||
tile = (tile & 0xf) + ((tile & ~0xf) * 16);
|
||||
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
tile = (tile & 0xf) + ((tile & ~0xf) * 16);
|
||||
tile <<= 1;
|
||||
|
||||
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
int drawline = (y * 16) + i;
|
||||
drawline -= scroll & 0xf;
|
||||
|
||||
if ((drawline >= 0) && (drawline < 256))
|
||||
{
|
||||
uint16_t* row = &bitmap.pix16(drawline);
|
||||
|
||||
if (m_5027_data & 0x20) // 4bpp
|
||||
{
|
||||
for (int xx = 0; xx < 16; xx += 2)
|
||||
{
|
||||
int realaddr = ((tile + i * 16) << 3) + (xx >> 1);
|
||||
uint8_t pix = fullbankspace.read_byte(realaddr);
|
||||
row[x * 16 + xx + 0] = ((pix & 0xf0) >> 4) + attr;
|
||||
row[x * 16 + xx + 1] = ((pix & 0x0f) >> 0) + attr;
|
||||
}
|
||||
}
|
||||
else // 8bpp
|
||||
{
|
||||
for (int xx = 0; xx < 16; xx++)
|
||||
{
|
||||
int realaddr = ((tile + i * 32) << 3) + xx;
|
||||
uint8_t pix = fullbankspace.read_byte(realaddr);
|
||||
row[x * 16 + xx] = pix;// + attr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // 8x8 tiles
|
||||
{
|
||||
// Phoenix scrolling actually skips a pixel, jumping from 0x001 to 0x1bf, scroll 0x000 isn't used, maybe it has other meanings?
|
||||
|
||||
int startrow = (scroll >> 3) & 0x3f;
|
||||
|
||||
for (int y = 0; y < 32; y++)
|
||||
{
|
||||
for (int x = 0; x < 32; x++)
|
||||
{
|
||||
int realstartrow = (startrow + y);
|
||||
|
||||
if (realstartrow >= 56)
|
||||
realstartrow -= 56;
|
||||
|
||||
int base = (((realstartrow)&0x3f)*32)+x;
|
||||
int tile = m_vram[base * 4] + (m_vram[(base * 4)+1] << 8);
|
||||
//int attr = m_vram[(base * 4)+ 2];
|
||||
|
||||
tile = (tile & 0x1f) + ((tile & ~0x1f) * 8);
|
||||
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
int drawline = (y * 8) + i;
|
||||
drawline -= scroll & 0x7;
|
||||
|
||||
if ((drawline >= 0) && (drawline < 256))
|
||||
{
|
||||
uint16_t* row = &bitmap.pix16(drawline);
|
||||
|
||||
for (int xx = 0; xx < 8; xx++)
|
||||
{
|
||||
int realaddr = ((tile + i * 32) << 3) + xx;
|
||||
uint8_t pix = fullbankspace.read_byte(realaddr);
|
||||
row[x * 8 + xx] = pix;// + attr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_tilemaps(screen,bitmap,cliprect,0);
|
||||
draw_sprites(screen,bitmap,cliprect);
|
||||
draw_tilemaps(screen,bitmap,cliprect,1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1327,7 +1426,7 @@ static MACHINE_CONFIG_START( radicasi )
|
||||
MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 28*8-1)
|
||||
MCFG_SCREEN_PALETTE("palette")
|
||||
|
||||
MCFG_PALETTE_ADD("palette", 1024)
|
||||
MCFG_PALETTE_ADD("palette", 256)
|
||||
|
||||
MCFG_GFXDECODE_ADD("gfxdecode", "palette", radicasi_fake)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user