2 Japan Electronics College MYCOMZ-80A Emulator 'eMYCOMZ-80A'
4 Author : Takeda.Toshiya
10 #include "mycomz80a.h"
11 #include "../../emu.h"
12 #include "../device.h"
15 #include "../datarec.h"
16 #include "../hd46505.h"
19 #include "../msm58321.h"
21 #include "../sn76489an.h"
25 #include "../debugger.h"
32 // ----------------------------------------------------------------------------
34 // ----------------------------------------------------------------------------
36 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
39 first_device = last_device = NULL;
40 dummy = new DEVICE(this, emu); // must be 1st device
41 event = new EVENT(this, emu); // must be 2nd device
42 dummy->set_device_name(_T("1st Dummy"));
44 drec = new DATAREC(this, emu);
45 drec->set_context_noise_play(new NOISE(this, emu));
46 drec->set_context_noise_stop(new NOISE(this, emu));
47 drec->set_context_noise_fast(new NOISE(this, emu));
48 crtc = new HD46505(this, emu);
49 pio1 = new I8255(this, emu);
50 pio1->set_device_name(_T("8255 PIO (VRAM/Keyboard)"));
51 pio2 = new I8255(this, emu);
52 pio2->set_device_name(_T("8255 PIO (Display/Keyboard/CMT)"));
53 pio3 = new I8255(this, emu);
54 pio3->set_device_name(_T("8255 PIO (FDC/RTC)"));
55 io = new IO(this, emu);
56 rtc = new MSM5832(this, emu); // MSM5832
57 psg = new SN76489AN(this, emu);
58 cpu = new Z80(this, emu);
60 display = new DISPLAY(this, emu);
61 keyboard = new KEYBOARD(this, emu);
62 memory = new MEMORY(this, emu);
65 event->set_context_cpu(cpu);
66 event->set_context_sound(psg);
67 event->set_context_sound(drec);
68 event->set_context_sound(drec->get_context_noise_play());
69 event->set_context_sound(drec->get_context_noise_stop());
70 event->set_context_sound(drec->get_context_noise_fast());
72 // 00 out system control
73 // 01 in/out vram data
75 // 03 in/out crtc data
77 // pa0-7 out vram addr low, psg data
78 // pb0-7 in keyboard data
79 // pc0-2 out vram addr high
80 // pc3 out fdc format write
83 // pc6 in keyboard s4 (motor on/off)
84 // pc7 in keyboard s5 (slow)
86 // pa0 in keyboard strobe (1=pressed)
87 // pa1 in keyboard shift (1=pressed)
89 // pa3-6 in printer ctrl
90 // pa7 in crtc disptmg
91 // pb0-7 out printer data
92 // pc0 out printer strobe
93 // pc1 out printer reset
98 // pc6 out display chr/cg (0=chr,1=cg)
99 // pc7 out display freq (0=80column,1=40column)
101 // pa0-6 in fdc control
102 // pb0-3 in/out rtc data
103 // pc0-3 out rtc address
108 drec->set_context_ear(pio2, SIG_I8255_PORT_A, 4);
109 crtc->set_context_disp(pio2, SIG_I8255_PORT_A, 0x80);
110 pio1->set_context_port_a(display, SIG_DISPLAY_ADDR_L, 0xff, 0);
111 pio1->set_context_port_a(psg, SIG_SN76489AN_DATA, 0xff, 0);
112 pio1->set_context_port_c(display, SIG_DISPLAY_ADDR_H, 7, 0);
113 pio2->set_context_port_c(drec, SIG_DATAREC_MIC, 4, 0);
114 pio2->set_context_port_c(drec, SIG_DATAREC_REMOTE, 8, 0);
115 pio2->set_context_port_c(psg, SIG_SN76489AN_WE, 0x10, 0);
116 pio2->set_context_port_c(psg, SIG_SN76489AN_CS, 0x20, 0);
117 pio2->set_context_port_c(display, SIG_DISPLAY_MODE, 0xc0, 0);
118 pio3->set_context_port_b(rtc, SIG_MSM58321_DATA, 0x0f, 0);
119 pio3->set_context_port_c(rtc, SIG_MSM5832_ADDR, 0x0f, 0);
120 pio3->set_context_port_c(rtc, SIG_MSM5832_HOLD, 0x10, 0);
121 pio3->set_context_port_c(rtc, SIG_MSM58321_READ, 0x20, 0);
122 pio3->set_context_port_c(rtc, SIG_MSM58321_WRITE, 0x40, 0);
123 pio3->set_context_port_c(rtc, SIG_MSM58321_CS, 0x80, 0);
124 rtc->set_context_data(pio3, SIG_I8255_PORT_B, 0x0f, 0);
126 display->set_context_crtc(crtc);
127 display->set_regs_ptr(crtc->get_regs());
128 keyboard->set_context_cpu(cpu);
129 keyboard->set_context_pio1(pio1);
130 keyboard->set_context_pio2(pio2);
133 cpu->set_context_mem(memory);
134 cpu->set_context_io(io);
135 cpu->set_context_intr(dummy);
137 cpu->set_context_debugger(new DEBUGGER(this, emu));
141 io->set_iomap_single_w(0x00, memory);
142 io->set_iomap_single_rw(0x01, display);
143 io->set_iomap_range_rw(0x02, 0x03, crtc);
144 io->set_iomap_range_rw(0x04, 0x07, pio1);
145 io->set_iomap_range_rw(0x08, 0x0b, pio2);
146 io->set_iomap_range_rw(0x0c, 0x0f, pio3);
148 // initialize all devices
149 for(DEVICE* device = first_device; device; device = device->next_device) {
150 device->initialize();
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) {
193 double VM::get_frame_rate()
195 return event->get_frame_rate();
198 // ----------------------------------------------------------------------------
200 // ----------------------------------------------------------------------------
203 DEVICE *VM::get_cpu(int index)
212 // ----------------------------------------------------------------------------
214 // ----------------------------------------------------------------------------
216 void VM::draw_screen()
218 display->draw_screen();
221 // ----------------------------------------------------------------------------
223 // ----------------------------------------------------------------------------
225 void VM::initialize_sound(int rate, int samples)
227 // init sound manager
228 event->initialize_sound(rate, samples);
231 psg->initialize_sound(rate, 2500800, 10000);
234 uint16_t* VM::create_sound(int* extra_frames)
236 return event->create_sound(extra_frames);
239 int VM::get_sound_buffer_ptr()
241 return event->get_sound_buffer_ptr();
244 #ifdef USE_SOUND_VOLUME
245 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
248 psg->set_volume(0, decibel_l, decibel_r);
250 drec->set_volume(0, decibel_l, decibel_r);
252 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
253 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
254 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
259 // ----------------------------------------------------------------------------
261 // ----------------------------------------------------------------------------
263 void VM::key_down(int code, bool repeat)
265 keyboard->key_down(code);
268 void VM::key_up(int code)
270 keyboard->key_up(code);
273 bool VM::get_caps_locked()
275 return keyboard->get_caps_locked();
278 bool VM::get_kana_locked()
280 return keyboard->get_kana_locked();
283 // ----------------------------------------------------------------------------
285 // ----------------------------------------------------------------------------
287 void VM::play_tape(int drv, const _TCHAR* file_path)
289 drec->play_tape(file_path);
290 // drec->set_remote(true);
293 void VM::rec_tape(int drv, const _TCHAR* file_path)
295 drec->rec_tape(file_path);
296 // drec->set_remote(true);
299 void VM::close_tape(int drv)
304 // drec->set_remote(false);
307 bool VM::is_tape_inserted(int drv)
309 return drec->is_tape_inserted();
312 bool VM::is_tape_playing(int drv)
314 return drec->is_tape_playing();
317 bool VM::is_tape_recording(int drv)
319 return drec->is_tape_recording();
322 int VM::get_tape_position(int drv)
324 return drec->get_tape_position();
327 const _TCHAR* VM::get_tape_message(int drv)
329 return drec->get_message();
332 void VM::push_play(int drv)
335 drec->set_remote(true);
338 void VM::push_stop(int drv)
340 drec->set_remote(false);
343 void VM::push_fast_forward(int drv)
346 drec->set_remote(true);
349 void VM::push_fast_rewind(int drv)
351 drec->set_ff_rew(-1);
352 drec->set_remote(true);
355 bool VM::is_frame_skippable()
357 return event->is_frame_skippable();
360 void VM::update_config()
362 for(DEVICE* device = first_device; device; device = device->next_device) {
363 device->update_config();
367 #define STATE_VERSION 3
369 #include "../../statesub.h"
370 #include "../../qt/gui/csp_logger.h"
371 extern CSP_Logger DLL_PREFIX_I *csp_logger;
373 void VM::decl_state(void)
375 state_entry = new csp_state_utils(STATE_VERSION, 0, (_TCHAR *)(_T("CSP::MYCOM_Z80A_HEAD")), csp_logger);
376 for(DEVICE* device = first_device; device; device = device->next_device) {
377 device->decl_state();
381 void VM::save_state(FILEIO* state_fio)
383 //state_fio->FputUint32(STATE_VERSION);
385 if(state_entry != NULL) {
386 state_entry->save_state(state_fio);
388 for(DEVICE* device = first_device; device; device = device->next_device) {
389 device->save_state(state_fio);
393 bool VM::load_state(FILEIO* state_fio)
395 //if(state_fio->FgetUint32() != STATE_VERSION) {
399 if(state_entry != NULL) {
400 mb = state_entry->load_state(state_fio);
403 emu->out_debug_log("INFO: HEADER DATA ERROR");
406 for(DEVICE* device = first_device; device; device = device->next_device) {
407 if(!device->load_state(state_fio)) {