/******************************************************************************/
/* */
/* TAITO K-SYSTEM (C) 1986 TAITO CORPORATION */
/* */
/* Z80+Z80+YM2203+M68705 */
/* NOTE: K-SYSTEM is not the official name. */
/* */
/******************************************************************************/
#include "gameinc.h"
#include "ksystem.h"
#include "tc220ioc.h"
#include "taitosnd.h"
#include "2203intf.h"
#include "decode.h"
#include "sasound.h" // sample support routines
#include "emumain.h"
#include "blit.h" // clear_game_screen
/*
Z80 x 2
M68705 x 1
YM2203 x 1
TC0010VCU x 1
*/
/*
changes/kayamon:
15/2/00:
- fixed Kick&Run at last, now it works properly =)
- undid antiriad's amazing F018 bullshit ;-)
now it works again, assuming MZ80 has been fixed.
NOTE: it's what we in the trade technically call a 'WATCHDOG'... :P
- renamed kickrun to kicknrun for general MAME compatibilty
30/8/99:
- added Knight Boy, dunno if it was worth it though.
- NOTE: MCU is tested for KKK, seems to be 100%, so any problems are
most likely due to the rest of the hardware instead.
- rewrote video h/w, based on Bubble Bobble.
- *** KICK&RUN not tested at all!!!!!!!!!!!
Not one bit. DIPs are wrong, etc
(probably doesn't work at all) ***
- MEXICO86 needs adding here too...
- had a go at that SOLID_MASK type stuff, hope it's right.
- added some more DIPs and stuff.
- overclocked main CPU, to avoid MZ80 IFF1 bug.
NOTE: I think the latest MZ80 fixes this itself.
- renamed driver to K-SYSTEM.
- added proper MCU emulation (hah, yeah right).
- fiddled DIPs/inputs about to work.
changes/antiriad:
- redid the speed hack, so they actually work ;). also hooked up F018 as
an interrupt request. it's probably some kind of vsync/waitvbl request.
- increased the cpu slices, because the main cpu was spending a lot of
time waiting for the sub cpu. i also put the main cpu back to 8mhz, I
can't see any problem yet, probably the use of F018 now prevents the
bug showing up (mz80 3.0 will fix iff1 bugs anyway).
- bank switching without memcpy :).
- fiddle with the gfx but didn't fix anything (monster priority is wrong,
if you render everything in reverse, the monsters are right, but not
much else).
*/
static struct DIR_INFO kick_and_run_dirs[] =
{
{ "kick_and_run", },
{ "kicknrun", },
{ NULL, },
};
static struct ROM_INFO kick_and_run_roms[] =
{
{ "a87-02.bin", 0x00008000, 0x64f1a85f, 0, 0, 0, },
{ "a87-03.bin", 0x00010000, 0xf42e8a88, 0, 0, 0, },
{ "a87-04.bin", 0x00008000, 0x8b438d20, 0, 0, 0, },
{ "a87-05.bin", 0x00010000, 0x4eee3a8a, 0, 0, 0, },
{ "a87-06.bin", 0x00008000, 0x1625b587, 0, 0, 0, },
{ "a87-07.bin", 0x00010000, 0x6cb6ebfe, 0, 0, 0, },
{ "a87-08.bin", 0x00010000, 0x715e1b04, 0, 0, 0, },
{ "a87-10.bin", 0x00000100, 0xbe6eb1f0, 0, 0, 0, },
{ "a87-11.bin", 0x00000100, 0x14f6c28d, 0, 0, 0, },
{ "a87-12.bin", 0x00000100, 0x3e953444, 0, 0, 0, },
{ "68_h.bin", 0x00000800, 0xff92f816, 0, 0, 0, },
{ NULL, 0, 0, 0, 0, 0, },
};
static struct INPUT_INFO kick_and_run_inputs[] =
{
{ KB_DEF_COIN1, MSG_COIN1, 0x020005, 0x01, BIT_ACTIVE_0 },
{ KB_DEF_COIN2, MSG_COIN2, 0x020005, 0x02, BIT_ACTIVE_0 },
{ KB_DEF_TILT, MSG_TILT, 0x020000, 0x04, BIT_ACTIVE_0 },
{ KB_DEF_SERVICE, MSG_SERVICE, 0x020000, 0x01, BIT_ACTIVE_0 },
{ KB_DEF_P1_START, MSG_P1_START, 0x020000, 0x08, BIT_ACTIVE_0 },
{ KB_DEF_P1_UP, MSG_P1_UP, 0x020001, 0x01, BIT_ACTIVE_0 },
{ KB_DEF_P1_DOWN, MSG_P1_DOWN, 0x020001, 0x02, BIT_ACTIVE_0 },
{ KB_DEF_P1_LEFT, MSG_P1_LEFT, 0x020001, 0x04, BIT_ACTIVE_0 },
{ KB_DEF_P1_RIGHT, MSG_P1_RIGHT, 0x020001, 0x08, BIT_ACTIVE_0 },
{ KB_DEF_P1_B1, MSG_P1_B1, 0x020001, 0x10, BIT_ACTIVE_0 },
{ KB_DEF_P1_B2, MSG_P1_B2, 0x020001, 0x20, BIT_ACTIVE_0 },
{ KB_DEF_P2_START, MSG_P2_START, 0x020000, 0x10, BIT_ACTIVE_0 },
{ KB_DEF_P2_UP, MSG_P2_UP, 0x020002, 0x01, BIT_ACTIVE_0 },
{ KB_DEF_P2_DOWN, MSG_P2_DOWN, 0x020002, 0x02, BIT_ACTIVE_0 },
{ KB_DEF_P2_LEFT, MSG_P2_LEFT, 0x020002, 0x04, BIT_ACTIVE_0 },
{ KB_DEF_P2_RIGHT, MSG_P2_RIGHT, 0x020002, 0x08, BIT_ACTIVE_0 },
{ KB_DEF_P2_B1, MSG_P2_B1, 0x020002, 0x10, BIT_ACTIVE_0 },
{ KB_DEF_P2_B2, MSG_P2_B2, 0x020002, 0x20, BIT_ACTIVE_0 },
{ 0, NULL, 0, 0, 0 },
};
static struct DSW_DATA dsw_data_kick_and_run_0[] =
{
{ MSG_DSWA_BIT1, 0x01, 0x02 },
{ MSG_OFF, 0x01, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ MSG_DSWA_BIT2, 0x02, 0x02 },
{ MSG_OFF, 0x02, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ MSG_DSWA_BIT3, 0x04, 0x02 },
{ MSG_OFF, 0x04, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ MSG_DSWA_BIT4, 0x08, 0x02 },
{ MSG_OFF, 0x08, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ MSG_DSWA_BIT5, 0x10, 0x02 },
{ MSG_OFF, 0x10, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ MSG_DSWA_BIT6, 0x20, 0x02 },
{ MSG_OFF, 0x20, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ MSG_DSWA_BIT7, 0x40, 0x02 },
{ MSG_OFF, 0x40, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ MSG_DSWA_BIT8, 0x80, 0x02 },
{ MSG_OFF, 0x80, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ NULL, 0, 0, },
};
static struct DSW_INFO kick_and_run_dsw[] =
{
{ 0x020003, 0xFF, dsw_data_kick_and_run_0 },
{ 0x020004, 0xFF, dsw_data_default_1 },
{ 0, 0, NULL, },
};
static struct VIDEO_INFO kiki_kai_kai_video =
{
DrawKikiKaiKai,
256,
224,
8,
VIDEO_ROTATE_90 |
VIDEO_ROTATABLE,
};
static struct VIDEO_INFO kick_and_run_video =
{
DrawKickRun,
256,
224,
8,
VIDEO_ROTATABLE,
};
static struct YM2203interface ym2203_interface =
{
1,
4000000,
{ 0x00ff20c0 },
{0},
{0},
{0},
{0},
{NULL}
};
static struct SOUND_INFO kiki_kai_kai_sound[] =
{
{ SOUND_YM2203, &ym2203_interface, },
{ 0, NULL, },
};
GAME( kick_and_run ,
kick_and_run_dirs,
kick_and_run_roms,
kick_and_run_inputs,
kick_and_run_dsw,
NULL,
LoadKickRun,
ClearKSystem,
&kick_and_run_video,
ExecuteKSystemFrame,
"kicknrun",
"Kick and Run",
NULL,
COMPANY_ID_TAITO,
"A87",
1986,
kiki_kai_kai_sound,
GAME_SPORTS
);
static struct DIR_INFO kiki_kai_kai_dirs[] =
{
{ "kiki_kai_kai", },
{ "kikikai", },
{ "kikikaik", },
{ NULL, },
};
static struct ROM_INFO kiki_kai_kai_roms[] =
{
{ "a85-08.rom", 0x00000100, 0xd15f61a8, 0, 0, 0, },
{ "a85-09.rom", 0x00000100, 0xb931c94d, 0, 0, 0, },
{ "a85-10.rom", 0x00000100, 0x8fc3fa86, 0, 0, 0, },
{ "a85-11.rom", 0x00008000, 0xcc3539db, 0, 0, 0, },
{ "a85-12.rom", 0x00010000, 0x91e58067, 0, 0, 0, },
{ "a85-13.rom", 0x00010000, 0x3eeaf878, 0, 0, 0, },
{ "a85-14.rom", 0x00010000, 0xa9df0453, 0, 0, 0, },
{ "a85-15.rom", 0x00010000, 0xaebc8c32, 0, 0, 0, },
{ "a85-16.rom", 0x00010000, 0x4094d750, 0, 0, 0, },
{ "a85-17.rom", 0x00010000, 0xc141d5ab, 0, 0, 0, },
{ "knightb.uc", 0x00000800, 0x3cc2bbe4, 0, 0, 0, },
{ NULL, 0, 0, 0, 0, 0, },
};
static struct INPUT_INFO kiki_kai_kai_inputs[] =
{
{ KB_DEF_COIN1, MSG_COIN1, 0x020005, 0x01, BIT_ACTIVE_0 },
{ KB_DEF_COIN2, MSG_COIN2, 0x020005, 0x02, BIT_ACTIVE_0 },
{ KB_DEF_TILT, MSG_TILT, 0x020000, 0x04, BIT_ACTIVE_0 },
{ KB_DEF_SERVICE, MSG_SERVICE, 0x020000, 0x01, BIT_ACTIVE_0 },
{ KB_DEF_P1_START, MSG_P1_START, 0x020000, 0x08, BIT_ACTIVE_0 },
{ KB_DEF_P1_UP, MSG_P1_UP, 0x020001, 0x01, BIT_ACTIVE_0 },
{ KB_DEF_P1_DOWN, MSG_P1_DOWN, 0x020001, 0x02, BIT_ACTIVE_0 },
{ KB_DEF_P1_LEFT, MSG_P1_LEFT, 0x020001, 0x04, BIT_ACTIVE_0 },
{ KB_DEF_P1_RIGHT, MSG_P1_RIGHT, 0x020001, 0x08, BIT_ACTIVE_0 },
{ KB_DEF_P1_B1, MSG_P1_B1, 0x020001, 0x10, BIT_ACTIVE_0 },
{ KB_DEF_P1_B2, MSG_P1_B2, 0x020001, 0x20, BIT_ACTIVE_0 },
{ KB_DEF_P2_START, MSG_P2_START, 0x020000, 0x10, BIT_ACTIVE_0 },
{ KB_DEF_P2_UP, MSG_P2_UP, 0x020002, 0x01, BIT_ACTIVE_0 },
{ KB_DEF_P2_DOWN, MSG_P2_DOWN, 0x020002, 0x02, BIT_ACTIVE_0 },
{ KB_DEF_P2_LEFT, MSG_P2_LEFT, 0x020002, 0x04, BIT_ACTIVE_0 },
{ KB_DEF_P2_RIGHT, MSG_P2_RIGHT, 0x020002, 0x08, BIT_ACTIVE_0 },
{ KB_DEF_P2_B1, MSG_P2_B1, 0x020002, 0x10, BIT_ACTIVE_0 },
{ KB_DEF_P2_B2, MSG_P2_B2, 0x020002, 0x20, BIT_ACTIVE_0 },
{ 0, NULL, 0, 0, 0 },
};
static struct DSW_DATA dsw_data_kiki_kai_kai_0[] =
{
{ "Cabinet", 0x01, 0x02 },
{ "Upright", 0x01, 0x00 },
{ "Table", 0x00, 0x00 },
{ MSG_DSWA_BIT2, 0x02, 0x02 },
{ MSG_OFF, 0x02, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ MSG_TEST_MODE, 0x04, 0x02 },
{ MSG_OFF, 0x04, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ MSG_DEMO_SOUND, 0x08, 0x02 },
{ MSG_ON, 0x08, 0x00 },
{ MSG_OFF, 0x00, 0x00 },
{ MSG_COIN1, 0x30, 0x04 },
{ MSG_1COIN_1PLAY, 0x30, 0x00 },
{ MSG_1COIN_2PLAY, 0x20, 0x00 },
{ MSG_2COIN_1PLAY, 0x10, 0x00 },
{ MSG_2COIN_3PLAY, 0x00, 0x00 },
{ MSG_COIN2, 0xC0, 0x04 },
{ MSG_1COIN_1PLAY, 0xC0, 0x00 },
{ MSG_1COIN_2PLAY, 0x80, 0x00 },
{ MSG_2COIN_1PLAY, 0x40, 0x00 },
{ MSG_2COIN_3PLAY, 0x00, 0x00 },
{ NULL, 0, 0, },
};
static struct DSW_DATA dsw_data_kiki_kai_kai_1[] =
{
{ MSG_DIFFICULTY, 0x03, 0x04 },
{ MSG_NORMAL, 0x03, 0x00 },
{ MSG_EASY, 0x02, 0x00 },
{ MSG_HARD, 0x01, 0x00 },
{ MSG_HARDEST, 0x00, 0x00 },
{ "Extra Life", 0x0C, 0x04 },
{ "70k 150k", 0x0C, 0x00 },
{ "70k 200k", 0x08, 0x00 },
{ "100k 300k", 0x04, 0x00 },
{ "50k 100k", 0x00, 0x00 },
{ "Lives", 0x30, 0x04 },
{ "3", 0x30, 0x00 },
{ "4", 0x20, 0x00 },
{ "5", 0x10, 0x00 },
{ "2", 0x00, 0x00 },
{ "Unknown", 0x40, 0x02 },
{ MSG_OFF, 0x40, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ "Number Match", 0x80, 0x02 },
{ MSG_OFF, 0x80, 0x00 },
{ MSG_ON, 0x00, 0x00 },
{ NULL, 0, 0, },
};
static struct DSW_INFO kiki_kai_kai_dsw[] =
{
{ 0x020003, 0xFF, dsw_data_kiki_kai_kai_0 },
{ 0x020004, 0xFF, dsw_data_kiki_kai_kai_1 },
{ 0, 0, NULL, },
};
GAME( kiki_kai_kai ,
kiki_kai_kai_dirs,
kiki_kai_kai_roms,
kiki_kai_kai_inputs,
kiki_kai_kai_dsw,
NULL,
LoadKikiKaiKai,
ClearKSystem,
&kiki_kai_kai_video,
ExecuteKSystemFrame,
"kikikai",
"Kiki Kai Kai",
NULL,
COMPANY_ID_TAITO,
"A85",
1986,
kiki_kai_kai_sound,
GAME_PLATFORM
);
static struct DIR_INFO knight_boy_dirs[] =
{
{ "knight_boy", },
{ "knightb", },
{ ROMOF("kikikai"), },
{ CLONEOF("kikikai"), },
{ NULL, },
};
static struct ROM_INFO knight_boy_roms[] =
{
{ "a85-10.rom", 0x00000100, 0x8fc3fa86, 0, 0, 0, },
{ "a85-09.rom", 0x00000100, 0xb931c94d, 0, 0, 0, },
{ "a85-08.rom", 0x00000100, 0xd15f61a8, 0, 0, 0, },
{ "a85-11.rom", 0x00008000, 0xcc3539db, 0, 0, 0, },
{ "a85-12.rom", 0x00010000, 0x91e58067, 0, 0, 0, },
{ "knightb.b", 0x00010000, 0x63ad7df3, 0, 0, 0, },
{ "a85-14.rom", 0x00010000, 0xa9df0453, 0, 0, 0, },
{ "knightb.d", 0x00010000, 0x53ecdb3f, 0, 0, 0, },
{ "a85-16.rom", 0x00010000, 0x4094d750, 0, 0, 0, },
{ "a85-17.rom", 0x00010000, 0xc141d5ab, 0, 0, 0, },
{ "knightb.uc", 0x00000800, 0x3cc2bbe4, 0, 0, 0, },
{ NULL, 0, 0, 0, 0, 0, },
};
GAME( knight_boy ,
knight_boy_dirs,
knight_boy_roms,
kiki_kai_kai_inputs,
kiki_kai_kai_dsw,
NULL,
LoadKnightBoy,
ClearKSystem,
&kiki_kai_kai_video,
ExecuteKSystemFrame,
"knightb",
"Knight Boy",
NULL,
COMPANY_ID_BOOTLEG,
NULL,
1986,
kiki_kai_kai_sound,
GAME_PLATFORM
);
static int romset;
static UINT8 *RAM2;
static UINT8 *ROM2;
static UINT8 *RAM_INPUT;
static UINT8 *RAM_COLOUR;
static UINT8 *RAM_MCU;
static UINT8 *GFX_BG0_SOLID;
/*
TAITO K-SYSTEM
--------------
0000-7FFF BASE ROM
8000-BFFF BANK ROM
D800-EFFF RAM
F000-F000 BANK SWITCH
F008-F008 MCU ENABLE?
F010-F010 INPUT READ
F018-F018 WATCHDOG
C000-FFFF <misc>
C500-CCFF SPRITE TILE RAM
CD00-D4FF BG0 RAM
D500-D501 BG0 SCROLL X
D502-D503 BG0 SCROLL Y
---
0000-7FFF BASE ROM
8000-9FFF COMMUNICATE RAM
C000-C001 YM2203
Supported romsets:
0 - B36 - Kiki Kai Kai - 1986
1 - A87 - Kick and Run - 1985
- Hardware info courtesy of Carl/DSC [Antiriad].
Todo:
- Graphics glitches: Shadows under monsters look like they might be in the
wrong priority... hmm..
- Player 2 inputs don't work in KKK?? (work in test mode, not in game).
Could be do to with writes to 0xffff...
Works in 'Table' mode, but using P1 inputs.
- I think this H/W has a system to connect 2 boards together...
*/
/******************************************************************************/
/* K-SYSTEM Z80 ROM BANKING */
/******************************************************************************/
static UINT8 Z80Bank, gfx_bank;
static UINT8 bank_map[8] =
{
4,5,6,7,2,3,0,1,
};
void KSystemNewBankWrite(UINT16 offset, UINT8 data)
{
if(bank_map[data&7] != Z80Bank){
Z80Bank = bank_map[data&7];
z80_set_bank(1,Z80Bank);
}
gfx_bank = (data & 0x20) >> 5;
}
static void init_bank_rom(UINT8 *src, UINT8 *dst)
{
z80_init_banks_area_ofs(1,src,0x20000,0x8000,0x4000,2);
}
/******************************************************************************/
/* K-SYSTEM COMMON RAM */
/******************************************************************************/
#if 0
// Unused functions !
static void KSystemCommonRAMWrite(UINT16 offset, UINT8 data)
{
RAM[0xC000+(offset&0x1FFF)] = data;
}
static UINT8 KSystemCommonRAMRead(UINT16 offset)
{
return RAM[0xC000+(offset&0x1FFF)];
}
#endif
/******************************************************************************/
/* K-SYSTEM MCU */
/******************************************************************************/
static int mcu_enable;
static UINT8 mcu_addr, mcu_latch, mcu_old_data;
static void KSystemMCUWrite(UINT16 offset, UINT8 data)
{
offset&=0xFF;
#ifdef RAINE_DEBUG
//print_debug("MCU Write: %02x:%02x [%04x]\n", offset, data, z80pc);
#endif
RAM[offset+0xE800] = data;
}
static UINT8 KSystemMCURead(UINT16 offset)
{
offset&=0xFF;
#ifdef RAINE_DEBUG
//print_debug("MCU Read: %02x:?? [%04x]\n", offset, z80pc);
#endif
return RAM[offset+0xE800];
}
void KikiKaiKai_mcu(int bih_count);
void KikiKaiKai_mcu_reset(void);
void KickRun_mcu(int bih_count);
void KickRun_mcu_reset(void);
UINT8 KSystem_MCU_RDMEM(int a)
{
//print_debug("MCU RDMEM(0x%x)=%x\n", a, RAM_MCU[a]);
if (a == 0x02) /* Port C - COIN,TILT,etc */
{
return RAM_INPUT[5];
}
return RAM_MCU[a];
}
void KSystem_MCU_WRMEM(int a, UINT8 v)
{
UINT8 rising,falling;
//print_debug("MCU WRMEM(0x%x,0x%x)\n", a, v);
RAM_MCU[a] = v;
if (a == 0x01) /* I/O control */
{
rising = (v ^ mcu_old_data) & v; /* only the rising-edge triggers these */
falling = (v ^ mcu_old_data) & mcu_old_data; /* only the falling-edge triggers these */
mcu_old_data = v;
if (falling & 0x01) RAM_MCU[0x00] = mcu_latch;
if (rising & 0x02) mcu_addr = RAM_MCU[0x00];
if (falling & 0x08)
{
if (v & 0x10) /* read */
{
if (v & 4) /* System RAM */
{
mcu_latch = RAM[0xe800 + mcu_addr];
} else {
mcu_latch = RAM_INPUT[mcu_addr+1];
}
} else { /* write */
if (v & 4) /* System RAM */
{
RAM[0xe800 + mcu_addr] = RAM_MCU[0x00];
} else {
print_debug("INPUT WRITE!!?! (%x)\n", mcu_addr);
}
}
}
//if (falling & 0x20) mz80int(0xff);
}
}
static void KSystemF008Write(UINT16 offset, UINT8 data)
{
print_debug("MCU control: %04x:%02x [%04x]\n", offset, data, z80pc);
// Just a hack for the MCU
if(data == 0x1e)
mcu_enable = 1;
else
mcu_enable = 0;
}
/******************************************************************************/
/* K-SYSTEM INPUT RAM */
/******************************************************************************/
static void KSystemInputWrite(UINT16 offset, UINT8 data)
{
print_debug("Input Write: %04x:%02x [%04x]\n", offset, data, z80pc);
}
static UINT8 KSystemInputRead(UINT16 offset)
{
return RAM_INPUT[0];
}
/******************************************************************************/
/* K-SYSTEM YM2203 AND DSW ACCESS */
/******************************************************************************/
static UINT8 ksys_ym2203_reg;
static UINT8 KSystemYM2203Read(UINT16 offset)
{
//print_debug("YM2203 RB:%04x/?? [%04x]\n", offset, z80pc);
if((offset&1)==0){
return 0; //YM2203_status_port_0_r(0);
}
else{
switch(ksys_ym2203_reg){
case 0x0e: return get_dsw(0);
case 0x0f: return get_dsw(1);
default: return 0; //return YM2203_read_port_0_r(0);
}
}
}
static void KSystemYM2203Write(UINT16 offset, UINT8 data)
{
//print_debug("YM2203 WB:%04x/%02x [%04x]\n", offset, data, z80pc);
if((offset&1)==0){
ksys_ym2203_reg = data;
}
else{
YM2203_control_port_0_w(0,ksys_ym2203_reg);
YM2203_write_port_0_w(1,data);
}
}
/******************************************************************************/
static void DrawNibble0(UINT8 *out, UINT32 plane, UINT8 c)
{
int count, t;
count = 4;
do {
t = c & 1;
*out = t << plane;
out++;
c >>= 1;
} while(--count);
}
static void DrawNibble(UINT8 *out, UINT32 plane, UINT8 c)
{
int count, t;
count = 4;
do {
t = c & 1;
*out |= t << plane;
out++;
c >>= 1;
} while(--count);
}
void LoadKikiKaiKai(void)
{
int ta,tb,tc,td;
UINT8 *TMP;
romset=0;
mcu_enable=0;
RAMSize=0x10000+0x10000+0x10+0x200+0x800;
if(!(ROM2=AllocateMem(0x8000))) return;
if(!(RAM=AllocateMem(RAMSize))) return;
RAM2 = RAM+0x10000;
RAM_INPUT = RAM+0x10000+0x10000;
RAM_COLOUR = RAM+0x10000+0x10000+0x10;
RAM_MCU = RAM+0x10000+0x10000+0x10+0x200;
if(!(TMP=AllocateMem(0x20000))) return;
if(!load_rom("a85-17.rom",TMP+0x00000,0x10000)) return; // Z80 MAIN ROM
if(!load_rom("a85-16.rom",TMP+0x10000,0x10000)) return; // Z80 MAIN ROM
// Fix Checksum
TMP[0x485a]=0xC9; // RET
// Skip Idle Z80
TMP[0x0503]=0x28; // JR Z,#0508
TMP[0x0504]=0x03; //
TMP[0x0505]=0xD3; // OUTA (AAh)
TMP[0x0506]=0xAA; //
SetStopZ80BMode2(0x04FF);
init_bank_rom(TMP,ROM);
memset(RAM+0x00000, 0x00, RAMSize);
memcpy(RAM, TMP, 0x8000+0x4000);
AddZ80BROMBase(RAM, 0x0038, 0x0066);
AddZ80BReadByte(0x0000, 0xBFFF, NULL, NULL); // Z80 ROM/BANK ROM
AddZ80BReadByte(0xC000, 0xE7FF, NULL, RAM+0xC000); // RAM
AddZ80BReadByte(0xE800, 0xE8FF, KSystemMCURead, NULL); // MCU COMM AREA
AddZ80BReadByte(0xE900, 0xEFFF, NULL, RAM+0xE900); // RAM
AddZ80BReadByte(0xF010, 0xF010, KSystemInputRead, NULL); // INPUT
AddZ80BReadByte(0x0000, 0xFFFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80BReadByte(-1, -1, NULL, NULL);
AddZ80BWriteByte(0xC000, 0xE7FF, NULL, RAM+0xC000); // RAM
AddZ80BWriteByte(0xE800, 0xE8FF, KSystemMCUWrite, NULL); // MCU COMM AREA
AddZ80BWriteByte(0xE900, 0xEFFF, NULL, RAM+0xE900); // RAM
AddZ80BWriteByte(0xF000, 0xF000, KSystemNewBankWrite, NULL); // ROM BANK
AddZ80BWriteByte(0xF008, 0xF008, KSystemF008Write, NULL); // MCU??
AddZ80BWriteByte(0xF010, 0xF010, KSystemInputWrite, NULL); // INPUT
AddZ80BWriteByte(0xF018, 0xF018, NULL, RAM+0xF018); // WATCHDOG
AddZ80BWriteByte(0x0000, 0xFFFF, DefBadWriteZ80, NULL); // <bad writes>
AddZ80BWriteByte(-1, -1, NULL, NULL);
AddZ80BReadPort(0x00, 0xFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80BReadPort(-1, -1, NULL, NULL);
AddZ80BWritePort(0xAA, 0xAA, StopZ80BMode2, NULL); // Trap Idle Z80
AddZ80BWritePort(0x00, 0xFF, DefBadWriteZ80, NULL); // <bad reads>
AddZ80BWritePort(-1, -1, NULL, NULL);
AddZ80BInit();
FreeMem(TMP);
if(!load_rom("a85-11.rom",ROM2,0x8000)) return; // Z80 SUB ROM
// Skip Idle Z80
// -------------
ROM2[0x007F]=0x00; // NOP
ROM2[0x0080]=0x00; // NOP
ROM2[0x00BE]=0xC3; // JP 00A4
ROM2[0x00BF]=0xA4; //
ROM2[0x00C0]=0x00; //
ROM2[0x009C]=0x1A; //
ROM2[0x009D]=0x32; //
ROM2[0x009E]=0xFD; //
ROM2[0x009F]=0x9F; //
ROM2[0x00A0]=0x36; //
ROM2[0x00A1]=0x0F; //
ROM2[0x00A2]=0x18; //
ROM2[0x00A3]=0x10; //
ROM2[0x00A4]=0xD3; // OUTA (AAh)
ROM2[0x00A5]=0xAA; //
ROM2[0x00A6]=0x7E; //
ROM2[0x00A7]=0xFE; //
ROM2[0x00A8]=0xFF; //
ROM2[0x00A9]=0x28; //
ROM2[0x00AA]=0xF9; //
ROM2[0x00AB]=0xC3; //
ROM2[0x00AC]=0xC3; //
ROM2[0x00AD]=0x00; //
SetStopZ80CMode2(0x00A6);
memset(RAM2+0x00000, 0x00, 0x10000);
memcpy(RAM2, ROM2, 0x8000);
AddZ80CROMBase(RAM2, 0x0038, 0x0066);
AddZ80CReadByte(0x0000, 0x7FFF, NULL, RAM2+0x0000); // Z80 ROM
AddZ80CReadByte(0x8000, 0x9FFF, NULL, RAM +0xC000); // COMMON RAM
AddZ80CReadByte(0xC000, 0xC001, KSystemYM2203Read, NULL); // YM2203; INPUT
AddZ80CReadByte(0xA800, 0xC7FF, NULL, RAM2+0xA800); // RAM?
AddZ80CReadByte(0x0000, 0xFFFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80CReadByte(-1, -1, NULL, NULL);
AddZ80CWriteByte(0x8000, 0x9FFF, NULL, RAM +0xC000); // COMMON RAM
AddZ80CWriteByte(0xC000, 0xC001, KSystemYM2203Write, NULL); // YM2203; INPUT
AddZ80CWriteByte(0xA800, 0xC7FF, NULL, RAM2+0xA800); // RAM?
AddZ80CWriteByte(0x0000, 0xFFFF, DefBadWriteZ80, NULL); // <bad writes>
AddZ80CWriteByte(-1, -1, NULL, NULL);
AddZ80CReadPort(0x00, 0xFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80CReadPort(-1, -1, NULL, NULL);
AddZ80CWritePort(0xAA, 0xAA, StopZ80CMode2, NULL); // Trap Idle Z80
AddZ80CWritePort(0x00, 0xFF, DefBadWriteZ80, NULL); // <bad reads>
AddZ80CWritePort(-1, -1, NULL, NULL);
AddZ80CInit();
/* MCU ROM */
if(!load_rom("knightb.uc",RAM_MCU,0x800)) return;
if(!(GFX=AllocateMem(0x080000))) return;
if(!(TMP=AllocateMem(0x040000))) return;
tb=0;
if(!load_rom("a85-15.rom", TMP+0x00000, 0x10000)) return;
if(!load_rom("a85-14.rom", TMP+0x10000, 0x10000)) return;
if(!load_rom("a85-13.rom", TMP+0x20000, 0x10000)) return;
if(!load_rom("a85-12.rom", TMP+0x30000, 0x10000)) return;
for(ta=0;ta<0x20000;ta+=2,tb+=8){
DrawNibble0(GFX+tb+0, 0, (UINT8) (TMP[ta+0x00000]&15) );
DrawNibble (GFX+tb+0, 1, (UINT8) (TMP[ta+0x00000]>>4) );
DrawNibble (GFX+tb+0, 2, (UINT8) (TMP[ta+0x20000]&15) );
DrawNibble (GFX+tb+0, 3, (UINT8) (TMP[ta+0x20000]>>4) );
DrawNibble0(GFX+tb+4, 0, (UINT8) (TMP[ta+0x00001]&15) );
DrawNibble (GFX+tb+4, 1, (UINT8) (TMP[ta+0x00001]>>4) );
DrawNibble (GFX+tb+4, 2, (UINT8) (TMP[ta+0x20001]&15) );
DrawNibble (GFX+tb+4, 3, (UINT8) (TMP[ta+0x20001]>>4) );
}
tb=0;
if(!load_rom("a85-08.rom", TMP+0x00000, 0x80)) return;
if(!load_rom("a85-10.rom", TMP+0x00080, 0x80)) return;
if(!load_rom("a85-09.rom", TMP+0x00100, 0x80)) return;
for(ta=0;ta<0x80;ta++,tb+=2){
td = (ta&0x70)|(0x0F-(ta&0x0F));
tc = (TMP[td+0x000]&0x0F)<<8;
tc |= (TMP[td+0x080]&0x0F)<<4;
tc |= (TMP[td+0x100]&0x0F)<<0;
WriteWord(&RAM_COLOUR[tb+0x000],tc);
WriteWord(&RAM_COLOUR[tb+0x100],tc);
}
FreeMem(TMP);
GFX_BG0_SOLID = make_solid_mask_8x8(GFX, 0x2000);
}
void LoadKnightBoy(void)
{
int ta,tb,tc,td;
UINT8 *TMP;
romset=0;
mcu_enable=0;
RAMSize=0x10000+0x10000+0x10+0x200+0x800;
if(!(ROM2=AllocateMem(0x8000))) return;
if(!(RAM=AllocateMem(RAMSize))) return;
RAM2 = RAM+0x10000;
RAM_INPUT = RAM+0x10000+0x10000;
RAM_COLOUR = RAM+0x10000+0x10000+0x10;
RAM_MCU = RAM+0x10000+0x10000+0x10+0x200;
if(!(TMP=AllocateMem(0x20000))) return;
if(!load_rom("a85-17.rom",TMP+0x00000,0x10000)) return; // Z80 MAIN ROM
if(!load_rom("a85-16.rom",TMP+0x10000,0x10000)) return; // Z80 MAIN ROM
// Fix Checksum
TMP[0x485a]=0xC9; // RET
// Skip Idle Z80
TMP[0x0503]=0x28; // JR Z,#0508
TMP[0x0504]=0x03; //
TMP[0x0505]=0xD3; // OUTA (AAh)
TMP[0x0506]=0xAA; //
SetStopZ80BMode2(0x04FF);
init_bank_rom(TMP,ROM);
memset(RAM+0x00000, 0x00, 0x10000);
memcpy(RAM, TMP, 0x8000+0x4000);
AddZ80BROMBase(RAM, 0x0038, 0x0066);
AddZ80BReadByte(0x0000, 0xBFFF, NULL, NULL); // Z80 ROM/BANK ROM
AddZ80BReadByte(0xC000, 0xE7FF, NULL, RAM+0xC000); // RAM
AddZ80BReadByte(0xE800, 0xE8FF, KSystemMCURead, NULL); // MCU COMM AREA
AddZ80BReadByte(0xE900, 0xEFFF, NULL, RAM+0xE900); // RAM
AddZ80BReadByte(0xF010, 0xF010, KSystemInputRead, NULL); // INPUT
AddZ80BReadByte(0x0000, 0xFFFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80BReadByte(-1, -1, NULL, NULL);
AddZ80BWriteByte(0xC000, 0xE7FF, NULL, RAM+0xC000); // RAM
AddZ80BWriteByte(0xE800, 0xE8FF, KSystemMCUWrite, NULL); // MCU COMM AREA
AddZ80BWriteByte(0xE900, 0xEFFF, NULL, RAM+0xE900); // RAM
AddZ80BWriteByte(0xF000, 0xF000, KSystemNewBankWrite, NULL); // ROM BANK
AddZ80BWriteByte(0xF008, 0xF008, KSystemF008Write, NULL); // MCU??
AddZ80BWriteByte(0xF010, 0xF010, KSystemInputWrite, NULL); // INPUT
AddZ80BWriteByte(0xF018, 0xF018, NULL, RAM+0xF018); // WATCHDOG
AddZ80BWriteByte(0x0000, 0xFFFF, DefBadWriteZ80, NULL); // <bad writes>
AddZ80BWriteByte(-1, -1, NULL, NULL);
AddZ80BReadPort(0x00, 0xFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80BReadPort(-1, -1, NULL, NULL);
AddZ80BWritePort(0xAA, 0xAA, StopZ80BMode2, NULL); // Trap Idle Z80
AddZ80BWritePort(0x00, 0xFF, DefBadWriteZ80, NULL); // <bad reads>
AddZ80BWritePort(-1, -1, NULL, NULL);
AddZ80BInit();
FreeMem(TMP);
if(!load_rom("a85-11.rom",ROM2,0x8000)) return; // Z80 SUB ROM
// Skip Idle Z80
// -------------
ROM2[0x007F]=0x00; // NOP
ROM2[0x0080]=0x00; // NOP
ROM2[0x00BE]=0xC3; // JP 00A4
ROM2[0x00BF]=0xA4; //
ROM2[0x00C0]=0x00; //
ROM2[0x009C]=0x1A; //
ROM2[0x009D]=0x32; //
ROM2[0x009E]=0xFD; //
ROM2[0x009F]=0x9F; //
ROM2[0x00A0]=0x36; //
ROM2[0x00A1]=0x0F; //
ROM2[0x00A2]=0x18; //
ROM2[0x00A3]=0x10; //
ROM2[0x00A4]=0xD3; // OUTA (AAh)
ROM2[0x00A5]=0xAA; //
ROM2[0x00A6]=0x7E; //
ROM2[0x00A7]=0xFE; //
ROM2[0x00A8]=0xFF; //
ROM2[0x00A9]=0x28; //
ROM2[0x00AA]=0xF9; //
ROM2[0x00AB]=0xC3; //
ROM2[0x00AC]=0xC3; //
ROM2[0x00AD]=0x00; //
SetStopZ80CMode2(0x00A6);
memset(RAM2+0x00000, 0x00, 0x10000);
memcpy(RAM2, ROM2, 0x8000);
AddZ80CROMBase(RAM2, 0x0038, 0x0066);
AddZ80CReadByte(0x0000, 0x7FFF, NULL, RAM2+0x0000); // Z80 ROM
AddZ80CReadByte(0x8000, 0x9FFF, NULL, RAM +0xC000); // COMMON RAM
AddZ80CReadByte(0xC000, 0xC001, KSystemYM2203Read, NULL); // YM2203; INPUT
AddZ80CReadByte(0xA000, 0xC7FF, NULL, RAM2+0xA000); // RAM?
AddZ80CReadByte(0x0000, 0xFFFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80CReadByte(-1, -1, NULL, NULL);
AddZ80CWriteByte(0x8000, 0x9FFF, NULL, RAM +0xC000); // COMMON RAM
AddZ80CWriteByte(0xC000, 0xC001, KSystemYM2203Write, NULL); // YM2203; INPUT
AddZ80CWriteByte(0xA000, 0xC7FF, NULL, RAM2+0xA000); // RAM?
AddZ80CWriteByte(0x0000, 0xFFFF, DefBadWriteZ80, NULL); // <bad writes>
AddZ80CWriteByte(-1, -1, NULL, NULL);
AddZ80CReadPort(0x00, 0xFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80CReadPort(-1, -1, NULL, NULL);
AddZ80CWritePort(0xAA, 0xAA, StopZ80CMode2, NULL); // Trap Idle Z80
AddZ80CWritePort(0x00, 0xFF, DefBadWriteZ80, NULL); // <bad reads>
AddZ80CWritePort(-1, -1, NULL, NULL);
AddZ80CInit();
/* MCU ROM */
if(!load_rom("knightb.uc",RAM_MCU,0x800)) return;
if(!(GFX=AllocateMem(0x080000))) return;
if(!(TMP=AllocateMem(0x040000))) return;
tb=0;
if(!load_rom("knightb.d", TMP+0x00000, 0x10000)) return;
if(!load_rom("a85-14.rom", TMP+0x10000, 0x10000)) return;
if(!load_rom("knightb.b", TMP+0x20000, 0x10000)) return;
if(!load_rom("a85-12.rom", TMP+0x30000, 0x10000)) return;
for(ta=0;ta<0x20000;ta+=2,tb+=8){
DrawNibble0(GFX+tb+0, 0, (UINT8) (TMP[ta+0x00000]&15) );
DrawNibble (GFX+tb+0, 1, (UINT8) (TMP[ta+0x00000]>>4) );
DrawNibble (GFX+tb+0, 2, (UINT8) (TMP[ta+0x20000]&15) );
DrawNibble (GFX+tb+0, 3, (UINT8) (TMP[ta+0x20000]>>4) );
DrawNibble0(GFX+tb+4, 0, (UINT8) (TMP[ta+0x00001]&15) );
DrawNibble (GFX+tb+4, 1, (UINT8) (TMP[ta+0x00001]>>4) );
DrawNibble (GFX+tb+4, 2, (UINT8) (TMP[ta+0x20001]&15) );
DrawNibble (GFX+tb+4, 3, (UINT8) (TMP[ta+0x20001]>>4) );
}
tb=0;
if(!load_rom("a85-08.rom", TMP+0x00000, 0x80)) return;
if(!load_rom("a85-10.rom", TMP+0x00080, 0x80)) return;
if(!load_rom("a85-09.rom", TMP+0x00100, 0x80)) return;
for(ta=0;ta<0x80;ta++,tb+=2){
td = (ta&0x70)|(0x0F-(ta&0x0F));
tc = (TMP[td+0x000]&0x0F)<<8;
tc |= (TMP[td+0x080]&0x0F)<<4;
tc |= (TMP[td+0x100]&0x0F)<<0;
WriteWord(&RAM_COLOUR[tb+0x000],tc);
WriteWord(&RAM_COLOUR[tb+0x100],tc);
}
FreeMem(TMP);
GFX_BG0_SOLID = make_solid_mask_8x8(GFX, 0x2000);
}
void ClearKSystem(void)
{
#ifdef RAINE_DEBUG
save_debug("RAM.bin", RAM, RAMSize, 0);
save_debug("GFX.bin", GFX, 0x080000, 0);
#endif
}
/* this is a patch for Kicn&Run.
* it hacks it to accept an MCU from Mexico86.
* If we ever got a proper K&R dump, we could probably remove this patch.
*/
static UINT8 PatchTable[] = {
0x3E, 0x00, 0x32, 0x4A, 0xE8, 0x32, 0x4B, 0xE8,
0x32, 0x77, 0xE8, 0x32, 0x54, 0xE8, 0x32, 0x60,
0xE8, 0x3E, 0x37, 0x32, 0x4C, 0xE8, 0x3E, 0x12,
0x32, 0x4F, 0xE8, 0x3E, 0x08, 0x32, 0x7B, 0xE8,
0x3E, 0x80, 0x32, 0x7F, 0xE8, 0x3E, 0x92, 0x32,
0x00, 0xE8, 0xC9
};
void LoadKickRun(void)
{
int ta,tb,tc,td;
UINT8 *TMP;
romset=1;
mcu_enable=0;
RAMSize=0x10000+0x10000+0x10+0x200+0x800;
if(!(ROM2=AllocateMem(0x8000))) return;
if(!(RAM=AllocateMem(RAMSize))) return;
RAM2 = RAM+0x10000;
RAM_INPUT = RAM+0x10000+0x10000;
RAM_COLOUR = RAM+0x10000+0x10000+0x10;
RAM_MCU = RAM+0x10000+0x10000+0x10+0x200;
if(!(TMP=AllocateMem(0x20000))) return;
if(!load_rom("a87-08.bin",TMP+0x00000,0x10000)) return; // Z80 MAIN ROM
if(!load_rom("a87-07.bin",TMP+0x10000,0x10000)) return; // Z80 MAIN ROM
/* Mexico86 is a bootleg of Kick&Run. We don't have a MCU dump for K&R, so
* we will use Mexico86's. However, the Mex86 dump is not quite an 100%
* copy, so we need to patch Kick&Run to accept it.
* If we ever got a proper K&R dump, we could probably remove this patch.
*/
TMP[0x01C8] = 0x92;
TMP[0x0207] = 0x3E;
TMP[0x0208] = 0x92;
TMP[0x0209] = 0x00;
TMP[0x0223] = 0x18;
TMP[0x07D1] = 0x18;
for (ta=0;ta<sizeof(PatchTable);ta++)
{
TMP[0x084C+ta] = PatchTable[ta];
}
for (ta=0x0877;ta<=0x08b1;ta++) TMP[ta] = 0xff;
init_bank_rom(TMP,ROM);
memset(RAM, 0x00, RAMSize);
memcpy(RAM, TMP, 0x8000+0x4000);
AddZ80BROMBase(RAM, 0x0038, 0x0066);
AddZ80BReadByte(0x0000, 0xBFFF, NULL, NULL); // Z80 ROM/BANK ROM
AddZ80BReadByte(0xC000, 0xE7FF, NULL, RAM+0xC000); // RAM
AddZ80BReadByte(0xE800, 0xE8FF, KSystemMCURead, NULL); // MCU
AddZ80BReadByte(0xE900, 0xEFFF, NULL, RAM+0xE900); // RAM
AddZ80BReadByte(0xF010, 0xF010, KSystemInputRead, NULL); // INPUT
AddZ80BReadByte(0xF800, 0xFFFF, NULL, RAM+0xF800); // RAM?
AddZ80BReadByte(0x0000, 0xFFFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80BReadByte(-1, -1, NULL, NULL);
AddZ80BWriteByte(0xC000, 0xE7FF, NULL, RAM+0xC000); // RAM
AddZ80BWriteByte(0xE800, 0xE8FF, KSystemMCUWrite, NULL); // MCU
AddZ80BWriteByte(0xE900, 0xEFFF, NULL, RAM+0xE900); // RAM
AddZ80BWriteByte(0xF000, 0xF000, KSystemNewBankWrite, NULL); // ROM BANK
AddZ80BWriteByte(0xF008, 0xF008, KSystemF008Write, NULL); // ?
AddZ80BWriteByte(0xF010, 0xF010, KSystemInputWrite, NULL); // INPUT
AddZ80BWriteByte(0xF018, 0xF018, NULL, RAM+0xF018); // WATCHDOG
AddZ80BWriteByte(0xF800, 0xFFFF, NULL, RAM+0xF800); // RAM?
AddZ80BWriteByte(0x0000, 0xFFFF, DefBadWriteZ80, NULL); // <bad writes>
AddZ80BWriteByte(-1, -1, NULL, NULL);
AddZ80BReadPort(0x00, 0xFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80BReadPort(-1, -1, NULL, NULL);
AddZ80BWritePort(0xAA, 0xAA, StopZ80BMode2, NULL); // Trap Idle Z80
AddZ80BWritePort(0x00, 0xFF, DefBadWriteZ80, NULL); // <bad reads>
AddZ80BWritePort(-1, -1, NULL, NULL);
AddZ80BInit();
if(!load_rom("a87-06.bin",ROM2,0x8000)) return; // Z80 SUB ROM
// Skip Idle Z80
// -------------
ROM2[0x037d]=0xAF; // XOR A (checksum always succeeds)
ROM2[0x00d7]=0xD3; // OUTA (AAh)
ROM2[0x00d8]=0xAA; //
SetStopZ80CMode2(0x00d4);
memset(RAM2+0x00000, 0x00, 0x10000);
memcpy(RAM2, ROM2, 0x8000);
AddZ80CROMBase(RAM2, 0x0038, 0x0066);
AddZ80CReadByte(0x0000, 0x7FFF, NULL, RAM2+0x0000); // Z80 ROM
AddZ80CReadByte(0x8000, 0xA7FF, NULL, RAM +0xC000); // COMMON RAM
AddZ80CReadByte(0xC000, 0xC001, KSystemYM2203Read, NULL); // YM2203; INPUT
AddZ80CReadByte(0xA800, 0xC7FF, NULL, RAM2+0xA800); // RAM?
AddZ80CReadByte(0x0000, 0xFFFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80CReadByte(-1, -1, NULL, NULL);
AddZ80CWriteByte(0x8000, 0xA7FF, NULL, RAM +0xC000); // COMMON RAM
AddZ80CWriteByte(0xC000, 0xC001, KSystemYM2203Write, NULL); // YM2203; INPUT
AddZ80CWriteByte(0xA800, 0xC7FF, NULL, RAM2+0xA800); // RAM?
AddZ80CWriteByte(0x0000, 0xFFFF, DefBadWriteZ80, NULL); // <bad writes>
AddZ80CWriteByte(-1, -1, NULL, NULL);
AddZ80CReadPort(0x00, 0xFF, DefBadReadZ80, NULL); // <bad reads>
AddZ80CReadPort(-1, -1, NULL, NULL);
AddZ80CWritePort(0xAA, 0xAA, StopZ80CMode2, NULL); // Trap Idle Z80
AddZ80CWritePort(0x00, 0xFF, DefBadWriteZ80, NULL); // <bad reads>
AddZ80CWritePort(-1, -1, NULL, NULL);
AddZ80CInit();
/* MCU ROM */
if(!load_rom("68_h.bin",RAM_MCU,0x800)) return;
if(!(GFX=AllocateMem(0x080000))) return;
if(!(TMP=AllocateMem(0x040000))) return;
if(!load_rom("a87-05.bin", TMP+0x00000, 0x10000)) return;
if(!load_rom("a87-04.bin", TMP+0x10000, 0x08000)) return;
if(!load_rom("a87-04.bin", TMP+0x18000, 0x08000)) return;
if(!load_rom("a87-03.bin", TMP+0x20000, 0x10000)) return;
if(!load_rom("a87-02.bin", TMP+0x30000, 0x08000)) return;
if(!load_rom("a87-02.bin", TMP+0x38000, 0x08000)) return;
// much annoyingness. we have to swap the upper/lower halves
// of the 64K roms (the 32K ones just get repeated) :-(
for(ta=0;ta<0x8000;ta++)
{
tb = TMP[0x00000+ta];
TMP[0x00000+ta] = TMP[0x08000+ta];
TMP[0x08000+ta] = tb;
tb = TMP[0x20000+ta];
TMP[0x20000+ta] = TMP[0x28000+ta];
TMP[0x28000+ta] = tb;
}
tb=0;
for(ta=0;ta<0x20000;ta+=2,tb+=8){
DrawNibble0(GFX+tb+0, 0, (UINT8) (TMP[ta+0x00000]&15) );
DrawNibble (GFX+tb+0, 1, (UINT8) (TMP[ta+0x00000]>>4) );
DrawNibble (GFX+tb+0, 2, (UINT8) (TMP[ta+0x20000]&15) );
DrawNibble (GFX+tb+0, 3, (UINT8) (TMP[ta+0x20000]>>4) );
DrawNibble0(GFX+tb+4, 0, (UINT8) (TMP[ta+0x00001]&15) );
DrawNibble (GFX+tb+4, 1, (UINT8) (TMP[ta+0x00001]>>4) );
DrawNibble (GFX+tb+4, 2, (UINT8) (TMP[ta+0x20001]&15) );
DrawNibble (GFX+tb+4, 3, (UINT8) (TMP[ta+0x20001]>>4) );
}
tb=0;
if(!load_rom("a87-10.bin", TMP+0x00000, 0x100)) return;
if(!load_rom("a87-12.bin", TMP+0x00100, 0x100)) return;
if(!load_rom("a87-11.bin", TMP+0x00200, 0x100)) return;
for(ta=0;ta<0x100;ta++,tb+=2){
td = ta ^ 0x0f;
tc = (TMP[td+0x000]&0x0F)<<8;
tc |= (TMP[td+0x100]&0x0F)<<4;
tc |= (TMP[td+0x200]&0x0F)<<0;
WriteWord(&RAM_COLOUR[tb],tc);
}
FreeMem(TMP);
GFX_BG0_SOLID = make_solid_mask_8x8(GFX, 0x2000);
}
void ExecuteKSystemFrame(void)
{
int ta;
if (cpu_get_pc(CPU_Z80_1) == 0x0000)
{
switch (romset) {
case 0: KikiKaiKai_mcu_reset(); break;
case 1: KickRun_mcu_reset(); break;
}
} else if (romset && cpu_get_pc(CPU_Z80_1) == 0x3ad3)
// This is apparently caused by the protection : the z80 waits here
// to be reseted, probably by the mcu. Since it does not happen in our
// emulation, we force the reset.
reset_game_hardware();
// ---------------------
if (romset==0)
{
for(ta=0;ta<16;ta++)
{
// probably actually only 6Mhz or so, but MZ80 bug means that...
cpu_execute_cycles(CPU_Z80_1, CPU_FRAME_MHz(16,60)/16); // Main Z80 (60fps)
if(cpu_get_pc(CPU_Z80_2) != 0x00A6)
cpu_execute_cycles(CPU_Z80_2, CPU_FRAME_MHz(8,60)/16); // Sub Z80 (60fps)
}
print_debug("Z80PC_MAIN:%04x\n",cpu_get_pc(CPU_Z80_1));
cpu_interrupt(CPU_Z80_1, 0x38);
cpu_interrupt(CPU_Z80_2, 0x38);
}
else {
cpu_execute_cycles(CPU_Z80_1, CPU_FRAME_MHz(8,60)); // Main Z80 6MHz (60fps)
print_debug("Z80PC_MAIN:%04x\n",z80pc);
cpu_interrupt(CPU_Z80_1, RAM[0xe800]);
cpu_execute_cycles(CPU_Z80_2, CPU_FRAME_MHz(8,60)); // Sub Z80 4MHz (60fps)
print_debug("Z80PC_SUB:%04x\n",z80pc);
cpu_interrupt(CPU_Z80_2, 0x38);
}
if (mcu_enable)
{
switch (romset) {
case 0: KikiKaiKai_mcu(1); break;
case 1: KickRun_mcu(1); break;
}
}
}
void DrawKikiKaiKai(void)
{
int x,y,ta;
int sx,sy,offs,goffs,gfx_offs,gfx_num,gfx_attr,height,xc,yc;
UINT8 map;
// PALETTE
if (RefreshBuffers)
{
for(x=0;x<0x200;x+=2)
{
ta = ReadWord(&RAM_COLOUR[x]);
pal[x >> 1].r = (ta & 0x0F00) >> 6;
pal[x >> 1].g = (ta & 0x00F0) >> 2;
pal[x >> 1].b = (ta & 0x000F) << 2;
}
}
// No Solid BG0
clear_game_screen(0);
// OBJECT
sx = 0;
for (offs=0;offs<0x300;offs+=4)
{
/* skip empty sprites */
if (*(UINT32 *)(&RAM[offs+0xd500]) == 0) continue;
gfx_num = RAM[0xd500 + offs + 1];
gfx_attr = RAM[0xd500 + offs + 3];
if ((gfx_num & 0x80) == 0) /* 16x16 sprites */
{
gfx_offs = ((gfx_num & 0x1f) * 0x80) + ((gfx_num & 0x60) >> 1) + 12;
height = 2;
}
else /* tilemaps (each sprite is a 16x256 column) */
{
gfx_offs = ((gfx_num & 0x3f) * 0x80);
height = 32;
}
if ((gfx_num & 0xc0) == 0xc0)
sx += 16;
else
{
sx = RAM[0xd500 + offs + 2];
if (gfx_attr & 0x40) sx -= 256;
}
sy = 256 - height*8 - (RAM[0xd500 + offs + 0]);
for (xc=0;xc<2;xc++)
{
goffs = gfx_offs;
for (yc=0;yc<height;yc++,goffs+=2)
{
/* this is different to Bubble Bobble */
ta = ReadWord(&RAM[0xc000+goffs]) & 0x1FFF;
if (!GFX_BG0_SOLID[ta]) continue; // No pixels; skip
map = (RAM[0xc001 + goffs] >> 1) & 0x70;
x = (sx + xc * 8) & 0xff;
y = ((sy + yc * 8) & 0xff) -16;
/* Kiki Kai Kai appears not to have a X/Y flip (eh?) */
if ((x > -8) && (y > -8) && (x < 256) && (y < 224))
{
if (GFX_BG0_SOLID[ta] == 1) // Some pixels; trans
{
Draw8x8_Trans_Rot(&GFX[ta<<6], x+8, y+8, map);
} else { // all pixels; solid
Draw8x8_Rot(&GFX[ta<<6], x+8, y+8, map);
}
}
}
gfx_offs += 64;
}
}
}
void DrawKickRun(void)
{
int x,y,ta;
int sx,sy,offs,goffs,gfx_offs,gfx_num,gfx_attr,height,xc,yc;
UINT8 map;
// PALETTE
if (RefreshBuffers)
{
for(x=0;x<0x200;x+=2)
{
ta = ReadWord(&RAM_COLOUR[x]);
pal[x >> 1].r = (ta & 0x0F00) >> 6;
pal[x >> 1].g = (ta & 0x00F0) >> 2;
pal[x >> 1].b = (ta & 0x000F) << 2;
}
}
// No Solid BG0
clear_game_screen(0);
// OBJECT
sx = 0;
for (offs=0;offs<0x4c0;offs+=4)
{
// I really give up on this bollocks, I really do.
// MAME says do this. <sigh>
if (offs >= 0x300 && offs < 0x480) continue;
/* skip empty sprites */
if (*(UINT32 *)(&RAM[offs+0xd500]) == 0) continue;
gfx_num = RAM[0xd500 + offs + 1];
gfx_attr = RAM[0xd500 + offs + 3];
if ((gfx_num & 0x80) == 0) /* 16x16 sprites */
{
gfx_offs = ((gfx_num & 0x1f) * 0x80) + ((gfx_num & 0x60) >> 1) + 12;
height = 2;
}
else /* tilemaps (each sprite is a 16x256 column) */
{
gfx_offs = ((gfx_num & 0x3f) * 0x80);
height = 32;
}
if ((gfx_num & 0xc0) == 0xc0)
sx += 16;
else
{
sx = RAM[0xd500 + offs + 2];
// not this either (accoring to MAME at least)?
//if (gfx_attr & 0x40) sx -= 256;
}
sy = 256 - height*8 - (RAM[0xd500 + offs + 0]);
for (xc=0;xc<2;xc++)
{
goffs = gfx_offs;
for (yc=0;yc<height;yc++,goffs+=2)
{
/* this is different to both Bubble Bobble and KKK */
ta = ReadWord(&RAM[0xc000+goffs]) & 0x07FF;
ta |= (RAM[0xc001+goffs] & 0x80) << 4;
ta |= gfx_bank << 12;
if (!GFX_BG0_SOLID[ta]) continue; // No pixels; skip
map = (RAM[0xc001 + goffs] << 1) & 0x70;
map |= (gfx_attr & 0x02) << 6;
x = (sx + xc * 8) & 0xff;
y = ((sy + yc * 8) & 0xff) -16;
if ((x > -8) && (y > -8) && (x < 256) && (y < 224))
{
if (GFX_BG0_SOLID[ta] == 1) // Some pixels; trans
{
if (RAM[0xc000+goffs+1] & 0x40)
Draw8x8_Trans_FlipY_Rot(&GFX[ta<<6], x+8, y+8, map);
else
Draw8x8_Trans_Rot(&GFX[ta<<6], x+8, y+8, map);
} else { // all pixels; solid
if (RAM[0xc000+goffs+1] & 0x40)
Draw8x8_FlipY_Rot(&GFX[ta<<6], x+8, y+8, map);
else
Draw8x8_Rot(&GFX[ta<<6], x+8, y+8, map);
}
}
}
gfx_offs += 64;
}
}
}