taitoair.c fixes and changes:

- Very preliminary Framebuffer DMA hook-up, mostly used for Top Landing to show Course Select on screen;
- Fixed analog inputs;
- Fixed color select for 3d;
- Fixed tilemap priority;

(I assume with this we can promote Top Landing as working)
This commit is contained in:
angelosa 2015-06-30 23:22:59 +02:00
parent de9c38923a
commit db079fd280
3 changed files with 139 additions and 52 deletions

View File

@ -220,6 +220,13 @@ cpu #2 (PC=00000609): unmapped memory word read from 00006838 & FFFF
cpu #2 (PC=0000060E): unmapped memory word read from 0000683A & FFFF cpu #2 (PC=0000060E): unmapped memory word read from 0000683A & FFFF
****************************************************************************/ ****************************************************************************/
/*!
@todo - Framebuffer DMA requires palette switch to be selected dynamically, see at first stage Course Select in Top Landing;
- Air Inferno: exception with DIVIDE BY ZERO after some time of gameplay;
- Air Inferno: Expert course has wrong 3d geometry;
- Top Landing: Night stages might have wrong priority for stars-above-sea;
- Input limiters / analog thresholds for both games;
*/
#include "emu.h" #include "emu.h"
#include "cpu/z80/z80.h" #include "cpu/z80/z80.h"
@ -370,6 +377,33 @@ WRITE8_MEMBER(taitoair_state::sound_bankswitch_w)
membank("z80bank")->set_entry(data & 3); membank("z80bank")->set_entry(data & 3);
} }
/*!
@brief Framebuffer DMA control
@regs [0] x--- ---- ---- ---- copy framebuffer to the screen
[0] --x- ---- ---- ---- unknown, used on POST test
[0] 1001 1111 1111 1111 used by Air Inferno after erase op, erase -> copy?
[0] 0001 1111 1111 1111 erase op?
[1] xxxx xxxx xxxx xxxx fill value? 0xffff by Top Landing, 0x0000 Air Inferno
[2] (unused)
[3] both games uses 0xb7, most likely a register setting.
*/
WRITE16_MEMBER(taitoair_state::dma_regs_w)
{
printf("%08x %04x\n",offset,data);
if(offset == 0 && ACCESSING_BITS_8_15)
{
if(data == 0x1fff)
{
fb_erase_op();
}
else if(data & 0x8000)
{
/*! @todo it also flushes current palette. */
fb_copy_op();
}
}
}
/*********************************************************** /***********************************************************
MEMORY STRUCTURES MEMORY STRUCTURES
@ -382,7 +416,7 @@ static ADDRESS_MAP_START( airsys_map, AS_PROGRAM, 16, taitoair_state )
AM_RANGE(0x180000, 0x187fff) AM_RAM_WRITE(airsys_gradram_w) AM_SHARE("gradram") /* "gradiation ram (0/1)" */ AM_RANGE(0x180000, 0x187fff) AM_RAM_WRITE(airsys_gradram_w) AM_SHARE("gradram") /* "gradiation ram (0/1)" */
AM_RANGE(0x188000, 0x189fff) AM_MIRROR(0x2000) AM_RAM_WRITE(airsys_paletteram16_w) AM_SHARE("paletteram") AM_RANGE(0x188000, 0x189fff) AM_MIRROR(0x2000) AM_RAM_WRITE(airsys_paletteram16_w) AM_SHARE("paletteram")
AM_RANGE(0x800000, 0x820fff) AM_DEVREADWRITE("tc0080vco", tc0080vco_device, word_r, word_w) /* tilemaps, sprites */ AM_RANGE(0x800000, 0x820fff) AM_DEVREADWRITE("tc0080vco", tc0080vco_device, word_r, word_w) /* tilemaps, sprites */
// AM_RANGE(0x906000, 0x906007) AM_RAM // DMA? AM_RANGE(0x906000, 0x906007) AM_WRITE(dma_regs_w) // DMA?
AM_RANGE(0x908000, 0x90ffff) AM_RAM AM_SHARE("line_ram") /* "line ram" */ AM_RANGE(0x908000, 0x90ffff) AM_RAM AM_SHARE("line_ram") /* "line ram" */
AM_RANGE(0x910000, 0x91ffff) AM_RAM AM_SHARE("dsp_ram") /* "dsp common ram" (TMS320C25) */ AM_RANGE(0x910000, 0x91ffff) AM_RAM AM_SHARE("dsp_ram") /* "dsp common ram" (TMS320C25) */
AM_RANGE(0x980000, 0x98000f) AM_RAM AM_SHARE("tc0430grw") /* TC0430GRW roz transform coefficients */ AM_RANGE(0x980000, 0x98000f) AM_RAM AM_SHARE("tc0430grw") /* TC0430GRW roz transform coefficients */
@ -585,10 +619,10 @@ static INPUT_PORTS_START( topland )
PORT_BIT( 0x00ff, 0x0000, IPT_AD_STICK_Z ) PORT_MINMAX(0x0080,0x007f) PORT_SENSITIVITY(30) PORT_KEYDELTA(40) PORT_PLAYER(1) PORT_REVERSE PORT_BIT( 0x00ff, 0x0000, IPT_AD_STICK_Z ) PORT_MINMAX(0x0080,0x007f) PORT_SENSITIVITY(30) PORT_KEYDELTA(40) PORT_PLAYER(1) PORT_REVERSE
PORT_START(STICK2_PORT_TAG) PORT_START(STICK2_PORT_TAG)
PORT_BIT( 0xffff, 0x0000, IPT_AD_STICK_X ) PORT_MINMAX(0xf800,0x07ff) PORT_SENSITIVITY(30) PORT_KEYDELTA(40) PORT_PLAYER(1) PORT_BIT( 0x0fff, 0x0000, IPT_AD_STICK_X ) PORT_MINMAX(0x00800, 0x07ff) PORT_SENSITIVITY(100) PORT_KEYDELTA(20) PORT_PLAYER(1)
PORT_START(STICK3_PORT_TAG) PORT_START(STICK3_PORT_TAG)
PORT_BIT( 0xffff, 0x0000, IPT_AD_STICK_Y ) PORT_MINMAX(0xf800,0x07ff) PORT_SENSITIVITY(30) PORT_KEYDELTA(40) PORT_PLAYER(1) PORT_BIT( 0x0fff, 0x0000, IPT_AD_STICK_Y ) PORT_MINMAX(0x00800, 0x07ff) PORT_SENSITIVITY(100) PORT_KEYDELTA(20) PORT_PLAYER(1)
INPUT_PORTS_END INPUT_PORTS_END
static INPUT_PORTS_START( ainferno ) static INPUT_PORTS_START( ainferno )
@ -645,10 +679,10 @@ static INPUT_PORTS_START( ainferno )
PORT_BIT( 0x00ff, 0x0000, IPT_AD_STICK_Z ) PORT_MINMAX(0x0080,0x007f) PORT_SENSITIVITY(30) PORT_KEYDELTA(40) PORT_PLAYER(1) PORT_REVERSE PORT_BIT( 0x00ff, 0x0000, IPT_AD_STICK_Z ) PORT_MINMAX(0x0080,0x007f) PORT_SENSITIVITY(30) PORT_KEYDELTA(40) PORT_PLAYER(1) PORT_REVERSE
PORT_START(STICK2_PORT_TAG) PORT_START(STICK2_PORT_TAG)
PORT_BIT( 0xffff, 0x0000, IPT_AD_STICK_X ) PORT_MINMAX(0xf800,0x7ff) PORT_SENSITIVITY(30) PORT_KEYDELTA(40) PORT_PLAYER(1) PORT_BIT( 0x0fff, 0x0000, IPT_AD_STICK_X ) PORT_MINMAX(0x00800, 0x07ff) PORT_SENSITIVITY(100) PORT_KEYDELTA(20) PORT_PLAYER(1)
PORT_START(STICK3_PORT_TAG) PORT_START(STICK3_PORT_TAG)
PORT_BIT( 0xffff, 0x0000, IPT_AD_STICK_Y ) PORT_MINMAX(0xf800,0x7ff) PORT_SENSITIVITY(30) PORT_KEYDELTA(40) PORT_PLAYER(1) PORT_BIT( 0x0fff, 0x0000, IPT_AD_STICK_Y ) PORT_MINMAX(0x00800, 0x07ff) PORT_SENSITIVITY(100) PORT_KEYDELTA(20) PORT_PLAYER(1)
INPUT_PORTS_END INPUT_PORTS_END
@ -953,6 +987,6 @@ ROM_END
/* ( YEAR NAME PARENT MACHINE INPUT INIT MONITOR COMPANY FULLNAME */ /* ( YEAR NAME PARENT MACHINE INPUT INIT MONITOR COMPANY FULLNAME */
GAME( 1988, topland, 0, airsys, topland, driver_device, 0, ROT0, "Taito Corporation Japan", "Top Landing (World)", GAME_NOT_WORKING ) GAME( 1988, topland, 0, airsys, topland, driver_device, 0, ROT0, "Taito Corporation Japan", "Top Landing (World)", GAME_IMPERFECT_GRAPHICS )
GAME( 1990, ainferno, 0, airsys, ainferno, driver_device, 0, ROT0, "Taito America Corporation", "Air Inferno (US)", GAME_NOT_WORKING ) GAME( 1990, ainferno, 0, airsys, ainferno, driver_device, 0, ROT0, "Taito America Corporation", "Air Inferno (US)", GAME_NOT_WORKING )
GAME( 1990, ainfernoj,ainferno, airsys, ainferno, driver_device, 0, ROT0, "Taito Corporation Japan", "Air Inferno (Japan)", GAME_NOT_WORKING ) GAME( 1990, ainfernoj,ainferno, airsys, ainferno, driver_device, 0, ROT0, "Taito Corporation Japan", "Air Inferno (Japan)", GAME_NOT_WORKING )

View File

@ -119,6 +119,7 @@ public:
DECLARE_READ16_MEMBER(stick2_input_r); DECLARE_READ16_MEMBER(stick2_input_r);
DECLARE_WRITE8_MEMBER(sound_bankswitch_w); DECLARE_WRITE8_MEMBER(sound_bankswitch_w);
DECLARE_WRITE16_MEMBER(dsp_flags_w); DECLARE_WRITE16_MEMBER(dsp_flags_w);
DECLARE_WRITE16_MEMBER(dma_regs_w);
virtual void machine_start(); virtual void machine_start();
virtual void machine_reset(); virtual void machine_reset();
@ -126,7 +127,10 @@ public:
UINT32 screen_update_taitoair(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); UINT32 screen_update_taitoair(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
int draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect ); int draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect );
int draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect, int start_offset ); int draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect, int start_offset );
void fb_copy_op(void);
void fb_fill_op(void);
void fb_erase_op(void);
void fill_slope( bitmap_ind16 &bitmap, const rectangle &cliprect, UINT16 header, INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 y1, INT32 y2, INT32 *nx1, INT32 *nx2 ); void fill_slope( bitmap_ind16 &bitmap, const rectangle &cliprect, UINT16 header, INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 y1, INT32 y2, INT32 *nx1, INT32 *nx2 );
void fill_poly( bitmap_ind16 &bitmap, const rectangle &cliprect, const struct taitoair_poly *q ); void fill_poly( bitmap_ind16 &bitmap, const rectangle &cliprect, const struct taitoair_poly *q );
int projectEyeCoordToScreen(float* projectionMatrix,const int Res,INT16* eyePoint3d,int type); int projectEyeCoordToScreen(float* projectionMatrix,const int Res,INT16* eyePoint3d,int type);

View File

@ -259,24 +259,26 @@ void taitoair_state::fill_slope( bitmap_ind16 &bitmap, const rectangle &cliprect
if (xx2 > cliprect.max_x) if (xx2 > cliprect.max_x)
xx2 = cliprect.max_x; xx2 = cliprect.max_x;
if(header & 0x4000 || machine().input().code_pressed(KEYCODE_Q)) if(header & 0x4000 && machine().input().code_pressed(KEYCODE_Q))
{ {
base_color = machine().rand() & 0x3fff; base_color = machine().rand() & 0x3fff;
grad_col = 0; grad_col = 0;
} }
else if(header & 0x40) else if(m_paletteram[(header & 0xff)+0x300] & 0x8000)
{
/* Non-terrain elements are colored with this. */
base_color = (header & 0x3f) + 0x340;
grad_col = 0;
}
else
{ {
/* Terrain elements, with a gradient applied. */ /* Terrain elements, with a gradient applied. */
/*! @todo it's unknown if gradient color applies by global screen Y coordinate or there's a calculation to somewhere ... */ /*! @todo it's unknown if gradient color applies by global screen Y coordinate or there's a calculation to somewhere ... */
base_color = ((header & 0x3f) * 0x80) + 0x2040; base_color = ((header & 0x3f) * 0x80) + 0x2040;
if(header & 0x3fe0)
base_color = machine().rand() & 0x3fff;
grad_col = (y1 >> 3) & 0x3f; grad_col = (y1 >> 3) & 0x3f;
} }
else
{
/* Non-terrain elements are colored with this. */
base_color = (header & 0xff) + 0x300;
grad_col = 0;
}
while (xx1 <= xx2) while (xx1 <= xx2)
{ {
@ -388,8 +390,84 @@ void taitoair_state::fill_poly( bitmap_ind16 &bitmap, const rectangle &cliprect,
dsp handlers dsp handlers
***************************************************************************/ ***************************************************************************/
/* void taitoair_state::fb_copy_op()
TODO: still don't know how this works. It calls three values (0x1fff-0x5fff-0xdfff), for two or three offsets. {
/*! @todo declare once */
rectangle cliprect;
/* printf("%04x -> %d\n",data,offset); */
cliprect.min_x = 0;
cliprect.min_y = 3*16;
cliprect.max_x = m_screen->width() - 1;
cliprect.max_y = m_screen->height() - 1;
/* clear screen fb */
m_framebuffer[1]->fill(0, cliprect);
/* copy buffer fb into screen fb (at this stage we are ready to draw) */
copybitmap_trans(*m_framebuffer[1], *m_framebuffer[0], 0, 0, 0, 0, cliprect, 0);
/* now clear buffer fb */
m_framebuffer[0]->fill(0, cliprect);
}
void taitoair_state::fb_erase_op()
{
/*! @todo declare once */
rectangle cliprect;
/* printf("%04x -> %d\n",data,offset); */
cliprect.min_x = 0;
cliprect.min_y = 3*16;
cliprect.max_x = m_screen->width() - 1;
cliprect.max_y = m_screen->height() - 1;
m_framebuffer[0]->fill(0, cliprect);
m_framebuffer[1]->fill(0, cliprect);
}
void taitoair_state::fb_fill_op()
{
/*! @todo declare once */
rectangle cliprect;
/* printf("%04x -> %d\n",data,offset); */
cliprect.min_x = 0;
cliprect.min_y = 3*16;
cliprect.max_x = m_screen->width() - 1;
cliprect.max_y = m_screen->height() - 1;
if (m_line_ram[0x3fff])
{
int adr = 0x3fff;
while (adr >= 0 && m_line_ram[adr] && m_line_ram[adr] != 0x4000)
{
int pcount = 0;
m_q.header = m_line_ram[adr--];
while (pcount < TAITOAIR_POLY_MAX_PT && adr >= 1 && !(m_line_ram[adr] & 0xc000))
{
m_q.p[pcount].y = m_line_ram[adr--] + 3 * 16;
m_q.p[pcount].x = m_line_ram[adr--];
pcount++;
}
adr--;
m_q.pcount = pcount;
if (!(m_line_ram[adr] & 0x8000))
{
m_q.header |= 0x4000;
logerror("special poly at %04x\n", adr);
while(adr >= 0 && !(m_line_ram[adr] & 0xc000))
adr--;
}
fill_poly(*m_framebuffer[0], cliprect, &m_q);
}
}
}
/*!
@todo still don't know how this works. It calls three values (0x1fff-0x5fff-0xdfff), for two or three offsets.
In theory this should fit into framebuffer draw, display, clear and swap in some way. In theory this should fit into framebuffer draw, display, clear and swap in some way.
*/ */
WRITE16_MEMBER(taitoair_state::dsp_flags_w) WRITE16_MEMBER(taitoair_state::dsp_flags_w)
@ -407,43 +485,13 @@ WRITE16_MEMBER(taitoair_state::dsp_flags_w)
/* clear and copy operation if offset is 0x3001 */ /* clear and copy operation if offset is 0x3001 */
if(offset == 1) if(offset == 1)
{ {
/* clear screen fb */ fb_copy_op();
m_framebuffer[1]->fill(0, cliprect);
/* copy buffer fb into screen fb (at this stage we are ready to draw) */
copybitmap_trans(*m_framebuffer[1], *m_framebuffer[0], 0, 0, 0, 0, cliprect, 0);
/* now clear buffer fb */
m_framebuffer[0]->fill(0, cliprect);
} }
/* if offset 0x3001 OR 0x3002 we put data in the buffer fb */ /* if offset 0x3001 OR 0x3002 we put data in the buffer fb */
if(offset) if(offset)
{ {
if (m_line_ram[0x3fff]) fb_fill_op();
{
int adr = 0x3fff;
while (adr >= 0 && m_line_ram[adr] && m_line_ram[adr] != 0x4000)
{
int pcount = 0;
m_q.header = m_line_ram[adr--];
while (pcount < TAITOAIR_POLY_MAX_PT && adr >= 1 && !(m_line_ram[adr] & 0xc000))
{
m_q.p[pcount].y = m_line_ram[adr--] + 3 * 16;
m_q.p[pcount].x = m_line_ram[adr--];
pcount++;
}
adr--;
m_q.pcount = pcount;
if (!(m_line_ram[adr] & 0x8000))
{
m_q.header |= 0x4000;
logerror("special poly at %04x\n", adr);
while(adr >= 0 && !(m_line_ram[adr] & 0xc000))
adr--;
}
fill_poly(*m_framebuffer[0], cliprect, &m_q);
}
}
} }
} }
} }
@ -505,13 +553,14 @@ UINT32 taitoair_state::screen_update_taitoair(screen_device &screen, bitmap_ind1
} }
m_tc0080vco->tilemap_draw(screen, bitmap, cliprect, 0, 0, 0);
copybitmap_trans(bitmap, *m_framebuffer[1], 0, 0, 0, 0, cliprect, 0); copybitmap_trans(bitmap, *m_framebuffer[1], 0, 0, 0, 0, cliprect, 0);
m_tc0080vco->tilemap_draw(screen, bitmap, cliprect, 0, 0, 0);
sprite_ptr = draw_sprites(bitmap, cliprect); sprite_ptr = draw_sprites(bitmap, cliprect);
m_tc0080vco->tilemap_draw(screen, bitmap, cliprect, 1, 0, 0); m_tc0080vco->tilemap_draw(screen, bitmap, cliprect, 1, 0, 0);
m_tc0080vco->tilemap_draw(screen, bitmap, cliprect, 2, 0, 0); m_tc0080vco->tilemap_draw(screen, bitmap, cliprect, 2, 0, 0);