2 EPSON QC-10 Emulator 'eQC-10'
4 Author : Takeda.Toshiya
11 #include "../../emu.h"
12 #include "../device.h"
16 #include "../hd146818p.h"
22 #include "../pcm1bit.h"
23 #include "../upd7220.h"
24 #include "../upd765a.h"
26 #include "../z80sio.h"
29 #include "../debugger.h"
38 #include "../../fileio.h"
40 // ----------------------------------------------------------------------------
42 // ----------------------------------------------------------------------------
44 VM::VM(EMU* parent_emu) : emu(parent_emu)
47 first_device = last_device = NULL;
48 dummy = new DEVICE(this, emu); // must be 1st device
49 event = new EVENT(this, emu); // must be 2nd device
51 rtc = new HD146818P(this, emu);
52 dma0 = new I8237(this, emu);
53 dma1 = new I8237(this, emu);
54 pit0 = new I8253(this, emu);
55 pit1 = new I8253(this, emu);
56 pio = new I8255(this, emu);
57 pic = new I8259(this, emu);
58 io = new IO(this, emu);
59 pcm = new PCM1BIT(this, emu);
60 gdc = new UPD7220(this, emu);
61 fdc = new UPD765A(this, emu);
62 cpu = new Z80(this, emu);
63 sio = new Z80SIO(this, emu); // uPD7201
65 display = new DISPLAY(this, emu);
66 floppy = new FLOPPY(this, emu);
67 keyboard = new KEYBOARD(this, emu);
68 memory = new MEMORY(this, emu);
69 mfont = new MFONT(this, emu);
72 event->set_context_cpu(cpu);
73 event->set_context_sound(pcm);
75 rtc->set_context_intr(pic, SIG_I8259_IR2 | SIG_I8259_CHIP1, 1);
76 dma0->set_context_memory(memory);
77 dma0->set_context_ch0(fdc);
78 dma0->set_context_ch1(gdc);
79 #ifdef SINGLE_MODE_DMA
80 dma0->set_context_child_dma(dma1);
82 dma1->set_context_memory(memory);
83 pit0->set_context_ch0(memory, SIG_MEMORY_PCM, 1);
84 pit0->set_context_ch1(pic, SIG_I8259_IR5 | SIG_I8259_CHIP1, 1);
85 pit0->set_context_ch2(pic, SIG_I8259_IR1 | SIG_I8259_CHIP0, 1);
86 pit0->set_constant_clock(2, CPU_CLOCKS >> 1); // 1.9968MHz
87 pit1->set_context_ch0(pcm, SIG_PCM1BIT_SIGNAL, 1);
88 pit1->set_context_ch1(pit0, SIG_I8253_CLOCK_0, 1);
89 pit1->set_context_ch1(pit0, SIG_I8253_CLOCK_1, 1);
90 pit1->set_context_ch1(sio, SIG_Z80SIO_TX_CLK_CH0, 1);
91 pit1->set_context_ch1(sio, SIG_Z80SIO_RX_CLK_CH0, 1);
92 pit1->set_context_ch2(sio, SIG_Z80SIO_TX_CLK_CH1, 1);
93 pit1->set_context_ch2(sio, SIG_Z80SIO_RX_CLK_CH1, 1);
94 pit1->set_constant_clock(0, CPU_CLOCKS >> 1); // 1.9968MHz
95 pit1->set_constant_clock(1, CPU_CLOCKS >> 1); // 1.9968MHz
96 pit1->set_constant_clock(2, CPU_CLOCKS >> 1); // 1.9968MHz
97 pio->set_context_port_c(pic, SIG_I8259_IR0 | SIG_I8259_CHIP1, 8, 0);
98 pic->set_context_cpu(cpu);
99 gdc->set_context_drq(dma0, SIG_I8237_CH1, 1);
100 gdc->set_vram_ptr(display->get_vram(), VRAM_SIZE);
101 // IR5 of I8259 #0 is from light pen
102 fdc->set_context_irq(pic, SIG_I8259_IR6 | SIG_I8259_CHIP0, 1);
103 fdc->set_context_irq(memory, SIG_MEMORY_FDC_IRQ, 1);
104 fdc->set_context_drq(dma0, SIG_I8237_CH0, 1);
105 sio->set_context_intr(pic, SIG_I8259_IR4 | SIG_I8259_CHIP0);
106 sio->set_context_send(0, keyboard, SIG_KEYBOARD_RECV);
107 // sio->set_tx_clock(0, 1200 * 16); // 1200 baud for keyboard
108 // sio->set_rx_clock(0, 1200 * 16); // clock is from 8253 ch1 (1.9968MHz/104)
109 // sio->set_tx_clock(1, 9600 * 16); // 9600 baud for RS-232C
110 // sio->set_rx_clock(1, 9600 * 16); // clock is from 8253 ch2 (1.9968MHz/13)
112 display->set_context_gdc(gdc);
113 display->set_sync_ptr(gdc->get_sync());
114 display->set_zoom_ptr(gdc->get_zoom());
115 display->set_ra_ptr(gdc->get_ra());
116 display->set_cs_ptr(gdc->get_cs());
117 display->set_ead_ptr(gdc->get_ead());
118 floppy->set_context_fdc(fdc);
119 floppy->set_context_mem(memory);
120 keyboard->set_context_sio(sio);
121 memory->set_context_pit(pit0);
122 memory->set_context_pcm(pcm);
123 memory->set_context_fdc(fdc);
124 mfont->set_context_pic(pic);
127 cpu->set_context_mem(memory);
128 cpu->set_context_io(io);
129 cpu->set_context_intr(pic);
130 #ifdef SINGLE_MODE_DMA
131 cpu->set_context_dma(dma0);
134 cpu->set_context_debugger(new DEBUGGER(this, emu));
138 io->set_iomap_range_rw(0x00, 0x03, pit0);
139 io->set_iomap_range_rw(0x04, 0x07, pit1);
140 io->set_iomap_alias_rw(0x08, pic, I8259_ADDR_CHIP0 | 0);
141 io->set_iomap_alias_rw(0x09, pic, I8259_ADDR_CHIP0 | 1);
142 io->set_iomap_alias_rw(0x0c, pic, I8259_ADDR_CHIP1 | 0);
143 io->set_iomap_alias_rw(0x0d, pic, I8259_ADDR_CHIP1 | 1);
144 io->set_iomap_alias_rw(0x10, sio, 0);
145 io->set_iomap_alias_rw(0x11, sio, 2);
146 io->set_iomap_alias_rw(0x12, sio, 1);
147 io->set_iomap_alias_rw(0x13, sio, 3);
148 io->set_iomap_range_rw(0x14, 0x17, pio);
149 io->set_iomap_range_rw(0x18, 0x1b, memory);
150 io->set_iomap_range_w(0x1c, 0x23, memory);
151 io->set_iomap_range_rw(0x2c, 0x2d, display);
152 io->set_iomap_range_r(0x30, 0x33, memory);
153 io->set_iomap_range_w(0x30, 0x33, floppy);
154 io->set_iomap_range_rw(0x34, 0x35, fdc);
155 io->set_iomap_range_rw(0x38, 0x3b, gdc);
156 io->set_iomap_range_rw(0x3c, 0x3d, rtc);
157 io->set_iomap_range_rw(0x40, 0x4f, dma0);
158 io->set_iomap_range_rw(0x50, 0x5f, dma1);
159 io->set_iomap_range_rw(0xfc, 0xfd, mfont);
161 // initialize all devices
162 for(DEVICE* device = first_device; device; device = device->next_device) {
163 device->initialize();
165 for(int i = 0; i < 4; i++) {
166 fdc->set_drive_type(i, DRIVE_TYPE_2D);
172 // delete all devices
173 for(DEVICE* device = first_device; device;) {
174 DEVICE *next_device = device->next_device;
177 device = next_device;
181 DEVICE* VM::get_device(int id)
183 for(DEVICE* device = first_device; device; device = device->next_device) {
184 if(device->this_device_id == id) {
191 // ----------------------------------------------------------------------------
192 // drive virtual machine
193 // ----------------------------------------------------------------------------
198 for(DEVICE* device = first_device; device; device = device->next_device) {
208 double VM::frame_rate()
210 return event->frame_rate();
213 // ----------------------------------------------------------------------------
215 // ----------------------------------------------------------------------------
218 DEVICE *VM::get_cpu(int index)
227 // ----------------------------------------------------------------------------
229 // ----------------------------------------------------------------------------
231 void VM::draw_screen()
233 display->draw_screen();
236 int VM::access_lamp()
238 uint32 status = fdc->read_signal(0);
239 return (status & (1 | 4)) ? 1 : (status & (2 | 8)) ? 2 : 0;
242 // ----------------------------------------------------------------------------
244 // ----------------------------------------------------------------------------
246 void VM::initialize_sound(int rate, int samples)
248 // init sound manager
249 event->initialize_sound(rate, samples);
252 pcm->init(rate, 4000);
255 uint16* VM::create_sound(int* extra_frames)
257 return event->create_sound(extra_frames);
260 int VM::sound_buffer_ptr()
262 return event->sound_buffer_ptr();
265 // ----------------------------------------------------------------------------
267 // ----------------------------------------------------------------------------
269 void VM::key_down(int code, bool repeat)
271 keyboard->key_down(code);
274 void VM::key_up(int code)
276 keyboard->key_up(code);
279 // ----------------------------------------------------------------------------
281 // ----------------------------------------------------------------------------
283 void VM::open_disk(int drv, _TCHAR* file_path, int bank)
285 fdc->open_disk(drv, file_path, bank);
288 void VM::close_disk(int drv)
290 fdc->close_disk(drv);
293 bool VM::disk_inserted(int drv)
295 return fdc->disk_inserted(drv);
300 return event->now_skip();
303 void VM::update_config()
305 for(DEVICE* device = first_device; device; device = device->next_device) {
306 device->update_config();
310 #define STATE_VERSION 1
312 void VM::save_state(FILEIO* state_fio)
314 state_fio->FputUint32(STATE_VERSION);
316 for(DEVICE* device = first_device; device; device = device->next_device) {
317 device->save_state(state_fio);
321 bool VM::load_state(FILEIO* state_fio)
323 if(state_fio->FgetUint32() != STATE_VERSION) {
326 for(DEVICE* device = first_device; device; device = device->next_device) {
327 if(!device->load_state(state_fio)) {