taito/qix.cpp: Fixed some issues and cleaned up code: (#13387)

* Use palette device for palette.
* Suppress side effects for debugger reads.
* Moved kram3 to a derived state class.
* Use logmacro.h helpers for configurable logging, made some variables const.
* Reduced literal tags, improved tags and member function names.
* Reduced preprocessor macros and duplicated code.
This commit is contained in:
cam900 2025-02-22 06:55:04 +09:00 committed by GitHub
parent ba5268cfc6
commit 36f61767f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 373 additions and 374 deletions

View File

@ -238,54 +238,86 @@ Interrupts:
/*************************************
*
* Slither SN76489 I/O
*
*************************************/
template <unsigned Which>
void slither_state::sn76489_ctrl_w(int state)
{
// write to the sound chip
if (!state && m_sn76489_ctrl[Which])
m_sn[Which]->write(m_pia[Which + 1]->b_output());
m_sn76489_ctrl[Which] = bool(state);
}
/*************************************
*
* Slither trackball I/O
*
*************************************/
template <unsigned Which>
uint8_t slither_state::trak_r()
{
return m_trak[Which + (m_flip ? 2 : 0)]->read();
}
/************************************* /*************************************
* *
* Data CPU memory handlers * Data CPU memory handlers
* *
*************************************/ *************************************/
void qix_state::main_map(address_map &map) void qix_state::qix_main_map(address_map &map)
{ {
map(0x8000, 0x83ff).ram().share("share1"); map(0x8000, 0x83ff).ram().share("sharedram");
map(0x8400, 0x87ff).ram(); map(0x8400, 0x87ff).ram();
map(0x8800, 0x8bff).nopr(); /* 6850 ACIA */ map(0x8800, 0x8bff).nopr(); /* 6850 ACIA */
map(0x8c00, 0x8c00).mirror(0x3fe).rw(FUNC(qix_state::qix_video_firq_r), FUNC(qix_state::qix_video_firq_w)); map(0x8c00, 0x8c00).mirror(0x3fe).rw(FUNC(qix_state::video_firq_r), FUNC(qix_state::video_firq_w));
map(0x8c01, 0x8c01).mirror(0x3fe).rw(FUNC(qix_state::qix_data_firq_ack_r), FUNC(qix_state::qix_data_firq_ack_w)); map(0x8c01, 0x8c01).mirror(0x3fe).rw(FUNC(qix_state::data_firq_ack_r), FUNC(qix_state::data_firq_ack_w));
map(0x9000, 0x93ff).rw(m_sndpia0, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x9000, 0x93ff).rw(m_sndpia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x9400, 0x97ff).r(m_pia0, FUNC(pia6821_device::read)).w(FUNC(qix_state::qix_pia_w)); map(0x9400, 0x97ff).r(m_pia[0], FUNC(pia6821_device::read)).w(FUNC(qix_state::pia_w));
map(0x9800, 0x9bff).rw(m_pia1, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x9800, 0x9bff).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x9c00, 0x9fff).rw(m_pia2, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x9c00, 0x9fff).rw(m_pia[2], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0xa000, 0xffff).rom(); map(0xa000, 0xffff).rom();
} }
void qix_state::kram3_main_map(address_map &map) void kram3_state::main_map(address_map &map)
{ {
map(0x8000, 0x83ff).ram().share("share1"); map(0x8000, 0x83ff).ram().share("sharedram");
map(0x8400, 0x87ff).ram(); map(0x8400, 0x87ff).ram();
map(0x8800, 0x8bff).nopr(); /* 6850 ACIA */ map(0x8800, 0x8bff).nopr(); /* 6850 ACIA */
map(0x8c00, 0x8c00).mirror(0x3fe).rw(FUNC(qix_state::qix_video_firq_r), FUNC(qix_state::qix_video_firq_w)); map(0x8c00, 0x8c00).mirror(0x3fe).rw(FUNC(kram3_state::video_firq_r), FUNC(kram3_state::video_firq_w));
map(0x8c01, 0x8c01).mirror(0x3fe).rw(FUNC(qix_state::qix_data_firq_ack_r), FUNC(qix_state::qix_data_firq_ack_w)); map(0x8c01, 0x8c01).mirror(0x3fe).rw(FUNC(kram3_state::data_firq_ack_r), FUNC(kram3_state::data_firq_ack_w));
map(0x9000, 0x93ff).rw(m_sndpia0, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x9000, 0x93ff).rw(m_sndpia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x9400, 0x97ff).r(m_pia0, FUNC(pia6821_device::read)).w(FUNC(qix_state::qix_pia_w)); map(0x9400, 0x97ff).r(m_pia[0], FUNC(pia6821_device::read)).w(FUNC(kram3_state::pia_w));
map(0x9800, 0x9bff).rw(m_pia1, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x9800, 0x9bff).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x9c00, 0x9fff).rw(m_pia2, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x9c00, 0x9fff).rw(m_pia[2], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0xa000, 0xffff).bankr("bank0"); map(0xa000, 0xffff).bankr(m_mainbank);
} }
void zookeep_state::main_map(address_map &map) void zookeep_state::main_map(address_map &map)
{ {
map(0x0000, 0x03ff).ram().share("share1"); map(0x0000, 0x03ff).ram().share("sharedram");
map(0x0400, 0x07ff).ram(); map(0x0400, 0x07ff).ram();
map(0x0800, 0x0bff).nopr(); /* ACIA */ map(0x0800, 0x0bff).nopr(); /* ACIA */
map(0x0c00, 0x0c00).mirror(0x3fe).rw(FUNC(zookeep_state::qix_video_firq_r), FUNC(zookeep_state::qix_video_firq_w)); map(0x0c00, 0x0c00).mirror(0x3fe).rw(FUNC(zookeep_state::video_firq_r), FUNC(zookeep_state::video_firq_w));
map(0x0c01, 0x0c01).mirror(0x3fe).rw(FUNC(zookeep_state::qix_data_firq_ack_r), FUNC(zookeep_state::qix_data_firq_ack_w)); map(0x0c01, 0x0c01).mirror(0x3fe).rw(FUNC(zookeep_state::data_firq_ack_r), FUNC(zookeep_state::data_firq_ack_w));
map(0x1000, 0x13ff).rw(m_sndpia0, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x1000, 0x13ff).rw(m_sndpia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x1400, 0x17ff).r(m_pia0, FUNC(pia6821_device::read)).w(FUNC(zookeep_state::qix_pia_w)); map(0x1400, 0x17ff).r(m_pia[0], FUNC(pia6821_device::read)).w(FUNC(zookeep_state::pia_w));
map(0x1800, 0x1bff).rw(m_pia1, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x1800, 0x1bff).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x1c00, 0x1fff).rw(m_pia2, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x1c00, 0x1fff).rw(m_pia[2], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x8000, 0xffff).rom(); map(0x8000, 0xffff).rom();
} }
@ -604,7 +636,7 @@ void qix_state::qix_base(machine_config &config)
{ {
/* basic machine hardware */ /* basic machine hardware */
MC6809E(config, m_maincpu, MAIN_CLOCK_OSC/4/4); /* 1.25 MHz */ MC6809E(config, m_maincpu, MAIN_CLOCK_OSC/4/4); /* 1.25 MHz */
m_maincpu->set_addrmap(AS_PROGRAM, &qix_state::main_map); m_maincpu->set_addrmap(AS_PROGRAM, &qix_state::qix_main_map);
// high interleave needed to ensure correct text in service mode // high interleave needed to ensure correct text in service mode
// Zookeeper settings and high score table seem especially sensitive to this // Zookeeper settings and high score table seem especially sensitive to this
@ -612,21 +644,21 @@ void qix_state::qix_base(machine_config &config)
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
PIA6821(config, m_pia0); PIA6821(config, m_pia[0]);
m_pia0->readpa_handler().set_ioport("P1"); m_pia[0]->readpa_handler().set_ioport("P1");
m_pia0->set_port_a_input_overrides_output_mask(0xff); m_pia[0]->set_port_a_input_overrides_output_mask(0xff);
m_pia0->readpb_handler().set_ioport("COIN"); m_pia[0]->readpb_handler().set_ioport("COIN");
PIA6821(config, m_pia1); PIA6821(config, m_pia[1]);
m_pia1->readpa_handler().set_ioport("SPARE"); m_pia[1]->readpa_handler().set_ioport("SPARE");
m_pia1->set_port_a_input_overrides_output_mask(0xff); m_pia[1]->set_port_a_input_overrides_output_mask(0xff);
m_pia1->readpb_handler().set_ioport("IN0"); m_pia[1]->readpb_handler().set_ioport("IN0");
PIA6821(config, m_pia2); PIA6821(config, m_pia[2]);
m_pia2->readpa_handler().set_ioport("P2"); m_pia[2]->readpa_handler().set_ioport("P2");
m_pia2->set_port_a_input_overrides_output_mask(0xff); m_pia[2]->set_port_a_input_overrides_output_mask(0xff);
m_pia2->writepb_handler().set(FUNC(qix_state::qix_coinctl_w)); m_pia[2]->writepb_handler().set(FUNC(qix_state::coinctr_w));
m_pia2->tspb_handler().set_constant(0); m_pia[2]->tspb_handler().set_constant(0);
/* video hardware */ /* video hardware */
qix_video(config); qix_video(config);
@ -639,13 +671,13 @@ void qix_state::qix(machine_config &config)
qix_audio(config); qix_audio(config);
} }
void qix_state::kram3(machine_config &config) void kram3_state::kram3(machine_config &config)
{ {
qix(config); qix(config);
m_maincpu->set_addrmap(AS_PROGRAM, &qix_state::kram3_main_map); m_maincpu->set_addrmap(AS_PROGRAM, &kram3_state::main_map);
m_maincpu->lic().set(FUNC(qix_state::kram3_lic_maincpu_changed)); m_maincpu->lic().set(FUNC(kram3_state::lic_maincpu_changed));
kram3_video(config); video(config);
} }
/*************************************************************************** /***************************************************************************
@ -660,6 +692,7 @@ void qixmcu_state::mcu(machine_config &config)
qix(config); qix(config);
/* basic machine hardware */ /* basic machine hardware */
constexpr XTAL COIN_CLOCK_OSC = XTAL(4'000'000); /* 4 MHz */
M68705P3(config, m_mcu, COIN_CLOCK_OSC); /* 1.00 MHz */ M68705P3(config, m_mcu, COIN_CLOCK_OSC); /* 1.00 MHz */
m_mcu->portb_r().set(FUNC(qixmcu_state::mcu_portb_r)); m_mcu->portb_r().set(FUNC(qixmcu_state::mcu_portb_r));
@ -667,10 +700,10 @@ void qixmcu_state::mcu(machine_config &config)
m_mcu->porta_w().set(FUNC(qixmcu_state::mcu_porta_w)); m_mcu->porta_w().set(FUNC(qixmcu_state::mcu_porta_w));
m_mcu->portb_w().set(FUNC(qixmcu_state::mcu_portb_w)); m_mcu->portb_w().set(FUNC(qixmcu_state::mcu_portb_w));
m_pia0->readpb_handler().set(FUNC(qixmcu_state::coin_r)); m_pia[0]->readpb_handler().set(FUNC(qixmcu_state::coin_r));
m_pia0->writepb_handler().set(FUNC(qixmcu_state::coin_w)); m_pia[0]->writepb_handler().set(FUNC(qixmcu_state::coin_w));
m_pia2->writepb_handler().set(FUNC(qixmcu_state::coinctrl_w)); m_pia[2]->writepb_handler().set(FUNC(qixmcu_state::coinctrl_w));
} }
@ -703,20 +736,20 @@ void slither_state::slither(machine_config &config)
m_maincpu->set_clock(SLITHER_CLOCK_OSC/4/4); /* 1.34 MHz */ m_maincpu->set_clock(SLITHER_CLOCK_OSC/4/4); /* 1.34 MHz */
m_pia1->readpa_handler().set(FUNC(slither_state::trak_lr_r)); m_pia[1]->readpa_handler().set(FUNC(slither_state::trak_r<1>));
m_pia1->cb2_handler().set(FUNC(slither_state::sn76489_0_ctrl_w)); m_pia[1]->cb2_handler().set(FUNC(slither_state::sn76489_ctrl_w<0>));
m_pia1->readpb_handler().set_constant(0); m_pia[1]->readpb_handler().set_constant(0);
m_pia2->readpa_handler().set(FUNC(slither_state::trak_ud_r)); m_pia[2]->readpa_handler().set(FUNC(slither_state::trak_r<0>));
m_pia2->writepb_handler().set_nop(); m_pia[2]->writepb_handler().set_nop();
m_pia2->cb2_handler().set(FUNC(slither_state::sn76489_1_ctrl_w)); m_pia[2]->cb2_handler().set(FUNC(slither_state::sn76489_ctrl_w<1>));
m_pia2->readpb_handler().set_constant(0); m_pia[2]->readpb_handler().set_constant(0);
/* video hardware */ /* video hardware */
slither_video(config); video(config);
/* audio hardware */ /* audio hardware */
slither_audio(config); audio(config);
} }
@ -1337,7 +1370,7 @@ static const uint8_t xor2_table[] =
99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,11, 6,99, 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,11, 6,99,
}; };
int qix_state::kram3_permut1(int idx, int value) static inline int kram3_permut1(int idx, int value)
{ {
switch (idx) switch (idx)
{ {
@ -1349,7 +1382,7 @@ int qix_state::kram3_permut1(int idx, int value)
} }
} }
int qix_state::kram3_permut2(int tbl_index, int idx, const uint8_t *xor_table) static inline int kram3_permut2(int tbl_index, int idx, const uint8_t *xor_table)
{ {
int xorval = 0; int xorval = 0;
@ -1370,7 +1403,7 @@ int qix_state::kram3_permut2(int tbl_index, int idx, const uint8_t *xor_table)
return xorval; return xorval;
} }
int qix_state::kram3_decrypt(int address, int value) static inline int kram3_decrypt(int address, int value)
{ {
int indx1 = (BIT(address,1) << 1) | BIT(address,5); int indx1 = (BIT(address,1) << 1) | BIT(address,5);
int indx2 = (BIT(address,7) << 1) | BIT(address,3); int indx2 = (BIT(address,7) << 1) | BIT(address,3);
@ -1396,11 +1429,11 @@ int qix_state::kram3_decrypt(int address, int value)
return ((bits2 & 0xe) << 4) | ((bits1 & 0x8) << 1) | ((bits2 & 0x1) << 3) | ((bits1 & 0x7) << 0); return ((bits2 & 0xe) << 4) | ((bits1 & 0x8) << 1) | ((bits2 & 0x1) << 3) | ((bits1 & 0x7) << 0);
} }
void qix_state::init_kram3() void kram3_state::init_kram3()
{ {
//const uint8_t *patch; //const uint8_t *patch;
assert(m_bank0); assert(m_mainbank);
assert(m_bank1); assert(m_videobank);
/******************************** /********************************
@ -1418,41 +1451,41 @@ void qix_state::init_kram3()
//patch = memregion("user1")->base(); //patch = memregion("user1")->base();
uint8_t *rom = memregion("maincpu")->base(); uint8_t *rom = memregion("maincpu")->base();
m_decrypted = std::make_unique<uint8_t[]>(0x6000); m_main_decrypted = std::make_unique<uint8_t[]>(0x6000);
memcpy(m_decrypted.get(),&rom[0xa000],0x6000); memcpy(m_main_decrypted.get(),&rom[0xa000],0x6000);
for (int i = 0xa000; i < 0x10000; ++i) for (int i = 0xa000; i < 0x10000; ++i)
{ {
m_decrypted[i-0xa000] = kram3_decrypt(i, rom[i]); m_main_decrypted[i - 0xa000] = kram3_decrypt(i, rom[i]);
} }
m_bank0->configure_entry(0, memregion("maincpu")->base() + 0xa000); m_mainbank->configure_entry(0, memregion("maincpu")->base() + 0xa000);
m_bank0->configure_entry(1, m_decrypted.get()); m_mainbank->configure_entry(1, m_main_decrypted.get());
m_bank0->set_entry(0); m_mainbank->set_entry(0);
//patch = memregion("user2")->base(); //patch = memregion("user2")->base();
rom = memregion("videocpu")->base(); rom = memregion("videocpu")->base();
m_decrypted2 = std::make_unique<uint8_t[]>(0x6000); m_video_decrypted = std::make_unique<uint8_t[]>(0x6000);
memcpy(m_decrypted2.get(),&rom[0xa000],0x6000); memcpy(m_video_decrypted.get(),&rom[0xa000],0x6000);
for (int i = 0xa000; i < 0x10000; ++i) for (int i = 0xa000; i < 0x10000; ++i)
{ {
m_decrypted2[i-0xa000] = kram3_decrypt(i, rom[i]); m_video_decrypted[i - 0xa000] = kram3_decrypt(i, rom[i]);
} }
m_bank1->configure_entry(0, memregion("videocpu")->base() + 0xa000); m_videobank->configure_entry(0, memregion("videocpu")->base() + 0xa000);
m_bank1->configure_entry(1, m_decrypted2.get()); m_videobank->configure_entry(1, m_video_decrypted.get());
m_bank1->set_entry(0); m_videobank->set_entry(0);
} }
void qix_state::kram3_lic_maincpu_changed(int state) void kram3_state::lic_maincpu_changed(int state)
{ {
m_bank0->set_entry( state ? 1 : 0 ); m_mainbank->set_entry(state ? 1 : 0);
} }
void qix_state::kram3_lic_videocpu_changed(int state) void kram3_state::lic_videocpu_changed(int state)
{ {
m_bank1->set_entry( state ? 1 : 0 ); m_videobank->set_entry(state ? 1 : 0);
} }
/************************************* /*************************************
@ -1476,7 +1509,7 @@ GAMEL(1982, elecyoyoa, elecyoyo, mcu, elecyoyo, qixmcu_state, empty_init,
GAME( 1982, kram, 0, mcu, kram, qixmcu_state, empty_init, ROT0, "Taito America Corporation", "Kram (rev 1)", MACHINE_SUPPORTS_SAVE ) GAME( 1982, kram, 0, mcu, kram, qixmcu_state, empty_init, ROT0, "Taito America Corporation", "Kram (rev 1)", MACHINE_SUPPORTS_SAVE )
GAME( 1982, krama, kram, mcu, kram, qixmcu_state, empty_init, ROT0, "Taito America Corporation", "Kram", MACHINE_SUPPORTS_SAVE ) GAME( 1982, krama, kram, mcu, kram, qixmcu_state, empty_init, ROT0, "Taito America Corporation", "Kram", MACHINE_SUPPORTS_SAVE )
GAME( 1982, krame, kram, kram3, kram, qix_state, init_kram3, ROT0, "Taito America Corporation", "Kram (encrypted)", MACHINE_UNEMULATED_PROTECTION | MACHINE_SUPPORTS_SAVE ) GAME( 1982, krame, kram, kram3, kram, kram3_state, init_kram3, ROT0, "Taito America Corporation", "Kram (encrypted)", MACHINE_UNEMULATED_PROTECTION | MACHINE_SUPPORTS_SAVE )
GAME( 1982, zookeep, 0, zookeep, zookeep, zookeep_state, empty_init, ROT0, "Taito America Corporation", "Zoo Keeper (set 1)", MACHINE_SUPPORTS_SAVE ) GAME( 1982, zookeep, 0, zookeep, zookeep, zookeep_state, empty_init, ROT0, "Taito America Corporation", "Zoo Keeper (set 1)", MACHINE_SUPPORTS_SAVE )
GAME( 1982, zookeep2, zookeep, zookeep, zookeep, zookeep_state, empty_init, ROT0, "Taito America Corporation", "Zoo Keeper (set 2)", MACHINE_SUPPORTS_SAVE ) GAME( 1982, zookeep2, zookeep, zookeep, zookeep, zookeep_state, empty_init, ROT0, "Taito America Corporation", "Zoo Keeper (set 2)", MACHINE_SUPPORTS_SAVE )

View File

@ -21,15 +21,10 @@
#include "video/mc6845.h" #include "video/mc6845.h"
#include "emupal.h"
#include "screen.h" #include "screen.h"
#define MAIN_CLOCK_OSC 20000000 /* 20 MHz */
#define SLITHER_CLOCK_OSC 21300000 /* 21.3 MHz */
#define SOUND_CLOCK_OSC 7372800 /* 7.3728 MHz */
#define COIN_CLOCK_OSC 4000000 /* 4 MHz */
#define QIX_CHARACTER_CLOCK (20000000/2/16)
class qix_state : public driver_device class qix_state : public driver_device
{ {
public: public:
@ -39,33 +34,22 @@ public:
m_audiocpu(*this, "audiocpu"), m_audiocpu(*this, "audiocpu"),
m_videocpu(*this, "videocpu"), m_videocpu(*this, "videocpu"),
m_crtc(*this, "vid_u18"), m_crtc(*this, "vid_u18"),
m_pia0(*this, "pia0"), m_pia(*this, "pia%u", 0U),
m_pia1(*this, "pia1"), m_sndpia(*this, "sndpia%u", 0U),
m_pia2(*this, "pia2"),
m_sndpia0(*this, "sndpia0"),
m_sndpia1(*this, "sndpia1"),
m_sndpia2(*this, "sndpia2"),
m_discrete(*this, "discrete"), m_discrete(*this, "discrete"),
m_paletteram(*this, "paletteram"), m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_videoram(*this, "videoram", 0x10000, ENDIANNESS_BIG), m_videoram(*this, "videoram", 0x10000, ENDIANNESS_BIG),
m_videoram_address(*this, "videoram_addr"), m_videoram_address(*this, "videoram_addr"),
m_videoram_mask(*this, "videoram_mask"),
m_scanline_latch(*this, "scanline_latch"), m_scanline_latch(*this, "scanline_latch"),
m_bank0(*this, "bank0"), m_videobank(*this, "videobank")
m_bank1(*this, "bank1"),
m_screen(*this, "screen")
{ } { }
void qix_base(machine_config &config); void qix(machine_config &config) ATTR_COLD;
void qix(machine_config &config);
void qix_video(machine_config &config);
void qix_audio(machine_config &config);
void kram3(machine_config &config);
void kram3_video(machine_config &config);
void init_kram3();
protected: protected:
static constexpr XTAL MAIN_CLOCK_OSC = XTAL(20'000'000); /* 20 MHz */
virtual void video_start() override ATTR_COLD; virtual void video_start() override ATTR_COLD;
/* devices */ /* devices */
@ -73,106 +57,129 @@ protected:
optional_device<cpu_device> m_audiocpu; optional_device<cpu_device> m_audiocpu;
required_device<mc6809e_device> m_videocpu; required_device<mc6809e_device> m_videocpu;
required_device<mc6845_device> m_crtc; required_device<mc6845_device> m_crtc;
required_device<pia6821_device> m_pia0; required_device_array<pia6821_device, 3> m_pia;
required_device<pia6821_device> m_pia1; optional_device_array<pia6821_device, 3> m_sndpia;
required_device<pia6821_device> m_pia2;
required_device<pia6821_device> m_sndpia0;
optional_device<pia6821_device> m_sndpia1;
optional_device<pia6821_device> m_sndpia2;
optional_device<discrete_sound_device> m_discrete; optional_device<discrete_sound_device> m_discrete;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
/* video state */ /* video state */
required_shared_ptr<uint8_t> m_paletteram;
memory_share_creator<uint8_t> m_videoram; memory_share_creator<uint8_t> m_videoram;
required_shared_ptr<uint8_t> m_videoram_address; required_shared_ptr<uint8_t> m_videoram_address;
optional_shared_ptr<uint8_t> m_videoram_mask;
required_shared_ptr<uint8_t> m_scanline_latch; required_shared_ptr<uint8_t> m_scanline_latch;
uint8_t m_flip = 0U;
optional_memory_bank m_videobank;
bool m_flip = false;
uint8_t m_palette_bank = 0U; uint8_t m_palette_bank = 0U;
uint8_t m_leds = 0U; uint8_t m_leds = 0U;
optional_memory_bank m_bank0; static rgb_t qix_R2G2B2I2(uint32_t raw);
optional_memory_bank m_bank1; void data_firq_w(uint8_t data);
required_device<screen_device> m_screen; void data_firq_ack_w(uint8_t data);
std::unique_ptr<uint8_t[]> m_decrypted; uint8_t data_firq_r(address_space &space);
std::unique_ptr<uint8_t[]> m_decrypted2; uint8_t data_firq_ack_r(address_space &space);
void video_firq_w(uint8_t data);
pen_t m_pens[0x400]{}; void video_firq_ack_w(uint8_t data);
void qix_data_firq_w(uint8_t data); uint8_t video_firq_r(address_space &space);
void qix_data_firq_ack_w(uint8_t data); uint8_t video_firq_ack_r(address_space &space);
uint8_t qix_data_firq_r(address_space &space); uint8_t videoram_r(offs_t offset);
uint8_t qix_data_firq_ack_r(address_space &space); void videoram_w(offs_t offset, uint8_t data);
void qix_video_firq_w(uint8_t data); uint8_t addresslatch_r();
void qix_video_firq_ack_w(uint8_t data); void addresslatch_w(uint8_t data);
uint8_t qix_video_firq_r(address_space &space); void paletteram_w(offs_t offset, uint8_t data);
uint8_t qix_video_firq_ack_r(address_space &space); void palettebank_w(uint8_t data);
uint8_t qix_videoram_r(offs_t offset);
void qix_videoram_w(offs_t offset, uint8_t data);
uint8_t qix_addresslatch_r(offs_t offset);
void qix_addresslatch_w(offs_t offset, uint8_t data);
void qix_paletteram_w(offs_t offset, uint8_t data);
void qix_palettebank_w(uint8_t data);
TIMER_CALLBACK_MEMBER(pia_w_callback); TIMER_CALLBACK_MEMBER(pia_w_callback);
TIMER_CALLBACK_MEMBER(deferred_sndpia1_porta_w); TIMER_CALLBACK_MEMBER(deferred_sndpia1_porta_w);
void qix_vsync_changed(int state); void vsync_changed(int state);
void qix_pia_w(offs_t offset, uint8_t data); void pia_w(offs_t offset, uint8_t data);
void qix_coinctl_w(uint8_t data); void coinctr_w(uint8_t data);
void display_enable_changed(int state); void display_enable_changed(int state);
void qix_flip_screen_w(int state); void flip_screen_w(int state);
void qix_dac_w(uint8_t data); void dac_w(uint8_t data);
void qix_vol_w(uint8_t data); void vol_w(uint8_t data);
void sndpia_2_warning_w(uint8_t data); void sndpia_2_warning_w(uint8_t data);
void sync_sndpia1_porta_w(uint8_t data); void sync_sndpia1_porta_w(uint8_t data);
MC6845_BEGIN_UPDATE(crtc_begin_update); MC6845_BEGIN_UPDATE(crtc_begin_update);
MC6845_UPDATE_ROW(crtc_update_row); MC6845_UPDATE_ROW(crtc_update_row);
void set_pen(int offs);
int kram3_permut1(int idx, int value); void qix_base(machine_config &config) ATTR_COLD;
int kram3_permut2(int tbl_index, int idx, const uint8_t *xor_table); void qix_video(machine_config &config) ATTR_COLD;
int kram3_decrypt(int address, int value); void qix_audio(machine_config &config) ATTR_COLD;
void kram3_lic_maincpu_changed(int state);
void kram3_lic_videocpu_changed(int state);
void audio_map(address_map &map) ATTR_COLD; void audio_map(address_map &map) ATTR_COLD;
void kram3_main_map(address_map &map) ATTR_COLD; void qix_main_map(address_map &map) ATTR_COLD;
void kram3_video_map(address_map &map) ATTR_COLD;
void main_map(address_map &map) ATTR_COLD;
void qix_video_map(address_map &map) ATTR_COLD; void qix_video_map(address_map &map) ATTR_COLD;
}; };
// with encrypted CPU opcode
class kram3_state : public qix_state
{
public:
kram3_state(const machine_config &mconfig, device_type type, const char *tag) :
qix_state(mconfig, type, tag),
m_mainbank(*this, "mainbank")
{ }
void kram3(machine_config &config) ATTR_COLD;
void init_kram3();
protected:
void video(machine_config &config) ATTR_COLD;
void main_map(address_map &map) ATTR_COLD;
void video_map(address_map &map) ATTR_COLD;
private:
void lic_maincpu_changed(int state);
void lic_videocpu_changed(int state);
std::unique_ptr<uint8_t[]> m_main_decrypted;
std::unique_ptr<uint8_t[]> m_video_decrypted;
required_memory_bank m_mainbank;
};
// with different sound system, video RAM write masking feature
class slither_state : public qix_state class slither_state : public qix_state
{ {
public: public:
slither_state(const machine_config &mconfig, device_type type, const char *tag) : slither_state(const machine_config &mconfig, device_type type, const char *tag) :
qix_state(mconfig, type, tag), qix_state(mconfig, type, tag),
m_sn(*this, "sn%u", 1U), m_sn(*this, "sn%u", 1U),
m_videoram_mask(*this, "videoram_mask"),
m_trak(*this, "AN%u", 0U) m_trak(*this, "AN%u", 0U)
{ } { }
void slither(machine_config &config); void slither(machine_config &config) ATTR_COLD;
void slither_video(machine_config &config);
void slither_audio(machine_config &config);
protected: protected:
virtual void machine_start() override ATTR_COLD; virtual void machine_start() override ATTR_COLD;
private: void video(machine_config &config) ATTR_COLD;
uint8_t trak_lr_r(); void audio(machine_config &config) ATTR_COLD;
uint8_t trak_ud_r();
void sn76489_0_ctrl_w(int state);
void sn76489_1_ctrl_w(int state);
void slither_coinctl_w(uint8_t data);
void slither_videoram_w(offs_t offset, uint8_t data);
void slither_addresslatch_w(offs_t offset, uint8_t data);
void slither_video_map(address_map &map) ATTR_COLD; void video_map(address_map &map) ATTR_COLD;
private:
static constexpr XTAL SLITHER_CLOCK_OSC = XTAL(21'300'000); /* 21.3 MHz */
template <unsigned Which> uint8_t trak_r();
template <unsigned Which> void sn76489_ctrl_w(int state);
void slither_coinctr_w(uint8_t data);
void slither_videoram_w(offs_t offset, uint8_t data);
void slither_addresslatch_w(uint8_t data);
required_device_array<sn76489_device, 2> m_sn; required_device_array<sn76489_device, 2> m_sn;
required_shared_ptr<uint8_t> m_videoram_mask;
required_ioport_array<4> m_trak; required_ioport_array<4> m_trak;
bool m_sn76489_ctrl[2] = { false, false }; bool m_sn76489_ctrl[2] = { false, false };
}; };
// with MCU
class qixmcu_state : public qix_state class qixmcu_state : public qix_state
{ {
public: public:
@ -182,7 +189,7 @@ public:
m_coin(*this, "COIN") m_coin(*this, "COIN")
{ } { }
void mcu(machine_config &config); void mcu(machine_config &config) ATTR_COLD;
protected: protected:
virtual void machine_start() override ATTR_COLD; virtual void machine_start() override ATTR_COLD;
@ -205,28 +212,27 @@ private:
uint8_t m_coinctrl = 0; uint8_t m_coinctrl = 0;
}; };
// with video CPU bankswitching
class zookeep_state : public qixmcu_state class zookeep_state : public qixmcu_state
{ {
public: public:
zookeep_state(const machine_config &mconfig, device_type type, const char *tag) : zookeep_state(const machine_config &mconfig, device_type type, const char *tag) :
qixmcu_state(mconfig, type, tag), qixmcu_state(mconfig, type, tag)
m_vidbank(*this, "bank1")
{ } { }
void zookeep(machine_config &config); void zookeep(machine_config &config) ATTR_COLD;
void zookeepbl(machine_config &config); void zookeepbl(machine_config &config) ATTR_COLD;
void video(machine_config &config);
protected: protected:
virtual void machine_start() override ATTR_COLD; virtual void machine_start() override ATTR_COLD;
private: void video(machine_config &config) ATTR_COLD;
void bankswitch_w(uint8_t data);
void main_map(address_map &map) ATTR_COLD; void main_map(address_map &map) ATTR_COLD;
void video_map(address_map &map) ATTR_COLD; void video_map(address_map &map) ATTR_COLD;
required_memory_bank m_vidbank; private:
void bankswitch_w(uint8_t data);
}; };
#endif // MAME_TAITO_QIX_H #endif // MAME_TAITO_QIX_H

View File

@ -10,17 +10,19 @@
#include "qix.h" #include "qix.h"
#include "cpu/m6800/m6800.h" #include "cpu/m6800/m6800.h"
#include "machine/input_merger.h" #include "machine/input_merger.h"
#include "sound/discrete.h" #include "sound/discrete.h"
#include "speaker.h" #include "speaker.h"
/* Discrete Sound Input Nodes */ /* Discrete Sound Input Nodes */
#define QIX_DAC_DATA NODE_01 static constexpr uint32_t QIX_DAC_DATA = NODE_01;
#define QIX_VOL_DATA NODE_02 static constexpr uint32_t QIX_VOL_DATA = NODE_02;
#define QIX_VOL_DATA_L NODE_03 static constexpr uint32_t QIX_VOL_DATA_L = NODE_03;
#define QIX_VOL_DATA_R NODE_04 static constexpr uint32_t QIX_VOL_DATA_R = NODE_04;
@ -28,12 +30,12 @@
Audio handlers Audio handlers
***************************************************************************/ ***************************************************************************/
void qix_state::qix_dac_w(uint8_t data) void qix_state::dac_w(uint8_t data)
{ {
m_discrete->write(QIX_DAC_DATA, data); m_discrete->write(QIX_DAC_DATA, data);
} }
void qix_state::qix_vol_w(uint8_t data) void qix_state::vol_w(uint8_t data)
{ {
m_discrete->write(QIX_VOL_DATA, data); m_discrete->write(QIX_VOL_DATA, data);
} }
@ -105,7 +107,7 @@ void qix_state::sndpia_2_warning_w(uint8_t data)
TIMER_CALLBACK_MEMBER(qix_state::deferred_sndpia1_porta_w) TIMER_CALLBACK_MEMBER(qix_state::deferred_sndpia1_porta_w)
{ {
m_sndpia1->porta_w(param); m_sndpia[1]->porta_w(param);
} }
@ -125,14 +127,13 @@ void qix_state::sync_sndpia1_porta_w(uint8_t data)
void qix_state::audio_map(address_map &map) void qix_state::audio_map(address_map &map)
{ {
map(0x2000, 0x2003).mirror(0x5ffc).rw(m_sndpia2, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x2000, 0x2003).mirror(0x5ffc).rw(m_sndpia[2], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x4000, 0x4003).mirror(0x3ffc).rw(m_sndpia1, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x4000, 0x4003).mirror(0x3ffc).rw(m_sndpia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0xd000, 0xffff).rom(); map(0xd000, 0xffff).rom();
} }
/************************************* /*************************************
* *
* Machine drivers * Machine drivers
@ -141,6 +142,8 @@ void qix_state::audio_map(address_map &map)
void qix_state::qix_audio(machine_config &config) void qix_state::qix_audio(machine_config &config)
{ {
constexpr XTAL SOUND_CLOCK_OSC = XTAL(7'372'800); /* 7.3728 MHz */
M6802(config, m_audiocpu, SOUND_CLOCK_OSC/2); /* 0.92 MHz */ M6802(config, m_audiocpu, SOUND_CLOCK_OSC/2); /* 0.92 MHz */
m_audiocpu->set_addrmap(AS_PROGRAM, &qix_state::audio_map); m_audiocpu->set_addrmap(AS_PROGRAM, &qix_state::audio_map);
@ -150,28 +153,28 @@ void qix_state::qix_audio(machine_config &config)
// SINT is connected to the sound CPU's IRQ line // SINT is connected to the sound CPU's IRQ line
INPUT_MERGER_ANY_HIGH(config, "sint").output_handler().set_inputline(m_audiocpu, M6802_IRQ_LINE); INPUT_MERGER_ANY_HIGH(config, "sint").output_handler().set_inputline(m_audiocpu, M6802_IRQ_LINE);
PIA6821(config, m_sndpia0); PIA6821(config, m_sndpia[0]);
m_sndpia0->writepa_handler().set(FUNC(qix_state::sync_sndpia1_porta_w)); m_sndpia[0]->writepa_handler().set(FUNC(qix_state::sync_sndpia1_porta_w));
m_sndpia0->writepb_handler().set(FUNC(qix_state::qix_vol_w)); m_sndpia[0]->writepb_handler().set(FUNC(qix_state::vol_w));
m_sndpia0->tspb_handler().set_constant(0xff); m_sndpia[0]->tspb_handler().set_constant(0xff);
m_sndpia0->ca2_handler().set("sndpia1", FUNC(pia6821_device::ca1_w)); m_sndpia[0]->ca2_handler().set(m_sndpia[1], FUNC(pia6821_device::ca1_w));
m_sndpia0->cb2_handler().set(FUNC(qix_state::qix_flip_screen_w)); m_sndpia[0]->cb2_handler().set(FUNC(qix_state::flip_screen_w));
m_sndpia0->irqa_handler().set("dint", FUNC(input_merger_device::in_w<0>)); m_sndpia[0]->irqa_handler().set("dint", FUNC(input_merger_device::in_w<0>));
m_sndpia0->irqb_handler().set("dint", FUNC(input_merger_device::in_w<1>)); m_sndpia[0]->irqb_handler().set("dint", FUNC(input_merger_device::in_w<1>));
PIA6821(config, m_sndpia1); PIA6821(config, m_sndpia[1]);
m_sndpia1->writepa_handler().set("sndpia0", FUNC(pia6821_device::porta_w)); m_sndpia[1]->writepa_handler().set(m_sndpia[0], FUNC(pia6821_device::porta_w));
m_sndpia1->writepb_handler().set(FUNC(qix_state::qix_dac_w)); m_sndpia[1]->writepb_handler().set(FUNC(qix_state::dac_w));
m_sndpia1->tspb_handler().set_constant(0); m_sndpia[1]->tspb_handler().set_constant(0);
m_sndpia1->ca2_handler().set("sndpia0", FUNC(pia6821_device::ca1_w)); m_sndpia[1]->ca2_handler().set(m_sndpia[0], FUNC(pia6821_device::ca1_w));
m_sndpia1->irqa_handler().set("sint", FUNC(input_merger_device::in_w<0>)); m_sndpia[1]->irqa_handler().set("sint", FUNC(input_merger_device::in_w<0>));
m_sndpia1->irqb_handler().set("sint", FUNC(input_merger_device::in_w<1>)); m_sndpia[1]->irqb_handler().set("sint", FUNC(input_merger_device::in_w<1>));
PIA6821(config, m_sndpia2); PIA6821(config, m_sndpia[2]);
m_sndpia2->writepa_handler().set(FUNC(qix_state::sndpia_2_warning_w)); m_sndpia[2]->writepa_handler().set(FUNC(qix_state::sndpia_2_warning_w));
m_sndpia2->writepb_handler().set(FUNC(qix_state::sndpia_2_warning_w)); m_sndpia[2]->writepb_handler().set(FUNC(qix_state::sndpia_2_warning_w));
m_sndpia2->ca2_handler().set(FUNC(qix_state::sndpia_2_warning_w)); m_sndpia[2]->ca2_handler().set(FUNC(qix_state::sndpia_2_warning_w));
m_sndpia2->cb2_handler().set(FUNC(qix_state::sndpia_2_warning_w)); m_sndpia[2]->cb2_handler().set(FUNC(qix_state::sndpia_2_warning_w));
SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right(); SPEAKER(config, "rspeaker").front_right();
@ -181,26 +184,26 @@ void qix_state::qix_audio(machine_config &config)
m_discrete->add_route(1, "rspeaker", 1.0); m_discrete->add_route(1, "rspeaker", 1.0);
} }
void slither_state::slither_audio(machine_config &config) void slither_state::audio(machine_config &config)
{ {
// DINT is connected to the data CPU's IRQ line // DINT is connected to the data CPU's IRQ line
INPUT_MERGER_ANY_HIGH(config, "dint").output_handler().set_inputline(m_maincpu, M6809_IRQ_LINE); INPUT_MERGER_ANY_HIGH(config, "dint").output_handler().set_inputline(m_maincpu, M6809_IRQ_LINE);
PIA6821(config, m_sndpia0); PIA6821(config, m_sndpia[0]);
m_sndpia0->readpa_handler().set_ioport("P2"); m_sndpia[0]->readpa_handler().set_ioport("P2");
m_sndpia0->writepb_handler().set(FUNC(slither_state::slither_coinctl_w)); m_sndpia[0]->writepb_handler().set(FUNC(slither_state::slither_coinctr_w));
m_sndpia0->tspb_handler().set_constant(0x0f); m_sndpia[0]->tspb_handler().set_constant(0x0f);
m_sndpia0->cb2_handler().set(FUNC(slither_state::qix_flip_screen_w)); m_sndpia[0]->cb2_handler().set(FUNC(slither_state::flip_screen_w));
m_sndpia0->irqa_handler().set("dint", FUNC(input_merger_device::in_w<0>)); m_sndpia[0]->irqa_handler().set("dint", FUNC(input_merger_device::in_w<0>));
m_sndpia0->irqb_handler().set("dint", FUNC(input_merger_device::in_w<1>)); m_sndpia[0]->irqb_handler().set("dint", FUNC(input_merger_device::in_w<1>));
SPEAKER(config, "mono").front_center(); SPEAKER(config, "mono").front_center();
SN76489(config, m_sn[0], SLITHER_CLOCK_OSC/4/4); SN76489(config, m_sn[0], SLITHER_CLOCK_OSC/4/4);
m_sn[0]->add_route(ALL_OUTPUTS, "mono", 0.50); m_sn[0]->add_route(ALL_OUTPUTS, "mono", 0.50);
m_sn[0]->ready_cb().set(m_pia1, FUNC(pia6821_device::cb1_w)); m_sn[0]->ready_cb().set(m_pia[1], FUNC(pia6821_device::cb1_w));
SN76489(config, m_sn[1], SLITHER_CLOCK_OSC/4/4); SN76489(config, m_sn[1], SLITHER_CLOCK_OSC/4/4);
m_sn[1]->add_route(ALL_OUTPUTS, "mono", 0.50); m_sn[1]->add_route(ALL_OUTPUTS, "mono", 0.50);
m_sn[1]->ready_cb().set(m_pia2, FUNC(pia6821_device::cb1_w)); m_sn[1]->ready_cb().set(m_pia[2], FUNC(pia6821_device::cb1_w));
} }

View File

@ -11,6 +11,15 @@
#include "qix.h" #include "qix.h"
#define LOG_MCU (1 << 1)
#define VERBOSE (0)
#include "logmacro.h"
#define LOGMCU(...) LOGMASKED(LOG_MCU, __VA_ARGS__)
/************************************* /*************************************
* *
* Machine initialization * Machine initialization
@ -47,9 +56,9 @@ void zookeep_state::machine_start()
qix_state::machine_start(); qix_state::machine_start();
// configure the banking // configure the banking
m_vidbank->configure_entry(0, memregion("videocpu")->base() + 0xa000); m_videobank->configure_entry(0, memregion("videocpu")->base() + 0xa000);
m_vidbank->configure_entry(1, memregion("videocpu")->base() + 0x10000); m_videobank->configure_entry(1, memregion("videocpu")->base() + 0x10000);
m_vidbank->set_entry(0); m_videobank->set_entry(0);
} }
/************************************* /*************************************
@ -58,9 +67,9 @@ void zookeep_state::machine_start()
* *
*************************************/ *************************************/
void qix_state::qix_vsync_changed(int state) void qix_state::vsync_changed(int state)
{ {
m_sndpia0->cb1_w(state); m_sndpia[0]->cb1_w(state);
} }
@ -73,9 +82,9 @@ void qix_state::qix_vsync_changed(int state)
void zookeep_state::bankswitch_w(uint8_t data) void zookeep_state::bankswitch_w(uint8_t data)
{ {
m_vidbank->set_entry(BIT(data, 2)); m_videobank->set_entry(BIT(data, 2));
// not necessary, but technically correct // not necessary, but technically correct
qix_palettebank_w(data); palettebank_w(data);
} }
@ -86,19 +95,19 @@ void zookeep_state::bankswitch_w(uint8_t data)
* *
*************************************/ *************************************/
void qix_state::qix_data_firq_w(uint8_t data) void qix_state::data_firq_w(uint8_t data)
{ {
m_maincpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE); m_maincpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE);
} }
void qix_state::qix_data_firq_ack_w(uint8_t data) void qix_state::data_firq_ack_w(uint8_t data)
{ {
m_maincpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE); m_maincpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
} }
uint8_t qix_state::qix_data_firq_r(address_space &space) uint8_t qix_state::data_firq_r(address_space &space)
{ {
if (!machine().side_effects_disabled()) if (!machine().side_effects_disabled())
m_maincpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE); m_maincpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE);
@ -106,7 +115,7 @@ uint8_t qix_state::qix_data_firq_r(address_space &space)
} }
uint8_t qix_state::qix_data_firq_ack_r(address_space &space) uint8_t qix_state::data_firq_ack_r(address_space &space)
{ {
if (!machine().side_effects_disabled()) if (!machine().side_effects_disabled())
m_maincpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE); m_maincpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
@ -121,19 +130,19 @@ uint8_t qix_state::qix_data_firq_ack_r(address_space &space)
* *
*************************************/ *************************************/
void qix_state::qix_video_firq_w(uint8_t data) void qix_state::video_firq_w(uint8_t data)
{ {
m_videocpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE); m_videocpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE);
} }
void qix_state::qix_video_firq_ack_w(uint8_t data) void qix_state::video_firq_ack_w(uint8_t data)
{ {
m_videocpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE); m_videocpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
} }
uint8_t qix_state::qix_video_firq_r(address_space &space) uint8_t qix_state::video_firq_r(address_space &space)
{ {
if (!machine().side_effects_disabled()) if (!machine().side_effects_disabled())
m_videocpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE); m_videocpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE);
@ -141,7 +150,7 @@ uint8_t qix_state::qix_video_firq_r(address_space &space)
} }
uint8_t qix_state::qix_video_firq_ack_r(address_space &space) uint8_t qix_state::video_firq_ack_r(address_space &space)
{ {
if (!machine().side_effects_disabled()) if (!machine().side_effects_disabled())
m_videocpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE); m_videocpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
@ -158,16 +167,17 @@ uint8_t qix_state::qix_video_firq_ack_r(address_space &space)
uint8_t qixmcu_state::coin_r() uint8_t qixmcu_state::coin_r()
{ {
logerror("qixmcu_state, coin_r = %02X\n", m_68705_porta_out); if (!machine().side_effects_disabled())
LOGMCU("qixmcu_state, coin_r = %02X\n", m_68705_porta_out);
return m_68705_porta_out; return m_68705_porta_out;
} }
void qixmcu_state::coin_w(uint8_t data) void qixmcu_state::coin_w(uint8_t data)
{ {
logerror("qixmcu_state, coin_w = %02X\n", data); LOGMCU("qixmcu_state, coin_w = %02X\n", data);
// this is a callback called by pia6821_device::write(), so I don't need to synchronize // this is a callback called by pia6821_device::write(), so I don't need to synchronize
// the CPUs - they have already been synchronized by qix_pia_w() // the CPUs - they have already been synchronized by pia_w()
m_mcu->pa_w(data); m_mcu->pa_w(data);
} }
@ -187,9 +197,9 @@ void qixmcu_state::coinctrl_w(uint8_t data)
} }
// this is a callback called by pia6821_device::write(), so I don't need to synchronize // this is a callback called by pia6821_device::write(), so I don't need to synchronize
// the CPUs - they have already been synchronized by qix_pia_w() // the CPUs - they have already been synchronized by pia_w()
m_coinctrl = data; m_coinctrl = data;
logerror("qixmcu_state, coinctrl_w = %02X\n", data); LOGMCU("qixmcu_state, coinctrl_w = %02X\n", data);
} }
@ -221,7 +231,7 @@ uint8_t qixmcu_state::mcu_portc_r()
void qixmcu_state::mcu_porta_w(uint8_t data) void qixmcu_state::mcu_porta_w(uint8_t data)
{ {
logerror("68705:portA_w = %02X\n", data); LOGMCU("68705:portA_w = %02X\n", data);
m_68705_porta_out = data; m_68705_porta_out = data;
} }
@ -229,8 +239,8 @@ void qixmcu_state::mcu_porta_w(uint8_t data)
void qixmcu_state::mcu_portb_w(offs_t offset, uint8_t data, uint8_t mem_mask) void qixmcu_state::mcu_portb_w(offs_t offset, uint8_t data, uint8_t mem_mask)
{ {
data &= mem_mask; data &= mem_mask;
machine().bookkeeping().coin_lockout_w(0, (~data >> 6) & 1); machine().bookkeeping().coin_lockout_w(0, BIT(~data, 6));
machine().bookkeeping().coin_counter_w(0, (data >> 7) & 1); machine().bookkeeping().coin_counter_w(0, BIT(data, 7));
} }
@ -243,11 +253,11 @@ void qixmcu_state::mcu_portb_w(offs_t offset, uint8_t data, uint8_t mem_mask)
TIMER_CALLBACK_MEMBER(qix_state::pia_w_callback) TIMER_CALLBACK_MEMBER(qix_state::pia_w_callback)
{ {
m_pia0->write(param >> 8, param & 0xff); m_pia[0]->write(param >> 8, param & 0xff);
} }
void qix_state::qix_pia_w(offs_t offset, uint8_t data) void qix_state::pia_w(offs_t offset, uint8_t data)
{ {
// make all the CPUs synchronize, and only AFTER that write the command to the PIA // make all the CPUs synchronize, and only AFTER that write the command to the PIA
// otherwise the 68705 will miss commands // otherwise the 68705 will miss commands
@ -262,60 +272,14 @@ void qix_state::qix_pia_w(offs_t offset, uint8_t data)
* *
*************************************/ *************************************/
void qix_state::qix_coinctl_w(uint8_t data) void qix_state::coinctr_w(uint8_t data)
{ {
machine().bookkeeping().coin_lockout_w(0, (~data >> 2) & 1); machine().bookkeeping().coin_lockout_w(0, BIT(~data, 2));
machine().bookkeeping().coin_counter_w(0, (data >> 1) & 1); machine().bookkeeping().coin_counter_w(0, BIT(data, 1));
} }
void slither_state::slither_coinctl_w(uint8_t data) void slither_state::slither_coinctr_w(uint8_t data)
{ {
machine().bookkeeping().coin_lockout_w(0, (~data >> 6) & 1); machine().bookkeeping().coin_lockout_w(0, BIT(~data, 6));
machine().bookkeeping().coin_counter_w(0, (data >> 5) & 1); machine().bookkeeping().coin_counter_w(0, BIT(data, 5));
}
/*************************************
*
* Slither SN76489 I/O
*
*************************************/
void slither_state::sn76489_0_ctrl_w(int state)
{
// write to the sound chip
if (!state && m_sn76489_ctrl[0])
m_sn[0]->write(m_pia1->b_output());
m_sn76489_ctrl[0] = bool(state);
}
void slither_state::sn76489_1_ctrl_w(int state)
{
// write to the sound chip
if (!state && m_sn76489_ctrl[1])
m_sn[1]->write(m_pia2->b_output());
m_sn76489_ctrl[1] = bool(state);
}
/*************************************
*
* Slither trackball I/O
*
*************************************/
uint8_t slither_state::trak_lr_r()
{
return m_trak[m_flip ? 3 : 1]->read();
}
uint8_t slither_state::trak_ud_r()
{
return m_trak[m_flip ? 2 : 0]->read();
} }

View File

@ -19,15 +19,10 @@
void qix_state::video_start() void qix_state::video_start()
{ {
/* initialize the palette */
for (int x = 0; x < 0x400; x++)
set_pen(x);
/* set up save states */ /* set up save states */
save_item(NAME(m_flip)); save_item(NAME(m_flip));
save_item(NAME(m_palette_bank)); save_item(NAME(m_palette_bank));
save_item(NAME(m_leds)); save_item(NAME(m_leds));
save_item(NAME(m_pens));
} }
@ -43,8 +38,8 @@ void qix_state::display_enable_changed(int state)
/* on the rising edge, latch the scanline */ /* on the rising edge, latch the scanline */
if (state) if (state)
{ {
uint16_t ma = m_crtc->get_ma(); uint16_t const ma = m_crtc->get_ma();
uint8_t ra = m_crtc->get_ra(); uint8_t const ra = m_crtc->get_ra();
/* RA0-RA2 goes to D0-D2 and MA5-MA9 goes to D3-D7 */ /* RA0-RA2 goes to D0-D2 and MA5-MA9 goes to D3-D7 */
*m_scanline_latch = ((ma >> 2) & 0xf8) | (ra & 0x07); *m_scanline_latch = ((ma >> 2) & 0xf8) | (ra & 0x07);
@ -59,7 +54,7 @@ void qix_state::display_enable_changed(int state)
* *
*************************************/ *************************************/
void qix_state::qix_flip_screen_w(int state) void qix_state::flip_screen_w(int state)
{ {
m_flip = state; m_flip = state;
} }
@ -81,7 +76,7 @@ void qix_state::qix_flip_screen_w(int state)
* *
*************************************/ *************************************/
uint8_t qix_state::qix_videoram_r(offs_t offset) uint8_t qix_state::videoram_r(offs_t offset)
{ {
/* add in the upper bit of the address latch */ /* add in the upper bit of the address latch */
offset += (m_videoram_address[0] & 0x80) << 8; offset += (m_videoram_address[0] & 0x80) << 8;
@ -89,7 +84,7 @@ uint8_t qix_state::qix_videoram_r(offs_t offset)
} }
void qix_state::qix_videoram_w(offs_t offset, uint8_t data) void qix_state::videoram_w(offs_t offset, uint8_t data)
{ {
/* update the screen in case the game is writing "behind" the beam - /* update the screen in case the game is writing "behind" the beam -
Zookeeper likes to do this */ Zookeeper likes to do this */
@ -135,36 +130,36 @@ void slither_state::slither_videoram_w(offs_t offset, uint8_t data)
* *
*************************************/ *************************************/
uint8_t qix_state::qix_addresslatch_r(offs_t offset) uint8_t qix_state::addresslatch_r()
{ {
/* compute the value at the address latch */ /* compute the value at the address latch */
offset = (m_videoram_address[0] << 8) | m_videoram_address[1]; offs_t const offset = (m_videoram_address[0] << 8) | m_videoram_address[1];
return m_videoram[offset]; return m_videoram[offset];
} }
void qix_state::qix_addresslatch_w(offs_t offset, uint8_t data) void qix_state::addresslatch_w(uint8_t data)
{ {
/* update the screen in case the game is writing "behind" the beam */ /* update the screen in case the game is writing "behind" the beam */
// m_screen->update_now(); // m_screen->update_now();
m_screen->update_partial(m_screen->vpos()); m_screen->update_partial(m_screen->vpos());
/* compute the value at the address latch */ /* compute the value at the address latch */
offset = (m_videoram_address[0] << 8) | m_videoram_address[1]; offs_t const offset = (m_videoram_address[0] << 8) | m_videoram_address[1];
/* write the data */ /* write the data */
m_videoram[offset] = data; m_videoram[offset] = data;
} }
void slither_state::slither_addresslatch_w(offs_t offset, uint8_t data) void slither_state::slither_addresslatch_w(uint8_t data)
{ {
/* update the screen in case the game is writing "behind" the beam */ /* update the screen in case the game is writing "behind" the beam */
// m_screen->update_now(); // m_screen->update_now();
m_screen->update_partial(m_screen->vpos()); m_screen->update_partial(m_screen->vpos());
/* compute the value at the address latch */ /* compute the value at the address latch */
offset = (m_videoram_address[0] << 8) | m_videoram_address[1]; offs_t const offset = (m_videoram_address[0] << 8) | m_videoram_address[1];
/* blend the data */ /* blend the data */
m_videoram[offset] = (m_videoram[offset] & ~*m_videoram_mask) | (data & *m_videoram_mask); m_videoram[offset] = (m_videoram[offset] & ~*m_videoram_mask) | (data & *m_videoram_mask);
@ -179,12 +174,9 @@ void slither_state::slither_addresslatch_w(offs_t offset, uint8_t data)
*************************************/ *************************************/
void qix_state::qix_paletteram_w(offs_t offset, uint8_t data) void qix_state::paletteram_w(offs_t offset, uint8_t data)
{ {
uint8_t old_data = m_paletteram[offset]; uint8_t const old_data = m_palette->read8(offset);
/* set the palette RAM value */
m_paletteram[offset] = data;
/* trigger an update if a currently visible pen has changed */ /* trigger an update if a currently visible pen has changed */
if (((offset >> 8) == m_palette_bank) && if (((offset >> 8) == m_palette_bank) &&
@ -194,11 +186,12 @@ void qix_state::qix_paletteram_w(offs_t offset, uint8_t data)
m_screen->update_partial(m_screen->vpos()); m_screen->update_partial(m_screen->vpos());
} }
set_pen(offset); /* set the palette RAM value */
m_palette->write8(offset, data);
} }
void qix_state::qix_palettebank_w(uint8_t data) void qix_state::palettebank_w(uint8_t data)
{ {
/* set the bank value */ /* set the bank value */
if (m_palette_bank != (data & 3)) if (m_palette_bank != (data & 3))
@ -213,7 +206,7 @@ void qix_state::qix_palettebank_w(uint8_t data)
} }
void qix_state::set_pen(int offs) rgb_t qix_state::qix_R2G2B2I2(uint32_t raw)
{ {
/* this conversion table should be about right. It gives a reasonable */ /* this conversion table should be about right. It gives a reasonable */
/* gray scale in the test screen, and the red, green and blue squares */ /* gray scale in the test screen, and the red, green and blue squares */
@ -238,21 +231,17 @@ void qix_state::set_pen(int offs)
0xff /* value = 3, intensity = 3 */ 0xff /* value = 3, intensity = 3 */
}; };
int bits, intensity, r, g, b;
uint8_t data = m_paletteram[offs];
/* compute R, G, B from the table */ /* compute R, G, B from the table */
intensity = (data >> 0) & 0x03; int const intensity = (raw >> 0) & 0x03;
bits = (data >> 6) & 0x03; int bits = (raw >> 6) & 0x03;
r = table[(bits << 2) | intensity]; int const r = table[(bits << 2) | intensity];
bits = (data >> 4) & 0x03; bits = (raw >> 4) & 0x03;
g = table[(bits << 2) | intensity]; int const g = table[(bits << 2) | intensity];
bits = (data >> 2) & 0x03; bits = (raw >> 2) & 0x03;
b = table[(bits << 2) | intensity]; int const b = table[(bits << 2) | intensity];
/* update the palette */ /* update the palette */
m_pens[offs] = rgb_t(r, g, b); return rgb_t(r, g, b);
} }
@ -264,7 +253,7 @@ void qix_state::set_pen(int offs)
* *
*************************************/ *************************************/
MC6845_BEGIN_UPDATE( qix_state::crtc_begin_update ) MC6845_BEGIN_UPDATE(qix_state::crtc_begin_update)
{ {
#if 0 #if 0
// note the confusing bit order! // note the confusing bit order!
@ -273,14 +262,14 @@ MC6845_BEGIN_UPDATE( qix_state::crtc_begin_update )
} }
MC6845_UPDATE_ROW( qix_state::crtc_update_row ) MC6845_UPDATE_ROW(qix_state::crtc_update_row)
{ {
uint32_t *const dest = &bitmap.pix(y); uint32_t *const dest = &bitmap.pix(y);
pen_t const *const pens = &m_pens[m_palette_bank << 8]; pen_t const *const pens = &m_palette->pens()[m_palette_bank << 8];
/* the memory is hooked up to the MA, RA lines this way */ /* the memory is hooked up to the MA, RA lines this way */
offs_t offs = ((ma << 6) & 0xf800) | ((ra << 8) & 0x0700); offs_t const offs = ((ma << 6) & 0xf800) | ((ra << 8) & 0x0700);
offs_t offs_xor = m_flip ? 0xffff : 0; offs_t const offs_xor = m_flip ? 0xffff : 0;
for (uint16_t x = 0; x < x_count * 8; x++) for (uint16_t x = 0; x < x_count * 8; x++)
dest[x] = pens[m_videoram[(offs + x) ^ offs_xor]]; dest[x] = pens[m_videoram[(offs + x) ^ offs_xor]];
@ -295,73 +284,73 @@ MC6845_UPDATE_ROW( qix_state::crtc_update_row )
void qix_state::qix_video_map(address_map &map) void qix_state::qix_video_map(address_map &map)
{ {
map(0x0000, 0x7fff).rw(FUNC(qix_state::qix_videoram_r), FUNC(qix_state::qix_videoram_w)); map(0x0000, 0x7fff).rw(FUNC(qix_state::videoram_r), FUNC(qix_state::videoram_w));
map(0x8000, 0x83ff).ram().share("share1"); map(0x8000, 0x83ff).ram().share("sharedram");
map(0x8400, 0x87ff).ram().share("nvram"); map(0x8400, 0x87ff).ram().share("nvram");
map(0x8800, 0x8800).mirror(0x03ff).w(FUNC(qix_state::qix_palettebank_w)); map(0x8800, 0x8800).mirror(0x03ff).w(FUNC(qix_state::palettebank_w));
map(0x8c00, 0x8c00).mirror(0x03fe).rw(FUNC(qix_state::qix_data_firq_r), FUNC(qix_state::qix_data_firq_w)); map(0x8c00, 0x8c00).mirror(0x03fe).rw(FUNC(qix_state::data_firq_r), FUNC(qix_state::data_firq_w));
map(0x8c01, 0x8c01).mirror(0x03fe).rw(FUNC(qix_state::qix_video_firq_ack_r), FUNC(qix_state::qix_video_firq_ack_w)); map(0x8c01, 0x8c01).mirror(0x03fe).rw(FUNC(qix_state::video_firq_ack_r), FUNC(qix_state::video_firq_ack_w));
map(0x9000, 0x93ff).ram().w(FUNC(qix_state::qix_paletteram_w)).share("paletteram"); map(0x9000, 0x93ff).ram().w(FUNC(qix_state::paletteram_w)).share("palette");
map(0x9400, 0x9400).mirror(0x03fc).rw(FUNC(qix_state::qix_addresslatch_r), FUNC(qix_state::qix_addresslatch_w)); map(0x9400, 0x9400).mirror(0x03fc).rw(FUNC(qix_state::addresslatch_r), FUNC(qix_state::addresslatch_w));
map(0x9402, 0x9403).mirror(0x03fc).writeonly().share("videoram_addr"); map(0x9402, 0x9403).mirror(0x03fc).writeonly().share(m_videoram_address);
map(0x9800, 0x9800).mirror(0x03ff).readonly().share("scanline_latch"); map(0x9800, 0x9800).mirror(0x03ff).readonly().share(m_scanline_latch);
map(0x9c00, 0x9c00).mirror(0x03fe).w(m_crtc, FUNC(mc6845_device::address_w)); map(0x9c00, 0x9c00).mirror(0x03fe).w(m_crtc, FUNC(mc6845_device::address_w));
map(0x9c01, 0x9c01).mirror(0x03fe).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w)); map(0x9c01, 0x9c01).mirror(0x03fe).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
map(0xa000, 0xffff).rom(); map(0xa000, 0xffff).rom();
} }
void qix_state::kram3_video_map(address_map &map) void kram3_state::video_map(address_map &map)
{ {
map(0x0000, 0x7fff).rw(FUNC(qix_state::qix_videoram_r), FUNC(qix_state::qix_videoram_w)); map(0x0000, 0x7fff).rw(FUNC(kram3_state::videoram_r), FUNC(kram3_state::videoram_w));
map(0x8000, 0x83ff).ram().share("share1"); map(0x8000, 0x83ff).ram().share("sharedram");
map(0x8400, 0x87ff).ram().share("nvram"); map(0x8400, 0x87ff).ram().share("nvram");
map(0x8800, 0x8800).mirror(0x03ff).w(FUNC(qix_state::qix_palettebank_w)); map(0x8800, 0x8800).mirror(0x03ff).w(FUNC(kram3_state::palettebank_w));
map(0x8c00, 0x8c00).mirror(0x03fe).rw(FUNC(qix_state::qix_data_firq_r), FUNC(qix_state::qix_data_firq_w)); map(0x8c00, 0x8c00).mirror(0x03fe).rw(FUNC(kram3_state::data_firq_r), FUNC(kram3_state::data_firq_w));
map(0x8c01, 0x8c01).mirror(0x03fe).rw(FUNC(qix_state::qix_video_firq_ack_r), FUNC(qix_state::qix_video_firq_ack_w)); map(0x8c01, 0x8c01).mirror(0x03fe).rw(FUNC(kram3_state::video_firq_ack_r), FUNC(kram3_state::video_firq_ack_w));
map(0x9000, 0x93ff).ram().w(FUNC(qix_state::qix_paletteram_w)).share("paletteram"); map(0x9000, 0x93ff).ram().w(FUNC(kram3_state::paletteram_w)).share("palette");
map(0x9400, 0x9400).mirror(0x03fc).rw(FUNC(qix_state::qix_addresslatch_r), FUNC(qix_state::qix_addresslatch_w)); map(0x9400, 0x9400).mirror(0x03fc).rw(FUNC(kram3_state::addresslatch_r), FUNC(kram3_state::addresslatch_w));
map(0x9402, 0x9403).mirror(0x03fc).writeonly().share("videoram_addr"); map(0x9402, 0x9403).mirror(0x03fc).writeonly().share(m_videoram_address);
map(0x9800, 0x9800).mirror(0x03ff).readonly().share("scanline_latch"); map(0x9800, 0x9800).mirror(0x03ff).readonly().share(m_scanline_latch);
map(0x9c00, 0x9c00).mirror(0x03fe).w(m_crtc, FUNC(mc6845_device::address_w)); map(0x9c00, 0x9c00).mirror(0x03fe).w(m_crtc, FUNC(mc6845_device::address_w));
map(0x9c01, 0x9c01).mirror(0x03fe).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w)); map(0x9c01, 0x9c01).mirror(0x03fe).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
map(0xa000, 0xffff).bankr("bank1"); map(0xa000, 0xffff).bankr(m_videobank);
} }
void zookeep_state::video_map(address_map &map) void zookeep_state::video_map(address_map &map)
{ {
map(0x0000, 0x7fff).rw(FUNC(zookeep_state::qix_videoram_r), FUNC(zookeep_state::qix_videoram_w)); map(0x0000, 0x7fff).rw(FUNC(zookeep_state::videoram_r), FUNC(zookeep_state::videoram_w));
map(0x8000, 0x83ff).ram().share("share1"); map(0x8000, 0x83ff).ram().share("sharedram");
map(0x8400, 0x87ff).ram().share("nvram"); map(0x8400, 0x87ff).ram().share("nvram");
map(0x8800, 0x8800).mirror(0x03fe).w(FUNC(zookeep_state::qix_palettebank_w)); map(0x8800, 0x8800).mirror(0x03fe).w(FUNC(zookeep_state::palettebank_w));
map(0x8801, 0x8801).mirror(0x03fe).w(FUNC(zookeep_state::bankswitch_w)); map(0x8801, 0x8801).mirror(0x03fe).w(FUNC(zookeep_state::bankswitch_w));
map(0x8c00, 0x8c00).mirror(0x03fe).rw(FUNC(zookeep_state::qix_data_firq_r), FUNC(zookeep_state::qix_data_firq_w)); map(0x8c00, 0x8c00).mirror(0x03fe).rw(FUNC(zookeep_state::data_firq_r), FUNC(zookeep_state::data_firq_w));
map(0x8c01, 0x8c01).mirror(0x03fe).rw(FUNC(zookeep_state::qix_video_firq_ack_r), FUNC(zookeep_state::qix_video_firq_ack_w)); map(0x8c01, 0x8c01).mirror(0x03fe).rw(FUNC(zookeep_state::video_firq_ack_r), FUNC(zookeep_state::video_firq_ack_w));
map(0x9000, 0x93ff).ram().w(FUNC(zookeep_state::qix_paletteram_w)).share("paletteram"); map(0x9000, 0x93ff).ram().w(FUNC(zookeep_state::paletteram_w)).share("palette");
map(0x9400, 0x9400).mirror(0x03fc).rw(FUNC(zookeep_state::qix_addresslatch_r), FUNC(zookeep_state::qix_addresslatch_w)); map(0x9400, 0x9400).mirror(0x03fc).rw(FUNC(zookeep_state::addresslatch_r), FUNC(zookeep_state::addresslatch_w));
map(0x9402, 0x9403).mirror(0x03fc).writeonly().share("videoram_addr"); map(0x9402, 0x9403).mirror(0x03fc).writeonly().share(m_videoram_address);
map(0x9800, 0x9800).mirror(0x03ff).readonly().share("scanline_latch"); map(0x9800, 0x9800).mirror(0x03ff).readonly().share(m_scanline_latch);
map(0x9c00, 0x9c00).mirror(0x03fe).w(m_crtc, FUNC(mc6845_device::address_w)); map(0x9c00, 0x9c00).mirror(0x03fe).w(m_crtc, FUNC(mc6845_device::address_w));
map(0x9c01, 0x9c01).mirror(0x03fe).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w)); map(0x9c01, 0x9c01).mirror(0x03fe).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
map(0xa000, 0xbfff).bankr(m_vidbank); map(0xa000, 0xbfff).bankr(m_videobank);
map(0xc000, 0xffff).rom(); map(0xc000, 0xffff).rom();
} }
void slither_state::slither_video_map(address_map &map) void slither_state::video_map(address_map &map)
{ {
map(0x0000, 0x7fff).rw(FUNC(slither_state::qix_videoram_r), FUNC(slither_state::slither_videoram_w)); map(0x0000, 0x7fff).rw(FUNC(slither_state::videoram_r), FUNC(slither_state::slither_videoram_w));
map(0x8000, 0x83ff).ram().share("share1"); map(0x8000, 0x83ff).ram().share("sharedram");
map(0x8400, 0x87ff).ram().share("nvram"); map(0x8400, 0x87ff).ram().share("nvram");
map(0x8800, 0x8800).mirror(0x03ff).w(FUNC(slither_state::qix_palettebank_w)); map(0x8800, 0x8800).mirror(0x03ff).w(FUNC(slither_state::palettebank_w));
map(0x8c00, 0x8c00).mirror(0x03fe).rw(FUNC(slither_state::qix_data_firq_r), FUNC(slither_state::qix_data_firq_w)); map(0x8c00, 0x8c00).mirror(0x03fe).rw(FUNC(slither_state::data_firq_r), FUNC(slither_state::data_firq_w));
map(0x8c01, 0x8c01).mirror(0x03fe).rw(FUNC(slither_state::qix_video_firq_ack_r), FUNC(slither_state::qix_video_firq_ack_w)); map(0x8c01, 0x8c01).mirror(0x03fe).rw(FUNC(slither_state::video_firq_ack_r), FUNC(slither_state::video_firq_ack_w));
map(0x9000, 0x93ff).ram().w(FUNC(slither_state::qix_paletteram_w)).share("paletteram"); map(0x9000, 0x93ff).ram().w(FUNC(slither_state::paletteram_w)).share("palette");
map(0x9400, 0x9400).mirror(0x03fc).rw(FUNC(slither_state::qix_addresslatch_r), FUNC(slither_state::slither_addresslatch_w)); map(0x9400, 0x9400).mirror(0x03fc).rw(FUNC(slither_state::addresslatch_r), FUNC(slither_state::slither_addresslatch_w));
map(0x9401, 0x9401).mirror(0x03fc).writeonly().share("videoram_mask"); map(0x9401, 0x9401).mirror(0x03fc).writeonly().share(m_videoram_mask);
map(0x9402, 0x9403).mirror(0x03fc).writeonly().share("videoram_addr"); map(0x9402, 0x9403).mirror(0x03fc).writeonly().share(m_videoram_address);
map(0x9800, 0x9800).mirror(0x03ff).readonly().share("scanline_latch"); map(0x9800, 0x9800).mirror(0x03ff).readonly().share(m_scanline_latch);
map(0x9c00, 0x9c00).mirror(0x03fe).w(m_crtc, FUNC(mc6845_device::address_w)); map(0x9c00, 0x9c00).mirror(0x03fe).w(m_crtc, FUNC(mc6845_device::address_w));
map(0x9c01, 0x9c01).mirror(0x03fe).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w)); map(0x9c01, 0x9c01).mirror(0x03fe).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
map(0xa000, 0xffff).rom(); map(0xa000, 0xffff).rom();
@ -377,6 +366,8 @@ void slither_state::slither_video_map(address_map &map)
void qix_state::qix_video(machine_config &config) void qix_state::qix_video(machine_config &config)
{ {
constexpr XTAL QIX_CHARACTER_CLOCK = (XTAL(20'000'000)/2/16);
MC6809E(config, m_videocpu, MAIN_CLOCK_OSC/4/4); /* 1.25 MHz */ MC6809E(config, m_videocpu, MAIN_CLOCK_OSC/4/4); /* 1.25 MHz */
m_videocpu->set_addrmap(AS_PROGRAM, &qix_state::qix_video_map); m_videocpu->set_addrmap(AS_PROGRAM, &qix_state::qix_video_map);
@ -387,17 +378,19 @@ void qix_state::qix_video(machine_config &config)
m_crtc->set_begin_update_callback(FUNC(qix_state::crtc_begin_update)); m_crtc->set_begin_update_callback(FUNC(qix_state::crtc_begin_update));
m_crtc->set_update_row_callback(FUNC(qix_state::crtc_update_row)); m_crtc->set_update_row_callback(FUNC(qix_state::crtc_update_row));
m_crtc->out_de_callback().set(FUNC(qix_state::display_enable_changed)); m_crtc->out_de_callback().set(FUNC(qix_state::display_enable_changed));
m_crtc->out_vsync_callback().set(FUNC(qix_state::qix_vsync_changed)); m_crtc->out_vsync_callback().set(FUNC(qix_state::vsync_changed));
SCREEN(config, m_screen, SCREEN_TYPE_RASTER); SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(QIX_CHARACTER_CLOCK*8, 0x148, 0, 0x100, 0x111, 0, 0x100); /* from CRTC */ m_screen->set_raw(QIX_CHARACTER_CLOCK*8, 0x148, 0, 0x100, 0x111, 0, 0x100); /* from CRTC */
m_screen->set_screen_update(m_crtc, FUNC(mc6845_device::screen_update)); m_screen->set_screen_update(m_crtc, FUNC(mc6845_device::screen_update));
PALETTE(config, m_palette, palette_device::BLACK).set_format(1, &qix_state::qix_R2G2B2I2, 0x400);
} }
void qix_state::kram3_video(machine_config &config) void kram3_state::video(machine_config &config)
{ {
m_videocpu->set_addrmap(AS_PROGRAM, &qix_state::kram3_video_map); m_videocpu->set_addrmap(AS_PROGRAM, &kram3_state::video_map);
m_videocpu->lic().set(FUNC(qix_state::kram3_lic_videocpu_changed)); m_videocpu->lic().set(FUNC(kram3_state::lic_videocpu_changed));
} }
void zookeep_state::video(machine_config &config) void zookeep_state::video(machine_config &config)
@ -405,8 +398,8 @@ void zookeep_state::video(machine_config &config)
m_videocpu->set_addrmap(AS_PROGRAM, &zookeep_state::video_map); m_videocpu->set_addrmap(AS_PROGRAM, &zookeep_state::video_map);
} }
void slither_state::slither_video(machine_config &config) void slither_state::video(machine_config &config)
{ {
m_videocpu->set_clock(SLITHER_CLOCK_OSC/4/4); /* 1.34 MHz */ m_videocpu->set_clock(SLITHER_CLOCK_OSC/4/4); /* 1.34 MHz */
m_videocpu->set_addrmap(AS_PROGRAM, &slither_state::slither_video_map); m_videocpu->set_addrmap(AS_PROGRAM, &slither_state::video_map);
} }