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) : VM_TEMPLATE(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 #if defined(__GIT_REPO_VERSION)
148 strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
150 for(DEVICE* device = first_device; device; device = device->next_device) {
151 device->initialize();
153 for(int i = 0; i < MAX_DRIVE; i++) {
154 fdc_tf20->set_drive_type(i, DRIVE_TYPE_2D);
160 // delete all devices
161 for(DEVICE* device = first_device; device;) {
162 DEVICE *next_device = device->next_device;
165 device = next_device;
169 DEVICE* VM::get_device(int id)
171 for(DEVICE* device = first_device; device; device = device->next_device) {
172 if(device->this_device_id == id) {
179 // ----------------------------------------------------------------------------
180 // drive virtual machine
181 // ----------------------------------------------------------------------------
186 for(DEVICE* device = first_device; device; device = device->next_device) {
189 cpu->write_signal(SIG_MC6801_PORT_1, 0x78, 0xff);
190 cpu->write_signal(SIG_MC6801_PORT_2, 0x9e, 0xff);
193 void VM::notify_power_off()
195 // this->out_debug_log(T("--- POWER OFF ---\n"));
196 memory->notify_power_off();
204 // ----------------------------------------------------------------------------
206 // ----------------------------------------------------------------------------
209 DEVICE *VM::get_cpu(int index)
213 } else if(index == 1) {
220 // ----------------------------------------------------------------------------
222 // ----------------------------------------------------------------------------
224 void VM::draw_screen()
226 memory->draw_screen();
229 // ----------------------------------------------------------------------------
231 // ----------------------------------------------------------------------------
233 void VM::initialize_sound(int rate, int samples)
235 // init sound manager
236 event->initialize_sound(rate, samples);
239 beep->initialize_sound(rate, 1000, 8000);
242 uint16_t* VM::create_sound(int* extra_frames)
244 return event->create_sound(extra_frames);
247 int VM::get_sound_buffer_ptr()
249 return event->get_sound_buffer_ptr();
252 #ifdef USE_SOUND_VOLUME
253 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
256 beep->set_volume(0, decibel_l, decibel_r);
258 fdc_tf20->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
259 fdc_tf20->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
260 fdc_tf20->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
265 // ----------------------------------------------------------------------------
267 // ----------------------------------------------------------------------------
269 void VM::key_down(int code, bool repeat)
271 memory->key_down(code);
274 void VM::key_up(int code)
276 memory->key_up(code);
279 // ----------------------------------------------------------------------------
281 // ----------------------------------------------------------------------------
283 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
285 fdc_tf20->open_disk(drv, file_path, bank);
288 void VM::close_floppy_disk(int drv)
290 fdc_tf20->close_disk(drv);
293 bool VM::is_floppy_disk_inserted(int drv)
295 return fdc_tf20->is_disk_inserted(drv);
298 void VM::is_floppy_disk_protected(int drv, bool value)
300 fdc_tf20->is_disk_protected(drv, value);
303 bool VM::is_floppy_disk_protected(int drv)
305 return fdc_tf20->is_disk_protected(drv);
308 uint32_t VM::is_floppy_disk_accessed()
310 return fdc_tf20->read_signal(0);
313 void VM::play_tape(int drv, const _TCHAR* file_path)
315 memory->play_tape(file_path);
318 void VM::rec_tape(int drv, const _TCHAR* file_path)
320 memory->rec_tape(file_path);
323 void VM::close_tape(int drv)
325 memory->close_tape();
328 bool VM::is_tape_inserted(int drv)
330 return memory->is_tape_inserted();
333 bool VM::is_frame_skippable()
335 return event->is_frame_skippable();
338 void VM::update_config()
340 for(DEVICE* device = first_device; device; device = device->next_device) {
341 device->update_config();
345 #define STATE_VERSION 3
347 #include "../../statesub.h"
348 #include "../../qt/gui/csp_logger.h"
349 extern CSP_Logger DLL_PREFIX_I *csp_logger;
351 void VM::decl_state(void)
353 state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::HC_20_HEAD")), csp_logger);
355 for(DEVICE* device = first_device; device; device = device->next_device) {
356 device->decl_state();
360 void VM::save_state(FILEIO* state_fio)
362 //state_fio->FputUint32(STATE_VERSION);
364 if(state_entry != NULL) {
365 state_entry->save_state(state_fio);
367 for(DEVICE* device = first_device; device; device = device->next_device) {
368 device->save_state(state_fio);
372 bool VM::load_state(FILEIO* state_fio)
374 //if(state_fio->FgetUint32() != STATE_VERSION) {
378 if(state_entry != NULL) {
379 mb = state_entry->load_state(state_fio);
382 emu->out_debug_log("INFO: HEADER DATA ERROR");
385 for(DEVICE* device = first_device; device; device = device->next_device) {
386 if(!device->load_state(state_fio)) {