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