mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
airbustr: add kaneko_hit device
This commit is contained in:
parent
ad4f0c9bf7
commit
7c1801658a
@ -49,8 +49,8 @@ protected:
|
||||
|
||||
attotime m_sensordelay;
|
||||
bool m_disable_leds;
|
||||
u8 m_led_data = 0;
|
||||
u8 m_mux = 0;
|
||||
u8 m_led_data;
|
||||
u8 m_mux;
|
||||
};
|
||||
|
||||
|
||||
|
@ -34,9 +34,9 @@ private:
|
||||
|
||||
void update_lcd();
|
||||
|
||||
int m_strobe = 0;
|
||||
u8 m_digit_idx = 0;
|
||||
u8 m_digit_data[4] = { 0, 0, 0, 0 };
|
||||
int m_strobe;
|
||||
u8 m_digit_idx;
|
||||
u8 m_digit_data[4];
|
||||
};
|
||||
|
||||
|
||||
|
@ -42,8 +42,8 @@ private:
|
||||
void lcd_palette(palette_device &palette) const;
|
||||
HD44780_PIXEL_UPDATE(lcd_pixel_update);
|
||||
|
||||
u8 m_latch = 0;
|
||||
u8 m_ctrl = 0;
|
||||
u8 m_latch;
|
||||
u8 m_ctrl;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Luca Elia
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Air Buster
|
||||
@ -86,10 +85,6 @@ f150<- index of table of routines at 2907
|
||||
|
||||
----------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Interesting routines (sub CPU)
|
||||
-------------------------------
|
||||
|
||||
@ -154,13 +149,6 @@ f14c scroll regs high bits
|
||||
|
||||
----------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Interesting routines (sound CPU)
|
||||
-------------------------------
|
||||
|
||||
@ -179,12 +167,11 @@ c760 ROM bank
|
||||
To Do
|
||||
-----
|
||||
|
||||
- Is the sub CPU / sound CPU communication status port (0e) correct ?
|
||||
- Main CPU: port 01 ? boot sub/sound CPU?
|
||||
- Is the sub CPU / sound CPU communication status port (0x0e) correct ?
|
||||
- Main CPU: port 0x01 ? boot sub/sound CPU?
|
||||
- Sub CPU: port 0x38 ? irq ack?
|
||||
- incomplete DSWs
|
||||
- Spriteram low 0x300 bytes (priority?)
|
||||
- Hook up KANEKO CALC1 chip for the original sets
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -228,7 +215,6 @@ Code at 505: waits for bit 1 to go low, writes command, waits for bit
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "machine/gen_latch.h"
|
||||
#include "machine/timer.h"
|
||||
#include "machine/watchdog.h"
|
||||
#include "sound/okim6295.h"
|
||||
#include "sound/ymopn.h"
|
||||
|
||||
@ -265,10 +251,10 @@ public:
|
||||
, m_slave(*this, "slave")
|
||||
, m_audiocpu(*this, "audiocpu")
|
||||
, m_pandora(*this, "pandora")
|
||||
, m_calc1(*this, "calc1")
|
||||
, m_gfxdecode(*this, "gfxdecode")
|
||||
, m_screen(*this, "screen")
|
||||
, m_palette(*this, "palette")
|
||||
, m_watchdog(*this, "watchdog")
|
||||
, m_soundlatch(*this, "soundlatch%u", 1)
|
||||
{
|
||||
}
|
||||
@ -276,8 +262,6 @@ public:
|
||||
void airbustr(machine_config &config);
|
||||
void airbustrb(machine_config &config);
|
||||
|
||||
void init_airbustr();
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
@ -304,13 +288,14 @@ private:
|
||||
required_device<cpu_device> m_slave;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<kaneko_pandora_device> m_pandora;
|
||||
optional_device<kaneko_hit_device> m_calc1;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<watchdog_timer_device> m_watchdog;
|
||||
required_device_array<generic_latch_8_device, 2> m_soundlatch;
|
||||
|
||||
uint8_t devram_r(address_space &space, offs_t offset);
|
||||
void calc1_w(offs_t offset, uint8_t data);
|
||||
uint8_t calc1_r(offs_t offset);
|
||||
void master_nmi_trigger_w(uint8_t data);
|
||||
void master_bankswitch_w(uint8_t data);
|
||||
void slave_bankswitch_w(uint8_t data);
|
||||
@ -325,16 +310,18 @@ private:
|
||||
DECLARE_WRITE_LINE_MEMBER(screen_vblank);
|
||||
INTERRUPT_GEN_MEMBER(slave_interrupt);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(scanline);
|
||||
void master_io_map(address_map &map);
|
||||
|
||||
void master_map(address_map &map);
|
||||
void slave_io_map(address_map &map);
|
||||
void master_prot_map(address_map &map);
|
||||
void master_io_map(address_map &map);
|
||||
void slave_map(address_map &map);
|
||||
void sound_io_map(address_map &map);
|
||||
void slave_io_map(address_map &map);
|
||||
void sound_map(address_map &map);
|
||||
void sound_io_map(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
// video
|
||||
// Video
|
||||
|
||||
/**************************************************************************
|
||||
|
||||
@ -364,7 +351,6 @@ private:
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/* Scroll Registers
|
||||
|
||||
Port:
|
||||
@ -444,40 +430,25 @@ WRITE_LINE_MEMBER(airbustr_state::screen_vblank)
|
||||
}
|
||||
|
||||
|
||||
// machine
|
||||
// Machine
|
||||
|
||||
// Read / Write Handlers
|
||||
uint8_t airbustr_state::devram_r(address_space &space, offs_t offset)
|
||||
|
||||
void airbustr_state::calc1_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
// this is a custom implementation of the Kaneko CALC1 chip. TODO: hook up the generic implementation in kaneko_hit.cpp
|
||||
switch (offset)
|
||||
{
|
||||
/* Reading efe0 probably resets a watchdog mechanism
|
||||
that would reset the main CPU. We avoid this and patch
|
||||
the ROM instead (main CPU has to be reset once at startup) */
|
||||
case 0xfe0:
|
||||
return m_watchdog->reset_r(space);
|
||||
offset += 0x1fe0;
|
||||
m_devram[offset] = data;
|
||||
|
||||
/* Reading a word at eff2 probably yields the product
|
||||
of the words written to eff0 and eff2 */
|
||||
case 0xff2:
|
||||
case 0xff3:
|
||||
{
|
||||
int x = (m_devram[0xff0] + m_devram[0xff1] * 256) * (m_devram[0xff2] + m_devram[0xff3] * 256);
|
||||
if (offset == 0xff2)
|
||||
return (x & 0x00ff) >> 0;
|
||||
else
|
||||
return (x & 0xff00) >> 8;
|
||||
}
|
||||
// CALC1 chip is 16-bit
|
||||
uint16_t data16 = m_devram[offset | 1] << 8 | m_devram[offset & ~1];
|
||||
m_calc1->kaneko_hit_w((offset & 0x1f) / 2, data16);
|
||||
}
|
||||
|
||||
/* Reading eff4, F0 times must yield at most 80-1 consecutive
|
||||
equal values */
|
||||
case 0xff4:
|
||||
return machine().rand();
|
||||
|
||||
default:
|
||||
return m_devram[offset];
|
||||
}
|
||||
uint8_t airbustr_state::calc1_r(offs_t offset)
|
||||
{
|
||||
// CALC1 chip is 16-bit
|
||||
uint16_t ret = m_calc1->kaneko_hit_r(offset / 2);
|
||||
return (offset & 1) ? (ret >> 8) : (ret & 0xff);
|
||||
}
|
||||
|
||||
void airbustr_state::master_nmi_trigger_w(uint8_t data)
|
||||
@ -537,17 +508,25 @@ void airbustr_state::coin_counter_w(uint8_t data)
|
||||
machine().bookkeeping().coin_lockout_w(1, ~data & 8);
|
||||
}
|
||||
|
||||
|
||||
// Memory Maps
|
||||
|
||||
void airbustr_state::master_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x7fff).rom();
|
||||
map(0x8000, 0xbfff).bankr(m_masterbank);
|
||||
map(0xc000, 0xcfff).rw(m_pandora, FUNC(kaneko_pandora_device::spriteram_r), FUNC(kaneko_pandora_device::spriteram_w));
|
||||
map(0xd000, 0xdfff).ram();
|
||||
map(0xe000, 0xefff).ram().share(m_devram); // shared with protection device
|
||||
map(0xe000, 0xefff).ram().share(m_devram); // shared with protection device (see below)
|
||||
map(0xf000, 0xffff).ram().share("master_slave");
|
||||
}
|
||||
|
||||
void airbustr_state::master_prot_map(address_map &map)
|
||||
{
|
||||
master_map(map);
|
||||
map(0xefe0, 0xeff5).rw(FUNC(airbustr_state::calc1_r), FUNC(airbustr_state::calc1_w));
|
||||
}
|
||||
|
||||
void airbustr_state::master_io_map(address_map &map)
|
||||
{
|
||||
map.global_mask(0xff);
|
||||
@ -600,7 +579,8 @@ void airbustr_state::sound_io_map(address_map &map)
|
||||
map(0x06, 0x06).r(m_soundlatch[0], FUNC(generic_latch_8_device::read)).w(m_soundlatch[1], FUNC(generic_latch_8_device::write));
|
||||
}
|
||||
|
||||
/* Input Ports */
|
||||
|
||||
// Input Ports
|
||||
|
||||
static INPUT_PORTS_START( airbustr )
|
||||
PORT_START("P1")
|
||||
@ -631,7 +611,7 @@ static INPUT_PORTS_START( airbustr )
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // used
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // used
|
||||
|
||||
PORT_START("DSW1")
|
||||
PORT_DIPUNUSED_DIPLOC( 0x01, IP_ACTIVE_LOW, "SW1:1" )
|
||||
@ -640,9 +620,9 @@ static INPUT_PORTS_START( airbustr )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_SERVICE_DIPLOC( 0x04, IP_ACTIVE_LOW, "SW1:3" )
|
||||
PORT_DIPNAME( 0x08, 0x08, "Coin Mode" ) PORT_DIPLOCATION("SW1:4")
|
||||
PORT_DIPSETTING( 0x08, "Mode 1" ) // routine at 0x056d: 11 21 12 16 (bit 3 active)
|
||||
PORT_DIPSETTING( 0x00, "Mode 2" ) // 11 21 13 14 (bit 3 not active)
|
||||
PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:5,6")
|
||||
PORT_DIPSETTING( 0x08, "Mode 1" ) // routine at 0x056d: 11 21 12 16 (bit 3 active)
|
||||
PORT_DIPSETTING( 0x00, "Mode 2" ) // 11 21 13 14 (bit 3 not active)
|
||||
PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:5,6")
|
||||
PORT_DIPSETTING( 0x20, DEF_STR( 2C_1C ) ) PORT_CONDITION("DSW1", 0x08, NOTEQUALS, 0x00)
|
||||
PORT_DIPSETTING( 0x30, DEF_STR( 1C_1C ) ) PORT_CONDITION("DSW1", 0x08, NOTEQUALS, 0x00)
|
||||
PORT_DIPSETTING( 0x10, DEF_STR( 1C_2C ) ) PORT_CONDITION("DSW1", 0x08, NOTEQUALS, 0x00)
|
||||
@ -651,7 +631,7 @@ static INPUT_PORTS_START( airbustr )
|
||||
PORT_DIPSETTING( 0x30, DEF_STR( 1C_1C ) ) PORT_CONDITION("DSW1", 0x08, EQUALS, 0x00)
|
||||
PORT_DIPSETTING( 0x10, DEF_STR( 1C_3C ) ) PORT_CONDITION("DSW1", 0x08, EQUALS, 0x00)
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( 1C_4C ) ) PORT_CONDITION("DSW1", 0x08, EQUALS, 0x00)
|
||||
PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:7,8")
|
||||
PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:7,8")
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( 2C_1C ) ) PORT_CONDITION("DSW1", 0x08, NOTEQUALS, 0x00)
|
||||
PORT_DIPSETTING( 0xc0, DEF_STR( 1C_1C ) ) PORT_CONDITION("DSW1", 0x08, NOTEQUALS, 0x00)
|
||||
PORT_DIPSETTING( 0x40, DEF_STR( 1C_2C ) ) PORT_CONDITION("DSW1", 0x08, NOTEQUALS, 0x00)
|
||||
@ -699,6 +679,7 @@ static INPUT_PORTS_START( airbustrj )
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( 1C_2C ) )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
// Graphics Decode Information
|
||||
|
||||
static GFXDECODE_START( gfx_airbustr )
|
||||
@ -728,6 +709,7 @@ INTERRUPT_GEN_MEMBER(airbustr_state::slave_interrupt)
|
||||
device.execute().set_input_line_and_vector(0, HOLD_LINE, 0xfd); // Z80
|
||||
}
|
||||
|
||||
|
||||
// Machine Initialization
|
||||
|
||||
void airbustr_state::machine_start()
|
||||
@ -750,17 +732,18 @@ void airbustr_state::machine_reset()
|
||||
m_highbits = 0;
|
||||
}
|
||||
|
||||
|
||||
// Machine Driver
|
||||
|
||||
void airbustr_state::airbustr(machine_config &config)
|
||||
void airbustr_state::airbustrb(machine_config &config)
|
||||
{
|
||||
// basic machine hardware
|
||||
Z80(config, m_master, XTAL(12'000'000) / 2); // verified on PCB
|
||||
Z80(config, m_master, XTAL(12'000'000) / 2); // verified on PCB
|
||||
m_master->set_addrmap(AS_PROGRAM, &airbustr_state::master_map);
|
||||
m_master->set_addrmap(AS_IO, &airbustr_state::master_io_map);
|
||||
TIMER(config, "scantimer").configure_scanline(FUNC(airbustr_state::scanline), "screen", 0, 1);
|
||||
|
||||
Z80(config, m_slave, XTAL(12'000'000) / 2); // verified on PCB
|
||||
Z80(config, m_slave, XTAL(12'000'000) / 2); // verified on PCB
|
||||
m_slave->set_addrmap(AS_PROGRAM, &airbustr_state::slave_map);
|
||||
m_slave->set_addrmap(AS_IO, &airbustr_state::slave_io_map);
|
||||
m_slave->set_vblank_int("screen", FUNC(airbustr_state::slave_interrupt)); // nmi signal from master CPU
|
||||
@ -769,10 +752,8 @@ void airbustr_state::airbustr(machine_config &config)
|
||||
m_audiocpu->set_addrmap(AS_PROGRAM, &airbustr_state::sound_map);
|
||||
m_audiocpu->set_addrmap(AS_IO, &airbustr_state::sound_io_map);
|
||||
|
||||
config.set_maximum_quantum(attotime::from_hz(6000)); // Palette RAM is filled by sub CPU with data supplied by main CPU
|
||||
// Maybe a high value is safer in order to avoid glitches
|
||||
|
||||
WATCHDOG_TIMER(config, m_watchdog).set_time(attotime::from_seconds(3)); // a guess, and certainly wrong
|
||||
// palette RAM is filled by sub CPU with data supplied by main CPU, maybe a high value is safer in order to avoid glitches
|
||||
config.set_maximum_quantum(attotime::from_hz(6000));
|
||||
|
||||
// video hardware
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
|
||||
@ -799,7 +780,7 @@ void airbustr_state::airbustr(machine_config &config)
|
||||
|
||||
GENERIC_LATCH_8(config, m_soundlatch[1]);
|
||||
|
||||
ym2203_device &ymsnd(YM2203(config, "ymsnd", XTAL(12'000'000) / 4)); // verified on PCB
|
||||
ym2203_device &ymsnd(YM2203(config, "ymsnd", XTAL(12'000'000) / 4)); // verified on PCB
|
||||
ymsnd.port_a_read_callback().set_ioport("DSW1");
|
||||
ymsnd.port_b_read_callback().set_ioport("DSW2");
|
||||
ymsnd.irq_handler().set_inputline(m_audiocpu, INPUT_LINE_IRQ0);
|
||||
@ -808,13 +789,17 @@ void airbustr_state::airbustr(machine_config &config)
|
||||
ymsnd.add_route(2, "mono", 0.25);
|
||||
ymsnd.add_route(3, "mono", 0.50);
|
||||
|
||||
OKIM6295(config, "oki", XTAL(12'000'000)/4, okim6295_device::PIN7_LOW).add_route(ALL_OUTPUTS, "mono", 0.80); // verified on PCB
|
||||
OKIM6295(config, "oki", XTAL(12'000'000)/4, okim6295_device::PIN7_LOW).add_route(ALL_OUTPUTS, "mono", 0.80); // verified on PCB
|
||||
}
|
||||
|
||||
void airbustr_state::airbustrb(machine_config &config)
|
||||
void airbustr_state::airbustr(machine_config &config)
|
||||
{
|
||||
airbustr(config);
|
||||
m_watchdog->set_time(attotime::from_seconds(0)); // no protection device or watchdog
|
||||
airbustrb(config);
|
||||
|
||||
m_master->set_addrmap(AS_PROGRAM, &airbustr_state::master_prot_map);
|
||||
|
||||
KANEKO_HIT(config, m_calc1).set_type(0);
|
||||
WATCHDOG_TIMER(config, "watchdog").set_time(attotime::from_seconds(3)); // a guess, and certainly wrong
|
||||
}
|
||||
|
||||
|
||||
@ -907,18 +892,11 @@ ROM_START( airbustrb )
|
||||
ROM_LOAD( "3.bin", 0x20000, 0x20000, CRC(58cd19e2) SHA1(479f22241bf29f7af67d9679fc6c20f10004fdd8) )
|
||||
ROM_END
|
||||
|
||||
// Driver Initialization
|
||||
|
||||
void airbustr_state::init_airbustr()
|
||||
{
|
||||
m_master->space(AS_PROGRAM).install_read_handler(0xe000, 0xefff, read8m_delegate(*this, FUNC(airbustr_state::devram_r))); // protection device lives here
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
// Game Drivers
|
||||
|
||||
GAME( 1990, airbustr, 0, airbustr, airbustr, airbustr_state, init_airbustr, ROT0, "Kaneko (Namco license)", "Air Buster: Trouble Specialty Raid Unit (World)", MACHINE_SUPPORTS_SAVE ) // 891220
|
||||
GAME( 1990, airbustrj, airbustr, airbustr, airbustrj, airbustr_state, init_airbustr, ROT0, "Kaneko (Namco license)", "Air Buster: Trouble Specialty Raid Unit (Japan)", MACHINE_SUPPORTS_SAVE ) // 891229
|
||||
GAME( 1990, airbustrb, airbustr, airbustrb, airbustrj, airbustr_state, empty_init, ROT0, "bootleg", "Air Buster: Trouble Specialty Raid Unit (bootleg)", MACHINE_SUPPORTS_SAVE ) // based on Japan set (891229)
|
||||
GAME( 1990, airbustr, 0, airbustr, airbustr, airbustr_state, empty_init, ROT0, "Kaneko (Namco license)", "Air Buster: Trouble Specialty Raid Unit (World)", MACHINE_SUPPORTS_SAVE ) // 891220
|
||||
GAME( 1990, airbustrj, airbustr, airbustr, airbustrj, airbustr_state, empty_init, ROT0, "Kaneko (Namco license)", "Air Buster: Trouble Specialty Raid Unit (Japan)", MACHINE_SUPPORTS_SAVE ) // 891229
|
||||
GAME( 1990, airbustrb, airbustr, airbustrb, airbustrj, airbustr_state, empty_init, ROT0, "bootleg", "Air Buster: Trouble Specialty Raid Unit (bootleg)", MACHINE_SUPPORTS_SAVE ) // based on Japan set (891229)
|
||||
|
@ -418,7 +418,6 @@ uint32_t expro02_state::screen_update_zipzap(screen_device &screen, bitmap_ind16
|
||||
*************************************/
|
||||
|
||||
static INPUT_PORTS_START( expro02 ) // TODO: at least for the 1994 version of New Fantasia running on the 940630 SWA and SWB should be inverted
|
||||
|
||||
PORT_START("DSW1")
|
||||
PORT_DIPNAME( 0x0003, 0x0003, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SWA:1,2")
|
||||
PORT_DIPSETTING( 0x0002, DEF_STR( Easy ) )
|
||||
@ -731,11 +730,11 @@ void expro02_state::expro02_map(address_map &map)
|
||||
map(0x900000, 0x900000).w(FUNC(expro02_state::oki_bankswitch_w));
|
||||
map(0xa00000, 0xa00001).nopw(); /* ??? */
|
||||
map(0xc80000, 0xc8ffff).ram();
|
||||
map(0xe00000, 0xe00015).rw("calc1_mcu", FUNC(kaneko_hit_device::kaneko_hit_r), FUNC(kaneko_hit_device::kaneko_hit_w));
|
||||
map(0xe00000, 0xe00015).rw("calc1", FUNC(kaneko_hit_device::kaneko_hit_r), FUNC(kaneko_hit_device::kaneko_hit_w));
|
||||
}
|
||||
|
||||
|
||||
// bigger ROM space, OKI commands moved, no CALC mcu
|
||||
// bigger ROM space, OKI commands moved, no CALC1 chip
|
||||
void expro02_state::fantasia_map(address_map &map)
|
||||
{
|
||||
expro02_video_base_map(map);
|
||||
@ -922,8 +921,6 @@ void expro02_state::expro02(machine_config &config)
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &expro02_state::expro02_map);
|
||||
TIMER(config, "scantimer").configure_scanline(FUNC(expro02_state::scanline), "screen", 0, 1);
|
||||
|
||||
/* CALC01 MCU @ 16Mhz (unknown type, simulated) */
|
||||
|
||||
/* video hardware */
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
|
||||
m_screen->set_refresh_hz(60);
|
||||
@ -947,7 +944,7 @@ void expro02_state::expro02(machine_config &config)
|
||||
m_kaneko_spr->set_palette(m_palette);
|
||||
m_kaneko_spr->set_color_base(0x100);
|
||||
|
||||
KANEKO_HIT(config, "calc1_mcu").set_type(0);
|
||||
KANEKO_HIT(config, "calc1").set_type(0);
|
||||
|
||||
/* arm watchdog */
|
||||
WATCHDOG_TIMER(config, "watchdog").set_time(attotime::from_seconds(3)); /* a guess, and certainly wrong */
|
||||
@ -968,7 +965,7 @@ void expro02_state::comad(machine_config &config)
|
||||
/* basic machine hardware */
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &expro02_state::fantasia_map);
|
||||
|
||||
config.device_remove("calc1_mcu");
|
||||
config.device_remove("calc1");
|
||||
|
||||
// these values might not be correct, behavior differs from original boards
|
||||
m_view2->set_invert_flip(1);
|
||||
|
@ -1,38 +1,43 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Luca Elia, David Haywood,Stephane Humbert
|
||||
// copyright-holders:Luca Elia, David Haywood, Stephane Humbert
|
||||
/* Kaneko 'Calc' hitbox collision / protection
|
||||
|
||||
It is thought that this is done by the 'CALC1' 'TOYBOX' and 'CALC3' protection chips found on the various boards
|
||||
however we have 3 implementations, and they don't quite pair up with the chips at the moment, this might be
|
||||
because our implementations are wrong / incomplete, or in some cases the newer chips are backwards compatible.
|
||||
It is thought that this is done by the 'CALC1' 'TOYBOX' and 'CALC3' protection chips found on the various boards
|
||||
however we have 3 implementations, and they don't quite pair up with the chips at the moment, this might be
|
||||
because our implementations are wrong / incomplete, or in some cases the newer chips are backwards compatible.
|
||||
|
||||
galpanica - CALC1 - type 0
|
||||
sandscrp - CALC1 - type 0 ( only uses Random Number? )
|
||||
bonkadv - TOYBOX - type 0 ( only uses Random Number, XY Overlap Collision bit and register '0x02' )
|
||||
gtmr - TOYBOX - type 1 ( only uses Random Number )
|
||||
gtmr2 - TOYBOX - type 1 ( only uses Random Number )
|
||||
bloodwar - TOYBOX - type 1
|
||||
shogwarr - CALC3 - type 1
|
||||
brapboys - CALC3 - type 2
|
||||
airbustr - CALC1 - type 0
|
||||
expro02 - CALC1 - type 0
|
||||
galpanica - CALC1 - type 0
|
||||
sandscrp - CALC1 - type 0 ( only uses Random Number? )
|
||||
bonkadv - TOYBOX - type 0 ( only uses Random Number, XY Overlap Collision bit and register '0x02' )
|
||||
gtmr - TOYBOX - type 1 ( only uses Random Number )
|
||||
gtmr2 - TOYBOX - type 1 ( only uses Random Number )
|
||||
bloodwar - TOYBOX - type 1
|
||||
shogwarr - CALC3 - type 1
|
||||
brapboys - CALC3 - type 2
|
||||
|
||||
note: shogwarr won't work with our brapboys implementation despite them being the same PCB and same MCU, this
|
||||
suggests that at least one of the implementations is wrong
|
||||
note: shogwarr won't work with our brapboys implementation despite them being the same PCB and same CALC chip,
|
||||
this suggests that at least one of the implementations is wrong
|
||||
|
||||
suprnova.c also has a similar device, the implementation hasn't been fully compared
|
||||
suprnova.cpp also has a similar device, the implementation hasn't been fully compared
|
||||
|
||||
CALC1 is a 40 pin DIP ULA with no internal ROM
|
||||
CALC1 is a 40 pin DIP ULA with no internal ROM
|
||||
|
||||
TODO:
|
||||
- change to 3 devices, it's not like m_hittype can be changed on the fly
|
||||
- is watchdog used by any driver? if not, watchdog device can be moved to here
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "kaneko_hit.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(KANEKO_HIT, kaneko_hit_device, "kaneko_hit", "Kaneko CALC Hitbox")
|
||||
|
||||
kaneko_hit_device::kaneko_hit_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, KANEKO_HIT, tag, owner, clock),
|
||||
m_watchdog(*this, "^watchdog")
|
||||
kaneko_hit_device::kaneko_hit_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, KANEKO_HIT, tag, owner, clock),
|
||||
m_watchdog(*this, "^watchdog")
|
||||
{
|
||||
m_hittype = -1;
|
||||
memset(&m_hit, 0, sizeof m_hit);
|
||||
@ -132,11 +137,14 @@ void kaneko_hit_device::kaneko_hit_w(offs_t offset, uint16_t data, uint16_t mem_
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
TYPE 0
|
||||
galpanica
|
||||
sandscrp
|
||||
bonkadv
|
||||
* airbustr
|
||||
* expro02
|
||||
* galpanica
|
||||
* sandscrp
|
||||
* bonkadv
|
||||
*********************************************************************/
|
||||
|
||||
uint16_t kaneko_hit_device::kaneko_hit_type0_r(offs_t offset)
|
||||
@ -220,8 +228,8 @@ void kaneko_hit_device::kaneko_hit_type0_w(offs_t offset, uint16_t data, uint16_
|
||||
|
||||
/*********************************************************************
|
||||
TYPE 1
|
||||
shogwarr
|
||||
bloorwar
|
||||
* shogwarr
|
||||
* bloorwar
|
||||
*********************************************************************/
|
||||
|
||||
uint16_t kaneko_hit_device::kaneko_hit_type1_r(offs_t offset)
|
||||
@ -230,7 +238,6 @@ uint16_t kaneko_hit_device::kaneko_hit_type1_r(offs_t offset)
|
||||
uint16_t data = 0;
|
||||
int16_t x_coll, y_coll;
|
||||
|
||||
|
||||
x_coll = calc_compute_x(hit);
|
||||
y_coll = calc_compute_y(hit);
|
||||
|
||||
@ -354,10 +361,9 @@ int16_t kaneko_hit_device::calc_compute_y(calc1_hit_t &hit)
|
||||
|
||||
/*********************************************************************
|
||||
TYPE 2
|
||||
brapboys
|
||||
* brapboys
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
void kaneko_hit_device::kaneko_hit_type2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
calc3_hit_t &hit3 = m_hit3;
|
||||
@ -369,54 +375,54 @@ void kaneko_hit_device::kaneko_hit_type2_w(offs_t offset, uint16_t data, uint16_
|
||||
// p is position, s is size
|
||||
case 0x00:
|
||||
case 0x28:
|
||||
|
||||
hit3.x1po = data; break;
|
||||
hit3.x1po = data; break;
|
||||
|
||||
case 0x04:
|
||||
case 0x2c:
|
||||
hit3.x1so = data; break;
|
||||
hit3.x1so = data; break;
|
||||
|
||||
case 0x08:
|
||||
case 0x30:
|
||||
hit3.y1po = data; break;
|
||||
hit3.y1po = data; break;
|
||||
|
||||
case 0x0c:
|
||||
case 0x34:
|
||||
hit3.y1so = data; break;
|
||||
hit3.y1so = data; break;
|
||||
|
||||
case 0x10:
|
||||
case 0x58:
|
||||
hit3.x2po = data; break;
|
||||
hit3.x2po = data; break;
|
||||
|
||||
case 0x14:
|
||||
case 0x5c:
|
||||
hit3.x2so = data; break;
|
||||
hit3.x2so = data; break;
|
||||
|
||||
case 0x18:
|
||||
case 0x60:
|
||||
hit3.y2po = data; break;
|
||||
hit3.y2po = data; break;
|
||||
|
||||
case 0x1c:
|
||||
case 0x64:
|
||||
hit3.y2so = data; break;
|
||||
hit3.y2so = data; break;
|
||||
|
||||
case 0x38:
|
||||
case 0x50:
|
||||
hit3.z1po = data; break;
|
||||
hit3.z1po = data; break;
|
||||
|
||||
case 0x3c:
|
||||
case 0x54:
|
||||
hit3.z1so = data; break;
|
||||
hit3.z1so = data; break;
|
||||
|
||||
case 0x20:
|
||||
case 0x68:
|
||||
hit3.z2po = data; break;
|
||||
hit3.z2po = data; break;
|
||||
|
||||
case 0x24:
|
||||
case 0x6c:
|
||||
hit3.z2so = data; break;
|
||||
hit3.z2so = data; break;
|
||||
|
||||
case 0x70:
|
||||
hit3.mode=data;break;
|
||||
hit3.mode = data; break;
|
||||
|
||||
default:
|
||||
logerror("%s warning - write unmapped hit address %06x [ %06x] = %06x\n",machine().describe_context(),offset<<1, idx, data);
|
||||
@ -477,7 +483,7 @@ uint16_t kaneko_hit_device::kaneko_hit_type2_r(offs_t offset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//calculate simple intersection of two segments
|
||||
// calculate simple intersection of two segments
|
||||
|
||||
int kaneko_hit_device::type2_calc_compute(int x1, int w1, int x2, int w2)
|
||||
{
|
||||
@ -485,21 +491,21 @@ int kaneko_hit_device::type2_calc_compute(int x1, int w1, int x2, int w2)
|
||||
|
||||
if(x2>=x1 && x2+w2<=(x1+w1))
|
||||
{
|
||||
//x2 inside x1
|
||||
// x2 inside x1
|
||||
dist=w2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(x1>=x2 && x1+w1<=(x2+w2))
|
||||
{
|
||||
//x1 inside x2
|
||||
// x1 inside x2
|
||||
dist=w1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(x2<x1)
|
||||
{
|
||||
//swap
|
||||
// swap
|
||||
int tmp=x1;
|
||||
x1=x2;
|
||||
x2=tmp;
|
||||
@ -513,7 +519,7 @@ int kaneko_hit_device::type2_calc_compute(int x1, int w1, int x2, int w2)
|
||||
return dist;
|
||||
}
|
||||
|
||||
//calc segment coordinates
|
||||
// calc segment coordinates
|
||||
|
||||
void kaneko_hit_device::type2_calc_org(int mode, int x0, int s0, int* x1, int* s1)
|
||||
{
|
||||
@ -524,12 +530,12 @@ void kaneko_hit_device::type2_calc_org(int mode, int x0, int s0, int* x1, int*
|
||||
case 2: *x1=x0-s0; *s1=s0; break;
|
||||
case 3: *x1=x0-s0; *s1=2*s0; break;
|
||||
}
|
||||
//x1 is the left most coord, s1 = width
|
||||
// x1 is the left most coord, s1 = width
|
||||
}
|
||||
|
||||
void kaneko_hit_device::type2_recalc_collisions(calc3_hit_t &hit3)
|
||||
{
|
||||
//calculate positions and sizes
|
||||
// calculate positions and sizes
|
||||
|
||||
int mode=hit3.mode;
|
||||
|
||||
@ -543,17 +549,14 @@ void kaneko_hit_device::type2_recalc_collisions(calc3_hit_t &hit3)
|
||||
type2_calc_org((mode>>10)&3, hit3.y2po, hit3.y2so, &hit3.y2p, &hit3.y2s);
|
||||
type2_calc_org((mode>>12)&3, hit3.z2po, hit3.z2so, &hit3.z2p, &hit3.z2s);
|
||||
|
||||
|
||||
hit3.x1tox2=abs(hit3.x2po-hit3.x1po);
|
||||
hit3.y1toy2=abs(hit3.y2po-hit3.y1po);
|
||||
hit3.z1toz2=abs(hit3.z2po-hit3.z1po);
|
||||
|
||||
|
||||
hit3.x_coll = type2_calc_compute(hit3.x1p, hit3.x1s, hit3.x2p, hit3.x2s);
|
||||
hit3.y_coll = type2_calc_compute(hit3.y1p, hit3.y1s, hit3.y2p, hit3.y2s);
|
||||
hit3.z_coll = type2_calc_compute(hit3.z1p, hit3.z1s, hit3.z2p, hit3.z2s);
|
||||
|
||||
|
||||
// 4th nibble: Y Absolute Collision -> possible values = 9,8,4,3,2
|
||||
if (hit3.y1p > hit3.y2p) hit3.flags |= 0x2000;
|
||||
else if (hit3.y1p == hit3.y2p) hit3.flags |= 0x4000;
|
||||
|
Loading…
Reference in New Issue
Block a user