02644: tdragon, tdragon1, hachamf: Coin counter doesn't decrease [Angelo Salese]

This commit is contained in:
Angelo Salese 2009-01-04 22:18:12 +00:00
parent 413ba46a0e
commit 5fabf88271
2 changed files with 164 additions and 145 deletions

View File

@ -46,23 +46,10 @@ TODO:
Therefore, it might be another protection device, which sits in the middle
between CPU and NMK004.
- Protection is patched in several games.
- In hachamf it seems that the protection device shares some RAM (fe000-fefff)
with the main CPU, and the main CPU fetches pointers from that shared RAM to
do important operations like reading the input ports. Some of them are easily
deduced checking for similarities in macross and bjtwin; however another
protection check involves (see the routine at 01429a) writing data to the
fe100-fe1ff range, and then jumping to subroutines in that range (most likely
function pointers since each one is only 0x10 bytes long), and heaven knows
what those should do.
On startup, hachamf does a RAM test, then copies some stuff and jumps to
RAM at 0xfef00, where it sits in a loop. We patch around that by replacing the
reset vector with the "real" one.
update: simulated this,see hachamf_mcu_shared_w() & tdragon_mcu_shared_w() for
more info about it.
- Hacha Mecha Fighter bg graphics are completely wrong except at the title screen &
- Hacha Mecha Fighter: mcu simulation *might* be wrong/incorrect (see notes).
- Hacha Mecha Fighter: bg graphics are completely wrong except at the title screen &
the level 7.Likely to be a rom issue,the game activates the bgbank
when it is on the above two cases.Also the bomb graphics are wrong when the game
is in japanese mode...
when it is on the above two cases.
- Cocktail mode is supported, but tilemap.c has problems with asymmetrical
visible areas.
- Music timing in nouryoku is a little off.
@ -72,6 +59,9 @@ TODO:
- Input ports in Bio-ship Paladin, Strahl
- Sound communication in Mustang might be incorrectly implemented
- Incorrect OKI samples banking in Rapid Hero
- Hacha Mecha Fighter: (BTANB) the bomb graphics are pretty weird when the game is in
japanese mode,but it's like this on the original game,it's just a japanese write for
"bomb" word (I presume)
----
@ -547,14 +537,15 @@ ADDRESS_MAP_END
Thunder Dragon & Hacha Mecha Fighter shares some ram with the MCU,the job of the latter
is to provide some jsr vectors used by the game for gameplay calculations.Also it has
the job to give the vectors of where the inputs are to be read & to calculate the coin
settings,the latter is in the video file to avoid sync problems.
settings,the latter is in a TIMER_DEVICE_CALLBACK to avoid sync problems.
To make a long story short,this MCU is an alternative version of the same protection
used by the MJ-8956 games (there are even the same kind of error codes!(i.e the number
printed on the up-left corner of the screen)...
Note: I'm 100% sure of the Thunder Dragon vectors because I've compared it with the
bootleg sets,I'm *not* 100% sure of the Hacha Mecha Fighter vectors because I don't have
anything to compare,infact
anything to compare and I don't know if for example an option should be there if you lose a
life,but the game looks pretty much hard without it.
******************************************************************************************/
@ -701,7 +692,6 @@ static WRITE16_HANDLER( hachamf_mainram_w )
}
}
static ADDRESS_MAP_START( hachamf_map, ADDRESS_SPACE_PROGRAM, 16 )
AM_RANGE(0x000000, 0x03ffff) AM_ROM
/* I/O Region */
@ -779,6 +769,157 @@ static WRITE16_HANDLER( tdragon_mainram_w )
}
}
/*coin setting MCU simulation*/
static void mcu_run(running_machine *machine, UINT8 dsw_setting)
{
static UINT8 input_pressed;
static UINT16 coin_input;
UINT8 dsw[2];
static UINT8 start_helper = 0;
static UINT8 coin_count[2],coin_count_frac[2];
static UINT8 i;
/*Accept the start button but needs some m68k processing first,otherwise you can't start a play with 1 credit inserted*/
if(start_helper & 1 && nmk16_mainram[0x9000/2] & 0x0200) /*start 1 */
{
nmk16_mainram[0xef00/2]--;
start_helper = start_helper & 2;
}
if(start_helper & 2 && nmk16_mainram[0x9000/2] & 0x0100) /*start 2*/
{
nmk16_mainram[0xef00/2]--;
start_helper = start_helper & 1;
}
/*needed because of the uncompatibility of the dsw settings.*/
if(dsw_setting) // Thunder Dragon
{
dsw[0] = (input_port_read(machine, "DSW2") & 0x7);
dsw[1] = (input_port_read(machine, "DSW2") & 0x38) >> 3;
for(i=0;i<2;i++)
{
switch(dsw[i] & 7)
{
case 0: nmk16_mainram[0x9000/2]|=0x4000; break; //free play
case 1: coin_count_frac[i] = 1; coin_count[i] = 4; break;
case 2: coin_count_frac[i] = 1; coin_count[i] = 3; break;
case 3: coin_count_frac[i] = 1; coin_count[i] = 2; break;
case 4: coin_count_frac[i] = 4; coin_count[i] = 1; break;
case 5: coin_count_frac[i] = 3; coin_count[i] = 1; break;
case 6: coin_count_frac[i] = 2; coin_count[i] = 1; break;
case 7: coin_count_frac[i] = 1; coin_count[i] = 1; break;
}
}
}
else // Hacha Mecha Fighter
{
dsw[0] = (input_port_read(machine, "DSW1") & 0x0700) >> 8;
dsw[1] = (input_port_read(machine, "DSW1") & 0x3800) >> 11;
for(i=0;i<2;i++)
{
switch(dsw[i] & 7)
{
case 0: nmk16_mainram[0x9000/2]|=0x4000; break; //free play
case 1: coin_count_frac[i] = 4; coin_count[i] = 1; break;
case 2: coin_count_frac[i] = 3; coin_count[i] = 1; break;
case 3: coin_count_frac[i] = 2; coin_count[i] = 1; break;
case 4: coin_count_frac[i] = 1; coin_count[i] = 4; break;
case 5: coin_count_frac[i] = 1; coin_count[i] = 3; break;
case 6: coin_count_frac[i] = 1; coin_count[i] = 2; break;
case 7: coin_count_frac[i] = 1; coin_count[i] = 1; break;
}
}
}
/*read the coin port*/
coin_input = (~(input_port_read(machine, "IN0")));
if(coin_input & 0x01)//coin 1
{
if((input_pressed & 0x01) == 0)
{
if(coin_count_frac[0] != 1)
{
nmk16_mainram[0xef02/2]+=coin_count[0];
if(coin_count_frac[0] == nmk16_mainram[0xef02/2])
{
nmk16_mainram[0xef00/2]+=coin_count[0];
nmk16_mainram[0xef02/2] = 0;
}
}
else
nmk16_mainram[0xef00/2]+=coin_count[0];
}
input_pressed = (input_pressed & 0xfe) | 1;
}
else
input_pressed = (input_pressed & 0xfe);
if(coin_input & 0x02)//coin 2
{
if((input_pressed & 0x02) == 0)
{
if(coin_count_frac[1] != 1)
{
nmk16_mainram[0xef02/2]+=coin_count[1];
if(coin_count_frac[1] == nmk16_mainram[0xef02/2])
{
nmk16_mainram[0xef00/2]+=coin_count[1];
nmk16_mainram[0xef02/2] = 0;
}
}
else
nmk16_mainram[0xef00/2]+=coin_count[1];
}
input_pressed = (input_pressed & 0xfd) | 2;
}
else
input_pressed = (input_pressed & 0xfd);
if(coin_input & 0x04)//service 1
{
if((input_pressed & 0x04) == 0)
nmk16_mainram[0xef00/2]++;
input_pressed = (input_pressed & 0xfb) | 4;
}
else
input_pressed = (input_pressed & 0xfb);
/*The 0x9000 ram address is the status */
if(nmk16_mainram[0xef00/2] > 0 && nmk16_mainram[0x9000/2] & 0x8000) //enable start button
{
if(coin_input & 0x08)//start 1
{
if((input_pressed & 0x08) == 0 && (!(nmk16_mainram[0x9000/2] & 0x0200))) //start 1
start_helper = 1;
input_pressed = (input_pressed & 0xf7) | 8;
}
else
input_pressed = (input_pressed & 0xf7);
if(coin_input & 0x10)//start 2
{
/*Decrease two coins to let two players play with one start 2 button and two credits inserted at the insert coin screen.*/
if((input_pressed & 0x10) == 0 && (!(nmk16_mainram[0x9000/2] & 0x0100))) // start 2
start_helper = (nmk16_mainram[0x9000/2] == 0x8000) ? (3) : (2);
input_pressed = (input_pressed & 0xef) | 0x10;
}
else
input_pressed = (input_pressed & 0xef);
}
}
static TIMER_DEVICE_CALLBACK( tdragon_mcu_sim )
{
mcu_run(timer->machine,1);
}
static TIMER_DEVICE_CALLBACK( hachamf_mcu_sim )
{
mcu_run(timer->machine,0);
}
static ADDRESS_MAP_START( tdragon_readmem, ADDRESS_SPACE_PROGRAM, 16 )
AM_RANGE(0x000000, 0x03ffff) AM_READ(SMH_ROM)
@ -3903,6 +4044,7 @@ static MACHINE_DRIVER_START( tdragon )
MDRV_VIDEO_START(macross)
MDRV_VIDEO_EOF(nmk)
MDRV_VIDEO_UPDATE(tdragon)
MDRV_TIMER_ADD_PERIODIC("coinsim", tdragon_mcu_sim, HZ(10000)) // not real, but for simulating the MCU
/* sound hardware */
MDRV_SPEAKER_STANDARD_MONO("mono")
@ -4029,6 +4171,7 @@ static MACHINE_DRIVER_START( hachamf )
MDRV_VIDEO_START(macross)
MDRV_VIDEO_EOF(nmk)
MDRV_VIDEO_UPDATE(hachamf)
MDRV_TIMER_ADD_PERIODIC("coinsim", hachamf_mcu_sim, HZ(10000)) // not real, but for simulating the MCU
/* sound hardware */
MDRV_SPEAKER_STANDARD_MONO("mono")

View File

@ -543,133 +543,9 @@ VIDEO_UPDATE( macross )
return 0;
}
/*coin setting MCU simulation*/
static void mcu_run(running_machine *machine, UINT8 dsw_setting)
{
static UINT8 read_coin;
static UINT8 old_value;
static UINT8 coina,coinb;
UINT8 dsw_a,dsw_b;
/*needed because of the uncompatibility of the dsw settings.*/
if(dsw_setting)
{
dsw_a = (input_port_read(machine, "DSW2") & 0x7);
dsw_b = (input_port_read(machine, "DSW2") & 0x38) >> 3;
}
else
{
dsw_a = (input_port_read(machine, "DSW1") & 0x0700) >> 8;
dsw_b = (input_port_read(machine, "DSW1") & 0x3800) >> 11;
}
read_coin = old_value;
old_value = input_port_read(machine, "IN0");
if(dsw_a == 0 || dsw_b == 0)
nmk16_mainram[0x9000/2]|=0x4000; //free_play
if(read_coin != old_value)
{
if(!(input_port_read(machine, "IN0") & 0x01))//COIN1
{
switch(dsw_a & 7)
{
case 1: nmk16_mainram[0xef00/2]+=4; break;
case 2: nmk16_mainram[0xef00/2]+=3; break;
case 3: nmk16_mainram[0xef00/2]+=2; break;
case 4:
coina++;
if(coina >= 4)
{
coina = 0;
nmk16_mainram[0xef00/2]++;
}
break;
case 5:
coina++;
if(coina >= 3)
{
coina = 0;
nmk16_mainram[0xef00/2]++;
}
break;
case 6:
coina++;
if(coina >= 2)
{
coina = 0;
nmk16_mainram[0xef00/2]++;
}
break;
case 7: nmk16_mainram[0xef00/2]++; break;
}
}
if(!(input_port_read(machine, "IN0") & 0x02))//COIN2
{
switch(dsw_b & 7)
{
case 1: nmk16_mainram[0xef00/2]+=4; break;
case 2: nmk16_mainram[0xef00/2]+=3; break;
case 3: nmk16_mainram[0xef00/2]+=2; break;
case 4:
coinb++;
if(coinb >= 4)
{
coinb = 0;
nmk16_mainram[0xef00/2]++;
}
break;
case 5:
coinb++;
if(coinb >= 3)
{
coinb = 0;
nmk16_mainram[0xef00/2]++;
}
break;
case 6:
coinb++;
if(coinb >= 2)
{
coinb = 0;
nmk16_mainram[0xef00/2]++;
}
break;
case 7: nmk16_mainram[0xef00/2]++; break;
}
}
if(!(input_port_read(machine, "IN0") & 0x04)) //SERVICE_COIN
nmk16_mainram[0xef00/2]++;
if(nmk16_mainram[0xef00/2] >= 1 && (nmk16_mainram[0x9000/2] & 0x8000))/*enable start button*/
{
/*Start a 1-player game,but don't decrement if the player 1 is already playing*/
if((!(input_port_read(machine, "IN0") & 0x08)) /*START1*/
&& (!(nmk16_mainram[0x9000/2] & 0x0200)) /*PLAYER-1 playing*/
)
nmk16_mainram[0xef00/2]--;
/*Start a 2-players game,but don't decrement if the player 2 is already playing*/
if((!(input_port_read(machine, "IN0") & 0x10))
&& (!(nmk16_mainram[0x9000/2] & 0x0100))
)
{
if(!(nmk16_mainram[0x9000/2] & 0x0200) && nmk16_mainram[0xef00/2] >= 2)
nmk16_mainram[0xef00/2]-=2;
else
nmk16_mainram[0xef00/2]--;
}
}
if(nmk16_mainram[0xef00/2] > 99) nmk16_mainram[0xef00/2] = 99;
}
}
VIDEO_UPDATE( tdragon )
{
mcu_run(screen->machine, 1);
// mcu_run(screen->machine, 1);
tilemap_set_scrollx(tx_tilemap,0,-videoshift);
@ -686,7 +562,7 @@ VIDEO_UPDATE( tdragon )
VIDEO_UPDATE( hachamf )
{
mcu_run(screen->machine, 0);
// mcu_run(screen->machine, 0);
tilemap_set_scrollx(tx_tilemap,0,-videoshift);