1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli
3 /***********************************************************************************************************
4 
5  A2600 VCS ROM cart emulation
6  Simple cart hardware with no additional hw
7 
8  Mapper implementation based on the wonderful docs by Kevtris
9  http://blog.kevtris.org/blogfiles/Atari%202600%20Mappers.txt
10 
11  (also inspired by previous work by Wilbert Pol et al.)
12 
13  ***********************************************************************************************************/
14 
15 
16 #include "emu.h"
17 #include "rom.h"
18 
19 
20 //-------------------------------------------------
21 //  a26_rom_*k_device - constructor
22 //-------------------------------------------------
23 
24 DEFINE_DEVICE_TYPE(A26_ROM_2K,    a26_rom_2k_device,    "vcs_2k",    "Atari VCS 2600 2K ROM Carts")
25 DEFINE_DEVICE_TYPE(A26_ROM_4K,    a26_rom_4k_device,    "vcs_4k",    "Atari VCS 2600 4K ROM Carts")
26 DEFINE_DEVICE_TYPE(A26_ROM_F4,    a26_rom_f4_device,    "vcs_f4",    "Atari VCS 2600 ROM Carts w/F4 bankswitch")
27 DEFINE_DEVICE_TYPE(A26_ROM_F6,    a26_rom_f6_device,    "vcs_f6",    "Atari VCS 2600 ROM Carts w/F6 bankswitch")
28 DEFINE_DEVICE_TYPE(A26_ROM_F8,    a26_rom_f8_device,    "vcs_f8",    "Atari VCS 2600 ROM Carts w/F8 bankswitch")
29 DEFINE_DEVICE_TYPE(A26_ROM_F8_SW, a26_rom_f8_sw_device, "vcs_f8_sw", "Atari VCS 2600 ROM Cart Snow White")
30 DEFINE_DEVICE_TYPE(A26_ROM_FA,    a26_rom_fa_device,    "vcs_fa",    "Atari VCS 2600 ROM Carts w/FA bankswitch")
31 DEFINE_DEVICE_TYPE(A26_ROM_FE,    a26_rom_fe_device,    "vcs_fe",    "Atari VCS 2600 ROM Carts w/FE bankswitch")
32 DEFINE_DEVICE_TYPE(A26_ROM_3E,    a26_rom_3e_device,    "vcs_3e",    "Atari VCS 2600 ROM Carts w/3E bankswitch")
33 DEFINE_DEVICE_TYPE(A26_ROM_3F,    a26_rom_3f_device,    "vcs_3f",    "Atari VCS 2600 ROM Carts w/3F bankswitch")
34 DEFINE_DEVICE_TYPE(A26_ROM_E0,    a26_rom_e0_device,    "vcs_e0",    "Atari VCS 2600 ROM Carts w/E0 bankswitch")
35 DEFINE_DEVICE_TYPE(A26_ROM_E7,    a26_rom_e7_device,    "vcs_e7",    "Atari VCS 2600 ROM Carts w/E7 bankswitch")
36 DEFINE_DEVICE_TYPE(A26_ROM_UA,    a26_rom_ua_device,    "vcs_ua",    "Atari VCS 2600 ROM Carts w/UA bankswitch")
37 DEFINE_DEVICE_TYPE(A26_ROM_CV,    a26_rom_cv_device,    "vcs_cv",    "Atari VCS 2600 ROM Carts w/Commavid bankswitch")
38 DEFINE_DEVICE_TYPE(A26_ROM_DC,    a26_rom_dc_device,    "vcs_dc",    "Atari VCS 2600 ROM Carts w/Dynacom bankswitch")
39 DEFINE_DEVICE_TYPE(A26_ROM_FV,    a26_rom_fv_device,    "vcs_fv",    "Atari VCS 2600 ROM Carts w/FV bankswitch")
40 DEFINE_DEVICE_TYPE(A26_ROM_JVP,   a26_rom_jvp_device,   "vcs_jvp",   "Atari VCS 2600 ROM Carts w/JVP bankswitch")
41 DEFINE_DEVICE_TYPE(A26_ROM_4IN1,  a26_rom_4in1_device,  "vcs_4in1",  "Atari VCS 2600 ROM Cart 4 in 1")
42 DEFINE_DEVICE_TYPE(A26_ROM_8IN1,  a26_rom_8in1_device,  "vcs_8in1",  "Atari VCS 2600 ROM Cart 8 in 1")
43 DEFINE_DEVICE_TYPE(A26_ROM_32IN1, a26_rom_32in1_device, "vcs_32in1", "Atari VCS 2600 ROM Cart 32 in 1")
44 DEFINE_DEVICE_TYPE(A26_ROM_X07,   a26_rom_x07_device,   "vcs_x07",   "Atari VCS 2600 ROM Carts w/X07 bankswitch")
45 
46 
a26_rom_2k_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)47 a26_rom_2k_device::a26_rom_2k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
48 	: device_t(mconfig, type, tag, owner, clock), device_vcs_cart_interface(mconfig, *this)
49 {
50 }
51 
a26_rom_2k_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)52 a26_rom_2k_device::a26_rom_2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
53 	: a26_rom_2k_device(mconfig, A26_ROM_2K, tag, owner, clock)
54 {
55 }
56 
57 
a26_rom_4k_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)58 a26_rom_4k_device::a26_rom_4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
59 	: a26_rom_2k_device(mconfig, A26_ROM_4K, tag, owner, clock)
60 {
61 }
62 
63 
a26_rom_f6_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)64 a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
65 	: a26_rom_2k_device(mconfig, type, tag, owner, clock)
66 	, m_base_bank(-1) // set to -1 to help the Xin1 multicart...
67 {
68 }
69 
a26_rom_f6_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)70 a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
71 	: a26_rom_f6_device(mconfig, A26_ROM_F6, tag, owner, clock)
72 {
73 }
74 
75 
a26_rom_f4_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)76 a26_rom_f4_device::a26_rom_f4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
77 	: a26_rom_f6_device(mconfig, A26_ROM_F4, tag, owner, clock)
78 {
79 }
80 
81 
a26_rom_f8_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)82 a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
83 	: a26_rom_f6_device(mconfig, type, tag, owner, clock)
84 {
85 }
86 
a26_rom_f8_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)87 a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
88 	: a26_rom_f8_device(mconfig, A26_ROM_F8, tag, owner, clock)
89 {
90 }
91 
a26_rom_f8_sw_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)92 a26_rom_f8_sw_device::a26_rom_f8_sw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
93 	: a26_rom_f8_device(mconfig, A26_ROM_F8_SW, tag, owner, clock)
94 {
95 }
96 
a26_rom_fa_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)97 a26_rom_fa_device::a26_rom_fa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
98 	: a26_rom_f6_device(mconfig, A26_ROM_FA, tag, owner, clock)
99 {
100 }
101 
102 
a26_rom_fe_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)103 a26_rom_fe_device::a26_rom_fe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
104 	: a26_rom_2k_device(mconfig, A26_ROM_FE, tag, owner, clock), m_base_bank(0), m_trigger_on_next_access(0)
105 {
106 }
107 
108 
a26_rom_3e_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)109 a26_rom_3e_device::a26_rom_3e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
110 	: a26_rom_f6_device(mconfig, A26_ROM_3E, tag, owner, clock), m_num_bank(0), m_ram_bank(0), m_ram_enable(0)
111 {
112 }
113 
114 
a26_rom_3f_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)115 a26_rom_3f_device::a26_rom_3f_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
116 	: a26_rom_f6_device(mconfig, A26_ROM_3F, tag, owner, clock), m_num_bank(0)
117 {
118 }
119 
120 
a26_rom_e0_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)121 a26_rom_e0_device::a26_rom_e0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
122 	: a26_rom_f6_device(mconfig, A26_ROM_E0, tag, owner, clock)
123 {
124 }
125 
126 
a26_rom_e7_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)127 a26_rom_e7_device::a26_rom_e7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
128 	: a26_rom_f6_device(mconfig, A26_ROM_E7, tag, owner, clock), m_ram_bank(0)
129 {
130 }
131 
132 
a26_rom_ua_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)133 a26_rom_ua_device::a26_rom_ua_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
134 	: a26_rom_f6_device(mconfig, A26_ROM_UA, tag, owner, clock)
135 {
136 }
137 
138 
a26_rom_cv_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)139 a26_rom_cv_device::a26_rom_cv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
140 	: a26_rom_2k_device(mconfig, A26_ROM_CV, tag, owner, clock)
141 {
142 }
143 
144 
a26_rom_dc_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)145 a26_rom_dc_device::a26_rom_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
146 	: a26_rom_f6_device(mconfig, A26_ROM_DC, tag, owner, clock)
147 {
148 }
149 
150 
a26_rom_fv_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)151 a26_rom_fv_device::a26_rom_fv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
152 	: a26_rom_f6_device(mconfig, A26_ROM_FV, tag, owner, clock), m_locked(0)
153 {
154 }
155 
156 
a26_rom_jvp_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)157 a26_rom_jvp_device::a26_rom_jvp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
158 	: a26_rom_f6_device(mconfig, A26_ROM_JVP, tag, owner, clock)
159 {
160 }
161 
162 
a26_rom_4in1_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)163 a26_rom_4in1_device::a26_rom_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
164 	: a26_rom_f6_device(mconfig, A26_ROM_4IN1, tag, owner, clock)
165 {
166 }
167 
168 
a26_rom_8in1_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)169 a26_rom_8in1_device::a26_rom_8in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
170 	: a26_rom_f8_device(mconfig, A26_ROM_8IN1, tag, owner, clock), m_reset_bank(0)
171 {
172 }
173 
174 
a26_rom_32in1_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)175 a26_rom_32in1_device::a26_rom_32in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
176 	: a26_rom_f6_device(mconfig, A26_ROM_32IN1, tag, owner, clock)
177 {
178 }
179 
a26_rom_x07_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)180 a26_rom_x07_device::a26_rom_x07_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
181 	: a26_rom_f6_device(mconfig, A26_ROM_X07, tag, owner, clock)
182 {
183 }
184 
185 
device_start()186 void a26_rom_2k_device::device_start()
187 {
188 }
189 
device_reset()190 void a26_rom_2k_device::device_reset()
191 {
192 }
193 
device_start()194 void a26_rom_f6_device::device_start()
195 {
196 	save_item(NAME(m_base_bank));
197 }
198 
device_reset()199 void a26_rom_f6_device::device_reset()
200 {
201 	m_base_bank = 0;
202 }
203 
device_reset()204 void a26_rom_f4_device::device_reset()
205 {
206 	m_base_bank = 7;
207 }
208 
device_reset()209 void a26_rom_f8_sw_device::device_reset()
210 {
211 	// Snow White proto starts from bank 1!!!
212 	m_base_bank = 1;
213 }
214 
device_start()215 void a26_rom_fe_device::device_start()
216 {
217 	save_item(NAME(m_base_bank));
218 	save_item(NAME(m_trigger_on_next_access));
219 }
220 
device_reset()221 void a26_rom_fe_device::device_reset()
222 {
223 	m_base_bank = 0;
224 	m_trigger_on_next_access = 0;
225 }
226 
device_start()227 void a26_rom_3e_device::device_start()
228 {
229 	save_item(NAME(m_base_bank));
230 	save_item(NAME(m_ram_bank));
231 	save_item(NAME(m_ram_enable));
232 }
233 
device_reset()234 void a26_rom_3e_device::device_reset()
235 {
236 	m_num_bank = m_rom_size / 0x800;
237 	m_base_bank = m_num_bank - 1;
238 	m_ram_bank = 0;
239 	m_ram_enable = 0;
240 }
241 
device_reset()242 void a26_rom_3f_device::device_reset()
243 {
244 	m_num_bank = m_rom_size / 0x800;
245 	m_base_bank = m_num_bank - 1;
246 }
247 
device_start()248 void a26_rom_e0_device::device_start()
249 {
250 	save_item(NAME(m_base_banks));
251 }
252 
device_reset()253 void a26_rom_e0_device::device_reset()
254 {
255 	m_base_banks[0] = 4;
256 	m_base_banks[1] = 5;
257 	m_base_banks[2] = 6;
258 	m_base_banks[3] = 7;
259 }
260 
device_start()261 void a26_rom_e7_device::device_start()
262 {
263 	save_item(NAME(m_base_bank));
264 	save_item(NAME(m_ram_bank));
265 }
266 
device_reset()267 void a26_rom_e7_device::device_reset()
268 {
269 	m_base_bank = 0;
270 	m_ram_bank = 0;
271 }
272 
device_reset()273 void a26_rom_ua_device::device_reset()
274 {
275 	m_base_bank = 0;
276 }
277 
device_start()278 void a26_rom_fv_device::device_start()
279 {
280 	save_item(NAME(m_base_bank));
281 	save_item(NAME(m_locked));
282 }
283 
device_reset()284 void a26_rom_fv_device::device_reset()
285 {
286 	m_base_bank = 0;
287 	m_locked = 0;
288 }
289 
290 
device_reset()291 void a26_rom_4in1_device::device_reset()
292 {
293 	m_base_bank++;
294 	m_base_bank &= 3;
295 }
296 
297 
device_start()298 void a26_rom_8in1_device::device_start()
299 {
300 	save_item(NAME(m_base_bank));
301 	save_item(NAME(m_reset_bank));
302 }
303 
device_reset()304 void a26_rom_8in1_device::device_reset()
305 {
306 	// we use here two different bank counter: the main one for the 8x8K chunks,
307 	// and the usual one (m_base_bank) for the 4K bank of the current game
308 	m_reset_bank++;
309 	m_reset_bank &= 7;
310 	m_base_bank = 0;
311 }
312 
313 
device_reset()314 void a26_rom_32in1_device::device_reset()
315 {
316 	m_base_bank++;
317 	m_base_bank &= 0x1f;
318 }
319 
320 
321 /*-------------------------------------------------
322  mapper specific handlers
323  -------------------------------------------------*/
324 
325 /*-------------------------------------------------
326  BASE 2K & 4K Carts:
327  no bankswitch
328 
329  GAMES: a large majority
330  -------------------------------------------------*/
331 
read_rom(offs_t offset)332 uint8_t a26_rom_2k_device::read_rom(offs_t offset)
333 {
334 	// Super Chip RAM reads are mapped in 0x1080-0x10ff
335 	if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
336 	{
337 		return m_ram[offset & (m_ram.size() - 1)];
338 	}
339 
340 	return m_rom[offset & (m_rom_size - 1)];
341 }
342 
343 /*-------------------------------------------------
344  "F4 Bankswitch" Carts:
345  read/write access to 0x1ff4-0x1ffb determines the
346  4K ROM bank to be read
347 
348  GAMES: Fatal Run
349  -------------------------------------------------*/
350 
read_rom(offs_t offset)351 uint8_t a26_rom_f4_device::read_rom(offs_t offset)
352 {
353 	// Super Chip RAM reads are mapped in 0x1080-0x10ff
354 	if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
355 	{
356 		return m_ram[offset & (m_ram.size() - 1)];
357 	}
358 
359 	// update banks
360 	if (!machine().side_effects_disabled())
361 	{
362 		switch (offset)
363 		{
364 			case 0x0ff4:
365 			case 0x0ff5:
366 			case 0x0ff6:
367 			case 0x0ff7:
368 			case 0x0ff8:
369 			case 0x0ff9:
370 			case 0x0ffa:
371 			case 0x0ffb:
372 				m_base_bank = offset - 0x0ff4;
373 				break;
374 		}
375 	}
376 
377 	return m_rom[offset + (m_base_bank * 0x1000)];
378 }
379 
write_bank(address_space & space,offs_t offset,uint8_t data)380 void a26_rom_f4_device::write_bank(address_space &space, offs_t offset, uint8_t data)
381 {
382 	// Super Chip RAM writes are mapped in 0x1000-0x107f
383 	if (!m_ram.empty() && offset < 0x80)
384 	{
385 		m_ram[offset & (m_ram.size() - 1)] = data;
386 		return;
387 	}
388 
389 	switch (offset)
390 	{
391 		case 0x0ff4:
392 		case 0x0ff5:
393 		case 0x0ff6:
394 		case 0x0ff7:
395 		case 0x0ff8:
396 		case 0x0ff9:
397 		case 0x0ffa:
398 		case 0x0ffb:
399 			m_base_bank = offset - 0x0ff4;
400 			break;
401 		default:
402 			logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
403 			break;
404 	}
405 }
406 
407 /*-------------------------------------------------
408  "F6 Bankswitch" Carts:
409  read/write access to 0x1ff6-0x1ff9 determines the
410  4K ROM bank to be read
411 
412  GAMES: Atari 16K games, like Crossbow, Crystal
413  Castles and the 2-in-1 carts
414 
415  -------------------------------------------------*/
416 
read_rom(offs_t offset)417 uint8_t a26_rom_f6_device::read_rom(offs_t offset)
418 {
419 	// Super Chip RAM reads are mapped in 0x1080-0x10ff
420 	if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
421 	{
422 		return m_ram[offset & (m_ram.size() - 1)];
423 	}
424 
425 	// update banks
426 	if (!machine().side_effects_disabled())
427 	{
428 		switch (offset)
429 		{
430 			case 0x0ff6:
431 			case 0x0ff7:
432 			case 0x0ff8:
433 			case 0x0ff9:
434 				m_base_bank = offset - 0x0ff6;
435 				break;
436 		}
437 	}
438 
439 	return m_rom[offset + (m_base_bank * 0x1000)];
440 }
441 
write_bank(address_space & space,offs_t offset,uint8_t data)442 void a26_rom_f6_device::write_bank(address_space &space, offs_t offset, uint8_t data)
443 {
444 	// Super Chip RAM writes are mapped in 0x1000-0x107f
445 	if (!m_ram.empty() && offset < 0x80)
446 	{
447 		m_ram[offset & (m_ram.size() - 1)] = data;
448 		return;
449 	}
450 
451 	switch (offset)
452 	{
453 		case 0x0ff6:
454 		case 0x0ff7:
455 		case 0x0ff8:
456 		case 0x0ff9:
457 			m_base_bank = offset - 0x0ff6;
458 			break;
459 		default:
460 			logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
461 			break;
462 	}
463 }
464 
465 /*-------------------------------------------------
466  "F8 Bankswitch" Carts:
467  read/write access to 0x1ff8-0x1ff9 determines the
468  4K ROM bank to be read
469 
470  GAMES: Atari 8K games, like Asteroids, Battlezone
471  and Taz
472 
473  -------------------------------------------------*/
474 
read_rom(offs_t offset)475 uint8_t a26_rom_f8_device::read_rom(offs_t offset)
476 {
477 	// Super Chip RAM reads are mapped in 0x1080-0x10ff
478 	if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
479 	{
480 		return m_ram[offset & (m_ram.size() - 1)];
481 	}
482 
483 	// update banks
484 	if (!machine().side_effects_disabled())
485 	{
486 		switch (offset)
487 		{
488 			case 0x0ff8:
489 			case 0x0ff9:
490 				m_base_bank = offset - 0x0ff8;
491 				break;
492 		}
493 	}
494 
495 	return m_rom[offset + (m_base_bank * 0x1000)];
496 }
497 
write_bank(address_space & space,offs_t offset,uint8_t data)498 void a26_rom_f8_device::write_bank(address_space &space, offs_t offset, uint8_t data)
499 {
500 	// Super Chip RAM writes are mapped in 0x1000-0x107f
501 	if (!m_ram.empty() && offset < 0x80)
502 	{
503 		m_ram[offset & (m_ram.size() - 1)] = data;
504 		return;
505 	}
506 
507 	switch (offset)
508 	{
509 		case 0x0ff8:
510 		case 0x0ff9:
511 			m_base_bank = offset - 0x0ff8;
512 			break;
513 		default:
514 			logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
515 			break;
516 	}
517 }
518 
519 /*-------------------------------------------------
520  "FA Bankswitch" Carts:
521  read/write access to 0x1ff8-0x1ffa determines the
522  4K ROM bank to be read
523  These games contained the CBS RAM+ chip (256bytes
524  of RAM)
525 
526  GAMES: CBS RAM Plus games like Omega Race and Tunnel
527  Runner
528 
529  -------------------------------------------------*/
530 
read_rom(offs_t offset)531 uint8_t a26_rom_fa_device::read_rom(offs_t offset)
532 {
533 	// CBS RAM+ reads are mapped in 0x1100-0x11ff
534 	if (!m_ram.empty() && offset >= 0x100 && offset < 0x200)
535 	{
536 		return m_ram[offset & (m_ram.size() - 1)];
537 	}
538 
539 	// update banks
540 	if (!machine().side_effects_disabled())
541 	{
542 		switch (offset)
543 		{
544 			case 0x0ff8:
545 			case 0x0ff9:
546 			case 0x0ffa:
547 				m_base_bank = offset - 0x0ff8;
548 				break;
549 		}
550 	}
551 
552 	return m_rom[offset + (m_base_bank * 0x1000)];
553 }
554 
write_bank(address_space & space,offs_t offset,uint8_t data)555 void a26_rom_fa_device::write_bank(address_space &space, offs_t offset, uint8_t data)
556 {
557 	// CBS RAM+ writes are mapped in 0x1000-0x10ff
558 	if (!m_ram.empty() && offset < 0x100)
559 	{
560 		m_ram[offset & (m_ram.size() - 1)] = data;
561 	}
562 
563 	switch (offset)
564 	{
565 		case 0x0ff8:
566 		case 0x0ff9:
567 		case 0x0ffa:
568 			m_base_bank = offset - 0x0ff8;
569 			break;
570 		default:
571 			logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
572 			break;
573 	}
574 }
575 
576 /*-------------------------------------------------
577  "FE Bankswitch" Carts:
578  read/write access to 0x01fe-0x1ff determines the
579  4K ROM bank to be read
580 
581  GAMES: Activision 8K games like Decathlon
582 
583  -------------------------------------------------*/
584 /*
585 
586  There seems to be a kind of lag between the writing to address 0x1FE and the
587  Activision switcher springing into action. It waits for the next byte to arrive
588  on the data bus, which is the new PCH in the case of a JSR, and the PCH of the
589  stored PC on the stack in the case of an RTS.
590 
591  depending on last byte & 0x20 -> 0x00 -> switch to bank #1
592  -> 0x20 -> switch to bank #0
593 
594  */
595 
read_rom(offs_t offset)596 uint8_t a26_rom_fe_device::read_rom(offs_t offset)
597 {
598 	uint8_t data;
599 
600 	// Super Chip RAM reads are mapped in 0x1080-0x10ff
601 	if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
602 	{
603 		return m_ram[offset & (m_ram.size() - 1)];
604 	}
605 
606 	data = m_rom[offset + (m_base_bank * 0x1000)];
607 
608 	if (!machine().side_effects_disabled())
609 	{
610 		if (m_trigger_on_next_access)
611 		{
612 			m_base_bank = BIT(data, 5) ? 0 : 1;
613 			m_trigger_on_next_access = 0;
614 		}
615 	}
616 
617 	return data;
618 }
619 
write_ram(offs_t offset,uint8_t data)620 void a26_rom_fe_device::write_ram(offs_t offset, uint8_t data)
621 {
622 	// Super Chip RAM writes are mapped in 0x1000-0x107f
623 	if (!m_ram.empty() && offset < 0x80)
624 	{
625 		m_ram[offset & (m_ram.size() - 1)] = data;
626 	}
627 }
628 
read_bank(address_space & space,offs_t offset)629 uint8_t a26_rom_fe_device::read_bank(address_space &space, offs_t offset)
630 {
631 	uint8_t data = space.read_byte(0xfe + offset);
632 
633 	if (!machine().side_effects_disabled())
634 	{
635 		switch (offset & 1)
636 		{
637 			case 0:
638 				// The next byte on the data bus determines which bank to switch to
639 				m_trigger_on_next_access = 1;
640 				break;
641 
642 			case 1:
643 				if (m_trigger_on_next_access)
644 				{
645 					m_base_bank = BIT(data, 5) ? 0 : 1;
646 					m_trigger_on_next_access = 0;
647 				}
648 				break;
649 		}
650 	}
651 	return data;
652 }
653 
write_bank(address_space & space,offs_t offset,uint8_t data)654 void a26_rom_fe_device::write_bank(address_space &space, offs_t offset, uint8_t data)
655 {
656 	space.write_byte(0xfe, data);
657 	if (!machine().side_effects_disabled())
658 	{
659 		// The next byte on the data bus determines which bank to switch to
660 		m_trigger_on_next_access = 1;
661 	}
662 }
663 
664 /*-------------------------------------------------
665  "3E Bankswitch" Carts:
666  write access to 0x3e determines the 2K ROM bank to
667  be read, write access to 0x3f determines the RAM bank
668  to be read
669 
670  GAMES: Boulder Dash (Homebrew)
671 
672  -------------------------------------------------*/
673 
read_rom(offs_t offset)674 uint8_t a26_rom_3e_device::read_rom(offs_t offset)
675 {
676 	if (!m_ram.empty() && m_ram_enable && offset < 0x400)
677 		return m_ram[offset + (m_ram_bank * 0x400)];
678 
679 	if (offset >= 0x800)
680 		return m_rom[(offset & 0x7ff) + (m_num_bank - 1) * 0x800];
681 	else
682 		return m_rom[offset + m_base_bank * 0x800];
683 }
684 
write_bank(address_space & space,offs_t offset,uint8_t data)685 void a26_rom_3e_device::write_bank(address_space &space, offs_t offset, uint8_t data)
686 {
687 	if (offset == 0x3f)
688 	{
689 		m_base_bank = data & (m_num_bank - 1);
690 		m_ram_enable = 0;
691 	}
692 	else if (offset == 0x3e)
693 	{
694 		m_ram_bank = data & 0x1f;
695 		m_ram_enable = 1;
696 	}
697 }
698 
write_ram(offs_t offset,uint8_t data)699 void a26_rom_3e_device::write_ram(offs_t offset, uint8_t data)
700 {
701 	if (!m_ram.empty() && m_ram_enable && offset >= 0x400 && offset < 0x800)
702 		m_ram[(offset & 0x3ff) + (m_ram_bank * 0x400)] = data;
703 }
704 
705 
706 /*-------------------------------------------------
707  "3F Bankswitch" Carts:
708  write access to 0x00-0x3f determines the 2K ROM bank
709  to be read
710 
711  GAMES: Tigervision 8K games like Espial and Miner
712  2049er. Extended version with bankswitch up to 512K
713  shall be supported as well (but we lack a test case)
714 
715  -------------------------------------------------*/
716 
read_rom(offs_t offset)717 uint8_t a26_rom_3f_device::read_rom(offs_t offset)
718 {
719 	if (offset >= 0x800)
720 		return m_rom[(offset & 0x7ff)  + (m_num_bank - 1) * 0x800];
721 	else
722 		return m_rom[offset + m_base_bank * 0x800];
723 }
724 
write_bank(address_space & space,offs_t offset,uint8_t data)725 void a26_rom_3f_device::write_bank(address_space &space, offs_t offset, uint8_t data)
726 {
727 	m_base_bank = data & (m_num_bank - 1);
728 }
729 
730 /*-------------------------------------------------
731  "E0 Bankswitch" Carts:
732  read/write access to 0x1fe0-0x1ff8 determines the
733  1K ROM bank to be read in each 1K chunk (0x1c00-0x1fff
734  always points to the last 1K of the ROM)
735 
736  GAMES: Parker Bros. 8K games like Gyruss and Popeye
737 
738  -------------------------------------------------*/
739 
read_rom(offs_t offset)740 uint8_t a26_rom_e0_device::read_rom(offs_t offset)
741 {
742 	// update banks
743 	if (!machine().side_effects_disabled())
744 	{
745 		if (offset >= 0xfe0 && offset <= 0xff8)
746 			m_base_banks[(offset >> 3) & 3] = offset & 7;
747 	}
748 
749 	return m_rom[(offset & 0x3ff) + (m_base_banks[(offset >> 10) & 3] * 0x400)];
750 }
751 
write_bank(address_space & space,offs_t offset,uint8_t data)752 void a26_rom_e0_device::write_bank(address_space &space, offs_t offset, uint8_t data)
753 {
754 	if (offset >= 0xfe0 && offset <= 0xff8)
755 		m_base_banks[(offset >> 3) & 3] = offset & 7;
756 }
757 
758 
759 /*-------------------------------------------------
760  "E7 Bankswitch" Carts:
761  this PCB can handle up to 16K of ROM and 2K of RAM,
762  with the following layout
763  1000-17ff is selectable bank
764  1800-19ff is RAM
765  1a00-1fff is fixed to the last 0x600 of ROM
766 
767  The selectable bank can be ROM (if selected by
768  0x1fe0-0x1fe6 access) or a first 1K of RAM (if
769  selected by 0x1fe7 access).
770  The other 256byte RAM bank can be one of the
771  four different chunks forming the other 1K of RAM
772  (the bank is selected by accessing 0x1fe8-0x1feb)
773 
774  GAMES: M Network 16K games like Burgertime and
775  Bump'n Jump
776 
777  -------------------------------------------------*/
778 
read_rom(offs_t offset)779 uint8_t a26_rom_e7_device::read_rom(offs_t offset)
780 {
781 	// update banks
782 	if (!machine().side_effects_disabled())
783 	{
784 		if (offset >= 0xfe0 && offset <= 0xfe7)
785 			m_base_bank = offset - 0xfe0;
786 		if (offset >= 0xfe8 && offset <= 0xfeb)
787 			m_ram_bank = offset - 0xfe8;
788 	}
789 
790 	if (!m_ram.empty())
791 	{
792 		// 1K of RAM
793 		if (m_base_bank == 0x07 && offset >= 0x400 && offset < 0x800)
794 			return m_ram[0x400 + (offset & 0x3ff)];
795 		// the other 1K of RAM
796 		if (offset >= 0x900 && offset < 0xa00)
797 		{
798 			offset -= 0x900;
799 			return m_ram[offset + (m_ram_bank * 0x100)];
800 		}
801 	}
802 
803 	if (offset > 0x800)
804 		return m_rom[(offset & 0x7ff) + 0x3800];
805 	else
806 		return m_rom[(offset & 0x7ff) + (m_base_bank * 0x800)];
807 }
808 
write_bank(address_space & space,offs_t offset,uint8_t data)809 void a26_rom_e7_device::write_bank(address_space &space, offs_t offset, uint8_t data)
810 {
811 	if (offset >= 0xfe0 && offset <= 0xfe7)
812 		m_base_bank = offset - 0xfe0;
813 	if (offset >= 0xfe8 && offset <= 0xfeb)
814 		m_ram_bank = offset - 0xfe8;
815 
816 	if (!m_ram.empty())
817 	{
818 		// 1K of RAM
819 		if (m_base_bank == 0x07 && offset < 0x400)
820 			m_ram[0x400 + (offset & 0x3ff)] = data;
821 		// the other 1K of RAM
822 		if (offset >= 0x800 && offset < 0x900)
823 		{
824 			offset -= 0x800;
825 			m_ram[offset + (m_ram_bank * 0x100)] = data;
826 		}
827 	}
828 }
829 
830 /*-------------------------------------------------
831  "UA Bankswitch" Carts:
832  read/write access to 0x200-0x27f determines the
833  4K ROM bank to be read (0x220-0x23f for low 4K,
834  0x240-0x27f for high 4K)
835 
836  GAMES: UA Ltd. 8K games like Funky Flash and
837  Pleaides
838 
839  -------------------------------------------------*/
840 
read_rom(offs_t offset)841 uint8_t a26_rom_ua_device::read_rom(offs_t offset)
842 {
843 	return m_rom[(offset + (m_base_bank * 0x1000)) & (m_rom_size - 1)];
844 }
845 
read_bank(address_space & space,offs_t offset)846 uint8_t a26_rom_ua_device::read_bank(address_space &space, offs_t offset)
847 {
848 	if (!machine().side_effects_disabled())
849 		m_base_bank = offset >> 6;
850 
851 	return 0;
852 }
853 
write_bank(address_space & space,offs_t offset,uint8_t data)854 void a26_rom_ua_device::write_bank(address_space &space, offs_t offset, uint8_t data)
855 {
856 	m_base_bank = offset >> 6;
857 }
858 
859 
860 /*-------------------------------------------------
861  Commavid Carts:
862  It allows for both ROM and RAM on the cartridge,
863  without using bankswitching.  There's 2K of ROM
864  and 1K of RAM.
865 
866  GAMES: Magicard and Video Life by Commavid
867 
868  -------------------------------------------------*/
869 
read_rom(offs_t offset)870 uint8_t a26_rom_cv_device::read_rom(offs_t offset)
871 {
872 	if (!m_ram.empty() && offset < 0x400)
873 	{
874 		return m_ram[offset & (m_ram.size() - 1)];
875 	}
876 
877 	// games shall not read from 0x1400-0x17ff (RAM write)
878 	// but we fall back to ROM just in case...
879 	return m_rom[offset & 0x7ff];
880 }
881 
write_bank(address_space & space,offs_t offset,uint8_t data)882 void a26_rom_cv_device::write_bank(address_space &space, offs_t offset, uint8_t data)
883 {
884 	if (!m_ram.empty() && offset >= 0x400 && offset < 0x800)
885 	{
886 		m_ram[offset & (m_ram.size() - 1)] = data;
887 	}
888 }
889 
890 
891 /*-------------------------------------------------
892  Dynacom Megaboy Carts (aka "F0 Banswitch"):
893  read/write access to 0x1ff0 determines the 4K ROM
894  bank to be read (each access increases the bank index
895  up to 16, since the cart was 64K wide)
896 
897  GAMES: Megaboy by Dynacom
898 
899  -------------------------------------------------*/
900 
read_rom(offs_t offset)901 uint8_t a26_rom_dc_device::read_rom(offs_t offset)
902 {
903 	if (!machine().side_effects_disabled())
904 	{
905 		if (offset == 0xff0)
906 			m_base_bank = (m_base_bank + 1) & 0x0f;
907 	}
908 
909 	if (offset == 0xfec)
910 		return m_base_bank;
911 
912 	return m_rom[offset + (m_base_bank * 0x1000)];
913 }
914 
write_bank(address_space & space,offs_t offset,uint8_t data)915 void a26_rom_dc_device::write_bank(address_space &space, offs_t offset, uint8_t data)
916 {
917 	if (offset == 0xff0)
918 		m_base_bank = (m_base_bank + 1) & 0x0f;
919 }
920 
921 
922 /*-------------------------------------------------
923  "FV Bankswitch" Carts:
924  The first access to 0x1fd0 switch the bank, but
925  only if pc() & 0x1f00 == 0x1f00!
926 
927  GAMES: Challenge by HES
928 
929  -------------------------------------------------*/
930 
read_rom(offs_t offset)931 uint8_t a26_rom_fv_device::read_rom(offs_t offset)
932 {
933 	if (!machine().side_effects_disabled())
934 	{
935 		if (offset == 0xfd0)
936 		{
937 			if (!m_locked && (machine().device<cpu_device>("maincpu")->pc() & 0x1f00) == 0x1f00)
938 			{
939 				m_locked = 1;
940 				m_base_bank = m_base_bank ^ 0x01;
941 			}
942 		}
943 	}
944 
945 	return m_rom[offset + (m_base_bank * 0x1000)];
946 }
947 
write_bank(address_space & space,offs_t offset,uint8_t data)948 void a26_rom_fv_device::write_bank(address_space &space, offs_t offset, uint8_t data)
949 {
950 	if (offset == 0xfd0)
951 	{
952 		if (!m_locked && (machine().device<cpu_device>("maincpu")->pc() & 0x1f00) == 0x1f00)
953 		{
954 			m_locked = 1;
955 			m_base_bank = m_base_bank ^ 0x01;
956 		}
957 	}
958 }
959 
960 
961 /*-------------------------------------------------
962  "JVP Bankswitch" Carts:
963  read/write access to 0x0fa0-0x0fc0 determines the
964  4K ROM bank to be read (notice that this overlaps
965  the RIOT, currently handled in the main driver until
966  I can better investigate the behavior)
967 
968  GAMES: No test case!?!
969 
970  -------------------------------------------------*/
971 
read_rom(offs_t offset)972 uint8_t a26_rom_jvp_device::read_rom(offs_t offset)
973 {
974 	return m_rom[offset + (m_base_bank * 0x1000)];
975 }
976 
write_bank(address_space & space,offs_t offset,uint8_t data)977 void a26_rom_jvp_device::write_bank(address_space &space, offs_t offset, uint8_t data)
978 {
979 	switch (offset)
980 	{
981 		case 0x00:
982 		case 0x20:
983 			m_base_bank ^= 1;
984 			break;
985 		default:
986 			//printf("%04X: write to unknown mapper address %02X\n", m_maincpu->pc(), 0xfa0 + offset);
987 			break;
988 	}
989 }
990 
991 
992 /*-------------------------------------------------
993  4 in 1 Carts (Reset based):
994  the 4K bank changes at each reset
995 
996  GAMES: 4 in 1 carts
997 
998  -------------------------------------------------*/
999 
read_rom(offs_t offset)1000 uint8_t a26_rom_4in1_device::read_rom(offs_t offset)
1001 {
1002 	return m_rom[offset + (m_base_bank * 0x1000)];
1003 }
1004 
1005 
1006 /*-------------------------------------------------
1007  8 in 1 Carts (Reset based):
1008  the 8K banks change at each reset, and internally
1009  each game runs as a F8-bankswitched cart
1010 
1011  GAMES: 8 in 1 cart
1012 
1013  -------------------------------------------------*/
1014 
read_rom(offs_t offset)1015 uint8_t a26_rom_8in1_device::read_rom(offs_t offset)
1016 {
1017 	if (!machine().side_effects_disabled())
1018 	{
1019 		switch (offset)
1020 		{
1021 			case 0x0ff8:
1022 			case 0x0ff9:
1023 				m_base_bank = offset - 0x0ff8;
1024 				break;
1025 		}
1026 	}
1027 
1028 	return m_rom[offset + (m_base_bank * 0x1000) + (m_reset_bank * 0x2000)];
1029 }
1030 
1031 
1032 /*-------------------------------------------------
1033  32 in 1 Carts (Reset based):
1034  the 2K banks change at each reset
1035 
1036  GAMES: 32 in 1 cart
1037 
1038  -------------------------------------------------*/
1039 
read_rom(offs_t offset)1040 uint8_t a26_rom_32in1_device::read_rom(offs_t offset)
1041 {
1042 	return m_rom[(offset & 0x7ff) + (m_base_bank * 0x800)];
1043 }
1044 
1045 
1046 /*-------------------------------------------------
1047  "X07 Bankswitch" Carts:
1048  banking done with a PALC22V10B
1049  implementation based on information at
1050  http://blog.kevtris.org/blogfiles/Atari%202600%20Mappers.txt
1051  --------------------------------------------------*/
1052 
read_rom(offs_t offset)1053 uint8_t a26_rom_x07_device::read_rom(offs_t offset)
1054 {
1055 	return m_rom[offset + (m_base_bank * 0x1000)];
1056 }
1057 
write_bank(address_space & space,offs_t offset,uint8_t data)1058 void a26_rom_x07_device::write_bank(address_space &space, offs_t offset, uint8_t data)
1059 {
1060 	/*
1061 	A13           A0
1062 	----------------
1063 	0 1xxx nnnn 1101
1064 	*/
1065 
1066 	if ((offset & 0x180f) == 0x080d)
1067 	{
1068 		m_base_bank = (offset & 0x00f0) >> 4;
1069 	}
1070 	/*
1071 	A13           A0
1072 	----------------
1073 	0 0xxx 0nxx xxxx
1074 	*/
1075 
1076 	if ((offset & 0x1880) == 0x0000)
1077 	{
1078 		// only has an effect if bank is already 14 or 15
1079 		if (m_base_bank == 14 || m_base_bank == 15)
1080 		{
1081 			if (offset & 0x0040)
1082 			{
1083 				m_base_bank = 15;
1084 			}
1085 			else
1086 			{
1087 				m_base_bank = 14;
1088 			}
1089 
1090 		}
1091 	}
1092 }
1093