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* 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->set_device_name(_T("Memory Mapped I/O (TK-80BS)"));
76 drec = new DATAREC(this, emu);
77 drec->set_context_noise_play(new NOISE(this, emu));
78 drec->set_context_noise_stop(new NOISE(this, emu));
79 drec->set_context_noise_fast(new NOISE(this, emu));
80 pio_t = new I8255(this, emu); // on TK-80
81 // memory = new MEMORY(this, emu);
83 pcm0 = new PCM1BIT(this, emu);
84 pcm0->set_device_name(_T("1-Bit PCM Sound #1"));
85 pcm1 = new PCM1BIT(this, emu);
86 pcm1->set_device_name(_T("1-Bit PCM Sound #2"));
88 #if defined(_TK80BS) || defined(_TK80)
89 cmt = new CMT(this, emu);
91 display = new DISPLAY(this, emu);
92 keyboard = new KEYBOARD(this, emu);
93 memory = new MEMBUS(this, emu);
95 pio_t->set_device_name(_T("i8255 PIO (TK-80/SOUND/KEYBOARD/DISPLAY)"));
97 pio_t->set_device_name(_T("i8255 PIO (TK-80/SOUND/KEYBOARD)"));
101 event->set_context_cpu(cpu);
102 event->set_context_sound(pcm0);
103 event->set_context_sound(pcm1);
104 event->set_context_sound(drec);
105 event->set_context_sound(drec->get_context_noise_play());
106 event->set_context_sound(drec->get_context_noise_stop());
107 event->set_context_sound(drec->get_context_noise_fast());
120 sio_b->set_context_out(cmt, SIG_CMT_OUT);
121 pio_b->set_context_port_c(display, SIG_DISPLAY_MODE, 3, 0);
123 #if defined(_TK80BS) || defined(_TK80)
124 drec->set_context_ear(cmt, SIG_CMT_EAR, 1);
125 pio_t->set_context_port_c(cmt, SIG_CMT_MIC, 1, 0);
127 drec->set_context_ear(cpu, SIG_I8085_SID, 1);
128 cpu->set_context_sod(drec, SIG_DATAREC_MIC, 1);
130 pio_t->set_context_port_c(pcm0, SIG_PCM1BIT_SIGNAL, 2, 0);
131 pio_t->set_context_port_c(pcm1, SIG_PCM1BIT_SIGNAL, 4, 0);
132 pio_t->set_context_port_c(keyboard, SIG_KEYBOARD_COLUMN, 0x70, 0);
133 #if defined(_TK80BS) || defined(_TK80)
134 pio_t->set_context_port_c(display, SIG_DISPLAY_DMA, 0x80, 0);
136 pio_t->set_context_port_c(memory, SIG_MEMBUS_PC7, 0x80, 0);
138 // Sound:: Force realtime rendering. This is temporally fix. 20161024 K.O
139 //pcm0->set_realtime_render(true);
140 //pcm1->set_realtime_render(true);
142 #if defined(_TK80BS) || defined(_TK80)
143 cmt->set_context_drec(drec);
144 cmt->set_context_pio(pio_t);
147 cmt->set_context_sio(sio_b);
148 display->set_vram_ptr(vram);
149 keyboard->set_context_pio_b(pio_b);
150 keyboard->set_context_cpu(cpu);
152 display->set_led_ptr(ram + 0x3f8);
153 keyboard->set_context_pio_t(pio_t);
154 memory->set_context_cpu(cpu);
157 cpu->set_context_mem(memory);
158 cpu->set_context_io(pio_t);
159 cpu->set_context_intr(keyboard);
161 cpu->set_context_debugger(new DEBUGGER(this, emu));
165 memset(mon, 0xff, sizeof(mon));
167 memset(bsmon, 0xff, sizeof(bsmon));
169 memset(ext, 0xff, sizeof(ext));
172 static const uint8_t top[3] = {0xc3, 0x00, 0xf0};
173 static const uint8_t rst[3] = {0xc3, 0xdd, 0x83};
175 if(!memory->read_bios(_T("TK80.ROM"), mon, sizeof(mon))) {
177 memcpy(mon, top, sizeof(top));
178 memcpy(mon + 0x38, rst, sizeof(rst));
180 if(memory->read_bios(_T("BSMON.ROM"), bsmon, sizeof(bsmon))) {
182 memcpy(mon + 0x38, rst, sizeof(rst));
185 memory->read_bios(_T("TK80.ROM"), mon, sizeof(mon));
187 memory->read_bios(_T("TK85.ROM"), mon, sizeof(mon));
189 memory->read_bios(_T("EXT.ROM"), ext, sizeof(ext));
191 memory->set_memory_r(0x0000, 0x07ff, mon);
192 memory->set_memory_r(0x0c00, 0x7bff, ext);
194 memory->set_memory_mapped_io_rw(0x7c00, 0x7dff, memio);
195 memory->set_memory_rw(0x7e00, 0x7fff, vram);
197 memory->set_memory_rw(0x8000, 0xcfff, ram);
199 memory->set_memory_r(0xd000, 0xefff, basic);
200 memory->set_memory_r(0xf000, 0xffff, bsmon);
203 memio->set_iomap_alias_rw(0x7df8, sio_b, 0);
204 memio->set_iomap_alias_rw(0x7df9, sio_b, 1);
205 memio->set_iomap_alias_rw(0x7dfc, pio_b, 0);
206 memio->set_iomap_alias_rw(0x7dfd, pio_b, 1);
207 memio->set_iomap_alias_rw(0x7dfe, pio_b, 2);
208 memio->set_iomap_alias_w(0x7dff, pio_b, 3);
211 // initialize all devices
212 #if defined(__GIT_REPO_VERSION)
213 strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
215 for(DEVICE* device = first_device; device; device = device->next_device) {
216 device->initialize();
222 // delete all devices
223 for(DEVICE* device = first_device; device;) {
224 DEVICE *next_device = device->next_device;
227 device = next_device;
231 DEVICE* VM::get_device(int id)
233 for(DEVICE* device = first_device; device; device = device->next_device) {
234 if(device->this_device_id == id) {
241 // ----------------------------------------------------------------------------
242 // drive virtual machine
243 // ----------------------------------------------------------------------------
249 if(boot_mode != config.boot_mode) {
250 memset(basic, 0xff, sizeof(basic));
251 if(config.boot_mode == 0) {
252 memory->read_bios(_T("LV1BASIC.ROM"), basic + 0x1000, 0x1000);
254 memory->read_bios(_T("LV2BASIC.ROM"), basic, sizeof(basic));
256 boot_mode = config.boot_mode;
258 memset(ram, 0, sizeof(ram));
262 emu->reload_bitmap();
264 memset(vram, 0x20, sizeof(vram));
268 for(DEVICE* device = first_device; device; device = device->next_device) {
272 // init 8255 on TK-80
273 pio_t->write_io8(0xfb, 0x92);
274 pio_t->write_signal(SIG_I8255_PORT_A, 0xff, 0xff);
282 // ----------------------------------------------------------------------------
284 // ----------------------------------------------------------------------------
287 DEVICE *VM::get_cpu(int index)
296 // ----------------------------------------------------------------------------
298 // ----------------------------------------------------------------------------
300 void VM::draw_screen()
302 display->draw_screen();
306 int VM::max_draw_ranges()
312 // ----------------------------------------------------------------------------
314 // ----------------------------------------------------------------------------
316 void VM::initialize_sound(int rate, int samples)
318 // init sound manager
319 event->initialize_sound(rate, samples);
322 pcm0->initialize_sound(rate, 8000);
323 pcm1->initialize_sound(rate, 8000);
326 uint16_t* VM::create_sound(int* extra_frames)
328 return event->create_sound(extra_frames);
331 int VM::get_sound_buffer_ptr()
333 return event->get_sound_buffer_ptr();
336 #ifdef USE_SOUND_VOLUME
337 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
340 pcm0->set_volume(0, decibel_l, decibel_r);
342 pcm1->set_volume(0, decibel_l, decibel_r);
344 drec->set_volume(0, decibel_l, decibel_r);
346 drec->get_context_noise_play()->set_volume(0, decibel_l, decibel_r);
347 drec->get_context_noise_stop()->set_volume(0, decibel_l, decibel_r);
348 drec->get_context_noise_fast()->set_volume(0, decibel_l, decibel_r);
353 // ----------------------------------------------------------------------------
355 // ----------------------------------------------------------------------------
357 void VM::key_down(int code, bool repeat)
361 cpu->write_signal(SIG_CPU_NMI, 1, 1);
365 keyboard->key_down(code);
368 void VM::key_up(int code)
375 keyboard->key_up(code);
378 bool VM::get_caps_locked()
380 return keyboard->get_caps_locked();
383 bool VM::get_kana_locked()
385 return keyboard->get_kana_locked();
388 // ----------------------------------------------------------------------------
390 // ----------------------------------------------------------------------------
392 void VM::load_binary(int drv, const _TCHAR* file_path)
395 memory->read_image(file_path, ram, sizeof(ram));
399 void VM::save_binary(int drv, const _TCHAR* file_path)
402 memory->write_image(file_path, ram, sizeof(ram));
406 void VM::play_tape(int drv, const _TCHAR* file_path)
409 drec->play_tape(file_path);
410 // drec->set_remote(true);
412 } else if(drv == 1) {
413 cmt->play_tape(file_path);
418 void VM::rec_tape(int drv, const _TCHAR* file_path)
421 drec->rec_tape(file_path);
422 // drec->set_remote(true);
424 } else if(drv == 1) {
425 cmt->rec_tape(file_path);
430 void VM::close_tape(int drv)
436 // drec->set_remote(false);
438 } else if(drv == 1) {
444 bool VM::is_tape_inserted(int drv)
447 return drec->is_tape_inserted();
449 } else if(drv == 1) {
450 return cmt->is_tape_inserted();
456 bool VM::is_tape_playing(int drv)
459 return drec->is_tape_playing();
461 } else if(drv == 1) {
462 return cmt->is_tape_playing();
468 bool VM::is_tape_recording(int drv)
471 return drec->is_tape_recording();
473 } else if(drv == 1) {
474 return cmt->is_tape_recording();
480 int VM::get_tape_position(int drv)
483 return drec->get_tape_position();
485 } else if(drv == 1) {
486 return cmt->get_tape_position();
492 const _TCHAR* VM::get_tape_message(int drv)
495 return drec->get_message();
500 void VM::push_play(int drv)
504 drec->set_remote(true);
508 void VM::push_stop(int drv)
511 drec->set_remote(false);
515 void VM::push_fast_forward(int drv)
519 drec->set_remote(true);
523 void VM::push_fast_rewind(int drv)
526 drec->set_ff_rew(-1);
527 drec->set_remote(true);
531 bool VM::is_frame_skippable()
533 // return event->is_frame_skippable();
537 void VM::update_config()
540 if(boot_mode != config.boot_mode) {
541 // boot mode is changed !!!
542 // boot_mode = config.boot_mode;
546 for(DEVICE* device = first_device; device; device = device->next_device) {
547 device->update_config();
554 #define STATE_VERSION 6
556 bool VM::process_state(FILEIO* state_fio, bool loading)
558 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
561 for(DEVICE* device = first_device; device; device = device->next_device) {
562 // Note: typeid(foo).name is fixed by recent ABI.Not dec 6.
563 // const char *name = typeid(*device).name();
564 // But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
565 const char *name = device->get_device_name();
566 int len = strlen(name);
568 if(!state_fio->StateCheckInt32(len)) {
570 printf("Class name len Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
574 if(!state_fio->StateCheckBuffer(name, len, 1)) {
576 printf("Class name Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
580 if(!device->process_state(state_fio, loading)) {
582 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
587 // Machine specified.
588 state_fio->StateBuffer(ram, sizeof(ram), 1);
590 state_fio->StateBuffer(vram, sizeof(vram), 1);
591 state_fio->StateInt32(boot_mode);
592 // state_fio->StateInt32(draw_ranges);
596 emu->reload_bitmap();