From: K.Ohta Date: Wed, 9 Jan 2019 12:56:55 +0000 (+0900) Subject: [VM][FMTOWNS] Add FONT ROMS, MSDOS ROM, SYSTEM ROM and SERIAL ROM. X-Git-Url: http://git.osdn.net/view?p=csp-qt%2Fcommon_source_project-fm7.git;a=commitdiff_plain;h=4cb5597006aa42de89c761acc5e73b93f822bd2d [VM][FMTOWNS] Add FONT ROMS, MSDOS ROM, SYSTEM ROM and SERIAL ROM. --- diff --git a/source/src/vm/fmtowns/CMakeLists.txt b/source/src/vm/fmtowns/CMakeLists.txt index 22e3854c9..bc9ce5f0d 100644 --- a/source/src/vm/fmtowns/CMakeLists.txt +++ b/source/src/vm/fmtowns/CMakeLists.txt @@ -3,13 +3,20 @@ cmake_minimum_required (VERSION 2.6) 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 +) diff --git a/source/src/vm/fmtowns/fontroms.cpp b/source/src/vm/fmtowns/fontroms.cpp new file mode 100644 index 000000000..ed072f605 --- /dev/null +++ b/source/src/vm/fmtowns/fontroms.cpp @@ -0,0 +1,89 @@ +/* + FUJITSU FM Towns Emulator 'eFMTowns' + + Author : Kyuma.Ohta + 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; +} + +} diff --git a/source/src/vm/fmtowns/fontroms.h b/source/src/vm/fmtowns/fontroms.h new file mode 100644 index 000000000..de1ea5ea6 --- /dev/null +++ b/source/src/vm/fmtowns/fontroms.h @@ -0,0 +1,42 @@ +/* + FUJITSU FM Towns Emulator 'eFMTowns' + + Author : Kyuma.Ohta + 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); +}; + +} + diff --git a/source/src/vm/fmtowns/msdosrom.cpp b/source/src/vm/fmtowns/msdosrom.cpp new file mode 100644 index 000000000..b6357ca57 --- /dev/null +++ b/source/src/vm/fmtowns/msdosrom.cpp @@ -0,0 +1,80 @@ +/* + FUJITSU FM Towns Emulator 'eFMTowns' + + Author : Kyuma.Ohta + 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; +} + +} diff --git a/source/src/vm/fmtowns/msdosrom.h b/source/src/vm/fmtowns/msdosrom.h new file mode 100644 index 000000000..2f14430ca --- /dev/null +++ b/source/src/vm/fmtowns/msdosrom.h @@ -0,0 +1,30 @@ +/* + FUJITSU FM Towns Emulator 'eFMTowns' + + Author : Kyuma.Ohta + 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(); + +}; + +} + diff --git a/source/src/vm/fmtowns/serialrom.cpp b/source/src/vm/fmtowns/serialrom.cpp new file mode 100644 index 000000000..05fdf087a --- /dev/null +++ b/source/src/vm/fmtowns/serialrom.cpp @@ -0,0 +1,194 @@ +/* + FUJITSU FM Towns Emulator 'eFMTowns' + + Author : Kyuma.Ohta + 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(0x00000123); + auto nmask = static_cast(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; +} + +} diff --git a/source/src/vm/fmtowns/serialrom.h b/source/src/vm/fmtowns/serialrom.h new file mode 100644 index 000000000..5f804b769 --- /dev/null +++ b/source/src/vm/fmtowns/serialrom.h @@ -0,0 +1,55 @@ +/* + FUJITSU FM Towns Emulator 'eFMTowns' + + Author : Kyuma.Ohta + 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; + } +}; + +} + diff --git a/source/src/vm/fmtowns/towns_dictionary.cpp b/source/src/vm/fmtowns/towns_dictionary.cpp new file mode 100644 index 000000000..6fbe54942 --- /dev/null +++ b/source/src/vm/fmtowns/towns_dictionary.cpp @@ -0,0 +1,276 @@ +/* + FUJITSU FM Towns Emulator 'eFMTowns' + + Author : Kyuma.Ohta + 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; +} +} diff --git a/source/src/vm/fmtowns/towns_dictionary.h b/source/src/vm/fmtowns/towns_dictionary.h new file mode 100644 index 000000000..1ed8f3bdb --- /dev/null +++ b/source/src/vm/fmtowns/towns_dictionary.h @@ -0,0 +1,77 @@ +/* + FUJITSU FM Towns Emulator 'eFMTowns' + + Author : Kyuma.Ohta + 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 diff --git a/source/src/vm/fmtowns/towns_memory.cpp b/source/src/vm/fmtowns/towns_memory.cpp index 860100d0a..e55756f81 100644 --- a/source/src/vm/fmtowns/towns_memory.cpp +++ b/source/src/vm/fmtowns/towns_memory.cpp @@ -4,9 +4,10 @@ Author : Kyuma.Ohta Date : 2017.01.01 - - [ memory] + [memory] */ +#include "../../fileio.h" #include "./towns_memory.h" #include "../i386.h" @@ -15,70 +16,22 @@ namespace FMTOWNS { 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. @@ -165,13 +118,14 @@ bool TOWNS_MEMORY::check_bank(uint32_t addr, uint32_t *mask, uint32_t *offset, v 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; } @@ -182,9 +136,10 @@ bool TOWNS_MEMORY::check_bank(uint32_t addr, uint32_t *mask, uint32_t *offset, v 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])); @@ -192,42 +147,6 @@ bool TOWNS_MEMORY::check_bank(uint32_t addr, uint32_t *mask, uint32_t *offset, v *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; @@ -622,6 +541,8 @@ void TOWNS_MEMORY::write_data32(uint32_t addr, uint32_t data) // 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) { @@ -645,6 +566,15 @@ 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; @@ -656,14 +586,7 @@ uint32_t TOWNS_MEMORY::read_io8(uint32_t addr) 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: @@ -700,6 +623,11 @@ uint32_t TOWNS_MEMORY::read_io8(uint32_t addr) } 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; } @@ -737,6 +665,13 @@ void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data) } // 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); @@ -747,12 +682,16 @@ void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data) 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; @@ -948,22 +887,11 @@ void TOWNS_MEMORY::initialize_tables(void) 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++) { @@ -1000,25 +928,28 @@ void TOWNS_MEMORY::initialize_tables(void) 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; } } @@ -1065,21 +996,43 @@ uint32_t TOWNS_MEMORY::read_dma_data16(uint32_t addr) } -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 @@ -1093,10 +1046,7 @@ bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading) 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); @@ -1111,12 +1061,6 @@ bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading) 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(); diff --git a/source/src/vm/fmtowns/towns_memory.h b/source/src/vm/fmtowns/towns_memory.h index 0857c69d6..c0714d95c 100644 --- a/source/src/vm/fmtowns/towns_memory.h +++ b/source/src/vm/fmtowns/towns_memory.h @@ -10,12 +10,11 @@ #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. @@ -49,14 +48,10 @@ enum { 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 @@ -69,7 +64,6 @@ namespace FMTOWNS { class TOWNS_VRAM; class TOWNS_SPRITE; class TOWNS_ROM_CARD; - class TOWNS_CMOS; class TOWNS_PCM; } @@ -82,15 +76,16 @@ protected: 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; @@ -114,11 +109,6 @@ protected: 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; @@ -127,10 +117,7 @@ protected: 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 @@ -159,7 +146,32 @@ public: 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() {} @@ -207,6 +219,18 @@ public: { 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; @@ -223,7 +247,18 @@ public: { 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; + } }; } diff --git a/source/src/vm/fmtowns/towns_sysrom.cpp b/source/src/vm/fmtowns/towns_sysrom.cpp new file mode 100644 index 000000000..5be5ddbaa --- /dev/null +++ b/source/src/vm/fmtowns/towns_sysrom.cpp @@ -0,0 +1,123 @@ +/* + FUJITSU FM Towns Emulator 'eFMTowns' + + Author : Kyuma.Ohta + 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; +} +} diff --git a/source/src/vm/fmtowns/towns_sysrom.h b/source/src/vm/fmtowns/towns_sysrom.h new file mode 100644 index 000000000..86d5deed1 --- /dev/null +++ b/source/src/vm/fmtowns/towns_sysrom.h @@ -0,0 +1,52 @@ +/* + FUJITSU FM Towns Emulator 'eFMTowns' + + Author : Kyuma.Ohta + 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