cmmb: Misc. improvements (nw)

- Better flash mapping means the IRQ handler can run now without crashing
- Hooked up up/down and service2 (0) keys to navigate service mode
- Bankdev added to handle 2000-AFFF region
This commit is contained in:
arbee 2018-08-25 19:38:35 -04:00
parent de1637512b
commit a524a99cd0

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
// copyright-holders:Angelo Salese, R. Belmont
/***************************************************************************
Centipede / Millipede / Missile Command / Let's Go Bowling
@ -13,17 +13,17 @@ Earlier revisions of this cabinet did not include the bowling game.
a port or prototype of an old Atari game.
TODO:
- flash ROM hookup (by the looks of it, at29x needs an address map?);
- flash ROM hookup
- finish video emulation;
- trackball inputs
- sound;
- NVRAM (flash ROM, as per NVRAM test at 0xC2A7).
- untangle switch-cases for inputs;
- One bit of the control register seems to want to bank the flash into 2000-7FFF
which would require bankdev if verified.
- IRQ handler is super-strange, it wants to JMP ($7FFE) and JMP ($3FFE) a lot,
which currently sends the game off into the weeds.
- In fact, the game goes off into the weeds anyway right now due to doing that.
- IRQs are problematic. Haven't yet found a reliable enable that works
for both mainline and service mode; maybe there's no mask and the
processor's SEI/CLI instructions are used for that?
- If IRQs are enabled in service mode, they eventually trash all of memory.
Probably on the CPLD (CY39100V208B) - Quoted from Cosmodog's website:
"Instead, we used a programmable chip that we could reconfigure very
@ -52,6 +52,7 @@ OSC @ 72.576MHz
#include "emu.h"
#include "cpu/m6502/m65sc02.h"
#include "machine/at29x.h"
#include "machine/bankdev.h"
#include "emupal.h"
#include "screen.h"
@ -66,7 +67,8 @@ public:
m_flash(*this, "at29c020" ),
m_videoram(*this, "videoram"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette")
m_palette(*this, "palette"),
m_bnk2000(*this, "bnk2000")
{ }
required_device<cpu_device> m_maincpu;
@ -74,6 +76,7 @@ public:
required_shared_ptr<uint8_t> m_videoram;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
required_device<address_map_bank_device> m_bnk2000;
uint8_t m_irq_mask;
@ -81,26 +84,14 @@ public:
DECLARE_WRITE8_MEMBER(cmmb_charram_w);
DECLARE_READ8_MEMBER(cmmb_input_r);
DECLARE_WRITE8_MEMBER(cmmb_output_w);
DECLARE_WRITE8_MEMBER(flash_dbg_0_w);
DECLARE_WRITE8_MEMBER(flash_dbg_1_w);
DECLARE_WRITE8_MEMBER(irq_ack_w)
{
m_maincpu->set_input_line(0, CLEAR_LINE);
}
DECLARE_WRITE8_MEMBER(irq_enable_w)
{
m_irq_mask = data & 0x80;
}
//DECLARE_READ8_MEMBER(kludge_r);
virtual void machine_reset() override;
virtual void video_start() override;
uint32_t screen_update_cmmb(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(vblank_irq);
void cmmb(machine_config &config);
void cmmb_map(address_map &map);
void bnk2000_map(address_map &map);
};
@ -120,7 +111,7 @@ uint32_t cmmb_state::screen_update_cmmb(screen_device &screen, bitmap_ind16 &bit
{
for (x=0;x<32;x++)
{
int tile = videoram[count] & 0x3f;
int tile = videoram[count] & 0x7f;
int colour = (videoram[count] & 0xc0)>>6;
gfx->opaque(bitmap,cliprect,tile,colour,0,0,x*8,y*8);
@ -170,13 +161,18 @@ WRITE8_MEMBER(cmmb_state::cmmb_output_w)
//printf("%02x -> [%02x] W\n",data,offset);
switch(offset)
{
case 0x00: // IRQ ack? may also be 0x09.
m_maincpu->set_input_line(0, CLEAR_LINE);
//printf("IRQ ack\n");
break;
case 0x01:
// m_irq_mask = data & 0x80;
m_irq_mask = data;
break;
case 0x02:
// bit 7 toggled - watchdog or status LED
// toggled by code at E3DB in IRQ handler - it's on when the frame count & 0x30 is 1 and off otherwise
// bit 6 set means accessing flash ROM, possibly that entire 2000-7FFF banks over to the flash?
// bit 6 set means accessing flash ROM at 0x2000
m_bnk2000->set_bank((data & 0x40) ? 1 : 0);
break;
case 0x03:
@ -184,55 +180,57 @@ WRITE8_MEMBER(cmmb_state::cmmb_output_w)
uint8_t *ROM = memregion("maincpu")->base();
uint32_t bankaddress;
bankaddress = 0x10000 + (0x4000 * (data & 0x0f));
//bankaddress = 0x10000 + (0x4000 * ((data & 0x0f)^0xf));
//printf("bank %02x => %x\n", data, bankaddress);
bankaddress = 0x10000 + 0x3a000;
membank("bank1")->set_base(&ROM[bankaddress]);
// bit 7 sub-devCB's flash at 0x2000-0x4000?
}
break;
case 0x07:
break;
case 0x09:
break;
}
}
WRITE8_MEMBER(cmmb_state::flash_dbg_0_w)
{
m_flash->write(space,0x2aaa,data);
}
WRITE8_MEMBER(cmmb_state::flash_dbg_1_w)
{
m_flash->write(space,0x5555,data);
}
/* overlap empty addresses */
void cmmb_state::cmmb_map(address_map &map)
{
map.global_mask(0xffff);
map(0x0000, 0x0fff).ram(); /* zero page address */
// AM_RANGE(0x13c0, 0x13ff) AM_RAM //spriteram
map(0x1000, 0x13ff).ram().share("videoram");
map(0x2000, 0x2000).portr("IN3");
map(0x2001, 0x2001).portr("IN4");
map(0x2011, 0x2011).portr("IN5");
map(0x2480, 0x249f).ram().w(m_palette, FUNC(palette_device::write8)).share("palette");
map(0x2505, 0x2505).w(FUNC(cmmb_state::irq_enable_w));
map(0x2600, 0x2600).w(FUNC(cmmb_state::irq_ack_w));
//AM_RANGE(0x4000, 0x400f) AM_READWRITE(cmmb_input_r,cmmb_output_w)
//AM_RANGE(0x4900, 0x4900) AM_READ(kludge_r)
map(0x4000, 0x7fff).bankr("bank1");
map(0x8000, 0x9fff).rom().region("maincpu", 0x18000);
map(0x1000, 0x1fff).ram().share("videoram");
map(0x2000, 0x9fff).m(m_bnk2000, FUNC(address_map_bank_device::amap8));
map(0xa000, 0xafff).ram();
map(0xb000, 0xbfff).rw(FUNC(cmmb_state::cmmb_charram_r), FUNC(cmmb_state::cmmb_charram_w));
map(0xc000, 0xc00f).rw(FUNC(cmmb_state::cmmb_input_r), FUNC(cmmb_state::cmmb_output_w));
// debugging, to be removed
// AM_RANGE(0x2aaa, 0x2aaa) AM_WRITE(flash_dbg_0_w)
// AM_RANGE(0x5555, 0x5555) AM_WRITE(flash_dbg_1_w)
map(0xc010, 0xffff).rom().region("maincpu", 0x1c010);
}
void cmmb_state::bnk2000_map(address_map &map)
{
map(0x0000, 0x5fff).bankr("bank1");
map(0x0000, 0x0000).portr("IN3");
map(0x0001, 0x0001).portr("IN4");
map(0x0011, 0x0011).portr("IN5");
map(0x0480, 0x049f).ram().w(m_palette, FUNC(palette_device::write8)).share("palette");
// map(0x0505, 0x0505).w(FUNC(cmmb_state::irq_enable_w));
// map(0x0600, 0x0600).w(FUNC(cmmb_state::irq_ack_w));
map(0x0680, 0x0680).nopw();
map(0x6000, 0x7fff).rom().region("maincpu", 0x18000);
map(0x8000, 0xffff).rw("at29c020", FUNC(at29c020_device::read), FUNC(at29c020_device::write));
}
static INPUT_PORTS_START( cmmb )
PORT_START("IN3")
#if 1
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
PORT_BIT( 0xcf, IP_ACTIVE_LOW, IPT_UNKNOWN )
#else
PORT_DIPNAME( 0x01, 0x01, "IN3" )
PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
@ -257,8 +255,13 @@ static INPUT_PORTS_START( cmmb )
PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
#endif
PORT_START("IN4")
#if 1
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
PORT_BIT( 0xdf, IP_ACTIVE_LOW, IPT_UNKNOWN)
#else
PORT_DIPNAME( 0x01, 0x01, "IN4" )
PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
@ -283,9 +286,9 @@ static INPUT_PORTS_START( cmmb )
PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
#endif
// TODO: pin-point writes for trackball
// TODO: trackball might be muxed for 1p & 2p sides
// TODO: bit 7 of 0x2507 selects trackball 1 and 2
PORT_START("IN5")
PORT_DIPNAME( 0x01, 0x01, "IN5" ) // trackball V clk
PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
@ -331,7 +334,7 @@ static INPUT_PORTS_START( cmmb )
PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 )
PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
PORT_DIPNAME( 0x40, 0x40, "Magic" ) // makes part of the IRQ handler skip if ON
PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x80, 0x80, DEF_STR( Service_Mode ) )
@ -356,12 +359,7 @@ static INPUT_PORTS_START( cmmb )
PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // if this is lit up, coins will auto-insert each frame until they hit 99 (?!)
INPUT_PORTS_END
static const gfx_layout charlayout =
@ -394,12 +392,10 @@ GFXDECODE_END
INTERRUPT_GEN_MEMBER(cmmb_state::vblank_irq)
{
#if 0
if (m_irq_mask & 0x80)
if (m_irq_mask & 0x08)
{
m_maincpu->set_input_line(0, ASSERT_LINE);
}
#endif
}
void cmmb_state::machine_reset()
@ -417,6 +413,8 @@ MACHINE_CONFIG_START(cmmb_state::cmmb)
AT29C020(config, "at29c020");
ADDRESS_MAP_BANK(config, "bnk2000").set_map(&cmmb_state::bnk2000_map).set_options(ENDIANNESS_LITTLE, 8, 32, 0x8000);
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_RAW_PARAMS(MAIN_CLOCK/12, 384, 0, 256, 264, 0, 240) // TBD, not real measurements
@ -446,7 +444,6 @@ ROM_START( cmmb162 )
ROM_LOAD( "cmmb162.u2", 0x10000, 0x40000, CRC(71a5a75d) SHA1(0ad7b97580082cda98cb1e8aab8efcf491d0ed25) )
ROM_COPY( "maincpu", 0x18000, 0x08000, 0x08000 )
ROM_FILL( 0x1c124, 2, 0xea ) // temporary patch to avoid waiting on IRQs
ROM_FILL( 0x1e3c3, 3, 0xea ) // patch out weird IRQ handler code that causes reboot each IRQ
ROM_REGION( 0x1000, "gfx", ROMREGION_ERASE00 )
ROM_END