mirror of
https://github.com/holub/mame
synced 2025-07-05 01:48:29 +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):
|
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
|
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
|
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"
|
#include "emu.h"
|
||||||
@ -306,6 +320,8 @@ private:
|
|||||||
void handle_sound_1_w(int which, int offset, uint8_t data);
|
void handle_sound_1_w(int which, int offset, uint8_t data);
|
||||||
uint8_t handle_sound_1_r(int which, int offset);
|
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);
|
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
|
Sprites
|
||||||
AA yy xx ?? XX YY aa bb
|
AA yy xx cc XX YY aa bb
|
||||||
|
|
||||||
yy = y position
|
yy = y position
|
||||||
xx = x position
|
xx = x position
|
||||||
XX = texture x start
|
XX = texture x start
|
||||||
YY = texture y start
|
YY = texture y start
|
||||||
aa = same as final param on tiles?
|
aa = same as unk2 on tiles
|
||||||
bb = sometimes set in invaders
|
bb = sometimes set in invaders
|
||||||
|
cc = same as attr on tiles (colour / priority?)
|
||||||
|
|
||||||
AA = attributes
|
AA = attributes
|
||||||
e--- fFsS
|
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 x = m_spriteram[i + 2];
|
||||||
uint8_t y = m_spriteram[i + 1];
|
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_x = m_spriteram[i + 4];
|
||||||
uint8_t tex_y = m_spriteram[i + 5];
|
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;
|
continue;
|
||||||
|
|
||||||
int sizex = 8;
|
int sizex = 8;
|
||||||
int sizey = 8;
|
int sizey = 8;
|
||||||
|
|
||||||
if (attrs & 0x01)
|
if (flags & 0x01)
|
||||||
{
|
{
|
||||||
sizex = 16;
|
sizex = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrs & 0x02)
|
if (flags & 0x02)
|
||||||
{
|
{
|
||||||
sizey = 16;
|
sizey = 16;
|
||||||
}
|
}
|
||||||
@ -375,8 +429,8 @@ void radica_6502_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap
|
|||||||
for (int yy = 0; yy < sizey; yy++)
|
for (int yy = 0; yy < sizey; yy++)
|
||||||
{
|
{
|
||||||
uint16_t* row;
|
uint16_t* row;
|
||||||
|
|
||||||
if (attrs & 0x08) // guess flipy
|
if (flags & 0x08) // guess flipy
|
||||||
{
|
{
|
||||||
row = &bitmap.pix16((y + (sizey - 1 - yy)) & 0xff);
|
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++)
|
for (int xx = 0; xx < sizex; xx++)
|
||||||
{
|
{
|
||||||
int realaddr = base + ((tex_x+xx)&0xff);
|
int realaddr = base + ((tex_x + xx) & 0xff);
|
||||||
realaddr += ((tex_y+yy)&0xff) * 256;
|
realaddr += ((tex_y + yy) & 0xff) * 256;
|
||||||
|
|
||||||
uint8_t pix = fullbankspace.read_byte(realaddr);
|
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
|
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;
|
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)
|
uint32_t radica_6502_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||||
{
|
{
|
||||||
bitmap.fill(0, 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);
|
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_sprites(screen,bitmap,cliprect);
|
||||||
|
draw_tilemaps(screen,bitmap,cliprect,1);
|
||||||
|
|
||||||
return 0;
|
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_VISIBLE_AREA(0*8, 32*8-1, 0*8, 28*8-1)
|
||||||
MCFG_SCREEN_PALETTE("palette")
|
MCFG_SCREEN_PALETTE("palette")
|
||||||
|
|
||||||
MCFG_PALETTE_ADD("palette", 1024)
|
MCFG_PALETTE_ADD("palette", 256)
|
||||||
|
|
||||||
MCFG_GFXDECODE_ADD("gfxdecode", "palette", radicasi_fake)
|
MCFG_GFXDECODE_ADD("gfxdecode", "palette", radicasi_fake)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user