This commit is contained in:
Robbbert 2019-11-05 13:55:43 +11:00
commit 5675bdec9c
3 changed files with 89 additions and 120 deletions

View File

@ -242,13 +242,8 @@ void elan_eu3a05_state::elan_eu3a05_map(address_map &map)
map(0x502a, 0x502a).rw(m_vid, FUNC(elan_eu3a05vid_device::tile_gfxbase_hi_r), FUNC(elan_eu3a05vid_device::tile_gfxbase_hi_w)); // tilebase
map(0x502b, 0x502b).rw(m_vid, FUNC(elan_eu3a05vid_device::sprite_gfxbase_lo_r), FUNC(elan_eu3a05vid_device::sprite_gfxbase_lo_w)); // tilebase (spr?)
map(0x502c, 0x502c).rw(m_vid, FUNC(elan_eu3a05vid_device::sprite_gfxbase_hi_r), FUNC(elan_eu3a05vid_device::sprite_gfxbase_hi_w)); // tilebase (spr?)
map(0x502d, 0x502d).ram();
map(0x502e, 0x502e).rw(m_vid, FUNC(elan_eu3a05vid_device::splitpos_r), FUNC(elan_eu3a05vid_device::splitpos_w)); // split position
map(0x502f, 0x502f).ram();
map(0x5030, 0x5030).ram();
map(0x5031, 0x5032).rw(m_vid, FUNC(elan_eu3a05vid_device::tile_scroll_r), FUNC(elan_eu3a05vid_device::tile_scroll_w));
map(0x5033, 0x5036).rw(m_vid, FUNC(elan_eu3a05vid_device::tile_xscroll_r), FUNC(elan_eu3a05vid_device::tile_xscroll_w)); // there are 2 scroll values in here, air blaster 3d stages uses split scrolling like huntin'3 on eu3a14
map(0x502d, 0x502e).rw(m_vid, FUNC(elan_eu3a05vid_device::splitpos_r), FUNC(elan_eu3a05vid_device::splitpos_w)); // split position
map(0x502f, 0x5036).rw(m_vid, FUNC(elan_eu3a05vid_device::tile_scroll_r), FUNC(elan_eu3a05vid_device::tile_scroll_w)); // there are 4 scroll values in here, x scroll, y scroll, xscroll1 for split, xscroll2 for split (eu3a14 can do split too)
// 5037
map(0x5038, 0x5038).ram();
@ -444,20 +439,26 @@ INTERRUPT_GEN_MEMBER(elan_eu3a05_state::interrupt)
}
// Tetris (PAL version) has XTAL of 21.281370
// Air Blaster (PAL version) has XTAL of 21.2813
// what are the NTSC clocks?
/* Tetris (PAL version) has XTAL of 21.281370
Air Blaster (PAL version) has XTAL of 21.2813
what are the NTSC clocks?
// not confirmed on Space Invaders, actual CPU clock unknown.
// 21281370 is the same value as a PAL SNES
// game speed in Air Blaster appears to be limited entirely by CPU speed (and therefore needs to be around 2mhz at most to match hardware)
// low clock speed also helps with the badly programmed controls in Tetris
not confirmed on Space Invaders, actual CPU clock unknown.
21281370 is the same value as a PAL SNES
game logic speed (but not level scroll speed) in Air Blaster appears to be limited entirely by CPU speed (and therefore needs to be around 2-3mhz
at most to match hardware) - a divider of 8 gives something close to original hardware
it is unclear exactly what limits the clock speed (maybe video / sound causes waitstates? - dma in progress could also slow / stop the CPU
and is not going to be 'instant' on hardware)
using a low clock speed also helps with the badly programmed controls in Tetris as that likewise seems to run the game logic 'as fast as possible'
there don't appear to be any kind of blanking bits being checked.
*/
void elan_eu3a05_state::elan_eu3a05(machine_config &config)
{
/* basic machine hardware */
M6502(config, m_maincpu, XTAL(21'281'370)/12); // wrong, this is the PAL clock
M6502(config, m_maincpu, XTAL(21'281'370)/8); // wrong, this is the PAL clock
m_maincpu->set_addrmap(AS_PROGRAM, &elan_eu3a05_state::elan_eu3a05_map);
m_maincpu->set_vblank_int("screen", FUNC(elan_eu3a05_state::interrupt));

View File

@ -35,19 +35,17 @@ void elan_eu3a05vid_device::device_reset()
m_vidctrl = 0x00; // need to default to an 8x8 mode for Space Invaders test mode at least
for (int i=0;i<2;i++)
for (int i=0;i<4*2;i++)
m_tile_scroll[i] = 0x00;
for (int i=0;i<2;i++)
m_tile_xscroll[i] = 0x00;
m_tile_gfxbase_lo_data = 0x00;
m_tile_gfxbase_hi_data = 0x00;
m_sprite_gfxbase_lo_data = 0x00;
m_sprite_gfxbase_hi_data = 0x00;
m_splitpos = 0x00;
for (int i=0;i<2;i++)
m_splitpos[i] = 0x00;
}
uint8_t elan_eu3a05vid_device::read_spriteram(int offset)
@ -258,11 +256,11 @@ bool elan_eu3a05vid_device::get_tile_data(int base, int drawpri, int& tile, int
}
void elan_eu3a05vid_device::draw_tilemaps(screen_device& screen, bitmap_ind16& bitmap, const rectangle& cliprect, int drawpri)
{
/*
/*
this doesn't handle 8x8 4bpp (not used by anything yet)
*/
int scroll = (m_tile_scroll[1] << 8) | m_tile_scroll[0];
int scroll = get_scroll(1);
address_space& fullbankspace = m_bank->space(AS_PROGRAM);
// Phoenix scrolling actually skips a pixel, jumping from 0x001 to 0x1bf, scroll 0x000 isn't used, maybe it has other meanings?
@ -331,10 +329,20 @@ void elan_eu3a05vid_device::draw_tilemaps(screen_device& screen, bitmap_ind16& b
int scrollx;
// split can be probably configured in more ways than this
if (drawline > m_splitpos)
scrollx = get_xscroll(1);
// exact enable conditions unclear
int splitpos = (m_splitpos[0] << 8) | m_splitpos[1];
if (splitpos != 0xffff)
{
if (drawline > splitpos)
scrollx = get_scroll(3);
else
scrollx = get_scroll(2);
}
else
scrollx = get_xscroll(0);
{
scrollx = get_scroll(0);
}
int base;
@ -362,92 +370,64 @@ void elan_eu3a05vid_device::draw_tilemaps(screen_device& screen, bitmap_ind16& b
int colour = attr & 0xf0;
if (m_vidctrl & 0x40) // 16x16 tiles
{
if (m_vidctrl & 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;
/* 'tiles' are organized / extracted from 'texture' lines that form a 'page' the length of the rom
each texture line in 8bpp mode is 256 bytes
each texture line in 4bpp mode is 128 bytes
in 8x8 mode these pages are 32 tiles wide
in 16x16 mode these pages are 16 tiles wide
tiles can start on any line
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
}
}
else
{
if (m_vidctrl & 0x20) // 4bpp
{
// TODO
tile = 0x0000;//machine().rand() & 0x1ff;
}
else
{
tile = (tile & 0x1f) + ((tile & ~0x1f) * 8);
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
}
}
it is unclear what the behavior is if the tile starts at the far edge of a line (wrap around on line?)
this is eu3a05 specific, eu3a14 uses a more traditional approach
*/
const int tilespersrcline = 256 / tilexsize;
const int tilespersrcline_mask = tilespersrcline - 1;
tile = (tile & tilespersrcline_mask) + ((tile & ~tilespersrcline_mask) * tilexsize);
if (!(m_vidctrl & 0x20)) // 8bpp
tile <<= 1;
if (!(m_vidctrl & 0x40)) // 8*8 tiles
tile >>= 1;
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
uint16_t* row = &bitmap.pix16(drawline);
if (m_vidctrl & 0x40) // 16x16 tiles
if (m_vidctrl & 0x20) // 4bpp
{
if (m_vidctrl & 0x20) // 4bpp
for (int xx = 0; xx < tilexsize; xx += 2)
{
for (int xx = 0; xx < tilexsize; xx += 2)
{
int realaddr = ((tile + i * 16) << 3) + (xx >> 1);
uint8_t pix = fullbankspace.read_byte(realaddr);
int realaddr = ((tile + i * 16) << 3) + (xx >> 1);
uint8_t pix = fullbankspace.read_byte(realaddr);
int drawxpos;
int drawxpos;
drawxpos = x * 16 + xx + 0;
drawxpos &= 0x1ff;
if ((drawxpos >= 0) && (drawxpos < 256))
row[drawxpos] = ((pix & 0xf0) >> 4) + colour;
drawxpos = x * tilexsize + xx + 0 - scrollx;
drawxpos &= 0x1ff;
if ((drawxpos >= 0) && (drawxpos < 256))
row[drawxpos] = ((pix & 0xf0) >> 4) + colour;
drawxpos = x * 16 + xx + 1;
drawxpos &= 0x1ff;
if ((drawxpos >= 0) && (drawxpos < 256))
row[drawxpos] = ((pix & 0x0f) >> 0) + colour;
}
}
else // 8bpp
{
for (int xx = 0; xx < tilexsize; xx++)
{
int realaddr = ((tile + i * 32) << 3) + xx;
uint8_t pix = fullbankspace.read_byte(realaddr);
int drawxpos = x * 16 + xx;
drawxpos &= 0x1ff;
if ((drawxpos >= 0) && (drawxpos < 256))
row[drawxpos] = (pix + ((colour & 0x70) << 1)) & 0xff;
}
drawxpos = x * tilexsize + xx + 1 - scrollx;
drawxpos &= 0x1ff;
if ((drawxpos >= 0) && (drawxpos < 256))
row[drawxpos] = ((pix & 0x0f) >> 0) + colour;
}
}
else // 8x8 tiles
else // 8bpp
{
if (m_vidctrl & 0x20) // 4bpp
for (int xx = 0; xx < tilexsize; xx++)
{
// TODO
}
else
{
for (int xx = 0; xx < tilexsize; xx++)
{
const int realaddr = ((tile + i * 32) << 3) + xx;
const uint8_t pix = fullbankspace.read_byte(realaddr);
int realaddr = ((tile + i * 32) << 3) + xx;
uint8_t pix = fullbankspace.read_byte(realaddr);
int drawxpos = x * tilexsize + xx - scrollx;
drawxpos &= 0x1ff;
if ((drawxpos >= 0) && (drawxpos < 256))
row[drawxpos] = (pix + ((colour & 0x70) << 1)) & 0xff;
}
int drawxpos = x * tilexsize + xx - scrollx;
drawxpos &= 0x1ff;
if ((drawxpos >= 0) && (drawxpos < 256))
row[drawxpos] = (pix + ((colour & 0x70) << 1)) & 0xff;
}
}
}
@ -533,34 +513,26 @@ WRITE8_MEMBER(elan_eu3a05vid_device::tile_scroll_w)
m_tile_scroll[offset] = data;
}
READ8_MEMBER(elan_eu3a05vid_device::tile_xscroll_r)
{
return m_tile_xscroll[offset];
}
WRITE8_MEMBER(elan_eu3a05vid_device::tile_xscroll_w)
{
m_tile_xscroll[offset] = data;
}
READ8_MEMBER(elan_eu3a05vid_device::splitpos_r)
{
return m_splitpos;
return m_splitpos[offset];
}
WRITE8_MEMBER(elan_eu3a05vid_device::splitpos_w)
{
m_splitpos = data;
m_splitpos[offset] = data;
}
uint16_t elan_eu3a05vid_device::get_xscroll(int which)
uint16_t elan_eu3a05vid_device::get_scroll(int which)
{
switch (which)
{
case 0x0: return (m_tile_xscroll[1] << 8) | (m_tile_xscroll[0]);
case 0x1: return (m_tile_xscroll[3] << 8) | (m_tile_xscroll[2]);
case 0x0: return (m_tile_scroll[1] << 8) | (m_tile_scroll[0]); // xscroll
case 0x1: return (m_tile_scroll[3] << 8) | (m_tile_scroll[2]); // yscroll
case 0x2: return (m_tile_scroll[5] << 8) | (m_tile_scroll[4]); // xsplit 1 scroll
case 0x3: return (m_tile_scroll[7] << 8) | (m_tile_scroll[6]); // scplit 2 scroll
}
return 0x0000;
}

View File

@ -34,13 +34,10 @@ public:
DECLARE_READ8_MEMBER(tile_scroll_r);
DECLARE_WRITE8_MEMBER(tile_scroll_w);
DECLARE_READ8_MEMBER(tile_xscroll_r);
DECLARE_WRITE8_MEMBER(tile_xscroll_w);
DECLARE_READ8_MEMBER(splitpos_r);
DECLARE_WRITE8_MEMBER(splitpos_w);
uint16_t get_xscroll(int which);
uint16_t get_scroll(int which);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
@ -61,10 +58,9 @@ private:
uint8_t m_sprite_gfxbase_lo_data;
uint8_t m_sprite_gfxbase_hi_data;
uint8_t m_tile_scroll[2];
uint8_t m_tile_xscroll[4];
uint8_t m_tile_scroll[4*2];
uint8_t m_splitpos;
uint8_t m_splitpos[2];
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);