trunk/src/mess/drivers/odyssey2.c
r19932 | r19933 | |
7 | 7 | Minor update to "the voice" rom names, and add comment about |
8 | 8 | the older revision of "the voice" - LN, 10/03/08 |
9 | 9 | |
| 10 | TODO: |
| 11 | - Reimplement the cartridge slot, and thus also the voice, as a slot device |
| 12 | - In case any more machines turn up using the i8245, reimplemnt it as a |
| 13 | real device. |
| 14 | - In case any more machines (TVs?) turn up using the EF9340 and/or EF9341, |
| 15 | reimplement as a real device. |
| 16 | |
10 | 17 | ***************************************************************************/ |
11 | 18 | |
12 | 19 | #include "emu.h" |
r19932 | r19933 | |
15 | 22 | #include "imagedev/cartslot.h" |
16 | 23 | #include "sound/sp0256.h" |
17 | 24 | |
| 25 | |
18 | 26 | static ADDRESS_MAP_START( odyssey2_mem , AS_PROGRAM, 8, odyssey2_state ) |
19 | | AM_RANGE( 0x0000, 0x03FF) AM_ROM |
20 | | AM_RANGE( 0x0400, 0x0BFF) AM_RAMBANK("bank1") |
21 | | AM_RANGE( 0x0C00, 0x0FFF) AM_RAMBANK("bank2") |
| 27 | AM_RANGE(0x0000, 0x03FF) AM_ROM |
| 28 | AM_RANGE(0x0400, 0x0BFF) AM_RAMBANK("bank1") |
| 29 | AM_RANGE(0x0C00, 0x0FFF) AM_RAMBANK("bank2") |
22 | 30 | ADDRESS_MAP_END |
23 | 31 | |
| 32 | |
24 | 33 | static ADDRESS_MAP_START( odyssey2_io , AS_IO, 8, odyssey2_state ) |
25 | | AM_RANGE( 0x00, 0xff) AM_READWRITE(odyssey2_bus_r, odyssey2_bus_w) |
26 | | AM_RANGE( MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(odyssey2_getp1, odyssey2_putp1 ) |
27 | | AM_RANGE( MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(odyssey2_getp2, odyssey2_putp2 ) |
28 | | AM_RANGE( MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READWRITE(odyssey2_getbus, odyssey2_putbus ) |
29 | | AM_RANGE( MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(odyssey2_t0_r ) |
30 | | AM_RANGE( MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(odyssey2_t1_r ) |
| 34 | AM_RANGE(0x00, 0xff) AM_READWRITE(io_read, io_write) |
| 35 | AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(p1_read, p1_write) |
| 36 | AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(p2_read, p2_write) |
| 37 | AM_RANGE(MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READWRITE(bus_read, bus_write) |
| 38 | AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(t0_read) |
| 39 | AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(t1_read) |
31 | 40 | ADDRESS_MAP_END |
32 | 41 | |
| 42 | |
33 | 43 | static ADDRESS_MAP_START( g7400_io , AS_IO, 8, odyssey2_state ) |
34 | | AM_RANGE( 0x00, 0xff) AM_READWRITE(g7400_bus_r, g7400_bus_w) |
35 | | AM_RANGE( MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(odyssey2_getp1, odyssey2_putp1 ) |
36 | | AM_RANGE( MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(odyssey2_getp2, odyssey2_putp2 ) |
37 | | AM_RANGE( MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READWRITE(odyssey2_getbus, odyssey2_putbus ) |
38 | | AM_RANGE( MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(odyssey2_t0_r ) |
39 | | AM_RANGE( MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(odyssey2_t1_r ) |
40 | | //AM_RANGE( MCS_MCS48_PORT_PROG, MCS48_PORT_PROG ) //write to 8243 with low four bits from P2 |
| 44 | AM_RANGE(0x00, 0xff) AM_READWRITE(g7400_io_read, g7400_io_write) |
| 45 | AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(p1_read, p1_write) |
| 46 | AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(p2_read, p2_write) |
| 47 | AM_RANGE(MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READWRITE(bus_read, bus_write) |
| 48 | AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(t0_read) |
| 49 | AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(t1_read) |
| 50 | //AM_RANGE(MCS48_PORT_PROG, MCS48_PORT_PROG) //write to 8243 with low four bits from P2 |
41 | 51 | ADDRESS_MAP_END |
42 | 52 | |
| 53 | |
43 | 54 | static INPUT_PORTS_START( odyssey2 ) |
44 | 55 | PORT_START("KEY0") /* IN0 */ |
45 | 56 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') |
r19932 | r19933 | |
118 | 129 | PORT_BIT( 0xe0, 0xe0, IPT_UNUSED ) |
119 | 130 | INPUT_PORTS_END |
120 | 131 | |
| 132 | |
121 | 133 | static const gfx_layout odyssey2_graphicslayout = |
122 | 134 | { |
123 | 135 | 8,1, |
r19932 | r19933 | |
156 | 168 | 1*8 |
157 | 169 | }; |
158 | 170 | |
| 171 | |
159 | 172 | static GFXDECODE_START( odyssey2 ) |
160 | 173 | GFXDECODE_ENTRY( "gfx1", 0x0000, odyssey2_graphicslayout, 0, 2 ) |
161 | 174 | GFXDECODE_ENTRY( "gfx1", 0x0000, odyssey2_spritelayout, 0, 2 ) |
162 | 175 | GFXDECODE_END |
163 | 176 | |
| 177 | |
164 | 178 | static const sp0256_interface the_voice_sp0256 = |
165 | 179 | { |
166 | | DEVCB_LINE(odyssey2_the_voice_lrq_callback), |
| 180 | DEVCB_DRIVER_LINE_MEMBER(odyssey2_state,the_voice_lrq_callback), |
167 | 181 | DEVCB_NULL |
168 | 182 | }; |
169 | 183 | |
| 184 | |
170 | 185 | static MACHINE_CONFIG_FRAGMENT( odyssey2_cartslot ) |
171 | 186 | MCFG_CARTSLOT_ADD("cart") |
172 | 187 | MCFG_CARTSLOT_EXTENSION_LIST("bin,rom") |
173 | 188 | MCFG_CARTSLOT_NOT_MANDATORY |
174 | 189 | MACHINE_CONFIG_END |
175 | 190 | |
| 191 | |
176 | 192 | static MACHINE_CONFIG_START( odyssey2, odyssey2_state ) |
177 | 193 | /* basic machine hardware */ |
178 | 194 | MCFG_CPU_ADD("maincpu", I8048, ( ( XTAL_7_15909MHz * 3 ) / 4 ) ) |
r19932 | r19933 | |
180 | 196 | MCFG_CPU_IO_MAP(odyssey2_io) |
181 | 197 | MCFG_QUANTUM_TIME(attotime::from_hz(60)) |
182 | 198 | |
183 | | |
184 | 199 | /* video hardware */ |
185 | 200 | MCFG_SCREEN_ADD("screen", RASTER) |
186 | 201 | MCFG_SCREEN_RAW_PARAMS( XTAL_7_15909MHz/2, I824X_LINE_CLOCKS, I824X_START_ACTIVE_SCAN, I824X_END_ACTIVE_SCAN, 262, I824X_START_Y, I824X_START_Y + I824X_SCREEN_HEIGHT ) |
r19932 | r19933 | |
189 | 204 | MCFG_GFXDECODE( odyssey2 ) |
190 | 205 | MCFG_PALETTE_LENGTH(24) |
191 | 206 | |
192 | | |
193 | 207 | /* sound hardware */ |
194 | 208 | MCFG_SPEAKER_STANDARD_MONO("mono") |
195 | 209 | MCFG_SOUND_ADD("custom", ODYSSEY2, XTAL_7_15909MHz/2) |
r19932 | r19933 | |
203 | 217 | MCFG_FRAGMENT_ADD(odyssey2_cartslot) |
204 | 218 | MACHINE_CONFIG_END |
205 | 219 | |
| 220 | |
206 | 221 | static MACHINE_CONFIG_START( videopac, odyssey2_state ) |
207 | 222 | /* basic machine hardware */ |
208 | 223 | MCFG_CPU_ADD("maincpu", I8048, ( XTAL_17_73447MHz / 3 ) ) |
r19932 | r19933 | |
210 | 225 | MCFG_CPU_IO_MAP(odyssey2_io) |
211 | 226 | MCFG_QUANTUM_TIME(attotime::from_hz(60)) |
212 | 227 | |
213 | | |
214 | 228 | /* video hardware */ |
215 | 229 | MCFG_SCREEN_ADD("screen", RASTER) |
216 | 230 | MCFG_SCREEN_RAW_PARAMS( XTAL_17_73447MHz/5, I824X_LINE_CLOCKS, I824X_START_ACTIVE_SCAN, I824X_END_ACTIVE_SCAN, 312, I824X_START_Y, I824X_START_Y + I824X_SCREEN_HEIGHT ) |
r19932 | r19933 | |
219 | 233 | MCFG_GFXDECODE( odyssey2 ) |
220 | 234 | MCFG_PALETTE_LENGTH(24) |
221 | 235 | |
222 | | |
223 | 236 | /* sound hardware */ |
224 | 237 | MCFG_SPEAKER_STANDARD_MONO("mono") |
225 | 238 | MCFG_SOUND_ADD("custom", ODYSSEY2, XTAL_17_73447MHz/5) |
r19932 | r19933 | |
232 | 245 | MCFG_FRAGMENT_ADD(odyssey2_cartslot) |
233 | 246 | MACHINE_CONFIG_END |
234 | 247 | |
| 248 | |
235 | 249 | static MACHINE_CONFIG_START( g7400, odyssey2_state ) |
236 | 250 | /* basic machine hardware */ |
237 | 251 | MCFG_CPU_ADD("maincpu", I8048, XTAL_5_911MHz ) |
r19932 | r19933 | |
239 | 253 | MCFG_CPU_IO_MAP(g7400_io) |
240 | 254 | MCFG_QUANTUM_TIME(attotime::from_hz(60)) |
241 | 255 | |
242 | | |
243 | 256 | /* video hardware */ |
244 | 257 | MCFG_SCREEN_ADD("screen", RASTER) |
245 | | MCFG_SCREEN_RAW_PARAMS( 3547000*2, 448, 96, 416, 312, 39, 289 ) /* EF9340 doubles the input clock into dot clocks internally */ |
| 258 | MCFG_SCREEN_RAW_PARAMS( 3547000*2, 2*I824X_LINE_CLOCKS, 2*I824X_START_ACTIVE_SCAN, 2*I824X_END_ACTIVE_SCAN, 312, I824X_START_Y, I824X_START_Y + I824X_SCREEN_HEIGHT ) |
246 | 259 | MCFG_SCREEN_UPDATE_DRIVER(odyssey2_state, screen_update_odyssey2) |
247 | 260 | |
| 261 | MCFG_VIDEO_START_OVERRIDE(odyssey2_state,g7400) |
| 262 | |
248 | 263 | MCFG_GFXDECODE( odyssey2 ) |
249 | 264 | MCFG_PALETTE_LENGTH(24) |
250 | 265 | |
251 | | |
252 | 266 | /* sound hardware */ |
253 | 267 | MCFG_SPEAKER_STANDARD_MONO("mono") |
254 | 268 | MCFG_SOUND_ADD("custom", ODYSSEY2, 3547000) |
r19932 | r19933 | |
257 | 271 | MCFG_FRAGMENT_ADD(odyssey2_cartslot) |
258 | 272 | MACHINE_CONFIG_END |
259 | 273 | |
| 274 | |
260 | 275 | ROM_START (odyssey2) |
261 | 276 | ROM_REGION(0x10000,"maincpu",0) /* safer for the memory handler/bankswitching??? */ |
262 | 277 | ROM_LOAD ("o2bios.rom", 0x0000, 0x0400, CRC(8016a315) SHA1(b2e1955d957a475de2411770452eff4ea19f4cee)) |
r19932 | r19933 | |
283 | 298 | ROM_LOAD( "spr128-004.bin", 0x8000, 0x4000, CRC(e79dfb75) SHA1(37f33d79ffd1739d7c2f226b010a1eac28d74ca0) ) |
284 | 299 | ROM_END |
285 | 300 | |
| 301 | |
286 | 302 | ROM_START (videopac) |
287 | 303 | ROM_REGION(0x10000,"maincpu",0) /* safer for the memory handler/bankswitching??? */ |
288 | 304 | ROM_SYSTEM_BIOS( 0, "g7000", "g7000" ) |
r19932 | r19933 | |
303 | 319 | ROM_LOAD( "spr128-004.bin", 0x8000, 0x4000, CRC(e79dfb75) SHA1(37f33d79ffd1739d7c2f226b010a1eac28d74ca0) ) |
304 | 320 | ROM_END |
305 | 321 | |
| 322 | |
306 | 323 | ROM_START (g7400) |
307 | 324 | ROM_REGION(0x10000,"maincpu",0) /* safer for the memory handler/bankswitching??? */ |
308 | 325 | ROM_LOAD ("g7400.bin", 0x0000, 0x0400, CRC(e20a9f41) SHA1(5130243429b40b01a14e1304d0394b8459a6fbae)) |
r19932 | r19933 | |
312 | 329 | ROM_CART_LOAD("cart", 0x0000, 0x4000, ROM_MIRROR) |
313 | 330 | ROM_END |
314 | 331 | |
| 332 | |
315 | 333 | ROM_START (jopac) |
316 | 334 | ROM_REGION(0x10000,"maincpu",0) /* safer for the memory handler/bankswitching??? */ |
317 | 335 | ROM_LOAD ("jopac.bin", 0x0000, 0x0400, CRC(11647ca5) SHA1(54b8d2c1317628de51a85fc1c424423a986775e4)) |
r19932 | r19933 | |
321 | 339 | ROM_CART_LOAD("cart", 0x0000, 0x4000, ROM_MIRROR) |
322 | 340 | ROM_END |
323 | 341 | |
| 342 | |
324 | 343 | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ |
325 | 344 | COMP( 1978, odyssey2, 0, 0, odyssey2, odyssey2, odyssey2_state, odyssey2, "Magnavox", "Odyssey 2", 0 ) |
326 | 345 | COMP( 1979, videopac, odyssey2, 0, videopac, odyssey2, odyssey2_state, odyssey2, "Philips", "Videopac G7000/C52", 0 ) |
trunk/src/mess/machine/odyssey2.c
r19932 | r19933 | |
13 | 13 | |
14 | 14 | |
15 | 15 | |
16 | | static void odyssey2_switch_banks(running_machine &machine) |
| 16 | void odyssey2_state::switch_banks() |
17 | 17 | { |
18 | | odyssey2_state *state = machine.driver_data<odyssey2_state>(); |
19 | | switch ( state->m_cart_size ) |
| 18 | switch ( m_cart_size ) |
20 | 19 | { |
21 | 20 | case 12288: |
22 | 21 | /* 12KB cart support (for instance, KTAA as released) */ |
23 | | state->membank( "bank1" )->set_base( machine.root_device().memregion("user1")->base() + (state->m_p1 & 0x03) * 0xC00 ); |
24 | | state->membank( "bank2" )->set_base( machine.root_device().memregion("user1")->base() + (state->m_p1 & 0x03) * 0xC00 + 0x800 ); |
| 22 | membank( "bank1" )->set_base( memregion("user1")->base() + (m_p1 & 0x03) * 0xC00 ); |
| 23 | membank( "bank2" )->set_base( memregion("user1")->base() + (m_p1 & 0x03) * 0xC00 + 0x800 ); |
25 | 24 | break; |
26 | 25 | |
27 | 26 | case 16384: |
28 | 27 | /* 16KB cart support (for instance, full sized version KTAA) */ |
29 | | state->membank( "bank1" )->set_base( machine.root_device().memregion("user1")->base() + (state->m_p1 & 0x03) * 0x1000 + 0x400 ); |
30 | | state->membank( "bank2" )->set_base( machine.root_device().memregion("user1")->base() + (state->m_p1 & 0x03) * 0x1000 + 0xC00 ); |
| 28 | membank( "bank1" )->set_base( memregion("user1")->base() + (m_p1 & 0x03) * 0x1000 + 0x400 ); |
| 29 | membank( "bank2" )->set_base( memregion("user1")->base() + (m_p1 & 0x03) * 0x1000 + 0xC00 ); |
31 | 30 | break; |
32 | 31 | |
33 | 32 | default: |
34 | | state->membank("bank1")->set_base(machine.root_device().memregion("user1")->base() + (state->m_p1 & 0x03) * 0x800); |
35 | | state->membank("bank2")->set_base(state->memregion("user1")->base() + (state->m_p1 & 0x03) * 0x800 ); |
| 33 | membank("bank1")->set_base(memregion("user1")->base() + (m_p1 & 0x03) * 0x800); |
| 34 | membank("bank2")->set_base(memregion("user1")->base() + (m_p1 & 0x03) * 0x800 ); |
36 | 35 | break; |
37 | 36 | } |
38 | 37 | } |
39 | 38 | |
40 | | void odyssey2_the_voice_lrq_callback(device_t *device, int state) |
| 39 | |
| 40 | WRITE_LINE_MEMBER(odyssey2_state::the_voice_lrq_callback) |
41 | 41 | { |
42 | | odyssey2_state *drvstate = device->machine().driver_data<odyssey2_state>(); |
43 | | drvstate->m_the_voice_lrq_state = state; |
| 42 | m_the_voice_lrq_state = state; |
44 | 43 | } |
45 | 44 | |
46 | | READ8_MEMBER(odyssey2_state::odyssey2_t0_r) |
| 45 | |
| 46 | READ8_MEMBER(odyssey2_state::t0_read) |
47 | 47 | { |
48 | 48 | return ( m_the_voice_lrq_state == ASSERT_LINE ) ? 0 : 1; |
49 | 49 | } |
50 | 50 | |
| 51 | |
51 | 52 | DRIVER_INIT_MEMBER(odyssey2_state,odyssey2) |
52 | 53 | { |
53 | 54 | int i; |
r19932 | r19933 | |
77 | 78 | m_cart_size = size; |
78 | 79 | } |
79 | 80 | |
| 81 | |
80 | 82 | void odyssey2_state::machine_reset() |
81 | 83 | { |
82 | 84 | /* jump to "last" bank, will work for all sizes due to being mirrored */ |
83 | 85 | m_p1 = 0xFF; |
84 | 86 | m_p2 = 0xFF; |
85 | | odyssey2_switch_banks(machine()); |
| 87 | switch_banks(); |
86 | 88 | } |
87 | 89 | |
88 | 90 | /****** External RAM ******************************/ |
89 | 91 | |
90 | | READ8_MEMBER(odyssey2_state::odyssey2_bus_r) |
| 92 | READ8_MEMBER(odyssey2_state::io_read) |
91 | 93 | { |
92 | 94 | if ((m_p1 & (P1_VDC_COPY_MODE_ENABLE | P1_VDC_ENABLE)) == 0) |
93 | 95 | { |
94 | | return odyssey2_video_r(space, offset); /* seems to have higher priority than ram??? */ |
| 96 | return video_read(space, offset); /* seems to have higher priority than ram??? */ |
95 | 97 | } |
96 | 98 | if (!(m_p1 & P1_EXT_RAM_ENABLE)) |
97 | 99 | { |
r19932 | r19933 | |
101 | 103 | return 0; |
102 | 104 | } |
103 | 105 | |
104 | | WRITE8_MEMBER(odyssey2_state::odyssey2_bus_w) |
| 106 | |
| 107 | WRITE8_MEMBER(odyssey2_state::io_write) |
105 | 108 | { |
106 | 109 | if ((m_p1 & (P1_EXT_RAM_ENABLE | P1_VDC_COPY_MODE_ENABLE)) == 0x00) |
107 | 110 | { |
r19932 | r19933 | |
121 | 124 | } |
122 | 125 | else if (!(m_p1 & P1_VDC_ENABLE)) |
123 | 126 | { |
124 | | odyssey2_video_w(space, offset, data); |
| 127 | video_write(space, offset, data); |
125 | 128 | } |
126 | 129 | } |
127 | 130 | |
128 | | READ8_MEMBER(odyssey2_state::g7400_bus_r) |
| 131 | |
| 132 | READ8_MEMBER(odyssey2_state::g7400_io_read) |
129 | 133 | { |
130 | 134 | if ((m_p1 & (P1_VDC_COPY_MODE_ENABLE | P1_VDC_ENABLE)) == 0) |
131 | 135 | { |
132 | | return odyssey2_video_r(space, offset); /* seems to have higher priority than ram??? */ |
| 136 | return video_read(space, offset); /* seems to have higher priority than ram??? */ |
133 | 137 | } |
134 | 138 | else if (!(m_p1 & P1_EXT_RAM_ENABLE)) |
135 | 139 | { |
r19932 | r19933 | |
137 | 141 | } |
138 | 142 | else |
139 | 143 | { |
140 | | //return ef9341_r( offset & 0x02, offset & 0x01 ); |
| 144 | return ef9341_r( offset & 0x02, offset & 0x01 ); |
141 | 145 | } |
142 | 146 | |
143 | 147 | return 0; |
144 | 148 | } |
145 | 149 | |
146 | | WRITE8_MEMBER(odyssey2_state::g7400_bus_w) |
| 150 | |
| 151 | WRITE8_MEMBER(odyssey2_state::g7400_io_write) |
147 | 152 | { |
148 | 153 | if ((m_p1 & (P1_EXT_RAM_ENABLE | P1_VDC_COPY_MODE_ENABLE)) == 0x00) |
149 | 154 | { |
r19932 | r19933 | |
151 | 156 | } |
152 | 157 | else if (!(m_p1 & P1_VDC_ENABLE)) |
153 | 158 | { |
154 | | odyssey2_video_w(space, offset, data); |
| 159 | video_write(space, offset, data); |
155 | 160 | } |
156 | 161 | else |
157 | 162 | { |
158 | | //ef9341_w( offset & 0x02, offset & 0x01, data ); |
| 163 | ef9341_w( offset & 0x02, offset & 0x01, data ); |
159 | 164 | } |
160 | 165 | } |
161 | 166 | |
162 | 167 | /***** 8048 Ports ************************/ |
163 | 168 | |
164 | | READ8_MEMBER(odyssey2_state::odyssey2_getp1) |
| 169 | READ8_MEMBER(odyssey2_state::p1_read) |
165 | 170 | { |
166 | 171 | UINT8 data = m_p1; |
167 | 172 | |
r19932 | r19933 | |
169 | 174 | return data; |
170 | 175 | } |
171 | 176 | |
172 | | WRITE8_MEMBER(odyssey2_state::odyssey2_putp1) |
| 177 | |
| 178 | WRITE8_MEMBER(odyssey2_state::p1_write) |
173 | 179 | { |
174 | 180 | m_p1 = data; |
175 | 181 | |
176 | | odyssey2_switch_banks(machine()); |
| 182 | switch_banks(); |
177 | 183 | |
178 | | odyssey2_lum_w ( space, 0, m_p1 >> 7 ); |
| 184 | lum_write(space, 0, m_p1 >> 7); |
179 | 185 | |
180 | 186 | logerror("%.6f p1 written %.2x\n", machine().time().as_double(), data); |
181 | 187 | } |
182 | 188 | |
183 | | READ8_MEMBER(odyssey2_state::odyssey2_getp2) |
| 189 | |
| 190 | READ8_MEMBER(odyssey2_state::p2_read) |
184 | 191 | { |
185 | 192 | UINT8 h = 0xFF; |
186 | 193 | int i, j; |
r19932 | r19933 | |
218 | 225 | return m_p2; |
219 | 226 | } |
220 | 227 | |
221 | | WRITE8_MEMBER(odyssey2_state::odyssey2_putp2) |
| 228 | |
| 229 | WRITE8_MEMBER(odyssey2_state::p2_write) |
222 | 230 | { |
223 | 231 | m_p2 = data; |
224 | 232 | |
225 | 233 | logerror("%.6f p2 written %.2x\n", machine().time().as_double(), data); |
226 | 234 | } |
227 | 235 | |
228 | | READ8_MEMBER(odyssey2_state::odyssey2_getbus) |
| 236 | |
| 237 | READ8_MEMBER(odyssey2_state::bus_read) |
229 | 238 | { |
230 | 239 | UINT8 data = 0xff; |
231 | 240 | |
r19932 | r19933 | |
243 | 252 | return data; |
244 | 253 | } |
245 | 254 | |
246 | | WRITE8_MEMBER(odyssey2_state::odyssey2_putbus) |
| 255 | |
| 256 | WRITE8_MEMBER(odyssey2_state::bus_write) |
247 | 257 | { |
248 | 258 | logerror("%.6f bus written %.2x\n", machine().time().as_double(), data); |
249 | 259 | } |
250 | 260 | |
251 | | /////////////////////////////////// |
252 | | |
253 | | #ifdef UNUSED_FUNCTION |
254 | | int odyssey2_cart_verify(const UINT8 *cartdata, size_t size) |
255 | | { |
256 | | odyssey2_state *state = machine.driver_data<odyssey2_state>(); |
257 | | state->m_cart_size = size; |
258 | | if ( (size == 2048) |
259 | | || (size == 4096) |
260 | | || (size == 8192) |
261 | | || (size == 12288) |
262 | | || (size == 16384)) |
263 | | { |
264 | | return IMAGE_VERIFY_PASS; |
265 | | } |
266 | | |
267 | | return IMAGE_VERIFY_FAIL; |
268 | | } |
269 | | #endif |
trunk/src/mess/includes/odyssey2.h
r19932 | r19933 | |
56 | 56 | |
57 | 57 | struct ef9341_t |
58 | 58 | { |
| 59 | UINT8 TA; |
| 60 | UINT8 TB; |
| 61 | UINT8 busy; |
| 62 | }; |
| 63 | |
| 64 | struct ef9340_t |
| 65 | { |
59 | 66 | UINT8 X; |
60 | 67 | UINT8 Y; |
61 | 68 | UINT8 Y0; |
62 | 69 | UINT8 R; |
63 | 70 | UINT8 M; |
64 | | UINT8 TA; |
65 | | UINT8 TB; |
66 | | UINT8 busy; |
67 | | UINT8 ram[1024]; |
68 | 71 | }; |
69 | 72 | |
70 | | |
71 | 73 | class odyssey2_state : public driver_device |
72 | 74 | { |
73 | 75 | public: |
74 | 76 | odyssey2_state(const machine_config &mconfig, device_type type, const char *tag) |
75 | | : driver_device(mconfig, type, tag) { } |
| 77 | : driver_device(mconfig, type, tag) |
| 78 | , m_maincpu(*this, "maincpu") |
| 79 | , m_screen(*this, "screen") |
| 80 | , m_g7400(false) |
| 81 | { } |
76 | 82 | |
| 83 | required_device<cpu_device> m_maincpu; |
| 84 | required_device<screen_device> m_screen; |
| 85 | |
77 | 86 | int m_the_voice_lrq_state; |
78 | 87 | UINT8 *m_ram; |
79 | 88 | UINT8 m_p1; |
r19932 | r19933 | |
86 | 95 | UINT8 m_control_status; |
87 | 96 | UINT8 m_collision_status; |
88 | 97 | int m_iff; |
89 | | emu_timer *m_i824x_line_timer; |
90 | | emu_timer *m_i824x_hblank_timer; |
91 | 98 | bitmap_ind16 m_tmp_bitmap; |
92 | 99 | int m_start_vpos; |
93 | 100 | int m_start_vblank; |
94 | 101 | UINT8 m_lum; |
95 | 102 | sound_stream *m_sh_channel; |
96 | 103 | UINT16 m_sh_count; |
97 | | //ef9341_t ef9341; |
98 | | DECLARE_READ8_MEMBER(odyssey2_t0_r); |
99 | | DECLARE_READ8_MEMBER(odyssey2_bus_r); |
100 | | DECLARE_WRITE8_MEMBER(odyssey2_bus_w); |
101 | | DECLARE_READ8_MEMBER(g7400_bus_r); |
102 | | DECLARE_WRITE8_MEMBER(g7400_bus_w); |
103 | | DECLARE_READ8_MEMBER(odyssey2_getp1); |
104 | | DECLARE_WRITE8_MEMBER(odyssey2_putp1); |
105 | | DECLARE_READ8_MEMBER(odyssey2_getp2); |
106 | | DECLARE_WRITE8_MEMBER(odyssey2_putp2); |
107 | | DECLARE_READ8_MEMBER(odyssey2_getbus); |
108 | | DECLARE_WRITE8_MEMBER(odyssey2_putbus); |
109 | | DECLARE_READ8_MEMBER(odyssey2_video_r); |
110 | | DECLARE_WRITE8_MEMBER(odyssey2_video_w); |
111 | | DECLARE_WRITE8_MEMBER(odyssey2_lum_w); |
112 | | DECLARE_READ8_MEMBER(odyssey2_t1_r); |
| 104 | DECLARE_READ8_MEMBER(t0_read); |
| 105 | DECLARE_READ8_MEMBER(io_read); |
| 106 | DECLARE_WRITE8_MEMBER(io_write); |
| 107 | DECLARE_READ8_MEMBER(bus_read); |
| 108 | DECLARE_WRITE8_MEMBER(bus_write); |
| 109 | DECLARE_READ8_MEMBER(g7400_io_read); |
| 110 | DECLARE_WRITE8_MEMBER(g7400_io_write); |
| 111 | DECLARE_READ8_MEMBER(p1_read); |
| 112 | DECLARE_WRITE8_MEMBER(p1_write); |
| 113 | DECLARE_READ8_MEMBER(p2_read); |
| 114 | DECLARE_WRITE8_MEMBER(p2_write); |
| 115 | DECLARE_READ8_MEMBER(video_read); |
| 116 | DECLARE_WRITE8_MEMBER(video_write); |
| 117 | DECLARE_WRITE8_MEMBER(lum_write); |
| 118 | DECLARE_READ8_MEMBER(t1_read); |
113 | 119 | DECLARE_DRIVER_INIT(odyssey2); |
114 | 120 | virtual void machine_reset(); |
115 | 121 | virtual void video_start(); |
| 122 | void video_start_g7400(); |
116 | 123 | virtual void palette_init(); |
117 | 124 | UINT32 screen_update_odyssey2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
118 | | TIMER_CALLBACK_MEMBER(i824x_scanline_callback); |
119 | | TIMER_CALLBACK_MEMBER(i824x_hblank_callback); |
120 | | }; |
| 125 | DECLARE_WRITE_LINE_MEMBER(the_voice_lrq_callback); |
121 | 126 | |
| 127 | void ef9341_w( UINT8 command, UINT8 b, UINT8 data ); |
| 128 | UINT8 ef9341_r( UINT8 command, UINT8 b ); |
122 | 129 | |
123 | | /*----------- defined in video/odyssey2.c -----------*/ |
| 130 | protected: |
| 131 | ef9340_t m_ef9340; |
| 132 | ef9341_t m_ef9341; |
| 133 | UINT8 m_ef934x_ram_a[1024]; |
| 134 | UINT8 m_ef934x_ram_b[1024]; |
| 135 | bool m_g7400; |
124 | 136 | |
125 | | extern const UINT8 odyssey2_colors[]; |
| 137 | inline UINT16 ef9340_get_c_addr(); |
| 138 | inline void ef9340_inc_c(); |
126 | 139 | |
| 140 | void i824x_scanline(int vpos); |
| 141 | void er9340_scanline(int vpos); |
127 | 142 | |
| 143 | /* timers */ |
| 144 | static const device_timer_id TIMER_LINE = 0; |
| 145 | static const device_timer_id TIMER_HBLANK = 1; |
128 | 146 | |
| 147 | emu_timer *m_line_timer; |
| 148 | emu_timer *m_hblank_timer; |
129 | 149 | |
| 150 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
130 | 151 | |
| 152 | void switch_banks(); |
| 153 | }; |
| 154 | |
| 155 | |
| 156 | /*----------- defined in video/odyssey2.c -----------*/ |
| 157 | |
| 158 | |
131 | 159 | STREAM_UPDATE( odyssey2_sh_update ); |
132 | 160 | |
133 | | void odyssey2_ef9341_w( running_machine &machine, int command, int b, UINT8 data ); |
134 | | UINT8 odyssey2_ef9341_r( running_machine &machine, int command, int b ); |
135 | | |
136 | 161 | class odyssey2_sound_device : public device_t, |
137 | 162 | public device_sound_interface |
138 | 163 | { |
r19932 | r19933 | |
152 | 177 | extern const device_type ODYSSEY2; |
153 | 178 | |
154 | 179 | |
155 | | /*----------- defined in machine/odyssey2.c -----------*/ |
156 | | |
157 | | |
158 | | |
159 | | /* i/o ports */ |
160 | | |
161 | | |
162 | | |
163 | | |
164 | | void odyssey2_the_voice_lrq_callback( device_t *device, int state ); |
165 | | |
166 | | |
167 | | int odyssey2_cart_verify(const UINT8 *cartdata, size_t size); |
168 | | |
169 | | |
170 | 180 | #endif /* ODYSSEY2_H_ */ |
trunk/src/mess/video/odyssey2.c
r19932 | r19933 | |
130 | 130 | }; |
131 | 131 | |
132 | 132 | |
133 | | |
134 | | |
135 | 133 | void odyssey2_state::palette_init() |
136 | 134 | { |
137 | 135 | int i; |
r19932 | r19933 | |
142 | 140 | } |
143 | 141 | } |
144 | 142 | |
145 | | READ8_MEMBER(odyssey2_state::odyssey2_video_r) |
| 143 | |
| 144 | READ8_MEMBER(odyssey2_state::video_read) |
146 | 145 | { |
147 | | UINT8 data = 0; |
| 146 | UINT8 data = 0; |
148 | 147 | |
149 | | switch (offset) |
150 | | { |
151 | | case 0xa1: |
| 148 | switch (offset) |
| 149 | { |
| 150 | case 0xa1: |
152 | 151 | data = m_control_status; |
153 | 152 | m_iff = 0; |
154 | | machine().device("maincpu")->execute().set_input_line(0, CLEAR_LINE); |
| 153 | m_maincpu->set_input_line(0, CLEAR_LINE); |
155 | 154 | m_control_status &= ~ 0x08; |
156 | | if ( machine().primary_screen->hpos() < I824X_START_ACTIVE_SCAN || machine().primary_screen->hpos() > I824X_END_ACTIVE_SCAN ) |
| 155 | if ( m_screen->hpos() < I824X_START_ACTIVE_SCAN || m_screen->hpos() > I824X_END_ACTIVE_SCAN ) |
157 | 156 | { |
158 | 157 | data |= 1; |
159 | 158 | } |
| 159 | break; |
160 | 160 | |
161 | | break; |
162 | | |
163 | | case 0xa2: |
| 161 | case 0xa2: |
164 | 162 | data = m_collision_status; |
165 | 163 | m_collision_status = 0; |
| 164 | break; |
166 | 165 | |
167 | | break; |
| 166 | case 0xa4: |
| 167 | if (m_o2_vdc.s.control & VDC_CONTROL_REG_STROBE_XY) |
| 168 | { |
| 169 | m_y_beam_pos = m_screen->vpos() - m_start_vpos; |
| 170 | } |
168 | 171 | |
169 | | case 0xa4: |
| 172 | data = m_y_beam_pos; |
170 | 173 | |
171 | | if ((m_o2_vdc.s.control & VDC_CONTROL_REG_STROBE_XY)) |
172 | | m_y_beam_pos = machine().primary_screen->vpos() - m_start_vpos; |
| 174 | break; |
173 | 175 | |
174 | | data = m_y_beam_pos; |
175 | 176 | |
176 | | break; |
177 | | |
178 | | |
179 | 177 | case 0xa5: |
180 | 178 | |
181 | 179 | if ((m_o2_vdc.s.control & VDC_CONTROL_REG_STROBE_XY)) |
182 | 180 | { |
183 | | m_x_beam_pos = machine().primary_screen->hpos(); |
| 181 | m_x_beam_pos = m_screen->hpos(); |
184 | 182 | if ( m_x_beam_pos < I824X_START_ACTIVE_SCAN ) |
185 | 183 | { |
186 | 184 | m_x_beam_pos = m_x_beam_pos - I824X_START_ACTIVE_SCAN + I824X_LINE_CLOCKS; |
r19932 | r19933 | |
202 | 200 | return data; |
203 | 201 | } |
204 | 202 | |
205 | | WRITE8_MEMBER(odyssey2_state::odyssey2_video_w) |
| 203 | |
| 204 | WRITE8_MEMBER(odyssey2_state::video_write) |
206 | 205 | { |
207 | 206 | /* Update the sound */ |
208 | 207 | if( offset >= 0xa7 && offset <= 0xaa ) |
r19932 | r19933 | |
215 | 214 | && !(data & VDC_CONTROL_REG_STROBE_XY)) |
216 | 215 | { |
217 | 216 | /* Toggling strobe bit, tuck away values */ |
218 | | m_x_beam_pos = machine().primary_screen->hpos(); |
| 217 | m_x_beam_pos = m_screen->hpos(); |
219 | 218 | if ( m_x_beam_pos < I824X_START_ACTIVE_SCAN ) |
220 | 219 | { |
221 | 220 | m_x_beam_pos = m_x_beam_pos - I824X_START_ACTIVE_SCAN + 228; |
r19932 | r19933 | |
225 | 224 | m_x_beam_pos = m_x_beam_pos - I824X_START_ACTIVE_SCAN; |
226 | 225 | } |
227 | 226 | |
228 | | m_y_beam_pos = machine().primary_screen->vpos() - m_start_vpos; |
| 227 | m_y_beam_pos = m_screen->vpos() - m_start_vpos; |
229 | 228 | } |
230 | 229 | } |
231 | 230 | |
232 | 231 | m_o2_vdc.reg[offset] = data; |
233 | 232 | } |
234 | 233 | |
235 | | WRITE8_MEMBER(odyssey2_state::odyssey2_lum_w) |
| 234 | |
| 235 | WRITE8_MEMBER(odyssey2_state::lum_write) |
236 | 236 | { |
237 | 237 | m_lum = data; |
238 | 238 | } |
239 | 239 | |
240 | | READ8_MEMBER(odyssey2_state::odyssey2_t1_r) |
| 240 | |
| 241 | READ8_MEMBER(odyssey2_state::t1_read) |
241 | 242 | { |
242 | | if ( machine().primary_screen->vpos() > m_start_vpos && machine().primary_screen->vpos() < m_start_vblank ) |
| 243 | if ( m_screen->vpos() > m_start_vpos && m_screen->vpos() < m_start_vblank ) |
243 | 244 | { |
244 | | if ( machine().primary_screen->hpos() >= I824X_START_ACTIVE_SCAN && machine().primary_screen->hpos() < I824X_END_ACTIVE_SCAN ) |
| 245 | if ( m_screen->hpos() >= I824X_START_ACTIVE_SCAN && m_screen->hpos() < I824X_END_ACTIVE_SCAN ) |
245 | 246 | { |
246 | 247 | return 1; |
247 | 248 | } |
r19932 | r19933 | |
249 | 250 | return 0; |
250 | 251 | } |
251 | 252 | |
252 | | TIMER_CALLBACK_MEMBER(odyssey2_state::i824x_scanline_callback) |
| 253 | |
| 254 | void odyssey2_state::i824x_scanline(int vpos) |
253 | 255 | { |
254 | 256 | UINT8 collision_map[160]; |
255 | | int vpos = machine().primary_screen->vpos(); |
256 | 257 | |
257 | 258 | if ( vpos < m_start_vpos ) |
258 | 259 | return; |
r19932 | r19933 | |
537 | 538 | m_control_status |= 0x08; |
538 | 539 | if ( ! m_iff ) |
539 | 540 | { |
540 | | machine().device("maincpu")->execute().set_input_line(0, ASSERT_LINE); |
| 541 | m_maincpu->set_input_line(0, ASSERT_LINE); |
541 | 542 | m_iff = 1; |
542 | 543 | } |
543 | 544 | } |
544 | 545 | } |
545 | 546 | |
546 | | TIMER_CALLBACK_MEMBER(odyssey2_state::i824x_hblank_callback) |
| 547 | |
| 548 | void odyssey2_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
547 | 549 | { |
548 | | int vpos = machine().primary_screen->vpos(); |
| 550 | int vpos = m_screen->vpos(); |
549 | 551 | |
550 | | if ( vpos < m_start_vpos - 1 ) |
551 | | return; |
| 552 | switch ( id ) |
| 553 | { |
| 554 | case TIMER_LINE: |
| 555 | // handle i824x line timer |
| 556 | i824x_scanline(vpos); |
| 557 | break; |
552 | 558 | |
553 | | if ( vpos < m_start_vblank - 1 ) |
554 | | { |
555 | | m_control_status |= 0x01; |
| 559 | case TIMER_HBLANK: |
| 560 | // handle i824x HBlank timer |
| 561 | if ( vpos < m_start_vpos - 1 ) |
| 562 | { |
| 563 | return; |
| 564 | } |
| 565 | |
| 566 | if ( vpos < m_start_vblank - 1 ) |
| 567 | { |
| 568 | m_control_status |= 0x01; |
| 569 | } |
| 570 | break; |
556 | 571 | } |
557 | 572 | } |
558 | 573 | |
| 574 | |
559 | 575 | /*************************************************************************** |
560 | 576 | |
561 | 577 | Start the video hardware emulation. |
r19932 | r19933 | |
564 | 580 | |
565 | 581 | void odyssey2_state::video_start() |
566 | 582 | { |
567 | | screen_device *screen = machine().first_screen(); |
568 | | |
569 | 583 | memset(m_o2_vdc.reg, 0, 0x100); |
570 | 584 | |
571 | 585 | m_o2_snd_shift[0] = m_o2_snd_shift[1] = 0; |
r19932 | r19933 | |
586 | 600 | m_control_status = 0; |
587 | 601 | m_iff = 0; |
588 | 602 | |
589 | | screen->register_screen_bitmap(m_tmp_bitmap); |
| 603 | m_screen->register_screen_bitmap(m_tmp_bitmap); |
590 | 604 | |
591 | | m_i824x_line_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(odyssey2_state::i824x_scanline_callback),this)); |
592 | | m_i824x_line_timer->adjust( machine().primary_screen->time_until_pos(1, I824X_START_ACTIVE_SCAN ), 0, machine().primary_screen->scan_period() ); |
| 605 | m_line_timer = timer_alloc(TIMER_LINE); |
| 606 | m_line_timer->adjust( m_screen->time_until_pos(1, I824X_START_ACTIVE_SCAN ), 0, m_screen->scan_period() ); |
593 | 607 | |
594 | | m_i824x_hblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(odyssey2_state::i824x_hblank_callback),this)); |
595 | | m_i824x_hblank_timer->adjust( machine().primary_screen->time_until_pos(1, I824X_END_ACTIVE_SCAN + 18 ), 0, machine().primary_screen->scan_period() ); |
| 608 | m_hblank_timer = timer_alloc(TIMER_HBLANK); |
| 609 | m_hblank_timer->adjust( m_screen->time_until_pos(1, I824X_END_ACTIVE_SCAN + 18 ), 0, m_screen->scan_period() ); |
596 | 610 | } |
597 | 611 | |
| 612 | |
| 613 | void odyssey2_state::video_start_g7400() |
| 614 | { |
| 615 | video_start(); |
| 616 | |
| 617 | m_ef9340.X = 0; |
| 618 | m_ef9340.Y = 0; |
| 619 | m_ef9340.Y0 = 0; |
| 620 | m_ef9340.R = 0; |
| 621 | m_ef9340.M = 0; |
| 622 | m_ef9341.TA = 0; |
| 623 | m_ef9341.TB = 0; |
| 624 | m_ef9341.busy = 0; |
| 625 | |
| 626 | m_g7400 = true; |
| 627 | } |
| 628 | |
| 629 | |
598 | 630 | /*************************************************************************** |
599 | 631 | |
600 | 632 | Refresh the video screen |
r19932 | r19933 | |
655 | 687 | /* Throw an interrupt if enabled */ |
656 | 688 | if( state->m_o2_vdc.s.control & 0x4 ) |
657 | 689 | { |
658 | | device->machine().device("maincpu")->execute().set_input_line(1, HOLD_LINE); /* Is this right? */ |
| 690 | state->m_maincpu->set_input_line(1, HOLD_LINE); /* Is this right? */ |
659 | 691 | } |
660 | 692 | |
661 | 693 | /* Adjust volume */ |
r19932 | r19933 | |
676 | 708 | Thomson EF9340/EF9341 extra chips in the g7400 |
677 | 709 | */ |
678 | 710 | |
679 | | #ifdef UNUSED_FUNCTION |
680 | | INLINE UINT16 ef9341_get_c_addr( odyssey2_state *state ) |
| 711 | UINT16 odyssey2_state::ef9340_get_c_addr() |
681 | 712 | { |
682 | | if ( ( state->m_ef9341.Y & 0x0C ) == 0x0C ) |
| 713 | if ( ( m_ef9340.Y & 0x0C ) == 0x0C ) |
683 | 714 | { |
684 | | return 0x318 | ( ( state->m_ef9341.X & 0x38 ) << 2 ) | ( state->m_ef9341.X & 0x07 ); |
| 715 | return 0x318 | ( ( m_ef9340.X & 0x38 ) << 2 ) | ( m_ef9340.X & 0x07 ); |
685 | 716 | } |
686 | | if ( state->m_ef9341.X & 0x20 ) |
| 717 | if ( m_ef9340.X & 0x20 ) |
687 | 718 | { |
688 | | return 0x300 | ( ( state->m_ef9341.Y & 0x07 ) << 5 ) | ( state->m_ef9341.Y & 0x18 ) | ( state->m_ef9341.X & 0x07 ); |
| 719 | return 0x300 | ( ( m_ef9340.Y & 0x07 ) << 5 ) | ( m_ef9340.Y & 0x18 ) | ( m_ef9340.X & 0x07 ); |
689 | 720 | } |
690 | | return ( state->m_ef9341.Y << 5 ) | state->m_ef9341.X; |
| 721 | return ( m_ef9340.Y << 5 ) | m_ef9340.X; |
691 | 722 | } |
692 | 723 | |
693 | | INLINE void ef9341_inc_c( odyssey2_state *state ) |
| 724 | void odyssey2_state::ef9340_inc_c() |
694 | 725 | { |
695 | | state->m_ef9341.X++; |
696 | | if ( state->m_ef9341.X >= 40 ) |
| 726 | m_ef9340.X++; |
| 727 | if ( m_ef9340.X >= 40 ) |
697 | 728 | { |
698 | | state->m_ef9341.Y = ( state->m_ef9341.Y + 1 ) % 24; |
| 729 | m_ef9340.Y = ( m_ef9340.Y + 1 ) % 24; |
699 | 730 | } |
700 | 731 | } |
701 | 732 | |
702 | | void odyssey2_ef9341_w( running_machine &machine, int command, int b, UINT8 data ) |
| 733 | void odyssey2_state::ef9341_w( UINT8 command, UINT8 b, UINT8 data ) |
703 | 734 | { |
704 | | odyssey2_state *state = machine.driver_data<odyssey2_state>(); |
705 | 735 | logerror("ef9341 %s write, t%s, data %02X\n", command ? "command" : "data", b ? "B" : "A", data ); |
706 | 736 | |
707 | 737 | if ( command ) |
708 | 738 | { |
709 | 739 | if ( b ) |
710 | 740 | { |
711 | | state->m_ef9341.TB = data; |
712 | | state->m_ef9341.busy = 0x80; |
713 | | switch( state->m_ef9341.TB & 0xE0 ) |
| 741 | m_ef9341.TB = data; |
| 742 | m_ef9341.busy = 0x80; |
| 743 | switch( m_ef9341.TB & 0xE0 ) |
714 | 744 | { |
715 | 745 | case 0x00: /* Begin row */ |
716 | | state->m_ef9341.X = 0; |
717 | | state->m_ef9341.Y = state->m_ef9341.TA & 0x1F; |
| 746 | m_ef9340.X = 0; |
| 747 | m_ef9340.Y = m_ef9341.TA & 0x1F; |
718 | 748 | break; |
719 | 749 | case 0x20: /* Load Y */ |
720 | | state->m_ef9341.Y = state->m_ef9341.TA & 0x1F; |
| 750 | m_ef9340.Y = m_ef9341.TA & 0x1F; |
721 | 751 | break; |
722 | 752 | case 0x40: /* Load X */ |
723 | | state->m_ef9341.X = state->m_ef9341.TA & 0x3F; |
| 753 | m_ef9340.X = m_ef9341.TA & 0x3F; |
724 | 754 | break; |
725 | 755 | case 0x60: /* INC C */ |
726 | | ef9341_inc_c(state); |
| 756 | ef9340_inc_c(); |
727 | 757 | break; |
728 | 758 | case 0x80: /* Load M */ |
729 | | state->m_ef9341.M = state->m_ef9341.TA; |
| 759 | m_ef9340.M = m_ef9341.TA; |
730 | 760 | break; |
731 | 761 | case 0xA0: /* Load R */ |
732 | | state->m_ef9341.R = state->m_ef9341.TA; |
| 762 | m_ef9340.R = m_ef9341.TA; |
733 | 763 | break; |
734 | 764 | case 0xC0: /* Load Y0 */ |
735 | | state->m_ef9341.Y0 = state->m_ef9341.TA & 0x3F; |
| 765 | m_ef9340.Y0 = m_ef9341.TA & 0x3F; |
736 | 766 | break; |
737 | 767 | } |
738 | | state->m_ef9341.busy = 0; |
| 768 | m_ef9341.busy = 0; |
739 | 769 | } |
740 | 770 | else |
741 | 771 | { |
742 | | state->m_ef9341.TA = data; |
| 772 | m_ef9341.TA = data; |
743 | 773 | } |
744 | 774 | } |
745 | 775 | else |
746 | 776 | { |
747 | 777 | if ( b ) |
748 | 778 | { |
749 | | state->m_ef9341.TB = data; |
750 | | state->m_ef9341.busy = 0x80; |
751 | | switch ( state->m_ef9341.M & 0xE0 ) |
| 779 | m_ef9341.TB = data; |
| 780 | m_ef9341.busy = 0x80; |
| 781 | switch ( m_ef9340.M & 0xE0 ) |
752 | 782 | { |
753 | 783 | case 0x00: /* Write */ |
754 | | state->m_ef9341.ram[ ef9341_get_c_addr(state) ] = state->m_ef9341.TB; |
755 | | ef9341_inc_c(state); |
| 784 | m_ef934x_ram_b[ ef9340_get_c_addr() & 0x3ff ] = m_ef9341.TB; |
| 785 | ef9340_inc_c(); |
756 | 786 | break; |
757 | 787 | case 0x20: /* Read */ |
758 | | logerror("ef9341 unimplemented data action %02X\n", state->m_ef9341.M & 0xE0 ); |
759 | | ef9341_inc_c(state); |
| 788 | logerror("ef9341 unimplemented data action %02X\n", m_ef9340.M & 0xE0 ); |
| 789 | ef9340_inc_c(); |
760 | 790 | break; |
761 | 791 | case 0x40: /* Write without increment */ |
762 | 792 | case 0x60: /* Read without increment */ |
763 | 793 | case 0x80: /* Write slice */ |
764 | 794 | case 0xA0: /* Read slice */ |
765 | | logerror("ef9341 unimplemented data action %02X\n", state->m_ef9341.M & 0xE0 ); |
| 795 | logerror("ef9341 unimplemented data action %02X\n", m_ef9340.M & 0xE0 ); |
766 | 796 | break; |
767 | 797 | } |
768 | | state->m_ef9341.busy = 0; |
| 798 | m_ef9341.busy = 0; |
769 | 799 | } |
770 | 800 | else |
771 | 801 | { |
772 | | state->m_ef9341.TA = data; |
| 802 | m_ef9341.TA = data; |
773 | 803 | } |
774 | 804 | } |
775 | 805 | } |
776 | 806 | |
777 | | UINT8 odyssey2_ef9341_r( running_machine &machine, int command, int b ) |
| 807 | UINT8 odyssey2_state::ef9341_r( UINT8 command, UINT8 b ) |
778 | 808 | { |
779 | | odyssey2_state *state = machine.driver_data<odyssey2_state>(); |
780 | 809 | UINT8 data = 0xFF; |
781 | 810 | |
782 | 811 | logerror("ef9341 %s read, t%s\n", command ? "command" : "data", b ? "B" : "A" ); |
r19932 | r19933 | |
788 | 817 | } |
789 | 818 | else |
790 | 819 | { |
791 | | data = state->m_ef9341.busy; |
| 820 | data = m_ef9341.busy; |
792 | 821 | } |
793 | 822 | } |
794 | 823 | else |
795 | 824 | { |
796 | 825 | if ( b ) |
797 | 826 | { |
798 | | data = state->m_ef9341.TB; |
799 | | state->m_ef9341.busy = 0x80; |
| 827 | data = m_ef9341.TB; |
| 828 | m_ef9341.busy = 0x80; |
800 | 829 | } |
801 | 830 | else |
802 | 831 | { |
803 | | data = state->m_ef9341.TA; |
| 832 | data = m_ef9341.TA; |
804 | 833 | } |
805 | 834 | } |
806 | 835 | return data; |
807 | 836 | } |
808 | | #endif |
809 | 837 | |
| 838 | |
| 839 | void odyssey2_state::er9340_scanline(int vpos) |
| 840 | { |
| 841 | if ( vpos < m_start_vpos ) |
| 842 | { |
| 843 | return; |
| 844 | } |
| 845 | |
| 846 | if ( vpos < m_start_vblank ) |
| 847 | { |
| 848 | } |
| 849 | } |
| 850 | |
| 851 | |
810 | 852 | const device_type ODYSSEY2 = &device_creator<odyssey2_sound_device>; |
811 | 853 | |
812 | 854 | odyssey2_sound_device::odyssey2_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |