2 EPSON HC-20 Emulator 'eHC-20'
4 Author : Takeda.Toshiya
11 #include "../../emu.h"
12 #include "../device.h"
17 #include "../hd146818p.h"
19 //#include "../mc6800.h"
20 #include "../hd6301.h"
23 #include "../upd765a.h"
25 #include "../z80sio.h"
28 #include "../debugger.h"
33 // ----------------------------------------------------------------------------
35 // ----------------------------------------------------------------------------
37 VM::VM(EMU* parent_emu) : emu(parent_emu)
40 first_device = last_device = NULL;
41 dummy = new DEVICE(this, emu); // must be 1st device
42 event = new EVENT(this, emu); // must be 2nd device
43 dummy->set_device_name(_T("1st Dummy"));
45 beep = new BEEP(this, emu);
46 rtc = new HD146818P(this, emu);
47 //cpu = new MC6800(this, emu);
48 cpu = new HD6301(this, emu);
49 tf20 = new TF20(this, emu);
50 pio_tf20 = new I8255(this, emu);
51 fdc_tf20 = new UPD765A(this, emu);
52 fdc_tf20->set_context_noise_seek(new NOISE(this, emu));
53 fdc_tf20->set_context_noise_head_down(new NOISE(this, emu));
54 fdc_tf20->set_context_noise_head_up(new NOISE(this, emu));
55 cpu_tf20 = new Z80(this, emu);
56 sio_tf20 = new Z80SIO(this, emu);
57 pio_tf20->set_device_name(_T("TF20 PIO(i8255)"));
58 cpu_tf20->set_device_name(_T("TF20 CPU(Z80)"));
59 sio_tf20->set_device_name(_T("TF20 SIO(Z80 SIO)"));
60 fdc_tf20->set_device_name(_T("TF20 FDC(uPD765A)"));
61 memory = new MEMORY(this, emu);
63 event->set_context_cpu(cpu);
64 event->set_context_cpu(cpu_tf20, 4000000);
65 event->set_context_sound(beep);
66 event->set_context_sound(fdc_tf20->get_context_noise_seek());
67 event->set_context_sound(fdc_tf20->get_context_noise_head_down());
68 event->set_context_sound(fdc_tf20->get_context_noise_head_up());
72 0002 in --- port1 (cpu)
73 0003 in/out --- port2 (cpu)
76 0020 out bit0-7 key scan line
77 0022 in bit0-7 key scan result (lo)
78 0026 out bit0-2 selection of lcd driver (0,1-6)
79 bit3 output selection for lcd driver (0=data 1=command)
80 bit4 key input interrupt mask (0=Mask)
81 bit5 pout (serial control line)
82 bit6 shift/load select for rom cartridge (0=load 1=shift)
83 bit7 clock for rom cartridge
84 0028 in bit0-1 key scan result (hi)
85 bit6 power switch interrupt flag (0=active)
86 bit7 busy signal of lcd controller (0=busy)
87 002a out bit0-7 output data to lcd controller
88 in --- serial clock to lcd controller
89 002b in --- serial clock to lcd controller
90 002c in/out --- used for interrupt mask setting in sleep mode
91 0030 in/out --- select expansion unit rom (bank1)
92 0032 in/out --- select internal rom (bank0)
93 0033 in/out --- select internal rom (bank0)
94 003c in --- XXX: unknown
99 p12 in error status of slave mcu (P34)
100 p13 in external interrupt flag(0=active)
101 p14 in battery voltage interrupt flag (0=active)
102 p15 in key input inerrupt flag (0=active)
103 p16 in pin (serial control line)
104 p17 in counter status of microcassete / rom data / plug-in option
107 p20 in barcode input signal (1=mark 0=space)
108 p21 out txd (RS-232C)
109 p22 out selection for CPU serial communication (0=slave 1=serial)
111 cpu->set_context_port2(memory, SIG_MEMORY_PORT_2, 0xff, 0);
112 cpu->set_context_port3(memory, SIG_MEMORY_PORT_3, 0xff, 0);
113 cpu->set_context_port4(memory, SIG_MEMORY_PORT_4, 0xff, 0);
114 cpu->set_context_sio(memory, SIG_MEMORY_SIO_MAIN);
115 rtc->set_context_intr(memory, SIG_MEMORY_RTC_IRQ, 1);
117 memory->set_context_beep(beep);
118 memory->set_context_cpu(cpu);
119 memory->set_context_rtc(rtc);
120 memory->set_context_sio_tf20(sio_tf20);
123 cpu->set_context_mem(memory);
125 cpu->set_context_debugger(new DEBUGGER(this, emu));
129 tf20->set_context_cpu(cpu_tf20);
130 tf20->set_context_fdc(fdc_tf20);
131 tf20->set_context_pio(pio_tf20);
132 tf20->set_context_sio(sio_tf20);
133 cpu_tf20->set_context_mem(tf20);
134 cpu_tf20->set_context_io(tf20);
135 cpu_tf20->set_context_intr(tf20);
137 cpu_tf20->set_context_debugger(new DEBUGGER(this, emu));
139 fdc_tf20->set_context_irq(cpu_tf20, SIG_CPU_IRQ, 1);
140 sio_tf20->set_context_send(0, memory, SIG_MEMORY_SIO_TF20);
141 sio_tf20->set_tx_clock(0, 4915200 / 8); // 4.9152MHz / 8 (38.4kbps)
142 sio_tf20->set_rx_clock(0, 4915200 / 8); // baud-rate can be changed by jumper pin
143 sio_tf20->set_tx_clock(1, 4915200 / 8);
144 sio_tf20->set_rx_clock(1, 4915200 / 8);
146 // initialize all devices
147 for(DEVICE* device = first_device; device; device = device->next_device) {
148 device->initialize();
150 for(int i = 0; i < MAX_DRIVE; i++) {
151 fdc_tf20->set_drive_type(i, DRIVE_TYPE_2D);
157 // delete all devices
158 for(DEVICE* device = first_device; device;) {
159 DEVICE *next_device = device->next_device;
162 device = next_device;
166 DEVICE* VM::get_device(int id)
168 for(DEVICE* device = first_device; device; device = device->next_device) {
169 if(device->this_device_id == id) {
176 // ----------------------------------------------------------------------------
177 // drive virtual machine
178 // ----------------------------------------------------------------------------
183 for(DEVICE* device = first_device; device; device = device->next_device) {
186 cpu->write_signal(SIG_MC6801_PORT_1, 0x78, 0xff);
187 cpu->write_signal(SIG_MC6801_PORT_2, 0x9e, 0xff);
190 void VM::notify_power_off()
192 // this->out_debug_log(T("--- POWER OFF ---\n"));
193 memory->notify_power_off();
201 // ----------------------------------------------------------------------------
203 // ----------------------------------------------------------------------------
206 DEVICE *VM::get_cpu(int index)
210 } else if(index == 1) {
217 // ----------------------------------------------------------------------------
219 // ----------------------------------------------------------------------------
221 void VM::draw_screen()
223 memory->draw_screen();
226 // ----------------------------------------------------------------------------
228 // ----------------------------------------------------------------------------
230 void VM::initialize_sound(int rate, int samples)
232 // init sound manager
233 event->initialize_sound(rate, samples);
236 beep->initialize_sound(rate, 1000, 8000);
239 uint16_t* VM::create_sound(int* extra_frames)
241 return event->create_sound(extra_frames);
244 int VM::get_sound_buffer_ptr()
246 return event->get_sound_buffer_ptr();
249 #ifdef USE_SOUND_VOLUME
250 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
253 beep->set_volume(0, decibel_l, decibel_r);
255 fdc_tf20->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
256 fdc_tf20->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
257 fdc_tf20->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
262 // ----------------------------------------------------------------------------
264 // ----------------------------------------------------------------------------
266 void VM::key_down(int code, bool repeat)
268 memory->key_down(code);
271 void VM::key_up(int code)
273 memory->key_up(code);
276 // ----------------------------------------------------------------------------
278 // ----------------------------------------------------------------------------
280 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
282 fdc_tf20->open_disk(drv, file_path, bank);
285 void VM::close_floppy_disk(int drv)
287 fdc_tf20->close_disk(drv);
290 bool VM::is_floppy_disk_inserted(int drv)
292 return fdc_tf20->is_disk_inserted(drv);
295 void VM::is_floppy_disk_protected(int drv, bool value)
297 fdc_tf20->is_disk_protected(drv, value);
300 bool VM::is_floppy_disk_protected(int drv)
302 return fdc_tf20->is_disk_protected(drv);
305 uint32_t VM::is_floppy_disk_accessed()
307 return fdc_tf20->read_signal(0);
310 void VM::play_tape(int drv, const _TCHAR* file_path)
312 memory->play_tape(file_path);
315 void VM::rec_tape(int drv, const _TCHAR* file_path)
317 memory->rec_tape(file_path);
320 void VM::close_tape(int drv)
322 memory->close_tape();
325 bool VM::is_tape_inserted(int drv)
327 return memory->is_tape_inserted();
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 #include "../../statesub.h"
345 #include "../../qt/gui/csp_logger.h"
346 extern CSP_Logger DLL_PREFIX_I *csp_logger;
348 void VM::decl_state(void)
350 state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::HC_20_HEAD")), csp_logger);
352 for(DEVICE* device = first_device; device; device = device->next_device) {
353 device->decl_state();
357 void VM::save_state(FILEIO* state_fio)
359 //state_fio->FputUint32(STATE_VERSION);
361 if(state_entry != NULL) {
362 state_entry->save_state(state_fio);
364 for(DEVICE* device = first_device; device; device = device->next_device) {
365 device->save_state(state_fio);
369 bool VM::load_state(FILEIO* state_fio)
371 //if(state_fio->FgetUint32() != STATE_VERSION) {
375 if(state_entry != NULL) {
376 mb = state_entry->load_state(state_fio);
379 emu->out_debug_log("INFO: HEADER DATA ERROR");
382 for(DEVICE* device = first_device; device; device = device->next_device) {
383 if(!device->load_state(state_fio)) {