OSDN Git Service

[VM][UI][Qt] General : Merge upstream 2015-08-01.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mz700 / mz700.cpp
1 /*
2         SHARP MZ-700 Emulator 'EmuZ-700'
3         SHARP MZ-800 Emulator 'EmuZ-800'
4         SHARP MZ-1500 Emulator 'EmuZ-1500'
5
6         Author : Takeda.Toshiya
7         Date   : 2008.06.05 -
8
9         [ virtual machine ]
10 */
11
12 #include "mz700.h"
13 #include "../../emu.h"
14 #include "../device.h"
15 #include "../event.h"
16
17 #include "../and.h"
18 #include "../datarec.h"
19 #include "../i8253.h"
20 #include "../i8255.h"
21 #include "../io.h"
22 #include "../pcm1bit.h"
23 #include "../z80.h"
24
25 #ifdef USE_DEBUGGER
26 #include "../debugger.h"
27 #endif
28
29 //#include "cmos.h"
30 #include "emm.h"
31 #include "kanji.h"
32 #include "keyboard.h"
33 #include "memory.h"
34 #include "ramfile.h"
35
36 #if defined(_MZ800) || defined(_MZ1500)
37 #include "../disk.h"
38 #include "../mb8877.h"
39 #if defined(_MZ800)
40 #include "../not.h"
41 #endif
42 #include "../sn76489an.h"
43 #include "../z80pio.h"
44 #include "../z80sio.h"
45 #include "floppy.h"
46 #if defined(_MZ1500)
47 #include "psg.h"
48 #endif
49 #include "quickdisk.h"
50 #endif
51
52 // ----------------------------------------------------------------------------
53 // initialize
54 // ----------------------------------------------------------------------------
55
56 VM::VM(EMU* parent_emu) : emu(parent_emu)
57 {
58 #if defined(_MZ800)
59         boot_mode = config.boot_mode;
60 #endif
61         
62         // create devices
63         first_device = last_device = NULL;
64         dummy = new DEVICE(this, emu);  // must be 1st device
65         event = new EVENT(this, emu);   // must be 2nd device
66         
67         and_int = new AND(this, emu);
68         drec = new DATAREC(this, emu);
69         pit = new I8253(this, emu);
70         pio = new I8255(this, emu);
71         io = new IO(this, emu);
72         pcm = new PCM1BIT(this, emu);
73         cpu = new Z80(this, emu);
74         
75 //      cmos = new CMOS(this, emu);
76         emm = new EMM(this, emu);
77         kanji = new KANJI(this, emu);
78         keyboard = new KEYBOARD(this, emu);
79         memory = new MEMORY(this, emu);
80         ramfile = new RAMFILE(this, emu);
81         
82 #if defined(_MZ800) || defined(_MZ1500)
83         and_snd = new AND(this, emu);
84         fdc = new MB8877(this, emu);    // mb8876
85 #if defined(_MZ800)
86         not_pit = new NOT(this, emu);
87         psg = new SN76489AN(this, emu);
88 #elif defined(_MZ1500)
89         psg_l = new SN76489AN(this, emu);
90         psg_r = new SN76489AN(this, emu);
91 #endif
92         pio_int = new Z80PIO(this, emu);
93         sio_rs = new Z80SIO(this, emu);
94         sio_qd = new Z80SIO(this, emu);
95         
96         floppy = new FLOPPY(this, emu);
97 #if defined(_MZ1500)
98         psg = new PSG(this, emu);
99 #endif
100         qd = new QUICKDISK(this, emu);
101 #endif
102         event->set_context_sound(drec);
103         
104         // set contexts
105         event->set_context_cpu(cpu);
106         event->set_context_sound(pcm);
107 #if defined(_MZ800)
108         event->set_context_sound(psg);
109 #elif defined(_MZ1500)
110         event->set_context_sound(psg_l);
111         event->set_context_sound(psg_r);
112 #endif
113 #if defined(DATAREC_SOUND)
114         event->set_context_sound(drec);
115 #endif
116         // VRAM/PCG wait
117         memory->set_context_cpu(cpu);
118         
119         // memory mapped I/O
120         memory->set_context_pio(pio);
121         memory->set_context_pit(pit);
122         
123 #if defined(_MZ1500)
124         // psg mixer
125         psg->set_context_psg_l(psg_l);
126         psg->set_context_psg_r(psg_r);
127 #endif
128         
129 #if defined(_MZ800)
130         // 8253:CLK#0 <- 1.10MHz
131         pit->set_constant_clock(0, 1100000);
132 #else
133         // 8253:CLK#0 <- 895KHz
134         pit->set_constant_clock(0, CPU_CLOCKS / 4);
135 #endif
136         
137 #if defined(_MZ800) || defined(_MZ1500)
138         // 8253:OUT#0 AND 8255:PC0 -> SPEAKER
139         pit->set_context_ch0(and_snd, SIG_AND_BIT_0, 1);
140         pio->set_context_port_c(and_snd, SIG_AND_BIT_1, 1, 0);
141         and_snd->set_context_out(pcm, SIG_PCM1BIT_SIGNAL, 1);
142         and_snd->set_mask(SIG_AND_BIT_0 | SIG_AND_BIT_1);
143 #else
144         // 8253:OUT#0 -> SPEAKER
145         pit->set_context_ch0(pcm, SIG_PCM1BIT_SIGNAL, 1);
146 #endif
147 #if defined(_MZ800)
148         // 8253:OUT#0 -> NOT -> Z80PIO:PA4
149         pit->set_context_ch0(not_pit, SIG_NOT_INPUT, 1);
150         not_pit->set_context_out(pio_int, SIG_Z80PIO_PORT_A, 0x10);
151 #elif defined(_MZ1500)
152         // 8253:OUT#0 -> Z80PIO:PA4
153         pit->set_context_ch0(pio_int, SIG_Z80PIO_PORT_A, 0x10);
154 #endif
155         
156         // 8253:CLK#1 <- 15.7KHz
157         pit->set_constant_clock(1, CPU_CLOCKS / 228);
158         
159         // 8253:OUT#1 -> 8253:CLK#2
160         pit->set_context_ch1(pit, SIG_I8253_CLOCK_2, 1);
161         
162         // 8253:OUT#2 (N)AND 8255:PC2 -> Z80:INT
163         pit->set_context_ch2(and_int, SIG_AND_BIT_0, 1);
164         pio->set_context_port_c(and_int, SIG_AND_BIT_1, 4, 0);
165         and_int->set_context_out(cpu, SIG_CPU_IRQ, 1);
166         and_int->set_mask(SIG_AND_BIT_0 | SIG_AND_BIT_1);
167         
168 #if defined(_MZ1500)
169         // 8253:OUT#2 -> Z80PIO:PA5
170         pit->set_context_ch2(pio_int, SIG_Z80PIO_PORT_A, 0x20);
171 #endif
172         
173         // 8255:PA0-3 -> KEYBOARD:STROBE
174         pio->set_context_port_a(keyboard, SIG_KEYBOARD_COLUMN, 0x0f, 0);
175 #if defined(_MZ800)
176         // 8255:PA4 -> JOYSTICK #1
177         // 8255:PA5 -> JOYSTICK #2
178 #endif
179         // 8255:PA7 -> 556 RESET
180         
181         // 8255:PB0-7 <- KEYBOARD:DATA
182         keyboard->set_context_pio(pio);
183         
184         // 8255:PC0 -> AND -> SPEAKER
185         // 8255:PC1 -> DATA RECORDER:WRITE DATA
186         pio->set_context_port_c(drec, SIG_DATAREC_OUT, 0x02, 0);
187         // 8255:PC2 -> (N)AND -> Z80:INT
188         // 8255:PC3 -> DATA RECORDER:MOTOR ON/OFF
189         pio->set_context_port_c(drec, SIG_DATAREC_TRIG, 0x08, 0);
190         // 8255:PC4 <- DATA RECORDER:MOTOR REMOTE
191         drec->set_context_remote(pio, SIG_I8255_PORT_C, 0x10);
192         // 8255:PC5 <- DATA RECORDER:READ DATA
193         drec->set_context_out(pio, SIG_I8255_PORT_C, 0x20);
194         // 8255:PC6 <- MEMORY:556 OUT (1.5KHz)
195         // 8255:PC7 <- MEMORY:VBLANK
196         
197 #if defined(_MZ800) || defined(_MZ1500)
198         // Z80PIO:PA0 <- PRINTER:RDA
199         // Z80PIO:PA1 <- PRINTER:STA
200         // Z80PIO:PA2 <- GND
201         // Z80PIO:PA3 <- GND
202 #if defined(_MZ800)
203         // Z80PIO:PA4 <- NOT <- 8253:OUT#0
204         // Z80PIO:PA5 <- HBLANK
205         memory->set_context_pio_int(pio_int);
206 #elif defined(_MZ1500)
207         // Z80PIO:PA4 <- 8253:OUT#0
208         // Z80PIO:PA5 <- 8253:OUT#2
209 #endif
210         // Z80PIO:PA6 -> PRINTER:IRT
211         // Z80PIO:PA7 -> PRINTER:RDP
212 #endif
213         
214 #if defined(_MZ800) || defined(_MZ1500)
215         // Z80SIO:RTSA -> QD:WRGA
216         sio_qd->set_context_rts(0, qd, QUICKDISK_SIO_RTSA, 1);
217         // Z80SIO:DTRB -> QD:MTON
218         sio_qd->set_context_dtr(1, qd, QUICKDISK_SIO_DTRB, 1);
219         // Z80SIO:SENDA -> QD:RECV
220         sio_qd->set_context_sync(0, qd, QUICKDISK_SIO_SYNC, 1);
221         sio_qd->set_context_rxdone(0, qd, QUICKDISK_SIO_RXDONE, 1);
222         sio_qd->set_context_send(0, qd, QUICKDISK_SIO_DATA);
223         sio_qd->set_context_break(0, qd, QUICKDISK_SIO_BREAK, 1);
224         // Z80SIO:CTSA <- QD:PROTECT
225         // Z80SIO:DCDA <- QD:INSERT
226         // Z80SIO:DCDB <- QD:HOE
227         qd->set_context_sio(sio_qd);
228         
229         sio_rs->set_tx_clock(0, 1200 * 16);     // 1200 baud
230         sio_rs->set_rx_clock(0, 1200 * 16);     // baud-rate can be changed by jumper pin
231         sio_rs->set_tx_clock(1, 1200 * 16);
232         sio_rs->set_rx_clock(1, 1200 * 16);
233         
234         sio_qd->set_tx_clock(0, 101562.5);
235         sio_qd->set_rx_clock(0, 101562.5);
236         sio_qd->set_tx_clock(1, 101562.5);
237         sio_qd->set_rx_clock(1, 101562.5);
238         
239         // floppy drives
240         floppy->set_context_cpu(cpu);
241         floppy->set_context_fdc(fdc);
242         fdc->set_context_drq(floppy, SIG_FLOPPY_DRQ, 1);
243 #endif
244         
245         // cpu bus
246         cpu->set_context_mem(memory);
247         cpu->set_context_io(io);
248 #if defined(_MZ800) || defined(_MZ1500)
249         cpu->set_context_intr(pio_int);
250         // z80 family daisy chain
251         // 0=8253:OUT2
252         pio_int->set_context_intr(cpu, 1);
253         pio_int->set_context_child(sio_rs);
254         sio_rs->set_context_intr(cpu, 2);
255         sio_rs->set_context_child(sio_qd);
256         sio_qd->set_context_intr(cpu, 3);
257 #else
258         cpu->set_context_intr(dummy);
259 #endif
260 #ifdef USE_DEBUGGER
261         cpu->set_context_debugger(new DEBUGGER(this, emu));
262 #endif
263         
264         // emm
265         io->set_iomap_range_rw(0x00, 0x03, emm);
266         // kanji
267         io->set_iomap_range_rw(0xb8, 0xb9, kanji);
268         // ramfile
269         io->set_iomap_range_rw(0xea, 0xeb, ramfile);
270         // cmos
271 //      io->set_iomap_range_rw(0xf8, 0xfa, cmos);
272         
273 #if defined(_MZ800)
274         // 8255/8253
275         io->set_iomap_range_rw(0xd0, 0xd3, pio);
276         io->set_iomap_range_rw(0xd4, 0xd7, pit);
277 #endif
278         
279 #if defined(_MZ800) || defined(_MZ1500)
280         // floppy drives
281         io->set_iomap_range_rw(0xd8, 0xdb, fdc);
282         io->set_iomap_range_w(0xdc, 0xdf, floppy);
283 #endif
284         
285         // memory mapper
286 #if defined(_MZ800)
287         io->set_iomap_range_r(0xe0, 0xe1, memory);
288         io->set_iomap_range_w(0xe0, 0xe6, memory);
289 #elif defined(_MZ1500)
290         io->set_iomap_range_w(0xe0, 0xe6, memory);
291 #else
292         io->set_iomap_range_w(0xe0, 0xe4, memory);
293 #endif
294         
295 #if defined(_MZ800)
296         // crtc
297         io->set_iomap_range_w(0xcc, 0xcf, memory);
298         io->set_iomap_single_r(0xce, memory);
299         // palette
300         io->set_iomap_single_w(0xf0, memory);
301 #elif defined(_MZ1500)
302         // palette
303         io->set_iomap_range_w(0xf0, 0xf1, memory);
304 #endif
305         
306 #if defined(_MZ800)
307         // joystick
308 //      io->set_iomap_range_r(0xf0, 0xf1, joystick);
309 #endif
310         
311         // psg
312 #if defined(_MZ800)
313         io->set_iomap_single_w(0xf2, psg);
314 #elif defined(_MZ1500)
315         io->set_iomap_single_w(0xe9, psg);
316         io->set_iomap_single_w(0xf2, psg_l);
317         io->set_iomap_single_w(0xf3, psg_r);
318 #endif
319         
320 #if defined(_MZ800) || defined(_MZ1500)
321         // z80pio/sio
322         // z80pio and z80sio*2
323         static const int z80_sio_addr[4] = {0, 2, 1, 3};
324         static const int z80_pio_addr[4] = {1, 3, 0, 2};
325         for(int i = 0; i < 4; i++) {
326                 io->set_iomap_alias_rw(0xb0 + i, sio_rs, z80_sio_addr[i]);
327                 io->set_iomap_alias_rw(0xf4 + i, sio_qd, z80_sio_addr[i]);
328                 io->set_iomap_alias_rw(0xfc + i, pio_int, z80_pio_addr[i]);
329         }
330 #else
331         // printer
332         io->set_iovalue_single_r(0xfe, 0xc0);
333 #endif
334
335         // initialize all devices
336         for(DEVICE* device = first_device; device; device = device->next_device) {
337                 device->initialize();
338         }
339 #if defined(_MZ800) || defined(_MZ1500)
340         for(int i = 0; i < MAX_DRIVE; i++) {
341                 fdc->set_drive_type(i, DRIVE_TYPE_2DD);
342         }
343 #endif
344 }
345
346 VM::~VM()
347 {
348         // delete all devices
349         for(DEVICE* device = first_device; device;) {
350                 DEVICE *next_device = device->next_device;
351                 device->release();
352                 delete device;
353                 device = next_device;
354         }
355 }
356
357 DEVICE* VM::get_device(int id)
358 {
359         for(DEVICE* device = first_device; device; device = device->next_device) {
360                 if(device->this_device_id == id) {
361                         return device;
362                 }
363         }
364         return NULL;
365 }
366
367 // ----------------------------------------------------------------------------
368 // drive virtual machine
369 // ----------------------------------------------------------------------------
370
371 void VM::reset()
372 {
373         // reset all devices
374         for(DEVICE* device = first_device; device; device = device->next_device) {
375                 device->reset();
376         }
377         and_int->write_signal(SIG_AND_BIT_0, 0, 1);     // CLOCK = L
378         and_int->write_signal(SIG_AND_BIT_1, 1, 1);     // INTMASK = H
379 #if defined(_MZ800) || defined(_MZ1500)
380         and_snd->write_signal(SIG_AND_BIT_1, 1, 1);     // SNDMASK = H
381 #endif
382 }
383
384 void VM::run()
385 {
386         event->drive();
387 }
388
389 // ----------------------------------------------------------------------------
390 // debugger
391 // ----------------------------------------------------------------------------
392
393 #ifdef USE_DEBUGGER
394 DEVICE *VM::get_cpu(int index)
395 {
396         if(index == 0) {
397                 return cpu;
398         }
399         return NULL;
400 }
401 #endif
402
403 // ----------------------------------------------------------------------------
404 // draw screen
405 // ----------------------------------------------------------------------------
406
407 void VM::draw_screen()
408 {
409         memory->draw_screen();
410 }
411
412 #if defined(_MZ800) || defined(_MZ1500)
413 int VM::access_lamp()
414 {
415   uint32 status = fdc->read_signal(0) | qd->read_signal(0); // 4 + 1: Nagative
416   return (status & (1 | 4)) ? 1 : (status & (2 | 8)) ? 2 : 0;
417 }
418 #endif
419
420 // ----------------------------------------------------------------------------
421 // soud manager
422 // ----------------------------------------------------------------------------
423
424 void VM::initialize_sound(int rate, int samples)
425 {
426         // init sound manager
427         event->initialize_sound(rate, samples);
428         
429         // init sound gen
430         pcm->init(rate, 8000);
431 #if defined(_MZ800)
432         psg->init(rate, 3579545, 8000);
433 #elif defined(_MZ1500)
434         psg_l->init(rate, 3579545, 8000);
435         psg_r->init(rate, 3579545, 8000);
436 #endif
437 }
438
439 uint16* VM::create_sound(int* extra_frames)
440 {
441         return event->create_sound(extra_frames);
442 }
443
444 int VM::sound_buffer_ptr()
445 {
446         return event->sound_buffer_ptr();
447 }
448
449 // ----------------------------------------------------------------------------
450 // user interface
451 // ----------------------------------------------------------------------------
452
453 void VM::play_tape(_TCHAR* file_path)
454 {
455         drec->play_tape(file_path);
456         drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);
457 }
458
459 void VM::rec_tape(_TCHAR* file_path)
460 {
461         drec->rec_tape(file_path);
462         drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);
463 }
464
465 void VM::close_tape()
466 {
467         drec->close_tape();
468         drec->write_signal(SIG_DATAREC_REMOTE, 0, 0);
469 }
470
471 bool VM::tape_inserted()
472 {
473         return drec->tape_inserted();
474 }
475
476 #if defined(USE_TAPE_PTR)
477 int VM::get_tape_ptr()
478 {
479         return drec->get_tape_ptr();
480 }
481 #endif
482
483 void VM::push_play()
484 {
485         drec->set_ff_rew(0);
486         drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);
487 }
488
489 void VM::push_stop()
490 {
491         drec->write_signal(SIG_DATAREC_REMOTE, 0, 1);
492 }
493
494 void VM::push_fast_forward()
495 {
496         drec->set_ff_rew(1);
497         drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);
498 }
499
500 void VM::push_fast_rewind()
501 {
502         drec->set_ff_rew(-1);
503         drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);
504 }
505
506 bool VM::get_tape_play(void)
507 {
508         return drec->get_tape_play();
509 }
510
511 #if defined(_MZ800) || defined(_MZ1500)
512 void VM::open_quickdisk(int drv, _TCHAR* file_path)
513 {
514         if(drv == 0) {
515                 qd->open_disk(file_path);
516         }
517 }
518
519 void VM::close_quickdisk(int drv)
520 {
521         if(drv == 0) {
522                 qd->close_disk();
523         }
524 }
525
526 bool VM::quickdisk_inserted(int drv)
527 {
528         if(drv == 0) {
529                 return qd->disk_inserted();
530         } else {
531                 return false;
532         }
533 }
534
535 void VM::open_disk(int drv, _TCHAR* file_path, int bank)
536 {
537         fdc->open_disk(drv, file_path, bank);
538 }
539
540 void VM::close_disk(int drv)
541 {
542         fdc->close_disk(drv);
543 }
544
545 bool VM::disk_inserted(int drv)
546 {
547         return fdc->disk_inserted(drv);
548 }
549
550 void VM::set_disk_protected(int drv, bool value)
551 {
552         fdc->set_disk_protected(drv, value);
553 }
554
555 bool VM::get_disk_protected(int drv)
556 {
557         return fdc->get_disk_protected(drv);
558 }
559 #endif
560
561 bool VM::now_skip()
562 {
563         return event->now_skip();
564 }
565
566 void VM::update_config()
567 {
568 #if defined(_MZ800)
569         if(boot_mode != config.boot_mode) {
570                 // boot mode is changed !!!
571                 boot_mode = config.boot_mode;
572                 reset();
573         } else {
574 #endif
575                 for(DEVICE* device = first_device; device; device = device->next_device) {
576                         device->update_config();
577                 }
578 #if defined(_MZ800)
579         }
580 #endif
581 }
582
583 #define STATE_VERSION   1
584
585 void VM::save_state(FILEIO* state_fio)
586 {
587         state_fio->FputUint32(STATE_VERSION);
588         
589         for(DEVICE* device = first_device; device; device = device->next_device) {
590                 device->save_state(state_fio);
591         }
592 #if defined(_MZ800)
593         state_fio->FputInt32(boot_mode);
594 #endif
595 }
596
597 bool VM::load_state(FILEIO* state_fio)
598 {
599         if(state_fio->FgetUint32() != STATE_VERSION) {
600                 return false;
601         }
602         for(DEVICE* device = first_device; device; device = device->next_device) {
603                 if(!device->load_state(state_fio)) {
604                         return false;
605                 }
606         }
607 #if defined(_MZ800)
608         boot_mode = state_fio->FgetInt32();
609 #endif
610         return true;
611 }
612