mirror of
https://github.com/holub/mame
synced 2025-05-12 00:58:53 +03:00
Implemented MCU simulation to terrafu / terrafa [Angelo Salese]
This commit is contained in:
parent
0ad33b6d4c
commit
e71f44201b
@ -24,8 +24,8 @@ TODO:
|
||||
- simulate the mcu/blitter (particularly needed in terrafu and legion)
|
||||
-- or figure out which chip it is, decap it, and emulate it.
|
||||
- time over doesn't kill the player in Kodure Ookami;
|
||||
- attract mode has a glitch with the "Terra Force" title screen at the left-right edges of the screen.
|
||||
could be due of protection;
|
||||
- intro in Terra Force isn't right, the square panels should be cleared after every
|
||||
animation is played, almost likely to not be protection related;
|
||||
- priorities, especially with the text layer (Terra Force);
|
||||
|
||||
|
||||
@ -181,26 +181,219 @@ static WRITE16_HANDLER( io_w )
|
||||
flip_screen_set(space->machine(), state->m_vreg & 0x1000);
|
||||
}
|
||||
|
||||
static void terrafu_sm_transfer(address_space *space,UINT16 src,UINT16 dst,UINT8 size)
|
||||
{
|
||||
armedf_state *state = space->machine().driver_data<armedf_state>();
|
||||
UINT8 * data = (UINT8 *)space->machine().region("gfx5")->base();
|
||||
int i;
|
||||
|
||||
for(i=0;i<size;i++)
|
||||
{
|
||||
state->m_text_videoram[i+dst+0x000] = data[i+0x0+src] & 0xff;
|
||||
state->m_text_videoram[i+dst+0x400] = data[i+0xc+src] & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
static void terrafu_sm_onoff(address_space *space,UINT16 dst,UINT8 condition)
|
||||
{
|
||||
armedf_state *state = space->machine().driver_data<armedf_state>();
|
||||
UINT8 * data = (UINT8 *)space->machine().region("gfx5")->base();
|
||||
int i;
|
||||
// char on_string[] = { "O", "N", " " };
|
||||
const UINT8 on_string[4] = { "ON " };
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
state->m_text_videoram[i+dst+0x000] = (condition) ? (data[i+0x0+0x316] & 0xff) : (on_string[i] & 0xff);
|
||||
state->m_text_videoram[i+dst+0x400] = 0x10;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: just before any string in the "MCU" rom, there's an offset, it indicates where the string should go in the tilemap.
|
||||
This is currently hard-coded */
|
||||
static void terrafu_mcu_exec(address_space *space,UINT16 mcu_cmd)
|
||||
{
|
||||
armedf_state *state = space->machine().driver_data<armedf_state>();
|
||||
UINT8 * data = (UINT8 *)space->machine().region("gfx5")->base();
|
||||
int i;
|
||||
int credit_count = (state->m_text_videoram[0xf] & 0xff);
|
||||
UINT8 fl_cond = space->machine().primary_screen->frame_number() & 0x10; /* for insert coin "flickering" */
|
||||
|
||||
switch(mcu_cmd)
|
||||
{
|
||||
case 0x0e00:
|
||||
break;
|
||||
case 0x0e1c: /* gameplay, unknown ... */
|
||||
break;
|
||||
case 0x0e80: /* attract demo */
|
||||
for(i=0;i<0x10;i++) /* CREDIT */
|
||||
{
|
||||
state->m_text_videoram[i+0x050+0x0000] = data[i+0x00+0x0025] & 0xff;
|
||||
state->m_text_videoram[i+0x050+0x0400] = data[i+0x10+0x0025] & 0xff;
|
||||
}
|
||||
state->m_text_videoram[0x05f+0x000] = ((credit_count) + 0x10);
|
||||
state->m_text_videoram[0x05f+0x400] = (0x40);
|
||||
|
||||
for(i=0;i<0x10;i++) /* INSERT COIN */
|
||||
{
|
||||
state->m_text_videoram[i+0x16a+0x0000] = (fl_cond) ? 0x20 : data[i+0x00+0x0003] & 0xff;
|
||||
state->m_text_videoram[i+0x16a+0x0400] = data[i+0x10+0x0003] & 0xff;
|
||||
}
|
||||
|
||||
for(i=0;i<0x10;i++) /* GAME OVER */
|
||||
{
|
||||
state->m_text_videoram[i+0x1a8+0x0000] = data[i+0x00+0x0135] & 0xff;
|
||||
state->m_text_videoram[i+0x1a8+0x0400] = data[i+0x10+0x0135] & 0xff;
|
||||
}
|
||||
break;
|
||||
case 0x0000: /* title screen / continue */
|
||||
for(i=0;i<0x10;i++)
|
||||
{
|
||||
state->m_text_videoram[i+0x050+0x0000] = data[i+0x00+0x0025] & 0xff;
|
||||
state->m_text_videoram[i+0x050+0x0400] = data[i+0x10+0x0025] & 0xff;
|
||||
}
|
||||
state->m_text_videoram[0x05f+0x000] = (credit_count + 0x10);
|
||||
state->m_text_videoram[0x05f+0x400] = (0x40);
|
||||
|
||||
if(credit_count == 0)
|
||||
{
|
||||
for(i=0;i<0x10;i++) /* INSERT COIN */
|
||||
{
|
||||
state->m_text_videoram[i+0x16a+0x0000] = (fl_cond) ? 0x20 : data[i+0x00+0x0003] & 0xff;
|
||||
state->m_text_videoram[i+0x16a+0x0400] = data[i+0x10+0x0003] & 0xff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0;i<0x18;i++) /* PUSH START BUTTON (0x1a8? Gets wrong on the continue with this ...) */
|
||||
{
|
||||
state->m_text_videoram[i+0x128+0x0000] = data[i+0x00+0x004b] & 0xff;
|
||||
state->m_text_videoram[i+0x128+0x0400] = data[i+0x18+0x004b] & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
if(credit_count == 1)
|
||||
{
|
||||
for(i=0;i<0x18;i++) /* ONE PLAYER ONLY */
|
||||
{
|
||||
state->m_text_videoram[i+0x168+0x0000] = data[i+0x00+0x007d] & 0xff;
|
||||
state->m_text_videoram[i+0x168+0x0400] = data[i+0x18+0x007d] & 0xff;
|
||||
}
|
||||
}
|
||||
else if(credit_count > 1)
|
||||
{
|
||||
for(i=0;i<0x18;i++) /* ONE OR TWO PLAYERS */
|
||||
{
|
||||
state->m_text_videoram[i+0x168+0x0000] = data[i+0x00+0x00af] & 0xff;
|
||||
state->m_text_videoram[i+0x168+0x0400] = data[i+0x18+0x00af] & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 0x0280: /* layer clearances */
|
||||
case 0x0282:
|
||||
for(i=0;i<0x400;i++)
|
||||
{
|
||||
state->m_text_videoram[i+0x000+0x0000] = data[i+0x000+0x2800] & 0xff;
|
||||
state->m_text_videoram[i+0x000+0x0400] = data[i+0x400+0x2800] & 0xff;
|
||||
}
|
||||
break;
|
||||
case 0x0200: /* Nichibutsu logo */
|
||||
case 0x0201:
|
||||
for(i=0;i<0x400;i++)
|
||||
{
|
||||
state->m_text_videoram[i+0x000+0x0000] = data[i+0x000+0x2000] & 0xff;
|
||||
state->m_text_videoram[i+0x000+0x0400] = data[i+0x400+0x2000] & 0xff;
|
||||
}
|
||||
break;
|
||||
case 0x600: /* service mode */
|
||||
for(i=0;i<0x400;i++)
|
||||
{
|
||||
if((state->m_text_videoram[i+0x000+0x0000] & 0xff00) == 0xff00) /* uhm, avoids bonus awards overwrite? */
|
||||
continue;
|
||||
|
||||
state->m_text_videoram[i+0x000+0x0000] = data[i+0x000+0x3000] & 0xff;
|
||||
state->m_text_videoram[i+0x000+0x0400] = data[i+0x400+0x3000] & 0xff;
|
||||
}
|
||||
state->m_text_videoram[0x252+0x000] = ((state->m_text_videoram[0x11] & 0xf0) >> 4) + 0x10;
|
||||
state->m_text_videoram[0x253+0x000] = (state->m_text_videoram[0x11] & 0x0f) + 0x10;
|
||||
state->m_text_videoram[0x252+0x400] = (0x40);
|
||||
state->m_text_videoram[0x253+0x400] = (0x40);
|
||||
|
||||
/*
|
||||
[0x02] & 0x01 p1 up
|
||||
[0x02] & 0x02 p1 down
|
||||
[0x02] & 0x04 p1 left
|
||||
[0x02] & 0x08 p1 right
|
||||
[0x02] & 0x10 p1 button 1
|
||||
[0x02] & 0x20 p1 button 2
|
||||
[0x02] & 0x40 p1 button 3
|
||||
[0x03] & 0x01 p2 up
|
||||
[0x03] & 0x02 p2 down
|
||||
[0x03] & 0x04 p2 left
|
||||
[0x03] & 0x08 p2 right
|
||||
[0x03] & 0x10 p2 button 1
|
||||
[0x03] & 0x20 p2 button 2
|
||||
[0x03] & 0x40 p2 button 3
|
||||
[0x04] & 0x10 service
|
||||
[0x04] & 0x04 coin A
|
||||
[0x04] & 0x08 coin B
|
||||
[0x04] & 0x01 start 1
|
||||
[0x04] & 0x02 start 2
|
||||
[0x05] DSW1
|
||||
[0x06] DSW2
|
||||
[0x07] & 0x40 demo sounds ON / OFF
|
||||
[0x07] & 0x7 lives setting
|
||||
[0x07] & 0x80 cabinet (upright / table)
|
||||
[0x07] & 0x30 difficulty (easy / normal / hard / hardest)
|
||||
[0x0f] coinage A
|
||||
[0x10] coinage B
|
||||
*/
|
||||
state->m_text_videoram[0x3bb|0x000] = (state->m_text_videoram[7] & 0x7) + 0x10;
|
||||
state->m_text_videoram[0x3bb|0x400] = (0x40);
|
||||
|
||||
terrafu_sm_transfer(space,0x1fa + (((state->m_text_videoram[7] & 0x30) >> 4) * 0x18),0x390,12);
|
||||
terrafu_sm_transfer(space,0x264 + (((state->m_text_videoram[7] & 0x80) >> 7) * 0x18),0x330,12);
|
||||
terrafu_sm_transfer(space,0x296 + (((state->m_text_videoram[7] & 0x40) >> 6) * 0x18),0x310,12);
|
||||
|
||||
state->m_text_videoram[0x2ee|0x000] = ((state->m_text_videoram[0xf] & 0xf0) >> 4) + 0x10;
|
||||
state->m_text_videoram[0x2ee|0x400] = (0x40);
|
||||
state->m_text_videoram[0x2f5|0x000] = ((state->m_text_videoram[0xf] & 0x0f) >> 0) + 0x10;
|
||||
state->m_text_videoram[0x2f5|0x400] = (0x40);
|
||||
state->m_text_videoram[0x2ce|0x000] = ((state->m_text_videoram[0x10] & 0xf0) >> 4) + 0x10;
|
||||
state->m_text_videoram[0x2ce|0x400] = (0x40);
|
||||
state->m_text_videoram[0x2d5|0x000] = ((state->m_text_videoram[0x10] & 0x0f) >> 0) + 0x10;
|
||||
state->m_text_videoram[0x2d5|0x400] = (0x40);
|
||||
|
||||
for(i=0;i<8;i++) /* dips */
|
||||
{
|
||||
terrafu_sm_onoff(space,0x074 + (i * 0x20),(state->m_text_videoram[0x05] >> (7-i)) & 1);
|
||||
terrafu_sm_onoff(space,0x079 + (i * 0x20),(state->m_text_videoram[0x06] >> (7-i)) & 1);
|
||||
}
|
||||
|
||||
/* TODO: inputs layout? */
|
||||
|
||||
break;
|
||||
//default:
|
||||
//printf("%04x\n",mcu_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static WRITE16_HANDLER( terraf_io_w )
|
||||
{
|
||||
armedf_state *state = space->machine().driver_data<armedf_state>();
|
||||
|
||||
if(data & 0x4000 && ((state->m_vreg & 0x4000) == 0)) //0 -> 1 transition, terrafu only?
|
||||
{
|
||||
terrafu_mcu_exec(space,(state->m_text_videoram[0] << 8) | (state->m_text_videoram[1] & 0xff));
|
||||
|
||||
tilemap_mark_all_tiles_dirty(state->m_tx_tilemap);
|
||||
}
|
||||
|
||||
COMBINE_DATA(&state->m_vreg);
|
||||
/* bits 0 and 1 of armedf_vreg are coin counters */
|
||||
/* bit 12 seems to handle screen flipping */
|
||||
flip_screen_set(space->machine(), state->m_vreg & 0x1000);
|
||||
|
||||
if ((state->m_vreg & 0x4000) && !(state->m_vreg & 0x0100))
|
||||
{
|
||||
int i;
|
||||
for (i = 0x10; i < 0x1000; i++)
|
||||
{
|
||||
state->m_text_videoram[i] = 0x20;
|
||||
}
|
||||
tilemap_mark_all_tiles_dirty(state->m_tx_tilemap);
|
||||
//logerror("vreg WIPE TX\n");
|
||||
}
|
||||
//logerror("VReg = %04x\n", state->m_vreg);
|
||||
}
|
||||
|
||||
static WRITE16_HANDLER( terrafb_io_w )
|
||||
@ -1646,9 +1839,9 @@ static DRIVER_INIT( cclimbr2 )
|
||||
/* YEAR, NAME, PARENT, MACHINE, INPUT, INIT, MONITOR, COMPANY, FULLNAME, FLAGS */
|
||||
GAME( 1987, legion, 0, legion, legion, legion, ROT270, "Nichibutsu", "Chouji Meikyuu Legion (ver 2.03)", GAME_SUPPORTS_SAVE | GAME_IMPERFECT_GRAPHICS | GAME_UNEMULATED_PROTECTION )
|
||||
GAME( 1987, legiono, legion, legiono, legion, legiono, ROT270, "Nichibutsu", "Chouji Meikyuu Legion (ver 1.05)", GAME_SUPPORTS_SAVE ) /* bootleg? */
|
||||
GAME( 1987, terraf, 0, terraf, terraf, terraf, ROT0, "Nichibutsu", "Terra Force (Japan set 1)", GAME_SUPPORTS_SAVE | GAME_IMPERFECT_GRAPHICS | GAME_UNEMULATED_PROTECTION )
|
||||
GAME( 1987, terraf, 0, terraf, terraf, terraf, ROT0, "Nichibutsu", "Terra Force (set 1)", GAME_SUPPORTS_SAVE | GAME_IMPERFECT_GRAPHICS ) //world bootleg?
|
||||
GAME( 1987, terrafb, terraf, terrafb, terraf, terrafb, ROT0, "bootleg", "Terra Force (Japan bootleg with additional Z80)", GAME_SUPPORTS_SAVE | GAME_IMPERFECT_GRAPHICS )
|
||||
GAME( 1987, terrafa, terraf, terraf, terraf, terrafu, ROT0, "Nichibutsu", "Terra Force (Japan set 2)", GAME_SUPPORTS_SAVE | GAME_IMPERFECT_GRAPHICS | GAME_UNEMULATED_PROTECTION )
|
||||
GAME( 1987, terrafa, terraf, terraf, terraf, terrafu, ROT0, "Nichibutsu", "Terra Force (set 2)", GAME_SUPPORTS_SAVE | GAME_IMPERFECT_GRAPHICS | GAME_UNEMULATED_PROTECTION ) //world?
|
||||
GAME( 1987, terrafu, terraf, terraf, terraf, terrafu, ROT0, "Nichibutsu USA", "Terra Force (US)", GAME_SUPPORTS_SAVE | GAME_IMPERFECT_GRAPHICS | GAME_UNEMULATED_PROTECTION )
|
||||
GAME( 1987, kodure, 0, kodure, kodure, kodure, ROT0, "Nichibutsu", "Kodure Ookami (Japan)", GAME_SUPPORTS_SAVE | GAME_IMPERFECT_GRAPHICS | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING )
|
||||
GAME( 1988, cclimbr2, 0, cclimbr2, cclimbr2, cclimbr2, ROT0, "Nichibutsu", "Crazy Climber 2 (Japan)", GAME_SUPPORTS_SAVE )
|
||||
|
@ -332,7 +332,7 @@ SCREEN_UPDATE( armedf )
|
||||
tilemap_set_enable(state->m_fg_tilemap, state->m_vreg & 0x400);
|
||||
tilemap_set_enable(state->m_tx_tilemap, state->m_vreg & 0x100);
|
||||
|
||||
if ((state->m_scroll_type == 0)||(state->m_scroll_type == 5 ))
|
||||
if ((state->m_scroll_type == 5 ))
|
||||
{
|
||||
if (state->m_old_mcu_mode != state->m_vreg)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user