OSDN Git Service

[VM][FMTOWNS][TOWNS_DMAC] Implement DMAC registers to I/O port 0020h-0024h, same...
authorK.Ohta <whatisthis.sowhat@gmail.com>
Wed, 29 Jan 2020 10:22:02 +0000 (19:22 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Wed, 29 Jan 2020 10:22:02 +0000 (19:22 +0900)
source/src/vm/fmtowns/fmtowns.cpp
source/src/vm/fmtowns/towns_dmac.cpp
source/src/vm/fmtowns/towns_dmac.h
source/src/vm/fmtowns/towns_memory.cpp
source/src/vm/fmtowns/towns_memory.h

index f83a46f..c45b78e 100644 (file)
@@ -325,6 +325,7 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_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_dmac(dma);
        memory->set_context_vram(vram);
        memory->set_context_system_rom(sysrom);
        memory->set_context_msdos(msdosrom);
index 1558219..39ddaee 100644 (file)
@@ -11,6 +11,9 @@ void TOWNS_DMAC::initialize()
 void TOWNS_DMAC::reset()
 {
        UPD71071::reset();
+       dma_wrap_reg = 0;
+       dma_addr_reg = 0;
+       dma_addr_mask = 0xffffffff; // OK?
 }
 
 void TOWNS_DMAC::write_io8(uint32_t addr, uint32_t data)
@@ -85,9 +88,9 @@ void TOWNS_DMAC::do_dma_inc_dec_ptr_8bit(int c)
 {
        // Note: FM-Towns may extend to 32bit.
        if(dma[c].mode & 0x20) {
-               dma[c].areg = (dma[c].areg - 1) & 0xffffffff;
+               dma[c].areg = (dma[c].areg - 1) & dma_addr_mask;
        } else {
-               dma[c].areg = (dma[c].areg + 1) & 0xffffffff;
+               dma[c].areg = (dma[c].areg + 1) & dma_addr_mask;
        }
 }
 
@@ -95,11 +98,112 @@ void TOWNS_DMAC::do_dma_inc_dec_ptr_16bit(int c)
 {
        // Note: FM-Towns may extend to 32bit.
        if(dma[c].mode & 0x20) {
-               dma[c].areg = (dma[c].areg - 2) & 0xffffffff;
+               dma[c].areg = (dma[c].areg - 2) & dma_addr_mask;
        } else {
-               dma[c].areg = (dma[c].areg + 2) & 0xffffffff;
+               dma[c].areg = (dma[c].areg + 2) & dma_addr_mask;
        }
 }
 
-       
+uint32_t TOWNS_DMAC::read_signal(int id)
+{
+       if(id == SIG_TOWNS_DMAC_ADDR_REG) {
+               return dma_addr_reg;
+       } else if(SIG_TOWNS_DMAC_WRAP_REG) {
+               return dma_wrap_reg;
+       } else if(id == SIG_TOWNS_DMAC_ADDR_MASK) {
+               return dma_addr_mask;
+       }
+       return UPD71071::read_signal(id);
+}
+
+void TOWNS_DMAC::write_signal(int id, uint32_t data, uint32_t mask)
+{
+       if(id == SIG_TOWNS_DMAC_ADDR_REG) {
+               dma_addr_reg = data & 3;
+               this->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, data, mask);
+       } else if(id == SIG_TOWNS_DMAC_WRAP_REG) {
+               dma_wrap_reg = data;
+               this->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, data, mask);
+       } else if(id == SIG_TOWNS_DMAC_ADDR_MASK) {
+               // From eFMR50 / memory.cpp / update_dma_addr_mask()
+               switch(dma_addr_reg & 3) {
+               case 0:
+                       dma_addr_mask = data;
+                       break;
+               case 1:
+                       if(!(dma_wrap_reg & 1) && (data == 0x000fffff)) {
+                               dma_addr_mask = 0x000fffff;
+                       } else {
+                               dma_addr_mask = 0x00ffffff;
+                       }
+                       break;
+               default:
+                       if(!(dma_wrap_reg & 1) && (data == 0x000fffff)) {
+                               dma_addr_mask = 0x000fffff;
+                       } else {
+                               dma_addr_mask = 0xffffffff;
+                       }
+                       break;
+               }
+       } else {
+               // Fallthrough.
+               UPD71071::write_signal(id, data, mask);
+       }
 }              
+
+
+void TOWNS_DMAC::write_via_debugger_data8(uint32_t addr, uint32_t data)
+{
+       d_mem->write_dma_data8(addr & dma_addr_mask, data);
+}
+
+uint32_t TOWNS_DMAC::read_via_debugger_data8(uint32_t addr)
+{
+       return d_mem->read_dma_data8(addr & dma_addr_mask);
+}
+
+void TOWNS_DMAC::write_via_debugger_data16(uint32_t addr, uint32_t data)
+{
+       d_mem->write_dma_data16(addr & dma_addr_mask, data);
+}
+
+uint32_t TOWNS_DMAC::read_via_debugger_data16(uint32_t addr)
+{
+       return d_mem->read_dma_data16(addr & dma_addr_mask);
+}
+
+// note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
+bool TOWNS_DMAC::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
+{
+       if(buffer == NULL) return false;
+       _TCHAR sbuf[4096] = {0};
+       if(UPD71071::get_debug_regs_info(sbuf, 4096)) {
+               my_stprintf_s(buffer, buffer_len,
+                                         _T("%s\n")
+                                         _T("ADDR_MASK=%08X ADDR_REG=%02X ADDR_WRAP=%02X\n")
+                                         , sbuf, dma_addr_mask, dma_addr_reg, dma_wrap_reg);
+               return true;
+       }
+       return false;
+}
+       
+#define STATE_VERSION  1
+       
+bool TOWNS_DMAC::process_state(FILEIO *state_fio, bool loading)
+{
+       if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+               return false;
+       }
+       if(!state_fio->StateCheckInt32(this_device_id)) {
+               return false;
+       }
+       if(!(UPD71071::process_state(state_fio, loading))) {
+               return false;
+       }
+       state_fio->StateValue(dma_addr_reg);
+       state_fio->StateValue(dma_wrap_reg);
+       state_fio->StateValue(dma_addr_mask);
+
+       return true;
+}
+}
index 1691bdf..c5f767c 100644 (file)
@@ -3,10 +3,19 @@
 #include "../vm.h"
 #include "../upd71071.h"
 
+// Using original signal using after 1 << 12.
+#define SIG_TOWNS_DMAC_ADDR_REG  4096
+#define SIG_TOWNS_DMAC_WRAP_REG  4100
+#define SIG_TOWNS_DMAC_ADDR_MASK 4104
+
 namespace FMTOWNS {
 class TOWNS_DMAC : public UPD71071
 {
 protected:
+       uint8_t dma_addr_reg;
+       uint8_t dma_wrap_reg;
+       uint32_t dma_addr_mask;
+       
        virtual void __FASTCALL do_dma_inc_dec_ptr_8bit(int c);
        virtual void __FASTCALL do_dma_inc_dec_ptr_16bit(int c);
 public:
@@ -18,13 +27,22 @@ public:
        // common functions
        virtual void initialize();
        virtual void reset();
+//     virtual void __FASTCALL do_dma();
+       
        virtual void __FASTCALL write_io8(uint32_t addr, uint32_t data);
        virtual uint32_t __FASTCALL read_io8(uint32_t addr);
-//     virtual void __FASTCALL write_signal(int id, uint32_t data, uint32_t mask);
-//     virtual uint32_t __FASTCALL read_signal(int id);
-//     virtual void __FASTCALL do_dma();
+       
+       virtual void __FASTCALL write_signal(int id, uint32_t data, uint32_t mask);
+       virtual uint32_t __FASTCALL read_signal(int id);
+       virtual bool process_state(FILEIO* state_fio, bool loading);
 
-//     virtual bool process_state(FILEIO* state_fio, bool loading);
+       // for debug
+       virtual void __FASTCALL write_via_debugger_data8(uint32_t addr, uint32_t data);
+       virtual uint32_t __FASTCALL read_via_debugger_data8(uint32_t addr);
+       virtual void __FASTCALL write_via_debugger_data16(uint32_t addr, uint32_t data);
+       virtual uint32_t __FASTCALL read_via_debugger_data16(uint32_t addr);
+       virtual bool get_debug_regs_info(_TCHAR *buffer, size_t buffer_len);
+       
 };
 
 }
index d1968f0..cc462d2 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "../../fileio.h"
 #include "./towns_memory.h"
+#include "./towns_dmac.h"
 #include "./towns_vram.h"
 #include "./towns_sprite.h"
 #include "./fontroms.h"
@@ -437,13 +438,6 @@ uint32_t TOWNS_MEMORY::read_dma_data8w(uint32_t addr, int* wait)
                }
                rd_table[bank].dev->read_memory_mapped_io8(addr);
 //             return rd_table[bank].dev->read_dma_data8w(addr, wait);
-       } else if(dma_is_vram) {
-               if(wait != NULL) {
-                       *wait = mem_wait_val;
-               }
-               if(d_vram != NULL) {
-                       return d_vram->read_memory_mapped_io8(addr);
-               }
        } else if(rd_table[bank].memory != NULL) {
                if(wait != NULL) {
                        *wait = mem_wait_val;
@@ -461,13 +455,6 @@ uint32_t TOWNS_MEMORY::read_dma_data16w(uint32_t addr, int* wait)
                        *wait = rd_table[bank].wait;
                }
                rd_table[bank].dev->read_memory_mapped_io16(addr);
-       } else if(dma_is_vram) {
-               if(wait != NULL) {
-                       *wait = mem_wait_val;
-               }
-               if(d_vram != NULL) {
-                       return d_vram->read_memory_mapped_io16(addr);
-               }
        } else if(rd_table[bank].memory != NULL) {
                if(wait != NULL) {
                        *wait = mem_wait_val;
@@ -490,13 +477,6 @@ void TOWNS_MEMORY::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
                }
                wr_table[bank].dev->write_memory_mapped_io8(addr, data);
                return;
-       } else if(dma_is_vram) {
-               if(wait != NULL) {
-                       *wait = mem_wait_val;
-               }
-               if(d_vram != NULL) {
-                       d_vram->write_memory_mapped_io8(addr, data);
-               }
        } else if(wr_table[bank].memory != NULL) {
                if(wait != NULL) {
                        *wait = mem_wait_val;
@@ -515,14 +495,6 @@ void TOWNS_MEMORY::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
                }
                wr_table[bank].dev->write_memory_mapped_io16(addr, data);
                return;
-       } else if(dma_is_vram) {
-               if(wait != NULL) {
-                       *wait = wr_table[bank].wait;
-               }
-               if(d_vram != NULL) {
-                       d_vram->write_memory_mapped_io16(addr, data);
-                       return;
-               }
        } else if(wr_table[bank].memory != NULL) {
                if(wait != NULL) {
                        *wait = mem_wait_val;
@@ -645,6 +617,16 @@ uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
        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 0x0030:
                val = (((machine_id & 0x1f) << 3) | (cpu_id & 7));
@@ -762,14 +744,22 @@ void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
                        }
                }
                if(d_cpu != NULL) {
-                       switch(data & 0x08) {
+//                     switch(data & 0x08) {
+                       switch(data & 0x30) { // From eFMR50
                        case 0x00:      // 20bit
-                               d_cpu->set_address_mask(0xffffffff);
+                               d_cpu->set_address_mask(0x000fffff);
+                               break;
+                       case 0x20:      // 24bit
+                               d_cpu->set_address_mask(0x00ffffff);
                                break;
                        default:        // 32bit
-                               d_cpu->set_address_mask(0x000fffff);
+                               d_cpu->set_address_mask(0xffffffff);
                                break;
                        }
+                       if(d_dmac != NULL) {
+                               uint32_t maskval = d_cpu->get_address_mask();
+                               d_dmac->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, maskval, 0xff);
+                       }
                }
                break;
        case 0x0022:
@@ -779,6 +769,15 @@ void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
                        }
                        emu->power_off();
                }
+               if(d_dmac != NULL) {
+                       d_dmac->write_signal(SIG_TOWNS_DMAC_ADDR_REG, data, 0xff);
+               }
+               // Power register
+               break;
+       case 0x0024:
+               if(d_dmac != NULL) {
+                       d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP_REG, data, 0xff);
+               }
                // Power register
                break;
        case 0x0032:
index be1232d..d2a2a16 100644 (file)
@@ -94,6 +94,7 @@ protected:
        DEVICE* d_romcard[2]; // 0xc0000000 - 0xc0ffffff / 0xc1000000 - 0xc1ffffff
        DEVICE* d_pcm;             // 0xc2200000 - 0xc2200fff 
        DEVICE* d_beep;
+       DEVICE* d_dmac;
        I386*   d_cpu;
        
        DEVICE* d_dictionary;
@@ -157,6 +158,7 @@ public:
                
                d_cpu = NULL;
                d_vram = NULL;
+               d_dmac = NULL;
                d_pcm = NULL;
                d_sprite = NULL;
                d_romcard[0] = d_romcard[1] = NULL;
@@ -298,6 +300,10 @@ public:
        {
                d_cpu = device;
        }
+       void set_context_dmac(DEVICE* device)
+       {
+               d_dmac = device;
+       }
        void set_context_vram(DEVICE* device)
        {
                d_vram = device;