mirror of
https://github.com/holub/mame
synced 2025-10-04 08:28:39 +03:00
Plug & Play improvements (Elan / Air Blaster Joystick) (#5856)
* elan video code improvements (nw) * fix x scroll on some air blaster bosses (non-split mode scrolling)
This commit is contained in:
parent
b053f1ee78
commit
5dc487c34d
@ -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(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(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(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(0x502d, 0x502e).rw(m_vid, FUNC(elan_eu3a05vid_device::splitpos_r), FUNC(elan_eu3a05vid_device::splitpos_w)); // split position
|
||||||
map(0x502e, 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)
|
||||||
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
|
|
||||||
// 5037
|
// 5037
|
||||||
map(0x5038, 0x5038).ram();
|
map(0x5038, 0x5038).ram();
|
||||||
|
|
||||||
@ -444,20 +439,26 @@ INTERRUPT_GEN_MEMBER(elan_eu3a05_state::interrupt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Tetris (PAL version) has XTAL of 21.281370
|
/* Tetris (PAL version) has XTAL of 21.281370
|
||||||
// Air Blaster (PAL version) has XTAL of 21.2813
|
Air Blaster (PAL version) has XTAL of 21.2813
|
||||||
// what are the NTSC clocks?
|
what are the NTSC clocks?
|
||||||
|
|
||||||
// not confirmed on Space Invaders, actual CPU clock unknown.
|
not confirmed on Space Invaders, actual CPU clock unknown.
|
||||||
// 21281370 is the same value as a PAL SNES
|
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
|
|
||||||
|
|
||||||
|
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)
|
void elan_eu3a05_state::elan_eu3a05(machine_config &config)
|
||||||
{
|
{
|
||||||
/* basic machine hardware */
|
/* 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_addrmap(AS_PROGRAM, &elan_eu3a05_state::elan_eu3a05_map);
|
||||||
m_maincpu->set_vblank_int("screen", FUNC(elan_eu3a05_state::interrupt));
|
m_maincpu->set_vblank_int("screen", FUNC(elan_eu3a05_state::interrupt));
|
||||||
|
|
||||||
|
@ -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
|
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;
|
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_lo_data = 0x00;
|
||||||
m_tile_gfxbase_hi_data = 0x00;
|
m_tile_gfxbase_hi_data = 0x00;
|
||||||
|
|
||||||
m_sprite_gfxbase_lo_data = 0x00;
|
m_sprite_gfxbase_lo_data = 0x00;
|
||||||
m_sprite_gfxbase_hi_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)
|
uint8_t elan_eu3a05vid_device::read_spriteram(int offset)
|
||||||
@ -262,7 +260,7 @@ void elan_eu3a05vid_device::draw_tilemaps(screen_device& screen, bitmap_ind16& b
|
|||||||
this doesn't handle 8x8 4bpp (not used by anything yet)
|
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);
|
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?
|
// 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;
|
int scrollx;
|
||||||
|
|
||||||
// split can be probably configured in more ways than this
|
// split can be probably configured in more ways than this
|
||||||
if (drawline > m_splitpos)
|
// exact enable conditions unclear
|
||||||
scrollx = get_xscroll(1);
|
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
|
else
|
||||||
scrollx = get_xscroll(0);
|
{
|
||||||
|
scrollx = get_scroll(0);
|
||||||
|
}
|
||||||
|
|
||||||
int base;
|
int base;
|
||||||
|
|
||||||
@ -362,92 +370,64 @@ void elan_eu3a05vid_device::draw_tilemaps(screen_device& screen, bitmap_ind16& b
|
|||||||
|
|
||||||
int colour = attr & 0xf0;
|
int colour = attr & 0xf0;
|
||||||
|
|
||||||
if (m_vidctrl & 0x40) // 16x16 tiles
|
/* '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
|
||||||
if (m_vidctrl & 0x20) // 4bpp mode
|
each texture line in 4bpp mode is 128 bytes
|
||||||
{
|
in 8x8 mode these pages are 32 tiles wide
|
||||||
tile = (tile & 0xf) + ((tile & ~0xf) * 16);
|
in 16x16 mode these pages are 16 tiles wide
|
||||||
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
|
tiles can start on any line
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tile = (tile & 0xf) + ((tile & ~0xf) * 16);
|
|
||||||
tile <<= 1;
|
|
||||||
|
|
||||||
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
|
||||||
else
|
*/
|
||||||
{
|
|
||||||
if (m_vidctrl & 0x20) // 4bpp
|
const int tilespersrcline = 256 / tilexsize;
|
||||||
{
|
const int tilespersrcline_mask = tilespersrcline - 1;
|
||||||
// TODO
|
|
||||||
tile = 0x0000;//machine().rand() & 0x1ff;
|
tile = (tile & tilespersrcline_mask) + ((tile & ~tilespersrcline_mask) * tilexsize);
|
||||||
}
|
|
||||||
else
|
if (!(m_vidctrl & 0x20)) // 8bpp
|
||||||
{
|
tile <<= 1;
|
||||||
tile = (tile & 0x1f) + ((tile & ~0x1f) * 8);
|
|
||||||
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
|
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);
|
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 = x * tilexsize + xx + 0 - scrollx;
|
||||||
drawxpos &= 0x1ff;
|
drawxpos &= 0x1ff;
|
||||||
if ((drawxpos >= 0) && (drawxpos < 256))
|
if ((drawxpos >= 0) && (drawxpos < 256))
|
||||||
row[drawxpos] = ((pix & 0xf0) >> 4) + colour;
|
row[drawxpos] = ((pix & 0xf0) >> 4) + colour;
|
||||||
|
|
||||||
drawxpos = x * 16 + xx + 1;
|
drawxpos = x * tilexsize + xx + 1 - scrollx;
|
||||||
drawxpos &= 0x1ff;
|
drawxpos &= 0x1ff;
|
||||||
if ((drawxpos >= 0) && (drawxpos < 256))
|
if ((drawxpos >= 0) && (drawxpos < 256))
|
||||||
row[drawxpos] = ((pix & 0x0f) >> 0) + colour;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // 8x8 tiles
|
else // 8bpp
|
||||||
{
|
{
|
||||||
if (m_vidctrl & 0x20) // 4bpp
|
for (int xx = 0; xx < tilexsize; xx++)
|
||||||
{
|
{
|
||||||
// TODO
|
int realaddr = ((tile + i * 32) << 3) + xx;
|
||||||
}
|
uint8_t pix = fullbankspace.read_byte(realaddr);
|
||||||
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 drawxpos = x * tilexsize + xx - scrollx;
|
int drawxpos = x * tilexsize + xx - scrollx;
|
||||||
drawxpos &= 0x1ff;
|
drawxpos &= 0x1ff;
|
||||||
|
if ((drawxpos >= 0) && (drawxpos < 256))
|
||||||
if ((drawxpos >= 0) && (drawxpos < 256))
|
row[drawxpos] = (pix + ((colour & 0x70) << 1)) & 0xff;
|
||||||
row[drawxpos] = (pix + ((colour & 0x70) << 1)) & 0xff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -533,32 +513,24 @@ WRITE8_MEMBER(elan_eu3a05vid_device::tile_scroll_w)
|
|||||||
m_tile_scroll[offset] = data;
|
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)
|
READ8_MEMBER(elan_eu3a05vid_device::splitpos_r)
|
||||||
{
|
{
|
||||||
return m_splitpos;
|
return m_splitpos[offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE8_MEMBER(elan_eu3a05vid_device::splitpos_w)
|
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)
|
switch (which)
|
||||||
{
|
{
|
||||||
case 0x0: return (m_tile_xscroll[1] << 8) | (m_tile_xscroll[0]);
|
case 0x0: return (m_tile_scroll[1] << 8) | (m_tile_scroll[0]); // xscroll
|
||||||
case 0x1: return (m_tile_xscroll[3] << 8) | (m_tile_xscroll[2]);
|
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;
|
return 0x0000;
|
||||||
|
@ -34,13 +34,10 @@ public:
|
|||||||
DECLARE_READ8_MEMBER(tile_scroll_r);
|
DECLARE_READ8_MEMBER(tile_scroll_r);
|
||||||
DECLARE_WRITE8_MEMBER(tile_scroll_w);
|
DECLARE_WRITE8_MEMBER(tile_scroll_w);
|
||||||
|
|
||||||
DECLARE_READ8_MEMBER(tile_xscroll_r);
|
|
||||||
DECLARE_WRITE8_MEMBER(tile_xscroll_w);
|
|
||||||
|
|
||||||
DECLARE_READ8_MEMBER(splitpos_r);
|
DECLARE_READ8_MEMBER(splitpos_r);
|
||||||
DECLARE_WRITE8_MEMBER(splitpos_w);
|
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);
|
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_lo_data;
|
||||||
uint8_t m_sprite_gfxbase_hi_data;
|
uint8_t m_sprite_gfxbase_hi_data;
|
||||||
|
|
||||||
uint8_t m_tile_scroll[2];
|
uint8_t m_tile_scroll[4*2];
|
||||||
uint8_t m_tile_xscroll[4];
|
|
||||||
|
|
||||||
uint8_t m_splitpos;
|
uint8_t m_splitpos[2];
|
||||||
|
|
||||||
bool get_tile_data(int base, int drawpri, int& tile, int &attr, int &unk2);
|
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_tilemaps(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int drawpri);
|
||||||
|
Loading…
Reference in New Issue
Block a user