#include "./cdc.h"
#include "./floppy.h"
#include "./fontroms.h"
+#include "./joystick.h"
#include "./keyboard.h"
#include "./msdosrom.h"
#include "./scsi.h"
using FMTOWNS::DICTIONARY;
using FMTOWNS::FLOPPY;
using FMTOWNS::FONT_ROMS;
+using FMTOWNS::JOYSTICK;
using FMTOWNS::KEYBOARD;
using FMTOWNS::MSDOSROM;
using FMTOWNS::SCSI;
floppy = new FLOPPY(this, emu);
keyboard = new KEYBOARD(this, emu);
+ joystick = new JOYSTICK(this, emu);
scsi = new SCSI(this, emu);
timer = new TIMER(this, emu);
//e_volume[1]->set_context_ch2(mic, MB87878_VOLUME_LEFT | MB87878_VOLUME_RIGHT);
//e_volume[1]->set_context_ch3(modem, MB87878_VOLUME_LEFT | MB87878_VOLUME_RIGHT);
+ memory->set_context_cpu(cpu);
memory->set_context_dmac(dma);
memory->set_context_vram(vram);
memory->set_context_system_rom(sysrom);
memory->set_context_sprite(sprite);
memory->set_machine_id(machine_id);
memory->set_cpu_id(cpu_id);
- memory->set_context_cpu(cpu);
cdrom->scsi_id = 0;
cdrom->set_context_interface(cdc_scsi);
cpu->set_context_intr(pic);
cpu->set_context_dma(dma);
cpu->set_context_bios(NULL);
+ cpu->set_context_extreset(memory, SIG_FMTOWNS_NOTIFY_RESET, 0xffffffff);
#ifdef USE_DEBUGGER
cpu->set_context_debugger(new DEBUGGER(this, emu));
#endif
io->set_iomap_range_rw(0x04c0, 0x04cf, cdc); // CDROM
// PAD, Sound
-#if 0
- io->set_iomap_single_r(0x04d0, pad); // Pad1
- io->set_iomap_single_r(0x04d2, pad); // Pad 2
- io->set_iomap_single_w(0x04d6, pad); // Pad out
+#if 1
+ io->set_iomap_single_r(0x04d0, joystick); // Pad1
+ io->set_iomap_single_r(0x04d2, joystick); // Pad 2
+ io->set_iomap_single_w(0x04d6, joystick); // Pad out
#endif
io->set_iomap_single_rw(0x04d5, adpcm); // mute
// OPN2(YM2612)
io->set_iomap_single_rw(0x0600, keyboard);
io->set_iomap_single_rw(0x0602, keyboard);
io->set_iomap_single_rw(0x0604, keyboard);
- io->set_iomap_single_r (0x0606, keyboard); // BufFul (After Towns2)
//io->set_iomap_single_rw(0x0800, printer);
//io->set_iomap_single_rw(0x0802, printer);
#endif
// ToDo : Use config framework
memory->set_extra_ram_size(6);
-
for(DEVICE* device = first_device; device; device = device->next_device) {
device->initialize();
}
// delete all devices
for(DEVICE* device = first_device; device;) {
DEVICE *next_device = device->next_device;
+// printf("DEVID=%d\n", device->this_device_id);
device->release();
delete device;
device = next_device;
for(DEVICE* device = first_device; device; device = device->next_device) {
device->reset();
}
- // temporary fix...
- for(DEVICE* device = first_device; device; device = device->next_device) {
- device->reset();
- }
}
void VM::run()
namespace FMTOWNS {
+#define ADDR_MASK (addr_max - 1)
+#define BANK_MASK (bank_size - 1)
+
void TOWNS_MEMORY::config_page00()
{
- set_memory_rw (0x00000000, 0x000bffff, ram_page0);
if(dma_is_vram) {
- set_memory_mapped_io_r (0x000b0000, 0x000bffff, d_msdos); // OK? <- for compatible ROM.
+ set_memory_rw (0x00000000, 0x000bffff, ram_page0);
+// set_memory_mapped_io_r (0x000b0000, 0x000bffff, d_msdos); // OK? <- for compatible ROM.
set_memory_mapped_io_rw(0x000c0000, 0x000c7fff, d_vram);
set_memory_mapped_io_rw(0x000c8000, 0x000cafff, d_sprite);
set_memory_mapped_io_rw(0x000cb000, 0x000cbfff, d_font);
// set_memory_mapped_io_rw(0x000d0000, 0x000d9fff, d_dictionary); // CMOS
set_memory_mapped_io_rw(0x000d8000, 0x000d9fff, d_dictionary); // CMOS
} else {
+ set_memory_rw (0x00000000, 0x000bffff, ram_page0);
set_memory_rw (0x000c0000, 0x000cffff, ram_pagec);
set_memory_rw (0x000d0000, 0x000d9fff, ram_paged);
set_memory_mapped_io_rw(0x000c8000, 0x000cafff, d_sprite);
void TOWNS_MEMORY::initialize()
{
if(initialized) return;
- initialized = true;
+ DEVICE::initialize();
extra_nmi_mask = true;
extra_nmi_val = false;
mem_wait_val = 3;
// Initialize R/W table
- memset(rd_dummy, 0xff, sizeof(rd_dummy));
- memset(wr_dummy, 0x00, sizeof(wr_dummy));
- memset(rd_table, 0x00, sizeof(rd_table));
- memset(wr_table, 0x00, sizeof(wr_table));
- for(int i = 0; i < (0x100000000 >> TOWNS_BANK_SHIFT); i++) {
- rd_table[i].dev = NULL;
- rd_table[i].memory = rd_dummy;
- rd_table[i].wait = 6;
+ _MEMORY_DISABLE_DMA_MMIO = osd->check_feature(_T("MEMORY_DISABLE_DMA_MMIO"));
+ if(!(addr_max_was_set) && osd->check_feature(_T("MEMORY_ADDR_MAX"))) {
+ addr_max = osd->get_feature_uint64_value(_T("MEMORY_ADDR_MAX"));
}
- for(int i = 0; i < (0x100000000 >> TOWNS_BANK_SHIFT); i++) {
- wr_table[i].dev = NULL;
- wr_table[i].memory = rd_dummy;
- wr_table[i].wait = 6;
+ if(!(bank_size_was_set) && osd->check_feature(_T("MEMORY_BANK_SIZE"))) {
+ bank_size = osd->get_feature_uint64_value(_T("MEMORY_BANK_SIZE"));
+ }
+ // allocate tables here to support multiple instances with different address range
+ if(rd_table == NULL) {
+ int64_t bank_num = addr_max / bank_size;
+ bank_mask = BANK_MASK;
+ addr_mask = ADDR_MASK;
+
+ 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 == (uint64_t)(1 << i)) {
+ addr_shift = i;
+ break;
+ }
+ }
+ memset(rd_dummy, 0xff, bank_size);
}
+ initialized = true;
extram_size = extram_size & 0x3ff00000;
set_extra_ram_size(extram_size >> 20); // Check extra ram size.
{
TOWNS_MEMORY::initialize();
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
- uint32_t to_bank = to >> addr_shift;
- int blocks = (int)((0xffffffff / bank_size) + 1);
+ uint64_t start_bank = start >> addr_shift;
+ uint64_t end_bank = end >> addr_shift;
+ uint64_t to_bank = to >> addr_shift;
+ uint64_t blocks = addr_max / bank_size;
for(uint32_t i = start_bank; i <= end_bank; i++) {
if(to_bank >= blocks) break;
{
TOWNS_MEMORY::initialize();
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
- uint32_t to_bank = to >> addr_shift;
- int blocks = (int)((0xffffffff / bank_size) + 1);
+ uint64_t start_bank = start >> addr_shift;
+ uint64_t end_bank = end >> addr_shift;
+ uint64_t to_bank = to >> addr_shift;
+ uint64_t blocks = addr_max / bank_size;
for(uint32_t i = start_bank; i <= end_bank; i++) {
if(to_bank >= blocks) break;
// 20191202 K.Ohta
uint32_t TOWNS_MEMORY::read_data8w(uint32_t addr, int *wait)
{
- uint32_t bank = addr >> TOWNS_BANK_SHIFT;
+ uint32_t bank = addr >> addr_shift;
if(wait != NULL) {
*wait = rd_table[bank].wait;
}
// return rd_table[bank].dev->read_data8w(addr, wait);
return rd_table[bank].dev->read_memory_mapped_io8(addr);
} else if(rd_table[bank].memory != NULL) {
- return rd_table[bank].memory[addr & (TOWNS_BANK_SIZE - 1)];
+ return rd_table[bank].memory[addr & bank_mask];
}
return 0xff;
}
uint32_t TOWNS_MEMORY::read_data16w(uint32_t addr, int *wait)
{
- uint32_t bank = addr >> TOWNS_BANK_SHIFT;
+ uint32_t bank = addr >> addr_shift;
if(wait != NULL) {
*wait = rd_table[bank].wait;
}
} else if(rd_table[bank].memory != NULL) {
// Internal memories may access with 32bit width.
pair32_t nd;
- nd.b.l = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 0];
- nd.b.h = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 1];
+ nd.b.l = rd_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 0];
+ nd.b.h = rd_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 1];
return nd.w.l;
}
return 0xffff;
uint32_t TOWNS_MEMORY::read_data32w(uint32_t addr, int *wait)
{
- uint32_t bank = addr >> TOWNS_BANK_SHIFT;
+ uint32_t bank = addr >> addr_shift;
if(wait != NULL) {
*wait = rd_table[bank].wait;
}
} else if(rd_table[bank].memory != NULL) {
// Internal memories may access with 32bit width.
pair32_t nd;
- nd.b.l = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 0];
- nd.b.h = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 1];
- nd.b.h2 = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 2];
- nd.b.h3 = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 3];
+ nd.b.l = rd_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 0];
+ nd.b.h = rd_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 1];
+ nd.b.h2 = rd_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 2];
+ nd.b.h3 = rd_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 3];
return nd.d;
}
return 0xffffffff;
void TOWNS_MEMORY::write_data8w(uint32_t addr, uint32_t data, int *wait)
{
- uint32_t bank = addr >> TOWNS_BANK_SHIFT;
+ uint32_t bank = addr >> addr_shift;
if(wait != NULL) {
*wait = wr_table[bank].wait;
}
wr_table[bank].dev->write_memory_mapped_io8(addr, data);
} else if(wr_table[bank].memory != NULL) {
// Internal memories may access with 32bit width.
- wr_table[bank].memory[addr & (TOWNS_BANK_SIZE - 1)] = data;
+ wr_table[bank].memory[addr & bank_mask] = data;
}
}
void TOWNS_MEMORY::write_data16w(uint32_t addr, uint32_t data, int *wait)
{
- uint32_t bank = addr >> TOWNS_BANK_SHIFT;
+ uint32_t bank = addr >> addr_shift;
if(wait != NULL) {
*wait = wr_table[bank].wait;
}
// Internal memories may access with 32bit width.
pair32_t nd;
nd.d = data;
- wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 0] = nd.b.l;
- wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 1] = nd.b.h;
+ wr_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 0] = nd.b.l;
+ wr_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 1] = nd.b.h;
}
}
void TOWNS_MEMORY::write_data32w(uint32_t addr, uint32_t data, int *wait)
{
- uint32_t bank = addr >> TOWNS_BANK_SHIFT;
+ uint32_t bank = addr >> addr_shift;
if(wait != NULL) {
*wait = wr_table[bank].wait;
}
// Internal memories may access with 32bit width.
pair32_t nd;
nd.d = data;
- wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 0] = nd.b.l;
- wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 1] = nd.b.h;
- wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 2] = nd.b.h2;
- wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 3] = nd.b.h3;
+ wr_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 0] = nd.b.l;
+ wr_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 1] = nd.b.h;
+ wr_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 2] = nd.b.h2;
+ wr_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 3] = nd.b.h3;
}
}
uint32_t TOWNS_MEMORY::read_dma_data8w(uint32_t addr, int* wait)
{
- int bank = (addr & (TOWNS_BANK_SIZE - 1)) >> addr_shift;
+ int bank = addr >> addr_shift;
if(rd_table[bank].dev != NULL) {
if(wait != NULL) {
*wait = rd_table[bank].wait;
if(wait != NULL) {
*wait = mem_wait_val;
}
- return rd_table[bank].memory[addr & (TOWNS_BANK_SIZE - 1)];
+ return rd_table[bank].memory[addr & bank_mask];
}
return 0xff;
}
uint32_t TOWNS_MEMORY::read_dma_data16w(uint32_t addr, int* wait)
{
- int bank = (addr & (TOWNS_BANK_SIZE - 2)) >> addr_shift;
+ int bank = addr >> addr_shift;
if(rd_table[bank].dev != NULL) {
if(wait != NULL) {
*wait = rd_table[bank].wait;
*wait = mem_wait_val;
}
pair16_t nd;
- nd.b.l = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 0];
- nd.b.h = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 1];
+ nd.b.l = rd_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 0];
+ nd.b.h = rd_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 1];
return nd.w;
}
return 0xffff;
void TOWNS_MEMORY::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
{
- int bank = (addr & (TOWNS_BANK_SIZE - 1)) >> addr_shift;
+ int bank = addr >> addr_shift;
if(wr_table[bank].dev != NULL) {
if(wait != NULL) {
*wait = wr_table[bank].wait;
if(wait != NULL) {
*wait = mem_wait_val;
}
- wr_table[bank].memory[addr & (TOWNS_BANK_SIZE - 1)] = data;
+ wr_table[bank].memory[addr & bank_mask] = data;
}
return;
}
void TOWNS_MEMORY::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
{
- int bank = (addr & (TOWNS_BANK_SIZE - 2)) >> addr_shift;
+ int bank = addr >> addr_shift;
if(wr_table[bank].dev != NULL) {
if(wait != NULL) {
*wait = wr_table[bank].wait;
}
pair32_t nd;
nd.d = data;
- wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 0] = nd.b.l;
- wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 1] = nd.b.h;
+ wr_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 0] = nd.b.l;
+ wr_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 1] = nd.b.h;
}
return;
}
void TOWNS_MEMORY::release()
{
+ if(rd_table != NULL) free(rd_table);
+ if(rd_dummy != NULL) free(rd_dummy);
+ if(wr_table != NULL) free(wr_table);
+ if(wr_dummy != NULL) free(wr_dummy);
+
if(extra_ram != NULL) {
free(extra_ram);
extra_ram = NULL;
uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
{
- uint32_t val = 0xff;
+ uint32_t val = 0x00; // MAY NOT FILL to "1" for unused bit 20200129 K.O
switch(addr & 0xffff) {
case 0x0020: // Software reset ETC.
// reset cause register
-#if 0
- val = 0x00;
-#else
if(d_cpu != NULL) {
val = ((software_reset) ? 1 : 0) | ((d_cpu->get_shutdown_flag() != 0) ? 2 : 0);
}
if(d_cpu != NULL) {
d_cpu->set_shutdown_flag(0);
}
-#endif
- val = val | 0x7c;
+// val = val | 0x7c; // MAY NOT FILL to "1" for unused bit 20200129 K.O
break;
case 0x0022:
// Power register
- val = 0xff;
// if(d_dmac != NULL) {
// val = d_dmac->read_signal(SIG_TOWNS_DMAC_ADDR_REG);
// }
break;
case 0x0024:
// Power register
- val = 0xff;
if(d_dmac != NULL) {
val = d_dmac->read_signal(SIG_TOWNS_DMAC_WRAP_REG);
}
}
break;
case 0x0400: // Resolution:
- val = 0xfe;
+// val = 0xfe;
+ val = 0x00;
break;
case 0x0404: // System Status Reg.
- val = (dma_is_vram) ? 0x7f : 0xff;
+// val = (dma_is_vram) ? 0x7f : 0xff;
+ val = (dma_is_vram) ? 0x00 : 0x80;
break;
case 0x05c0:
- val = (extra_nmi_mask) ? 0xf7 : 0xff;
+// val = (extra_nmi_mask) ? 0xf7 : 0xff;
+ val = (extra_nmi_mask) ? 0x00 : 0x08;
break;
case 0x05c2:
- val = (extra_nmi_val) ? 0xff : 0xf7;
+// val = (extra_nmi_val) ? 0xff : 0xf7;
+ val = (extra_nmi_val) ? 0x08 : 0x00;
break;
case 0x05e8:
// After Towns1F/2F/1H/2H
val = ((extram_size >> 20) & 0x7f);
break;
default:
- val = 0xff; // ???
+ val = 0x00; // ???
break;
}
}
}
}
if(d_cpu != NULL) {
-// switch(data & 0x08) {
+#if 1
+
+ switch(data & 0x08) {
+ case 0x00: // 32bit
+ d_cpu->set_address_mask(0xffffffff);
+ break;
+ default: // 20bit
+ d_cpu->set_address_mask(0x000fffff);
+ break;
+ }
+
+#else
switch(data & 0x30) { // From eFMR50
case 0x00: // 20bit
d_cpu->set_address_mask(0x000fffff);
d_cpu->set_address_mask(0xffffffff);
break;
}
+#endif
if(d_dmac != NULL) {
uint32_t maskval = d_cpu->get_address_mask();
d_dmac->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, maskval, 0xff);
if(d_dmac != NULL) {
d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP_REG, data, 0xff);
}
- // Power register
break;
case 0x0032:
{
if(d_cpu != NULL) {
d_cpu->write_signal(SIG_I386_A20, data, mask);
}
+ } else if(ch == SIG_FMTOWNS_NOTIFY_RESET) {
+ out_debug_log("RESET FROM CPU!!!\n");
+// d_cpu->set_address_mask(0x000fffff);
+ d_cpu->set_address_mask(0xffffffff);
} else if(ch == SIG_FMTOWNS_RAM_WAIT) {
mem_wait_val = (int)data;
set_wait_values();