1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder, hap
3 /**********************************************************************
4
5 Tasc Final ChessCard cartridge emulation
6
7 It expects a mouse in port 2, and/or joystick in port 1.
8
9 The cartridge includes its own CPU (G65SC02P-4 @ 5MHz), making a relatively
10 strong chess program possible on C64.
11 It was also released for IBM PC, with an ISA card.
12
13 **********************************************************************/
14
15 #include "emu.h"
16 #include "fcc.h"
17
18
19 //**************************************************************************
20 // DEVICE DEFINITIONS
21 //**************************************************************************
22
23 DEFINE_DEVICE_TYPE(C64_FCC, c64_final_chesscard_device, "c64_fcc", "C64 Final ChessCard")
24
25
26 //-------------------------------------------------
27 // ADDRESS_MAP( c64_fcc_map )
28 //-------------------------------------------------
29
c64_fcc_map(address_map & map)30 void c64_final_chesscard_device::c64_fcc_map(address_map &map)
31 {
32 map(0x0000, 0x1fff).rw(FUNC(c64_final_chesscard_device::nvram_r), FUNC(c64_final_chesscard_device::nvram_w)); // A13-A15 = low
33 //map(0x6000, 0x6000).noprw(); // N/C
34 map(0x7f00, 0x7f00).mirror(0x00ff).r(m_sublatch, FUNC(generic_latch_8_device::read)).w(m_mainlatch, FUNC(generic_latch_8_device::write)); // A8-A14 = high
35 map(0x8000, 0xffff).r(FUNC(c64_final_chesscard_device::rom_r));
36 }
37
38
39 //-------------------------------------------------
40 // device_add_mconfig - add device configuration
41 //-------------------------------------------------
42
device_add_mconfig(machine_config & config)43 void c64_final_chesscard_device::device_add_mconfig(machine_config &config)
44 {
45 M65SC02(config, m_maincpu, 5_MHz_XTAL);
46 m_maincpu->set_addrmap(AS_PROGRAM, &c64_final_chesscard_device::c64_fcc_map);
47
48 GENERIC_LATCH_8(config, m_mainlatch).data_pending_callback().set(FUNC(c64_final_chesscard_device::mainlatch_int));
49 GENERIC_LATCH_8(config, m_sublatch).data_pending_callback().set_inputline(m_maincpu, INPUT_LINE_NMI);
50 }
51
52
53 //-------------------------------------------------
54 // INPUT_PORTS( c64_fcc )
55 //-------------------------------------------------
56
57 static INPUT_PORTS_START( c64_fcc )
58 PORT_START("RESET")
PORT_CODE(KEYCODE_F11)59 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, c64_expansion_slot_device, reset_w)
60 INPUT_PORTS_END
61
62
63 //-------------------------------------------------
64 // input_ports - device-specific input ports
65 //-------------------------------------------------
66
67 ioport_constructor c64_final_chesscard_device::device_input_ports() const
68 {
69 return INPUT_PORTS_NAME( c64_fcc );
70 }
71
72
73 //**************************************************************************
74 // LIVE DEVICE
75 //**************************************************************************
76
77 //-------------------------------------------------
78 // c64_final_chesscard_device - constructor
79 //-------------------------------------------------
80
c64_final_chesscard_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)81 c64_final_chesscard_device::c64_final_chesscard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
82 device_t(mconfig, C64_FCC, tag, owner, clock),
83 device_c64_expansion_card_interface(mconfig, *this),
84 device_nvram_interface(mconfig, *this),
85 m_maincpu(*this, "maincpu"),
86 m_mainlatch(*this, "mainlatch"),
87 m_sublatch(*this, "sublatch"),
88 m_bank(0),
89 m_hidden(0)
90 {
91 }
92
93
94 //-------------------------------------------------
95 // device_start - device-specific startup
96 //-------------------------------------------------
97
device_start()98 void c64_final_chesscard_device::device_start()
99 {
100 // state saving
101 save_item(NAME(m_bank));
102 save_item(NAME(m_hidden));
103 }
104
105
106 //-------------------------------------------------
107 // device_reset - device-specific reset
108 //-------------------------------------------------
109
device_reset()110 void c64_final_chesscard_device::device_reset()
111 {
112 m_mainlatch->read();
113 m_sublatch->read();
114 m_maincpu->reset();
115
116 m_bank = 0;
117 m_hidden = 0;
118 m_exrom = 0;
119 m_game = 0;
120 }
121
122
123 //-------------------------------------------------
124 // c64_cd_r - cartridge data read
125 //-------------------------------------------------
126
c64_cd_r(offs_t offset,uint8_t data,int sphi2,int ba,int roml,int romh,int io1,int io2)127 uint8_t c64_final_chesscard_device::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
128 {
129 if (!roml || !romh)
130 data = m_roml[(m_bank << 14) | (offset & 0x3fff)];
131 else if (!io2)
132 data = m_mainlatch->read();
133
134 return data;
135 }
136
137
138 //-------------------------------------------------
139 // c64_cd_w - cartridge data write
140 //-------------------------------------------------
141
c64_cd_w(offs_t offset,uint8_t data,int sphi2,int ba,int roml,int romh,int io1,int io2)142 void c64_final_chesscard_device::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
143 {
144 if (!m_hidden && !io1)
145 {
146 // d0: rom bank
147 // d1: EXROM/GAME
148 // d7: hide register
149 m_bank = BIT(data, 0);
150 m_exrom = BIT(data, 1);
151 m_game = BIT(data, 1);
152 m_hidden = BIT(data, 7);
153 }
154 else if (!io2)
155 m_sublatch->write(data);
156 }
157