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) : VM_TEMPLATE(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 #if defined(__GIT_REPO_VERSION)
172 strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
174 for(DEVICE* device = first_device; device; device = device->next_device) {
175 device->initialize();
178 //pcm->set_realtime_render(true);
179 for(int i = 0; i < 4; i++) {
180 fdc->set_drive_type(i, DRIVE_TYPE_2D);
186 // delete all devices
187 for(DEVICE* device = first_device; device;) {
188 DEVICE *next_device = device->next_device;
191 device = next_device;
195 DEVICE* VM::get_device(int id)
197 for(DEVICE* device = first_device; device; device = device->next_device) {
198 if(device->this_device_id == id) {
205 // ----------------------------------------------------------------------------
206 // drive virtual machine
207 // ----------------------------------------------------------------------------
212 for(DEVICE* device = first_device; device; device = device->next_device) {
222 double VM::get_frame_rate()
224 return event->get_frame_rate();
227 // ----------------------------------------------------------------------------
229 // ----------------------------------------------------------------------------
232 DEVICE *VM::get_cpu(int index)
241 // ----------------------------------------------------------------------------
243 // ----------------------------------------------------------------------------
245 void VM::draw_screen()
247 display->draw_screen();
250 // ----------------------------------------------------------------------------
252 // ----------------------------------------------------------------------------
254 void VM::initialize_sound(int rate, int samples)
256 // init sound manager
257 event->initialize_sound(rate, samples);
260 pcm->initialize_sound(rate, 4000);
263 uint16_t* VM::create_sound(int* extra_frames)
265 return event->create_sound(extra_frames);
268 int VM::get_sound_buffer_ptr()
270 return event->get_sound_buffer_ptr();
273 #ifdef USE_SOUND_VOLUME
274 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
277 pcm->set_volume(0, decibel_l, decibel_r);
279 fdc->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
280 fdc->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
281 fdc->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
286 // ----------------------------------------------------------------------------
288 // ----------------------------------------------------------------------------
290 void VM::key_down(int code, bool repeat)
292 keyboard->key_down(code);
295 void VM::key_up(int code)
297 keyboard->key_up(code);
300 // ----------------------------------------------------------------------------
302 // ----------------------------------------------------------------------------
304 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
306 fdc->open_disk(drv, file_path, bank);
309 void VM::close_floppy_disk(int drv)
311 fdc->close_disk(drv);
314 bool VM::is_floppy_disk_inserted(int drv)
316 return fdc->is_disk_inserted(drv);
319 void VM::is_floppy_disk_protected(int drv, bool value)
321 fdc->is_disk_protected(drv, value);
324 bool VM::is_floppy_disk_protected(int drv)
326 return fdc->is_disk_protected(drv);
329 uint32_t VM::is_floppy_disk_accessed()
331 return fdc->read_signal(0);
334 bool VM::is_frame_skippable()
336 return event->is_frame_skippable();
339 void VM::update_config()
341 for(DEVICE* device = first_device; device; device = device->next_device) {
342 device->update_config();
346 #define STATE_VERSION 3
348 #include "../../statesub.h"
349 #include "../../qt/gui/csp_logger.h"
350 extern CSP_Logger DLL_PREFIX_I *csp_logger;
352 void VM::decl_state(void)
354 #ifdef _COLOR_MONITOR
355 state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::QC_10_WITH_COLOR_MONITOR_HEAD")), csp_logger);
357 state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::QC_10_HEAD")), csp_logger);
359 for(DEVICE* device = first_device; device; device = device->next_device) {
360 device->decl_state();
364 void VM::save_state(FILEIO* state_fio)
366 //state_fio->FputUint32(STATE_VERSION);
368 if(state_entry != NULL) {
369 state_entry->save_state(state_fio);
371 for(DEVICE* device = first_device; device; device = device->next_device) {
372 device->save_state(state_fio);
376 bool VM::load_state(FILEIO* state_fio)
378 //if(state_fio->FgetUint32() != STATE_VERSION) {
382 if(state_entry != NULL) {
383 mb = state_entry->load_state(state_fio);
386 emu->out_debug_log("INFO: HEADER DATA ERROR");
389 for(DEVICE* device = first_device; device; device = device->next_device) {
390 if(!device->load_state(state_fio)) {
397 bool VM::process_state(FILEIO* state_fio, bool loading)
399 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
402 for(DEVICE* device = first_device; device; device = device->next_device) {
403 const char *name = typeid(*device).name() + 6; // skip "class "
404 int len = strlen(name);
406 if(!state_fio->StateCheckInt32(len)) {
409 if(!state_fio->StateCheckBuffer(name, len, 1)) {
412 if(!device->process_state(state_fio, loading)) {