1 // license:GPL-2.0+
2 // copyright-holders:Juergen Buchmueller
3 /******************************************************************************
4 * Microtan 65
5 *
6 * machine driver
7 *
8 * Juergen Buchmueller <pullmoll@t-online.de>, Jul 2000
9 *
10 * Thanks go to Geoff Macdonald <mail@geoff.org.uk>
11 * for his site http://www.geoff.org.uk/microtan/index.htm
12 * and to Fabrice Frances <frances@ensica.fr>
13 * for his site http://oric.free.fr/microtan.html
14 *
15 *****************************************************************************/
16
17 #include "emu.h"
18 #include "includes/microtan.h"
19
20 //#define VERBOSE 1
21 #include "logmacro.h"
22
23
24 static const char keyboard[8][9][8] = {
25 { /* normal */
26 { 27,'1','2','3','4','5','6','7'},
27 {'8','9','0',':','-', 12,127,'^'},
28 {'q','w','e','r','t','y','u','i'},
29 {'o','p','[',']', 13, 3, 0, 0},
30 {'a','s','d','f','g','h','j','k'},
31 {'l',';','@', 92, 0,'z','x','c'},
32 {'v','b','n','m',',','.','/', 0},
33 { 10,' ','-',',', 13,'.','0','1'},
34 {'2','3','4','5','6','7','8','9'},
35 },
36 { /* Shift */
37 { 27,'!','"','#','$','%','&', 39},
38 {'(',')','~','*','=', 12,127,'_'},
39 {'Q','W','E','R','T','Y','U','I'},
40 {'O','P','{','}', 13, 3, 0, 0},
41 {'A','S','D','F','G','H','J','K'},
42 {'L','+','`','|', 0,'Z','X','C'},
43 {'V','B','N','M','<','>','?', 0},
44 { 10,' ','-',',', 13,'.','0','1'},
45 {'2','3','4','5','6','7','8','9'},
46 },
47 { /* Control */
48 { 27,'1','2','3','4','5','6','7'},
49 {'8','9','0',':','-','`',127, 30},
50 { 17, 23, 5, 18, 20, 25, 21, 9},
51 { 15, 16, 27, 29, 13, 3, 0, 0},
52 { 1, 19, 4, 6, 7, 8, 10, 11},
53 { 12,';','@', 28, 0, 26, 24, 3},
54 { 22, 2, 14, 13,',','.','/', 0},
55 { 10,' ','-',',', 13,'.','0','1'},
56 {'2','3','4','5','6','7','8','9'},
57 },
58 { /* Shift+Control */
59 { 27,'!','"','#','$','%','&', 39},
60 {'(',')','~','*','=', 12,127, 31},
61 { 17, 23, 5, 18, 20, 25, 21, 9},
62 { 15, 16, 27, 29, 13,127, 0, 0},
63 { 1, 19, 4, 6, 7, 8, 10, 11},
64 { 12,'+','`', 28, 0, 26, 24, 3},
65 { 22, 2, 14, 13,',','.','/', 0},
66 { 10,' ','-',',', 13,'.','0','1'},
67 {'2','3','4','5','6','7','8','9'},
68 },
69 { /* CapsLock */
70 { 27,'1','2','3','4','5','6','7'},
71 {'8','9','0',':','-', 12,127,'^'},
72 {'Q','W','E','R','T','Y','U','I'},
73 {'O','P','[',']', 13, 3, 0, 0},
74 {'A','S','D','F','G','H','J','K'},
75 {'L',';','@', 92, 0,'Z','X','C'},
76 {'V','B','N','M',',','.','/', 0},
77 { 10,' ','-',',', 13,'.','0','1'},
78 {'2','3','4','5','6','7','8','9'},
79 },
80 { /* Shift+CapsLock */
81 { 27,'!','"','#','$','%','&', 39},
82 {'(',')','~','*','=', 12,127,'_'},
83 {'q','w','e','r','t','y','u','i'},
84 {'o','p','{','}', 13, 3, 0, 0},
85 {'a','s','d','f','g','h','j','k'},
86 {'l','+','`','|', 0,'z','x','c'},
87 {'v','b','n','m','<','>','?', 0},
88 { 10,' ','-',',', 13,'.','0','1'},
89 {'2','3','4','5','6','7','8','9'},
90 },
91 { /* Control+CapsLock */
92 { 27,'1','2','3','4','5','6','7'},
93 {'8','9','0',':','-', 12,127, 9},
94 { 17, 23, 5, 18, 20, 25, 21, 9},
95 { 15, 16, 27, 29, 13,127, 0, 0},
96 { 1, 19, 4, 6, 7, 8, 10, 11},
97 { 12,';', 39, 28, 0, 26, 24, 3},
98 { 22, 2, 14, 13,',','.','/', 0},
99 { 10,' ','-',',', 13,'.','0','1'},
100 {'2','3','4','5','6','7','8','9'},
101 },
102 { /* Shift+Control+CapsLock */
103 { 27,'!','"','#','$','%','&', 39},
104 {'(',')','~','*','=', 12,127, 9},
105 { 17, 23, 5, 18, 20, 25, 21, 9},
106 { 15, 16, 27, 29, 13,127, 0, 0},
107 { 1, 19, 4, 6, 7, 8, 10, 11},
108 { 12,':','"', 28, 0, 26, 24, 3},
109 { 22, 2, 14, 13,',','.','/', 0},
110 { 10,' ','-',',', 13,'.','0','1'},
111 {'2','3','4','5','6','7','8','9'},
112 },
113 };
114
115
sound_r()116 uint8_t microtan_state::sound_r()
117 {
118 int data = 0xff;
119 LOG("sound_r: -> %02x\n", data);
120 return data;
121 }
122
sound_w(uint8_t data)123 void microtan_state::sound_w(uint8_t data)
124 {
125 LOG("sound_w: <- %02x\n", data);
126 }
127
128
bffx_r(offs_t offset)129 uint8_t microtan_state::bffx_r(offs_t offset)
130 {
131 int data = 0xff;
132 switch( offset & 3 )
133 {
134 case 0: /* BFF0: read enables chunky graphics */
135 m_chunky_graphics = 1;
136 LOG("bff0_r: -> %02x (chunky graphics on)\n", data);
137 break;
138 case 1: /* BFF1: read undefined (?) */
139 LOG("bff1_r: -> %02x\n", data);
140 break;
141 case 2: /* BFF2: read undefined (?) */
142 LOG("bff2_r: -> %02x\n", data);
143 break;
144 case 3: /* BFF3: read keyboard/keypad */
145 switch (m_config->read() & 3)
146 {
147 case 0: /* ASCII Keyboard */
148 data = m_keyboard_ascii;
149 break;
150 case 1: /* Hex Keypad */
151 data = 0x00;
152 for (u8 i = 0; i < 4; i++)
153 if (BIT(m_keypad_column, i))
154 data |= m_io_keypad[i]->read();
155
156 break;
157 case 2: /* ETI Keypad */
158 data = (m_keypad->read() & 0x1f) | (m_config->read() & 0x60);
159 break;
160 }
161 LOG("bff3_r: -> %02x (keyboard ASCII)\n", data);
162 break;
163 }
164 return data;
165 }
166
167
168 /* This callback is called one clock cycle after BFF2 is written (delayed nmi) */
TIMER_CALLBACK_MEMBER(microtan_state::pulse_nmi)169 TIMER_CALLBACK_MEMBER(microtan_state::pulse_nmi)
170 {
171 m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
172 }
173
bffx_w(offs_t offset,uint8_t data)174 void microtan_state::bffx_w(offs_t offset, uint8_t data)
175 {
176 switch( offset & 3 )
177 {
178 case 0: /* BFF0: write reset keyboard interrupt flag */
179 /* This removes bit 7 from the ASCII value of the last key pressed. */
180 LOG("bff0_w: %d <- %02x (keyboard IRQ clear )\n", offset, data);
181 m_keyboard_ascii &= ~0x80;
182 m_irq_line->in_w<IRQ_KBD>(0);
183 break;
184 case 1: /* BFF1: write delayed NMI */
185 LOG("bff1_w: %d <- %02x (delayed NMI)\n", offset, data);
186 m_pulse_nmi_timer->adjust(m_maincpu->cycles_to_attotime(8));
187 break;
188 case 2: /* BFF2: write keypad */
189 LOG("bff2_w: %d <- %02x (keypad column)\n", offset, data); // 1, 2, 4, 7, f
190 m_keypad_column = data & 0x0f;
191 break;
192 case 3: /* BFF3: write disable chunky graphics */
193 LOG("bff3_w: %d <- %02x (chunky graphics off)\n", offset, data);
194 m_chunky_graphics = 0;
195 break;
196 }
197 }
198
keyboard_r()199 uint8_t mt6809_state::keyboard_r()
200 {
201 uint8_t data = m_keyboard_ascii;
202
203 m_keyboard_ascii = 0x00;
204
205 return data;
206 }
207
store_key(int key)208 void mt6809_state::store_key(int key)
209 {
210 m_keyboard_ascii = key | 0x80;
211 }
212
store_key(int key)213 void microtan_state::store_key(int key)
214 {
215 m_keyboard_ascii = key | 0x80;
216 m_irq_line->in_w<IRQ_KBD>(1);
217 }
218
TIMER_DEVICE_CALLBACK_MEMBER(microtan_state::kbd_scan)219 TIMER_DEVICE_CALLBACK_MEMBER(microtan_state::kbd_scan)
220 {
221 /* ASCII Keyboard only */
222 if (m_config->read() & 3)
223 return;
224
225 int mod, row, col, chg, newvar;
226
227 if( m_repeat )
228 {
229 if( !--m_repeat )
230 m_repeater = 4;
231 }
232 else if( m_repeater )
233 m_repeat = m_repeater;
234
235 row = 9;
236 newvar = m_io_keyboard[8]->read();
237 chg = m_keyrows[--row] ^ newvar;
238
239 while ( !chg && row > 0)
240 {
241 newvar = m_io_keyboard[row - 1]->read();
242 chg = m_keyrows[--row] ^ newvar;
243 }
244 if (!chg)
245 --row;
246
247 if (row >= 0)
248 {
249 m_repeater = 0x00;
250 m_mask = 0x00;
251 m_key = 0x00;
252 m_lastrow = row;
253 /* CapsLock LED */
254 if( row == 3 && chg == 0x80 )
255 m_led = BIT(~m_keyrows[3], 7);
256
257 if (newvar & chg) /* key(s) pressed ? */
258 {
259 mod = 0;
260
261 /* Shift modifier */
262 if ( (m_keyrows[5] & 0x10) || (m_keyrows[6] & 0x80) )
263 mod |= 1;
264
265 /* Control modifier */
266 if (m_keyrows[3] & 0x40)
267 mod |= 2;
268
269 /* CapsLock modifier */
270 if (m_keyrows[3] & 0x80)
271 mod |= 4;
272
273 /* find newvar key */
274 m_mask = 0x01;
275 for (col = 0; col < 8; col ++)
276 {
277 if (chg & m_mask)
278 {
279 newvar &= m_mask;
280 m_key = keyboard[mod][row][col];
281 break;
282 }
283 m_mask <<= 1;
284 }
285 if( m_key ) /* normal key */
286 {
287 m_repeater = 30;
288 store_key(m_key);
289 }
290 else
291 if( (row == 0) && (chg == 0x04) ) /* Ctrl-@ (NUL) */
292 store_key(0);
293 m_keyrows[row] |= newvar;
294 }
295 else
296 m_keyrows[row] = newvar;
297
298 m_repeat = m_repeater;
299 }
300 else
301 if ( m_key && (m_keyrows[m_lastrow] & m_mask) && m_repeat == 0 )
302 store_key(m_key);
303 }
304
305
pgm_chargen_w(offs_t offset,uint8_t data)306 void microtan_state::pgm_chargen_w(offs_t offset, uint8_t data)
307 {
308 switch (offset & 0x200)
309 {
310 case 0x000:
311 /* update char &80-&1F */
312 m_gfx1->base()[offset | 0x800] = data;
313 m_gfxdecode->gfx(0)->mark_dirty(0x80 | (offset >> 4));
314 break;
315 case 0x200:
316 /* update char &E0-&FF */
317 m_gfx1->base()[offset | 0xc00] = data;
318 m_gfxdecode->gfx(0)->mark_dirty(0xc0 | (offset >> 4));
319 break;
320 }
321 }
322
init_gfx2()323 void microtan_state::init_gfx2()
324 {
325 uint8_t *dst = memregion("gfx2")->base();
326
327 for (int i = 0; i < 256; i++)
328 {
329 switch (i & 3)
330 {
331 case 0: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0x00; break;
332 case 1: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0xf0; break;
333 case 2: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0x0f; break;
334 case 3: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0xff; break;
335 }
336 dst += 4;
337 switch (BIT(i, 2, 2))
338 {
339 case 0: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0x00; break;
340 case 1: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0xf0; break;
341 case 2: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0x0f; break;
342 case 3: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0xff; break;
343 }
344 dst += 4;
345 switch (BIT(i, 4, 2))
346 {
347 case 0: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0x00; break;
348 case 1: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0xf0; break;
349 case 2: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0x0f; break;
350 case 3: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0xff; break;
351 }
352 dst += 4;
353 switch (BIT(i, 6, 2))
354 {
355 case 0: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0x00; break;
356 case 1: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0xf0; break;
357 case 2: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0x0f; break;
358 case 3: dst[ 0] = dst[ 1] = dst[ 2] = dst[ 3] = 0xff; break;
359 }
360 dst += 4;
361 }
362 }
363
init_microtan()364 void microtan_state::init_microtan()
365 {
366 init_gfx2();
367
368 m_pulse_nmi_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(microtan_state::pulse_nmi), this));
369 }
370
machine_start()371 void microtan_state::machine_start()
372 {
373 m_led.resolve();
374
375 save_item(NAME(m_keypad_column));
376 save_item(NAME(m_keyboard_ascii));
377 save_item(NAME(m_keyrows));
378 save_item(NAME(m_lastrow));
379 save_item(NAME(m_mask));
380 save_item(NAME(m_key));
381 save_item(NAME(m_repeat));
382 save_item(NAME(m_repeater));
383 }
384
machine_reset()385 void microtan_state::machine_reset()
386 {
387 for (int i = 1; i < 10; i++)
388 m_keyrows[i] = m_io_keyboard[i-1].read_safe(0);
389
390 m_led = BIT(~m_keyrows[3], 7);
391 }
392
verify_snapshot(uint8_t * data,int size)393 image_verify_result microtan_state::verify_snapshot(uint8_t *data, int size)
394 {
395 if (size == 8263)
396 {
397 logerror("snapshot_id: magic size %d found\n", size);
398 return image_verify_result::PASS;
399 }
400 else
401 {
402 if (4 + data[2] + 256 * data[3] + 1 + 16 + 16 + 16 + 1 + 1 + 16 + 16 + 64 + 7 == size)
403 {
404 logerror("snapshot_id: header RAM size + structures matches filesize %d\n", size);
405 return image_verify_result::PASS;
406 }
407 }
408
409 return image_verify_result::FAIL;
410 }
411
parse_intel_hex(uint8_t * snapshot_buff,char * src)412 image_init_result microtan_state::parse_intel_hex(uint8_t *snapshot_buff, char *src)
413 {
414 char line[128];
415 int /*row = 0,*/ column = 0, last_addr = 0, last_size = 0;
416
417 while (*src)
418 {
419 if (*src == '\r' || *src == '\n')
420 {
421 if (column)
422 {
423 unsigned int size, addr, null, b[32], cs, n;
424
425 line[column] = '\0';
426 /*row++;*/
427 n = sscanf(line, ":%02x%04x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
428 &size, &addr, &null,
429 &b[ 0], &b[ 1], &b[ 2], &b[ 3], &b[ 4], &b[ 5], &b[ 6], &b[ 7],
430 &b[ 8], &b[ 9], &b[10], &b[11], &b[12], &b[13], &b[14], &b[15],
431 &b[16], &b[17], &b[18], &b[19], &b[20], &b[21], &b[22], &b[23],
432 &b[24], &b[25], &b[26], &b[27], &b[28], &b[29], &b[30], &b[31],
433 &cs);
434 if (n == 0)
435 logerror("parse_intel_hex: malformed line [%s]\n", line);
436 else
437 if (n == 1)
438 logerror("parse_intel_hex: only size found [%s]\n", line);
439 else
440 if (n == 2)
441 logerror("parse_intel_hex: only size and addr found [%s]\n", line);
442 else
443 if (n == 3)
444 logerror("parse_intel_hex: only size, addr and null found [%s]\n", line);
445 else
446 if (null != 0)
447 logerror("parse_intel_hex: warning null byte is != 0 [%s]\n", line);
448 else
449 {
450 int i, sum;
451
452 n -= 3;
453
454 sum = size + (addr & 0xff) + ((addr >> 8) & 0xff);
455 if (n != 32 + 1)
456 cs = b[n-1];
457
458 last_addr = addr;
459 last_size = n-1;
460 logerror("parse_intel_hex: %04X", addr);
461 for (i = 0; i < n-1; i++)
462 {
463 sum += b[i];
464 snapshot_buff[addr++] = b[i];
465 }
466 logerror("-%04X checksum %02X+%02X = %02X\n", addr-1, cs, sum & 0xff, (cs + sum) & 0xff);
467 }
468 }
469 column = 0;
470 }
471 else
472 line[column++] = *src;
473
474 src++;
475 }
476 /* register preset? */
477 if (last_size == 7)
478 {
479 logerror("parse_intel_hex: registers (?) at %04X\n", last_addr);
480 memcpy(&snapshot_buff[8192+64], &snapshot_buff[last_addr], last_size);
481 }
482 return image_init_result::PASS;
483 }
484
parse_zillion_hex(uint8_t * snapshot_buff,char * src)485 image_init_result microtan_state::parse_zillion_hex(uint8_t *snapshot_buff, char *src)
486 {
487 char line[128];
488 int parsing = 0, /*row = 0,*/ column = 0;
489
490 while (*src)
491 {
492 if (parsing)
493 {
494 if (*src == '}')
495 parsing = 0;
496 else
497 {
498 if (*src == '\r' || *src == '\n')
499 {
500 if (column)
501 {
502 unsigned int addr, b[8], n;
503
504 line[column] = '\0';
505 /*row++;*/
506 n = sscanf(line, "%x %x %x %x %x %x %x %x %x", &addr, &b[0], &b[1], &b[2], &b[3], &b[4], &b[5], &b[6], &b[7]);
507 if (n == 0)
508 logerror("parse_zillion_hex: malformed line [%s]\n", line);
509 else
510 if (n == 1)
511 logerror("parse_zillion_hex: only addr found [%s]\n", line);
512 else
513 {
514 logerror("parse_zillion_hex: %04X", addr);
515 for (int i = 0; i < n-1; i++)
516 snapshot_buff[addr++] = b[i];
517 logerror("-%04X\n", addr-1);
518 }
519 }
520 column = 0;
521 }
522 else
523 line[column++] = *src;
524 }
525 }
526 else
527 {
528 if (*src == '\r' || *src == '\n')
529 {
530 if (column)
531 {
532 int addr;
533
534 /*row++;*/
535 line[column] = '\0';
536 int n = sscanf(line, "G%x", (unsigned int *) &addr);
537 if (n == 1 && !snapshot_buff[8192+64+0] && !snapshot_buff[8192+64+1])
538 {
539 logerror("microtan_hexfile_init: go addr %04X\n", addr);
540 snapshot_buff[8192+64+0] = addr & 0xff;
541 snapshot_buff[8192+64+1] = (addr >> 8) & 0xff;
542 }
543 }
544 column = 0;
545 }
546 else
547 line[column++] = *src;
548
549 if (*src == '{')
550 {
551 parsing = 1;
552 column = 0;
553 }
554 }
555 src++;
556 }
557 return image_init_result::PASS;
558 }
559
set_cpu_regs(const uint8_t * snapshot_buff,int base)560 void microtan_state::set_cpu_regs(const uint8_t *snapshot_buff, int base)
561 {
562 logerror("snapshot_copy: PC:%02X%02X P:%02X A:%02X X:%02X Y:%02X SP:1%02X\n",
563 snapshot_buff[base+1], snapshot_buff[base+0], snapshot_buff[base+2], snapshot_buff[base+3],
564 snapshot_buff[base+4], snapshot_buff[base+5], snapshot_buff[base+6]);
565 m_maincpu->set_state_int(M6502_PC, snapshot_buff[base+0] + (snapshot_buff[base+1] << 8));
566 m_maincpu->set_state_int(M6502_P, snapshot_buff[base+2]);
567 m_maincpu->set_state_int(M6502_A, snapshot_buff[base+3]);
568 m_maincpu->set_state_int(M6502_X, snapshot_buff[base+4]);
569 m_maincpu->set_state_int(M6502_Y, snapshot_buff[base+5]);
570 m_maincpu->set_state_int(M6502_S, snapshot_buff[base+6] + 0x100);
571 }
572
snapshot_copy(uint8_t * snapshot_buff,int snapshot_size)573 void microtan_state::snapshot_copy(uint8_t *snapshot_buff, int snapshot_size)
574 {
575 address_space &space = m_maincpu->space(AS_PROGRAM);
576
577 /* check for .DMP file format */
578 if (snapshot_size == 8263)
579 {
580 /********** DMP format
581 * Lower 8k of RAM (0000 to 1fff)
582 * 64 bytes of chunky graphics bits (first byte bit is for character at 0200, bit 1=0201, etc)
583 * 7 bytes of CPU registers (PCL, PCH, PSW, A, IX, IY, SP)
584 */
585
586 int base = 0;
587 /* 8K of RAM from 0000 to 1fff */
588 for (int i = 0; i < 0x2000; i++)
589 space.write_byte(i, snapshot_buff[base + i]);
590
591 base += 8192;
592 /* 64 bytes of chunky graphics info */
593 for (int i = 0; i < 32*16; i++)
594 m_chunky_buffer[i] = (snapshot_buff[base+i/8] >> (i&7)) & 1;
595
596 base += 64;
597 set_cpu_regs(snapshot_buff, base);
598 }
599 else
600 {
601 /********** M65 format ************************************
602 * 2 bytes: File version
603 * 2 bytes: RAM size
604 * n bytes: RAM (0000 to RAM Size)
605 * 16 bytes: 1st 6522 (0xbfc0 to 0xbfcf)
606 * 16 bytes: 2nd 6522 (0xbfe0 to 0xbfef)
607 * 16 bytes: Microtan IO (0xbff0 to 0xbfff)
608 * 1 byte : Space Invasion sound (0xbc04)
609 * 1 byte : Chunky graphics state (0=off, 1=on)
610 * 16 bytes: 1st AY8910 registers
611 * 16 bytes: 2nd AY8910 registers
612 * 64 bytes: Chunky graphics bits (first byte bit 0 is for character at 0200, bit 1=0201, etc)
613 * 7 bytes: CPU registers (PCL, PCH, PSW, A, IX, IY, SP)
614 */
615 int ramend = snapshot_buff[2] + 256 * snapshot_buff[3];
616 if (2 + 2 + ramend + 1 + 16 + 16 + 16 + 1 + 1 + 16 + 16 + 64 + 7 != snapshot_size)
617 {
618 logerror("snapshot_copy: size %d doesn't match RAM size %d + structure size\n", snapshot_size, ramend+1);
619 return;
620 }
621
622 int base = 4;
623 for (int i = 0; i < snapshot_buff[2] + 256 * snapshot_buff[3] + 1; i++)
624 space.write_byte(i, snapshot_buff[base + i]);
625 base += ramend + 1;
626
627 /* first set of VIA6522 registers */
628 for (int i = 0; i < 16; i++ )
629 space.write_byte(0xbfc0 + i, snapshot_buff[base++]);
630
631 /* second set of VIA6522 registers */
632 for (int i = 0; i < 16; i++ )
633 space.write_byte(0xbfe0 + i, snapshot_buff[base++]);
634
635 /* microtan IO bff0-bfff */
636 for (int i = 0; i < 16; i++ )
637 {
638 if (i < 4)
639 bffx_w(i, snapshot_buff[base++]);
640 }
641
642 sound_w(snapshot_buff[base++]);
643 m_chunky_graphics = snapshot_buff[base++];
644
645 /* first set of AY8910 registers */
646 for (int i = 0; i < 16; i++ )
647 {
648 space.write_byte(0xbc00, i);
649 space.write_byte(0xbc01, snapshot_buff[base++]);
650 }
651
652 /* second set of AY8910 registers */
653 for (int i = 0; i < 16; i++ )
654 {
655 space.write_byte(0xbc02, i);
656 space.write_byte(0xbc03, snapshot_buff[base++]);
657 }
658
659 for (int i = 0; i < 32*16; i++)
660 m_chunky_buffer[i] = (snapshot_buff[base+i/8] >> (i&7)) & 1;
661
662 base += 64;
663
664 set_cpu_regs(snapshot_buff, base);
665 }
666 }
667
SNAPSHOT_LOAD_MEMBER(microtan_state::snapshot_cb)668 SNAPSHOT_LOAD_MEMBER(microtan_state::snapshot_cb)
669 {
670 uint8_t *snapshot_buff = (uint8_t*)image.ptr();
671 if (!snapshot_buff)
672 return image_init_result::FAIL;
673
674 if (verify_snapshot(snapshot_buff, snapshot_size) != image_verify_result::PASS)
675 return image_init_result::FAIL;
676
677 snapshot_copy(snapshot_buff, snapshot_size);
678 return image_init_result::PASS;
679 }
680
QUICKLOAD_LOAD_MEMBER(microtan_state::quickload_cb)681 QUICKLOAD_LOAD_MEMBER(microtan_state::quickload_cb)
682 {
683 int snapshot_size = 8263; /* magic size */
684 std::vector<uint8_t> snapshot_buff(snapshot_size, 0);
685 std::vector<char> buff(quickload_size + 1);
686 image_init_result rc;
687
688 image.fread(&buff[0], quickload_size);
689
690 buff[quickload_size] = '\0';
691
692 if (buff[0] == ':')
693 rc = parse_intel_hex(&snapshot_buff[0], &buff[0]);
694 else
695 rc = parse_zillion_hex(&snapshot_buff[0], &buff[0]);
696 if (rc == image_init_result::PASS)
697 snapshot_copy(&snapshot_buff[0], snapshot_size);
698 return rc;
699 }
700