2 NEC PC-8201 Emulator 'ePC-8201'
4 Author : Takeda.Toshiya
11 #include "../../emu.h"
12 #include "../device.h"
15 #include "../datarec.h"
20 #include "../pcm1bit.h"
21 #include "../upd1990a.h"
24 #include "../debugger.h"
33 using PC8201::KEYBOARD;
37 // ----------------------------------------------------------------------------
39 // ----------------------------------------------------------------------------
41 VM::VM(EMU_TEMPLATE* parent_emu) : VM_TEMPLATE(parent_emu)
44 first_device = last_device = NULL;
45 dummy = new DEVICE(this, emu); // must be 1st device
46 event = new EVENT(this, emu); // must be 2nd device
48 drec = new DATAREC(this, emu);
49 drec->set_context_noise_play(new NOISE(this, emu));
50 drec->set_context_noise_stop(new NOISE(this, emu));
51 drec->set_context_noise_fast(new NOISE(this, emu));
52 cpu = new I8080(this, emu);
53 pio = new I8155(this, emu);
54 io = new IO(this, emu);
56 pcm = new PCM1BIT(this, emu);
57 rtc = new UPD1990A(this, emu);
59 // pcm->set_context_debugger(new DEBUGGER(this, emu));
62 cmt = new CMT(this, emu);
63 keyboard = new KEYBOARD(this, emu);
64 lcd = new LCD(this, emu);
65 memory = new MEMORY(this, emu);
68 event->set_context_cpu(cpu);
69 event->set_context_sound(pcm);
70 event->set_context_sound(drec);
71 event->set_context_sound(drec->get_context_noise_play());
72 event->set_context_sound(drec->get_context_noise_stop());
73 event->set_context_sound(drec->get_context_noise_fast());
75 drec->set_context_ear(cpu, SIG_I8085_SID, 1);
76 cpu->set_context_sod(cmt, SIG_CMT_SOD, 1);
77 pio->set_context_port_a(rtc, SIG_UPD1990A_C0, 1, 0);
78 pio->set_context_port_a(rtc, SIG_UPD1990A_C1, 2, 0);
79 pio->set_context_port_a(rtc, SIG_UPD1990A_C2, 4, 0);
80 pio->set_context_port_a(rtc, SIG_UPD1990A_CLK, 8, 0);
81 pio->set_context_port_a(rtc, SIG_UPD1990A_DIN, 0x10, 0);
82 pio->set_context_port_a(keyboard, SIG_KEYBOARD_COLUMN_L, 0xff, 0);
83 pio->set_context_port_a(lcd, SIG_LCD_CHIPSEL_L, 0xff, 0);
84 pio->set_context_port_b(keyboard, SIG_KEYBOARD_COLUMN_H, 1, 0);
85 pio->set_context_port_b(lcd, SIG_LCD_CHIPSEL_H, 3, 0);
86 pio->set_context_port_b(pcm, SIG_PCM1BIT_MUTE, 0x20, 0);
87 pio->set_context_timer(pcm, SIG_PCM1BIT_SIGNAL, 1);
88 pio->set_constant_clock(CPU_CLOCKS);
89 rtc->set_context_dout(pio, SIG_I8155_PORT_C, 1);
90 rtc->set_context_tp(cpu, SIG_I8085_RST7, 1);
92 memory->set_context_cmt(cmt);
93 memory->set_context_drec(drec);
94 memory->set_context_rtc(rtc);
97 cpu->set_context_mem(memory);
98 cpu->set_context_io(io);
99 cpu->set_context_intr(io);
101 cpu->set_context_debugger(new DEBUGGER(this, emu));
105 io->set_iomap_range_w(0x90, 0x9f, memory);
106 io->set_iomap_range_rw(0xa0, 0xaf, memory);
107 io->set_iomap_range_rw(0xb0, 0xbf, pio);
108 io->set_iomap_range_r(0xe0, 0xef, keyboard);
109 io->set_iomap_range_rw(0xf0, 0xff, lcd);
111 // initialize all devices
112 #if defined(__GIT_REPO_VERSION)
113 set_git_repo_version(__GIT_REPO_VERSION);
115 initialize_devices();
117 rtc->write_signal(SIG_UPD1990A_STB, 0, 0);
122 // delete all devices
123 for(DEVICE* device = first_device; device;) {
124 DEVICE *next_device = device->next_device;
127 device = next_device;
131 DEVICE* VM::get_device(int id)
133 for(DEVICE* device = first_device; device; device = device->next_device) {
134 if(device->this_device_id == id) {
141 // ----------------------------------------------------------------------------
142 // drive virtual machine
143 // ----------------------------------------------------------------------------
148 for(DEVICE* device = first_device; device; device = device->next_device) {
158 // ----------------------------------------------------------------------------
160 // ----------------------------------------------------------------------------
163 DEVICE *VM::get_cpu(int index)
172 // ----------------------------------------------------------------------------
174 // ----------------------------------------------------------------------------
176 void VM::draw_screen()
181 // ----------------------------------------------------------------------------
183 // ----------------------------------------------------------------------------
185 void VM::initialize_sound(int rate, int samples)
187 // init sound manager
188 event->initialize_sound(rate, samples);
191 pcm->initialize_sound(rate, 8000);
194 uint16_t* VM::create_sound(int* extra_frames)
196 return event->create_sound(extra_frames);
199 int VM::get_sound_buffer_ptr()
201 return event->get_sound_buffer_ptr();
204 #ifdef USE_SOUND_VOLUME
205 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
208 pcm->set_volume(0, decibel_l, decibel_r);
210 drec->set_volume(0, decibel_l, decibel_r);
212 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
213 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
214 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
219 // ----------------------------------------------------------------------------
221 // ----------------------------------------------------------------------------
223 void VM::key_down(int code, bool repeat)
225 keyboard->key_down(code);
228 void VM::key_up(int code)
232 bool VM::get_caps_locked()
234 return keyboard->get_caps_locked();
237 bool VM::get_kana_locked()
239 return keyboard->get_kana_locked();
242 // ----------------------------------------------------------------------------
244 // ----------------------------------------------------------------------------
246 void VM::play_tape(int drv, const _TCHAR* file_path)
250 bool remote = drec->get_remote();
252 if(drec->play_tape(file_path) && remote) {
253 // if machine already sets remote on, start playing now
258 void VM::rec_tape(int drv, const _TCHAR* file_path)
263 drec->set_remote(false);
265 cmt->rec_tape(file_path);
268 void VM::close_tape(int drv)
273 drec->set_remote(false);
278 bool VM::is_tape_inserted(int drv)
280 return drec->is_tape_inserted() || cmt->is_tape_inserted();
283 bool VM::is_tape_playing(int drv)
285 if(drec->is_tape_inserted()) {
286 return drec->is_tape_playing();
288 return cmt->is_tape_playing();
292 bool VM::is_tape_recording(int drv)
294 if(drec->is_tape_inserted()) {
295 return drec->is_tape_recording();
297 return cmt->is_tape_recording();
301 int VM::get_tape_position(int drv)
303 if(drec->is_tape_inserted()) {
304 return drec->get_tape_position();
306 return cmt->get_tape_position();
310 const _TCHAR* VM::get_tape_message(int drv)
312 if(drec->is_tape_inserted()) {
313 return drec->get_message();
319 void VM::push_play(int drv)
321 if(drec->is_tape_inserted()) {
322 drec->set_remote(false);
324 drec->set_remote(true);
328 void VM::push_stop(int drv)
330 if(drec->is_tape_inserted()) {
331 drec->set_remote(false);
335 void VM::push_fast_forward(int drv)
337 if(drec->is_tape_inserted()) {
338 drec->set_remote(false);
340 drec->set_remote(true);
344 void VM::push_fast_rewind(int drv)
346 if(drec->is_tape_inserted()) {
347 drec->set_remote(false);
348 drec->set_ff_rew(-1);
349 drec->set_remote(true);
353 bool VM::is_frame_skippable()
355 return event->is_frame_skippable();
358 void VM::update_config()
360 for(DEVICE* device = first_device; device; device = device->next_device) {
361 device->update_config();
365 double VM::get_current_usec()
367 if(event == NULL) return 0.0;
368 return event->get_current_usec();
371 uint64_t VM::get_current_clock_uint64()
373 if(event == NULL) return (uint64_t)0;
374 return event->get_current_clock_uint64();
377 #define STATE_VERSION 3
379 bool VM::process_state(FILEIO* state_fio, bool loading)
381 if(!(VM_TEMPLATE::process_state_core(state_fio, loading, STATE_VERSION))) {
384 // Machine specified.