message("* vm/fm-towns")
add_library(vm_fmtowns
- cmos.cpp
floppy.cpp
keyboard.cpp
scsi.cpp
timer.cpp
+
+ serialrom.cpp
+ sysrom.cpp
+ dictionary.cpp
+ msdosrom.cpp
+
+ fontroms.cpp
+
towns_crtc.cpp
towns_memory.cpp
towns_sprite.cpp
towns_vram.cpp
-)
\ No newline at end of file
+)
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2019.01.09 -
+
+ [fonts]
+*/
+
+#inclide "../towns_common.h"
+#include "../../fileio.h"
+#include "./fontroms.h"
+
+namespace FMTOWNS {
+
+void FONT_ROMS::initialize()
+{
+ wait_val = 3;
+ memset(font_kanji16, sizeof(font_kanji16), 0xff);
+ FILEIO* fio = new FILEIO();
+
+ if(fio->Fopen(create_local_path(_T("FMT_FNT.ROM")), FILEIO_READ_BINARY)) { // FONT
+ fio->Fread(font_kanji16, sizeof(font_kanji16), 1);
+ fio->Fclose();
+ }
+
+#if defined(HAVE_20PIXS_FONT)
+ memset(font_kanji20, sizeof(font_kanji20), 0xff);
+ if(fio->Fopen(create_local_path(_T("FMT_F20.ROM")), FILEIO_READ_BINARY)) { // FONT
+ fio->Fread(font_kanji20, sizeof(font_kanji20), 1);
+ fio->Fclose();
+ }
+#endif
+
+ delete fio;
+}
+
+uint32_t FONT_ROMS::read_data8(uint32_t addr)
+{
+ if((addr >= 0xc2100000) && (addr < 0xc2140000)) {
+ return (uint32_t)(font_kanji16[addr & 0x3ffff]);
+ } else if((addr >= 0xc2180000) && (addr < 0xc2200000)) {
+#if defined(HAVE_20PIXS_FONT)
+ return (uint32_t)(font_kanji20[addr & 0x7ffff]);
+#else
+ return 0xff;
+#endif
+ } else if((addr >= 0x000ca000) && (addr < 0x000ca800)) {
+ return (uint32_t)(font_kanji16[0x1e800 + (addr & 0x7ff)]);
+ } else if((addr >= 0x000cb000) && (addr < 0x000cc000)) {
+ return (uint32_t)(font_kanji16[0x1f000 + (addr & 0x7ff)]);
+ }
+ return 0xff;
+}
+
+uint32_t FONT_ROMS::read_data8w(uint32_t addr, int* wait)
+{
+ if(wait != NULL) *wait = wait_val;
+ return read_data8(addr);
+}
+
+void FONT_ROMS::write_data8w(uint32_t addr, uint32_t data, int* wait)
+{
+ if(wait != NULL) *wait = wait_val;
+}
+
+void FONT_ROMS::write_signal(int ch, uint32_t data, uint32_t mask)
+{
+ if(ch == SIG_FMTOWNS_SET_MEMWAIT) {
+ wait_val = (int)data;
+ }
+}
+
+#define STATE_VERSION 1
+
+bool FONT_ROMS::process_state(FILEIO* state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ state_fio->StateValue(wait_val);
+
+ return true;
+}
+
+}
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2019.01.09 -
+
+ [fonts]
+*/
+
+#pragma once
+
+#include "../vm.h"
+#include "../device.h"
+
+namespace FMTOWNS {
+
+class FONT_ROMS : public DEVICE
+{
+protected:
+ int wait_val;
+ uint8_t font_kanji16[0x40000];
+#if defined(HAVE_20PIXS_FONT)
+ uint8_t font_kanji20[0x80000];
+#endif
+public:
+ FONT_ROMS(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+ {
+ set_device_name("Font Roms");
+ }
+ ~FONT_ROMS() {}
+
+ void initialize();
+
+ uint32_t read_data8(uint32_t addr);
+ uint32_t read_data8w(uint32_t addr, int* wait);
+ void write_data8w(uint32_t addr, uint32_t data, int* wait);
+ void write_signal(int ch, uint32_t data, uint32_t mask);
+ bool process_state(FILEIO* state_fio, bool loading);
+};
+
+}
+
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2019.01.09 -
+
+ [MSDOS ROM]
+*/
+
+#include "./towns_common.h"
+#include "./msdosrom.h"
+
+namespace FMTOWNS {
+
+void MSDOSROM::initialize()
+{
+ memset(rom, 0xff, sizeof(rom));
+ FILEIO *fio;
+ if(fio->Fopen(create_local_path(_T("FMT_DOS.ROM")), FILEIO_READ_BINARY)) { // MSDOS
+ fio->Fread(rom, sizeof(rom), 1);
+ fio->Fclose();
+ }
+ delete fio;
+
+ wait_val = 3;
+}
+
+uint32_t MSDOSROM::read_data8(uint32_t addr)
+{
+ uint8_t d = 0xff;
+ if((addr >= 0xc2000000) && (addr < 0xc2080000)) {
+ d = rom[addr & 0x7ffff];
+ }
+ return (uint32_t)d;
+}
+
+uint32_t MSDOSROM::read_data8w(uint32_t addr, int* wait)
+{
+ if(wait != NULL) *wait = wait_val;
+ return read_data8(addr);
+}
+void MSDOSROM::write_data8w(uint32_t addr, uint32_t data, int* wait)
+{
+ if(wait != NULL) *wait = wait_val;
+}
+
+void MSDOSROM::write_signal(int ch, uint32_t data, uint32_t mask)
+{
+ switch(ch) {
+ case SIG_FMTOWNS_SET_MEMWAIT:
+ wait_val = (int)data;
+ break;
+ }
+}
+
+uint32_t MSDOSROM::read_signal(int ch)
+{
+ switch(ch) {
+ case SIG_FMTOWNS_SET_MEMWAIT:
+ return (uint32_t)wait_val;
+ break;
+ }
+ return 0;
+}
+
+#define STATE_VERSION 1
+
+bool DICTIONARY::process_state(FILEIO* state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ state_fio->StateValue(wait_val);
+ return true;
+}
+
+}
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2018.01.09 -
+
+ [ msdos rom ]
+*/
+#pragma once
+
+#include "../device.h"
+
+namespace FMTOWNS {
+
+class MSDOSROM : public DEVICE
+{
+private:
+ uint8_t rom[0x80000]; // 0xc2000000 - 0xc207ffff
+public:
+ MSDOSROM(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) {
+ set_device_name(_T("MSDOS ROM"));
+ }
+ ~MSDOSROM() {}
+
+ void initialize();
+
+};
+
+}
+
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2019.01.09 -
+
+ [serial rom]
+*/
+
+#include "../../fileio.h"
+#include "./towns_memory.h"
+#include "./serialrom.h"
+#include "../i386.h"
+
+namespace FMTOWNS {
+
+void SERIAL_ROM::initialize()
+{
+ cs = true;
+ clk = false;
+ reset_reg = false;
+ reset_state = 0;
+ rom_addr = 0;
+
+ memset(rom, 0xff, sizeof(rom));
+ FILEIO *fio = new FULEIO();
+ if(fio->Fopen(create_local_path(_T("MYTOWNS.ROM")), FILEIO_READ_BINARY)) { // FONT
+ fio->Fread(rom, sizeof(rom), 1);
+ fio->Fcolose();
+ } else if(fio->Fopen(create_local_path(_T("SERIAL.ROM")), FILEIO_READ_BINARY)) { // FONT
+ fio->Fread(rom, sizeof(rom), 1);
+ fio->Fcolose();
+ } else {
+ // Header
+ const _TCHAR *id = _T("FUJITSU");
+ int _len = strlen(id);
+ if(_len < 0) _len = 0; // Bit 251 - 72
+ if(_len >= 22) _len = 21; // Bit 251 - 72
+ for(int i = 0; i < (_len + 1); i++) {
+ rom[32 - i] = 0x00;
+ }
+ for(int i = 0; i < _len; i++) {
+ uint8_t _c = (uint8_t)id[i];
+ uint8_t _revc = 0x00;
+ uint8_t val = 0x80;
+ for(int j = 0; j < 8; j++) {
+ if((_c & 0x01) != 0) _revc = _revc | val;
+ val >>= 1;
+ _c >>= 1;
+ }
+ rom[31 - i] = rom[31 - i] | ((_revc & 0xf0) >> 4); // High
+ rom[31 - (i + 1)] = rom[31 - (i + 1)] | ((_revc & 0x0f) << 4); // Low
+ }
+ rom[31 - _len] = rom[31 - _len] | 0x0f; // Last bit
+ // Machine ID (bit 71 - bit 56) must be dummy.
+
+ // Serial (bit 55 - bit20)
+ auto serial = static_cast<uint64_t>(0x00000123);
+ auto nmask = static_cast<uint64_t>(0x0f);
+ nmask = nmask << 32;
+ int nibblepos = 8;
+ // Initialize footer and serial ID.
+ for(int i = 0; i < 7; i++) {
+ rom[7 - i] = 0x00;
+ }
+
+ for(int i = 0; i < 9; i++) {
+ uint64_t nval = (nmask & serial) >> 32;
+ uint8_t _c = ((uint8_t)nval) & 0x0f;
+ uint8_t _revc = 0x00;
+ uint8_t val = 0x08;
+ for(int j = 0; j < 4; j++) {
+ if((_c & 0x01) != 0) _revc = _revc | val;
+ val >>= 1;
+ _c >>= 1;
+ }
+ serial <<= 4;
+ // High
+ if((i & 1) == 0) { // Lower
+ rom[6 - (i / 2)] = rom[6 - (i / 2)] | (_revc << 4);
+ } else { // Lower
+ rom[6 - (i / 2)] = rom[6 - (i / 2)] | _revc;
+ }
+ }
+ }
+}
+
+void SERIAL_ROM::reset()
+{
+// cs = true;
+// clk = 0;
+// reset_state = 0;
+// rom_addr = 0;
+}
+
+void SERIAL_ROM::write_signal(int ch, uint32_t data, uint32_t mask)
+{
+ switch(ch) {
+ case SIG_SERIAL_ROM_CLK:
+ {
+ bool oldclk = clk;
+ bool newclk = clk;
+ if(cs) {
+ newclk = ((data & mask) != 0);
+ }
+ if((oldclk != newclk) && !(reset_reg)) {
+ clk = newclk;
+ if(!(oldclk)) {
+ // Rise up
+ rom_addr = (rom_addr + 1) & 0xff;
+ }
+ }
+ }
+ break;
+ case SIG_SERIAL_ROM_CS:
+ cs = ((data & mask) == 0);
+ break;
+ case SIG_SERIAL_ROM_RESET:
+ reset_reg = ((data & mask) != 0);
+ if((cs) && (clk)) {
+ switch(reset_state) {
+ case 0:
+ if(reset_reg) reset_state++;
+ break;
+ case 1:
+ if(!(reset_reg)) {
+ // Do Reset
+ rom_addr = 0;
+ reset_state = 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ }
+ break;
+ }
+}
+
+uint32_t SERIAL_ROM::read_signal(int ch)
+{
+ switch(ch) {
+ case SIG_SERIALROM_CLK:
+ return ((clk) ? 0xffffffff : 0x00000000);
+ break;
+ case SIG_SERIALROM_CS:
+ return 0;
+ break;
+ case SIG_SERIALROM_RESET:
+ return ((reset_reg) ? 0xffffffff : 0x00000000);
+ break;
+ case SIG_SERIALROM_DATA:
+ {
+ if((rom_addr >= 56) && (rom_addr < 72)) {
+ // Serial id
+ uint32_t machine_id = d_mem->read_signal(SIG_FMTOWNS_MACHINE_ID);
+ uint32_t bitaddr = 15 - (rom_addr - 56);
+ uint32_t bitmask = 0x8000 >> bitaddr;
+ return (((bitmask & machine_id) != 0) ? 0xffffffff : 0x00000000);
+ } else {
+ uint32_t localaddr = (rom_addr & 0xff) >> 3;
+ uint32_t localbit = (rom_addr & 0xff) & 0x07;
+ uint8_t _c = rom[localaddr];
+ uint8_t _bmask = 0x01 << localbit;
+ return (((_c & _bmask) != 0) ? 0xffffffff : 0x00000000);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+#define STATE_VERSION 1
+
+bool SERIAL_ROM::process_state(FILEIO* state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ state_fio->StateValue(cs);
+ state_fio->StateValue(clk);
+ state_fio->StateValue(reset_reg);
+ state_fio->StateValue(reset_state);
+ state_fio->StateValue(rom_addr);
+ state_fio->StateArray(rom, sizeof(rom), 1);
+
+ return true;
+}
+
+}
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2019.01.09 -
+
+ [serial rom]
+*/
+
+#pragma once
+
+#include "../device.h"
+
+#define SIG_SERIALROM_CLK 1
+#define SIG_SERIALROM_CS 2
+#define SIG_SERIALROM_RESET 3
+#define SIG_SERIALROM_DATA 4
+
+namespace FMTOWNS {
+
+class SERIAL_ROM : public DEVICE
+{
+protected:
+ DEVICE* d_mem;
+
+ bool cs;
+ bool clk;
+ bool reset_reg;
+ int reset_state;
+ uint8_t rom_addr;
+ uint8_t rom[32];
+
+public:
+ SERIAL_ROM(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) {
+ set_device_name(_T("FMTOWNS_SERIAL_ROM"));
+ d_mem = NULL;
+ }
+ ~SERIAL_ROM() {}
+
+ void initialize();
+ void reset();
+
+ void write_signal(int ch, uint32_t data, uint32_t mask);
+ uint32_t read_signal(int ch);
+
+ bool process_state(FILEIO* state_fio, bool loading);
+
+ void set_context_mem(DEVICE* dev)
+ {
+ d_mem = dev;
+ }
+};
+
+}
+
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2019.01.09-
+
+ [ dictionary rom/ram & cmos & RAM area 0x000d0000 - 0x000effff]
+*/
+
+#include "./towns_common.h"
+#include "./towns_dictrom.h"
+#include "./towns_sysrom.h"
+#include "../../fileio.h"
+
+namespace FMTOWNS {
+void DICTIONARY::initialize()
+{
+ cmos_dirty = false;
+
+ memset(dict_rom, 0xff, sizeof(dict_rom));
+ memset(dict_ram, 0x00, sizeof(dict_ram));
+ memset(ram_0d0, 0x00, sizeof(ram_0d0));
+
+ FILEIO* fio = new FILEIO();
+ if(fio->Fopen(create_local_path(_T("FMT_DIC.ROM")), FILEIO_READ_BINARY)) { // DICTIONARIES
+ fio->Fread(dict_rom, sizeof(dict_rom), 1);
+ fio->Fclose();
+ }
+
+ if(fio->Fopen(create_local_path(_T("FMT_CMOS.BIN")), FILEIO_READ_BINARY)) {
+ fio->Fread(dict_ram, sizeof(dict_ram), 1);
+ fio->Fclose();
+ } else {
+ cmos_dirty = true;
+ }
+ delete fio;
+
+ wait_val = 3;
+ dict_bank = 0;
+ bankd0_dict = false;
+}
+
+void DICTIONARY::release()
+{
+ if(cmos_dirty) {
+ FILEIO* fio = new FILEIO();
+ if(fio->Fopen(create_local_path(_T("FMT_CMOS.BIN")), FILEIO_WRITE_BINARY)) {
+ fio->Fwrite(dict_ram, sizeof(dict_ram), 1);
+ fio->Fclose();
+ }
+ delete fio;
+ }
+}
+
+void DICTIONARY::reset()
+{
+ //wait_val = 6; // OK?
+ dict_bank = 0;
+ bankd0_dict = false;
+
+}
+uint32_t DICTIONARY::read_data8(uint32_t addr)
+{
+ uint8_t n_data = 0xff;
+ if((addr < 0x000f0000) && (addr >= 0x000d0000)) {
+ if(bankd0_dict) {
+ if(addr < 0x000d8000) {
+ n_data = dict_rom[(addr & 0x7fff) + (((uint32_t)(dict_bank & 0x0f)) << 15)];
+ } else if(addr < 0x000da000) {
+ n_data = dict_ram[addr & 0x1fff];
+ }/* else { // ToDo: Check correctness
+ n_data = 0xff;
+ }*/
+ } else {
+ n_data = ram_0d0[addr & 0x1ffff];
+ }
+ } else if((addr >= 0xc20800000) && (addr < 0xc2100000)) {
+ n_data = dict_rom[addr & 0x7ffff];
+ } else if((addr >= 0xc21400000) && (addr < 0xc2142000)) {
+ n_data = dict_ram[addr & 0x1fff];
+ }
+ return n_data;
+}
+
+void DICTIONARY::write_data8(uint32_t addr, uint32_t data)
+{
+ if((addr < 0x000f0000) && (addr >= 0x000d0000)) {
+ if(bankd0_dict) {
+ if((addr >= 0x000d8000) && (addr < 0x000da000)) {
+ cmos_dirty = true;
+ dict_ram[addr & 0x1fff] = data; // ToDo: Check correctness
+ } /* else { // ToDo: Check correctness
+
+ }*/
+ } else {
+ ram_0d0[addr & 0x1ffff] = (uint8_t)data;
+ }
+ } else if((addr >= 0xc21400000) && (addr < 0xc2142000)) {
+ dict_ram[addr & 0x1fff] = (uint8_t)data;
+ }
+}
+
+uint32_t DICTIONARY::read_data16(uint32_t addr)
+{
+ pair16_t n;
+ addr = addr & 0xfffffffe;
+ n.l = (uint8_t)read_data8(addr + 0);
+ n.h = (uint8_t)read_data8(addr + 1);
+ return (uint32_t)(n.u16);
+}
+
+uint32_t DICTIONARY::read_data32(uint32_t addr)
+{
+ pair32_t n;
+ addr = addr & 0xfffffffc;
+ n.l = (uint8_t)read_data8(addr + 0);
+ n.h = (uint8_t)read_data8(addr + 1);
+ n.h2 = (uint8_t)read_data8(addr + 2);
+ n.h3 = (uint8_t)read_data8(addr + 3);
+ return n.u32;
+}
+
+void DICTIONARY::write_data16(uint32_t addr, uint32_t data)
+{
+ pair16_t n;
+ addr = addr & 0xfffffffe;
+ n.u16 = (uint16_t)data;
+ write_data8(addr + 0, n.l);
+ write_data8(addr + 1, n.h);
+}
+
+void DICTIONARY::write_data32(uint32_t addr, uint32_t data)
+{
+ pair32_t n;
+ addr = addr & 0xfffffffc;
+ n.u32 = data;
+ write_data8(addr + 0, n.l);
+ write_data8(addr + 1, n.h);
+ write_data8(addr + 2, n.h2);
+ write_data8(addr + 3, n.h3);
+}
+
+uint32_t DICTIONARY::read_data8w(uint32_t addr, int *wait)
+{
+ if(wait != NULL) *wait = wait_val;
+ return read_data8(addr, data);
+}
+
+uint32_t DICTIONARY::read_data16w(uint32_t addr, int *wait)
+{
+ if(wait != NULL) *wait = wait_val * 2;
+ return read_data16(addr, data);
+}
+
+uint32_t DICTIONARY::read_data32w(uint32_t addr, int *wait)
+{
+ if(wait != NULL) *wait = wait_val * 4;
+ return read_data32(addr, data);
+}
+
+
+void DICTIONARY::write_data8w(uint32_t addr, uint32_t data, int *wait)
+{
+ if(wait != NULL) *wait = wait_val;
+ write_data8(addr, data);
+}
+
+void DICTIONARY::write_data16w(uint32_t addr, uint32_t data, int *wait)
+{
+ if(wait != NULL) *wait = wait_val * 2;
+ write_data16(addr, data);
+}
+
+void DICTIONARY::write_data32w(uint32_t addr, uint32_t data, int *wait)
+{
+ if(wait != NULL) *wait = wait_val * 4;
+ write_data32(addr, data);
+}
+
+void DICTIONARY::write_io8(uint32_t addr, uint32_t data)
+{
+ if(addr == 0x0480) {
+ bankd0_dict = ((data & 0x01) != 0);
+ d_sysrom->write_signal(SIG_FMTONWS_SYSROMSEL, data, 0x02);
+ } else if(addr == 0x0484) {
+ dict_bank = data & 0x0f;
+ } else if((addr >= 0x3000) && (addr < 0x4000)) {
+ if((addr & 0x0001) == 0) { // OK?
+ uint32_t naddr = (addr >> 1) & 0x7ff;
+ cmos_dirty = true;
+ dict_ram[naddr] = (uint8_t)data;
+ }
+ }
+}
+
+uint32_t DICTIONARY::read_io8(uint32_t addr)
+{
+ uint32_t data;
+ if(addr == 0x0480) {
+ data = ((bank0_dict) ? 0x01 : 0x00) | ((d_sysrom->read_signal(SIG_FMTOWNS_SYSROMSEL) == 0) ? 0x02 : 0x00);
+ } else if(addr == 0x0484) {
+ data = dict_bank & 0x0f;
+ } else if((addr >= 0x3000) && (addr < 0x4000)) {
+ if((addr & 0x0001) == 0) { // OK?
+ uint32_t naddr = (addr >> 1) & 0x7ff;
+ data = dict_ram[naddr];
+ } else {
+ data = 0xff;
+ }
+ } else {
+ data = 0xff;
+ }
+ return data;
+}
+
+void DICTIONARY::write_signal(int ch, uint32_t data, uint32_t mask)
+{
+ switch(ch) {
+ case SIG_FMTOWNS_DICTSEL:
+ bankd0_dict = ((data & mask) != 0);
+ break;
+ case SIG_FMTOWNS_DICTBANK:
+ dict_bank = (uint8_t)(data & 0x0f);
+ break;
+ case SIG_FMTOWNS_SET_MEMWAIT:
+ wait_val = (int)data;
+ break;
+ }
+}
+
+uint32_t DICTIONARY::read_signal(int ch)
+{
+ switch(ch) {
+ case SIG_FMTOWNS_DICTSEL:
+ return ((bankd0_dict) ? 0xffffffff : 0x00000000);
+ break;
+ case SIG_FMTOWNS_DICTBANK:
+ return (uint32_t)(dict_bank & 0x0f);
+ break;
+ case SIG_FMTOWNS_SET_MEMWAIT:
+ return (uinrt32_t)wait_val;
+ break;
+ }
+ return 0x00;
+}
+
+#define STATE_VERSION 1
+
+bool DICTIONARY::process_state(FILEIO* state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ state_fio->StateValue(wait_val);
+ state_fio->StateValue(dict_bank);
+ state_fio->StateValue(bankd0_dict);
+ state_fio->StateArray(dict_ram, sizeof(dict_ram), 1);
+ state_fio->StateArray(ram_0d0, sizeof(ram_0d0), 1);
+
+ if(loading) {
+ cmos_dirty = true;
+ }/* else {
+ FILEIO* fio = new FILEIO();
+ if(fio->Fopen(create_local_path(_T("FMT_CMOS.BIN")), FILEIO_WRITE_BINARY)) {
+ fio->Fwrite(dict_ram, sizeof(dict_ram), 1);
+ fio->Fclose();
+ }
+ delete fio;
+ cmos_dirty = false;
+ } */
+ return true;
+}
+}
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2019.01.09-
+
+ [ dictionary rom/ram & cmos & RAM area 0x000d0000 - 0x000effff]
+*/
+
+#pragma once
+
+#include "../../common.h"
+#include "../device.h"
+
+#define SIG_FMTOWNS_DICTSEL 0x1000
+#define SIG_FMTOWNS_DICTBANK 0x1001
+
+namespace FMTOWNS {
+
+class DICTIONARY : public DEVICE
+{
+protected:
+ DEVICE *d_sysrom;
+
+ uint8_t dict_rom[0x80000]; // 512KB
+ uint8_t dict_ram[0x2000]; // 2 + 6KB
+ uint8_t ram_0d0[0x20000]; // 128KB
+
+ bool bankd0_dict;
+ uint8_t dict_bank;
+ int wait_val;
+
+ bool cmos_dirty;
+
+public:
+ DICTIONARY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+ {
+ set_device_name("FM-Towns Dictionary ROM/RAM 0x000d0000 - 0x000effff with CMOS RAM");
+ }
+ ~DICTIONARY() {}
+ void initialize();
+ void release();
+ void reset();
+
+ uint32_t read_data8(uint32_t addr);
+ uint32_t read_data16(uint32_t addr);
+ uint32_t read_data32(uint32_t addr);
+
+ uint32_t read_data8w(uint32_t addr, int* wait);
+ uint32_t read_data16w(uint32_t addr, int* wait);
+ uint32_t read_data32w(uint32_t addr, int* wait);
+
+ void write_data8(uint32_t addr, uint32_t data);
+ void write_data16(uint32_t addr, uint32_t data);
+ void write_data32(uint32_t addr, uint32_t data);
+
+ void write_data8w(uint32_t addr, uint32_t data, int* wait);
+ void write_data16w(uint32_t addr, uint32_t data, int* wait);
+ void write_data32w(uint32_t addr, uint32_t data, int* wait);
+
+ void write_io8(uint32_t addr, uint32_t data);
+ void read_io8(uint32_t addr, uint32_t data);
+
+ void write_signal(int ch, uint32_t data, uint32_t mask);
+ uint32_t read_signal(int ch);
+
+ bool process_state(FILEIO* state_fio, bool loading);
+
+ void set_context_sysrom(DEVICE* dev)
+ {
+ d_sysrom = dev;
+ }
+};
+
+}
+
+// END
Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
Date : 2017.01.01 -
- [ memory]
+ [memory]
*/
+#include "../../fileio.h"
#include "./towns_memory.h"
#include "../i386.h"
void TOWNS_MEMORY::initialize()
{
- bankf8_ram = false;
- bankd0_dict = false;
- dict_bank = 0;
extra_nmi_mask = true;
extra_nmi_val = false;
vram_wait_val = 6;
mem_wait_val = 3;
- machine_id = 0x0100; // FM-Towns 1,2
- // machine_id = 0x0200 // FM-Towns 1F/2F/1H/2H
- // machine_id = 0x0300 // FM-Towns UX10/UX20/UX40
- // machine_id = 0x0400 // FM-Towns 10F/20F/40H/80H
- // machine_id = 0x0500 // FM-Towns2 CX10/CX20/CX40/CX100
- // machine_id = 0x0600 // FM-Towns2 UG10/UG20/UG40/UG80
- // machine_id = 0x0700 // FM-Towns2 HR20/HR100/HR200
- // machine_id = 0x0800 // FM-Towns2 HG20/HG40/HG100
- // machine_id = 0x0900 // FM-Towns2 UR20/UR40/UR80
- // machine_id = 0x0b00 // FM-Towns2 MA20/MA170/MA340
- // machine_id = 0x0c00 // FM-Towns2 MX20/MX170/MX340
- // machine_id = 0x0d00 // FM-Towns2 ME20/ME170
- // machine_id = 0x0f00 // FM-Towns2 MF20/MF170/Fresh
- //cpu_id = 0x00; // 80286.
- cpu_id = 0x01; // 80386DX.
- //cpu_id = 0x02; // 80486SX/DX.
- //cpu_id = 0x03; // 80386SX.
-
-
- memset(ram_page0, 0x00, sizeof(ram_page0));
- memset(ram_0f0, 0x00, sizeof(ram_0f0));
- memset(ram_0f8, 0x00, sizeof(ram_0f8));
- memset(rom_msdos, 0xff, sizeof(rom_msdos));
- memset(rom_font1, 0xff, sizeof(rom_font1));
-#if 0
- memset(rom_font20, 0xff, sizeof(rom_font20));
-#endif
- memset(rom_dict, 0xff, sizeof(rom_dict));
- memset(rom_system, 0xff, sizeof(rom_system));
+ memset(ram_page0, 0x00, sizeof(ram_page0));
// load rom image
- FILEIO* fio = new FILEIO();
- if(fio->Fopen(create_local_path(_T("FMT_SYS.ROM")), FILEIO_READ_BINARY)) { // SYSTEM
- fio->Fread(rom_system, sizeof(rom_system), 1);
- fio->Fclose();
- }
- if(fio->Fopen(create_local_path(_T("FMT_FNT.ROM")), FILEIO_READ_BINARY)) { // FONT
- fio->Fread(rom_font1, sizeof(rom_font1), 1);
- fio->Fclose();
- }
#if 0
if(fio->Fopen(create_local_path(_T("FMT_F20.ROM")), FILEIO_READ_BINARY)) { // 20 pixels FONT : Optional
fio->Fread(rom_font20, sizeof(rom_font20), 1);
fio->Fclose();
}
#endif
- if(fio->Fopen(create_local_path(_T("FMT_DOS.ROM")), FILEIO_READ_BINARY)) { // MSDOS
- fio->Fread(msdos_rom, sizeof(msdos_rom), 1);
- fio->Fclose();
- }
- if(fio->Fopen(create_local_path(_T("FMT_DIC.ROM")), FILEIO_READ_BINARY)) { // DICTIONARIES
- fio->Fread(dict_rom, sizeof(dict_rom), 1);
- fio->Fclose();
- }
// ToDo: Will move to config.
extram_size = TOWNS_EXTRAM_PAGES * 0x100000;
// ToDo: Limit extram_size per VM.
break;
case TOWNS_MEMORY_SPRITE_ANKCG1:
if(!mainmem_enabled) {
- if((ankcg_enabled) && ((addr & 0xfff) < 0x800)) {
- *mask = 0x7ff;
- *readp = (void*)(&(rom_font1[(addr & 0x7ff) + 0x3d000]));
- *writep = (void*)(&(ram_0ca[addr & 0x7ff]));
+ if(ankcg_enabled) {
+ *offset = 0x000ca000;
+ *mask = 0x0fff;
+ *readfn = (void *)d_fonts;
+ *writefn = (void *)d_fonts;
} else {
*offset = 0x2000 + FMTOWNS_VRAM_TEXT_VRAM;
- *mask = 0xfff;
+ *mask = 0x0fff;
*readfn = (void *)d_vram;
*writefn = (void *)d_vram;
}
break;
case TOWNS_MEMORY_SPRITE_ANKCG2:
if(!(mainmem_enabled) && (ankcg_enabled)) {
- *readp = (void*)(&(rom_font1[(addr & 0x0fff) + 0x3d800]));
- *writep = (void*)(&(ram_0cb[addr & 0xfff]));
+ *offset = 0x000cb000;
*mask = 0x0fff;
+ *readfn = (void *)d_fonts;
+ *writefn = (void *)d_fonts;
} else {
*readp = (void*)(&(ram_0cb[addr & 0xfff]));
*writep = (void*)(&(ram_0cb[addr & 0xfff]));
*offset = 0;
}
break;
- case TOWNS_MEMORY_DICT_0D0:
- if(bankd0_dict) {
- *readp = (void*)(&(dict_rom[(addr & 0x7fff) + (((uint32_t)(dict_bank & 0x0f)) << 15))]);
- *writep = (void*)(&(ram_0d0[addr & 0x7fff]));
- } else {
- *readp = (void*)(&(ram_0d0[addr & 0x7fff]));
- *writep = (void*)(&(ram_0d0[addr & 0x7fff]));
- }
- break;
- case TOWNS_MEMORY_CMOS_0D8:
- if(bankd0_dict) {
- *offset = 0;
- *mask = 0x1fff;
- *readfn = (void *)d_cmos;
- *writefn = (void *)d_cmos;
- } else {
- *offset = 0;
- *mask = 0x1fff;
- *readp = (void*)(&(ram_0d8[addr & 0x1fff]));
- *writep = (void*)(&(ram_0d8[addr & 0x1fff]));
- }
- break;
-
- case TOWNS_MEMORY_PAGE0F8:
- if(bankf8_ram) {
- *offset = 0;
- *mask = 0x7fff;
- *readp = (void*)(&(ram_0f8[addr & 0x7fff]));
- *writep = (void*)(&(ram_0f8[addr & 0x7fff]));
- } else {
- *offset = 0;
- *mask = 0x7fff;
- *readp = (void*)(&rom_system[0x38000 + (addr & 0x7fff)]);
- *writep = (void*)(&(ram_0f8[addr & 0x7fff]));
- }
- break;
default:
return false;
break;
// 0x0020 - 0x0022, 0x0030-0x0031,
// 0x0400 - 0x0404,
// 0x0480 - 0x0484
+// 0x05c0 - 0x05c2
+// 0x05ec (Wait register)
// Is set extra NMI (0x05c0 - 0x05c2)?
uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
{
case 0x0031:
val = ((machine_id >> 5) & 0xff);
break;
+ case 0x0032:
+ {
+ //bool __cs = (d_serialrom->read_data8(SIG_SERIALROM_CS) == 0);
+ bool __clk = (d_serialrom->read_data8(SIG_SERIALROM_CLK) != 0);
+ bool __reset = (d_serialrom->read_data8(SIG_SERIALROM_RESET) != 0);
+ bool __dat = (d_serialrom->read_data8(SIG_SERIALROM_DATA) != 0);
+ val = ((__reset) ? 0x80 : 0x00) | ((__clk) ? 0x40 : 0x00) | 0x3e | ((__dat) ? 0x01 : 0x00);
+ }
+ break;
case 0x006c: // Wait register.
if(machine_id >= 0x0300) { // After UX*/10F/20F/40H/80H
val = 0x7f;
case 0x0404: // System Status Reg.
val = (bankc0_vram) ? 0x7f : 0xff;
break;
- case 0x0480: // MEMORY BANK REGISTER
- val = val & ((bankd0_dict) ? 0xff : 0xfe);
- val = val & ((bankf8_ram) ? 0xff : 0xfd);
- break;
- case 0x0484:
- val = (val & 0xf0 ) | (dict_bank & 0x0f);
- break;
- case 0x05c2:
+ case 0x05c0:
val = (extra_nmi_mask) ? 0xf7 : 0xff;
break;
case 0x05c2:
}
break;
+ case 0x05ec:
+ if(machine_id >= 0x0500) { // Towns2 CX : Is this hidden register after Towns 1F/2F/1H/2H?
+ val = 0x00 | ((mem_wait_val > 0) ? 0x01 : 0x00);
+ }
+ break;
default:
break;
}
}
// Power register
break;
+ case 0x0032:
+ {
+ d_serialrom->write_data8(SIG_SERIALROM_CS, ~data, 0x20);
+ d_serialrom->write_data8(SIG_SERIALROM_CLK, data, 0x40);
+ d_serialrom->write_data8(SIG_SERIALROM_RESET, data, 0x80);
+ }
+ break;
case 0x006c: // Wait register.
if(machine_id >= 0x0300) { // After UX*/10F/20F/40H/80H
if(event_wait_1us != -1) cancel_event(this, event_wait_1us);
case 0x0404: // System Status Reg.
bankc0_vram = ((data & 0x80) != 0);
break;
- case 0x0480: // MEMORY BANK REGISTER
- bankd0_dict = ((data & 0x01) != 0);
- bankf8_ram = ((data & 0x02) != 0);
+ case 0x05c0:
+ extra_nmi_mask = ((data & 0x08) == 0);
break;
- case 0x0484:
- dict_bank = data & 0x0f;
+ case 0x05ec:
+ if(machine_id >= 0x0500) { // Towns2 CX : Is this hidden register after Towns 1F/2F/1H/2H?
+ vram_wait_val = ((data & 0x01) != 0) ? 3 : 6;
+ mem_wait_val = ((data & 0x01) != 0) ? 0 : 3;
+ this->write_signal(SIG_FMTOWNS_SET_VRAMWAIT, vram_wait_val, 0xff);
+ this->write_signal(SIG_FMTOWNS_SET_MEMWAIT, mem_wait_val, 0xff);
+ }
break;
default:
break;
for(uint32_t ui = 0x000cc; ui < 0x000d0; ui++) { // $000c0000 - $000effff
type_bank_adrs_cx[ui] = (TOWNS_MEMORY_MMIO_0CC << 24) | ((ui - 0xcc) << 12);
}
- for(uint32_t ui = 0x000d0; ui < 0x000d8; ui++) { // $000c0000 - $000effff
- type_bank_adrs_cx[ui] = (TOWNS_MEMORY_DICT_0D0 << 24) | ((ui - 0xd0) << 12);
- }
- for(uint32_t ui = 0x000d8; ui < 0x000da; ui++) { // $000c0000 - $000effff
- type_bank_adrs_cx[ui] = (TOWNS_MEMORY_CMOS_0D8 << 24) | ((ui - 0xd8) << 12);
- }
- for(uint32_t ui = 0x000da; ui < 0x000f0; ui++) { // $00000000 - $000bffff
- read_bank_adrs_cx[ui] = &(ram_0da[ui << 12]);
- write_bank_adrs_cx[ui] = &(ram_0da[ui << 12]);
+ for(uint32_t ui = 0x000d0; ui < 0x000f0; ui++) { // $000c0000 - $000effff
+ device_bank_adrs_cx[ui] = d_dictionary;
}
- for(uint32_t ui = 0x000f0; ui < 0x000f8; ui++) { // $000f0000 - $000f7fff
- read_bank_adrs_cx[ui] = &(ram_0f0[(ui - 0xf0) << 12]);
- write_bank_adrs_cx[ui] = &(ram_0f0[(ui - 0xf0) << 12]);
- }
- for(uint32_t ui = 0x000f8; ui < 0x00100; ui++) { // $000c0000 - $000effff
- type_bank_adrs_cx[ui] = (TOWNS_MEMORY_PAGE0F8 << 24) | ((ui - 0xf8) << 12);
+ for(uint32_t ui = 0x000f0; ui < 0x00100; ui++) { // $000f0000 - $000fffff
+ device_bank_adrs_cx[ui] = d_sysrom;
}
// Extra RAM
for(uint32_t ui = 0x00100; ui < (0x00100 + (extram_size >> 12)); ui++) {
device_bank_adrs_cx[ui] = d_romcard[1];
}
for(uint32_t ui = 0xc2140; ui < 0xc2142; ui++) {
- device_bank_adrs_cx[ui] = d_cmos;
+ device_bank_adrs_cx[ui] = d_dictionary;
}
for(uint32_t ui = 0xc2200; ui < 0xc2201; ui++) {
device_bank_adrs_cx[ui] = d_pcm;
}
// ROMs
for(uint32_t ui = 0xc2000; ui < 0xc2080; ui++) {
- read_bank_adrs_cx[ui] = &(rom_msdos[(ui - 0xc2000) << 12]);
+ device_bank_adrs_cx[ui] = d_msdos;
}
for(uint32_t ui = 0xc2080; ui < 0xc2100; ui++) {
- read_bank_adrs_cx[ui] = &(rom_dict[(ui - 0xc2080) << 12]);
+ device_bank_adrs_cx[ui] = d_dictionary;
}
for(uint32_t ui = 0xc2100; ui < 0xc2140; ui++) {
- read_bank_adrs_cx[ui] = &(rom_font1[(ui - 0xc2100) << 12]);
+ device_bank_adrs_cx[ui] = d_fonts;
+ }
+ for(uint32_t ui = 0xc2180; ui < 0xc2200; ui++) { // 20pixs fonts.
+ device_bank_adrs_cx[ui] = d_fonts;
}
// SYSTEM CODE ROM
for(uint32_t ui = 0xfffc0; ui < 0x100000; ui++) {
- read_bank_adrs_cx[ui] = &(rom_system[(ui - 0xfffc0) << 12]);
+ device_bank_adrs_cx[ui] = d_sysrom;
}
}
}
-void TOWNS_MEMORY::write_signal(int id, uint32_t data, uint32_t mask)
+void TOWNS_MEMORY::write_signal(int ch, uint32_t data, uint32_t mask)
{
- if(id == SIG_MEMORY_EXTNMI) {
+ if(ch == SIG_MEMORY_EXTNMI) {
extra_nmi_val = ((data & mask) != 0);
- } else if(id == SIG_CPU_NMI) {
+ } else if(ch == SIG_CPU_NMI) {
// Check protect
d_cpu->write_signal(SIG_CPU_NMI, data, mask);
- } else if(id == SIG_CPU_IRQ) {
+ } else if(ch == SIG_CPU_IRQ) {
d_cpu->write_signal(SIG_CPU_IRQ, data, mask);
- } else if(id == SIG_CPU_BUSREQ) {
+ } else if(ch == SIG_CPU_BUSREQ) {
d_cpu->write_signal(SIG_CPU_BUSREQ, data, mask);
- } else if(id == SIG_I386_A20) {
+ } else if(ch == SIG_I386_A20) {
d_cpu->write_signal(SIG_I386_A20, data, mask);
+ } else if(ch == SIG_FMTOWNS_SET_MEMWAIT) {
+ mem_wait_val = (int)data;
+ d_sysrom->write_signal(SIG_FMTOWNS_SET_MEMWAIT, data, mask);
+ d_dictionary->write_signal(SIG_FMTOWNS_SET_MEMWAIT, data, mask);
+ d_msdos->write_signal(SIG_FMTOWNS_SET_MEMWAIT, data, mask);
+ d_fonts->write_signal(SIG_FMTOWNS_SET_MEMWAIT, data, mask);
+ } else if(ch == SIG_FMTOWNS_SET_VRAMWAIT) {
+ vram_wait_val = (int)data;
+ d_vram->write_signal(SIG_FMTOWNS_SET_MEMWAIT, data, mask);
}
}
+
+uint32_t TOWNS_MEMORY::read_signal(int ch)
+{
+ if(ch == SIG_FMTOWNS_MACHINE_ID) {
+ uint16_t d = (machine_id & 0xfff8) | ((uint16_t)(cpu_id & 0x07));
+ return (uint32_t)d;
+ } else if(ch == SIG_FMTOWNS_SET_MEMWAIT) {
+ return (uint32_t)mem_wait_val;
+ } else if(ch == SIG_FMTOWNS_SET_VRAMWAIT) {
+ return (uint32_t)vram_wait_val;
+ }
+ return 0;
+}
// ToDo: DMA
#define STATE_VERSION 1
return false;
}
state_fio->StateValue(bankc0_vram);
- state_fio->StateValue(bankf8_vram);
- state_fio->StateValue(bankd0_dict);
state_fio->StateValue(ankcg_enabled);
- state_fio->StateValue(dict_bank);
state_fio->StateValue(machine_id);
state_fio->StateValue(cpu_id);
state_fio->StateArray(ram_0cb, sizeof(ram_0cb), 1);
state_fio->StateArray(ram_0cc, sizeof(ram_0cc), 1);
- state_fio->StateArray(ram_0d0, sizeof(ram_0d0), 1);
- state_fio->StateArray(ram_0d8, sizeof(ram_0d8), 1);
- state_fio->StateArray(ram_0da, sizeof(ram_0da), 1);
-
- state_fio->StateArray(ram_0f0, sizeof(ram_0f0), 1);
- state_fio->StateArray(ram_0f8, sizeof(ram_0f8), 1);
if(loading) {
uint32_t length_tmp = state_fio->FgetUint32_LE();
#ifndef _TOWNS_MEMORY_H_
#define _TOWNS_MEMORY_H_
-#include "../vm.h"
-#include "../../emu.h"
+//#include "../vm.h"
+//#include "../../emu.h"
#include "../device.h"
-//#define SIG_MEMORY_DISP 0
-//#define SIG_MEMORY_VSYNC 1
+#define SIG_FMTOWNS_MACHINE_ID 1
class I386;
// Bank size = 1GB / 1MB.
TOWNS_MEMORY_ANKCG2,
TOWNS_MEMORY_MMIO_0CC,
- TOWNS_MEMORY_DICT_0D0,
- TOWNS_MEMORY_CMOS_0D8,
- TOWNS_MEMORY_PAGE0F8,
TOWNS_MEMORY_TYPE_EXT_MMIO,
TOWNS_MEMORY_TYPE_LEARN_RAM,
TOWNS_MEMORY_TYPE_WAVERAM,
- TOWNS_MEMORY_TYPE_SYSTEM_ROM,
};
}
// Please set from config
class TOWNS_VRAM;
class TOWNS_SPRITE;
class TOWNS_ROM_CARD;
- class TOWNS_CMOS;
class TOWNS_PCM;
}
TOWNS_VRAM* d_vram;
TOWNS_SPRITE* d_sprite; // 0x81000000 - 0x8101ffff ?
TOWNS_ROM_CARD* d_romcard[2]; // 0xc0000000 - 0xc0ffffff / 0xc1000000 - 0xc1ffffff
- TOWNS_CMOS* d_cmos; // 0xc2140000 - 0xc2141fff
TOWNS_PCM* d_pcm; // 0xc2200000 - 0xc2200fff
BEEP* d_beep;
+
+ DEVICE* d_dictionary;
+ DEVICE* d_sysrom;
+ DEVICE* d_msdos;
+ DEVICE* d_serialrom;
bool bankc0_vram;
- bool bankf8_ram;
- bool bankd0_dict;
bool ankcg_enabled;
- uint8_t dict_bank;
uint16_t machine_id;
uint8_t cpu_id;
uint8_t ram_0ca[0x1000]; // 0x000ca000 - 0x000cafff : ANKCG1 / IO / RAM
uint8_t ram_0cb[0x1000]; // 0x000cb000 - 0x000cbfff : ANKCG2 / RAM
uint8_t ram_0cc[0x4000]; // 0x000cc000 - 0x000cffff : MMIO / RAM
- uint8_t ram_0d0[0x8000]; // 0x000d0000 - 0x000d7fff : RAM / BANKED DICTIONARY
- uint8_t ram_0d8[0x2000]; // 0x000d8000 - 0x000d9fff : RAM / CMOS
- uint8_t ram_0da[0x16000]; // 0x000da000 - 0x000effff : RAM
- uint8_t ram_0f0[0x8000]; // 0x000f0000 - 0x000f7fff
- uint8_t ram_0f8[0x8000]; // 0x000f8000 - 0x000fffff : RAM/ROM
uint8_t *extram; // 0x00100000 - (0x3fffffff) : Size is defined by extram_size;
uint32_t extram_size;
uint32_t mem_wait_val;
// ROM
- uint8_t rom_msdos[0x80000]; // 0xc2000000 - 0xc207ffff
- uint8_t rom_dict[0x80000]; // 0xc2080000 - 0xc20fffff
uint8_t rom_font1[0x40000]; // 0xc2100000 - 0xc23f0000
- uint8_t rom_system[0x40000]; // 0xfffc0000 - 0xffffffff
#if 0
uint8_t rom_font20[0x80000];
#endif
d_sprite = NULL;
d_romcard[0] = d_romcard[1] = NULL;
d_beep = NULL;
- machine_id = 0;
+ d_sysrom = NULL;
+ d_dictionary = NULL;
+ d_msdos = NULL;
+ // Note: machine id must set before initialize() from set_context_machine_id() by VM::VM().
+ // machine_id = 0x0100; // FM-Towns 1,2
+ // machine_id = 0x0200 // FM-Towns 1F/2F/1H/2H
+ // machine_id = 0x0300 // FM-Towns UX10/UX20/UX40
+ // machine_id = 0x0400 // FM-Towns 10F/20F/40H/80H
+ // machine_id = 0x0500 // FM-Towns2 CX10/CX20/CX40/CX100
+ // machine_id = 0x0600 // FM-Towns2 UG10/UG20/UG40/UG80
+ // machine_id = 0x0700 // FM-Towns2 HR20/HR100/HR200
+ // machine_id = 0x0800 // FM-Towns2 HG20/HG40/HG100
+ // machine_id = 0x0900 // FM-Towns2 UR20/UR40/UR80
+ // machine_id = 0x0b00 // FM-Towns2 MA20/MA170/MA340
+ // machine_id = 0x0c00 // FM-Towns2 MX20/MX170/MX340
+ // machine_id = 0x0d00 // FM-Towns2 ME20/ME170
+ // machine_id = 0x0f00 // FM-Towns2 MF20/MF170/Fresh
+ machine_id = 0x0100; // FM-Towns 1,2
+
+ // Note: cpu id must set before initialize() from set_context_cpu_id() by VM::VM().
+ // cpu_id = 0x00; // 80286.
+ // cpu_id = 0x01; // 80386DX.
+ // cpu_id = 0x02; // 80486SX/DX.
+ // cpu_id = 0x03; // 80386SX.
+ cpu_id = 0x01; // 80386DX.
+
}
~TOWNS_MEMORY() {}
{
d_vram = device;
}
+ void set_context_system_rom(DEVICE* device)
+ {
+ d_sysrom = device;
+ }
+ void set_context_dictionary(DEVICE* device)
+ {
+ d_dictionary = device;
+ }
+ void set_context_msdos(DEVICE* device)
+ {
+ d_msdos = device;
+ }
void set_context_beep(DEVICE* device)
{
d_beep = device;
{
d_pcm = device;
}
-
+ void set_context_serial_rom(DEVICE* device)
+ {
+ d_serialrom = device;
+ }
+ void set_context_machine_id(uint16_t val)
+ {
+ machine_id = val & 0xfff8;
+ }
+ void set_context_cpu_id(uint16_t val)
+ {
+ cpu_id = val & 0x07;
+ }
};
}
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2019.01.09-
+
+ [ system rom & RAM area 0x000f0000 - 0x000fffff]
+*/
+
+#include "./towns_common.h"
+#include "./towns_sysrom.h"
+#include "../../fileio.h"
+
+namespace FMTOWNS {
+void SYSROM::initialize()
+{
+ cmos_dirty = false;
+
+ memset(rom, 0xff, sizeof(rom));
+ memset(ram, 0x00, sizeof(ram));
+
+ FILEIO* fio = new FILEIO();
+ if(fio->Fopen(create_local_path(_T("FMT_SYS.ROM")), FILEIO_READ_BINARY)) { // DICTIONARIES
+ fio->Fread(rom, sizeof(rom), 1);
+ fio->Fclose();
+ }
+
+ wait_val = 3;
+ map_dos = true;
+}
+
+
+void SYSROM::reset()
+{
+ //wait_val = 6; // OK?
+ //map_dos = true;
+}
+
+uint32_t SYSROM::read_data8(uint32_t addr)
+{
+ uint8_t n_data = 0xff;
+ if(addr < 0xfffc0000) { // Banked (from MSDOS/i86 compatible mode)
+ if((addr >= 0x000f8000) && (addr < 0x00100000)) {
+ if(map_dos) {
+ n_data = rom[(addr & 0x7fff) + 0x38000];
+ } else {
+ n_data = ram[addr & 0xffff];
+ }
+ } else if((addr >= 0x000f0000) && (addr < 0x00100000)) {
+ n_data = ram[addr & 0xffff];
+ }
+ } else {
+ n_data = rom[addr & 0x3ffff];
+ }
+ return (uint32_t)n_data;
+}
+
+void SYSROM::write_data8(uint32_t addr, uint32_t data)
+{
+ if(addr < 0xfffc0000) {
+ if((addr >= 0x000f8000) && (addr < 0x00100000)) {
+ if(!(map_dos)) {
+ ram[addr & 0xffff] = (uint8_t)data;
+ }
+ } else if((addr >= 0x000f0000) && (addr < 0x00100000)) {
+ ram[addr & 0xffff] = (uint8_t)data;
+ }
+ }
+}
+
+void SYSROM::write_signal(int ch, uint32_t data, uint32_t mask)
+{
+ switch(ch) {
+ case SIG_FMTOWNS_SYSROMSEL:
+ map_dos = ((data & mask) == 0);
+ break;
+ case SIG_FMTOWNS_SET_MEMWAIT:
+ wait_val = (int)data;
+ break;
+ }
+}
+
+uint32_t SYSROM::read_signal(int ch)
+{
+ switch(ch) {
+ case SIG_FMTOWNS_SYSROMSEL:
+ return ((map_dos) ? 0x00 : 0x02);
+ break;
+ case SIG_FMTOWNS_SET_MEMWAIT:
+ return (uint32_t)wait_val;
+ break;
+ }
+ return 0x00;
+}
+
+uint32_t SYSROM::read_data8w(uint32_t addr, int *wait)
+{
+ if(wait != NULL) *wait = wait_val;
+ return read_data8(addr, data);
+}
+
+void SYSROM::write_data8w(uint32_t addr, uint32_t data, int *wait)
+{
+ if(wait != NULL) *wait = wait_val;
+ write_data8(addr, data);
+}
+
+#define STATE_VERSION 1
+
+bool SYSROM::process_state(FILEIO* state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ state_fio->StateValue(wait_val);
+ state_fio->StateValue(map_dos);
+ state_fio->StateArray(ram, sizeof(ram), 1);
+ return true;
+}
+}
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2019.01.09-
+
+ [ SYSTEM rom & RAM area 0x000f0000 - 0x000fffff]
+*/
+
+#pragma once
+
+#include "common.h"
+#include "device.h"
+
+#define SIG_FMTOWNS_SYSROMSEL 0x1000
+
+namespace FMTOWNS {
+
+class SYSROM : public DEVICE
+{
+protected:
+ uint8_t rom[0x40000]; // 256KB
+ uint8_t ram[0x10000]; // 64KB
+ int wait_val;
+
+ bool map_dos;
+
+public:
+ SYSROM(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+ {
+ set_device_name("FM-Towns SYSTEM ROM/RAM 0x000fxxxx");
+ }
+ ~SYSROM() {}
+ void initialize();
+ void reset();
+
+ uint32_t read_data8(uint32_t addr);
+ uint32_t read_data8w(uint32_t addr, int* wait);
+
+ void write_data8(uint32_t addr, uint32_t data);
+ void write_data8w(uint32_t addr, uint32_t data, int* wait);
+
+ void write_signal(int ch, uint32_t data, uint32_t mask);
+ uint32_t read_signal(int ch);
+
+ bool process_state(FILEIO* state_fio, bool loading);
+
+};
+
+}
+
+// END