Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
Date : 2017.01.01 -
- [ memory]
+ [memory]
*/
+#include "../../fileio.h"
#include "./towns_memory.h"
#include "../i386.h"
+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;
+
- memset(page0, 0x00, sizeof(page0));
- memset(ram_0d0, 0x00, sizeof(ram_0d0));
- memset(ram_0f0, 0x00, sizeof(ram_0f0));
- memset(ram_0f8, 0x00, sizeof(ram_0f8));
-
- memset(system_rom, 0xff, sizeof(system_rom));
- memset(font_rom, 0xff, sizeof(font_rom));
-#if 0
- memset(font_20_rom, 0xff, sizeof(font_20_rom));
-#endif
- memset(msdos_rom, 0xff, sizeof(msdos_rom));
- memset(dict_rom, 0xff, sizeof(dict_rom));
+ 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(system_rom, sizeof(system_rom), 1);
- fio->Fclose();
- }
- if(fio->Fopen(create_local_path(_T("FMT_FNT.ROM")), FILEIO_READ_BINARY)) { // FONT
- fio->Fread(font_rom, sizeof(font_rom), 1);
- fio->Fclose();
- }
#if 0
if(fio->Fopen(create_local_path(_T("FMT_F20.ROM")), FILEIO_READ_BINARY)) { // 20 pixels FONT : Optional
- fio->Fread(font_20_rom, sizeof(font_20_rom), 1);
+ 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)) { // MSDOS
- fio->Fread(dict_rom, sizeof(dict_rom), 1);
- fio->Fclose();
- }
// ToDo: Will move to config.
- extram_pages = TOWNS_EXTRAM_PAGES;
- extram_base = (uint8_t *)malloc(extram_pages * 0x100000);
-
+ extram_size = TOWNS_EXTRAM_PAGES * 0x100000;
+ // ToDo: Limit extram_size per VM.
+ extram = (uint8_t *)malloc(extram_size);
+ // ToDo: More smart.
+ vram_size = 0x80000; // OK?
+
+ //dma_addr_reg = dma_wrap_reg = 0;
+ dma_addr_mask = 0x00ffffff; // ToDo
+
initialize_tables();
}
d_cpu->set_address_mask(0xffffffff);
}
-void TOWNS_MEMORY::write_page0_8(uint32_t addr, uint32_t data, int *wait)
+bool TOWNS_MEMORY::check_bank(uint32_t addr, uint32_t *mask, uint32_t *offset, void** readfn, void** writefn, void** readp, void** writep)
{
- addr = addr & 0x000fffff;
- if(wait != NULL) *wait = mem_wait_val;
+ uint8_t __type = (uint8_t)(type_bank_adrs_cx[banknum] >> 24);
+ uint32_t __offset = type_bank_adrs_cx[banknum] & 0x00ffffff;
+ if(offset == NULL) return false;
+ if(mask == NULL) return false;
+ if(readfn == NULL) return false;
+ if(writefn == NULL) return false;
+ if(readp == NULL) return false;
+ if(writep == NULL) return false;
- if(addr < 0xc0000) {
- page0[addr] = (uint8_t)data;
- } else if(addr < 0xc8000) {
- if(d_vram != NULL) {
- d_vram->write_plane_data8(addr & 0x7fff, data);
- if(wait != NULL) *wait = vram_wait_val;
- }
- } else if(addr < 0xd0000) {
- // MMIO, VRAM and ram.
- if(0xcff80 <= addr && addr < 0xcffe0) {
-#ifdef _DEBUG_LOG
-// this->out_debug_log(_T("MW\t%4x, %2x\n"), addr, data);
-#endif
- // memory mapped i/o
- switch(addr & 0xffff) {
- case 0xff80:
- // mix register
- mix = data;
- break;
- case 0xff81:
- // update register
- wplane = data & 7;
- rplane = (data >> 6) & 3;
- update_bank();
- break;
- case 0xff82:
- // display ctrl register
- dispctrl = data;
- update_bank();
- break;
- case 0xff83:
- // page select register
- pagesel = data;
- update_bank();
- break;
- case 0xff88:
- // access start register
- accaddr = (accaddr & 0xff) | ((data & 0x7f) << 8);
- break;
- case 0xff89:
- // access start register
- accaddr = (accaddr & 0xff00) | (data & 0xfe);
- break;
- case 0xff8a:
- // display start register
- dispaddr = (dispaddr & 0xff) | ((data & 0x7f) << 8);
- break;
- case 0xff8b:
- // display start register
- dispaddr = (dispaddr & 0xff00) | (data & 0xfe);
- break;
- case 0xff8e:
- // crtc addr register
- d_crtc->write_io8(0, data);
- break;
- case 0xff8f:
- // crtc data register
- d_crtc->write_io8(1, data);
- break;
- case 0xff94:
- kj_h = data & 0x7f;
- break;
- case 0xff95:
- kj_l = data & 0x7f;
- kj_row = 0;
- if(kj_h < 0x30) {
- kj_ofs = (((kj_l - 0x00) & 0x1f) << 5) | (((kj_l - 0x20) & 0x20) << 9) | (((kj_l - 0x20) & 0x40) << 7) | (((kj_h - 0x00) & 0x07) << 10);
- } else if(kj_h < 0x70) {
- kj_ofs = (((kj_l - 0x00) & 0x1f) << 5) + (((kj_l - 0x20) & 0x60) << 9) + (((kj_h - 0x00) & 0x0f) << 10) + (((kj_h - 0x30) & 0x70) * 0xc00) + 0x08000;
- } else {
- kj_ofs = (((kj_l - 0x00) & 0x1f) << 5) | (((kj_l - 0x20) & 0x20) << 9) | (((kj_l - 0x20) & 0x40) << 7) | (((kj_h - 0x00) & 0x07) << 10) | 0x38000;
- }
- break;
- case 0xff96:
- kanji16[(kj_ofs | ((kj_row & 0xf) << 1)) & 0x3ffff] = data;
- break;
- case 0xff97:
- kanji16[(kj_ofs | ((kj_row++ & 0xf) << 1) | 1) & 0x3ffff] = data;
- break;
- case 0xff99:
- ankcg = data;
- update_bank();
- break;
- case 0xffa0:
- cmdreg = data;
- break;
- case 0xffa1:
- imgcol = data;
- break;
- case 0xffa2:
- maskreg = data;
- break;
- case 0xffa3:
- case 0xffa4:
- case 0xffa5:
- case 0xffa6:
- case 0xffa7:
- case 0xffa8:
- case 0xffa9:
- case 0xffaa:
- compreg[addr & 7] = data;
- break;
- case 0xffab:
- bankdis = data;
- break;
- case 0xffac:
- case 0xffad:
- case 0xffae:
- case 0xffaf:
- tilereg[addr & 3] = data;
- break;
- case 0xffb0:
- lofs = (lofs & 0xff) | (data << 8);
- break;
- case 0xffb1:
- lofs = (lofs & 0xff00) | data;
- break;
- case 0xffb2:
- lsty = (lsty & 0xff) | (data << 8);
- break;
- case 0xffb3:
- lsty = (lsty & 0xff00) | data;
- break;
- case 0xffb4:
- lsx = (lsx & 0xff) | (data << 8);
- break;
- case 0xffb5:
- lsx = (lsx & 0xff00) | data;
- break;
- case 0xffb6:
- lsy = (lsy & 0xff) | (data << 8);
- break;
- case 0xffb7:
- lsy = (lsy & 0xff00) | data;
- break;
- case 0xffb8:
- lex = (lex & 0xff) | (data << 8);
- break;
- case 0xffb9:
- lex = (lex & 0xff00) | data;
- break;
- case 0xffba:
- ley = (ley & 0xff) | (data << 8);
- break;
- case 0xffbb:
- ley = (ley & 0xff00) | data;
- // start drawing line
- line();
- break;
- }
- return;
+ *readfn = NULL;
+ *writefn = NULL;
+ *readp = NULL;
+ *writep = NULL;
+ *mask = 0x00;
+ *offset = 0;
+ switch(__type) {
+ case TOWNS_MEMORY_FMR_VRAM:
+ if(!mainmem_enabled) {
+ *readfn = (void *)d_vram;
+ *writefn = (void *)d_vram;
+ *offset = FMTOWNS_VRAM_PLANE_ACCESS;
+ *mask = 0x7fff;
+ } else {
+ *readp = (void *)(&(ram_0c0[addr & 0x7fff]));
+ *writep = (void *)(&(ram_0c0[addr & 0x7fff]));
+ *mask = 0x7fff;
}
- } else if(addr < 0xd8000) {
- if(!bankd0_dict) {
- ram_0d0[addr - 0x0d0000] = (uint8_t)data;
- // RAM? DICT?
+ break;
+ case TOWNS_MEMORY_FMR_TEXT:
+ if(!mainmem_enabled) {
+ if((addr & 0x1000) == 0) {
+ *readfn = (void *)d_vram;
+ *writefn = (void *)d_vram;
+ *offset = FMTOWNS_VRAM_TEXT_VRAM;
+ *mask = 0x0fff;
+ } else {
+ *mask = 0x1fff;
+ *readp = (void*)(&(ram_0c8[addr & 0x1fff]));
+ *writedp = (void*)(&(ram_0c8[addr & 0x1fff]));
+ }
} else {
- // DICT
- //dict_rom[addr - 0xd0000 + (((uint32_t)dict_bank) << 15))
+ *mask = 0x1fff;
+ *readp = (void*)(&(ram_0c8[addr & 0x1fff]));
+ *writedp = (void*)(&(ram_0c8[addr & 0x1fff]));
}
- } else if(addr < 0xda000) {
- if(!bankd0_dict) {
- // RAM? DICT?
- ram_0d0[addr - 0x0d0000] = (uint8_t)data;
+ break;
+ case TOWNS_MEMORY_MMIO_0CC:
+ if(!mainmem_enabled) {
+ if((addr & 0xfffff) < 0xcff80) {
+ *mask = 0x3fff;
+ *readp = (void*)(&(ram_0cc[addr & 0x3fff]));
+ *writedp = (void*)(&(ram_0cc[addr & 0x3fff]));
+ }
} else {
- // DICT
- if(d_cmos != NULL) d_cmos->write_data8(addr, data);
- return;
+ *mask = 0x3fff;
+ *readp = (void*)(&(ram_0cc[addr & 0x3fff]));
+ *writedp = (void*)(&(ram_0cc[addr & 0x3fff]));
}
- } else if(addr < 0xf0000) {
- if(!bankd0_dict) {
- ram_0d0[addr - 0x0d0000] = (uint8_t)data;
+ break;
+ case TOWNS_MEMORY_SPRITE_ANKCG1:
+ if(!mainmem_enabled) {
+ if(ankcg_enabled) {
+ *offset = 0x000ca000;
+ *mask = 0x0fff;
+ *readfn = (void *)d_fonts;
+ *writefn = (void *)d_fonts;
+ } else {
+ *offset = 0x2000 + FMTOWNS_VRAM_TEXT_VRAM;
+ *mask = 0x0fff;
+ *readfn = (void *)d_vram;
+ *writefn = (void *)d_vram;
+ }
+ } else {
+ *readp = (void*)(&(ram_0ca[addr & 0xfff]));
+ *writep = (void*)(&(ram_0ca[addr & 0xfff]));
}
- } else if(addr < 0xf8000) {
- ram_0f0[addr - 0xf0000] = (uint8_t)data;
- } else if(addr < 0x100000) {
- if(bankf8_ram) {
- // RAM
- ram_0f8[addr - 0xf8000] = (uint8_t)data;
+ break;
+ case TOWNS_MEMORY_SPRITE_ANKCG2:
+ if(!(mainmem_enabled) && (ankcg_enabled)) {
+ *offset = 0x000cb000;
+ *mask = 0x0fff;
+ *readfn = (void *)d_fonts;
+ *writefn = (void *)d_fonts;
} else {
- // BOOT ROM(ro)
- //system_rom[addr - 0xf8000 + 0x18000];
+ *readp = (void*)(&(ram_0cb[addr & 0xfff]));
+ *writep = (void*)(&(ram_0cb[addr & 0xfff]));
+ *mask = 0xfff;
+ *offset = 0;
}
+ break;
+ default:
+ return false;
+ break;
}
+ return true;
+
}
-void TOWNS_MEMORY::initialize_tables(void)
+
+uint32_t TOWNS_MEMORY::read_data_base(uint32_t addr, int* wait, int wordsize)
{
- memset(extram_adrs, 0x00, sizeof(extram_adrs));
- if(extram_base == NULL) {
- extram_pages = 0;
- } else {
- for(uint32_t ui = 0; ui < extram_pages; ui++) {
- uint8_t *p;
- p = &(extram_base[ui << 20]);
- extram_adrs[ui] = p;
- }
+ uint8_t *maddr;
+ DEVICE *daddr;
+ uint32_t banknum = addr >> 12;
+ uint32_t _naddr;
+ switch(wordsize) {
+ case 2:
+ _naddr = addr & 0xfffffffe;
+ break;
+ case 4:
+ _naddr = addr & 0xfffffffc;
+ break;
+ dafault:
+ _naddr = addr;
+ break;
}
- // Address Cx000000
- memset(write_bank_adrs_cx, 0x00, sizeof(write_bank_adrs_cx));
- memset(read_bank_adrs_cx, 0x00, sizeof(read_bank_adrs_cx));
- memset(device_bank_adrs_cx, 0x00, sizeof(device_bank_adrs_cx));
-
- for(uint32_t ui = 0x0000; ui < 0x4000; ui++) {
- if(ui < 0x2000) {
- // ROM CARD?
- } else if(ui < 0x2080) {
- read_bank_adrs_cx[ui] = &(msdos_rom[(ui - 0x2000) << 12]);
- } else if(ui < 0x2100) {
- read_bank_adrs_cx[ui] = &(dict_rom[(ui - 0x2080) << 12]);
- } else if(ui < 0x2140) {
- read_bank_adrs_cx[ui] = &(font_rom[(ui - 0x2100) << 12]);
- } else if(ui < 0x2142) {
- devicetype_adrs_cx[ui] = TOWNS_MEMORY_TYPE_DICTLEARN;
- } eise if(ui < 0x2200) {
- // Reserved.
- } else if(ui < 0x2201) {
- devicetype_adrs_cx[ui] = TOWNS_MEMORY_TYPE_WAVERAM;
+
+ maddr = read_bank_adrs_cx[banknum];
+ if(maddr != NULL) {
+ // Memory found.
+ if(wait != NULL) *wait = mem_wait_val;
+ uint8_t *p;
+ switch(wordsize) {
+ case 1:
+ p = &maddr[addr & 0x00000fff];
+ return (uint32_t)(*p);
+ break;
+ case 2:
+ {
+ pair16_t _d;
+ p = &maddr[addr & 0x00000ffe];
+#if defined(__LITTLE_ENDIAN__)
+ uint16_t* pp = (uint16_t*)p;
+ _d.u16 = *pp;
+#else
+ _d.l = p[0];
+ _d.h = p[1];
+#endif
+ return _d.u16;
+ }
+ break;
+ case 4:
+ {
+ pair32_t _d;
+ p = &maddr[addr & 0x00000ffc];
+#if defined(__LITTLE_ENDIAN__)
+ uint32_t* pp = (uint32_t*)p;
+ _d.u32 = *pp;
+#else
+ _d.l = p[0];
+ _d.h = p[1];
+ _d.h2 = p[2];
+ _d.h3 = p[3];
+#endif
+ return _d.u32;
+ }
+ break;
+ default:
+ return 0xffffffff; // Word size error
+ break;
+ }
+ } else {
+ daddr = device_bank_adrs_cx[banknum];
+ if(daddr != NULL) {
+ // Device chained.
+ switch(wordsize) {
+ case 1:
+ return daddr->read_data8w(addr, wait);
+ break;
+ case 2:
+ return daddr->read_data16w(addr, wait);
+ break;
+ case 4:
+ return daddr->read_data32w(addr, wait);
+ break;
+ default:
+ return 0xffffffff;
+ break;
+ }
} else {
- // Reserved.
+ uint32_t _mask;
+ uint32_t _offset;
+ DEVICE* readfn;
+ DEVICE* writefn;
+ uint8_t* readp;
+ uint8_t* writep;
+ if(check_bank(_naddr, &_mask, &_offset, (void**)(&readfn), (void**)(&writefn), (void**)(&readp), (void**)(&writep))) {
+ switch(wordsize)
+ {
+ case 1:
+ if(readp != NULL) {
+ if(wait != NULL) *wait = mem_wait_val;
+ return (uint32_t)(*readp);
+ } else if(readfn != NULL) {
+ return readfn->read_data8w(_naddr, wait);
+ } else {
+ return 0xff;
+ }
+ break;
+ case 2:
+ if(readp != NULL) {
+
+ if(wait != NULL) *wait = mem_wait_val;
+#if defined(__LITTLE_ENDIAN__)
+ uint16_t *pp = (uint16_t*)readp;
+ return (uint32_t)(*pp);
+#else
+ pair16_t _d;
+ pair16_t *pp = (pair16_t*)readp;
+ _d.l = pp[0];
+ _d.h = pp[1];
+ return _d.u16;
+#endif
+ } else if(readfn != NULL) {
+ return readfn->read_data16w(_naddr, wait);
+ } else {
+ return 0xffff;
+ }
+ break;
+ case 2:
+ if(readp != NULL) {
+
+ if(wait != NULL) *wait = mem_wait_val;
+#if defined(__LITTLE_ENDIAN__)
+ uint32_t *pp = (uint32_t*)readp;
+ return (uint32_t)(*pp);
+#else
+ pair32_t _d;
+ _d.l = readp[0];
+ _d.h = readp[1];
+ _d.h2 = readp[2];
+ _d.h3 = readp[3];
+ return _d.u32;
+#endif
+ } else if(readfn != NULL) {
+ return readfn->read_data32w(_naddr, wait);
+ } else {
+ return 0xffffffff;
+ }
+ break;
+ default:
+ return 0xffffffff;
+ break;
+ }
+ // Function or memory don't exist this bank.
+ } else {
+ // Bank not registered.
+ if((addr >= 0x000cff80) && (addr <= 0x000cffff)) {
+ bool _hit;
+ uint32_t val;
+ val = read_mmio(addr, wait, &_hit);
+ if(!_hit) {
+ ///
+ } else {
+ return val;
+ }
+ }
+ }
}
+ // Neither memory nor device nor bank.
}
-}
-void TOWNS_MEMORY::write_data8(uint32_t addr, uint32_t data)
+ return 0xffffffff;
+}
+
+uint32_t TOWNS_MEMORY::read_data8w(uint32_t addr, int *wait)
{
- int wait = 0;
- write_data8w(addr, data, &wait);
+ return read_data_base(addr, wait, 1);
}
-
-void TOWNS_MEMORY::write_data16(uint32_t addr, uint32_t data)
+uint32_t TOWNS_MEMORY::read_data16w(uint32_t addr, int *wait)
{
- int wait = 0;
- write_data16w(addr, data, &wait);
+ return read_data_base(addr, wait, 2);
}
-void TOWNS_MEMORY::write_data32(uint32_t addr, uint32_t data)
+uint32_t TOWNS_MEMORY::read_data32w(uint32_t addr, int *wait)
{
- int wait = 0;
- write_data32w(addr, data, &wait);
+ return read_data_base(addr, wait, 4);
}
-void TOWNS_MEMORY::write_data8w(uint32_t addr, uint32_t data, int *wait)
+void TOWNS_MEMORY::write_data_base(uint32_t addr, uint32_t data, int* wait, int wordsize)
{
- uint32_t addr_head = (addr & 0xf0000000) >> 28;
- uint32_t addr_mid;
- uint32_t addr_low;
- uint32_t ui;
- uint8_t *pp;
-
- if(wait != NULL) *wait = mem_wait_val;
- switch(addr_head) {
- case 0x0:
- case 0x1:
- case 0x2:
- case 0x3:
- if(addr < 0x00100000) {
- write_page0_8(addr, data, wait);
- } else {
- ui = (((addr - 0x00100000) & 0x3ff00000) >> 20);
- uint8_t *p = extram_adrs[ui];
- if(p != NULL) {
- addr_low = addr & 0x000fffff;
- p[addr_low] = (uint8_t)data;
- }
- }
+ uint8_t *maddr;
+ DEVICE *daddr;
+ uint32_t banknum = addr >> 12;
+ uint32_t _naddr;
+ switch(wordsize) {
+ case 2:
+ _naddr = addr & 0xfffffffe;
break;
case 4:
- case 5:
- case 6:
- case 7:
- if(extio != NULL) extio->write_data8(addr, data);
- break;
- case 8:
- if(d_vram != NULL) {
- d_vram->write_data8(addr, data);
- if(wait != NULL) *wait = vram_wait_val;
- }
+ _naddr = addr & 0xfffffffc;
break;
- case 9:
- case 0x0a:
- case 0x0b:
- // ??
- break;
- case 0x0c:
- addr_mid = (addr & 0x03fff000) >> 16 ;
- addr_low = addr & 0x00000fff;
- pp = write_bank_adrs_cx[addr_mid];
- if(pp != NULL) {
- pp[addr_low] = (uint8_t)data;
- } else if(device_type_adrs_cx[addr_mid] != 0) {
- switch(device_type_adrs_cx[addr_mid]) {
- case TOWNS_MEMORY_TYPE_WAVERAM:
- if(d_pcm != NULL) {
- d_pcm->write_data8(addr, data);
- }
- break;
- case TOWNS_MEMORY_TYPE_DICTLEARN:
- if(d_cmos != NULL) {
- d_cmos->write_data8(addr, data);
- }
- break;
- case TOWNS_MEMORY_TYPE_FORBID:
- default:
- break;
- }
- }
- break;
- case 0x0d:
- case 0x0e:
- // ??
- break;
- case 0x0f:
- // ROM, maybe unable to write.
+ dafault:
+ _naddr = addr;
break;
}
-}
-
-void TOWNS_MEMORY::write_data16w(uint32_t addr, uint32_t data, int *wait)
-{
- uint32_t addr_head = (addr & 0xf0000000) >> 28;
- uint32_t addr_low;
- uint32_t addr_mid;
- uint16_t *pp;
- if(wait != NULL) *wait = mem_wait_val;
- switch(addr_head) {
- case 0x0:
- case 0x1:
- case 0x2:
- case 0x3:
- if(addr < 0x00100000) {
- write_page0_16(addr, data, wait);
- } else {
- ui = (((addr - 0x00100000) & 0x3ff00000) >> 20);
- uint16_t *p = (uint16_t *)extram_adrs[ui];
- if(p != NULL) {
- addr_low = (addr & 0x000fffff) >> 1;
-#if __LITTLE_ENDIAN__
- p[addr_low] = (uint16_t)data;
+
+ maddr = write_bank_adrs_cx[banknum];
+ if(maddr != NULL) {
+ // Memory found.
+ if(wait != NULL) *wait = mem_wait_val;
+ uint8_t *p;
+ switch(wordsize) {
+ case 1:
+ p = &maddr[addr & 0x00000fff];
+ *p = (uint8_t)data;
+ return;
+ break;
+ case 2:
+ {
+ pair16_t _d;
+ _d.u16 = (uint16_t)data;
+ p = &maddr[addr & 0x00000ffe];
+#if defined(__LITTLE_ENDIAN__)
+ uint16_t* pp = (uint16_t*)p;
+ *pp = _d.u16;
#else
- uint8_t *p8 = (uint8_*)(&(p[addr_low]));
- pair_t d;
- d.d = data;
- d.write_2bytes_le_to(p8);
+ p[0] = _d.l;
+ p[1] = _d.h;
#endif
+ return;
}
- }
- break;
- case 4:
- case 5:
- case 6:
- case 7:
- if(extio != NULL) extio->write_data16(addr, data);
- break;
- case 8:
- if(d_vram != NULL) {
- d_vram->write_data16(addr, data);
- if(wait != NULL) *wait = mem_wait_val;
- }
- break;
- case 9:
- case 0x0a:
- case 0x0b:
- // ??
- break;
- case 0x0c:
- addr_mid = (addr & 0x03fff000) >> 16 ;
- addr_low = addr & 0x00000fff;
- pp = (uint16_t *)write_bank_adrs_cx[addr_mid];
- if(pp != NULL) {
-#if __LITTLE_ENDIAN__
- pp[addr_low >> 1] = (uint16_t)data;
+ break;
+ case 4:
+ {
+ pair32_t _d;
+ _d.u32 = data;
+ p = &maddr[addr & 0x00000ffc];
+#if defined(__LITTLE_ENDIAN__)
+ uint32_t* pp = (uint32_t*)p;
+ *pp = data;
#else
- uint8_t *p8 = (uint8_*)(&(pp[addr_low]));
- pair_t d;
- d.d = data;
- d.write_2bytes_le_to(p8);
+ p[0] = _d.l;
+ p[1] = _d.h;
+ p[2] = _d.h2;
+ p[3] = _d.h3;
#endif
- } else if(device_type_adrs_cx[addr_mid] != 0) {
- switch(device_type_adrs_cx[addr_mid]) {
- case TOWNS_MEMORY_TYPE_WAVERAM:
- if(d_pcm != NULL) {
- d_pcm->write_data8(addr, data);
- }
+ return;
+ }
+ break;
+ default:
+ return; // Word size error
+ break;
+ }
+ } else {
+ daddr = device_bank_adrs_cx[banknum];
+ if(daddr != NULL) {
+ // Device chained.
+ switch(wordsize) {
+ case 1:
+ daddr->write_data8w(addr, data, wait);
break;
- case TOWNS_MEMORY_TYPE_DICTLEARN:
- if(d_cmos != NULL) {
- d_cmos->write_data8(addr, data);
- }
+ case 2:
+ daddr->write_data16w(addr, data, wait);
+ break;
+ case 4:
+ daddr->write_data32w(addr, data, wait);
break;
- case TOWNS_MEMORY_TYPE_FORBID:
default:
break;
}
- }
- break;
- case 0x0d:
- case 0x0e:
- // ??
- break;
- case 0x0f:
- // ROM, maybe unable to write.
- break;
- }
-}
-
-void TOWNS_MEMORY::write_data32w(uint32_t addr, uint32_t data, int *wait)
-{
- uint32_t addr_head = (addr & 0xf0000000) >> 28;
- uint32_t addr_low;
- uint32_t addr_mid;
- uint32_t *pp;
- if(wait != NULL) *wait = mem_wait_val;
- switch(addr_head) {
- case 0x0:
- case 0x1:
- case 0x2:
- case 0x3:
- if(addr < 0x00100000) {
- write_page0_32(addr, data, wait);
+ return;
} else {
- ui = (((addr - 0x00100000) & 0x3ff00000) >> 20);
- uint32_t *p = (uint32_t *)extram_adrs[ui];
- if(p != NULL) {
- addr_low = (addr & 0x000fffff) >> 2;
-#if __LITTLE_ENDIAN__
- p[addr_low] = data;
+ uint32_t _mask;
+ uint32_t _offset;
+ DEVICE* readfn;
+ DEVICE* writefn;
+ uint8_t* readp;
+ uint8_t* writep;
+ if(check_bank(_naddr, &_mask, &_offset, (void**)(&readfn), (void**)(&writefn), (void**)(&readp), (void**)(&writep))) {
+ switch(wordsize)
+ {
+ case 1:
+ if(writep != NULL) {
+ if(wait != NULL) *wait = mem_wait_val;
+ *writep = (uint8_t)data;
+ } else if(writefn != NULL) {
+ writefn->write_data8w(_naddr, data, wait);
+ }
+ break;
+ case 2:
+ if(writep != NULL) {
+
+ if(wait != NULL) *wait = mem_wait_val;
+#if defined(__LITTLE_ENDIAN__)
+ uint16_t *pp = (uint16_t*)writep;
+ *pp = (uint16_t)data;
#else
- uint8_t *p8 = (uint8_*)(&(p[addr_low]));
- pair_t d;
- d.d = data;
- d.write_4bytes_le_to(p8);
+ pair16_t _d;
+ _d.u16 = (uint16_t)data;
+ writep[0] = _d.l;
+ writep[1] = _d.h;
#endif
- }
- }
- break;
- case 4:
- case 5:
- case 6:
- case 7:
- if(extio != NULL) extio->write_data32(addr, data);
- break;
- case 8:
- if(d_vram != NULL) {
- d_vram->write_data32(addr, data);
- if(wait != NULL) *wait = vram_wait_val;
- }
- break;
- case 9:
- case 0x0a:
- case 0x0b:
- // ??
- break;
- case 0x0c:
- addr_mid = (addr & 0x03fff000) >> 16 ;
- addr_low = (addr & 0x00000fff >> 2);
- pp = (uint32_t *)write_bank_adrs_cx[addr_mid];
- if(pp != NULL) {
-#if __LITTLE_ENDIAN__
- pp[addr_low >> 2] = data;
+ } else if(writefn != NULL) {
+ writefn->write_data16w(_naddr, data, wait);
+ }
+ break;
+ case 4:
+ if(writep != NULL) {
+
+ if(wait != NULL) *wait = mem_wait_val;
+#if defined(__LITTLE_ENDIAN__)
+ uint32_t *pp = (uint32_t*)writep;
+ *pp = (uint32_t)data;
#else
- uint8_t *p8 = (uint8_*)(&(pp[addr_low]));
- pair_t d;
- d.d = data;
- d.write_4bytes_le_to(p8);
+ pair32_t _d;
+ _d.u32 = data;
+ writep[0] = _d.l;
+ writep[1] = _d.h;
+ writep[2] = _d.h2;
+ writep[3] = _d.h3;
#endif
- } else if(device_type_adrs_cx[addr_mid] != 0) {
- switch(device_type_adrs_cx[addr_mid]) {
- case TOWNS_MEMORY_TYPE_WAVERAM:
- if(d_pcm != NULL) {
- d_pcm->write_data8(addr, data);
+ } else if(writefn != NULL) {
+ writefn->write_data32w(_naddr, data, wait);
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+ // Function or memory don't exist this bank.
+ } else {
+ // Bank not registered.
+ if((addr >= 0x000cff80) && (addr <= 0x000cffff)) {
+ bool _hit;
+ write_mmio(addr, data, wait, &_hit); // ToDo: Not Hit
}
- break;
- case TOWNS_MEMORY_TYPE_DICTLEARN:
- if(d_cmos != NULL) {
- d_cmos->write_data8(addr, data);
- }
- break;
- case TOWNS_MEMORY_TYPE_FORBID:
- default:
- break;
}
}
- break;
- case 0x0d:
- case 0x0e:
- // ??
- break;
- case 0x0f:
- // ROM, maybe unable to write.
- break;
+ // Neither memory nor device nor bank.
}
+ return;
+}
+
+void TOWNS_MEMORY::write_data8w(uint32_t addr, uint32_t data, int *wait)
+{
+ write_data_base(addr, data, wait, 1);
}
-uint32_t TOWNS_MEMORY::read_page0_8(uint32_t addr, int *wait)
+void TOWNS_MEMORY::write_data16w(uint32_t addr, uint32_t data, int *wait)
{
+ write_data_base(addr, data, wait, 2);
+}
- addr = addr & 0x000fffff;
- if(wait != NULL) *wait = mem_wait_val;
- if(addr < 0xc0000) {
- return page0[addr];
- } else if(addr < 0xc8000) {
- if(d_vram != NULL) {
- if(wait != NULL) *wait = vram_wait_val;
- return d_vram->read_plane_data8(addr 0x7fff);
- }
- return 0xff;
- } else if(addr < 0xd0000) {
- // MMIO, VRAM and ram.
- if(0xcff80 <= addr && addr < 0xcffe0) {
-#ifdef _DEBUG_LOG
-// this->out_debug_log(_T("MR\t%4x\n"), addr);
-#endif
- // memory mapped i/o
- switch(addr & 0xffff) {
- case 0xff80:
- // mix register
- return mix;
- case 0xff81:
- // update register
- return wplane | (rplane << 6);
- case 0xff83:
- // page select register
- return pagesel;
- case 0xff86:
- // status register
- return (disp ? 0x80 : 0) | (vsync ? 4 : 0) | 0x10;
- case 0xff8e:
- // crtc addr register
- return d_crtc->read_io8(0);
- case 0xff8f:
- // crtc data register
- return d_crtc->read_io8(1);
- case 0xff94:
- return 0x80; // ???
- case 0xff96:
- return kanji16[(kj_ofs | ((kj_row & 0xf) << 1)) & 0x3ffff];
- case 0xff97:
- return kanji16[(kj_ofs | ((kj_row++ & 0xf) << 1) | 1) & 0x3ffff];
- case 0xffa0:
- return cmdreg;
- case 0xffa1:
- return imgcol | 0xf0;
- case 0xffa2:
- return maskreg;
- case 0xffa3:
- return compbit;
- case 0xffab:
- return bankdis & 0xf;
- }
- return 0xff;
- }
- } else if(addr < 0xd8000) {
- if(!bankd0_dict) {
- return ram_0d0[addr - 0x0d0000];
- // RAM? DICT?
- } else {
- // DICT
- return dict_rom[addr - 0xd0000 + (((uint32_t)dict_bank) << 15))];
- }
- } else if(addr < 0xda000) {
- if(!bankd0_dict) {
- // RAM? DICT?
- return ram_0d0[addr - 0x0d0000];
- } else {
- // DICT
- if(d_cmos != NULL) return d_cmos->read_data8(addr);
- return;
- }
- } else if(addr < 0xf0000) {
- if(!bankd0_dict) {
- return ram_0d0[addr - 0x0d0000];
- }
- return 0xff;
- } else if(addr < 0xf8000) {
- return ram_0f0[addr - 0xf0000];
- } else if(addr < 0x100000) {
- if(bankf8_ram) {
- // RAM
- return ram_0f8[addr - 0xf8000];
- } else {
- // BOOT ROM(ro)
- return system_rom[addr - 0xf8000 + 0x18000];
- }
- }
- return 0xff;
+void TOWNS_MEMORY::write_data32w(uint32_t addr, uint32_t data, int *wait)
+{
+ write_data_base(addr, data, wait, 4);
}
+
uint32_t TOWNS_MEMORY::read_data8(uint32_t addr)
{
- int wait;
- return read_data8w(addr, &wait);
+ return read_data_base(addr, NULL, 1);
}
uint32_t TOWNS_MEMORY::read_data16(uint32_t addr)
{
- int wait;
- return read_data16w(addr, &wait);
+ return read_data_base(addr, NULL, 2);
}
uint32_t TOWNS_MEMORY::read_data32(uint32_t addr)
{
- int wait;
- return read_data32w(addr, &wait);
+ return read_data_base(addr, NULL, 4);
}
-uint32_t TOWNS_MEMORY::read_data8w(uint32_t addr, int *wait)
+void TOWNS_MEMORY::write_data8(uint32_t addr, uint32_t data)
{
- uint32_t addr_head = (addr & 0xf0000000) >> 28;
- uint32_t addr_mid;
- uint32_t addr_low;
- uint32_t ui;
- uint8_t *pp;
-
- if(wait != NULL) *wait = mem_wait_val;
- switch(addr_head) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- if(addr < 0x00100000) {
- return read_page0_8(addr, wait);
- } else {
- ui = (((addr - 0x00100000) & 0x3ff00000) >> 20);
- pp = extram_adrs[ui];
- if(pp != NULL) {
- addr_low = addr & 0x000fffff;
- return pp[addr_low];
- }
- }
- return 0xff;
+ write_data_base(addr, data, NULL, 1);
+}
+
+void TOWNS_MEMORY::write_data16(uint32_t addr, uint32_t data)
+{
+ write_data_base(addr, data, NULL, 2);
+}
+
+void TOWNS_MEMORY::write_data32(uint32_t addr, uint32_t data)
+{
+ write_data_base(addr, data, NULL, 4);
+}
+
+// Address (TOWNS BASIC):
+// 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)
+{
+ uint32_t val = 0xff;
+ switch(addr & 0xffff) {
+ case 0x0020: // Software reset ETC.
+ // reset cause register
+ val = ((software_reset) ? 1 : 0) | ((d_cpu->get_shutdown_flag() != 0) ? 2 : 0);
+ software_reset = false;
+ d_cpu->set_shutdown_flag(0);
+ val = val | 0x7c;
break;
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- if(extio != NULL) return extio->read_data8(addr);
+ case 0x0022:
+ // Power register
+ val = 0xff;
break;
- case 0x08:
- if(d_vram != NULL) {
- if(wait != NULL) *wait = vram_wait_val;
- return d_vram->read_data8(addr);
+ case 0x0030:
+ val = (((machine_id & 0x1f) << 3) | (cpu_id & 7));
+ // SPEED: bit0/Write
+ break;
+ 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;
}
break;
- case 0x09:
- case 0x0a:
- case 0x0b:
- return 0xff;
- // ??
+ case 0x0400: // Resolution:
+ val = 0xfe;
break;
- case 0x0c:
- addr_mid = (addr & 0x03fff000) >> 12 ;
- pp = read_bank_adrs_cx[addr_mid];
- if(pp != NULL) {
- addr_low = addr & 0x00000fff;
- return pp[addr_low];
- } else if(device_type_adrs_cx[addr_mid] != 0) {
- switch(device_type_adrs_cx[addr_mid]) {
- case TOWNS_MEMORY_TYPE_WAVERAM:
- if(d_pcm != NULL) {
- return d_pcm->read_data8((addr & 0x0ffe));
- }
+ case 0x0404: // System Status Reg.
+ val = (bankc0_vram) ? 0x7f : 0xff;
+ break;
+ case 0x05c0:
+ val = (extra_nmi_mask) ? 0xf7 : 0xff;
+ break;
+ case 0x05c2:
+ val = (extra_nmi_val) ? 0xff : 0xf7;
+ break;
+ case 0x05e8:
+ // After Towns1F/2F/1H/2H
+ {
+ switch(machine_id & 0xff00) {
+ case 0x0000:
+ case 0x0100:
+ val = 0xff;
break;
- case TOWNS_MEMORY_TYPE_DICTLEARN:
- if(d_cmos != NULL) {
- return d_cmos->read_data8((addr & 0x0ffe));
- }
+ case 0x0200:
+ case 0x0300:
+ case 0x0400:
+ case 0x0500:
+ case 0x0600:
+ case 0x0700:
+ case 0x0800:
+ case 0x0a00:
+ val = ((extram_size >> 20) & 0x1f);
+ break;
+ case 0x0b00:
+ case 0x0c00:
+ case 0x0d00:
+ case 0x0f00:
+ val = ((extram_size >> 20) & 0x7f);
break;
- case TOWNS_MEMORY_TYPE_FORBID:
default:
- return 0xff;
+ val = 0xff; // ???
break;
}
- return 0xff;
- } else {
- return 0xff;
}
break;
- case 0x0d:
- case 0x0e:
- // ??
- return 0xff;
+
+ 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;
- case 0x0f:
- // ROM, maybe unable to write.
- if(addr < 0xfffc0000) {
- return 0xff;
+ }
+ return val;
+}
+
+void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
+{
+
+ switch(addr & 0xffff) {
+ case 0x0020: // Software reset ETC.
+ // reset cause register
+ if((data & 0x80) != 0) {
+ nmi_vector_protect = true;
+ } else {
+ nmi_vector_protect = false;
+ }
+ if((data & 0x01) != 0) {
+ software_reset = true;
} else {
- pp = system_rom;
- addr_low = addr - 0xfffc0000;
- return (uint32_t)pp[addr_low];
+ software_reset = false;
+ }
+ if((data & 0x40) != 0) {
+ d_cpu->set_shutdown_flag(1);
+ emu->power_off();
+ }
+ if(software_reset) {
+ d_cpu->reset();
+ }
+ break;
+ case 0x0022:
+ if((data & 0x40) != 0) {
+ d_cpu->set_shutdown_flag(1);
+ emu->power_off();
+ }
+ // 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);
+ register_event(this, EVENT_1US_WAIT, 1.0, false, &event_wait_1us);
+ d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
}
break;
+ case 0x0404: // System Status Reg.
+ bankc0_vram = ((data & 0x80) != 0);
+ break;
+ case 0x05c0:
+ extra_nmi_mask = ((data & 0x08) == 0);
+ break;
+ 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;
}
- return 0xff;
+ return;
}
-uint32_t TOWNS_MEMORY::read_data16w(uint32_t addr, int *wait)
+void TOWNS_MEMORY::event_callback(int id, int err)
{
- uint32_t addr_head = (addr & 0xf0000000) >> 28;
- uint32_t addr_mid;
- uint32_t addr_low;
- uint32_t ui;
- uint16_t *pp;
-
+ switch(id) {
+ case EVENT_1US_WAIT:
+ cvent_wait_1us = -1;
+ if(machine_id >= 0x0300) { // After UX*/10F/20F/40H/80H
+ d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
+ }
+ break;
+ default:
+ break;
+ }
- if(wait != NULL) *wait = mem_wait_val;
- switch(addr_head) {
+}
+
+uint32_t TOWNS_MEMORY::read_mmio(uint32_t addr, int *wait, bool *hit)
+{
+ if(hit != NULL) *hit = false;
+ if(wait != NULL) *wait = 0; // OK?
+ if(addr >= 0x000d0000) return 0xffffffff;
+ if(addr < 0x000cff80) return 0xffffffff;
+ uint32_t val = 0xff;
+ bool found = false;
+ switch(addr & 0x7f) {
case 0x00:
+ if(d_vram != NULL) {
+ val = d_vram->read_io8(FMTOWNS_VRAM_IO_CURSOR);
+ found = true;
+ }
+ break;
case 0x01:
+ if(d_vram != NULL) {
+ val = d_vram->read_io8(FMTOWNS_VRAM_IO_FMR_RAMSELECT);
+ found = true;
+ }
+ break;
case 0x02:
+ if(d_vram != NULL) {
+ val = d_vram->read_io8(FMTOWNS_VRAM_IO_FMR_DISPMODE);
+ found = true;
+ }
+ break;
case 0x03:
- if(addr < 0x00100000) {
- return read_page0_16(addr, wait);
- } else {
- ui = (((addr - 0x00100000) & 0x3ff00000) >> 20);
- pp = (uint16_t *)extram_adrs[ui];
- if(pp != NULL) {
-#ifdef __LITTLE_ENDIAN__
- addr_low = (addr & 0x000fffff) >> 1;
- return pp[addr_low];
-#else
- pair_t d;
- uint8 *p8 = (uint8 *)pp;
- addr_low = addr & 0x000ffffe;
- d.read_2bytes_le_from(&(p8[addr_low]));
- return d.d;
-#endif
- }
+ if(d_vram != NULL) {
+ val = d_vram->read_io8(FMTOWNS_VRAM_IO_FMR_PAGESEL);
+ found = true;
}
- return 0xffffffff;
break;
case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- if(extio != NULL) return extio->read_data16(addr);
+ val = 0x7f; // Reserve.FIRQ
+ found = true;
break;
- case 0x08:
+ case 0x06:
if(d_vram != NULL) {
- if(wait != NULL) *wait = vram_wait_val;
- return d_vram->read_data16(addr);
+ val = d_vram->read_io8(FMTOWNS_VRAM_IO_SYNC_STATUS);
+ found = true;
}
break;
- case 0x09:
- case 0x0a:
- case 0x0b:
- return 0xffffffff;
- // ??
+ //case 0x14:
+ //case 0x15:
+ case 0x16:
+ case 0x17:
+ if(d_vram != NULL) {
+ val = d_vram->read_io8(FMTOWNS_VRAM_KANJICG + (addr & 3));
+ found = true;
+ }
break;
- case 0x0c:
- addr_mid = (addr & 0x03fff000) >> 12 ;
- pp = (uint16_t *)read_bank_adrs_cx[addr_mid];
- if(pp != NULL) {
-#ifdef __LITTLE_ENDIAN__
- addr_low = (addr & 0x00000fff) >> 1;
- return pp[addr_low];
-#else
- pair_t d;
- uint8 *p8 = (uint8 *)pp;
- addr_low = addr & 0x00000ffe;
- d.read_2bytes_le_from(&(p8[addr_low]));
- return d.d;
-#endif
- } else if(device_type_adrs_cx[addr_mid] != 0) {
- switch(device_type_adrs_cx[addr_mid]) {
- case TOWNS_MEMORY_TYPE_WAVERAM:
- if(d_pcm != NULL) {
- return d_pcm->read_data8((addr & 0x0ffe));
- }
- break;
- case TOWNS_MEMORY_TYPE_DICTLEARN:
- if(d_cmos != NULL) {
- return d_cmos->read_data8((addr & 0x0ffe));
- }
- break;
- case TOWNS_MEMORY_TYPE_FORBID:
- default:
- return 0xffff;
- break;
- }
- return 0xffff;
- } else {
- return 0xffff;
+ case 0x18:
+ if(d_beep != NULL) {
+ d_beep->write_signal(SIG_BEEP_ON, 1, 1);
+ found = true;
}
break;
- case 0x0d:
- case 0x0e:
- // ??
- return 0xffff;
+ case 0x19:
+ val = val & ((ankcg_enabled) ? 0x00 : 0x01);
+ found = true;
break;
- case 0x0f:
- // ROM, maybe unable to write.
- if(addr < 0xfffc0000) {
- return 0xffff;
- } else {
-#ifdef __LITTLE_ENDIAN__
- pp = (uint16_t *)system_rom;
- addr_low = (addr - 0xfffc0000) >> 1;
- return (uint32_t)pp[addr_low];
-#else
- pair_t d;
- uint8_t *p8;
- addr_low = (addr - 0xfffc0000) & 0x3fffe;
- p8 = &(system_rom[addr_low]);
- d.read_2bytes_le_from(p8);
- return d.d;
-#endif
- }
+ case 0x20:
+ val = 0xff;
+ val = val & 0x7f;
+ found = true;
+ break;
+ default:
break;
}
- return 0xffff;
+ if(hit != NULL) *hit = found;
+ return (uint32_t)val;
}
-uint32_t TOWNS_MEMORY::read_data32w(uint32_t addr, int *wait)
+void TOWNS_MEMORY::write_mmio(uint32_t addr, uint32_t data, int *wait, bool *hit)
{
- uint32_t addr_head = (addr & 0xf0000000) >> 28;
- uint32_t addr_mid;
- uint32_t addr_low;
- uint32_t ui;
- uint32_t *pp;
-
- if(wait != NULL) *wait = mem_wait_val;
- switch(addr_head) {
+ if(hit != NULL) *hit = false;
+ if(wait != NULL) *wait = 0; // OK?
+ if(addr >= 0x000d0000) return;
+ if(addr < 0x000cff80) return;
+ bool found = false;
+ switch(addr & 0x7f) {
case 0x00:
+ if(d_vram != NULL) {
+ d_vram->write_io8(FMTOWNS_VRAM_IO_CURSOR, data);
+ found = true;
+ }
+ break;
case 0x01:
+ if(d_vram != NULL) {
+ d_vram->write_io8(FMTOWNS_VRAM_IO_FMR_RAMSELECT, data);
+ found = true;
+ }
+ break;
case 0x02:
+ if(d_vram != NULL) {
+ d_vram->write_io8(FMTOWNS_VRAM_IO_FMR_DISPMODE, data);
+ found = true;
+ }
+ break;
case 0x03:
- if(addr < 0x00100000) {
- return read_page0_32(addr);
- } else {
- ui = (((addr - 0x00100000) & 0x3ff00000) >> 20);
- pp = (uint32_t *)extram_adrs[ui];
- if(pp != NULL) {
-#ifdef __LITTLE_ENDIAN__
- addr_low = (addr & 0x000fffff) >> 2;
- return pp[addr_low];
-#else
- pair_t d;
- uint8 *p8 = (uint8 *)pp;
- addr_low = addr & 0x000ffffc;
- d.read_4bytes_le_from(&(p8[addr_low]));
- return d.d;
-#endif
- }
+ if(d_vram != NULL) {
+ d_vram->write_io8(FMTOWNS_VRAM_IO_FMR_PAGESEL, data);
+ found = true;
}
- return 0xffffffff;
break;
case 0x04:
- case 0x05:
+ found = true;
+ break;
case 0x06:
- case 0x07:
- if(extio != NULL) return extio->read_data32(addr);
+ found = true;
break;
- case 0x08:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
if(d_vram != NULL) {
- if(wait != NULL) *wait = vram_wait_val;
- return d_vram->read_data32(addr);
+ d_vram->write_io8(FMTOWNS_VRAM_KANJICG + (addr & 3), data);
+ found = true;
}
break;
- case 0x09:
- case 0x0a:
- case 0x0b:
- return 0xffffffff;
- // ??
- break;
- case 0x0c:
- addr_mid = (addr & 0x03fff000) >> 12 ;
- pp = (uint32_t *)read_bank_adrs_cx[addr_mid];
- if(pp != NULL) {
-#ifdef __LITTLE_ENDIAN__
- addr_low = (addr & 0x00000fff) >> 2;
- return pp[addr_low];
-#else
- pair_t d;
- uint8 *p8 = (uint8 *)pp;
- addr_low = addr & 0x00000ffc;
- d.read_4bytes_le_from(&(p8[addr_low]));
- return d.d;
-#endif
- } else if(device_type_adrs_cx[addr_mid] != 0) {
- switch(device_type_adrs_cx[addr_mid]) {
- case TOWNS_MEMORY_TYPE_WAVERAM:
- if(d_pcm != NULL) {
- return d_pcm->read_data8((addr & 0x0ffc));
- }
- break;
- case TOWNS_MEMORY_TYPE_DICTLEARN:
- if(d_cmos != NULL) {
- return d_cmos->read_data8((addr & 0x0ffc));
- }
- break;
- case TOWNS_MEMORY_TYPE_FORBID:
- default:
- return 0xffffffff;
- break;
- }
- return 0xffffffff;
- } else {
- return 0xffffffff;
+ case 0x18:
+ if(d_beep != NULL) {
+ d_beep->write_signal(SIG_BEEP_ON, 0, 1);
+ found = true;
}
break;
- case 0x0d:
- case 0x0e:
- // ??
- return 0xffffffff;
+ case 0x19:
+ ankcg_enabled = ((data & 1) == 0);
+ found = true;
break;
- case 0x0f:
- // ROM, maybe unable to write.
- if(addr < 0xfffc0000) {
- return 0xffffffff;
- } else {
-#ifdef __LITTLE_ENDIAN__
- pp = (uint32_t *)system_rom;
- addr_low = (addr - 0xfffc0000) >> 2;
- return pp[addr_low];
-#else
- pair_t d;
- uint8_t *p8;
- addr_low = (addr - 0xfffc0000) & 0x3fffc;
- p8 = &(system_rom[addr_low]);
- d.read_4bytes_le_from(p8);
- return d.d;
-#endif
- }
+ case 0x20:
+ found = true;
+ break;
+ default:
break;
}
- return 0xffffffff;
+ if(hit != NULL) *hit = found;
+ return;
+}
+
+void TOWNS_MEMORY::initialize_tables(void)
+{
+ // Address Cx000000
+ memset(write_bank_adrs_cx, 0x00, sizeof(write_bank_adrs_cx));
+ memset(read_bank_adrs_cx, 0x00, sizeof(read_bank_adrs_cx));
+ memset(device_bank_adrs_cx, 0x00, sizeof(device_bank_adrs_cx));
+ memset(type_bank_adrs_cx, 0x00, sizeof(type_bank_adrs_cx));
+
+ // PAGE0
+ for(uint32_t ui = 0x00000; ui < 0x000c0; ui++) { // $00000000 - $000bffff
+ read_bank_adrs_cx[ui] = &(ram_page0[ui << 12]);
+ write_bank_adrs_cx[ui] = &(ram_page0[ui << 12]);
+ }
+
+ for(uint32_t ui = 0x000c0; ui < 0x000c8; ui++) { // $000c0000 - $000effff
+ type_bank_adrs_cx[ui] = (TOWNS_MEMORY_FMR_VRAM << 24) | ((ui - 0xc0) << 12);
+ }
+ for(uint32_t ui = 0x000c8; ui < 0x000c9; ui++) { // $000c0000 - $000effff
+ type_bank_adrs_cx[ui] = (TOWNS_MEMORY_FMR_TEXT << 24) | ((ui - 0xc8) << 12);
+ }
+ for(uint32_t ui = 0x000c9; ui < 0x000ca; ui++) { // $000c0000 - $000effff
+ type_bank_adrs_cx[ui] = (TOWNS_MEMORY_FMR_VRAM_RESERVE << 24) | ((ui - 0xc8) << 12);
+ }
+ for(uint32_t ui = 0x000ca; ui < 0x000cb; ui++) { // $000c0000 - $000effff
+ type_bank_adrs_cx[ui] = (TOWNS_MEMORY_SPRITE_ANKCG1 << 24) | ((ui - 0xca) << 12);
+ }
+ for(uint32_t ui = 0x000cb; ui < 0x000cc; ui++) { // $000c0000 - $000effff
+ type_bank_adrs_cx[ui] = (TOWNS_MEMORY_ANKCG2 << 24) | ((ui - 0xcb) << 12);
+ }
+ 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 < 0x000f0; ui++) { // $000c0000 - $000effff
+ device_bank_adrs_cx[ui] = d_dictionary;
+ }
+ 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++) {
+ read_bank_adrs_cx[ui] = &(extram[(ui - 0x100) << 12]);
+ write_bank_adrs_cx[ui] = &(extram[(ui - 0x100) << 12]);
+ }
+ // ToDo: EXTRA IO(0x40000000 - 0x80000000)
+
+ // VRAM
+ /*
+ for(uint32_t ui = 0x000c0; ui < 0x000ca; ui++) {
+ device_bank_adrs_cx[ui] = d_vram;
+ }
+ for(uint32_t ui = 0x000ca; ui < 0x000cb; ui++) {
+ device_bank_adrs_cx[ui] = d_sprite;
+ }
+ */
+ for(uint32_t ui = 0x80000; ui < (0x80000 + (vram_size >> 12)); ui++) {
+ device_bank_adrs_cx[ui] = d_vram;
+ }
+ for(uint32_t ui = 0x80100; ui < (0x80100 + (vram_size >> 12)); ui++) {
+ device_bank_adrs_cx[ui] = d_vram;
+ }
+ for(uint32_t ui = 0x81000; ui < 0x81020; ui++) {
+ device_bank_adrs_cx[ui] = d_sprite;
+ }
+
+ // ROM CARD
+ for(uint32_t ui = 0xc0000; ui < 0xc1000; ui++) {
+ device_bank_adrs_cx[ui] = d_romcard[0];
+ }
+ // ROM CARD2
+ for(uint32_t ui = 0xc1000; ui < 0xc2000; ui++) {
+ device_bank_adrs_cx[ui] = d_romcard[1];
+ }
+ for(uint32_t ui = 0xc2140; ui < 0xc2142; ui++) {
+ 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++) {
+ device_bank_adrs_cx[ui] = d_msdos;
+ }
+ for(uint32_t ui = 0xc2080; ui < 0xc2100; ui++) {
+ device_bank_adrs_cx[ui] = d_dictionary;
+ }
+ for(uint32_t ui = 0xc2100; ui < 0xc2140; ui++) {
+ 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++) {
+ device_bank_adrs_cx[ui] = d_sysrom;
+ }
+}
+
+
+uint32_t TOWNS_MEMORY::read_data8(uint32_t addr)
+{
+ int wait;
+ return read_data8w(addr, &wait);
+}
+
+uint32_t TOWNS_MEMORY::read_data16(uint32_t addr)
+{
+ int wait;
+ return read_data16w(addr, &wait);
+}
+
+uint32_t TOWNS_MEMORY::read_data32(uint32_t addr)
+{
+ int wait;
+ return read_data32w(addr, &wait);
}
void TOWNS_MEMORY::write_dma_data8(uint32_t addr, uint32_t data)
return read_data16w(addr & dma_addr_mask, &wait);
}
-void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
-{
- switch(addr & 0xffff) {
- case 0x20:
- // protect and reset
- protect = data;
- update_bank();
- if(data & 0x40) {
- // power off
- emu->power_off();
- }
- if(data & 1) {
- // software reset
- rst |= 1;
- d_cpu->reset();
- }
- // protect mode
- if(data & 0x80) {
- // NMI Vector protect
- }
- break;
- case 0x22:
- // Power off
- if(data & 0x40) {
- // power off
- emu->power_off();
- }
- break;
- case 0x400:
- // video output control
- break;
- case 0x402:
- // update register
- wplane = data & 0xf;
- break;
- case 0x404:
- // read out register
- mainmem = data & 0x80;
- rplane = data & 3;
- update_bank();
- break;
- case 0x408:
- // palette code register
- apalsel = data & 0xf;
- break;
- case 0x40a:
- // blue level register
- apal[apalsel][0] = data & 0xf0;
- palette_cg[apalsel] = RGB_COLOR(apal[apalsel][1], apal[apalsel][2], apal[apalsel][0]);
- break;
- case 0x40c:
- // red level register
- apal[apalsel][1] = data & 0xf0;
- palette_cg[apalsel] = RGB_COLOR(apal[apalsel][1], apal[apalsel][2], apal[apalsel][0]);
- break;
- case 0x40e:
- // green level register
- apal[apalsel][2] = data & 0xf0;
- palette_cg[apalsel] = RGB_COLOR(apal[apalsel][1], apal[apalsel][2], apal[apalsel][0]);
- break;
- case 0x480:
- bankf8_ram = false;
- if((data & 0x02) != 0) {
- bankf8_ram = true;
- }
- bankf8_dic = false;
- if((data & 0x01) != 0) {
- bankf8_dic = true;
- }
- break;
- case 0x484:
- dict_bank = data & 0x0f;
- break;
- case 0xfd98:
- case 0xfd99:
- case 0xfd9a:
- case 0xfd9b:
- case 0xfd9c:
- case 0xfd9d:
- case 0xfd9e:
- case 0xfd9f:
- // digital palette
- dpal[addr & 7] = data;
- if(data & 8) {
- palette_cg[addr & 7] = RGB_COLOR(data & 2 ? 255 : 0, data & 4 ? 255 : 0, data & 1 ? 255 : 0);
- } else {
- palette_cg[addr & 7] = RGB_COLOR(data & 2 ? 127 : 0, data & 4 ? 127 : 0, data & 1 ? 127 : 0);
- }
- break;
- case 0xfda0:
- // video output control
- outctrl = data;
- break;
- }
-}
-
-uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
-{
- uint32_t val = 0xff;
-
- switch(addr & 0xffff) {
- case 0x20:
- // reset cause register
- val = rst | (d_cpu->get_shutdown_flag() << 1);
- rst = 0;
- d_cpu->set_shutdown_flag(0);
- return val | 0x7c;
- case 0x21:
-// return 0x1f;
- return 0xdf;
- case 0x24:
- return dma_wrap_reg;
- case 0x30:
- // machine & cpu id
- return machine_id;
- case 0x400:
- // system status register
-#ifdef _FMR60
- return 0xff;
-#else
- return 0xfe;
-// return 0xf6;
-#endif
- case 0x402:
- // update register
- return wplane | 0xf0;
- case 0x404:
- // read out register
- return mainmem | rplane | 0x7c;
- case 0x40a:
- // blue level register
- return apal[apalsel][0];
- case 0x40c:
- // red level register
- return apal[apalsel][1];
- case 0x40e:
- // green level register
- return apal[apalsel][2];
- // Towns
- case 0x480:
- return (bankf8_ram ? 0x02 : 0x00) | (bankf8_dic ? 0x01 : 0x00);
- break;
- case 0x484:
- return dict_bank & 0x0f;
- break;
- case 0xfd98:
- case 0xfd99:
- case 0xfd9a:
- case 0xfd9b:
- case 0xfd9c:
- case 0xfd9d:
- case 0xfd9e:
- case 0xfd9f:
- // digital palette
- return dpal[addr & 7] | 0xf0;
- case 0xfda0:
- // status register
- return (disp ? 2 : 0) | (vsync ? 1 : 0) | 0xfc;
- }
- return 0xff;
-}
-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_DISP) {
- disp = ((data & mask) != 0);
- } else if(id == SIG_MEMORY_VSYNC) {
- vsync = ((data & mask) != 0);
+ if(ch == SIG_MEMORY_EXTNMI) {
+ extra_nmi_val = ((data & mask) != 0);
+ } else if(ch == SIG_CPU_NMI) {
+ // Check protect
+ d_cpu->write_signal(SIG_CPU_NMI, data, mask);
+ } else if(ch == SIG_CPU_IRQ) {
+ d_cpu->write_signal(SIG_CPU_IRQ, data, mask);
+ } else if(ch == SIG_CPU_BUSREQ) {
+ d_cpu->write_signal(SIG_CPU_BUSREQ, data, mask);
+ } 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);
}
}
-void TOWNS_MEMORY::update_dma_addr_mask()
+uint32_t TOWNS_MEMORY::read_signal(int ch)
{
- switch(dma_addr_reg & 3) {
- case 0:
- dma_addr_mask = d_cpu->get_address_mask();
- break;
- case 1:
- if(!(dma_wrap_reg & 1) && d_cpu->get_address_mask() == 0x000fffff) {
- dma_addr_mask = 0x000fffff;
- } else {
- dma_addr_mask = 0x00ffffff;
- }
- break;
- default:
- if(!(dma_wrap_reg & 1) && d_cpu->get_address_mask() == 0x000fffff) {
- dma_addr_mask = 0x000fffff;
- } else {
- dma_addr_mask = 0xffffffff;
- }
- break;
- }
+ 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
-void TOWNS_MEMORY::save_state(FILEIO* state_fio)
+bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
{
- state_fio->FputUint32(STATE_VERSION);
- state_fio->FputInt32(this_device_id);
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ state_fio->StateValue(bankc0_vram);
+ state_fio->StateValue(ankcg_enabled);
+ state_fio->StateValue(machine_id);
+ state_fio->StateValue(cpu_id);
- state_fio->FputBool(bank8_ram);
- state_fio->FputBool(bankd0_dict);
- state_fio->FputUint8(dict_bank);
- state_fio->FputUint32_LE(extram_pages);
-
- state_fio->FputInt8((int8_t)vram_wait_val);
- state_fio->FputInt8((int8_t)mem_wait_val);
- state_fio->FputInt8((int8_t)extio_wait_val);
-
- // Save rom?
- state_fio->Fwrite(page0, sizeof(page0));
- state_fio->Fwrite(ram_0d0, sizeof(ram_0d0));
- state_fio->Fwrite(ram_0f0, sizeof(ram_0f0));
- state_fio->Fwrite(ram_0f8, sizeof(ram_0f8));
+ state_fio->StateValue(dma_addr_mask);
+ //state_fio->StateValue(dma_addr_reg);
+ //state_fio->StateValue(dma_wrap_reg);
- // ROM?
- state_fio->Fwrite(msdos_rom, sizeof(msdos_rom));
- state_fio->Fwrite(dict_rom, sizeof(dict_rom));
- state_fio->Fwrite(font_rom, sizeof(font_rom));
- //state_fio->Fwrite(font_20_rom, sizeof(font_20_rom));
- state_fio->Fwrite(system_rom, sizeof(system_rom));
+ state_fio->StateArray(ram_page0, sizeof(ram_page0), 1);
+ state_fio->StateArray(ram_0c0, sizeof(ram_0c0), 1);
+ state_fio->StateArray(ram_0c8, sizeof(ram_0c8), 1);
+ state_fio->StateArray(ram_0ca, sizeof(ram_0ca), 1);
+ state_fio->StateArray(ram_0cb, sizeof(ram_0cb), 1);
+ state_fio->StateArray(ram_0cc, sizeof(ram_0cc), 1);
- state_fio->Fwrite(extram_base, extram_pages * 0x100000);
-
-// ToDo
- state_fio->FputUint8(protect);
- state_fio->FputUint8(rst);
-}
-bool TOWNS_MEMORY::load_state(FILEIO* state_fio)
-{
- if(state_fio->FgetUint32() != STATE_VERSION) {
- return false;
- }
- if(state_fio->FgetInt32() != this_device_id) {
- return false;
+ if(loading) {
+ uint32_t length_tmp = state_fio->FgetUint32_LE();
+ if(extram != NULL) {
+ free(extram);
+ extram = NULL;
+ }
+ length_tmp = length_tmp & 0x3ff00000;
+ extram_size = length_tmp;
+ if(length_tmp > 0) {
+ extram = (uint8_t*)malloc(length_tmp);
+ }
+ if(extram == NULL) {
+ extram_size = 0;
+ return false;
+ } else {
+ state_fio->Fread(extram, extram_size, 1);
+ }
+ } else {
+ if(extram == NULL) {
+ state_fio->FputUint32_LE(0);
+ } else {
+ state_fio->FputUint32_LE(extram_size & 0x3ff00000);
+ state_fio->Fwrite(extram, extram_size, 1);
+ }
}
+
+ state_fio->StateValue(vram_wait_val);
+ state_fio->StateValue(mem_wait_val);
+ state_fio->StateValue(vram_size);
- bank8_tam = state_fio->FgetBool();
- bank0_dict = state_fio->FgetBool();
- dict_bank = state_fio->FgetUint8();
- extram_pages = state_fio->FgetUint32_LE();
-
- vram_wait_val = (int)state_fio->FgetInt8();
- mem_wait_val = (int)state_fio->FgetInt8();
- extio_wait_val = (int)state_fio->FgetInt8();
+ // ToDo: Do save ROMs?
- // Save rom?
- state_fio->Fread(page0, sizeof(page0));
- state_fio->Fread(ram_0d0, sizeof(ram_0d0));
- state_fio->Fread(ram_0f0, sizeof(ram_0f0));
- state_fio->Fread(ram_0f8, sizeof(ram_0f8));
-
- // ROM?
- state_fio->Fread(msdos_rom, sizeof(msdos_rom));
- state_fio->Fread(dict_rom, sizeof(dict_rom));
- state_fio->Fread(font_rom, sizeof(font_rom));
- //state_fio->Fwrite(font_20_rom, sizeof(font_20_rom));
- state_fio->Fread(system_rom, sizeof(system_rom));
-
- uint8_t *pp;
- pp = malloc(extram_pages * 0x100000);
- if(pp == NULL) {
- return false;
- } else {
- state_fio->Fread(pp, extram_pages * 0x100000);
+ if(loading) {
+ initialize_tables();
}
- //ToDo
- protect = state_fio->FgetUint8();
- rst = state_fio->FgetUint8();
-
-
- // post process
- //update_bank();
- extram_base = pp;
- initialize_tables();
-
return true;
}
+}