OSDN Git Service

[VM] Merge Upstream 2018-02-23.
authorK.Ohta <whatisthis.sowhat@gmail.com>
Fri, 23 Feb 2018 18:04:27 +0000 (03:04 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Fri, 23 Feb 2018 18:04:27 +0000 (03:04 +0900)
27 files changed:
source/src/common.h
source/src/vm/disk.cpp
source/src/vm/disk.h
source/src/vm/fm16beta/CMakeLists.txt [new file with mode: 0644]
source/src/vm/fm16beta/cmos.cpp [new file with mode: 0644]
source/src/vm/fm16beta/cmos.h [new file with mode: 0644]
source/src/vm/fm16beta/fm16beta.cpp [new file with mode: 0644]
source/src/vm/fm16beta/fm16beta.h [new file with mode: 0644]
source/src/vm/fm16beta/keyboard.cpp [new file with mode: 0644]
source/src/vm/fm16beta/keyboard.h [new file with mode: 0644]
source/src/vm/fm16beta/main.cpp [new file with mode: 0644]
source/src/vm/fm16beta/main.h [new file with mode: 0644]
source/src/vm/fm16beta/memo.txt [new file with mode: 0644]
source/src/vm/fm16beta/sub.cpp [new file with mode: 0644]
source/src/vm/fm16beta/sub.h [new file with mode: 0644]
source/src/vm/fmr50/memory.cpp
source/src/vm/i8237.cpp
source/src/vm/i8237.h
source/src/vm/i8237_base.cpp
source/src/vm/io.cpp
source/src/vm/io.h
source/src/vm/mc6840.cpp
source/src/vm/memory.cpp
source/src/vm/memory.h
source/src/vm/pc9801/pc9801.cpp
source/src/vm/upd765a.cpp
source/src/vm/vm.h

index aa24254..696bec7 100644 (file)
@@ -18,7 +18,9 @@
 // use zlib to decompress gzip file???
 #ifdef _WIN32
        #if defined(_MSC_VER) && (_MSC_VER >= 1500)
-               #define USE_ZLIB
+               #ifndef _ANY2D88
+                       #define USE_ZLIB
+               #endif
        #endif
 #endif
 
index 28b4e25..1011424 100644 (file)
@@ -501,6 +501,24 @@ void DISK::open(const _TCHAR* file_path, int bank)
                        }
                }
                
+               // check two side
+               int valid_side = 0;
+               
+               for(int trk = 0; trk < 82; trk++) {
+                       for(int side = 0; side < 2; side++) {
+                               int trkside = trk * 2 + side;
+                               pair_t offset;
+                               offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
+                               
+                               if(IS_VALID_TRACK(offset.d)) {
+                                       valid_side |= (1 << side);
+                               }
+                       }
+                       if(valid_side == 3) break;
+               }
+               // FIXME: unformat disk is recognized as two side
+               two_side = (valid_side != 1);
+               
                // fix write protect flag
                if(buffer[0x1a] != 0) {
                        buffer[0x1a] = 0x10;
index 45c712b..7e1f1a7 100644 (file)
@@ -186,6 +186,7 @@ public:
        bool write_protected;
        bool changed;
        uint8_t media_type;
+       bool two_side;
        int is_special_disk;
        
        // track
diff --git a/source/src/vm/fm16beta/CMakeLists.txt b/source/src/vm/fm16beta/CMakeLists.txt
new file mode 100644 (file)
index 0000000..72666ab
--- /dev/null
@@ -0,0 +1,34 @@
+cmake_minimum_required (VERSION 2.6)
+
+message("* vm/fm16beta")
+
+set(VM_FM16BETA_LIB_SRCS
+     cmos.cpp
+     keyboard.cpp
+     main.cpp
+     sub.cpp
+     fm16beta.cpp
+)
+
+if(USE_DEVICES_SHARED_LIB)
+else()
+       set(VM_FM16BETA_LIB_SRCS ${VM_FM16BETA_LIB_SRCS} 
+                                hd46505.cpp
+                                i8237.cpp
+                                i8251.cpp
+                                i8259.cpp
+                                mb8877.cpp
+                                mc6809.cpp
+                                mc6840.cpp
+                                msm58321.cpp
+                                pcm1bit.cpp
+                                
+                                disk.cpp
+                                
+                                memory.cpp
+                                io.cpp
+                                )
+endif()
+add_library(vm_fm16beta
+       ${VM_FM16BETA_LIB_SRCS}
+)
diff --git a/source/src/vm/fm16beta/cmos.cpp b/source/src/vm/fm16beta/cmos.cpp
new file mode 100644 (file)
index 0000000..544ac31
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+       FUJITSU FM16beta Emulator 'eFM16beta'
+
+       Author : Takeda.Toshiya
+       Date   : 2017.12.30-
+
+       [ cmos ]
+*/
+
+#include "cmos.h"
+
+void CMOS::initialize()
+{
+       // load cmos image
+       memset(cmos, 0, sizeof(cmos));
+       modified = false;
+       
+       FILEIO* fio = new FILEIO();
+       if(fio->Fopen(create_local_path(_T("CMOS.BIN")), FILEIO_READ_BINARY)) {
+               fio->Fread(cmos, sizeof(cmos), 1);
+               fio->Fclose();
+       }
+       delete fio;
+}
+
+void CMOS::release()
+{
+       if(modified) {
+               FILEIO* fio = new FILEIO();
+               if(fio->Fopen(create_local_path(_T("CMOS.BIN")), FILEIO_WRITE_BINARY)) {
+                       fio->Fwrite(cmos, sizeof(cmos), 1);
+                       fio->Fclose();
+               }
+               delete fio;
+       }
+}
+
+void CMOS::write_io8(uint32_t addr, uint32_t data)
+{
+       if(cmos[addr & 0x7ff] != data) {
+               cmos[addr & 0x7ff] = data;
+               modified = true;
+       }
+}
+
+uint32_t CMOS::read_io8(uint32_t addr)
+{
+       return cmos[addr & 0x7ff];
+}
+
+#define STATE_VERSION  1
+
+void CMOS::save_state(FILEIO* state_fio)
+{
+       state_fio->FputUint32(STATE_VERSION);
+       state_fio->FputInt32(this_device_id);
+       
+       state_fio->Fwrite(cmos, sizeof(cmos), 1);
+       state_fio->FputBool(modified);
+}
+
+bool CMOS::load_state(FILEIO* state_fio)
+{
+       if(state_fio->FgetUint32() != STATE_VERSION) {
+               return false;
+       }
+       if(state_fio->FgetInt32() != this_device_id) {
+               return false;
+       }
+       state_fio->Fread(cmos, sizeof(cmos), 1);
+       modified = state_fio->FgetBool();
+       return true;
+}
+
diff --git a/source/src/vm/fm16beta/cmos.h b/source/src/vm/fm16beta/cmos.h
new file mode 100644 (file)
index 0000000..2e5736b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+       FUJITSU FM16beta Emulator 'eFM16beta'
+
+       Author : Takeda.Toshiya
+       Date   : 2017.12.30-
+
+       [ cmos ]
+*/
+
+#ifndef _CMOS_H_
+#define _CMOS_H_
+
+#include "../vm.h"
+#include "../../emu.h"
+#include "../device.h"
+
+class CMOS : public DEVICE
+{
+private:
+       uint8_t cmos[0x800];
+       bool modified;
+       
+public:
+       CMOS(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+       {
+               set_device_name(_T("CMOS RAM"));
+       }
+       ~CMOS() {}
+       
+       // common functions
+       void initialize();
+       void release();
+       void write_io8(uint32_t addr, uint32_t data);
+       uint32_t read_io8(uint32_t addr);
+       void save_state(FILEIO* state_fio);
+       bool load_state(FILEIO* state_fio);
+};
+
+#endif
+
diff --git a/source/src/vm/fm16beta/fm16beta.cpp b/source/src/vm/fm16beta/fm16beta.cpp
new file mode 100644 (file)
index 0000000..ec0cc19
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+       FUJITSU FM16beta Emulator 'eFM16beta'
+
+       Author : Takeda.Toshiya
+       Date   : 2017.12.28-
+
+       [ virtual machine ]
+*/
+
+#include "fm16beta.h"
+#include "../../emu.h"
+#include "../device.h"
+#include "../event.h"
+
+#include "../disk.h"
+#include "../hd46505.h"
+#include "../i8237.h"
+#include "../i8251.h"
+#include "../i8259.h"
+#include "../i286.h"
+#include "../io.h"
+#include "../mb8877.h"
+#include "../mc6809.h"
+#include "../mc6840.h"
+#include "../msm58321.h"
+#include "../noise.h"
+#include "../pcm1bit.h"
+
+#ifdef USE_DEBUGGER
+#include "../debugger.h"
+#endif
+
+#include "cmos.h"
+#include "keyboard.h"
+#include "main.h"
+#include "sub.h"
+
+// ----------------------------------------------------------------------------
+// initialize
+// ----------------------------------------------------------------------------
+
+VM::VM(EMU* parent_emu) : emu(parent_emu)
+{
+       // create devices
+       first_device = last_device = NULL;
+       dummy = new DEVICE(this, emu);  // must be 1st device
+       event = new EVENT(this, emu);   // must be 2nd device
+       
+       crtc = new HD46505(this, emu);
+       cpu = new I286(this, emu);
+       io = new IO(this, emu);
+       dma = new I8237(this, emu);
+       sio = new I8251(this, emu);
+       pic = new I8259(this, emu);
+       fdc_2hd = new MB8877(this, emu);
+       fdc_2hd->set_context_noise_seek(new NOISE(this, emu));
+       fdc_2hd->set_context_noise_head_down(new NOISE(this, emu));
+       fdc_2hd->set_context_noise_head_up(new NOISE(this, emu));
+       fdc_2d = new MB8877(this, emu);
+       fdc_2d->set_context_noise_seek(new NOISE(this, emu));
+       fdc_2d->set_context_noise_head_down(new NOISE(this, emu));
+       fdc_2d->set_context_noise_head_up(new NOISE(this, emu));
+       subcpu = new MC6809(this, emu);
+       ptm = new MC6840(this, emu);
+       rtc = new MSM58321(this, emu);
+       pcm = new PCM1BIT(this, emu);
+
+       cmos = new CMOS(this, emu);
+       keyboard = new KEYBOARD(this, emu);
+       main = new MAIN(this, emu);
+       
+
+       
+       
+       
+       sub = new SUB(this, emu);
+       
+       // set contexts
+       event->set_context_cpu(cpu, 8000000);
+       event->set_context_cpu(subcpu, 2000000);
+       event->set_context_sound(pcm);
+       event->set_context_sound(fdc_2hd->get_context_noise_seek());
+       event->set_context_sound(fdc_2hd->get_context_noise_head_down());
+       event->set_context_sound(fdc_2hd->get_context_noise_head_up());
+       event->set_context_sound(fdc_2d->get_context_noise_seek());
+       event->set_context_sound(fdc_2d->get_context_noise_head_down());
+       event->set_context_sound(fdc_2d->get_context_noise_head_up());
+       
+       keyboard->set_context_main(main);
+#ifdef HAS_I286
+       main->set_context_cpu(cpu);
+#endif
+       main->set_context_dma(dma);
+       main->set_context_fdc_2hd(fdc_2hd);
+       main->set_context_fdc_2d(fdc_2d);
+       main->set_context_pic(pic);
+       main->set_context_pcm(pcm);
+       main->set_context_rtc(rtc);
+       main->set_context_sub(sub);
+       main->set_context_keyboard(keyboard);
+
+       dma->set_context_memory(main);
+       dma->set_context_ch0(fdc_2d);
+       dma->set_context_ch1(fdc_2hd);
+
+       sio->set_context_txrdy(main, SIG_MAIN_IRQ0_TX, 1);
+       sio->set_context_rxrdy(main, SIG_MAIN_IRQ0_RX, 1);
+       sio->set_context_syndet(main, SIG_MAIN_IRQ0_SYN, 1);
+
+       fdc_2hd->set_context_irq(main, SIG_MAIN_IRQ5, 1);
+       fdc_2hd->set_context_drq(main, SIG_MAIN_DRQ_2HD, 1);
+       fdc_2hd->set_context_drq(dma, SIG_I8237_CH1, 1);
+
+       fdc_2d->set_context_irq(main, SIG_MAIN_IRQ4, 1);
+       fdc_2d->set_context_drq(main, SIG_MAIN_DRQ_2D, 1);
+       fdc_2d->set_context_drq(dma, SIG_I8237_CH0, 1);
+
+       ptm->set_context_ch0(pcm, SIG_PCM1BIT_SIGNAL, 1);
+       ptm->set_context_irq(main, SIG_MAIN_IRQ8, 1);
+       ptm->set_internal_clock(19200); // temporary
+       ptm->set_external_clock(0, 19200);
+       ptm->set_external_clock(1, 19200);
+       ptm->set_external_clock(2, 19200);
+
+       rtc->set_context_data(main, SIG_MAIN_RTC_DATA, 0x0f, 0);
+       rtc->set_context_busy(main, SIG_MAIN_RTC_BUSY, 0x80);
+
+       crtc->set_context_disp(sub, SIG_SUB_DISP, 1);
+       crtc->set_context_vsync(sub, SIG_SUB_VSYNC, 1);
+       
+       sub->addr_max = 0x10000;
+       sub->bank_size = 0x80;
+       sub->set_context_crtc(crtc);
+       sub->set_chregs_ptr(crtc->get_regs());
+       sub->set_context_pcm(pcm);
+       sub->set_context_main(main);
+       sub->set_context_subcpu(subcpu);
+       sub->set_context_keyboard(keyboard);
+
+       // cpu bus
+       cpu->set_context_mem(main);
+       cpu->set_context_io(io);
+       cpu->set_context_intr(pic);
+#ifdef SINGLE_MODE_DMA
+       cpu->set_context_dma(dma);
+#endif
+       subcpu->set_context_mem(sub);
+#ifdef USE_DEBUGGER
+       cpu->set_context_debugger(new DEBUGGER(this, emu));
+       subcpu->set_context_debugger(new DEBUGGER(this, emu));
+#endif
+       
+       
+       // i/o bus
+       io->set_iomap_range_rw(0x0000, 0x0001, pic);
+       io->set_iomap_range_rw(0x0010, 0x001f, dma);
+       io->set_iomap_range_w(0x0020, 0x0023, main);    // dma bank regs
+#ifdef HAS_I286
+       io->set_iomap_single_rw(0x0060, main);          // reset
+#endif
+
+       io->set_iomap_range_rw(0xf000, 0xf7ff, cmos);
+       io->set_iomap_range_rw(0xfc80, 0xfcff, sub);    // shared ram
+
+       io->set_iomap_range_r(0xfd00, 0xfd01, keyboard);
+       io->set_iomap_range_rw(0xfd02, 0xfd05, main);
+
+       io->set_iomap_range_rw(0xfd06, 0xfd07, sio);
+
+       io->set_iomap_single_rw(0xfd0f, main);
+
+       io->set_iomap_range_rw(0xfd10, 0xfd11, main);
+
+       io->set_iomap_range_rw(0xfd18, 0xfd1b, fdc_2d);
+       io->set_iomap_range_rw(0xfd1c, 0xfd1f, main);
+
+       io->set_iomap_range_r(0xfd20, 0xfd22, sub);     // attention
+
+       io->set_iomap_single_rw(0xfd2c, main);
+
+       io->set_iomap_range_rw(0xfd30, 0xfd33, fdc_2hd);
+       io->set_iomap_range_rw(0xfd34, 0xfd37, main);
+
+       io->set_iomap_range_rw(0xfd38, 0xfd3f, ptm);
+       io->set_iomap_range_rw(0xfd98, 0xfd9f, sub);
+       io->set_iomap_single_w(0xfda0, sub);
+       io->set_iomap_single_r(0xfda0, main);
+
+       
+       // initialize all devices
+       for(DEVICE* device = first_device; device; device = device->next_device) {
+               device->initialize();
+       }
+       for(int i = 0; i < 4; i++) {
+               fdc_2hd->set_drive_type(i, DRIVE_TYPE_2HD);
+               fdc_2d->set_drive_type(i, DRIVE_TYPE_2D);
+       }
+       fdc_2hd->get_disk_handler(0)->drive_num = 0;
+       fdc_2hd->get_disk_handler(1)->drive_num = 1;
+       fdc_2d->get_disk_handler(0)->drive_num = 2;
+       fdc_2d->get_disk_handler(1)->drive_num = 3;
+}
+
+VM::~VM()
+{
+       // delete all devices
+       for(DEVICE* device = first_device; device;) {
+               DEVICE *next_device = device->next_device;
+               device->release();
+               delete device;
+               device = next_device;
+       }
+}
+
+DEVICE* VM::get_device(int id)
+{
+       for(DEVICE* device = first_device; device; device = device->next_device) {
+               if(device->this_device_id == id) {
+                       return device;
+               }
+       }
+       return NULL;
+}
+
+// ----------------------------------------------------------------------------
+// drive virtual machine
+// ----------------------------------------------------------------------------
+
+void VM::reset()
+{
+       // reset all devices
+       for(DEVICE* device = first_device; device; device = device->next_device) {
+               device->reset();
+       }
+
+       emu->out_debug_log(_T("----- RESET -----\n"));
+
+}
+
+void VM::run()
+{
+       event->drive();
+}
+
+// ----------------------------------------------------------------------------
+// debugger
+// ----------------------------------------------------------------------------
+
+#ifdef USE_DEBUGGER
+DEVICE *VM::get_cpu(int index)
+{
+       if(index == 0) {
+               return cpu;
+       } else if(index == 1) {
+               return subcpu;
+       }
+       return NULL;
+}
+#endif
+
+// ----------------------------------------------------------------------------
+// draw screen
+// ----------------------------------------------------------------------------
+
+void VM::draw_screen()
+{
+       sub->draw_screen();
+}
+
+// ----------------------------------------------------------------------------
+// soud manager
+// ----------------------------------------------------------------------------
+
+void VM::initialize_sound(int rate, int samples)
+{
+       // init sound manager
+       event->initialize_sound(rate, samples);
+       
+       // init sound gen
+       pcm->initialize_sound(rate, 8000);
+}
+
+uint16_t* VM::create_sound(int* extra_frames)
+{
+       return event->create_sound(extra_frames);
+}
+
+int VM::get_sound_buffer_ptr()
+{
+       return event->get_sound_buffer_ptr();
+}
+
+#ifdef USE_SOUND_VOLUME
+void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
+{
+       if(ch == 0) {
+               pcm->set_volume(0, decibel_l, decibel_r);
+       } else if(ch == 1) {
+               fdc_2hd->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
+               fdc_2hd->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
+               fdc_2hd->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
+               fdc_2d->get_context_noise_seek()->set_volume(0, decibel_l, decibel_r);
+               fdc_2d->get_context_noise_head_down()->set_volume(0, decibel_l, decibel_r);
+               fdc_2d->get_context_noise_head_up()->set_volume(0, decibel_l, decibel_r);
+       }
+}
+#endif
+
+// ----------------------------------------------------------------------------
+// notify key
+// ----------------------------------------------------------------------------
+
+void VM::key_down(int code, bool repeat)
+{
+       keyboard->key_down(code);
+}
+
+void VM::key_up(int code)
+{
+       keyboard->key_up(code);
+}
+
+// ----------------------------------------------------------------------------
+// user interface
+// ----------------------------------------------------------------------------
+
+void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
+{
+       if(drv < 2) {
+               fdc_2hd->open_disk(drv, file_path, bank);
+       } else if(drv < 4) {
+               fdc_2d->open_disk(drv - 2, file_path, bank);
+       }
+}
+
+void VM::close_floppy_disk(int drv)
+{
+       if(drv < 2) {
+               fdc_2hd->close_disk(drv);
+       } else if(drv < 4) {
+               fdc_2d->close_disk(drv - 2);
+       }
+}
+
+bool VM::is_floppy_disk_inserted(int drv)
+{
+       if(drv < 2) {
+               return fdc_2hd->is_disk_inserted(drv);
+       } else if(drv < 4) {
+               return fdc_2d->is_disk_inserted(drv - 2);
+       }
+       return false;
+}
+
+void VM::is_floppy_disk_protected(int drv, bool value)
+{
+       if(drv < 2) {
+               fdc_2hd->is_disk_protected(drv, value);
+       } else if(drv < 4) {
+               fdc_2d->is_disk_protected(drv - 2, value);
+       }
+}
+
+bool VM::is_floppy_disk_protected(int drv)
+{
+       if(drv < 2) {
+               return fdc_2hd->is_disk_protected(drv);
+       } else if(drv < 4) {
+               return fdc_2d->is_disk_protected(drv - 2);
+       }
+       return false;
+}
+
+uint32_t VM::is_floppy_disk_accessed()
+{
+       return (fdc_2hd->read_signal(0) & 3) | ((fdc_2d->read_signal(0) & 3) << 2);
+}
+
+bool VM::is_frame_skippable()
+{
+       return event->is_frame_skippable();
+}
+
+void VM::update_config()
+{
+       for(DEVICE* device = first_device; device; device = device->next_device) {
+               device->update_config();
+       }
+}
+
+#define STATE_VERSION  1
+
+void VM::save_state(FILEIO* state_fio)
+{
+       state_fio->FputUint32(STATE_VERSION);
+       
+       for(DEVICE* device = first_device; device; device = device->next_device) {
+               const char *name = typeid(*device).name() + 6; // skip "class "
+               
+               state_fio->FputInt32(strlen(name));
+               state_fio->Fwrite(name, strlen(name), 1);
+               device->save_state(state_fio);
+       }
+}
+
+bool VM::load_state(FILEIO* state_fio)
+{
+       if(state_fio->FgetUint32() != STATE_VERSION) {
+               return false;
+       }
+       for(DEVICE* device = first_device; device; device = device->next_device) {
+               const char *name = typeid(*device).name() + 6; // skip "class "
+               
+               if(!(state_fio->FgetInt32() == strlen(name) && state_fio->Fcompare(name, strlen(name)))) {
+                       return false;
+               }
+               if(!device->load_state(state_fio)) {
+                       return false;
+               }
+       }
+       return true;
+}
+
diff --git a/source/src/vm/fm16beta/fm16beta.h b/source/src/vm/fm16beta/fm16beta.h
new file mode 100644 (file)
index 0000000..40153b9
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+       FUJITSU FM16beta Emulator 'eFM16beta'
+
+       Author : Takeda.Toshiya
+       Date   : 2017.12.28-
+
+       [ virtual machine ]
+*/
+
+#ifndef _FM16BETA_H_
+#define _FM16BETA_H_
+
+#if defined(HAS_I286)
+#define DEVICE_NAME            "FUJITSU FM16beta (i286)"
+#define CONFIG_NAME            "fm16beta_i286"
+#else
+#define DEVICE_NAME            "FUJITSU FM16beta (i186)"
+#define CONFIG_NAME            "fm16beta_i186"
+#endif
+
+// device informations for virtual machine
+
+// TODO: check refresh rate
+#define FRAMES_PER_SEC         55.38
+#define LINES_PER_FRAME        440
+#define CHARS_PER_LINE         54
+#define HD46505_HORIZ_FREQ     (21052600.0 / 864)
+
+#define CPU_CLOCKS             8000000
+#define SCREEN_WIDTH           640
+#define SCREEN_HEIGHT          400
+#define WINDOW_HEIGHT_ASPECT   480
+#define MAX_DRIVE              4
+#define I8259_MAX_CHIPS                2
+#define SINGLE_MODE_DMA
+//#define MB8877_NO_BUSY_AFTER_SEEK
+
+#if defined(HAS_I286)
+#define MEMORY_ADDR_MAX                0x1000000       // 16MB
+#else
+#define MEMORY_ADDR_MAX                0x100000        // 1MB
+#endif
+#define MEMORY_BANK_SIZE       0x4000
+
+#define IO_ADDR_MAX            0x10000
+
+// device informations for win32
+#define USE_FD1
+#define USE_FD2
+#define USE_FD3
+#define USE_FD4
+#define NOTIFY_KEY_DOWN
+#define USE_SHIFT_NUMPAD_KEY
+#define USE_ALT_F10_KEY
+#define USE_AUTO_KEY           5
+#define USE_AUTO_KEY_RELEASE   6
+#define USE_AUTO_KEY_NUMPAD
+#define USE_SCREEN_FILTER
+#define USE_SOUND_VOLUME       2
+#define USE_DEBUGGER
+#define USE_STATE
+
+#include "../../common.h"
+#include "../../fileio.h"
+
+#ifdef USE_SOUND_VOLUME
+static const _TCHAR *sound_device_caption[] = {
+       _T("Beep"), _T("Noise (FDD)"),
+};
+#endif
+
+class EMU;
+class DEVICE;
+class EVENT;
+
+class HD46505;
+class I8237;
+class I8251;
+class I8259;
+class I286;
+class IO;
+class MB8877;
+class MC6809;
+class MC6840;
+class MSM58321;
+class PCM1BIT;
+
+class CMOS;
+class KEYBOARD;
+class MAIN;
+class SUB;
+
+class VM
+{
+protected:
+       EMU* emu;
+       
+       // devices
+       EVENT* event;
+       
+       HD46505* crtc;
+       I8237* dma;
+       I8251* sio;
+       I8259* pic;
+       I286* cpu;
+       IO* io;
+       MB8877* fdc_2hd;
+       MB8877* fdc_2d;
+       MC6809* subcpu;
+       MC6840* ptm;
+       MSM58321* rtc;
+       PCM1BIT* pcm;
+       
+       CMOS* cmos;
+       MAIN* main;
+       KEYBOARD* keyboard;
+       SUB* sub;
+       
+public:
+       // ----------------------------------------
+       // initialize
+       // ----------------------------------------
+       
+       VM(EMU* parent_emu);
+       ~VM();
+       
+       // ----------------------------------------
+       // for emulation class
+       // ----------------------------------------
+       
+       // drive virtual machine
+       void reset();
+       void notify_power_off();
+       void run();
+       
+#ifdef USE_DEBUGGER
+       // debugger
+       DEVICE *get_cpu(int index);
+#endif
+       
+       // draw screen
+       void draw_screen();
+       
+       // sound generation
+       void initialize_sound(int rate, int samples);
+       uint16_t* create_sound(int* extra_frames);
+       int get_sound_buffer_ptr();
+#ifdef USE_SOUND_VOLUME
+       void set_sound_device_volume(int ch, int decibel_l, int decibel_r);
+#endif
+       
+       // notify key
+       void key_down(int code, bool repeat);
+       void key_up(int code);
+       
+       // user interface
+       void open_floppy_disk(int drv, const _TCHAR* file_path, int bank);
+       void close_floppy_disk(int drv);
+       bool is_floppy_disk_inserted(int drv);
+       void is_floppy_disk_protected(int drv, bool value);
+       bool is_floppy_disk_protected(int drv);
+       uint32_t is_floppy_disk_accessed();
+       bool is_frame_skippable();
+       
+       void update_config();
+       void save_state(FILEIO* state_fio);
+       bool load_state(FILEIO* state_fio);
+       
+       // ----------------------------------------
+       // for each device
+       // ----------------------------------------
+       
+       // devices
+       DEVICE* get_device(int id);
+       DEVICE* dummy;
+       DEVICE* first_device;
+       DEVICE* last_device;
+};
+
+#endif
diff --git a/source/src/vm/fm16beta/keyboard.cpp b/source/src/vm/fm16beta/keyboard.cpp
new file mode 100644 (file)
index 0000000..bf57ac2
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+       FUJITSU FM16beta Emulator 'eFM16beta'
+
+       Author : Takeda.Toshiya
+       Date   : 2018.01.01 -
+
+       [ keyboard ]
+*/
+
+#include "keyboard.h"
+#include "main.h"
+#include "../../fifo.h"
+
+
+void KEYBOARD::initialize()
+{
+       key_buf = new FIFO(64);
+       register_frame_event(this);
+}
+
+void KEYBOARD::release()
+{
+       key_buf->release();
+       delete key_buf;
+}
+
+void KEYBOARD::reset()
+{
+       memset(table, 0, sizeof(table));
+       key_buf->clear();
+       kbstat = kbdata = 0;
+}
+
+uint32_t KEYBOARD::read_io8(uint32_t addr)
+{
+       if(addr & 1) {
+               d_main->write_signal(SIG_MAIN_IRQ1, 0, 0);
+               kbstat &= ~1;
+               return kbdata & 0xff;
+       } else {
+               return kbdata >> 8;
+       }
+}
+
+void KEYBOARD::event_frame()
+{
+       if(!(kbstat & 1) && !key_buf->empty()) {
+               d_main->write_signal(SIG_MAIN_IRQ1, 1, 1);
+               kbstat |= 1;
+               kbdata = key_buf->read();
+       }
+}
+
+void KEYBOARD::key_down(int code)
+{
+//     if(!table[code]) {
+               table[code] = 1;
+               if(code = key_table[code]) {
+//code=0x20;
+                       key_buf->write(code);
+               }
+//     }
+}
+
+void KEYBOARD::key_up(int code)
+{
+//     if(table[code]) {
+               table[code] = 0;
+               if(code = key_table[code]) {
+//code=0x20;
+                       key_buf->write(code| 0x80);
+               }
+//     }
+}
+
+#define STATE_VERSION  1
+
+void KEYBOARD::save_state(FILEIO* state_fio)
+{
+       state_fio->FputUint32(STATE_VERSION);
+       state_fio->FputInt32(this_device_id);
+       
+       key_buf->save_state((void *)state_fio);
+       state_fio->FputInt32(kbstat);
+       state_fio->FputInt32(kbdata);
+       state_fio->Fwrite(table, sizeof(table), 1);
+}
+
+bool KEYBOARD::load_state(FILEIO* state_fio)
+{
+       if(state_fio->FgetUint32() != STATE_VERSION) {
+               return false;
+       }
+       if(state_fio->FgetInt32() != this_device_id) {
+               return false;
+       }
+       if(!key_buf->load_state((void *)state_fio)) {
+               return false;
+       }
+       kbstat = state_fio->FgetInt32();
+       kbdata = state_fio->FgetInt32();
+       state_fio->Fread(table, sizeof(table), 1);
+       return true;
+}
+
+static const int key_code[] = {
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x008,  0x009,  -1,     -1,     -1,     0x00D,  -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x10B,  -1,     0x01B,  0x10D,  0x10E,  -1,     -1,
+0x020, 0x112,  0x113,  0x111,  0x115,  0x118,  0x116,  0x119,  0x117,  -1,     -1,     -1,     -1,     0x110,  0x114,  -1,
+0x030, 0x031,  0x032,  0x033,  0x034,  0x035,  0x036,  0x037,  0x038,  0x039,  -1,     -1,     -1,     -1,     -1,     -1,
+-1,    0x061,  0x062,  0x063,  0x064,  0x065,  0x066,  0x067,  0x068,  0x069,  0x06A,  0x06B,  0x06C,  0x06D,  0x06E,  0x06F,
+0x070, 0x071,  0x072,  0x073,  0x074,  0x075,  0x076,  0x077,  0x078,  0x079,  0x07A,  -1,     -1,     -1,     -1,     -1,
+0x030, 0x031,  0x032,  0x033,  0x034,  0x035,  0x036,  0x037,  0x038,  0x039,  0x02A,  0x02B,  0x02C,  0x02D,  0x02E,  0x02F,
+0x101, 0x102,  0x103,  0x104,  0x105,  0x106,  0x107,  0x108,  0x109,  0x10A,  0x10B,  0x10C,  -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x03A,  0x03B,  0x02C,  0x02D,  0x02E,  0x02F,
+0x040, -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x05B,  0x05C,  0x05D,  0x05E,  -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+};
+static const int key_code_shift[] = {
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x008,  0x009,  -1,     -1,     -1,     0x00D,  -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x12B,  -1,     0x01B,  0x12D,  0x12E,  -1,     -1,
+0x020, 0x132,  0x133,  0x131,  0x135,  0x138,  0x136,  0x139,  0x137,  -1,     -1,     -1,     -1,     0x130,  0x134,  -1,
+-1,    0x021,  0x022,  0x023,  0x024,  0x025,  0x026,  0x027,  0x028,  0x029,  -1,     -1,     -1,     -1,     -1,     -1,
+-1,    0x041,  0x042,  0x043,  0x044,  0x045,  0x046,  0x047,  0x048,  0x049,  0x04A,  0x04B,  0x04C,  0x04D,  0x04E,  0x04F,
+0x050, 0x051,  0x052,  0x053,  0x054,  0x055,  0x056,  0x057,  0x058,  0x059,  0x05A,  -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+0x121, 0x122,  0x123,  0x124,  0x125,  0x126,  0x127,  0x128,  0x129,  0x12A,  0x12B,  0x12C,  -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x02B,  0x02A,  0x03C,  0x03D,  0x03E,  0x03F,
+0x060, -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x07B,  0x07C,  0x07D,  0x07E,  -1,
+-1,    -1,     0x05F,  -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+};
+static const int key_code_kana[] = {
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x008,  0x009,  -1,     -1,     -1,     0x00D,  -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x10B,  -1,     0x01B,  0x10D,  0x10E,  -1,     -1,
+0x020, 0x112,  0x113,  0x111,  0x115,  0x118,  0x116,  0x119,  0x117,  -1,     -1,     -1,     -1,     0x110,  0x114,  -1,
+0x0DC, 0x0C7,  0x0CC,  0x0B1,  0x0B3,  0x0B4,  0x0B5,  0x0D4,  0x0D5,  0x0D6,  -1,     -1,     -1,     -1,     -1,     -1,
+-1,    0x0C1,  0x0BA,  0x0BF,  0x0BC,  0x0B2,  0x0CA,  0x0B7,  0x0B8,  0x0C6,  0x0C9,  0x0C9,  0x0D8,  0x0D3,  0x0D0,  0x0D7,
+0x0BE, 0x0C0,  0x0BD,  0x0C4,  0x0B6,  0x0C5,  0x0CB,  0x0C3,  0x0BB,  0x0DD,  0x0C2,  -1,     -1,     -1,     -1,     -1,
+0x030, 0x031,  0x032,  0x033,  0x034,  0x035,  0x036,  0x037,  0x038,  0x039,  0x02A,  0x02B,  0x02C,  0x02D,  0x02E,  0x02F,
+0x101, 0x102,  0x103,  0x104,  0x105,  0x106,  0x107,  0x108,  0x109,  0x10A,  0x10B,  0x10C,  -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x0B9,  0x0DA,  0x0C8,  0x0CE,  0x0D9,  0x0D2,
+0x0DE, -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x0DF,  0x0B0,  0x0D1,  0x0CD,  -1,
+-1,    -1,     0x0DB,  -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+};
+static const int key_code_kana_shift[] = {
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x008,  0x009,  -1,     -1,     -1,     0x00D,  -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x12B,  -1,     0x01B,  0x12D,  0x12E,  -1,     -1,
+0x020, 0x132,  0x133,  0x131,  0x135,  0x138,  0x136,  0x139,  0x137,  -1,     -1,     -1,     -1,     0x130,  0x134,  -1,
+0x0A6, -1,     -1,     0x0A7,  0x0A9,  0x0AA,  0x0AB,  0x0AC,  0x0AD,  0x0AE,  -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     0x0A8,  -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x0AF,  -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+0x121, 0x122,  0x123,  0x124,  0x125,  0x126,  0x127,  0x128,  0x129,  0x12A,  0x12B,  0x12C,  -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x0A4,  -1,     0x0A1,  0x0A5,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x0A2,  -1,     0x0A3,  -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+};
+static const int key_code_graph[] = {
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x008,  0x009,  -1,     -1,     -1,     0x00D,  -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x10B,  -1,     0x01B,  0x10D,  0x10E,  -1,     -1,
+0x020, 0x112,  0x113,  0x111,  0x115,  0x118,  0x116,  0x119,  0x117,  -1,     -1,     -1,     -1,     0x110,  0x114,  -1,
+0x0F7, 0x0F9,  0x0FA,  0x0FB,  0x0FC,  0x0F2,  0x0F3,  0x0F4,  0x0F5,  0x0F6,  -1,     -1,     -1,     -1,     -1,     -1,
+-1,    0x095,  0x084,  0x082,  0x0E6,  0x0E4,  0x0E7,  0x09E,  0x09F,  0x0E8,  0x0EA,  0x0EB,  0x08E,  0x086,  0x085,  0x0E9,
+0x08D, 0x0FD,  0x0E5,  0x096,  0x09C,  0x0F0,  0x083,  0x0F8,  0x081,  0x09D,  0x080,  -1,     -1,     -1,     -1,     -1,
+-1,    0x09A,  0x090,  0x09B,  0x093,  0x080,  0x092,  0x0E1,  0x0E2,  0x0E3,  0x098,  0x099,  -1,     0x0EE,  -1,     0x091,
+0x101, 0x102,  0x103,  0x104,  0x105,  0x106,  0x107,  0x108,  0x109,  0x10A,  0x10B,  0x10C,  -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x094,  0x089,  0x087,  0x08C,  0x088,  0x097,
+0x08A, -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x0ED,  0x0F1,  0x0EC,  0x08B,  -1,
+-1,    -1,     0x0E0,  -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+};
+static const int key_code_graph_shift[] = {
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x008,  0x009,  -1,     -1,     -1,     0x00D,  -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x12B,  -1,     0x01B,  0x12D,  0x12E,  -1,     -1,
+0x020, 0x132,  0x133,  0x131,  0x135,  0x138,  0x136,  0x139,  0x137,  -1,     -1,     -1,     -1,     0x130,  0x134,  -1,
+0x0F7, 0x0F9,  0x0FA,  0x0FB,  0x0FC,  0x0F2,  0x0F3,  0x0F4,  0x0F5,  0x0F6,  -1,     -1,     -1,     -1,     -1,     -1,
+-1,    0x095,  0x084,  0x082,  0x0E6,  0x0E4,  0x0E7,  0x09E,  0x09F,  0x0E8,  0x0EA,  0x0EB,  0x08E,  0x086,  0x085,  0x0E9,
+0x08D, 0x0FD,  0x0E5,  0x096,  0x09C,  0x0F0,  0x083,  0x0F8,  0x081,  0x09D,  0x080,  -1,     -1,     -1,     -1,     -1,
+-1,    0x09A,  0x090,  0x09B,  0x093,  0x080,  0x092,  0x0E1,  0x0E2,  0x0E3,  0x098,  0x099,  -1,     0x0EE,  -1,     0x091,
+0x101, 0x102,  0x103,  0x104,  0x105,  0x106,  0x107,  0x108,  0x109,  0x10A,  0x10B,  0x10C,  -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x094,  0x089,  0x087,  0x08C,  0x088,  0x097,
+0x08A, -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x0ED,  0x0F1,  0x0EC,  0x08B,  -1,
+-1,    -1,     0x0E0,  -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+};
+static const int key_code_ctrl[] = {
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x14B,  -1,     -1,     0x14D,  0x14E,  -1,     -1,
+-1,    0x152,  0x153,  0x151,  0x155,  0x158,  0x156,  0x159,  0x157,  -1,     -1,     -1,     -1,     0x150,  0x154,  -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    0x001,  0x002,  0x003,  0x004,  0x005,  0x006,  0x007,  0x008,  0x009,  0x00A,  0x00B,  0x00C,  0x00D,  0x00E,  0x00F,
+0x010, 0x011,  0x012,  0x013,  0x014,  0x015,  0x016,  0x017,  0x018,  0x109,  0x01A,  -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+0x141, 0x142,  0x143,  0x144,  0x145,  0x146,  0x147,  0x148,  0x149,  0x14A,  0x14B,  0x14C,  -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+0x000, -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x01B,  0x01C,  0x01D,  0x01E,  -1,
+-1,    -1,     0x01F,  -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+};
+static const int scan_code[] = {
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x0F,   0x10,   -1,     -1,     -1,     0x1D,   -1,     -1,
+0x53,  0x52,   0x56,   -1,     0x55,   0x5A,   -1,     -1,     -1,     0x59,   -1,     0x01,   0x58,   0x57,   -1,     -1,
+0x35,  0x49,   0x4C,   0x4A,   0x4E,   0x4F,   0x4D,   0x51,   0x50,   -1,     -1,     -1,     -1,     0x48,   0x4B,   -1,
+0x0B,  0x02,   0x03,   0x04,   0x05,   0x06,   0x07,   0x08,   0x09,   0x0A,   -1,     -1,     -1,     -1,     -1,     -1,
+-1,    0x1E,   0x2E,   0x2C,   0x20,   0x13,   0x21,   0x22,   0x23,   0x18,   0x24,   0x25,   0x26,   0x30,   0x2F,   0x19,
+0x1A,  0x11,   0x14,   0x1F,   0x15,   0x17,   0x2D,   0x12,   0x2B,   0x16,   0x2A,   -1,     -1,     -1,     -1,     -1,
+0x46,  0x42,   0x43,   0x44,   0x3E,   0x3F,   0x40,   0x3A,   0x3B,   0x3C,   0x36,   0x38,   0x41,   0x39,   0x47,   0x37,
+0x5D,  0x5E,   0x5F,   0x60,   0x61,   0x62,   0x63,   0x64,   0x65,   0x66,   0x59,   0x5B,   -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x28,   0x27,   0x31,   0x0C,   0x32,   0x33,
+0x1B,  -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     0x1C,   0x0E,   0x29,   0x0D,   -1,
+-1,    -1,     0x34,   -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+-1,    -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
+};
diff --git a/source/src/vm/fm16beta/keyboard.h b/source/src/vm/fm16beta/keyboard.h
new file mode 100644 (file)
index 0000000..ca67d9b
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+       FUJITSU FM16beta Emulator 'eFM16beta'
+
+       Author : Takeda.Toshiya
+       Date   : 2018.01.01 -
+
+       [ keyboard ]
+*/
+
+#ifndef _KEYBOARD_H_
+#define _KEYBOARD_H_
+
+#include "../vm.h"
+#include "../../emu.h"
+#include "../device.h"
+
+#define SIG_KEYBOARD_INSLED    0
+
+/*
+       \82Ð\82ç\82ª\82È/\83\8d\81[\83}\8e\9a       \82Ð\82ç\82ª\82È
+       \94¼\8ap/\91S\8ap               \94¼\8ap/\91S\8ap
+       \95Ï\8a·                    \95Ï\8a·
+       \96³\95Ï\8a·                  \96³\95Ï\8a·
+       \82©\82È/\8a¿\8e\9a
+       \83J\83^\83J\83i
+       \91O\8ds                    PgUp
+       \8e\9f\8ds                    PgDn
+       \8eÀ\8ds                    F12
+       \8eæ\8fÁ                    F11
+       COPY
+*/
+
+static const int key_table[256] = {
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x10,0x00,0x00,0x00,0x1D,0x00,0x00,
+       0x53,0x52,0x00,0x7C,0x55,0x52,0x00,0x00,0x00,0x71,0x00,0x01,0x58,0x57,0x00,0x00,
+       0x35,0x6E,0x70,0x00,0x4E,0x4F,0x4D,0x51,0x50,0x00,0x00,0x00,0x00,0x48,0x4B,0x00,
+       0x0B,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,
+       0x00,0x1E,0x2E,0x2C,0x20,0x13,0x21,0x22,0x23,0x18,0x24,0x25,0x26,0x30,0x2F,0x19,
+       0x1A,0x11,0x14,0x1F,0x15,0x17,0x2D,0x12,0x2B,0x16,0x2A,0x00,0x00,0x00,0x00,0x00,
+       0x46,0x42,0x43,0x44,0x3E,0x3F,0x40,0x3A,0x3B,0x3C,0x36,0x38,0x00,0x39,0x47,0x37,
+       0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x72,0x73,0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+       0x00,0x7D,0x6B,0x6C,0x6D,0x57,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x27,0x31,0x0C,0x32,0x33,
+       0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x0E,0x29,0x0D,0x00,
+       0x00,0x00,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+class FIFO;
+
+class KEYBOARD : public DEVICE
+{
+private:
+       DEVICE* d_main;
+       
+       FIFO *key_buf;
+       int kbstat, kbdata;
+       uint8_t table[256];
+       
+public:
+       KEYBOARD(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+       {
+               set_device_name(_T("Keyboard"));
+       }
+       ~KEYBOARD() {}
+       
+       // common functions
+       void initialize();
+       void release();
+       void reset();
+       uint32_t read_io8(uint32_t addr);
+       void event_frame();
+       void save_state(FILEIO* state_fio);
+       bool load_state(FILEIO* state_fio);
+       
+       // unique functions
+       void set_context_main(DEVICE* device)
+       {
+               d_main = device;
+       }
+       void key_down(int code);
+       void key_up(int code);
+};
+
+#endif
diff --git a/source/src/vm/fm16beta/main.cpp b/source/src/vm/fm16beta/main.cpp
new file mode 100644 (file)
index 0000000..098287f
--- /dev/null
@@ -0,0 +1,441 @@
+/*
+       FUJITSU FM16beta Emulator 'eFM16beta'
+
+       Author : Takeda.Toshiya
+       Date   : 2017.12.28-
+
+       [ main system ]
+*/
+
+#include "main.h"
+#include "sub.h"
+#include "keyboard.h"
+#include "../disk.h"
+#include "../i8237.h"
+#include "../i8259.h"
+#include "../mb8877.h"
+#include "../msm58321.h"
+#include "../pcm1bit.h"
+
+void MAIN::initialize()
+{
+       MEMORY::initialize();
+       
+       memset(ram, 0x00, sizeof(ram));
+       memset(rom, 0xff, sizeof(rom));
+       direct = 0;
+       
+       read_bios(_T("IPL.ROM"), rom, sizeof(rom));
+       
+       set_memory_rw(0x00000, 0xfbfff, ram);
+       set_memory_r(0xfc000, 0xfffff, rom);
+       
+       // main-sub
+//     sub_busy = false;
+       
+       // 1mb fdd
+       sidereg_2hd = 0;        // side 0
+       drvreg_2hd = 0;         // drive #0, motor on
+       drq_2hd = false;
+       d_fdc_2hd->write_signal(SIG_MB8877_MOTOR, 1, 1);
+       d_fdc_2hd->write_signal(SIG_MB8877_DRIVEREG, 0, 3);
+       
+       // 320kb fdd
+       sidereg_2d = 0;         // side 0
+       drvreg_2d = 0x80;       // drive #0, motor on
+       drq_2d = false;
+       d_fdc_2d->write_signal(SIG_MB8877_MOTOR, 1, 1);
+       d_fdc_2d->write_signal(SIG_MB8877_DRIVEREG, 0, 3);
+       
+       // rtc
+       rtc_data = 0;
+       
+       // irq
+       irq_enb = ext_irq_enb = 0;
+       irq0_tx = irq0_rx = irq0_syn = irq1 = irq2 = irq3 = irq4 = irq5 = irq6 = irq7 = irq8 = irq9 = false;
+       firq0 = firq1 = firq2 = firq3 = false;
+       int0 = int1 = int2 = int3 = int4 = int5 = int6 = int7 = false;
+}
+
+void MAIN::release()
+{
+       MEMORY::release();
+}
+
+void MAIN::reset()
+{
+       MEMORY::reset();
+       
+#ifdef HAS_I286
+       d_dma->set_address_mask(0x000fffff);
+       d_cpu->set_address_mask(0x000fffff);
+       rst = 0x00;
+#endif
+       
+       
+       d_pcm->write_signal(SIG_PCM1BIT_ON, 0, 0);
+}
+
+void MAIN::write_io8(uint32_t addr, uint32_t data)
+{
+       uint8_t change;
+       
+       switch(addr) {
+       case 0x0020:
+               d_dma->write_signal(SIG_I8237_BANK0, data, 0xff);
+               break;
+       case 0x0021:
+               d_dma->write_signal(SIG_I8237_BANK1, data, 0xff);
+               break;
+       case 0x0022:
+               d_dma->write_signal(SIG_I8237_BANK2, data, 0xff);
+               break;
+       case 0x0023:
+               d_dma->write_signal(SIG_I8237_BANK3, data, 0xff);
+               break;
+
+
+#ifdef HAS_I286
+       case 0x0060:
+               if((data & 0xc0) == 0x40) {
+                       d_cpu->reset();
+                       rst |= 0x01;
+               }
+               if(data & 0x01) {
+                       d_dma->set_address_mask(0x00ffffff);
+                       d_cpu->set_address_mask(0x00ffffff);
+               } else {
+                       d_dma->set_address_mask(0x000fffff);
+                       d_cpu->set_address_mask(0x000fffff);
+               }
+               break;
+#endif
+       case 0xfd02:
+               change = irq_enb ^ data;
+               irq_enb = data;
+               if(change & 0x01) update_int7();        // Printer
+               if(change & 0x0e) update_int4();        // RS-232C
+               if(change & 0x10) update_int0();        // PTM
+               if(change & 0x20) update_int6();        // 320KB FDD
+               if(change & 0x80) update_int1();        // Keyboard
+               break;
+       case 0xfd03:
+               d_pcm->write_signal(SIG_PCM1BIT_ON, data, 0x80);
+               break;
+
+       case 0xfd04:
+               d_sub->write_signal(SIG_SUB_MAINACK, 1, 1);
+               break;
+
+       case 0xfd05:
+               d_sub->write_signal(SIG_SUB_HALT, data, 0x80);
+               d_sub->write_signal(SIG_SUB_CANCEL, data, 0x40);
+               break;
+
+       case 0xfd0f:
+               change = direct ^ data;
+               direct = data;
+               if(change & 0x80) {
+                       if(direct & 0x80) {
+                               set_memory_mapped_io_rw(0xc0000, 0xcffff, d_sub);
+                       } else {
+                               set_memory_rw(0xc0000, 0xcffff, ram + 0xc0000);
+                       }
+               }
+               d_keyboard->write_signal(SIG_KEYBOARD_INSLED, data, 0x02);
+               break;
+       case 0xfd10:
+               d_rtc->write_signal(SIG_MSM58321_DATA, data, 0x0f);
+               break;
+       case 0xfd11:
+               d_rtc->write_signal(SIG_MSM58321_CS, data, 0x80);
+               d_rtc->write_signal(SIG_MSM58321_READ, data, 0x04);
+               d_rtc->write_signal(SIG_MSM58321_WRITE, data, 0x02);
+               d_rtc->write_signal(SIG_MSM58321_ADDR_WRITE, data, 0x01);
+               break;
+
+       case 0xfd1c:
+               d_fdc_2d->write_signal(SIG_MB8877_SIDEREG, data, 0x01);
+               sidereg_2d = data;
+               break;
+       case 0xfd1d:
+               d_fdc_2d->write_signal(SIG_MB8877_MOTOR, data, 0x80);
+               d_fdc_2d->write_signal(SIG_MB8877_DRIVEREG, data, 0x03);
+               drvreg_2d = data;
+               break;
+
+
+       case 0xfd2c:
+               change = ext_irq_enb ^ data;
+               ext_irq_enb = data;
+               if(change & 0x08) update_int2();        // 1MB FDD
+               break;
+
+       case 0xfd34:
+               d_fdc_2hd->write_signal(SIG_MB8877_SIDEREG, data, 0x01);
+               sidereg_2hd = data;
+               break;
+       case 0xfd35:
+               d_fdc_2hd->write_signal(SIG_MB8877_MOTOR, ~data, 0x80);
+               d_fdc_2hd->write_signal(SIG_MB8877_DRIVEREG, data, 0x03);
+               drvreg_2hd = data;
+               break;
+
+       }
+}
+
+uint32_t MAIN::read_io8(uint32_t addr)
+{
+       switch(addr) {
+#ifdef HAS_I286
+       case 0x0060:
+               {
+                       uint8_t val = rst | (d_cpu->get_shutdown_flag() << 1);
+                       rst = 0;
+                       d_cpu->set_shutdown_flag(0);
+                       return val;
+               }
+#endif
+       case 0xfd03:
+               return (irq8 ? 0x01 : 0) | (irq7 ? 0x02 : 0) | (irq4 ? 0x08 : 0) | (irq3 ? 0x10 : 0) | (irq2 ? 0x20 : 0) | (irq1 ? 0x40 : 0) | (irq0_tx || irq0_rx || irq0_syn ? 0x80 : 0);
+
+
+       case 0xfd04:
+               return (firq0 ? 0x01 : 0) | (firq1 ? 0x02 : 0) | (firq2 ? 0x80 : 0);
+
+       case 0xfd05:
+               return (sub_busy ? 0x80 : 0);
+
+       case 0xfd0f:
+               return direct;
+
+       case 0xfd10:
+               return rtc_data;
+
+       case 0xfd1c:
+               return sidereg_2d;
+       case 0xfd1d:
+               return drvreg_2d;
+       case 0xfd1f:
+               return (irq4 ? 0x40 : 0) | (drq_2d ? 0x80 : 0);
+
+       case 0xfd2c:
+               return (irq6 ? 0x04 : 0) | (irq5 ? 0x40 : 0);
+
+       case 0xfd34:
+               return sidereg_2hd;
+       case 0xfd35:
+               return drvreg_2hd;
+       case 0xfd36:
+               {
+                       uint8_t val = 0x40; // DSNS=1
+                       if(d_fdc_2hd->read_signal(SIG_MB8877_MOTOR)) {
+                               for(int i = 0; i < 4; i++) {
+                                       if(d_fdc_2hd->is_disk_inserted(i)) {
+                                               val |= 1 << i;
+                                       }
+                               }
+                       }
+                       DISK *disk = d_fdc_2hd->get_disk_handler(drvreg_2hd & 3);
+                       if(disk->get_rpm() == 300) {
+                               val |= 0x20;
+                       }
+                       if(disk->inserted && disk->two_side) {
+                               val |= 0x80;
+                       }
+                       return val;
+               }
+       case 0xfd37:
+               return (irq5 ? 0x40 : 0) | (drq_2hd ? 0x80 : 0);
+
+//     case 0xfda0:
+
+       }
+       return 0xff;
+}
+
+void MAIN::write_signal(int id, uint32_t data, uint32_t mask)
+{
+       if(id == SIG_MAIN_IRQ0_TX) {
+               irq0_tx = ((data & mask) != 0);
+               update_int4();
+       } else if(id == SIG_MAIN_IRQ0_RX) {
+               irq0_rx = ((data & mask) != 0);
+               update_int4();
+       } else if(id == SIG_MAIN_IRQ0_SYN) {
+               irq0_syn = ((data & mask) != 0);
+               update_int4();
+       } else if(id == SIG_MAIN_IRQ1) {
+               if(!(irq_enb & 0x80)) {
+                       d_sub->write_signal(SIG_SUB_KEY, data, mask);
+               }
+               irq1 = ((data & mask) != 0);
+               update_int1();
+       } else if(id == SIG_MAIN_IRQ2) {
+               irq2 = ((data & mask) != 0);
+               update_int5();
+       } else if(id == SIG_MAIN_IRQ3) {
+               irq3 = ((data & mask) != 0); // dma
+//             update_int*();
+       } else if(id == SIG_MAIN_IRQ4) {
+               irq4 = ((data & mask) != 0);
+               update_int6();
+       } else if(id == SIG_MAIN_IRQ5) {
+               irq5 = ((data & mask) != 0);
+               update_int2();
+       } else if(id == SIG_MAIN_IRQ6) {
+               irq6 = ((data & mask) != 0);
+               update_int2();
+       } else if(id == SIG_MAIN_IRQ7) {
+               irq7 = ((data & mask) != 0);
+               update_int6();
+       } else if(id == SIG_MAIN_IRQ8) {
+               irq8 = ((data & mask) != 0);
+               update_int0();
+       } else if(id == SIG_MAIN_IRQ9) {
+               irq9 = ((data & mask) != 0);
+               update_int5();
+       } else if(id == SIG_MAIN_FIRQ0) {
+               firq0 = ((data & mask) != 0);
+               update_int3();
+       } else if(id == SIG_MAIN_FIRQ1) {
+               firq1 = ((data & mask) != 0);
+               update_int1();
+       } else if(id == SIG_MAIN_FIRQ2) {
+               firq2 = ((data & mask) != 0);
+               update_int3();
+       } else if(id == SIG_MAIN_FIRQ3) {
+               firq3 = ((data & mask) != 0);
+               update_int3();
+       } else if(id == SIG_MAIN_SUB_BUSY) {
+               sub_busy = ((data & mask) != 0);
+
+this->out_debug_log("SUB -> MAIN: SUB BUSY = %d\n", sub_busy);
+
+       } else if(id == SIG_MAIN_DRQ_2HD) {
+               drq_2hd = ((data & mask) != 0);
+       } else if(id == SIG_MAIN_DRQ_2D) {
+               drq_2d = ((data & mask) != 0);
+       } else if(id == SIG_MAIN_RTC_DATA) {
+               rtc_data = (data & mask) | (rtc_data & ~mask);
+       } else if(id == SIG_MAIN_RTC_BUSY) {
+               rtc_data = (data & mask) | (rtc_data & ~mask);
+       }
+}
+
+/*
+IRQ8                   -> INT0
+       IRQ8: \83^\83C\83}\81[
+IRQ1 + FIRQ1           -> INT1
+       IRQ1: \83L\81[\83{\81[\83h
+       FIRQ1: BREAK\83L\81[
+IRQ5 + IRQ6            -> INT2
+       IRQ5: IMB\83t\83\8d\83b\83s\83B\83f\83B\83X\83N
+       IRQ6: \83n\81[\83h\83f\83B\83X\83N
+FIRQ0 + FIRQ2 + FIRQ3  -> INT3
+       FIRQ0: SUB\83A\83e\83\93\83V\83\87\83\93
+       FIRQ2: \8ag\92£
+       FIRQ3: \83\86\81[\83U\97p
+IRQ0                   -> INT4
+       IRQ0: RS-232C
+IRQ2 + IRQ9 + INTNDP   -> INT5
+       IRQ2: \8ag\92£
+       IRQ9: \83\86\81[\83U\97p
+IRQ4                   -> INT6
+       IRQ4: 320KB\83t\83\8d\83b\83s\83B\83f\83B\83X\83N
+IRQ7                   -> INT7
+       IRQ7: \83v\83\8a\83\93\83^
+*/
+
+void MAIN::update_int0()
+{
+//     bool prev = int0;
+       int0 = (irq8 && (irq_enb & 0x10));
+//     if(prev != int0) {
+               d_pic->write_signal(SIG_I8259_IR0, int0 ? 1 : 0, 1);
+//     }
+}
+
+void MAIN::update_int1()
+{
+//     bool prev = int1;
+       int1 = (irq1 && (irq_enb & 0x80)) || firq1;
+//     if(prev != int1) {
+               d_pic->write_signal(SIG_I8259_IR1, int1 ? 1 : 0, 1);
+//     }
+}
+
+void MAIN::update_int2()
+{
+//     bool prev = int2;
+       int2 = (irq5 && (ext_irq_enb & 0x08)) || irq6;
+//     if(prev != int2) {
+               d_pic->write_signal(SIG_I8259_IR2, int2 ? 1 : 0, 1);
+//     }
+}
+
+void MAIN::update_int3()
+{
+//     bool prev = int3;
+       int3 = firq0 || firq2 || firq3;
+//     if(prev != int3) {
+               d_pic->write_signal(SIG_I8259_IR3, int3 ? 1 : 0, 1);
+//     }
+}
+
+void MAIN::update_int4()
+{
+//     bool prev = int4;
+       int4 = (irq0_tx && (irq_enb & 0x02)) || (irq0_rx && (irq_enb & 0x04)) || (irq0_syn && (irq_enb & 0x08));
+//     if(prev != int4) {
+               d_pic->write_signal(SIG_I8259_IR4, int4 ? 1 : 0, 1);
+//     }
+}
+
+void MAIN::update_int5()
+{
+//     bool prev = int5;
+       int5 = irq2 || irq9;
+//     if(prev != int5) {
+               d_pic->write_signal(SIG_I8259_IR5, int5 ? 1 : 0, 1);
+//     }
+}
+
+void MAIN::update_int6()
+{
+//     bool prev = int6;
+       int6 = (irq6 && (irq_enb & 0x20));
+//     if(prev != int6) {
+               d_pic->write_signal(SIG_I8259_IR6, int6 ? 1 : 0, 1);
+//     }
+}
+
+void MAIN::update_int7()
+{
+//     bool prev = int7;
+       int7 = irq7 && (irq_enb & 0x01);
+//     if(prev != int7) {
+               d_pic->write_signal(SIG_I8259_IR7, int7 ? 1 : 0, 1);
+//     }
+}
+
+#define STATE_VERSION  1
+
+void MAIN::save_state(FILEIO* state_fio)
+{
+       state_fio->FputUint32(STATE_VERSION);
+       state_fio->FputInt32(this_device_id);
+       
+}
+
+bool MAIN::load_state(FILEIO* state_fio)
+{
+       if(state_fio->FgetUint32() != STATE_VERSION) {
+               return false;
+       }
+       if(state_fio->FgetInt32() != this_device_id) {
+               return false;
+       }
+       return true;
+}
+
diff --git a/source/src/vm/fm16beta/main.h b/source/src/vm/fm16beta/main.h
new file mode 100644 (file)
index 0000000..c5ae648
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+       FUJITSU FM16beta Emulator 'eFM16beta'
+
+       Author : Takeda.Toshiya
+       Date   : 2017.12.28-
+
+       [ main system ]
+*/
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+#include "../memory.h"
+
+#define SIG_MAIN_IRQ0_TX       0       // RS-232C
+#define SIG_MAIN_IRQ0_RX       1       // RS-232C
+#define SIG_MAIN_IRQ0_SYN      2       // RS-232C
+#define SIG_MAIN_IRQ1          3       // Keyboard
+#define SIG_MAIN_IRQ2          4       // Expantion
+#define SIG_MAIN_IRQ3          5       // DMA Controller
+#define SIG_MAIN_IRQ4          6       // 320KB Floppy Disk
+#define SIG_MAIN_IRQ5          7       // 1MB Floppy Disk
+#define SIG_MAIN_IRQ6          8       // Hard Disk
+#define SIG_MAIN_IRQ7          9       // Printer
+#define SIG_MAIN_IRQ8          10      // PTM
+#define SIG_MAIN_IRQ9          11      // User
+#define SIG_MAIN_FIRQ0         12      // Sub system attention
+#define SIG_MAIN_FIRQ1         13      // Break
+#define SIG_MAIN_FIRQ2         14      // Expantion
+#define SIG_MAIN_FIRQ3         15      // User
+
+#define SIG_MAIN_SUB_BUSY      16
+
+#define SIG_MAIN_DRQ_2HD       17
+#define SIG_MAIN_DRQ_2D                18
+
+#define SIG_MAIN_RTC_DATA      19
+#define SIG_MAIN_RTC_BUSY      20
+
+#ifdef HAS_I286
+class I286;
+#endif
+class I8237;
+class MB8877;
+
+class MAIN : public MEMORY
+{
+private:
+#ifdef HAS_I286
+       I286 *d_cpu;
+       uint8_t rst;
+#endif
+       I8237 *d_dma;
+       DEVICE *d_pic;
+       DEVICE *d_pcm;
+       DEVICE *d_keyboard;
+
+       // memory
+       uint8_t ram[0xfc000];
+       uint8_t rom[0x04000];
+       uint8_t direct;
+       
+       // main-sub
+       DEVICE *d_sub;
+       bool sub_busy;
+       
+       // 1mb fdd
+       MB8877 *d_fdc_2hd;
+       uint8_t sidereg_2hd, drvreg_2hd;
+       bool drq_2hd;
+       
+       // 320kb fdd
+       MB8877 *d_fdc_2d;
+       uint8_t sidereg_2d, drvreg_2d;
+       bool drq_2d;
+       
+       // rtc
+       DEVICE *d_rtc;
+       uint8_t rtc_data;
+       
+       // irq
+       uint8_t irq_enb, ext_irq_enb;
+       bool irq0_tx, irq0_rx, irq0_syn, irq1, irq2, irq3, irq4, irq5, irq6, irq7, irq8, irq9;
+       bool firq0, firq1, firq2, firq3;
+       bool int0, int1, int2, int3, int4, int5, int6, int7;
+       
+       void update_int0();
+       void update_int1();
+       void update_int2();
+       void update_int3();
+       void update_int4();
+       void update_int5();
+       void update_int6();
+       void update_int7();
+       
+public:
+       MAIN(VM* parent_vm, EMU* parent_emu) : MEMORY(parent_vm, parent_emu)
+       {
+               set_device_name(_T("Main System"));
+       }
+       ~MAIN() {}
+       
+       // common functions
+       void initialize();
+       void release();
+       void reset();
+       void write_io8(uint32_t addr, uint32_t data);
+       uint32_t read_io8(uint32_t addr);
+       void write_signal(int id, uint32_t data, uint32_t mask);
+       void save_state(FILEIO* state_fio);
+       bool load_state(FILEIO* state_fio);
+       
+       // unique functions
+#ifdef HAS_I286
+       void set_context_cpu(I286* device)
+       {
+               d_cpu = device;
+       }
+#endif
+       void set_context_dma(I8237* device)
+       {
+               d_dma = device;
+       }
+       void set_context_fdc_2hd(MB8877* device)
+       {
+               d_fdc_2hd = device;
+       }
+       void set_context_fdc_2d(MB8877* device)
+       {
+               d_fdc_2d = device;
+       }
+       void set_context_pic(DEVICE* device)
+       {
+               d_pic = device;
+       }
+       void set_context_pcm(DEVICE* device)
+       {
+               d_pcm = device;
+       }
+       void set_context_rtc(DEVICE* device)
+       {
+               d_rtc = device;
+       }
+       void set_context_sub(DEVICE* device)
+       {
+               d_sub = device;
+       }
+       void set_context_keyboard(DEVICE* device)
+       {
+               d_keyboard = device;
+       }
+};
+
+#endif
diff --git a/source/src/vm/fm16beta/memo.txt b/source/src/vm/fm16beta/memo.txt
new file mode 100644 (file)
index 0000000..f260ad1
--- /dev/null
@@ -0,0 +1,26 @@
+IRQ8                   -> INT0
+       IRQ8: \83^\83C\83}\81[
+IRQ1 + FIRQ1           -> INT1
+       IRQ1: \83L\81[\83{\81[\83h
+       FIRQ1: BREAK\83L\81[
+IRQ5 + IRQ6            -> INT2
+       IRQ5: 1MB\83t\83\8d\83b\83s\83B\83f\83B\83X\83N
+       IRQ6: \83n\81[\83h\83f\83B\83X\83N
+FIRQ0 + FIRQ2 + FIRQ3  -> INT3
+       FIRQ0: SUB\83A\83e\83\93\83V\83\87\83\93
+       FIRQ2: \8ag\92£
+       FIRQ3: \83\86\81[\83U\97p
+IRQ0                   -> INT4
+       IRQ0: RS-232C
+IRQ2 + IRQ9 + INTNDP   -> INT5
+       IRQ2: \8ag\92£
+       IRQ9: \83\86\81[\83U\97p
+IRQ4                   -> INT6
+       IRQ4: 320KB\83t\83\8d\83b\83s\83B\83f\83B\83X\83N
+IRQ7                   -> INT7
+       IRQ7: \83v\83\8a\83\93\83^
+
+DMA0   320KB\83t\83\8d\83b\83s\83B\83f\83B\83X\83N
+DMA1   1MB\83t\83\8d\83b\83s\83B\83f\83B\83X\83N
+DMA2   \83n\81[\83h\83f\83B\83X\83N
+DMA3   \83\86\81[\83U
diff --git a/source/src/vm/fm16beta/sub.cpp b/source/src/vm/fm16beta/sub.cpp
new file mode 100644 (file)
index 0000000..92a1ec9
--- /dev/null
@@ -0,0 +1,957 @@
+/*
+       FUJITSU FM16beta Emulator 'eFM16beta'
+
+       Author : Takeda.Toshiya
+       Date   : 2017.12.28-
+
+       [ sub system ]
+*/
+
+#include "sub.h"
+#include "main.h"
+#include "../pcm1bit.h"
+
+void SUB::initialize()
+{
+       MEMORY::initialize();
+
+       // init memory
+       memset(wram, 0, sizeof(wram));
+       memset(sram, 0, sizeof(sram));
+       memset(gvram, 0, sizeof(gvram));
+       memset(dummy, 0, sizeof(dummy));
+       memset(cvram, 0, sizeof(cvram));
+       memset(kvram, 0, sizeof(kvram));
+       memset(rom, 0xff, sizeof(rom));
+       memset(ank8, 0xff, sizeof(ank8));
+       memset(ank16, 0xff, sizeof(ank16));
+       memset(kanji16, 0xff, sizeof(kanji16));
+       
+       // load rom image
+       FILEIO* fio = new FILEIO();
+       if(fio->Fopen(create_local_path(_T("SUBSYS.ROM")), FILEIO_READ_BINARY) ||
+          fio->Fopen(create_local_path(_T("SUB.ROM")), FILEIO_READ_BINARY)) {
+               fio->Fread(rom, sizeof(rom), 1);
+               fio->Fclose();
+               if(rom[0x4ff2] == 0xff && rom[0x4ff3] == 0xff) { // SWI3
+                       rom[0x4ff2] = 0x9f;
+                       rom[0x4ff3] = 0x6e;
+               }
+               if(rom[0x4ff4] == 0xff && rom[0x4ff5] == 0xff) { // SWI2
+                       rom[0x4ff4] = 0x9f;
+                       rom[0x4ff5] = 0x71;
+               }
+               if(rom[0x4ff6] == 0xff && rom[0x4ff7] == 0xff) { // FIRQ
+                       rom[0x4ff6] = 0x9f;
+                       rom[0x4ff7] = 0x74;
+               }
+               if(rom[0x4ff8] == 0xff && rom[0x4ff9] == 0xff) { // IRQ
+                       rom[0x4ff8] = 0x9f;
+                       rom[0x4ff9] = 0x77;
+               }
+               if(rom[0x4ffa] == 0xff && rom[0x4ffb] == 0xff) { // SWI
+                       rom[0x4ffa] = 0x9f;
+                       rom[0x4ffb] = 0x7a;
+               }
+               if(rom[0x4ffc] == 0xff && rom[0x4ffd] == 0xff) { // NMI
+                       rom[0x4ffc] = 0x9f;
+                       rom[0x4ffd] = 0x7d;
+               }
+               if(rom[0x4ffe] == 0xff && rom[0x4fff] == 0xff) { // RESET
+                       for(int i = 0; i < sizeof(rom) - 4; i++) {
+                               static const uint8_t boot[4] = {0x86, 0x90, 0x1f, 0x8b};
+                               if(memcmp(rom + i, boot, sizeof(boot)) == 0) {
+                                       i += 0xb000;
+                                       rom[0x4ffe] = (i >> 8) & 0xff;
+                                       rom[0x4fff] = (i >> 0) & 0xff;
+                                       break;
+                               }
+                       }
+               }
+       }
+       if(fio->Fopen(create_local_path(_T("ANK8.ROM")), FILEIO_READ_BINARY)) {
+               fio->Fread(ank8, sizeof(ank8), 1);
+               fio->Fclose();
+       }
+       if(fio->Fopen(create_local_path(_T("ANK16.ROM")), FILEIO_READ_BINARY)) {
+               fio->Fread(ank16, sizeof(ank16), 1);
+               fio->Fclose();
+       }
+       if(fio->Fopen(create_local_path(_T("KANJI16.ROM")), FILEIO_READ_BINARY)) {
+               fio->Fread(kanji16, sizeof(kanji16), 1);
+               fio->Fclose();
+       }
+       delete fio;
+       
+       set_memory_rw(0x9000, 0x9f7f, wram + 0x1000);
+       set_memory_rw(0x9f80, 0x9fff, sram);
+       set_memory_r (0xb000, 0xffff, rom);
+       
+       for(int i = 0; i < 8; i++) {
+               palette_txt[i] = palette_cg[i] = RGB_COLOR(i & 2 ? 255 : 0, i & 4 ? 255 : 0, i & 1 ? 255 : 0);
+       }
+
+
+}
+
+void SUB::release()
+{
+       MEMORY::release();
+}
+
+void SUB::reset()
+{
+       MEMORY::reset();
+       
+       // reset crtc
+       blink = 0;
+       outctrl = 0xf;
+       
+       d_main->write_signal(SIG_MAIN_SUB_BUSY, 1, 1);
+       mix = 0x00;
+       
+       update = dispctrl = pagesel = 0;
+       ankcg = 0;
+       accaddr = dispaddr = 0;
+       
+       update_cvram_bank();
+       update_kvram_bank();
+       
+       memset(attention, 0, sizeof(attention));
+       mainack = 0x80;
+       
+       irq_cancel = irq_vsync = firq_key = firq_pen = false;
+       
+       kj_l = kj_h = kj_ofs = kj_row = 0;
+       
+       cmdreg = maskreg = compbit = bankdis = 0;
+       memset(compreg, 0xff, sizeof(compreg));
+}
+
+void SUB::write_data8(uint32_t addr, uint32_t data)
+{
+       // sub cpu memory bus
+       write_memory(addr, data);
+#ifdef _IO_DEBUG_LOG
+       if((addr >= 0x9f80 && addr < 0xa000) || (addr >= 0xff80 && addr < 0xffe0)) {
+               this->out_debug_log(_T("SUB %06x\tOUT8\t%04x,%02x\n"), get_cpu_pc(1), addr, data);
+       }
+#endif
+}
+
+uint32_t SUB::read_data8(uint32_t addr)
+{
+       // sub cpu memory bus
+       uint32_t val = read_memory(addr);
+#ifdef _IO_DEBUG_LOG
+       if((addr >= 0x9f80 && addr < 0xa000) || (addr >= 0xff80 && addr < 0xffe0)) {
+               this->out_debug_log(_T("SUB %06x\tIN8\t%04x,%02x\n"), get_cpu_pc(1), addr, val);
+       }
+#endif
+       return val;
+}
+
+void SUB::write_memory_mapped_io8(uint32_t addr, uint32_t data)
+{
+       // main cpu direct access
+       addr &= 0xffff;
+       write_memory(addr, data);
+#ifdef _IO_DEBUG_LOG
+       if((addr >= 0x9f80 && addr < 0xa000) || (addr >= 0xff80 && addr < 0xffe0)) {
+               this->out_debug_log(_T("MAIN %06x\tOUT8\t%04x,%02x\n"), get_cpu_pc(0), addr, data);
+       }
+#endif
+}
+
+uint32_t SUB::read_memory_mapped_io8(uint32_t addr)
+{
+       // main cpu direct access
+       addr &= 0xffff;
+       uint32_t val = read_memory(addr);
+#ifdef _IO_DEBUG_LOG
+       if((addr >= 0x9f80 && addr < 0xa000) || (addr >= 0xff80 && addr < 0xffe0)) {
+               this->out_debug_log(_T("MAIN %06x\tIN8\t%04x,%02x\n"), get_cpu_pc(1), addr, val);
+       }
+#endif
+       return val;
+}
+
+void SUB::write_memory(uint32_t addr, uint32_t data)
+{
+       if(addr < 0x8000) {
+               if(dispctrl & 0x40) {
+                       uint32_t bank = (pagesel >> 4) & 1;
+                       addr &= 0x7fff;
+                       addr |= bank << 15;
+               } else {
+                       uint32_t bank = (pagesel >> 3) & 3;
+                       addr &= 0x3fff;
+                       addr |= bank << 14;
+               }
+               if(update & 1) gvram[addr | 0x00000] = data;
+               if(update & 2) gvram[addr | 0x10000] = data;
+               if(update & 4) gvram[addr | 0x20000] = data;
+       } else if(addr >= 0xff80 && addr < 0xffe0) {
+               uint8_t change;
+               
+               switch(addr) {
+               case 0xff80:
+                       d_main->write_signal(SIG_MAIN_SUB_BUSY, ~data, 1);
+                       mix = data;
+                       break;
+               case 0xff81:
+                       update = data;
+                       break;
+               case 0xff82:
+                       dispctrl = data;
+                       break;
+               case 0xff83:
+                       change = pagesel ^ data;
+                       pagesel = data;
+                       if(change & 0x20) {
+                               update_cvram_bank();
+                       }
+                       break;
+
+
+
+
+               case 0xff87:
+                       d_main->write_signal(SIG_MAIN_FIRQ0, 1, 1);
+                       mainack &= ~0x80;
+                       break;
+
+               case 0xff88:
+                       accaddr = (accaddr & 0x00ff) | (data << 8);
+                       break;
+               case 0xff89:
+                       accaddr = (accaddr & 0xff00) | (data << 0);
+                       break;
+               case 0xff8a:
+                       dispaddr = (dispaddr & 0x00ff) | (data << 8);
+                       break;
+               case 0xff8b:
+                       dispaddr = (dispaddr & 0xff00) | (data << 0);
+                       break;
+
+               case 0xff8e:
+               case 0xff8f:
+                       d_crtc->write_io8(addr, data);
+                       break;
+
+               case 0xff90:
+               case 0xff91:
+               case 0xff92:
+                       attention[addr & 3] = data;
+                       break;
+               case 0xff94:
+                       kj_h = data & 0x7f;
+                       break;
+               case 0xff95:
+                       kj_l = data & 0x7f;
+                       kj_row = 0;
+                       if(kj_h < 0x30) {
+                               kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) | (((kj_l - 0x20) & 0x20) <<  9) | (((kj_l - 0x20) & 0x40) <<  7) | (((kj_h - 0x00) & 0x07) << 10);
+                       } else if(kj_h < 0x70) {
+                               kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) + (((kj_l - 0x20) & 0x60) <<  9) + (((kj_h - 0x00) & 0x0f) << 10) + (((kj_h - 0x30) & 0x70) * 0xc00) + 0x08000;
+                       } else {
+                               kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) | (((kj_l - 0x20) & 0x20) <<  9) | (((kj_l - 0x20) & 0x40) <<  7) | (((kj_h - 0x00) & 0x07) << 10) | 0x38000;
+                       }
+                       break;
+               case 0xff96:
+                       kanji16[(kj_ofs | ((kj_row & 0xf) << 1)) & 0x3ffff] = data;
+                       break;
+               case 0xff97:
+                       kanji16[(kj_ofs | ((kj_row++ & 0xf) << 1) | 1) & 0x3ffff] = data;
+                       break;
+
+               case 0xff98:
+                       d_pcm->write_signal(SIG_PCM1BIT_ON, 0, 0);
+                       break;
+
+               case 0xff99:
+                       change = ankcg ^ data;
+                       ankcg = data;
+                       if(change & 0x01) {
+                               update_kvram_bank();
+                       }
+                       if(change & 0x80) {
+                               update_kvram_bank();
+                       }
+                       break;
+
+               case 0xffa0:
+                       cmdreg = data;
+                       break;
+               case 0xffa1:
+                       imgcol = data;
+                       break;
+               case 0xffa2:
+                       maskreg = data;
+                       break;
+               case 0xffa3:
+               case 0xffa4:
+               case 0xffa5:
+               case 0xffa6:
+               case 0xffa7:
+               case 0xffa8:
+               case 0xffa9:
+               case 0xffaa:
+                       compreg[addr & 7] = data;
+                       break;
+               case 0xffab:
+                       bankdis = data;
+                       break;
+               case 0xffac:
+               case 0xffad:
+               case 0xffae:
+               case 0xffaf:
+                       tilereg[addr & 3] = data;
+                       break;
+               case 0xffb0:
+                       lofs = (lofs & 0xff) | (data << 8);
+                       break;
+               case 0xffb1:
+                       lofs = (lofs & 0xff00) | data;
+                       break;
+               case 0xffb2:
+                       lsty = (lsty & 0xff) | (data << 8);
+                       break;
+               case 0xffb3:
+                       lsty = (lsty & 0xff00) | data;
+                       break;
+               case 0xffb4:
+                       lsx = (lsx & 0xff) | (data << 8);
+                       break;
+               case 0xffb5:
+                       lsx = (lsx & 0xff00) | data;
+                       break;
+               case 0xffb6:
+                       lsy = (lsy & 0xff) | (data << 8);
+                       break;
+               case 0xffb7:
+                       lsy = (lsy & 0xff00) | data;
+                       break;
+               case 0xffb8:
+                       lex = (lex & 0xff) | (data << 8);
+                       break;
+               case 0xffb9:
+                       lex = (lex & 0xff00) | data;
+                       break;
+               case 0xffba:
+                       ley = (ley & 0xff) | (data << 8);
+                       break;
+               case 0xffbb:
+                       ley = (ley & 0xff00) | data;
+                       // start drawing line
+                       line();
+                       break;
+#ifdef _IO_DEBUG_LOG
+               default:
+                       this->out_debug_log(_T("UNKNOWN:\t"));
+                       break;
+#endif
+               }
+       } else {
+               MEMORY::write_data8(addr, data);
+       }
+}
+
+uint32_t SUB::read_memory(uint32_t addr)
+{
+       if(addr < 0x8000) {
+               if(dispctrl & 0x40) {
+                       uint32_t bank = (pagesel >> 4) & 1;
+                       addr &= 0x7fff;
+                       addr |= bank << 15;
+               } else {
+                       uint32_t bank = (pagesel >> 3) & 3;
+                       addr &= 0x3fff;
+                       addr |= bank << 14;
+               }
+               switch(update & 0xc0) {
+               case 0x00: return gvram[addr | 0x00000];
+               case 0x40: return gvram[addr | 0x10000];
+               case 0x80: return gvram[addr | 0x20000];
+               }
+               return 0xff;
+       } else if(addr >= 0xff80 && addr < 0xffe0) {
+               switch(addr) {
+               case 0xff80:
+                       // bit5: Cursor LSB
+                       // bit4: Light Pen FIRQ 0:Disabled 1:Enabled
+                       // bit3: WIDTH 0:40 1:80
+                       // bit2: FLASH 0:OFF 1:ON
+                       // bit1: INSLED 0:OFF 1:ON
+                       // bit0: SUB BUSY 0:BUSY 1:READY
+                       return mix | 0xc0;
+               case 0xff81:
+                       // bit7: Read Out Control RC2
+                       // bit6: Read Out Control RC1
+                       // bit2: RAM Select Bit RAM3
+                       // bit1: RAM Select Bit RAM2
+                       // bit0: RAM Select Bit RAM1
+                       return update | 0x38;
+               case 0xff83:
+                       return pagesel | 0xc7;
+
+               case 0xff84:
+                       {
+                               uint8_t val = (firq_key ? 0x01 : 0) | (firq_pen ? 0x80 : 0);
+                               firq_key = firq_pen = false;
+                               update_firq();
+                               return val;
+                       }
+
+               case 0xff85:
+                       {
+                               uint8_t val = (irq_cancel ? 0x01 : 0) | (irq_vsync ? 0x02 : 0) | 0x7e;
+                               irq_cancel = irq_vsync = false;
+                               update_irq();
+                               return val;
+                       }
+
+
+
+               case 0xff86:
+                       return (disp ? 0x80 : 0) | (vsync ? 0x04 : 0) | 0x70;
+
+               case 0xff87:
+                       d_main->write_signal(SIG_MAIN_FIRQ0, 1, 1);
+                       mainack &= ~0x80;
+                       break;
+
+               case 0xff8c:
+               case 0xff8d:
+                       return d_keyboard->read_io8(addr);
+               case 0xff8e:
+               case 0xff8f:
+                       return d_crtc->read_io8(addr);
+               case 0xff90:
+               case 0xff91:
+               case 0xff92:
+                       return attention[addr & 3];
+               case 0xff93:
+                       return mainack;
+               case 0xff94:
+                       return 0x80; // \91æ\93ñ\90\85\8f\80\82 \82è
+               case 0xff96:
+                       return kanji16[(kj_ofs | ((kj_row & 0xf) << 1)) & 0x3ffff];
+               case 0xff97:
+                       return kanji16[(kj_ofs | ((kj_row++ & 0xf) << 1) | 1) & 0x3ffff];
+               case 0xff98:
+                       d_pcm->write_signal(SIG_PCM1BIT_ON, 1, 1);
+                       break;
+
+               case 0xff99:
+                       return ankcg;
+               case 0xffa0:
+                       return cmdreg;
+               case 0xffa1:
+                       return imgcol | 0xf0;
+               case 0xffa2:
+                       return maskreg;
+               case 0xffa3:
+                       return compbit;
+               case 0xffab:
+                       return bankdis & 0x0f;
+
+               case 0xffb0:
+                       return (lofs >> 8) & 0xff;
+               case 0xffb1:
+                       return (lofs >> 0) & 0xff;
+#ifdef _IO_DEBUG_LOG
+               default:
+                       this->out_debug_log(_T("UNKNOWN:\t"));
+                       break;
+#endif
+               }
+               return 0xff;
+       } else {
+               return MEMORY::read_data8(addr);
+       }
+}
+
+void SUB::write_io8(uint32_t addr, uint32_t data)
+{
+       // main cpu i/o bus
+       switch(addr) {
+       case 0xfd98:
+       case 0xfd99:
+       case 0xfd9a:
+       case 0xfd9b:
+       case 0xfd9c:
+       case 0xfd9d:
+       case 0xfd9e:
+       case 0xfd9f:
+               // digital palette
+               if(data & 8) {
+                       palette_cg[addr & 7] = RGB_COLOR(data & 2 ? 255 : 0, data & 4 ? 255 : 0, data & 1 ? 255 : 0);
+               } else {
+                       palette_cg[addr & 7] = RGB_COLOR(data & 2 ? 127 : 0, data & 4 ? 127 : 0, data & 1 ? 127 : 0);
+               }
+               dpal[addr & 7] = data;
+               break;
+       case 0xfda0:
+               outctrl = data;
+               break;
+       // 0xfc80 - 0xfcff
+       default:
+               sram[addr & 0x7f] = data;
+               break;
+       }
+}
+
+uint32_t SUB::read_io8(uint32_t addr)
+{
+       // main cpu i/o bus
+       switch(addr) {
+       case 0xfd20:
+       case 0xfd21:
+       case 0xfd22:
+               return attention[addr & 3];
+
+       case 0xfd98:
+       case 0xfd99:
+       case 0xfd9a:
+       case 0xfd9b:
+       case 0xfd9c:
+       case 0xfd9d:
+       case 0xfd9e:
+       case 0xfd9f:
+               // digital palette
+               return dpal[addr & 7] | 0xf0;
+       // 0xfc80 - 0xfcff
+       default:
+               return sram[addr & 0x7f];
+       }
+       return 0xff;
+}
+
+void SUB::write_signal(int id, uint32_t data, uint32_t mask)
+{
+       if(id == SIG_SUB_DISP) {
+               disp = ((data & mask) != 0);
+       } else if(id == SIG_SUB_VSYNC) {
+               irq_vsync = vsync = ((data & mask) != 0);
+               update_irq();
+       } else if(id == SIG_SUB_CANCEL) {
+               irq_cancel = ((data & mask) != 0);
+               update_irq();
+this->out_debug_log("MAIN -> SUB: CANCEL = %d\n", irq_cancel);
+
+       } else if(id == SIG_SUB_KEY) {
+               firq_key = ((data & mask) != 0);
+               update_firq();
+       } else if(id == SIG_SUB_HALT) {
+this->out_debug_log("MAIN -> SUB: HALT = %d\n", data & mask ?1 : 0);
+               if(data & mask) {
+                       d_main->write_signal(SIG_MAIN_SUB_BUSY, 1, 1);
+                       mix &= ~0x01;
+               }
+               d_subcpu->write_signal(SIG_CPU_BUSREQ, data, mask);
+       } else if(id == SIG_SUB_MAINACK) {
+this->out_debug_log("MAIN -> SUB: MAINACK = %d\n", data & mask ? 1 : 0);
+               if(data & mask) {
+                       d_main->write_signal(SIG_MAIN_FIRQ0, 0, 0);
+                       mainack |= 0x80;
+               }
+       }
+}
+
+void SUB::update_irq()
+{
+       d_subcpu->write_signal(SIG_CPU_IRQ, irq_cancel || (irq_vsync && (ankcg & 0x80)) ? 1 : 0, 1);
+}
+
+void SUB::update_firq()
+{
+       d_subcpu->write_signal(SIG_CPU_FIRQ, firq_key || (firq_pen &&  (mix & 0x10)) ? 1 : 0, 1);
+}
+
+void SUB::update_cvram_bank()
+{
+       if(pagesel & 0x20) {
+               set_memory_rw(0x8000, 0x8fff, wram);
+       } else {
+               set_memory_rw(0x8000, 0x8fff, cvram);
+       }
+}
+
+void SUB::update_kvram_bank()
+{
+       if(ankcg & 0x01) {
+               set_memory_r(0xa000, 0xa7ff, ank8);
+               set_memory_r(0xa800, 0xafff, ank8);
+       } else {
+               set_memory_rw(0xa000, 0xafff, kvram);
+       }
+}
+
+void SUB::key_down(int code)
+{
+       
+}
+
+void SUB::key_up(int code)
+{
+       
+}
+
+void SUB::point(int x, int y, int col)
+{
+       if(x < 640 && y < 400) {
+               int ofs = ((lofs & 0x3fff) + (x >> 3) + y * 80) & 0x7fff;
+               uint8_t bit = 0x80 >> (x & 7);
+               for(int pl = 0; pl < 3; pl++) {
+                       uint8_t pbit = 1 << pl;
+                       if(!(bankdis & pbit)) {
+                               if(col & pbit) {
+                                       gvram[0x8000 * pl + ofs] |= bit;
+                               } else {
+                                       gvram[0x8000 * pl + ofs] &= ~bit;
+                               }
+                       }
+               }
+       }
+}
+
+void SUB::line()
+{
+       int nx = lsx, ny = lsy;
+       int dx = abs(lex - lsx) * 2;
+       int dy = abs(ley - lsy) * 2;
+       int sx = (lex < lsx) ? -1 : 1;
+       int sy = (ley < lsy) ? -1 : 1;
+       int c = 0;
+       
+       point(lsx, lsy, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
+       if(dx > dy) {
+               int frac = dy - dx / 2;
+               while(nx != lex) {
+                       if(frac >= 0) {
+                               ny += sy;
+                               frac -= dx;
+                       }
+                       nx += sx;
+                       frac += dy;
+                       point(nx, ny, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
+               }
+       } else {
+               int frac = dx - dy / 2;
+               while(ny != ley) {
+                       if(frac >= 0) {
+                               nx += sx;
+                               frac -= dy;
+                       }
+                       ny += sy;
+                       frac += dx;
+                       point(nx, ny, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
+               }
+       }
+//     point(lex, ley, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
+}
+
+void SUB::draw_screen()
+{
+       // render screen
+       memset(screen_txt, 0, sizeof(screen_txt));
+       memset(screen_cg, 0, sizeof(screen_cg));
+       
+       if(outctrl & 1) {
+               if(mix & 8) {
+                       draw_text80();
+               } else {
+                       draw_text40();
+               }
+       } else if(outctrl & 2) {
+               // greem text
+       }
+       if(outctrl & 4) {
+               draw_cg();
+       } else if(outctrl & 8) {
+               // green graphics
+       }
+       
+       for(int y = 0; y < SCREEN_HEIGHT; y++) {
+               scrntype_t* dest = emu->get_screen_buffer(y);
+               uint8_t* txt = screen_txt[y];
+               uint8_t* cg = screen_cg[y];
+               
+               for(int x = 0; x < SCREEN_WIDTH; x++) {
+                       dest[x] = txt[x] ? palette_txt[txt[x] & 15] : palette_cg[cg[x]];
+               }
+       }
+       emu->screen_skip_line(false);
+}
+
+void SUB::draw_text40()
+{
+       int src = ((chreg[12] << 9) | (chreg[13] << 1)) & 0xfff;
+       int caddr = ((chreg[8] & 0xc0) == 0xc0) ? -1 : (((chreg[14] << 9) | (chreg[15] << 1) | (mix & 0x20 ? 1 : 0)) & 0x7ff);
+       int ymax = (chreg[6] > 0) ? chreg[6] : 25;
+       int yofs = 400 / ymax;
+       
+       for(int y = 0; y < ymax; y++) {
+               for(int x = 0; x < 40; x++) {
+                       bool cursor = ((src >> 1) == caddr);
+                       int cx = x;
+                       uint8_t code = cvram[src];
+                       uint8_t h = kvram[src] & 0x7f;
+                       src = (src + 1) & 0xfff;
+                       uint8_t attr = cvram[src];
+                       uint8_t l = kvram[src] & 0x7f;
+                       src = (src + 1) & 0xfff;
+                       uint8_t col = ((attr & 0x20) >> 2) | (attr & 7) | 16;
+                       bool blnk = (blink & 32) && (attr & 0x10);
+                       bool rev = ((attr & 8) != 0);
+                       uint8_t xor_mask = (rev != blnk) ? 0xff : 0;
+                       
+                       if(attr & 0x40) {
+                               // kanji
+                               int ofs;
+                               if(h < 0x30) {
+                                       ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10);
+                               } else if(h < 0x70) {
+                                       ofs = (((l - 0x00) & 0x1f) <<  5) + (((l - 0x20) & 0x60) <<  9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
+                               } else {
+                                       ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
+                               }
+                               
+                               for(int l = 0; l < 16 && l < yofs; l++) {
+                                       uint8_t pat0 = kanji16[ofs + (l << 1) + 0] ^ xor_mask;
+                                       uint8_t pat1 = kanji16[ofs + (l << 1) + 1] ^ xor_mask;
+                                       int yy = y * yofs + l;
+                                       if(yy >= 400) {
+                                               break;
+                                       }
+                                       uint8_t* d = &screen_txt[yy][x << 4];
+                                       
+                                       d[ 0] = d[ 1] = (pat0 & 0x80) ? col : 0;
+                                       d[ 2] = d[ 3] = (pat0 & 0x40) ? col : 0;
+                                       d[ 4] = d[ 5] = (pat0 & 0x20) ? col : 0;
+                                       d[ 6] = d[ 7] = (pat0 & 0x10) ? col : 0;
+                                       d[ 8] = d[ 9] = (pat0 & 0x08) ? col : 0;
+                                       d[10] = d[11] = (pat0 & 0x04) ? col : 0;
+                                       d[12] = d[13] = (pat0 & 0x02) ? col : 0;
+                                       d[14] = d[15] = (pat0 & 0x01) ? col : 0;
+                                       d[16] = d[17] = (pat1 & 0x80) ? col : 0;
+                                       d[18] = d[19] = (pat1 & 0x40) ? col : 0;
+                                       d[20] = d[21] = (pat1 & 0x20) ? col : 0;
+                                       d[22] = d[23] = (pat1 & 0x10) ? col : 0;
+                                       d[24] = d[25] = (pat1 & 0x08) ? col : 0;
+                                       d[26] = d[27] = (pat1 & 0x04) ? col : 0;
+                                       d[28] = d[29] = (pat1 & 0x02) ? col : 0;
+                                       d[30] = d[31] = (pat1 & 0x01) ? col : 0;
+                               }
+                               src = (src + 2) & 0xfff;
+                               x++;
+                       } else {
+                               for(int l = 0; l < 16 && l < yofs; l++) {
+                                       uint8_t pat = ank16[(code << 4) + l] ^ xor_mask;
+                                       int yy = y * yofs + l;
+                                       if(yy >= 400) {
+                                               break;
+                                       }
+                                       uint8_t* d = &screen_txt[yy][x << 4];
+                                       
+                                       d[ 0] = d[ 1] = (pat & 0x80) ? col : 0;
+                                       d[ 2] = d[ 3] = (pat & 0x40) ? col : 0;
+                                       d[ 4] = d[ 5] = (pat & 0x20) ? col : 0;
+                                       d[ 6] = d[ 7] = (pat & 0x10) ? col : 0;
+                                       d[ 8] = d[ 9] = (pat & 0x08) ? col : 0;
+                                       d[10] = d[11] = (pat & 0x04) ? col : 0;
+                                       d[12] = d[13] = (pat & 0x02) ? col : 0;
+                                       d[14] = d[15] = (pat & 0x01) ? col : 0;
+                               }
+                       }
+                       if(cursor) {
+                               int bp = chreg[10] & 0x60;
+                               if(bp == 0 || (bp == 0x40 && (blink & 8)) || (bp == 0x60 && (blink & 0x10))) {
+                                       int st = chreg[10] & 15;
+                                       int ed = chreg[11] & 15;
+                                       for(int i = st; i < ed && i < yofs; i++) {
+                                               memset(&screen_txt[y * yofs + i][cx << 3], 7, 8);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void SUB::draw_text80()
+{
+       int src = ((chreg[12] << 9) | (chreg[13] << 1)) & 0xfff;
+       int caddr = ((chreg[8] & 0xc0) == 0xc0) ? -1 : (((chreg[14] << 9) | (chreg[15] << 1) | (mix & 0x20 ? 1 : 0)) & 0x7ff);
+       int ymax = (chreg[6] > 0) ? chreg[6] : 25;
+       int yofs = 400 / ymax;
+       
+       for(int y = 0; y < 25; y++) {
+               for(int x = 0; x < 80; x++) {
+                       bool cursor = ((src >> 1) == caddr);
+                       int cx = x;
+                       uint8_t code = cvram[src];
+                       uint8_t h = kvram[src] & 0x7f;
+                       src = (src + 1) & 0xfff;
+                       uint8_t attr = cvram[src];
+                       uint8_t l = kvram[src] & 0x7f;
+                       src = (src + 1) & 0xfff;
+                       uint8_t col = ((attr & 0x20) >> 2) | (attr & 7) | 16;
+                       bool blnk = (blink & 32) && (attr & 0x10);
+                       bool rev = ((attr & 8) != 0);
+                       uint8_t xor_mask = (rev != blnk) ? 0xff : 0;
+                       
+                       if(attr & 0x40) {
+                               // kanji
+                               int ofs;
+                               if(h < 0x30) {
+                                       ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10);
+                               } else if(h < 0x70) {
+                                       ofs = (((l - 0x00) & 0x1f) <<  5) + (((l - 0x20) & 0x60) <<  9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
+                               } else {
+                                       ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
+                               }
+                               
+                               for(int l = 0; l < 16 && l < yofs; l++) {
+                                       uint8_t pat0 = kanji16[ofs + (l << 1) + 0] ^ xor_mask;
+                                       uint8_t pat1 = kanji16[ofs + (l << 1) + 1] ^ xor_mask;
+                                       int yy = y * yofs + l;
+                                       if(yy >= 400) {
+                                               break;
+                                       }
+                                       uint8_t* d = &screen_txt[yy][x << 3];
+                                       
+                                       d[ 0] = (pat0 & 0x80) ? col : 0;
+                                       d[ 1] = (pat0 & 0x40) ? col : 0;
+                                       d[ 2] = (pat0 & 0x20) ? col : 0;
+                                       d[ 3] = (pat0 & 0x10) ? col : 0;
+                                       d[ 4] = (pat0 & 0x08) ? col : 0;
+                                       d[ 5] = (pat0 & 0x04) ? col : 0;
+                                       d[ 6] = (pat0 & 0x02) ? col : 0;
+                                       d[ 7] = (pat0 & 0x01) ? col : 0;
+                                       d[ 8] = (pat1 & 0x80) ? col : 0;
+                                       d[ 9] = (pat1 & 0x40) ? col : 0;
+                                       d[10] = (pat1 & 0x20) ? col : 0;
+                                       d[11] = (pat1 & 0x10) ? col : 0;
+                                       d[12] = (pat1 & 0x08) ? col : 0;
+                                       d[13] = (pat1 & 0x04) ? col : 0;
+                                       d[14] = (pat1 & 0x02) ? col : 0;
+                                       d[15] = (pat1 & 0x01) ? col : 0;
+                               }
+                               src = (src + 2) & 0xfff;
+                               x++;
+                       } else {
+                               for(int l = 0; l < 16 && l < yofs; l++) {
+                                       uint8_t pat = ank16[(code << 4) + l] ^ xor_mask;
+                                       int yy = y * yofs + l;
+                                       if(yy >= 400) {
+                                               break;
+                                       }
+                                       uint8_t* d = &screen_txt[yy][x << 3];
+                                       
+                                       d[0] = (pat & 0x80) ? col : 0;
+                                       d[1] = (pat & 0x40) ? col : 0;
+                                       d[2] = (pat & 0x20) ? col : 0;
+                                       d[3] = (pat & 0x10) ? col : 0;
+                                       d[4] = (pat & 0x08) ? col : 0;
+                                       d[5] = (pat & 0x04) ? col : 0;
+                                       d[6] = (pat & 0x02) ? col : 0;
+                                       d[7] = (pat & 0x01) ? col : 0;
+                               }
+                       }
+                       if(cursor) {
+                               int bp = chreg[10] & 0x60;
+                               if(bp == 0 || (bp == 0x40 && (blink & 8)) || (bp == 0x60 && (blink & 0x10))) {
+                                       int st = chreg[10] & 15;
+                                       int ed = chreg[11] & 15;
+                                       for(int i = st; i < ed && i < yofs; i++) {
+                                               memset(&screen_txt[y * yofs + i][cx << 3], 7, 8);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void SUB::draw_cg()
+{
+       if(dispctrl & 0x40) {
+               // 400line
+               int pofs = ((dispctrl >> 3) & 1) * 0x20000;
+               uint8_t* p0 = (dispctrl & 0x01) ? &gvram[pofs | 0x00000] : dummy;
+               uint8_t* p1 = (dispctrl & 0x02) ? &gvram[pofs | 0x08000] : dummy;
+               uint8_t* p2 = (dispctrl & 0x04) ? &gvram[pofs | 0x10000] : dummy;
+               int ptr = dispaddr & 0x7ffe;
+               
+               for(int y = 0; y < 400; y++) {
+                       for(int x = 0; x < 640; x += 8) {
+                               uint8_t r = p0[ptr];
+                               uint8_t g = p1[ptr];
+                               uint8_t b = p2[ptr++];
+                               ptr &= 0x7fff;
+                               uint8_t* d = &screen_cg[y][x];
+                               
+                               d[0] = ((r & 0x80) >> 7) | ((g & 0x80) >> 6) | ((b & 0x80) >> 5);
+                               d[1] = ((r & 0x40) >> 6) | ((g & 0x40) >> 5) | ((b & 0x40) >> 4);
+                               d[2] = ((r & 0x20) >> 5) | ((g & 0x20) >> 4) | ((b & 0x20) >> 3);
+                               d[3] = ((r & 0x10) >> 4) | ((g & 0x10) >> 3) | ((b & 0x10) >> 2);
+                               d[4] = ((r & 0x08) >> 3) | ((g & 0x08) >> 2) | ((b & 0x08) >> 1);
+                               d[5] = ((r & 0x04) >> 2) | ((g & 0x04) >> 1) | ((b & 0x04) >> 0);
+                               d[6] = ((r & 0x02) >> 1) | ((g & 0x02) >> 0) | ((b & 0x02) << 1);
+                               d[7] = ((r & 0x01) >> 0) | ((g & 0x01) << 1) | ((b & 0x01) << 2);
+                       }
+               }
+       } else {
+               // 200line
+               int pofs = ((dispctrl >> 3) & 3) * 0x10000;
+               uint8_t* p0 = (dispctrl & 0x01) ? &gvram[pofs | 0x0000] : dummy;
+               uint8_t* p1 = (dispctrl & 0x02) ? &gvram[pofs | 0x4000] : dummy;
+               uint8_t* p2 = (dispctrl & 0x04) ? &gvram[pofs | 0x8000] : dummy;
+               int ptr = dispaddr & 0x3ffe;
+               
+               for(int y = 0; y < 400; y += 2) {
+                       for(int x = 0; x < 640; x += 8) {
+                               uint8_t r = p0[ptr];
+                               uint8_t g = p1[ptr];
+                               uint8_t b = p2[ptr++];
+                               ptr &= 0x3fff;
+                               uint8_t* d = &screen_cg[y][x];
+                               
+                               d[0] = ((r & 0x80) >> 7) | ((g & 0x80) >> 6) | ((b & 0x80) >> 5);
+                               d[1] = ((r & 0x40) >> 6) | ((g & 0x40) >> 5) | ((b & 0x40) >> 4);
+                               d[2] = ((r & 0x20) >> 5) | ((g & 0x20) >> 4) | ((b & 0x20) >> 3);
+                               d[3] = ((r & 0x10) >> 4) | ((g & 0x10) >> 3) | ((b & 0x10) >> 2);
+                               d[4] = ((r & 0x08) >> 3) | ((g & 0x08) >> 2) | ((b & 0x08) >> 1);
+                               d[5] = ((r & 0x04) >> 2) | ((g & 0x04) >> 1) | ((b & 0x04) >> 0);
+                               d[6] = ((r & 0x02) >> 1) | ((g & 0x02) >> 0) | ((b & 0x02) << 1);
+                               d[7] = ((r & 0x01) >> 0) | ((g & 0x01) << 1) | ((b & 0x01) << 2);
+                       }
+                       memcpy(screen_cg[y + 1], screen_cg[y], 640);
+               }
+       }
+}
+
+#define STATE_VERSION  1
+
+void SUB::save_state(FILEIO* state_fio)
+{
+       state_fio->FputUint32(STATE_VERSION);
+       state_fio->FputInt32(this_device_id);
+       
+       MEMORY::save_state(state_fio);
+}
+
+bool SUB::load_state(FILEIO* state_fio)
+{
+       if(state_fio->FgetUint32() != STATE_VERSION) {
+               return false;
+       }
+       if(state_fio->FgetInt32() != this_device_id) {
+               return false;
+       }
+       if(!MEMORY::load_state(state_fio)) {
+               return false;
+       }
+       return true;
+}
+
diff --git a/source/src/vm/fm16beta/sub.h b/source/src/vm/fm16beta/sub.h
new file mode 100644 (file)
index 0000000..aa0465b
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+       FUJITSU FM16beta Emulator 'eFM16beta'
+
+       Author : Takeda.Toshiya
+       Date   : 2017.12.28-
+
+       [ sub system ]
+*/
+
+#ifndef _SUB_H_
+#define _SUB_H_
+
+#include "../memory.h"
+
+#define SIG_SUB_DISP   0
+#define SIG_SUB_VSYNC  1
+#define SIG_SUB_CANCEL 2
+#define SIG_SUB_KEY    3
+#define SIG_SUB_HALT   4
+#define SIG_SUB_MAINACK        5
+
+class SUB : public MEMORY
+{
+private:
+       DEVICE *d_crtc, *d_pcm, *d_main, *d_subcpu, *d_keyboard;
+       
+       uint8_t gvram[0x30000];
+       uint8_t dummy[0x8000];  // dummy plane
+       uint8_t cvram[0x1000];
+       uint8_t kvram[0x1000];
+       
+       uint8_t wram[0x1f80];
+       uint8_t sram[0x0080];
+       uint8_t rom[0x5000];
+       
+       uint8_t ank8[0x800];
+       uint8_t ank16[0x1000];
+       uint8_t kanji16[0x40000];
+       
+       uint8_t mix;
+       uint8_t update, dispctrl, pagesel;
+       uint8_t ankcg;
+       uint16_t accaddr, dispaddr;
+       
+       // main-sub
+       uint8_t attention[3];
+       uint8_t mainack;
+       
+       // interrupts
+       bool irq_cancel, irq_vsync, firq_key, firq_pen;
+       void update_irq();
+       void update_firq();
+       
+       // crtc
+       uint8_t* chreg;
+       bool disp, vsync;
+       int blink;
+       
+       // video
+       uint8_t dpal[8];
+       uint8_t outctrl;
+       
+       void update_cvram_bank();
+       void update_kvram_bank();
+       
+       // kanji
+       int kj_h, kj_l, kj_ofs, kj_row;
+       
+       // logical operation
+       uint8_t cmdreg, imgcol, maskreg, compreg[8], compbit, bankdis, tilereg[3];
+       uint16_t lofs, lsty, lsx, lsy, lex, ley;
+       void point(int x, int y, int col);
+       void line();
+       
+       uint8_t screen_txt[SCREEN_HEIGHT][SCREEN_WIDTH + 14];
+       uint8_t screen_cg[SCREEN_HEIGHT][SCREEN_WIDTH];
+//     uint8_t screen_txt[400][648];
+//     uint8_t screen_cg[400][640];
+       scrntype_t palette_txt[8];
+       scrntype_t palette_cg[8];
+       
+       void draw_text40();
+       void draw_text80();
+       void draw_cg();
+       
+       void write_memory(uint32_t addr, uint32_t data);
+       uint32_t read_memory(uint32_t addr);
+       
+public:
+       SUB(VM* parent_vm, EMU* parent_emu) : MEMORY(parent_vm, parent_emu)
+       {
+               set_device_name(_T("Sub System"));
+       }
+       ~SUB() {}
+       
+       // common functions
+       void initialize();
+       void release();
+       void reset();
+       void write_data8(uint32_t addr, uint32_t data);
+       uint32_t read_data8(uint32_t addr);
+       void write_memory_mapped_io8(uint32_t addr, uint32_t data);
+       uint32_t read_memory_mapped_io8(uint32_t addr);
+       void write_io8(uint32_t addr, uint32_t data);
+       uint32_t read_io8(uint32_t addr);
+       void write_signal(int id, uint32_t data, uint32_t mask);
+       void save_state(FILEIO* state_fio);
+       bool load_state(FILEIO* state_fio);
+       
+       // unique functions
+       void set_context_crtc(DEVICE* device)
+       {
+               d_crtc = device;
+       }
+       void set_chregs_ptr(uint8_t* ptr)
+       {
+               chreg = ptr;
+       }
+       void set_context_pcm(DEVICE* device)
+       {
+               d_pcm = device;
+       }
+       void set_context_main(DEVICE* device)
+       {
+               d_main = device;
+       }
+       void set_context_subcpu(DEVICE* device)
+       {
+               d_subcpu = device;
+       }
+       void set_context_keyboard(DEVICE* device)
+       {
+               d_keyboard = device;
+       }
+       void key_down(int code);
+       void key_up(int code);
+       void draw_screen();
+};
+
+#endif
index dc3a99d..018cb18 100644 (file)
@@ -171,7 +171,7 @@ void MEMORY::reset()
        
        // reset logical operation
        cmdreg = maskreg = compbit = bankdis = 0;
-       memset(compreg, sizeof(compreg), 0xff);
+       memset(compreg, 0xff, sizeof(compreg));
 #endif
        dma_addr_reg = dma_wrap_reg = 0;
        dma_addr_mask = 0x00ffffff;
index 11b8960..835d985 100644 (file)
@@ -101,10 +101,11 @@ void I8237::write_io8(uint32_t addr, uint32_t data)
 void I8237::write_signal(int id, uint32_t data, uint32_t mask)
 {
        if(SIG_I8237_CH0 <= id && id <= SIG_I8237_CH3) {
-               uint8_t bit = 1 << (id & 3);
+               int ch = id - SIG_I8237_CH0;
+               uint8_t bit = 1 << ch;
                if(data & mask) {
                        if(!(req & bit)) {
-                               write_signals(&dma[id & 3].outputs_tc, 0);
+                               write_signals(&dma[ch].outputs_tc, 0);
                                req |= bit;
 #ifndef SINGLE_MODE_DMA
                                do_dma();
@@ -115,10 +116,12 @@ void I8237::write_signal(int id, uint32_t data, uint32_t mask)
                }
        } else if(SIG_I8237_BANK0 <= id && id <= SIG_I8237_BANK3) {
                // external bank registers
-               dma[id & 3].bankreg = data & mask;
+               int ch = id - SIG_I8237_BANK0;
+               dma[ch].bankreg = data & mask;
        } else if(SIG_I8237_MASK0 <= id && id <= SIG_I8237_MASK3) {
                // external bank registers
-               dma[id & 3].incmask = data & mask;
+               int ch = id - SIG_I8237_MASK0;
+               dma[ch].incmask = data & mask;
        }
 }
 
@@ -183,7 +186,7 @@ void I8237::do_dma()
 #endif
 }
 
-#define STATE_VERSION  1
+#define STATE_VERSION  2
 
 void I8237::save_state(FILEIO* state_fio)
 {
@@ -206,6 +209,7 @@ void I8237::save_state(FILEIO* state_fio)
        state_fio->FputUint8(tc);
        state_fio->FputUint32(tmp);
        state_fio->FputBool(mode_word);
+       state_fio->FputUint32(addr_mask);
 }
 
 bool I8237::load_state(FILEIO* state_fio)
@@ -232,6 +236,7 @@ bool I8237::load_state(FILEIO* state_fio)
        tc = state_fio->FgetUint8();
        tmp = state_fio->FgetUint32();
        mode_word = state_fio->FgetBool();
+       addr_mask = state_fio->FgetUint32();
        return true;
 }
 
index f7d1a4d..0d25d34 100644 (file)
@@ -55,6 +55,7 @@ protected:
        uint8_t tc;
        uint32_t tmp;
        bool mode_word;
+       uint32_t addr_mask;
 
        void write_mem(uint32_t addr, uint32_t data);
        uint32_t read_mem(uint32_t addr);
@@ -71,6 +72,7 @@ public:
                        initialize_output_signals(&dma[i].outputs_tc);
                }
                mode_word = false;
+               addr_mask = 0xffffffff;
                set_device_name(_T("i8237 DMAC"));
        }
        ~I8237_BASE() {}
@@ -112,20 +114,24 @@ public:
        }
        void set_context_tc1(DEVICE* device, int id, uint32_t mask)
        {
-               register_output_signal(&dma[0].outputs_tc, device, id, mask);
+               register_output_signal(&dma[1].outputs_tc, device, id, mask);
        }
        void set_context_tc2(DEVICE* device, int id, uint32_t mask)
        {
-               register_output_signal(&dma[0].outputs_tc, device, id, mask);
+               register_output_signal(&dma[2].outputs_tc, device, id, mask);
        }
        void set_context_tc3(DEVICE* device, int id, uint32_t mask)
        {
-               register_output_signal(&dma[0].outputs_tc, device, id, mask);
+               register_output_signal(&dma[3].outputs_tc, device, id, mask);
        }
        void set_mode_word(bool val)
        {
                mode_word = val;
        }
+       void set_address_mask(uint32_t val)
+       {
+               addr_mask = val;
+       }
 };
 
 class I8237 : public I8237_BASE {
index 6286b9c..af2839b 100644 (file)
@@ -76,18 +76,18 @@ void I8237_BASE::do_dma()
 void I8237_BASE::write_mem(uint32_t addr, uint32_t data)
 {
        if(mode_word) {
-               d_mem->write_dma_data16(addr << 1, data);
+               d_mem->write_dma_data16((addr << 1) & addr_mask, data);
        } else {
-               d_mem->write_dma_data8(addr, data);
+               d_mem->write_dma_data8(addr & addr_mask, data);
        }
 }
 
 uint32_t I8237_BASE::read_mem(uint32_t addr)
 {
        if(mode_word) {
-               return d_mem->read_dma_data16(addr << 1);
+               return d_mem->read_dma_data16((addr << 1) & addr_mask);
        } else {
-               return d_mem->read_dma_data8(addr);
+               return d_mem->read_dma_data8(addr & addr_mask);
        }
 }
 
index ddba5f8..09e1cfb 100644 (file)
@@ -9,6 +9,29 @@
 
 #include "io.h"
 
+#define IO_ADDR_MASK (addr_max - 1)
+
+void IO::initialize()
+{
+       // allocate tables here to support multiple instances with different address range
+       if(wr_table == NULL) {
+               wr_table = (wr_bank_t *)calloc(addr_max, sizeof(wr_bank_t));
+               rd_table = (rd_bank_t *)calloc(addr_max, sizeof(rd_bank_t));
+               
+               // vm->dummy must be generated first !
+               for(int i = 0; i < addr_max; i++) {
+                       wr_table[i].dev = rd_table[i].dev = vm->dummy;
+                       wr_table[i].addr = rd_table[i].addr = i;
+               }
+       }
+}
+
+void IO::release()
+{
+       free(wr_table);
+       free(rd_table);
+}
+
 void IO::write_io8(uint32_t addr, uint32_t data)
 {
        write_port8(addr, data, false);
@@ -208,12 +231,16 @@ uint32_t IO::read_port32(uint32_t addr, bool is_dma)
 
 void IO::set_iomap_single_r(uint32_t addr, DEVICE* device)
 {
+       IO::initialize(); // subclass may overload initialize()
+       
        rd_table[addr & IO_ADDR_MASK].dev = device;
        rd_table[addr & IO_ADDR_MASK].addr = addr & IO_ADDR_MASK;
 }
 
 void IO::set_iomap_single_w(uint32_t addr, DEVICE* device)
 {
+       IO::initialize();
+       
        wr_table[addr & IO_ADDR_MASK].dev = device;
        wr_table[addr & IO_ADDR_MASK].addr = addr & IO_ADDR_MASK;
 }
@@ -226,12 +253,16 @@ void IO::set_iomap_single_rw(uint32_t addr, DEVICE* device)
 
 void IO::set_iomap_alias_r(uint32_t addr, DEVICE* device, uint32_t alias)
 {
+       IO::initialize();
+       
        rd_table[addr & IO_ADDR_MASK].dev = device;
        rd_table[addr & IO_ADDR_MASK].addr = alias & IO_ADDR_MASK;
 }
 
 void IO::set_iomap_alias_w(uint32_t addr, DEVICE* device, uint32_t alias)
 {
+       IO::initialize();
+       
        wr_table[addr & IO_ADDR_MASK].dev = device;
        wr_table[addr & IO_ADDR_MASK].addr = alias & IO_ADDR_MASK;
 }
@@ -244,6 +275,8 @@ void IO::set_iomap_alias_rw(uint32_t addr, DEVICE* device, uint32_t alias)
 
 void IO::set_iomap_range_r(uint32_t s, uint32_t e, DEVICE* device)
 {
+       IO::initialize();
+       
        for(uint32_t i = s; i <= e; i++) {
                rd_table[i & IO_ADDR_MASK].dev = device;
                rd_table[i & IO_ADDR_MASK].addr = i & IO_ADDR_MASK;
@@ -252,6 +285,8 @@ void IO::set_iomap_range_r(uint32_t s, uint32_t e, DEVICE* device)
 
 void IO::set_iomap_range_w(uint32_t s, uint32_t e, DEVICE* device)
 {
+       IO::initialize();
+       
        for(uint32_t i = s; i <= e; i++) {
                wr_table[i & IO_ADDR_MASK].dev = device;
                wr_table[i & IO_ADDR_MASK].addr = i & IO_ADDR_MASK;
@@ -266,12 +301,16 @@ void IO::set_iomap_range_rw(uint32_t s, uint32_t e, DEVICE* device)
 
 void IO::set_iovalue_single_r(uint32_t addr, uint32_t value)
 {
+       IO::initialize();
+       
        rd_table[addr & IO_ADDR_MASK].value = value;
        rd_table[addr & IO_ADDR_MASK].value_registered = true;
 }
 
 void IO::set_iovalue_range_r(uint32_t s, uint32_t e, uint32_t value)
 {
+       IO::initialize();
+       
        for(uint32_t i = s; i <= e; i++) {
                rd_table[i & IO_ADDR_MASK].value = value;
                rd_table[i & IO_ADDR_MASK].value_registered = true;
@@ -280,6 +319,8 @@ void IO::set_iovalue_range_r(uint32_t s, uint32_t e, uint32_t value)
 
 void IO::set_flipflop_single_rw(uint32_t addr, uint32_t value)
 {
+       IO::initialize();
+       
        wr_table[addr & IO_ADDR_MASK].is_flipflop = true;
        rd_table[addr & IO_ADDR_MASK].value = value;
        rd_table[addr & IO_ADDR_MASK].value_registered = true;
@@ -287,6 +328,8 @@ void IO::set_flipflop_single_rw(uint32_t addr, uint32_t value)
 
 void IO::set_flipflop_range_rw(uint32_t s, uint32_t e, uint32_t value)
 {
+       IO::initialize();
+       
        for(uint32_t i = s; i <= e; i++) {
                wr_table[i & IO_ADDR_MASK].is_flipflop = true;
                rd_table[i & IO_ADDR_MASK].value = value;
@@ -296,11 +339,15 @@ void IO::set_flipflop_range_rw(uint32_t s, uint32_t e, uint32_t value)
 
 void IO::set_iowait_single_r(uint32_t addr, int wait)
 {
+       IO::initialize();
+       
        rd_table[addr & IO_ADDR_MASK].wait = wait;
 }
 
 void IO::set_iowait_single_w(uint32_t addr, int wait)
 {
+       IO::initialize();
+       
        wr_table[addr & IO_ADDR_MASK].wait = wait;
 }
 
@@ -312,6 +359,8 @@ void IO::set_iowait_single_rw(uint32_t addr, int wait)
 
 void IO::set_iowait_range_r(uint32_t s, uint32_t e, int wait)
 {
+       IO::initialize();
+       
        for(uint32_t i = s; i <= e; i++) {
                rd_table[i & IO_ADDR_MASK].wait = wait;
        }
@@ -319,6 +368,8 @@ void IO::set_iowait_range_r(uint32_t s, uint32_t e, int wait)
 
 void IO::set_iowait_range_w(uint32_t s, uint32_t e, int wait)
 {
+       IO::initialize();
+       
        for(uint32_t i = s; i <= e; i++) {
                wr_table[i & IO_ADDR_MASK].wait = wait;
        }
@@ -337,7 +388,7 @@ void IO::save_state(FILEIO* state_fio)
        state_fio->FputUint32(STATE_VERSION);
        state_fio->FputInt32(this_device_id);
        
-       for(int i = 0; i < IO_ADDR_MAX; i++) {
+       for(int i = 0; i < addr_max; i++) {
                state_fio->FputUint32(rd_table[i].value);
        }
 }
@@ -350,7 +401,7 @@ bool IO::load_state(FILEIO* state_fio)
        if(state_fio->FgetInt32() != this_device_id) {
                return false;
        }
-       for(int i = 0; i < IO_ADDR_MAX; i++) {
+       for(int i = 0; i < addr_max; i++) {
                rd_table[i].value = state_fio->FgetUint32();
        }
        return true;
index 452207b..3745254 100644 (file)
 #ifndef IO_ADDR_MAX
 #define IO_ADDR_MAX 0x100
 #endif
-#define IO_ADDR_MASK (IO_ADDR_MAX - 1)
 
 class IO : public DEVICE
 {
 private:
        // i/o map
-       struct {
+       typedef struct {
                DEVICE* dev;
                uint32_t addr;
                int wait;
                bool is_flipflop;
-       } wr_table[IO_ADDR_MAX];
+       } wr_bank_t;
        
-       struct {
+       typedef struct {
                DEVICE* dev;
                uint32_t addr;
                int wait;
                bool value_registered;
                uint32_t value;
-       } rd_table[IO_ADDR_MAX];
+       } rd_bank_t;
+       
+       wr_bank_t *wr_table;
+       rd_bank_t *rd_table;
        
        void write_port8(uint32_t addr, uint32_t data, bool is_dma);
        uint32_t read_port8(uint32_t addr, bool is_dma);
@@ -48,22 +50,21 @@ private:
 public:
        IO(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
        {
-               memset(wr_table, 0, sizeof(wr_table));
-               memset(rd_table, 0, sizeof(rd_table));
-               
-               // vm->dummy must be generated first !
-               for(int i = 0; i < IO_ADDR_MAX; i++) {
-                       wr_table[i].dev = rd_table[i].dev = vm->dummy;
-                       wr_table[i].addr = rd_table[i].addr = i;
-               }
 #ifdef _IO_DEBUG_LOG
                cpu_index = 0;
 #endif
+               addr_max = IO_ADDR_MAX;
+               
+               wr_table = NULL;
+               rd_table = NULL;
+               
                set_device_name(_T("Generic I/O Bus"));
        }
        ~IO() {}
        
        // common functions
+       void initialize();
+       void release();
        void write_io8(uint32_t addr, uint32_t data);
        uint32_t read_io8(uint32_t addr);
        void write_io16(uint32_t addr, uint32_t data);
@@ -111,6 +112,7 @@ public:
 #ifdef _IO_DEBUG_LOG
        int cpu_index;
 #endif
+       int addr_max;
 };
 
 #endif
index 373cebb..d82f397 100644 (file)
@@ -222,7 +222,7 @@ void MC6840::update_interrupts()
                                        ((m_status_reg & 0x02) && (m_control_reg[1] & 0x40)) ||
                                        ((m_status_reg & 0x04) && (m_control_reg[2] & 0x40));
 
-       if (new_state != m_IRQ)
+//     if (new_state != m_IRQ)
        {
                m_IRQ = new_state;
 
@@ -364,7 +364,9 @@ uint32_t MC6840::read_io8(uint32_t offset)
 {
        int val;
 
-       switch ( offset & 7 )
+       offset &= 7;
+
+       switch ( offset )
        {
                case PTM_6840_CTRL1:
                {
@@ -425,7 +427,9 @@ uint32_t MC6840::read_io8(uint32_t offset)
 
 void MC6840::write_io8(uint32_t offset, uint32_t data)
 {
-       switch ( offset & 7 )
+       offset &= 7;
+
+       switch ( offset )
        {
                case PTM_6840_CTRL1:
                case PTM_6840_CTRL2:
index 1d08401..d01e1a8 100644 (file)
@@ -9,23 +9,56 @@
 
 #include "memory.h"
 
-#define ADDR_MASK (MEMORY_ADDR_MAX - 1)
-#define BANK_MASK (MEMORY_BANK_SIZE - 1)
+#define ADDR_MASK (addr_max - 1)
+#define BANK_MASK (bank_size - 1)
+
+void MEMORY::initialize()
+{
+       // allocate tables here to support multiple instances with different address range
+       if(rd_table == NULL) {
+               int bank_num = addr_max / bank_size;
+               
+               rd_dummy = (uint8_t *)malloc(bank_size);
+               wr_dummy = (uint8_t *)malloc(bank_size);
+               
+               rd_table = (bank_t *)calloc(bank_num, sizeof(bank_t));
+               wr_table = (bank_t *)calloc(bank_num, sizeof(bank_t));
+               
+               for(int i = 0; i < bank_num; i++) {
+                       rd_table[i].dev = NULL;
+                       rd_table[i].memory = rd_dummy;
+                       rd_table[i].wait = 0;
+                       
+                       wr_table[i].dev = NULL;
+                       wr_table[i].memory = wr_dummy;
+                       rd_table[i].wait = 0;
+               }
+               for(int i = 0;; i++) {
+                       if(bank_size == (1 << i)) {
+                               addr_shift = i;
+                               break;
+                       }
+               }
+               memset(rd_dummy, 0xff, bank_size);
+       }
+}
 
 void MEMORY::release()
 {
-       free(read_table);
-       free(write_table);
+       free(rd_table);
+       free(wr_table);
+       free(rd_dummy);
+       free(wr_dummy);
 }
 
 uint32_t MEMORY::read_data8(uint32_t addr)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(read_table[bank].dev != NULL) {
-               return read_table[bank].dev->read_memory_mapped_io8(addr);
+       if(rd_table[bank].dev != NULL) {
+               return rd_table[bank].dev->read_memory_mapped_io8(addr);
        } else {
-               return read_table[bank].memory[addr & BANK_MASK];
+               return rd_table[bank].memory[addr & BANK_MASK];
        }
 }
 
@@ -33,10 +66,10 @@ void MEMORY::write_data8(uint32_t addr, uint32_t data)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(write_table[bank].dev != NULL) {
-               write_table[bank].dev->write_memory_mapped_io8(addr, data);
+       if(wr_table[bank].dev != NULL) {
+               wr_table[bank].dev->write_memory_mapped_io8(addr, data);
        } else {
-               write_table[bank].memory[addr & BANK_MASK] = data;
+               wr_table[bank].memory[addr & BANK_MASK] = data;
        }
 }
 
@@ -44,8 +77,8 @@ uint32_t MEMORY::read_data16(uint32_t addr)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(read_table[bank].dev != NULL) {
-               return read_table[bank].dev->read_memory_mapped_io16(addr);
+       if(rd_table[bank].dev != NULL) {
+               return rd_table[bank].dev->read_memory_mapped_io16(addr);
        } else {
                uint32_t val = read_data8(addr);
                val |= read_data8(addr + 1) << 8;
@@ -57,8 +90,8 @@ void MEMORY::write_data16(uint32_t addr, uint32_t data)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(write_table[bank].dev != NULL) {
-               write_table[bank].dev->write_memory_mapped_io16(addr, data);
+       if(wr_table[bank].dev != NULL) {
+               wr_table[bank].dev->write_memory_mapped_io16(addr, data);
        } else {
                write_data8(addr, data & 0xff);
                write_data8(addr + 1, (data >> 8) & 0xff);
@@ -69,8 +102,8 @@ uint32_t MEMORY::read_data32(uint32_t addr)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(read_table[bank].dev != NULL) {
-               return read_table[bank].dev->read_memory_mapped_io32(addr);
+       if(rd_table[bank].dev != NULL) {
+               return rd_table[bank].dev->read_memory_mapped_io32(addr);
        } else {
                uint32_t val = read_data16(addr);
                val |= read_data16(addr + 2) << 16;
@@ -82,8 +115,8 @@ void MEMORY::write_data32(uint32_t addr, uint32_t data)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(write_table[bank].dev != NULL) {
-               write_table[bank].dev->write_memory_mapped_io32(addr, data);
+       if(wr_table[bank].dev != NULL) {
+               wr_table[bank].dev->write_memory_mapped_io32(addr, data);
        } else {
                write_data16(addr, data & 0xffff);
                write_data16(addr + 2, (data >> 16) & 0xffff);
@@ -94,11 +127,11 @@ uint32_t MEMORY::read_data8w(uint32_t addr, int* wait)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       *wait = read_table[bank].wait;
-       if(read_table[bank].dev != NULL) {
-               return read_table[bank].dev->read_memory_mapped_io8(addr);
+       *wait = rd_table[bank].wait;
+       if(rd_table[bank].dev != NULL) {
+               return rd_table[bank].dev->read_memory_mapped_io8(addr);
        } else {
-               return read_table[bank].memory[addr & BANK_MASK];
+               return rd_table[bank].memory[addr & BANK_MASK];
        }
 }
 
@@ -106,11 +139,11 @@ void MEMORY::write_data8w(uint32_t addr, uint32_t data, int* wait)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       *wait = write_table[bank].wait;
-       if(write_table[bank].dev != NULL) {
-               write_table[bank].dev->write_memory_mapped_io8(addr, data);
+       *wait = wr_table[bank].wait;
+       if(wr_table[bank].dev != NULL) {
+               wr_table[bank].dev->write_memory_mapped_io8(addr, data);
        } else {
-               write_table[bank].memory[addr & BANK_MASK] = data;
+               wr_table[bank].memory[addr & BANK_MASK] = data;
        }
 }
 
@@ -153,11 +186,11 @@ uint32_t MEMORY::read_dma_data8(uint32_t addr)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(read_table[bank].dev != NULL) {
-//             return read_table[bank].dev->read_memory_mapped_io8(addr);
+       if(rd_table[bank].dev != NULL) {
+//             return rd_table[bank].dev->read_memory_mapped_io8(addr);
                return 0xff;
        } else {
-               return read_table[bank].memory[addr & BANK_MASK];
+               return rd_table[bank].memory[addr & BANK_MASK];
        }
 }
 
@@ -165,10 +198,10 @@ void MEMORY::write_dma_data8(uint32_t addr, uint32_t data)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(write_table[bank].dev != NULL) {
-//             write_table[bank].dev->write_memory_mapped_io8(addr, data);
+       if(wr_table[bank].dev != NULL) {
+//             wr_table[bank].dev->write_memory_mapped_io8(addr, data);
        } else {
-               write_table[bank].memory[addr & BANK_MASK] = data;
+               wr_table[bank].memory[addr & BANK_MASK] = data;
        }
 }
 
@@ -176,8 +209,8 @@ uint32_t MEMORY::read_dma_data16(uint32_t addr)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(read_table[bank].dev != NULL) {
-//             return read_table[bank].dev->read_memory_mapped_io16(addr);
+       if(rd_table[bank].dev != NULL) {
+//             return rd_table[bank].dev->read_memory_mapped_io16(addr);
                return 0xffff;
        } else {
                uint32_t val = read_dma_data8(addr);
@@ -190,8 +223,8 @@ void MEMORY::write_dma_data16(uint32_t addr, uint32_t data)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(write_table[bank].dev != NULL) {
-//             write_table[bank].dev->write_memory_mapped_io16(addr, data);
+       if(wr_table[bank].dev != NULL) {
+//             wr_table[bank].dev->write_memory_mapped_io16(addr, data);
        } else {
                write_dma_data8(addr, data & 0xff);
                write_dma_data8(addr + 1, (data >> 8) & 0xff);
@@ -202,8 +235,8 @@ uint32_t MEMORY::read_dma_data32(uint32_t addr)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(read_table[bank].dev != NULL) {
-//             return read_table[bank].dev->read_memory_mapped_io32(addr);
+       if(rd_table[bank].dev != NULL) {
+//             return rd_table[bank].dev->read_memory_mapped_io32(addr);
                return 0xffffffff;
        } else {
                uint32_t val = read_dma_data16(addr);
@@ -216,8 +249,8 @@ void MEMORY::write_dma_data32(uint32_t addr, uint32_t data)
 {
        int bank = (addr & ADDR_MASK) >> addr_shift;
        
-       if(write_table[bank].dev != NULL) {
-//             write_table[bank].dev->write_memory_mapped_io32(addr, data);
+       if(wr_table[bank].dev != NULL) {
+//             wr_table[bank].dev->write_memory_mapped_io32(addr, data);
        } else {
                write_dma_data16(addr, data & 0xffff);
                write_dma_data16(addr + 2, (data >> 16) & 0xffff);
@@ -229,85 +262,101 @@ void MEMORY::write_dma_data32(uint32_t addr, uint32_t data)
 
 void MEMORY::set_memory_r(uint32_t start, uint32_t end, uint8_t *memory)
 {
+       MEMORY::initialize(); // subclass may overload initialize()
+       
        uint32_t start_bank = start >> addr_shift;
        uint32_t end_bank = end >> addr_shift;
        
        for(uint32_t i = start_bank; i <= end_bank; i++) {
-               read_table[i].dev = NULL;
-               read_table[i].memory = memory + MEMORY_BANK_SIZE * (i - start_bank);
+               rd_table[i].dev = NULL;
+               rd_table[i].memory = memory + bank_size * (i - start_bank);
        }
 }
 
 void MEMORY::set_memory_w(uint32_t start, uint32_t end, uint8_t *memory)
 {
+       MEMORY::initialize();
+       
        uint32_t start_bank = start >> addr_shift;
        uint32_t end_bank = end >> addr_shift;
        
        for(uint32_t i = start_bank; i <= end_bank; i++) {
-               write_table[i].dev = NULL;
-               write_table[i].memory = memory + MEMORY_BANK_SIZE * (i - start_bank);
+               wr_table[i].dev = NULL;
+               wr_table[i].memory = memory + bank_size * (i - start_bank);
        }
 }
 
 void MEMORY::set_memory_mapped_io_r(uint32_t start, uint32_t end, DEVICE *device)
 {
+       MEMORY::initialize();
+       
        uint32_t start_bank = start >> addr_shift;
        uint32_t end_bank = end >> addr_shift;
        
        for(uint32_t i = start_bank; i <= end_bank; i++) {
-               read_table[i].dev = device;
+               rd_table[i].dev = device;
        }
 }
 
 void MEMORY::set_memory_mapped_io_w(uint32_t start, uint32_t end, DEVICE *device)
 {
+       MEMORY::initialize();
+       
        uint32_t start_bank = start >> addr_shift;
        uint32_t end_bank = end >> addr_shift;
        
        for(uint32_t i = start_bank; i <= end_bank; i++) {
-               write_table[i].dev = device;
+               wr_table[i].dev = device;
        }
 }
 
 void MEMORY::set_wait_r(uint32_t start, uint32_t end, int wait)
 {
+       MEMORY::initialize();
+       
        uint32_t start_bank = start >> addr_shift;
        uint32_t end_bank = end >> addr_shift;
        
        for(uint32_t i = start_bank; i <= end_bank; i++) {
-               read_table[i].wait = wait;
+               rd_table[i].wait = wait;
        }
 }
 
 void MEMORY::set_wait_w(uint32_t start, uint32_t end, int wait)
 {
+       MEMORY::initialize();
+       
        uint32_t start_bank = start >> addr_shift;
        uint32_t end_bank = end >> addr_shift;
        
        for(uint32_t i = start_bank; i <= end_bank; i++) {
-               write_table[i].wait = wait;
+               wr_table[i].wait = wait;
        }
 }
 
 void MEMORY::unset_memory_r(uint32_t start, uint32_t end)
 {
+       MEMORY::initialize();
+       
        uint32_t start_bank = start >> addr_shift;
        uint32_t end_bank = end >> addr_shift;
        
        for(uint32_t i = start_bank; i <= end_bank; i++) {
-               read_table[i].dev = NULL;
-               read_table[i].memory = read_dummy;
+               rd_table[i].dev = NULL;
+               rd_table[i].memory = rd_dummy;
        }
 }
 
 void MEMORY::unset_memory_w(uint32_t start, uint32_t end)
 {
+       MEMORY::initialize();
+       
        uint32_t start_bank = start >> addr_shift;
        uint32_t end_bank = end >> addr_shift;
        
        for(uint32_t i = start_bank; i <= end_bank; i++) {
-               write_table[i].dev = NULL;
-               write_table[i].memory = write_dummy;
+               wr_table[i].dev = NULL;
+               wr_table[i].memory = wr_dummy;
        }
 }
 
index 3a0c3f9..35bfa79 100644 (file)
@@ -32,43 +32,29 @@ private:
                int wait;
        } bank_t;
        
-       bank_t *read_table;
-       bank_t *write_table;
+       bank_t *rd_table;
+       bank_t *wr_table;
        
        int addr_shift;
        
-       uint8_t read_dummy[MEMORY_BANK_SIZE];
-       uint8_t write_dummy[MEMORY_BANK_SIZE];
+       uint8_t *rd_dummy;
+       uint8_t *wr_dummy;
        
 public:
        MEMORY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
        {
-               int bank_num = MEMORY_ADDR_MAX / MEMORY_BANK_SIZE;
-               
-               read_table = (bank_t *)malloc(sizeof(bank_t) * bank_num);
-               write_table = (bank_t *)malloc(sizeof(bank_t) * bank_num);
-               
-               for(int i = 0; i < bank_num; i++) {
-                       read_table[i].dev = NULL;
-                       read_table[i].memory = read_dummy;
-                       read_table[i].wait = 0;
-                       
-                       write_table[i].dev = NULL;
-                       write_table[i].memory = write_dummy;
-                       read_table[i].wait = 0;
-               }
-               for(int i = 0;; i++) {
-                       if(MEMORY_BANK_SIZE == (1 << i)) {
-                               addr_shift = i;
-                               break;
-                       }
-               }
-               memset(read_dummy, 0xff, MEMORY_BANK_SIZE);
-               set_device_name(_T("GENERIC MEMORY"));
+               addr_max = MEMORY_ADDR_MAX;
+               bank_size = MEMORY_BANK_SIZE;
+               
+               rd_table = wr_table = NULL;
+               rd_dummy = wr_dummy = NULL;
+               
+               set_device_name(_T("Generic Memory Bus"));
        }
        ~MEMORY() {}
        
        // common functions
+       void initialize();
        void release();
        uint32_t read_data8(uint32_t addr);
        void write_data8(uint32_t addr, uint32_t data);
@@ -124,6 +110,9 @@ public:
        bool write_bios(const _TCHAR *file_name, uint8_t *buffer, int size);
        bool read_image(const _TCHAR *file_path, uint8_t *buffer, int size);
        bool write_image(const _TCHAR *file_path, uint8_t *buffer, int size);
+       
+       int addr_max;
+       int bank_size;
 };
 
 #endif
index f5936df..cd11e3a 100644 (file)
@@ -291,16 +291,21 @@ VM::VM(EMU* parent_emu) : emu(parent_emu)
        // dma ch.1: memory refresh
 #if defined(SUPPORT_2HD_FDD_IF)
        dma->set_context_ch2(fdc_2hd);
+       dma->set_context_tc2(fdc_2hd, SIG_UPD765A_TC, 1);
 #endif
 #if defined(SUPPORT_2DD_FDD_IF)
        dma->set_context_ch3(fdc_2dd);
+       dma->set_context_tc3(fdc_2dd, SIG_UPD765A_TC, 1);
 #endif
 #if defined(SUPPORT_2HD_2DD_FDD_IF)
 #if !defined(SUPPORT_HIRESO)
        dma->set_context_ch2(fdc);
        dma->set_context_ch3(fdc);
+       dma->set_context_tc2(fdc, SIG_UPD765A_TC, 1);
+       dma->set_context_tc3(fdc, SIG_UPD765A_TC, 1);
 #else
        dma->set_context_ch1(fdc);
+       dma->set_context_tc1(fdc, SIG_UPD765A_TC, 1);
 #endif
 #endif
 //     sio_rs->set_context_rxrdy(pic, SIG_I8259_CHIP0 | SIG_I8259_IR4, 1);
index 5365a2b..36bb82e 100644 (file)
@@ -711,13 +711,13 @@ void UPD765A::cmd_sence_intstat()
 uint8_t UPD765A::get_devstat(int drv)
 {
        if(drv >= _max_drive) {
-               return 0x80 | drv;
+               return ST3_FT | drv;
        }
        // XM8 version 1.20
        if(force_ready && !disk[drv]->inserted) {
                return drv;
        }
-       return 0x28 | drv | (fdc[drv].track ? 0 : 0x10) | ((fdc[drv].track & 1) ? 0x04 : 0) | (disk[drv]->write_protected ? 0x40 : 0);
+       return drv | ((fdc[drv].track & 1) ? ST3_HD : 0) | (disk[drv]->inserted && disk[drv]->two_side ? ST3_TS : 0) | (fdc[drv].track ? 0 : ST3_T0) | (force_ready || disk[drv]->inserted ? ST3_RY : 0) | (disk[drv]->write_protected ? ST3_WP : 0);
 }
 
 void UPD765A::cmd_seek()
@@ -1123,6 +1123,9 @@ uint32_t UPD765A::read_sector()
 #endif
                        continue;
                }
+#ifdef _FDC_DEBUG_LOG
+               this->out_debug_log(_T("FDC: SECTOR FOUND (TRK=%d SIDE=%d ID=%2x,%2x,%2x,%2x)\n"), trk, side, id[0], id[1], id[2], id[3]);
+#endif
                if(disk[drv]->sector_size.sd == 0) {
                        continue;
                }
index 1fe5be4..9403d0b 100644 (file)
 #include "fm7/fm7.h"
 #endif
 
+// FUJITSU FM16beta
+#ifdef _FM16BETA
+#include "fm16beta/fm16beta.h"
+#endif
+
 // FUJITSU FM16pi
 #ifdef _FM16PI
 #include "fm16pi/fm16pi.h"