2 EPSON QC-10 Emulator 'eQC-10'
4 Author : Takeda.Toshiya
11 #include "../../emu.h"
12 #include "../device.h"
16 #include "../hd146818p.h"
23 #include "../pcm1bit.h"
24 #include "../upd7220.h"
25 #include "../upd765a.h"
27 #include "../z80sio.h"
30 #include "../debugger.h"
39 // ----------------------------------------------------------------------------
41 // ----------------------------------------------------------------------------
43 VM::VM(EMU* parent_emu) : emu(parent_emu)
46 first_device = last_device = NULL;
47 dummy = new DEVICE(this, emu); // must be 1st device
48 event = new EVENT(this, emu); // must be 2nd device
49 dummy->set_device_name(_T("1st Dummy"));
51 rtc = new HD146818P(this, emu);
52 dma0 = new I8237(this, emu);
53 dma0->set_device_name(_T("8237 DMAC (FDC/GDC)"));
54 dma1 = new I8237(this, emu);
55 dma1->set_device_name(_T("8237 DMAC (User)"));
56 pit0 = new I8253(this, emu);
57 pit0->set_device_name(_T("8253 PIT (Sound/PIC)"));
58 pit1 = new I8253(this, emu);
59 pit1->set_device_name(_T("8253 PIT (Sound/SIO)"));
60 pio = new I8255(this, emu);
61 pic = new I8259(this, emu);
62 io = new IO(this, emu);
63 pcm = new PCM1BIT(this, emu);
64 gdc = new UPD7220(this, emu);
65 fdc = new UPD765A(this, emu);
66 fdc->set_context_noise_seek(new NOISE(this, emu));
67 fdc->set_context_noise_head_down(new NOISE(this, emu));
68 fdc->set_context_noise_head_up(new NOISE(this, emu));
69 cpu = new Z80(this, emu);
70 sio = new Z80SIO(this, emu); // uPD7201
72 display = new DISPLAY(this, emu);
73 floppy = new FLOPPY(this, emu);
74 keyboard = new KEYBOARD(this, emu);
75 memory = new MEMORY(this, emu);
76 mfont = new MFONT(this, emu);
78 event->set_context_cpu(cpu);
79 event->set_context_sound(pcm);
80 event->set_context_sound(fdc->get_context_noise_seek());
81 event->set_context_sound(fdc->get_context_noise_head_down());
82 event->set_context_sound(fdc->get_context_noise_head_up());
84 rtc->set_context_intr(pic, SIG_I8259_IR2 | SIG_I8259_CHIP1, 1);
85 dma0->set_context_memory(memory);
86 dma0->set_context_ch0(fdc);
87 dma0->set_context_ch1(gdc);
88 #ifdef SINGLE_MODE_DMA
89 dma0->set_context_child_dma(dma1);
91 dma1->set_context_memory(memory);
92 pit0->set_context_ch0(memory, SIG_MEMORY_PCM, 1);
93 pit0->set_context_ch1(pic, SIG_I8259_IR5 | SIG_I8259_CHIP1, 1);
94 pit0->set_context_ch2(pic, SIG_I8259_IR1 | SIG_I8259_CHIP0, 1);
95 pit0->set_constant_clock(2, CPU_CLOCKS >> 1); // 1.9968MHz
96 pit1->set_context_ch0(pcm, SIG_PCM1BIT_SIGNAL, 1);
97 pit1->set_context_ch1(pit0, SIG_I8253_CLOCK_0, 1);
98 pit1->set_context_ch1(pit0, SIG_I8253_CLOCK_1, 1);
99 pit1->set_context_ch1(sio, SIG_Z80SIO_TX_CLK_CH0, 1);
100 pit1->set_context_ch1(sio, SIG_Z80SIO_RX_CLK_CH0, 1);
101 pit1->set_context_ch2(sio, SIG_Z80SIO_TX_CLK_CH1, 1);
102 pit1->set_context_ch2(sio, SIG_Z80SIO_RX_CLK_CH1, 1);
103 pit1->set_constant_clock(0, CPU_CLOCKS >> 1); // 1.9968MHz
104 pit1->set_constant_clock(1, CPU_CLOCKS >> 1); // 1.9968MHz
105 pit1->set_constant_clock(2, CPU_CLOCKS >> 1); // 1.9968MHz
106 pio->set_context_port_c(pic, SIG_I8259_IR0 | SIG_I8259_CHIP1, 8, 0);
107 pic->set_context_cpu(cpu);
108 gdc->set_context_drq(dma0, SIG_I8237_CH1, 1);
109 gdc->set_vram_ptr(display->get_vram(), VRAM_SIZE);
110 // IR5 of I8259 #0 is from light pen
111 fdc->set_context_irq(pic, SIG_I8259_IR6 | SIG_I8259_CHIP0, 1);
112 fdc->set_context_irq(memory, SIG_MEMORY_FDC_IRQ, 1);
113 fdc->set_context_drq(dma0, SIG_I8237_CH0, 1);
114 sio->set_context_intr(pic, SIG_I8259_IR4 | SIG_I8259_CHIP0);
115 sio->set_context_send(0, keyboard, SIG_KEYBOARD_RECV);
116 // sio->set_tx_clock(0, 1200 * 16); // 1200 baud for keyboard
117 // sio->set_rx_clock(0, 1200 * 16); // clock is from 8253 ch1 (1.9968MHz/104)
118 // sio->set_tx_clock(1, 9600 * 16); // 9600 baud for RS-232C
119 // sio->set_rx_clock(1, 9600 * 16); // clock is from 8253 ch2 (1.9968MHz/13)
121 display->set_context_gdc(gdc);
122 display->set_sync_ptr(gdc->get_sync());
123 display->set_zoom_ptr(gdc->get_zoom());
124 display->set_ra_ptr(gdc->get_ra());
125 display->set_cs_ptr(gdc->get_cs());
126 display->set_ead_ptr(gdc->get_ead());
127 floppy->set_context_fdc(fdc);
128 floppy->set_context_mem(memory);
129 keyboard->set_context_sio(sio);
130 memory->set_context_pit(pit0);
131 memory->set_context_pcm(pcm);
132 memory->set_context_fdc(fdc);
133 mfont->set_context_pic(pic);
136 cpu->set_context_mem(memory);
137 cpu->set_context_io(io);
138 cpu->set_context_intr(pic);
139 #ifdef SINGLE_MODE_DMA
140 cpu->set_context_dma(dma0);
143 cpu->set_context_debugger(new DEBUGGER(this, emu));
147 io->set_iomap_range_rw(0x00, 0x03, pit0);
148 io->set_iomap_range_rw(0x04, 0x07, pit1);
149 io->set_iomap_alias_rw(0x08, pic, I8259_ADDR_CHIP0 | 0);
150 io->set_iomap_alias_rw(0x09, pic, I8259_ADDR_CHIP0 | 1);
151 io->set_iomap_alias_rw(0x0c, pic, I8259_ADDR_CHIP1 | 0);
152 io->set_iomap_alias_rw(0x0d, pic, I8259_ADDR_CHIP1 | 1);
153 io->set_iomap_alias_rw(0x10, sio, 0);
154 io->set_iomap_alias_rw(0x11, sio, 2);
155 io->set_iomap_alias_rw(0x12, sio, 1);
156 io->set_iomap_alias_rw(0x13, sio, 3);
157 io->set_iomap_range_rw(0x14, 0x17, pio);
158 io->set_iomap_range_rw(0x18, 0x1b, memory);
159 io->set_iomap_range_w(0x1c, 0x23, memory);
160 io->set_iomap_range_rw(0x2c, 0x2d, display);
161 io->set_iomap_range_r(0x30, 0x33, memory);
162 io->set_iomap_range_w(0x30, 0x33, floppy);
163 io->set_iomap_range_rw(0x34, 0x35, fdc);
164 io->set_iomap_range_rw(0x38, 0x3b, gdc);
165 io->set_iomap_range_rw(0x3c, 0x3d, rtc);
166 io->set_iomap_range_rw(0x40, 0x4f, dma0);
167 io->set_iomap_range_rw(0x50, 0x5f, dma1);
168 io->set_iomap_range_rw(0xfc, 0xfd, mfont);
170 // initialize all devices
171 for(DEVICE* device = first_device; device; device = device->next_device) {
172 device->initialize();
174 //pcm->set_realtime_render(true);
175 for(int i = 0; i < 4; i++) {
176 fdc->set_drive_type(i, DRIVE_TYPE_2D);
182 // delete all devices
183 for(DEVICE* device = first_device; device;) {
184 DEVICE *next_device = device->next_device;
187 device = next_device;
191 DEVICE* VM::get_device(int id)
193 for(DEVICE* device = first_device; device; device = device->next_device) {
194 if(device->this_device_id == id) {
201 // ----------------------------------------------------------------------------
202 // drive virtual machine
203 // ----------------------------------------------------------------------------
208 for(DEVICE* device = first_device; device; device = device->next_device) {
218 double VM::get_frame_rate()
220 return event->get_frame_rate();
223 // ----------------------------------------------------------------------------
225 // ----------------------------------------------------------------------------
228 DEVICE *VM::get_cpu(int index)
237 // ----------------------------------------------------------------------------
239 // ----------------------------------------------------------------------------
241 void VM::draw_screen()
243 display->draw_screen();
246 // ----------------------------------------------------------------------------
248 // ----------------------------------------------------------------------------
250 void VM::initialize_sound(int rate, int samples)
252 // init sound manager
253 event->initialize_sound(rate, samples);
256 pcm->initialize_sound(rate, 4000);
259 uint16_t* VM::create_sound(int* extra_frames)
261 return event->create_sound(extra_frames);
264 int VM::get_sound_buffer_ptr()
266 return event->get_sound_buffer_ptr();
269 #ifdef USE_SOUND_VOLUME
270 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
273 pcm->set_volume(0, decibel_l, decibel_r);
275 fdc->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
276 fdc->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
277 fdc->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
282 // ----------------------------------------------------------------------------
284 // ----------------------------------------------------------------------------
286 void VM::key_down(int code, bool repeat)
288 keyboard->key_down(code);
291 void VM::key_up(int code)
293 keyboard->key_up(code);
296 // ----------------------------------------------------------------------------
298 // ----------------------------------------------------------------------------
300 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
302 fdc->open_disk(drv, file_path, bank);
305 void VM::close_floppy_disk(int drv)
307 fdc->close_disk(drv);
310 bool VM::is_floppy_disk_inserted(int drv)
312 return fdc->is_disk_inserted(drv);
315 void VM::is_floppy_disk_protected(int drv, bool value)
317 fdc->is_disk_protected(drv, value);
320 bool VM::is_floppy_disk_protected(int drv)
322 return fdc->is_disk_protected(drv);
325 uint32_t VM::is_floppy_disk_accessed()
327 return fdc->read_signal(0);
330 bool VM::is_frame_skippable()
332 return event->is_frame_skippable();
335 void VM::update_config()
337 for(DEVICE* device = first_device; device; device = device->next_device) {
338 device->update_config();
342 #define STATE_VERSION 3
344 void VM::save_state(FILEIO* state_fio)
346 state_fio->FputUint32(STATE_VERSION);
348 for(DEVICE* device = first_device; device; device = device->next_device) {
349 const char *name = typeid(*device).name() + 6; // skip "class "
351 state_fio->FputInt32(strlen(name));
352 state_fio->Fwrite(name, strlen(name), 1);
353 device->save_state(state_fio);
357 bool VM::load_state(FILEIO* state_fio)
359 if(state_fio->FgetUint32() != STATE_VERSION) {
362 for(DEVICE* device = first_device; device; device = device->next_device) {
363 const char *name = typeid(*device).name() + 6; // skip "class "
365 if(!(state_fio->FgetInt32() == strlen(name) && state_fio->Fcompare(name, strlen(name)))) {
368 if(!device->load_state(state_fio)) {