2 NEC TK-80BS (COMPO BS/80) Emulator 'eTK-80BS'
3 NEC TK-80 Emulator 'eTK-80'
4 NEC TK-85 Emulator 'eTK-85'
6 Author : Takeda.Toshiya
13 #include "../../emu.h"
14 #include "../device.h"
17 #include "../datarec.h"
24 //#include "../memory.h"
26 #include "../pcm1bit.h"
29 #include "../debugger.h"
32 #if defined(_TK80BS) || defined(_TK80)
39 #if defined(_TK80BS) || defined(_TK80)
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 VM::VM(EMU_TEMPLATE* parent_emu) : VM_TEMPLATE(parent_emu)
54 // boot_mode = config.boot_mode;
57 #if defined(_TK80BS) || defined(_TK80)
58 config.wave_shaper[0] = false;
62 first_device = last_device = NULL;
63 dummy = new DEVICE(this, emu); // must be 1st device
64 dummy->set_device_name(_T("1st Dummy"));
65 event = new EVENT(this, emu); // must be 2nd device
67 cpu = new I8080(this, emu);
69 sio_b = new I8251(this, emu); // on TK-80BS
70 sio_b->set_device_name(_T("i8251 SIO (TK-80BS/CMT)"));
71 pio_b = new I8255(this, emu);
72 pio_b->set_device_name(_T("i8255 PIO (TK-80BS/DISPLAY)"));
73 memio = new IO(this, emu);
74 memio->space = 0x10000;
75 memio->set_device_name(_T("Memory Mapped I/O (TK-80BS)"));
77 drec = new DATAREC(this, emu);
78 drec->set_context_noise_play(new NOISE(this, emu));
79 drec->set_context_noise_stop(new NOISE(this, emu));
80 drec->set_context_noise_fast(new NOISE(this, emu));
81 pio_t = new I8255(this, emu); // on TK-80
82 // memory = new MEMORY(this, emu);
84 pcm0 = new PCM1BIT(this, emu);
85 pcm0->set_device_name(_T("1-Bit PCM Sound #1"));
86 pcm1 = new PCM1BIT(this, emu);
87 pcm1->set_device_name(_T("1-Bit PCM Sound #2"));
89 // pcm0->set_context_debugger(new DEBUGGER(this, emu));
90 // pcm1->set_context_debugger(new DEBUGGER(this, emu));
93 #if defined(_TK80BS) || defined(_TK80)
94 cmt = new CMT(this, emu);
96 display = new DISPLAY(this, emu);
97 keyboard = new KEYBOARD(this, emu);
98 memory = new MEMBUS(this, emu);
99 memory->space = 0x10000;
100 memory->bank_size = 0x200;
103 pio_t->set_device_name(_T("i8255 PIO (TK-80/SOUND/KEYBOARD/DISPLAY)"));
105 pio_t->set_device_name(_T("i8255 PIO (TK-80/SOUND/KEYBOARD)"));
109 event->set_context_cpu(cpu);
110 event->set_context_sound(pcm0);
111 event->set_context_sound(pcm1);
112 event->set_context_sound(drec);
113 event->set_context_sound(drec->get_context_noise_play());
114 event->set_context_sound(drec->get_context_noise_stop());
115 event->set_context_sound(drec->get_context_noise_fast());
128 sio_b->set_context_out(cmt, SIG_CMT_OUT);
129 pio_b->set_context_port_c(display, SIG_DISPLAY_MODE, 3, 0);
131 #if defined(_TK80BS) || defined(_TK80)
132 drec->set_context_ear(cmt, SIG_CMT_EAR, 1);
133 pio_t->set_context_port_c(cmt, SIG_CMT_MIC, 1, 0);
135 drec->set_context_ear(cpu, SIG_I8085_SID, 1);
136 cpu->set_context_sod(drec, SIG_DATAREC_MIC, 1);
138 pio_t->set_context_port_c(pcm0, SIG_PCM1BIT_SIGNAL, 2, 0);
139 pio_t->set_context_port_c(pcm1, SIG_PCM1BIT_SIGNAL, 4, 0);
140 pio_t->set_context_port_c(keyboard, SIG_KEYBOARD_COLUMN, 0x70, 0);
141 #if defined(_TK80BS) || defined(_TK80)
142 pio_t->set_context_port_c(display, SIG_DISPLAY_DMA, 0x80, 0);
144 pio_t->set_context_port_c(memory, SIG_MEMBUS_PC7, 0x80, 0);
146 // Sound:: Force realtime rendering. This is temporally fix. 20161024 K.O
147 //pcm0->set_realtime_render(true);
148 //pcm1->set_realtime_render(true);
150 #if defined(_TK80BS) || defined(_TK80)
151 cmt->set_context_drec(drec);
152 cmt->set_context_pio(pio_t);
155 cmt->set_context_sio(sio_b);
156 display->set_vram_ptr(vram);
157 keyboard->set_context_pio_b(pio_b);
158 keyboard->set_context_cpu(cpu);
160 display->set_led_ptr(ram + 0x3f8);
161 keyboard->set_context_pio_t(pio_t);
162 memory->set_context_cpu(cpu);
165 cpu->set_context_mem(memory);
166 cpu->set_context_io(pio_t);
167 cpu->set_context_intr(keyboard);
169 cpu->set_context_debugger(new DEBUGGER(this, emu));
173 memset(mon, 0xff, sizeof(mon));
175 memset(bsmon, 0xff, sizeof(bsmon));
177 memset(ext, 0xff, sizeof(ext));
180 static const uint8_t top[3] = {0xc3, 0x00, 0xf0};
181 static const uint8_t rst[3] = {0xc3, 0xdd, 0x83};
183 if(!memory->read_bios(_T("TK80.ROM"), mon, sizeof(mon))) {
185 memcpy(mon, top, sizeof(top));
186 memcpy(mon + 0x38, rst, sizeof(rst));
188 if(memory->read_bios(_T("BSMON.ROM"), bsmon, sizeof(bsmon))) {
190 memcpy(mon + 0x38, rst, sizeof(rst));
193 memory->read_bios(_T("TK80.ROM"), mon, sizeof(mon));
195 memory->read_bios(_T("TK85.ROM"), mon, sizeof(mon));
197 memory->read_bios(_T("EXT.ROM"), ext, sizeof(ext));
199 memory->set_memory_r(0x0000, 0x07ff, mon);
200 memory->set_memory_r(0x0c00, 0x7bff, ext);
202 memory->set_memory_mapped_io_rw(0x7c00, 0x7dff, memio);
203 memory->set_memory_rw(0x7e00, 0x7fff, vram);
205 memory->set_memory_rw(0x8000, 0xcfff, ram);
207 memory->set_memory_r(0xd000, 0xefff, basic);
208 memory->set_memory_r(0xf000, 0xffff, bsmon);
211 memio->set_iomap_alias_rw(0x7df8, sio_b, 0);
212 memio->set_iomap_alias_rw(0x7df9, sio_b, 1);
213 memio->set_iomap_alias_rw(0x7dfc, pio_b, 0);
214 memio->set_iomap_alias_rw(0x7dfd, pio_b, 1);
215 memio->set_iomap_alias_rw(0x7dfe, pio_b, 2);
216 memio->set_iomap_alias_w(0x7dff, pio_b, 3);
219 // initialize all devices
220 #if defined(__GIT_REPO_VERSION)
221 set_git_repo_version(__GIT_REPO_VERSION);
223 initialize_devices();
229 // delete all devices
230 for(DEVICE* device = first_device; device;) {
231 DEVICE *next_device = device->next_device;
234 device = next_device;
238 DEVICE* VM::get_device(int id)
240 for(DEVICE* device = first_device; device; device = device->next_device) {
241 if(device->this_device_id == id) {
248 // ----------------------------------------------------------------------------
249 // drive virtual machine
250 // ----------------------------------------------------------------------------
256 if(boot_mode != config.boot_mode) {
257 memset(basic, 0xff, sizeof(basic));
258 if(config.boot_mode == 0) {
259 memory->read_bios(_T("LV1BASIC.ROM"), basic + 0x1000, 0x1000);
261 memory->read_bios(_T("LV2BASIC.ROM"), basic, sizeof(basic));
263 boot_mode = config.boot_mode;
265 memset(ram, 0, sizeof(ram));
269 emu->reload_bitmap();
271 memset(vram, 0x20, sizeof(vram));
275 for(DEVICE* device = first_device; device; device = device->next_device) {
279 // init 8255 on TK-80
280 pio_t->write_io8(0xfb, 0x92);
281 pio_t->write_signal(SIG_I8255_PORT_A, 0xff, 0xff);
289 // ----------------------------------------------------------------------------
291 // ----------------------------------------------------------------------------
294 DEVICE *VM::get_cpu(int index)
303 // ----------------------------------------------------------------------------
305 // ----------------------------------------------------------------------------
307 void VM::draw_screen()
309 display->draw_screen();
313 int VM::max_draw_ranges()
319 // ----------------------------------------------------------------------------
321 // ----------------------------------------------------------------------------
323 void VM::initialize_sound(int rate, int samples)
325 // init sound manager
326 event->initialize_sound(rate, samples);
329 pcm0->initialize_sound(rate, 8000);
330 pcm1->initialize_sound(rate, 8000);
333 uint16_t* VM::create_sound(int* extra_frames)
335 return event->create_sound(extra_frames);
338 int VM::get_sound_buffer_ptr()
340 return event->get_sound_buffer_ptr();
343 #ifdef USE_SOUND_VOLUME
344 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
347 pcm0->set_volume(0, decibel_l, decibel_r);
349 pcm1->set_volume(0, decibel_l, decibel_r);
351 drec->set_volume(0, decibel_l, decibel_r);
353 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
354 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
355 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
360 // ----------------------------------------------------------------------------
362 // ----------------------------------------------------------------------------
364 void VM::key_down(int code, bool repeat)
368 cpu->write_signal(SIG_CPU_NMI, 1, 1);
372 keyboard->key_down(code);
375 void VM::key_up(int code)
382 keyboard->key_up(code);
385 bool VM::get_caps_locked()
387 return keyboard->get_caps_locked();
390 bool VM::get_kana_locked()
392 return keyboard->get_kana_locked();
395 // ----------------------------------------------------------------------------
397 // ----------------------------------------------------------------------------
399 void VM::load_binary(int drv, const _TCHAR* file_path)
402 memory->read_image(file_path, ram, sizeof(ram));
406 void VM::save_binary(int drv, const _TCHAR* file_path)
409 memory->write_image(file_path, ram, sizeof(ram));
413 void VM::play_tape(int drv, const _TCHAR* file_path)
416 bool remote = drec->get_remote();
418 if(drec->play_tape(file_path) && remote) {
419 // if machine already sets remote on, start playing now
423 } else if(drv == 1) {
424 cmt->play_tape(file_path);
429 void VM::rec_tape(int drv, const _TCHAR* file_path)
432 bool remote = drec->get_remote();
434 if(drec->rec_tape(file_path) && remote) {
435 // if machine already sets remote on, start recording now
439 } else if(drv == 1) {
440 cmt->rec_tape(file_path);
445 void VM::close_tape(int drv)
451 drec->set_remote(false);
453 } else if(drv == 1) {
459 bool VM::is_tape_inserted(int drv)
462 return drec->is_tape_inserted();
464 } else if(drv == 1) {
465 return cmt->is_tape_inserted();
471 bool VM::is_tape_playing(int drv)
474 return drec->is_tape_playing();
476 } else if(drv == 1) {
477 return cmt->is_tape_playing();
483 bool VM::is_tape_recording(int drv)
486 return drec->is_tape_recording();
488 } else if(drv == 1) {
489 return cmt->is_tape_recording();
495 int VM::get_tape_position(int drv)
498 return drec->get_tape_position();
500 } else if(drv == 1) {
501 return cmt->get_tape_position();
507 const _TCHAR* VM::get_tape_message(int drv)
510 return drec->get_message();
515 void VM::push_play(int drv)
518 drec->set_remote(false);
520 drec->set_remote(true);
524 void VM::push_stop(int drv)
527 drec->set_remote(false);
531 void VM::push_fast_forward(int drv)
534 drec->set_remote(false);
536 drec->set_remote(true);
540 void VM::push_fast_rewind(int drv)
543 drec->set_remote(false);
544 drec->set_ff_rew(-1);
545 drec->set_remote(true);
549 bool VM::is_frame_skippable()
551 // return event->is_frame_skippable();
555 void VM::update_config()
558 if(boot_mode != config.boot_mode) {
559 // boot mode is changed !!!
560 // boot_mode = config.boot_mode;
564 for(DEVICE* device = first_device; device; device = device->next_device) {
565 device->update_config();
572 double VM::get_current_usec()
574 if(event == NULL) return 0.0;
575 return event->get_current_usec();
578 uint64_t VM::get_current_clock_uint64()
580 if(event == NULL) return (uint64_t)0;
581 return event->get_current_clock_uint64();
584 #define STATE_VERSION 6
586 bool VM::process_state(FILEIO* state_fio, bool loading)
588 if(!(VM_TEMPLATE::process_state_core(state_fio, loading, STATE_VERSION))) {
591 // Machine specified.
592 state_fio->StateArray(ram, sizeof(ram), 1);
594 state_fio->StateArray(vram, sizeof(vram), 1);
595 state_fio->StateValue(boot_mode);
596 // state_fio->StateValue(draw_ranges);
600 emu->reload_bitmap();