]> localhost Git - WindEmu.git/commitdiff
add draft Osaris/ER4 emulation
authorAsh Wolf <ninji@wuffs.org>
Tue, 24 Dec 2019 23:34:02 +0000 (23:34 +0000)
committerAsh Wolf <ninji@wuffs.org>
Tue, 24 Dec 2019 23:34:02 +0000 (23:34 +0000)
17 files changed:
WindCore/WindCore.pro
WindCore/arm710.cpp [moved from WindCore/arm710t.cpp with 92% similarity]
WindCore/arm710.h [moved from WindCore/arm710t.h with 97% similarity]
WindCore/clps7111.cpp [new file with mode: 0644]
WindCore/clps7111.h [new file with mode: 0644]
WindCore/clps7111_defs.h [new file with mode: 0644]
WindCore/clps7600.cpp [new file with mode: 0644]
WindCore/clps7600.h [new file with mode: 0644]
WindCore/etna.cpp
WindCore/etna.h
WindCore/hardware.h [moved from WindCore/wind_hw.h with 86% similarity]
WindCore/wind_defs.cpp [moved from WindCore/wind.cpp with 96% similarity]
WindCore/wind_defs.h [moved from WindCore/wind.h with 71% similarity]
WindCore/windermere.cpp [moved from WindCore/emu.cpp with 91% similarity]
WindCore/windermere.h [moved from WindCore/emu.h with 94% similarity]
WindQt/mainwindow.cpp
WindQt/mainwindow.h

index b935136bcb4f8b93d52ab0c9c59504b5b7355792..5d131139e896d4d0c99184f2a4c97dbc799ff2e6 100644 (file)
@@ -23,20 +23,25 @@ DEFINES += QT_DEPRECATED_WARNINGS
 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
 
 SOURCES += \
-    arm710t.cpp \
+    arm710.cpp \
+    clps7111.cpp \
+    clps7600.cpp \
     etna.cpp \
-    wind.cpp \
     isa-arm.c \
     decoder.c \
     decoder-arm.c \
     arm.c \
-    emu.cpp
+    wind_defs.cpp \
+    windermere.cpp
 
 HEADERS += \
-    arm710t.h \
+    arm710.h \
+    clps7111.h \
+    clps7111_defs.h \
+    clps7600.h \
     etna.h \
-    wind_hw.h \
-    wind.h \
+    hardware.h \
+    wind_defs.h \
     macros.h \
     isa-inlines.h \
     isa-arm.h \
@@ -46,7 +51,7 @@ HEADERS += \
     decoder-inlines.h \
     common.h \
     arm.h \
-    emu.h
+    windermere.h
 unix {
     target.path = /usr/lib
     INSTALLS += target
similarity index 92%
rename from WindCore/arm710t.cpp
rename to WindCore/arm710.cpp
index e344da3c888b41115f718461aea6ba4020c3a75a..bbb6401f16673aa04a87b55e8fec3058e271bd4c 100644 (file)
@@ -1,4 +1,4 @@
-#include "arm710t.h"
+#include "arm710.h"
 #include "common.h"
 
 // this will need changing if this code ever compiles on big-endian procs
@@ -10,7 +10,7 @@ inline void write32LE(uint8_t *p, uint32_t v) {
 }
 
 
-void ARM710T::switchBank(BankIndex newBank) {
+void ARM710::switchBank(BankIndex newBank) {
        if (newBank != bank) {
                // R13 and R14 need saving/loading for all banks
                allModesBankedRegisters[bank][0] = GPRs[13];
@@ -34,7 +34,7 @@ void ARM710T::switchBank(BankIndex newBank) {
 }
 
 
-void ARM710T::switchMode(Mode newMode) {
+void ARM710::switchMode(Mode newMode) {
        auto oldMode = currentMode();
        if (newMode != oldMode) {
 //             log("Switching mode! %x", newMode);
@@ -45,7 +45,7 @@ void ARM710T::switchMode(Mode newMode) {
        }
 }
 
-void ARM710T::raiseException(Mode mode, uint32_t savedPC, uint32_t newPC) {
+void ARM710::raiseException(Mode mode, uint32_t savedPC, uint32_t newPC) {
        auto bankIndex = modeToBank[mode & 0xF];
 //     log("Raising exception mode %x, saving PC %08x, CPSR %08x", mode, savedPC, CPSR);
        SPSRs[bankIndex] = CPSR;
@@ -57,19 +57,19 @@ void ARM710T::raiseException(Mode mode, uint32_t savedPC, uint32_t newPC) {
        GPRs[15] = newPC;
 }
 
-void ARM710T::requestFIQ() {
+void ARM710::requestFIQ() {
        raiseException(FIQ32, getRealPC() + 4, 0x1C);
        CPSR |= CPSR_FIQDisable;
        CPSR |= CPSR_IRQDisable;
 }
 
-void ARM710T::requestIRQ() {
+void ARM710::requestIRQ() {
 //     log("Requesting IRQ: Last exec = %08x, setting LR = %08x", lastPcExecuted(), getRealPC() + 4);
        raiseException(IRQ32, getRealPC() + 4, 0x18);
        CPSR |= CPSR_IRQDisable;
 }
 
-void ARM710T::reset() {
+void ARM710::reset() {
 #ifdef ARM710T_CACHE
        clearCache();
 #endif
@@ -78,7 +78,7 @@ void ARM710T::reset() {
 
 
 
-uint32_t ARM710T::tick() {
+uint32_t ARM710::tick() {
        // pop an instruction off the end of the pipeline
        bool haveInsn = false;
        uint32_t insn;
@@ -138,7 +138,7 @@ static inline bool extract1(uint32_t value, uint32_t bit) {
 }
 
 
-uint32_t ARM710T::executeInstruction(uint32_t i) {
+uint32_t ARM710::executeInstruction(uint32_t i) {
        uint32_t cycles = 1;
 //     log("executing insn %08x @ %08x", i, GPRs[15] - 0xC);
 
@@ -169,7 +169,7 @@ uint32_t ARM710T::executeInstruction(uint32_t i) {
        return cycles;
 }
 
-uint32_t ARM710T::execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t Rn, uint32_t Rd, uint32_t Operand2)
+uint32_t ARM710::execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t Rn, uint32_t Rd, uint32_t Operand2)
 {
        uint32_t cycles = 0; // TODO increment me semi-accurately
        bool shifterCarryOutput;
@@ -381,7 +381,7 @@ uint32_t ARM710T::execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t R
        return cycles;
 }
 
-uint32_t ARM710T::execMultiply(uint32_t AS, uint32_t Rd, uint32_t Rn, uint32_t Rs, uint32_t Rm)
+uint32_t ARM710::execMultiply(uint32_t AS, uint32_t Rd, uint32_t Rn, uint32_t Rs, uint32_t Rm)
 {
        // no need for R15 fuckery
        // datasheet says it's not allowed here
@@ -399,7 +399,7 @@ uint32_t ARM710T::execMultiply(uint32_t AS, uint32_t Rd, uint32_t Rn, uint32_t R
        return 0;
 }
 
-uint32_t ARM710T::execSingleDataSwap(bool B, uint32_t Rn, uint32_t Rd, uint32_t Rm)
+uint32_t ARM710::execSingleDataSwap(bool B, uint32_t Rn, uint32_t Rd, uint32_t Rm)
 {
        auto valueSize = B ? V8 : V32;
        auto readResult = readVirtual(GPRs[Rn], valueSize);
@@ -417,7 +417,7 @@ uint32_t ARM710T::execSingleDataSwap(bool B, uint32_t Rn, uint32_t Rd, uint32_t
        return 1;
 }
 
-uint32_t ARM710T::execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn, uint32_t Rd, uint32_t offset)
+uint32_t ARM710::execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn, uint32_t Rd, uint32_t offset)
 {
        bool load = extract1(IPUBWL, 0);
        bool writeback = extract1(IPUBWL, 1);
@@ -501,7 +501,7 @@ uint32_t ARM710T::execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn, uint32_t
        return 2;
 }
 
-uint32_t ARM710T::execBlockDataTransfer(uint32_t PUSWL, uint32_t Rn, uint32_t registerList)
+uint32_t ARM710::execBlockDataTransfer(uint32_t PUSWL, uint32_t Rn, uint32_t registerList)
 {
        bool load = extract1(PUSWL, 0);
        bool store = !load;
@@ -586,7 +586,7 @@ uint32_t ARM710T::execBlockDataTransfer(uint32_t PUSWL, uint32_t Rn, uint32_t re
        return 0; // fixme
 }
 
-uint32_t ARM710T::execBranch(bool L, uint32_t offset)
+uint32_t ARM710::execBranch(bool L, uint32_t offset)
 {
        if (L)
                GPRs[14] = GPRs[15] - 8;
@@ -600,7 +600,7 @@ uint32_t ARM710T::execBranch(bool L, uint32_t offset)
        return 0;
 }
 
-uint32_t ARM710T::execCP15RegisterTransfer(uint32_t CPOpc, bool L, uint32_t CRn, uint32_t Rd, uint32_t CP, uint32_t CRm)
+uint32_t ARM710::execCP15RegisterTransfer(uint32_t CPOpc, bool L, uint32_t CRn, uint32_t Rd, uint32_t CP, uint32_t CRm)
 {
        (void)CP;
        (void)CRm;
@@ -630,16 +630,31 @@ uint32_t ARM710T::execCP15RegisterTransfer(uint32_t CPOpc, bool L, uint32_t CRn,
                case 1: cp15_control = what; log("setting cp15_control to %08x", what); break;
                case 2: cp15_translationTableBase = what; break;
                case 3: cp15_domainAccessControl = what; break;
-               case 5: cp15_faultStatus = what; break;
-               case 6: cp15_faultAddress = what; break;
+               case 5:
+                       if (isTVersion)
+                               cp15_faultStatus = what;
+                       else
+                               flushTlb();
+                       break;
+               case 6:
+                       if (isTVersion)
+                               cp15_faultAddress = what;
+                       else
+                               flushTlb(what);
+                       break;
+               case 7:
 #ifdef ARM710T_CACHE
-               case 7: clearCache(); log("cache cleared"); break;
+                       clearCache();
+                       log("cache cleared");
 #endif
+                       break;
                case 8: {
-                       if (CPOpc == 1)
-                               flushTlb(what);
-                       else
-                               flushTlb();
+                       if (isTVersion) {
+                               if (CPOpc == 1)
+                                       flushTlb(what);
+                               else
+                                       flushTlb();
+                       }
                        break;
                }
                }
@@ -735,7 +750,7 @@ bool ARM710T::writeCached(uint32_t value, uint32_t virtAddr, ValueSize valueSize
 #endif
 
 
-uint32_t ARM710T::physAddrFromTlbEntry(TlbEntry *tlbEntry, uint32_t virtAddr) {
+uint32_t ARM710::physAddrFromTlbEntry(TlbEntry *tlbEntry, uint32_t virtAddr) {
        if ((tlbEntry->lv2Entry & 3) == 2) {
                // Smøl page
                return (tlbEntry->lv2Entry & 0xFFFFF000) | (virtAddr & 0xFFF);
@@ -749,7 +764,7 @@ uint32_t ARM710T::physAddrFromTlbEntry(TlbEntry *tlbEntry, uint32_t virtAddr) {
 }
 
 
-MaybeU32 ARM710T::virtToPhys(uint32_t virtAddr) {
+MaybeU32 ARM710::virtToPhys(uint32_t virtAddr) {
        if (!isMMUEnabled())
                return virtAddr;
 
@@ -764,7 +779,7 @@ MaybeU32 ARM710T::virtToPhys(uint32_t virtAddr) {
 }
 
 
-MaybeU32 ARM710T::readVirtualDebug(uint32_t virtAddr, ValueSize valueSize) {
+MaybeU32 ARM710::readVirtualDebug(uint32_t virtAddr, ValueSize valueSize) {
        if (auto v = virtToPhys(virtAddr); v.has_value())
                return readPhysical(v.value(), valueSize);
        else
@@ -772,7 +787,7 @@ MaybeU32 ARM710T::readVirtualDebug(uint32_t virtAddr, ValueSize valueSize) {
 }
 
 
-pair<MaybeU32, ARM710T::MMUFault> ARM710T::readVirtual(uint32_t virtAddr, ValueSize valueSize) {
+pair<MaybeU32, ARM710::MMUFault> ARM710::readVirtual(uint32_t virtAddr, ValueSize valueSize) {
        if (isAlignmentFaultEnabled() && valueSize == V32 && virtAddr & 3)
                return make_pair(MaybeU32(), encodeFault(AlignmentFault, 0, virtAddr));
 
@@ -817,7 +832,7 @@ pair<MaybeU32, ARM710T::MMUFault> ARM710T::readVirtual(uint32_t virtAddr, ValueS
                return make_pair(result, encodeFaultSorP(SorPOtherBusError, isPage, domain, virtAddr));
 }
 
-ARM710T::MMUFault ARM710T::writeVirtual(uint32_t value, uint32_t virtAddr, ValueSize valueSize) {
+ARM710::MMUFault ARM710::writeVirtual(uint32_t value, uint32_t virtAddr, ValueSize valueSize) {
        if (isAlignmentFaultEnabled() && valueSize == V32 && virtAddr & 3)
                return encodeFault(AlignmentFault, 0, virtAddr);
 
@@ -854,11 +869,11 @@ ARM710T::MMUFault ARM710T::writeVirtual(uint32_t value, uint32_t virtAddr, Value
 
 
 // TLB
-void ARM710T::flushTlb() {
+void ARM710::flushTlb() {
        for (TlbEntry &e : tlb)
                e = {0, 0, 0, 0};
 }
-void ARM710T::flushTlb(uint32_t virtAddr) {
+void ARM710::flushTlb(uint32_t virtAddr) {
        for (TlbEntry &e : tlb) {
                if (e.addrMask && (virtAddr & e.addrMask) == e.addr) {
                        e = {0, 0, 0, 0};
@@ -867,7 +882,7 @@ void ARM710T::flushTlb(uint32_t virtAddr) {
        }
 }
 
-ARM710T::TlbEntry *ARM710T::_allocateTlbEntry(uint32_t addrMask, uint32_t addr) {
+ARM710::TlbEntry *ARM710::_allocateTlbEntry(uint32_t addrMask, uint32_t addr) {
        TlbEntry *entry = &tlb[nextTlbIndex];
        entry->addrMask = addrMask;
        entry->addr = addr & addrMask;
@@ -875,7 +890,7 @@ ARM710T::TlbEntry *ARM710T::_allocateTlbEntry(uint32_t addrMask, uint32_t addr)
        return entry;
 }
 
-variant<ARM710T::TlbEntry *, ARM710T::MMUFault> ARM710T::translateAddressUsingTlb(uint32_t virtAddr, TlbEntry *useMe) {
+variant<ARM710::TlbEntry *, ARM710::MMUFault> ARM710::translateAddressUsingTlb(uint32_t virtAddr, TlbEntry *useMe) {
        // first things first, do we have a matching entry in the TLB?
        for (TlbEntry &e : tlb) {
                if (e.addrMask && (virtAddr & e.addrMask) == e.addr)
@@ -942,7 +957,7 @@ variant<ARM710T::TlbEntry *, ARM710T::MMUFault> ARM710T::translateAddressUsingTl
 
 
 
-ARM710T::MMUFault ARM710T::checkAccessPermissions(ARM710T::TlbEntry *entry, uint32_t virtAddr, bool isWrite) const {
+ARM710::MMUFault ARM710::checkAccessPermissions(ARM710::TlbEntry *entry, uint32_t virtAddr, bool isWrite) const {
        int domain;
        int accessPerms;
        bool isPage;
@@ -1013,7 +1028,7 @@ ARM710T::MMUFault ARM710T::checkAccessPermissions(ARM710T::TlbEntry *entry, uint
 }
 
 
-void ARM710T::reportFault(MMUFault fault) {
+void ARM710::reportFault(MMUFault fault) {
        if (fault != NoFault) {
                if ((fault & 0xF) != NonMMUError) {
                        cp15_faultStatus = fault & (MMUFaultTypeMask | MMUFaultDomainMask);
@@ -1051,7 +1066,7 @@ void ARM710T::reportFault(MMUFault fault) {
 }
 
 
-void ARM710T::log(const char *format, ...) {
+void ARM710::log(const char *format, ...) {
        if (logger) {
                char buffer[1024];
 
@@ -1064,7 +1079,7 @@ void ARM710T::log(const char *format, ...) {
        }
 }
 
-void ARM710T::logPcHistory() {
+void ARM710::logPcHistory() {
        for (int i = 0; i < PcHistoryCount; i++) {
                pcHistoryIndex = (pcHistoryIndex + 1) % PcHistoryCount;
                log("%03d: %08x %08x", i, pcHistory[pcHistoryIndex].addr, pcHistory[pcHistoryIndex].insn);
similarity index 97%
rename from WindCore/arm710t.h
rename to WindCore/arm710.h
index 785287780886590283f17b6bea6735de49184f90..c8179c66ff3038b1fc062360949407e286405a6e 100644 (file)
@@ -21,7 +21,7 @@ using namespace std;
 
 typedef optional<uint32_t> MaybeU32;
 
-class ARM710T
+class ARM710
 {
 public:
        enum ValueSize { V8 = 0, V32 = 1 };
@@ -57,11 +57,12 @@ public:
 
 
 
-       ARM710T() {
-               cp15_id = 0x41807100;
+       ARM710(bool _isTVersion) {
+               isTVersion = _isTVersion;
+               cp15_id = _isTVersion ? 0x41807100 : 0x41047100;
                clearAllValues();
        }
-       virtual ~ARM710T() { }
+       virtual ~ARM710() { }
 
        void clearAllValues() {
                bank = MainBank;
@@ -104,8 +105,8 @@ public:
 
        pair<MaybeU32, MMUFault> readVirtual(uint32_t virtAddr, ValueSize valueSize);
        virtual MaybeU32 readPhysical(uint32_t physAddr, ValueSize valueSize) = 0;
-       MMUFault writeVirtual(uint32_t value, uint32_t virtAddr, ARM710T::ValueSize valueSize);
-       virtual bool writePhysical(uint32_t value, uint32_t physAddr, ARM710T::ValueSize valueSize) = 0;
+       MMUFault writeVirtual(uint32_t value, uint32_t virtAddr, ARM710::ValueSize valueSize);
+       virtual bool writePhysical(uint32_t value, uint32_t physAddr, ARM710::ValueSize valueSize) = 0;
 
        uint32_t getGPR(int index) const { return GPRs[index]; }
        uint32_t getCPSR() const { return CPSR; }
@@ -115,7 +116,7 @@ public:
 
        void setLogger(std::function<void(const char *)> newLogger) { logger = newLogger; }
        uint32_t lastPcExecuted() const { return pcHistory[(pcHistoryIndex - 1) % PcHistoryCount].addr; }
-protected:
+public:
        void log(const char *format, ...);
        void logPcHistory();
 private:
@@ -181,6 +182,8 @@ private:
        uint8_t  cp15_faultStatus;          // 5: read-only (writing has unrelated effects)
        uint32_t cp15_faultAddress;         // 6: read-only (writing has unrelated effects)
 
+       bool isTVersion;
+
        bool flagV() const { return CPSR & CPSR_V; }
        bool flagC() const { return CPSR & CPSR_C; }
        bool flagZ() const { return CPSR & CPSR_Z; }
diff --git a/WindCore/clps7111.cpp b/WindCore/clps7111.cpp
new file mode 100644 (file)
index 0000000..17f864d
--- /dev/null
@@ -0,0 +1,497 @@
+#include "clps7111.h"
+#include "clps7111_defs.h"
+#include "hardware.h"
+#include <time.h>
+#include "common.h"
+
+
+CLPS7111::CLPS7111() : ARM710(false), pcCardController(this) {
+}
+
+
+uint32_t CLPS7111::getRTC() {
+       return time(nullptr) - 946684800;
+}
+
+
+uint32_t CLPS7111::readReg8(uint32_t reg) {
+       if (reg == PADR) {
+               return readKeyboard();
+       } else if (reg == PBDR) {
+               return (portValues >> 16) & 0xFF;
+       } else if (reg == PDDR) {
+               return (portValues >> 8) & 0xFF;
+       } else if (reg == PEDR) {
+               return portValues & 0xFF;
+       } else if (reg == PADDR) {
+               return (portDirections >> 24) & 0xFF;
+       } else if (reg == PBDDR) {
+               return (portDirections >> 16) & 0xFF;
+       } else if (reg == PDDDR) {
+               return (portDirections >> 8) & 0xFF;
+       } else if (reg == PEDDR) {
+               return portDirections & 0xFF;
+       } else {
+               log("RegRead8 unknown:: pc=%08x lr=%08x reg=%03x", getRealPC(), getGPR(14), reg);
+               return 0xFF;
+       }
+}
+uint32_t CLPS7111::readReg32(uint32_t reg) {
+       if (reg == SYSCON1) {
+               uint32_t flg = 0;
+               if (tc1.config & Timer::PERIODIC) flg |= 0x10;
+               if (tc1.config & Timer::MODE_512KHZ) flg |= 0x20;
+               if (tc2.config & Timer::PERIODIC) flg |= 0x40;
+               if (tc2.config & Timer::MODE_512KHZ) flg |= 0x80;
+               flg |= (kScan & 0xF);
+               return flg;
+       } else if (reg == SYSFLG1) {
+               uint32_t flg = sysFlg1;
+               flg |= (rtcDiv << 16);
+               // maybe set more stuff?
+               return flg;
+       } else if (reg == INTSR1) {
+               return pendingInterrupts & 0xFFFF;
+       } else if (reg == INTMR1) {
+               return interruptMask & 0xFFFF;
+       } else if (reg == LCDCON) {
+               return lcdControl;
+       } else if (reg == TC1D) {
+               return tc1.value;
+       } else if (reg == TC2D) {
+               return tc2.value;
+       } else if (reg == RTCDR) {
+               return rtc;
+       } else if (reg == PALLSW) {
+               return lcdPalette & 0xFFFFFFFF;
+       } else if (reg == PALMSW) {
+               return lcdPalette >> 32;
+       } else if (reg == SYSCON2) {
+               return 0;
+       } else if (reg == SYSFLG2) {
+               return 0;
+       } else if (reg == INTSR2) {
+               return pendingInterrupts >> 16;
+       } else if (reg == INTMR2) {
+               return interruptMask >> 16;
+       } else {
+               log("RegRead32 unknown:: pc=%08x lr=%08x reg=%03x", getRealPC(), getGPR(14), reg);
+               return 0xFFFFFFFF;
+       }
+}
+
+void CLPS7111::writeReg8(uint32_t reg, uint8_t value) {
+       if (reg == PADR) {
+               uint32_t oldPorts = portValues;
+               portValues &= 0x00FFFFFF;
+               portValues |= (uint32_t)value << 24;
+               diffPorts(oldPorts, portValues);
+       } else if (reg == PBDR) {
+               uint32_t oldPorts = portValues;
+               portValues &= 0xFF00FFFF;
+               portValues |= (uint32_t)value << 16;
+//             if ((portValues & 0x10000) && !(oldPorts & 0x10000))
+//                     etna.setPromBit0High();
+//             else if (!(portValues & 0x10000) && (oldPorts & 0x10000))
+//                     etna.setPromBit0Low();
+//             if ((portValues & 0x20000) && !(oldPorts & 0x20000))
+//                     etna.setPromBit1High();
+               diffPorts(oldPorts, portValues);
+       } else if (reg == PDDR) {
+               uint32_t oldPorts = portValues;
+               portValues &= 0xFFFF00FF;
+               portValues |= (uint32_t)value << 8;
+               diffPorts(oldPorts, portValues);
+       } else if (reg == PEDR) {
+               uint32_t oldPorts = portValues;
+               portValues &= 0xFFFFFF00;
+               portValues |= (uint32_t)value;
+               diffPorts(oldPorts, portValues);
+       } else if (reg == PADDR) {
+               portDirections &= 0x00FFFFFF;
+               portDirections |= (uint32_t)value << 24;
+       } else if (reg == PBDDR) {
+               portDirections &= 0xFF00FFFF;
+               portDirections |= (uint32_t)value << 16;
+       } else if (reg == PDDDR) {
+               portDirections &= 0xFFFF00FF;
+               portDirections |= (uint32_t)value << 8;
+       } else if (reg == PEDDR) {
+               portDirections &= 0xFFFFFF00;
+               portDirections |= (uint32_t)value;
+       } else if (reg == FRBADDR) {
+               log("LCD: address write %08x", value << 28);
+               lcdAddress = value << 28;
+       } else {
+               log("RegWrite8 unknown:: pc=%08x reg=%03x value=%02x", getRealPC(), reg, value);
+       }
+}
+void CLPS7111::writeReg32(uint32_t reg, uint32_t value) {
+       if (reg == SYSCON1) {
+               kScan = value & 0xF;
+               tc1.config = Timer::ENABLED; // always on with PS-7111!
+               if (value & 0x10) tc1.config |= Timer::PERIODIC;
+               if (value & 0x20) tc1.config |= Timer::MODE_512KHZ;
+               tc2.config = Timer::ENABLED;
+               if (value & 0x40) tc2.config |= Timer::PERIODIC;
+               if (value & 0x80) tc2.config |= Timer::MODE_512KHZ;
+       } else if (reg == INTMR1) {
+               interruptMask &= 0xFFFF0000;;
+               interruptMask |= (value & 0xFFFF);
+       } else if (reg == LCDCON) {
+               log("LCD: ctl write %08x", value);
+               lcdControl = value;
+       } else if (reg == TC1D) {
+               tc1.load(value);
+       } else if (reg == TC2D) {
+               tc2.load(value);
+       } else if (reg == RTCDR) {
+               rtc = value;
+       } else if (reg == PALLSW) {
+               lcdPalette &= 0xFFFFFFFF00000000;
+               lcdPalette |= value;
+       } else if (reg == PALMSW) {
+               lcdPalette &= 0x00000000FFFFFFFF;
+               lcdPalette |= (uint64_t)value << 32;
+       } else if (reg == HALT) {
+               halted = true;
+       // BLEOI = 0x410,
+       // MCEOI = 0x414,
+       } else if (reg == TEOI) {
+               pendingInterrupts &= ~(1 << TINT);
+       // TEOI = 0x418,
+       // STFCLR = 0x41C,
+       // E2EOI = 0x420,
+       } else if (reg == TC1EOI) {
+               pendingInterrupts &= ~(1 << TC1OI);
+       } else if (reg == TC2EOI) {
+               pendingInterrupts &= ~(1 << TC2OI);
+       } else if (reg == SYSCON2) {
+               log("SysCon2 write: %08x", value);
+       } else if (reg == INTMR2) {
+               interruptMask &= 0xFFFF;
+               interruptMask |= (value << 16);
+       } else if (reg == KBDEOI) {
+               pendingInterrupts &= ~(1 << KBDINT);
+       } else {
+               log("RegWrite32 unknown:: pc=%08x reg=%03x value=%08x", getRealPC(), reg, value);
+       }
+}
+
+bool CLPS7111::isPhysAddressValid(uint32_t physAddress) const {
+       uint8_t region = (physAddress >> 24) & 0xF1;
+       switch (region) {
+       case 0: return true;
+       case 0x80: return (physAddress <= 0x80000FFF);
+       case 0xC0: return true;
+       default: return false;
+       }
+}
+
+
+MaybeU32 CLPS7111::readPhysical(uint32_t physAddr, ValueSize valueSize) {
+       uint8_t region = (physAddr >> 28);
+       if (valueSize == V8) {
+               if (region == 0)
+                       return ROM[physAddr & 0xFFFFFF];
+               else if (region == 1)
+                       return ROM2[physAddr & 0x3FFFF];
+               else if (region == 4)
+                       return pcCardController.read(physAddr & 0xFFFFFFF, V8);
+               else if (region == 8 && physAddr <= 0x80001FFF)
+                       return readReg8(physAddr & 0x1FFF);
+               else if (region == 0xC)
+                       return MemoryBlockC0[physAddr & MemoryBlockMask];
+               else if (region > 0xC)
+                       return 0xFF; // just throw accesses to unmapped RAM away
+       } else {
+               uint32_t result;
+               if (region == 0)
+                       LOAD_32LE(result, physAddr & 0xFFFFFF, ROM);
+               else if (region == 1)
+                       LOAD_32LE(result, physAddr & 0x3FFFF, ROM2);
+               else if (region == 4)
+                       result = pcCardController.read(physAddr & 0xFFFFFFF, V32);
+               else if (region == 8 && physAddr <= 0x80001FFF)
+                       result = readReg32(physAddr & 0x1FFF);
+               else if (region == 0xC)
+                       LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockC0);
+               else if (region > 0xC)
+                       return 0xFFFFFFFF; // just throw accesses to unmapped RAM away
+               else
+                       return {};
+               return result;
+       }
+
+       return {};
+}
+
+bool CLPS7111::writePhysical(uint32_t value, uint32_t physAddr, ValueSize valueSize) {
+       uint8_t region = (physAddr >> 28);
+       if (valueSize == V8) {
+               if (region == 0xC)
+                       MemoryBlockC0[physAddr & MemoryBlockMask] = (uint8_t)value;
+               else if (region > 0xC)
+                       return true; // just throw accesses to unmapped RAM away
+               else if (region == 4)
+                       pcCardController.write(value, physAddr & 0xFFFFFFF, V8);
+               else if (region == 8 && physAddr <= 0x80001FFF)
+                       writeReg8(physAddr & 0x1FFF, value);
+               else
+                       return false;
+       } else {
+               if (region == 0xC)
+                       STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockC0);
+               else if (region > 0xC)
+                       return true; // just throw accesses to unmapped RAM away
+               else if (region == 4)
+                       pcCardController.write(value, physAddr & 0xFFFFFFF, V32);
+               else if (region == 8 && physAddr <= 0x80001FFF)
+                       writeReg32(physAddr & 0x1FFF, value);
+               else
+                       return false;
+       }
+       return true;
+}
+
+
+
+void CLPS7111::configure() {
+       if (configured) return;
+       configured = true;
+
+       srand(1000);
+
+       memset(&tc1, 0, sizeof(tc1));
+       memset(&tc2, 0, sizeof(tc1));
+       tc1.clockSpeed = CLOCK_SPEED;
+       tc2.clockSpeed = CLOCK_SPEED;
+
+       nextTickAt = TICK_INTERVAL;
+       rtc = getRTC();
+
+       reset();
+}
+
+void CLPS7111::loadROM(const char *path) {
+       FILE *f = fopen(path, "rb");
+       fread(ROM, 1, sizeof(ROM), f);
+       fclose(f);
+}
+
+void CLPS7111::executeUntil(int64_t cycles) {
+       if (!configured)
+               configure();
+
+       while (!asleep && passedCycles < cycles) {
+               if (passedCycles >= nextTickAt) {
+                       // increment RTCDIV
+                       if (rtcDiv == 0x3F) {
+                               rtc++;
+                               rtcDiv = 0;
+                       } else {
+                               rtcDiv++;
+                       }
+
+                       nextTickAt += TICK_INTERVAL;
+                       pendingInterrupts |= (1<<TINT);
+               }
+               if (tc1.tick(passedCycles))
+                       pendingInterrupts |= (1<<TC1OI);
+               if (tc2.tick(passedCycles))
+                       pendingInterrupts |= (1<<TC2OI);
+
+               if ((pendingInterrupts & interruptMask & FIQ_INTERRUPTS) != 0 && canAcceptFIQ()) {
+                       requestFIQ();
+                       halted = false;
+               }
+               if ((pendingInterrupts & interruptMask & IRQ_INTERRUPTS) != 0 && canAcceptIRQ()) {
+                       requestIRQ();
+                       halted = false;
+               }
+
+               // what's running?
+               if (halted) {
+                       // keep the clock moving
+                       passedCycles++;
+               } else {
+                       if (auto v = virtToPhys(getGPR(15) - 0xC); v.has_value() && instructionReady())
+                               debugPC(v.value());
+                       passedCycles += tick();
+
+                       uint32_t new_pc = getGPR(15) - 0xC;
+                       if (_breakpoints.find(new_pc) != _breakpoints.end()) {
+                               log("⚠️ Breakpoint triggered at %08x!", new_pc);
+                               return;
+                       }
+                       if (new_pc >= 0x80000000 && new_pc <= 0x90000000) {
+                               log("BAD PC %08x!!", new_pc);
+                               logPcHistory();
+                               return;
+                       }
+               }
+       }
+}
+
+void CLPS7111::dumpRAM(const char *path) {
+       FILE *f = fopen(path, "wb");
+       fwrite(MemoryBlockC0, 1, sizeof(MemoryBlockC0), f);
+       fclose(f);
+}
+
+
+
+void CLPS7111::printRegs() {
+       printf("R00:%08x R01:%08x R02:%08x R03:%08x\n", getGPR(0), getGPR(1), getGPR(2), getGPR(3));
+       printf("R04:%08x R05:%08x R06:%08x R07:%08x\n", getGPR(4), getGPR(5), getGPR(6), getGPR(7));
+       printf("R08:%08x R09:%08x R10:%08x R11:%08x\n", getGPR(8), getGPR(9), getGPR(10), getGPR(11));
+       printf("R12:%08x R13:%08x R14:%08x R15:%08x\n", getGPR(12), getGPR(13), getGPR(14), getGPR(15));
+//    printf("cpsr=%08x spsr=%08x\n", cpu.cpsr.packed, cpu.spsr.packed);
+}
+
+const char *CLPS7111::identifyObjectCon(uint32_t ptr) {
+       if (ptr == readVirtualDebug(0x80000880, V32).value()) return "process";
+       if (ptr == readVirtualDebug(0x80000884, V32).value()) return "thread";
+       if (ptr == readVirtualDebug(0x80000888, V32).value()) return "chunk";
+//     if (ptr == readVirtualDebug(0x8000088C, V32).value()) return "semaphore";
+//     if (ptr == readVirtualDebug(0x80000890, V32).value()) return "mutex";
+       if (ptr == readVirtualDebug(0x80000894, V32).value()) return "logicaldevice";
+       if (ptr == readVirtualDebug(0x80000898, V32).value()) return "physicaldevice";
+       if (ptr == readVirtualDebug(0x8000089C, V32).value()) return "channel";
+       if (ptr == readVirtualDebug(0x800008A0, V32).value()) return "server";
+//     if (ptr == readVirtualDebug(0x800008A4, V32).value()) return "unk8A4"; // name always null
+       if (ptr == readVirtualDebug(0x800008AC, V32).value()) return "library";
+//     if (ptr == readVirtualDebug(0x800008B0, V32).value()) return "unk8B0"; // name always null
+//     if (ptr == readVirtualDebug(0x800008B4, V32).value()) return "unk8B4"; // name always null
+       return "???";
+}
+
+void CLPS7111::fetchStr(uint32_t str, char *buf) {
+       if (str == 0) {
+               strcpy(buf, "<NULL>");
+               return;
+       }
+       int size = readVirtualDebug(str, V32).value();
+       for (int i = 0; i < size; i++) {
+               buf[i] = readVirtualDebug(str + 4 + i, V8).value();
+       }
+       buf[size] = 0;
+}
+
+void CLPS7111::fetchName(uint32_t obj, char *buf) {
+       fetchStr(readVirtualDebug(obj + 0x10, V32).value(), buf);
+}
+
+void CLPS7111::fetchProcessFilename(uint32_t obj, char *buf) {
+       fetchStr(readVirtualDebug(obj + 0x3C, V32).value(), buf);
+}
+
+void CLPS7111::debugPC(uint32_t pc) {
+       char objName[1000];
+       if (pc == 0x32304) {
+               // CObjectCon::AddL()
+               uint32_t container = getGPR(0);
+               uint32_t obj = getGPR(1);
+               const char *wut = identifyObjectCon(container);
+               if (wut) {
+                       fetchName(obj, objName);
+                       if (strcmp(wut, "process") == 0) {
+                               char procName[1000];
+                               fetchProcessFilename(obj, procName);
+                               log("OBJS: added %s at %08x <%s> <%s>", wut, obj, objName, procName);
+                       } else {
+                               log("OBJS: added %s at %08x <%s>", wut, obj, objName);
+                       }
+               }
+       }
+
+       if (pc == 0x634) {
+               uint32_t virtAddr = getGPR(0);
+               uint32_t physAddr = getGPR(1);
+               uint32_t btIndex = getGPR(2);
+               uint32_t regionSize = getGPR(3);
+               log("KERNEL MMU SECTION: v:%08x p:%08x size:%08x idx:%02x",
+                       virtAddr, physAddr, regionSize, btIndex);
+       }
+       if (pc == 0x66C) {
+               uint32_t virtAddr = getGPR(0);
+               uint32_t physAddr = getGPR(1);
+               uint32_t btIndex = getGPR(2);
+               uint32_t regionSize = getGPR(3);
+               uint32_t pageTableA = getGPR(4);
+               uint32_t pageTableB = getGPR(5);
+               log("KERNEL MMU PAGES: v:%08x p:%08x size:%08x idx:%02x tableA:%08x tableB:%08x",
+                       virtAddr, physAddr, regionSize, btIndex, pageTableA, pageTableB);
+       }
+       if (pc == 0x15070) {
+               uint32_t virtAddr = getGPR(0);
+               uint32_t physAddr = getGPR(1);
+               uint32_t regionSize = getGPR(2);
+               uint32_t a = getGPR(3);
+               log("DPlatChunkHw MAPPING: v:%08x p:%08x size:%08x arg:%08x",
+                       virtAddr, physAddr, regionSize, a);
+       }
+//     if (pc == 0x3B250) {
+//             log("DBG 5003B250: pc=%08x lr=%08x sp=%08x", getRealPC(), getGPR(14), getGPR(13));
+//     }
+}
+
+
+const uint8_t *CLPS7111::getLCDBuffer() const {
+       if ((lcdAddress >> 24) == 0xC0)
+               return &MemoryBlockC0[lcdAddress & MemoryBlockMask];
+       else
+               return nullptr;
+}
+
+
+uint8_t CLPS7111::readKeyboard() {
+       uint8_t val = 0;
+       if (kScan & 8) {
+               // Select one keyboard
+               int whichColumn = kScan & 7;
+               for (int i = 0; i < 7; i++)
+                       if (keyboardKeys[whichColumn * 7 + i])
+                               val |= (1 << i);
+       } else if (kScan == 0) {
+               // Report all columns combined
+               // EPOC's keyboard driver relies on this...
+               for (int i = 0; i < 8*7; i++)
+                       if (keyboardKeys[i])
+                               val |= (1 << (i % 7));
+       }
+       return val;
+}
+
+
+
+void CLPS7111::diffPorts(uint32_t oldval, uint32_t newval) {
+       uint32_t changes = oldval ^ newval;
+       if (changes & 1) log("PRT E0: %d", newval&1);
+       if (changes & 2) log("PRT E1: %d", newval&2);
+       if (changes & 4) log("PRT E2: %d", newval&4);
+       if (changes & 0x100) log("PRT D0: %d", newval&0x100);
+       if (changes & 0x200) log("PRT D1: %d", newval&0x200);
+       if (changes & 0x400) log("PRT D2: %d", newval&0x400);
+       if (changes & 0x800) log("PRT D3: %d", newval&0x800);
+       if (changes & 0x1000) log("PRT D4: %d", newval&0x1000);
+       if (changes & 0x2000) log("PRT D5: %d", newval&0x2000);
+       if (changes & 0x4000) log("PRT D6: %d", newval&0x4000);
+       if (changes & 0x8000) log("PRT D7: %d", newval&0x8000);
+       if (changes & 0x10000) log("PRT B0: %d", newval&0x10000);
+       if (changes & 0x20000) log("PRT B1: %d", newval&0x20000);
+       if (changes & 0x40000) log("PRT B2: %d", newval&0x40000);
+       if (changes & 0x80000) log("PRT B3: %d", newval&0x80000);
+       if (changes & 0x100000) log("PRT B4: %d", newval&0x100000);
+       if (changes & 0x200000) log("PRT B5: %d", newval&0x200000);
+       if (changes & 0x400000) log("PRT B6: %d", newval&0x400000);
+       if (changes & 0x800000) log("PRT B7: %d", newval&0x800000);
+       if (changes & 0x1000000) log("PRT A0: %d", newval&0x1000000);
+       if (changes & 0x2000000) log("PRT A1: %d", newval&0x2000000);
+       if (changes & 0x4000000) log("PRT A2: %d", newval&0x4000000);
+       if (changes & 0x8000000) log("PRT A3: %d", newval&0x8000000);
+       if (changes & 0x10000000) log("PRT A4: %d", newval&0x10000000);
+       if (changes & 0x20000000) log("PRT A5: %d", newval&0x20000000);
+       if (changes & 0x40000000) log("PRT A6: %d", newval&0x40000000);
+       if (changes & 0x80000000) log("PRT A7: %d", newval&0x80000000);
+}
diff --git a/WindCore/clps7111.h b/WindCore/clps7111.h
new file mode 100644 (file)
index 0000000..3ab514a
--- /dev/null
@@ -0,0 +1,76 @@
+#pragma once
+#include "arm710.h"
+#include "clps7111_defs.h"
+#include "clps7600.h"
+#include "hardware.h"
+#include "etna.h"
+#include <unordered_set>
+
+class CLPS7111 : public ARM710 {
+public:
+       uint8_t ROM[0x800000];
+       uint8_t ROM2[0x40000];
+       uint8_t MemoryBlockC0[0x400000];
+       enum { MemoryBlockMask = 0x3FFFFF };
+
+private:
+       uint16_t pendingInterrupts = 0;
+       uint16_t interruptMask = 0;
+       uint32_t portValues = 0;
+       uint32_t portDirections = 0;
+       uint32_t sysFlg1 = 0x20008000; // constant CL-PS7111 flag and cold start flag
+       uint32_t lcdControl = 0;
+       uint32_t lcdAddress = 0xC0000000;
+       uint32_t kScan = 0;
+       uint32_t rtc = 0;
+       uint32_t rtcDiv = 0;
+       uint64_t lcdPalette = 0;
+
+       int64_t passedCycles = 0;
+       int64_t nextTickAt = 0;
+       Timer tc1, tc2;
+       CLPS7600 pcCardController;
+       bool halted = false, asleep = false;
+
+       std::unordered_set<uint32_t> _breakpoints;
+
+       uint32_t getRTC();
+
+       uint32_t readReg8(uint32_t reg);
+       uint32_t readReg32(uint32_t reg);
+       void writeReg8(uint32_t reg, uint8_t value);
+       void writeReg32(uint32_t reg, uint32_t value);
+
+public:
+       bool isPhysAddressValid(uint32_t addr) const;
+       MaybeU32 readPhysical(uint32_t physAddr, ValueSize valueSize) override;
+       bool writePhysical(uint32_t value, uint32_t physAddr, ValueSize valueSize) override;
+
+       const uint8_t *getLCDBuffer() const;
+       uint64_t getLCDPalette() const { return lcdPalette; }
+       uint32_t getLCDControl() const { return lcdControl; }
+
+private:
+       bool configured = false;
+       void configure();
+
+       void printRegs();
+       const char *identifyObjectCon(uint32_t ptr);
+       void fetchStr(uint32_t str, char *buf);
+       void fetchName(uint32_t obj, char *buf);
+       void fetchProcessFilename(uint32_t obj, char *buf);
+       void debugPC(uint32_t pc);
+       void diffPorts(uint32_t oldval, uint32_t newval);
+
+       uint8_t readKeyboard();
+public:
+       bool keyboardKeys[8*7] = {0};
+
+public:
+       CLPS7111();
+       void loadROM(const char *path);
+       void dumpRAM(const char *path);
+       void executeUntil(int64_t cycles);
+       std::unordered_set<uint32_t> &breakpoints() { return _breakpoints; }
+       uint64_t currentCycles() const { return passedCycles; }
+};
diff --git a/WindCore/clps7111_defs.h b/WindCore/clps7111_defs.h
new file mode 100644 (file)
index 0000000..86db239
--- /dev/null
@@ -0,0 +1,81 @@
+#pragma once
+#include <stdint.h>
+
+enum {
+       CLOCK_SPEED = 0x4800*1000,
+       TICK_INTERVAL = CLOCK_SPEED / 64
+};
+
+enum Interrupt {
+       EXTFIQ = 0,   // FiqExternal
+       BLINT = 1,    // FiqBatLow
+       WEINT = 2,    // FiqWatchDog
+       MCINT = 3,    // FiqMediaChg
+       CSINT = 4,    // IrqCodec
+       EINT1 = 5,    // IrqExt1
+       EINT2 = 6,    // IrqExt2
+       EINT3 = 7,    // IrqExt3
+       TC1OI = 8,    // IrqTimer1
+       TC2OI = 9,    // IrqTimer2
+       RTCMI = 10,   // IrqRtcMatch
+       TINT = 11,    // IrqTick
+       UTXINT = 12,  // IrqUartTx?
+       URXINT1 = 13, // IrqUartRx?
+       UMSINT = 14,  // IrqUartModem?
+       SSEOTI = 15,  // IrqSpi
+       KBDINT = 16,  // IrqKeyPress?
+       UTXINT2 = 28, // IrqSpi2Tx?
+       URXINT2 = 29, // IrqSpi2Rx?
+       FIQ_INTERRUPTS = 0x000F,
+       IRQ_INTERRUPTS = 0xFFF0
+};
+
+enum Clps7111Reg {
+       PADR = 0,
+       PBDR = 1,
+       PDDR = 3,
+       PADDR = 0x40,
+       PBDDR = 0x41,
+       PDDDR = 0x43,
+       PEDR = 0x80,
+       PEDDR = 0xC0,
+       SYSCON1 = 0x100,
+       SYSFLG1 = 0x140,
+       MEMCFG1 = 0x180,
+       MEMCFG2 = 0x1C0,
+       DRFPR = 0x200,
+       INTSR1 = 0x240,
+       INTMR1 = 0x280,
+       LCDCON = 0x2C0,
+       TC1D = 0x300,
+       TC2D = 0x340,
+       RTCDR = 0x380,
+       RTCMR = 0x3C0,
+       PMPCON = 0x400,
+       CODR = 0x440,
+       UARTDR1 = 0x480,
+       UBRLCR1 = 0x4C0,
+       SYNCIO = 0x500,
+       PALLSW = 0x540,
+       PALMSW = 0x580,
+       STFCLR = 0x5C0,
+       BLEOI = 0x600,
+       MCEOI = 0x640,
+       TEOI = 0x680,
+       TC1EOI = 0x6C0,
+       TC2EOI = 0x700,
+       RTCEOI = 0x740,
+       UMSEOI = 0x780,
+       COEOI = 0x7C0,
+       HALT = 0x800,
+       STDBY = 0x840,
+       FRBADDR = 0x1000,
+       SYSCON2 = 0x1100,
+       SYSFLG2 = 0x1140,
+       INTSR2 = 0x1240,
+       INTMR2 = 0x1280,
+       UARTDR2 = 0x1480,
+       UBRLCR2 = 0x14C0,
+       KBDEOI = 0x1700
+};
+
diff --git a/WindCore/clps7600.cpp b/WindCore/clps7600.cpp
new file mode 100644 (file)
index 0000000..3b2d36a
--- /dev/null
@@ -0,0 +1,133 @@
+#include "clps7600.h"
+#include "arm710.h"
+
+CLPS7600::CLPS7600(ARM710 *_cpu)
+{
+       cpu = _cpu;
+}
+
+enum {
+       PCM_BVD1 = 1,
+       PCM_BVD2 = 2,
+       PCM_CD1 = 4,
+       PCM_CD2 = 8,
+       PCM_VS1 = 0x10,
+       PCM_VS2 = 0x20,
+       PDREQ_L = 0x40,
+       PCTL = 0x100,
+       PCM_WP = 0x200,
+       PCM_RDY = 0x400,
+       FIFOTHLD = 0x800,
+       IDLE = 0x1000,
+       WR_FAIL = 0x2000,
+       RD_FAIL = 0x4000,
+       RESERVED = 0x8000
+};
+
+uint32_t CLPS7600::getInputLevel() const {
+       uint32_t v = 0;
+
+       if (isMemoryMode())
+               v |= PCM_RDY; // we are ALWAYS ready
+
+       return v;
+}
+
+uint32_t CLPS7600::read(uint32_t addr, ARM710::ValueSize valueSize)
+{
+       cpu->log("CLPS7600 read: addr=%07x size=%d pc=%08x lr=%08x", addr, (valueSize == ARM710::V32) ? 32 : 8, cpu->getRealPC(), cpu->getGPR(14));
+       if (valueSize == ARM710::V32) {
+               switch (addr) {
+               case 0xC000000: // Interrupt Status
+                       return interruptStatus;
+               case 0xC000400: // Interrupt Mask
+                       return interruptMask;
+               case 0xC001C00: // Interrupt Input Level
+                       return getInputLevel();
+               case 0xC002000: // System Interface Configuration
+                       return systemInterfaceConfig;
+               case 0xC002400: // Card Interface Configuration
+                       return cardInterfaceConfig;
+               case 0xC002800: // Power Management
+                       return powerManagement;
+               case 0xC002C00: // Card Power Control
+                       return cardPowerControl;
+               case 0xC003000: // Card Interface Timing 0A
+                       return cardInterfaceTiming0A;
+               case 0xC003400: // Card Interface Timing 0B
+                       return cardInterfaceTiming0B;
+               case 0xC003800: // Card Interface Timing 1A
+                       return cardInterfaceTiming1A;
+               case 0xC003C00: // Card Interface Timing 1B
+                       return cardInterfaceTiming1B;
+               case 0xC004000: // DMA Control
+                       return dmaControl;
+               case 0xC004400: // Device Information
+                       return deviceInformation;
+               default:
+                       cpu->log("CLPS7600 unknown register read: addr=%07x pc=%08x lr=%08x", addr, cpu->getRealPC(), cpu->getGPR(14));
+                       return 0xFFFFFFFF;
+               }
+       }
+       cpu->log("unknown!!");
+       return 0xFF;
+}
+
+void CLPS7600::write(uint32_t value, uint32_t addr, ARM710::ValueSize valueSize)
+{
+       cpu->log("CLPS7600 write: addr=%07x size=%d value=%08x pc=%08x lr=%08x", addr, (valueSize == ARM710::V32) ? 32 : 8, value, cpu->getRealPC(), cpu->getGPR(14));
+       if (valueSize == ARM710::V32) {
+               switch (addr) {
+               case 0xC000400: // Interrupt Mask
+                       interruptMask = value;
+                       break;
+               case 0xC000800: // Interrupt Clear
+                       break;
+               case 0xC000C00: // Interrupt Output Select
+                       break;
+               case 0xC001000: // Interrupt Reserved Register 1
+                       break;
+               case 0xC001400: // Interrupt Reserved Register 2
+                       break;
+               case 0xC001800: // Interrupt Reserved Register 3
+                       break;
+               case 0xC002000: // System Interface Configuration
+                       systemInterfaceConfig = value;
+                       break;
+               case 0xC002400: // Card Interface Configuration
+                       cardInterfaceConfig = value;
+                       cpu->log("PC card enabled: %s", (value & 0x400) ? "yes" : "no");
+                       cpu->log("PC card write protect: %s", (value & 0x200) ? "yes" : "no");
+                       cpu->log("PC card mode: %s", (value & 0x100) ? "i/o" : "memory");
+                       break;
+               case 0xC002800: // Power Management
+                       powerManagement = value;
+                       break;
+               case 0xC002C00: // Card Power Control
+                       cardPowerControl = value;
+                       break;
+               case 0xC003000: // Card Interface Timing 0A
+                       cardInterfaceTiming0A = value;
+                       break;
+               case 0xC003400: // Card Interface Timing 0B
+                       cardInterfaceTiming0B = value;
+                       break;
+               case 0xC003800: // Card Interface Timing 1A
+                       cardInterfaceTiming1A = value;
+                       break;
+               case 0xC003C00: // Card Interface Timing 1B
+                       cardInterfaceTiming1B = value;
+                       break;
+               case 0xC004000: // DMA Control
+                       dmaControl = value;
+                       break;
+               case 0xC004400: // Device Information
+                       deviceInformation = value;
+                       break;
+               default:
+                       cpu->log("CLPS7600 unknown register write: addr=%07x value=%08x pc=%08x lr=%08x", addr, value, cpu->getRealPC(), cpu->getGPR(14));
+               }
+       } else {
+               cpu->log("unknown write!!");
+       }
+}
diff --git a/WindCore/clps7600.h b/WindCore/clps7600.h
new file mode 100644 (file)
index 0000000..e9fe2a9
--- /dev/null
@@ -0,0 +1,33 @@
+#pragma once
+#include <stdint.h>
+#include "arm710.h"
+
+class CLPS7600
+{
+private:
+       ARM710 *cpu;
+
+       uint32_t interruptStatus = 0;
+       uint32_t interruptMask = 0;
+       uint32_t systemInterfaceConfig = 0x1F8;
+       uint32_t cardInterfaceConfig = 0;
+       uint32_t powerManagement = 0;
+       uint32_t cardPowerControl = 0;
+       uint32_t cardInterfaceTiming0A = 0x1F00;
+       uint32_t cardInterfaceTiming0B = 0;
+       uint32_t cardInterfaceTiming1A = 0x1F00;
+       uint32_t cardInterfaceTiming1B = 0;
+       uint32_t dmaControl = 0;
+       uint32_t deviceInformation = 0x40;
+
+       bool isIOMode() const { return (cardInterfaceConfig & 0x100); }
+       bool isMemoryMode() const { return !(cardInterfaceConfig & 0x100); }
+       uint32_t getInputLevel() const;
+
+public:
+       CLPS7600(ARM710 *_cpu);
+
+       uint32_t read(uint32_t addr, ARM710::ValueSize valueSize);
+       void write(uint32_t value, uint32_t addr, ARM710::ValueSize valueSize);
+};
+
index 0356d52f5cd65ab763e40063579426bebdcd66c5..d79ca82f963530824735e625758e0bb2121c6af5 100644 (file)
@@ -1,5 +1,5 @@
 #include "etna.h"
-#include "emu.h"
+#include "arm710.h"
 #include <stdio.h>
 #include <string.h>
 
@@ -45,7 +45,7 @@ static const char *nameReg(uint32_t reg) {
 }
 
 
-Etna::Etna(Emu *owner) {
+Etna::Etna(ARM710 *owner) {
     this->owner = owner;
 
     for (int i = 0; i < 0x80; i++)
index ae63b022029c3a1c9a14a0fc847701d78c57415a..ef42e89d30d903ab314b0489bd36d83681454689 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 #include <stdint.h>
 
-class Emu;
+class ARM710;
 
 class Etna {
     uint8_t prom[0x80] = {};
@@ -12,10 +12,10 @@ class Etna {
     uint8_t pendingInterrupts = 0, interruptMask = 0;
     uint8_t wake1 = 0, wake2 = 0;
 
-    Emu *owner;
+       ARM710 *owner;
 
 public:
-    Etna(Emu *owner);
+       Etna(ARM710 *owner);
 
     uint32_t readReg8(uint32_t reg);
     uint32_t readReg32(uint32_t reg);
similarity index 86%
rename from WindCore/wind_hw.h
rename to WindCore/hardware.h
index 25ae4864c12cc2f8de7f525f5e7ae47afb60e3c7..c1857ae5632ee4979a1f19208a0c5967301ff011 100644 (file)
@@ -1,14 +1,11 @@
 #pragma once
-#include "wind.h"
-#include "arm710t.h"
+#include "arm710.h"
 #include <stdio.h>
 
 struct Timer {
-       ARM710T *cpu;
+       ARM710 *cpu;
 
        enum {
-               TICK_INTERVAL_SLOW = CLOCK_SPEED / 2000,
-               TICK_INTERVAL_FAST = CLOCK_SPEED / 512000,
                MODE_512KHZ = 1<<3,
                PERIODIC = 1<<6,
                ENABLED = 1<<7
@@ -17,9 +14,10 @@ struct Timer {
        uint8_t config;
        uint32_t interval;
        int32_t value;
+       int clockSpeed;
 
        int tickInterval() const {
-               return (config & MODE_512KHZ) ? TICK_INTERVAL_FAST : TICK_INTERVAL_SLOW;
+               return (config & MODE_512KHZ) ? (clockSpeed / 512000) : (clockSpeed / 2000);
        }
        void load(uint32_t lval) {
                interval = lval;
@@ -49,8 +47,33 @@ struct Timer {
        }
 };
 
+enum UartRegs {
+       UART0DATA = 0x600,
+       UART0FCR = 0x604,
+       UART0LCR = 0x608,
+       UART0CON = 0x60C,
+       UART0FLG = 0x610,
+       UART0INT = 0x614,
+       UART0INTM = 0x618,
+       UART0INTR = 0x61C,
+       UART0TEST1 = 0x620,
+       UART0TEST2 = 0x624,
+       UART0TEST3 = 0x628,
+       UART1DATA = 0x700,
+       UART1FCR = 0x704,
+       UART1LCR = 0x708,
+       UART1CON = 0x70C,
+       UART1FLG = 0x710,
+       UART1INT = 0x714,
+       UART1INTM = 0x718,
+       UART1INTR = 0x71C,
+       UART1TEST1 = 0x720,
+       UART1TEST2 = 0x724,
+       UART1TEST3 = 0x728,
+};
+
 struct UART {
-       ARM710T *cpu;
+       ARM710 *cpu;
 
        enum {
                IntRx = 1,
similarity index 96%
rename from WindCore/wind.cpp
rename to WindCore/wind_defs.cpp
index 851e4f23e57cbbf80dd2d14bc3df8d4db5f305b8..c6b56d2f2381982ab42e64c5a0a5639b58d1e9c3 100644 (file)
@@ -1,7 +1,7 @@
-#include "wind.h"
+#include "wind_defs.h"
 #include <stdio.h>
 
-void diffPorts(uint32_t oldval, uint32_t newval) {
+void windDiffPorts(uint32_t oldval, uint32_t newval) {
        uint32_t changes = oldval ^ newval;
        if (changes & 1) printf("PRT codec enable: %d\n", newval&1);
        if (changes & 2) printf("PRT audio amp enable: %d\n", newval&2);
@@ -37,7 +37,7 @@ void diffPorts(uint32_t oldval, uint32_t newval) {
        if (changes & 0x80000000) printf("PRT kb7: %d\n", newval&0x80000000);
 }
 
-void diffInterrupts(uint16_t oldval, uint16_t newval) {
+void windDiffInterrupts(uint16_t oldval, uint16_t newval) {
        uint16_t changes = oldval ^ newval;
        if (changes & 1) printf("INTCHG external=%d\n", newval & 1);
        if (changes & 2) printf("INTCHG lowbat=%d\n", newval & 2);
similarity index 71%
rename from WindCore/wind.h
rename to WindCore/wind_defs.h
index 593d87d46835eafe10c14d9aa31b7fd2caf45bbc..c616e5f3436ef8ea497d137a6f62e102d5b30961 100644 (file)
@@ -1,8 +1,10 @@
 #pragma once
 #include <stdint.h>
 
-const int CLOCK_SPEED = 0x9000*1000;
-const int TICK_INTERVAL = CLOCK_SPEED / 64;
+enum {
+       CLOCK_SPEED = 0x9000*1000,
+       TICK_INTERVAL = CLOCK_SPEED / 64
+};
 
 enum Interrupt {
        EXTFIQ = 0,  // FiqExternal
@@ -50,28 +52,6 @@ enum WindermereReg {
        INTENC = 0x50C,
        INTTEST1 = 0x514,
        INTTEST2 = 0x518,
-       UART0DATA = 0x600,
-       UART0FCR = 0x604,
-       UART0LCR = 0x608,
-       UART0CON = 0x60C,
-       UART0FLG = 0x610,
-       UART0INT = 0x614,
-       UART0INTM = 0x618,
-       UART0INTR = 0x61C,
-       UART0TEST1 = 0x620,
-       UART0TEST2 = 0x624,
-       UART0TEST3 = 0x628,
-       UART1DATA = 0x700,
-       UART1FCR = 0x704,
-       UART1LCR = 0x708,
-       UART1CON = 0x70C,
-       UART1FLG = 0x710,
-       UART1INT = 0x714,
-       UART1INTM = 0x718,
-       UART1INTR = 0x71C,
-       UART1TEST1 = 0x720,
-       UART1TEST2 = 0x724,
-       UART1TEST3 = 0x728,
        PUMPCON = 0x900,
        CODR = 0xA00,
        CONFG = 0xA04,
@@ -110,5 +90,5 @@ enum WindermereReg {
        LCDMUX = 0xE2C
 };
 
-void diffPorts(uint32_t oldval, uint32_t newval);
-void diffInterrupts(uint16_t oldval, uint16_t newval);
+void windDiffPorts(uint32_t oldval, uint32_t newval);
+void windDiffInterrupts(uint16_t oldval, uint16_t newval);
similarity index 91%
rename from WindCore/emu.cpp
rename to WindCore/windermere.cpp
index c607e923152da8f2dadeb6247a754ae9038f8e69..898598e3aeacedaa0a295ed6287a87489b32813b 100644 (file)
@@ -1,6 +1,6 @@
-#include "emu.h"
-#include "wind.h"
-#include "wind_hw.h"
+#include "windermere.h"
+#include "wind_defs.h"
+#include "hardware.h"
 #include <time.h>
 #include "common.h"
 
@@ -8,16 +8,16 @@
 //#define INCLUDE_D
 //#define INCLUDE_BANK1
 
-Emu::Emu() : etna(this) {
+Windermere::Windermere() : ARM710(true), etna(this) {
 }
 
 
-uint32_t Emu::getRTC() {
+uint32_t Windermere::getRTC() {
     return time(nullptr) - 946684800;
 }
 
 
-uint32_t Emu::readReg8(uint32_t reg) {
+uint32_t Windermere::readReg8(uint32_t reg) {
        if ((reg & 0xF00) == 0x600) {
                return uart1.readReg8(reg & 0xFF);
        } else if ((reg & 0xF00) == 0x700) {
@@ -47,7 +47,7 @@ uint32_t Emu::readReg8(uint32_t reg) {
                return 0xFF;
        }
 }
-uint32_t Emu::readReg32(uint32_t reg) {
+uint32_t Windermere::readReg32(uint32_t reg) {
        if (reg == LCDCTL) {
                printf("LCD control read pc=%08x lr=%08x !!!\n", getGPR(15), getGPR(14));
                return lcdControl;
@@ -92,7 +92,7 @@ uint32_t Emu::readReg32(uint32_t reg) {
        }
 }
 
-void Emu::writeReg8(uint32_t reg, uint8_t value) {
+void Windermere::writeReg8(uint32_t reg, uint8_t value) {
        if ((reg & 0xF00) == 0x600) {
                uart1.writeReg8(reg & 0xFF, value);
        } else if ((reg & 0xF00) == 0x700) {
@@ -105,7 +105,7 @@ void Emu::writeReg8(uint32_t reg, uint8_t value) {
                uint32_t oldPorts = portValues;
                portValues &= 0x00FFFFFF;
                portValues |= (uint32_t)value << 24;
-               diffPorts(oldPorts, portValues);
+               windDiffPorts(oldPorts, portValues);
        } else if (reg == PBDR) {
                uint32_t oldPorts = portValues;
                portValues &= 0xFF00FFFF;
@@ -116,17 +116,17 @@ void Emu::writeReg8(uint32_t reg, uint8_t value) {
                        etna.setPromBit0Low();
                if ((portValues & 0x20000) && !(oldPorts & 0x20000))
                        etna.setPromBit1High();
-               diffPorts(oldPorts, portValues);
+               windDiffPorts(oldPorts, portValues);
        } else if (reg == PCDR) {
                uint32_t oldPorts = portValues;
                portValues &= 0xFFFF00FF;
                portValues |= (uint32_t)value << 8;
-               diffPorts(oldPorts, portValues);
+               windDiffPorts(oldPorts, portValues);
        } else if (reg == PDDR) {
                uint32_t oldPorts = portValues;
                portValues &= 0xFFFFFF00;
                portValues |= (uint32_t)value;
-               diffPorts(oldPorts, portValues);
+               windDiffPorts(oldPorts, portValues);
        } else if (reg == PADDR) {
                portDirections &= 0x00FFFFFF;
                portDirections |= (uint32_t)value << 24;
@@ -145,7 +145,7 @@ void Emu::writeReg8(uint32_t reg, uint8_t value) {
 //             printf("RegWrite8 unknown:: pc=%08x reg=%03x value=%02x\n", getGPR(15)-4, reg, value);
        }
 }
-void Emu::writeReg32(uint32_t reg, uint32_t value) {
+void Windermere::writeReg32(uint32_t reg, uint32_t value) {
        if (reg == LCDCTL) {
                printf("LCD: ctl write %08x\n", value);
                lcdControl = value;
@@ -159,10 +159,10 @@ void Emu::writeReg32(uint32_t reg, uint32_t value) {
        } else if (reg == LCDT2) {
                printf("LCD: clocks write %08x\n", value);
        } else if (reg == INTENS) {
-//             diffInterrupts(interruptMask, interruptMask | value);
+//             windDiffInterrupts(interruptMask, interruptMask | value);
                interruptMask |= value;
        } else if (reg == INTENC) {
-//             diffInterrupts(interruptMask, interruptMask &~ value);
+//             windDiffInterrupts(interruptMask, interruptMask &~ value);
                interruptMask &= ~value;
        } else if (reg == HALT) {
                halted = true;
@@ -190,7 +190,7 @@ void Emu::writeReg32(uint32_t reg, uint32_t value) {
        }
 }
 
-bool Emu::isPhysAddressValid(uint32_t physAddress) const {
+bool Windermere::isPhysAddressValid(uint32_t physAddress) const {
        uint8_t region = (physAddress >> 24) & 0xF1;
        switch (region) {
        case 0: return true;
@@ -204,7 +204,7 @@ bool Emu::isPhysAddressValid(uint32_t physAddress) const {
 }
 
 
-MaybeU32 Emu::readPhysical(uint32_t physAddr, ValueSize valueSize) {
+MaybeU32 Windermere::readPhysical(uint32_t physAddr, ValueSize valueSize) {
        uint8_t region = (physAddr >> 24) & 0xF1;
        if (valueSize == V8) {
                if (region == 0)
@@ -273,7 +273,7 @@ MaybeU32 Emu::readPhysical(uint32_t physAddr, ValueSize valueSize) {
        return {};
 }
 
-bool Emu::writePhysical(uint32_t value, uint32_t physAddr, ValueSize valueSize) {
+bool Windermere::writePhysical(uint32_t value, uint32_t physAddr, ValueSize valueSize) {
        uint8_t region = (physAddr >> 24) & 0xF1;
        if (valueSize == V8) {
 #if defined(INCLUDE_BANK1)
@@ -336,7 +336,7 @@ bool Emu::writePhysical(uint32_t value, uint32_t physAddr, ValueSize valueSize)
 
 
 
-void Emu::configure() {
+void Windermere::configure() {
        if (configured) return;
        configured = true;
 
@@ -346,6 +346,8 @@ void Emu::configure() {
        uart2.cpu = this;
        memset(&tc1, 0, sizeof(tc1));
        memset(&tc2, 0, sizeof(tc1));
+       tc1.clockSpeed = CLOCK_SPEED;
+       tc2.clockSpeed = CLOCK_SPEED;
 
        nextTickAt = TICK_INTERVAL;
        rtc = getRTC();
@@ -353,13 +355,13 @@ void Emu::configure() {
        reset();
 }
 
-void Emu::loadROM(const char *path) {
+void Windermere::loadROM(const char *path) {
        FILE *f = fopen(path, "rb");
        fread(ROM, 1, sizeof(ROM), f);
        fclose(f);
 }
 
-void Emu::executeUntil(int64_t cycles) {
+void Windermere::executeUntil(int64_t cycles) {
        if (!configured)
                configure();
 
@@ -413,7 +415,7 @@ void Emu::executeUntil(int64_t cycles) {
        }
 }
 
-void Emu::dumpRAM(const char *path) {
+void Windermere::dumpRAM(const char *path) {
        FILE *f = fopen(path, "wb");
        fwrite(MemoryBlockC0, 1, sizeof(MemoryBlockC0), f);
        fwrite(MemoryBlockC1, 1, sizeof(MemoryBlockC1), f);
@@ -424,7 +426,7 @@ void Emu::dumpRAM(const char *path) {
 
 
 
-void Emu::printRegs() {
+void Windermere::printRegs() {
        printf("R00:%08x R01:%08x R02:%08x R03:%08x\n", getGPR(0), getGPR(1), getGPR(2), getGPR(3));
        printf("R04:%08x R05:%08x R06:%08x R07:%08x\n", getGPR(4), getGPR(5), getGPR(6), getGPR(7));
        printf("R08:%08x R09:%08x R10:%08x R11:%08x\n", getGPR(8), getGPR(9), getGPR(10), getGPR(11));
@@ -432,7 +434,7 @@ void Emu::printRegs() {
 //    printf("cpsr=%08x spsr=%08x\n", cpu.cpsr.packed, cpu.spsr.packed);
 }
 
-const char *Emu::identifyObjectCon(uint32_t ptr) {
+const char *Windermere::identifyObjectCon(uint32_t ptr) {
        if (ptr == readVirtualDebug(0x80000980, V32).value()) return "process";
        if (ptr == readVirtualDebug(0x80000984, V32).value()) return "thread";
        if (ptr == readVirtualDebug(0x80000988, V32).value()) return "chunk";
@@ -449,7 +451,7 @@ const char *Emu::identifyObjectCon(uint32_t ptr) {
        return NULL;
 }
 
-void Emu::fetchStr(uint32_t str, char *buf) {
+void Windermere::fetchStr(uint32_t str, char *buf) {
        if (str == 0) {
                strcpy(buf, "<NULL>");
                return;
@@ -461,15 +463,15 @@ void Emu::fetchStr(uint32_t str, char *buf) {
        buf[size] = 0;
 }
 
-void Emu::fetchName(uint32_t obj, char *buf) {
+void Windermere::fetchName(uint32_t obj, char *buf) {
        fetchStr(readVirtualDebug(obj + 0x10, V32).value(), buf);
 }
 
-void Emu::fetchProcessFilename(uint32_t obj, char *buf) {
+void Windermere::fetchProcessFilename(uint32_t obj, char *buf) {
        fetchStr(readVirtualDebug(obj + 0x3C, V32).value(), buf);
 }
 
-void Emu::debugPC(uint32_t pc) {
+void Windermere::debugPC(uint32_t pc) {
        char objName[1000];
        if (pc == 0x2CBC4) {
                // CObjectCon::AddL()
@@ -509,7 +511,7 @@ void Emu::debugPC(uint32_t pc) {
 }
 
 
-const uint8_t *Emu::getLCDBuffer() const {
+const uint8_t *Windermere::getLCDBuffer() const {
        if ((lcdAddress >> 24) == 0xC0)
                return &MemoryBlockC0[lcdAddress & MemoryBlockMask];
        else
@@ -517,7 +519,7 @@ const uint8_t *Emu::getLCDBuffer() const {
 }
 
 
-uint8_t Emu::readKeyboard() {
+uint8_t Windermere::readKeyboard() {
        uint8_t val = 0;
        if (kScan & 8) {
                // Select one keyboard
similarity index 94%
rename from WindCore/emu.h
rename to WindCore/windermere.h
index 17402c6425c7c480200d8a387841e5d535bcbba7..bcbe3201f05d9ac497dea99d7aafd9541547e143 100644 (file)
@@ -1,10 +1,11 @@
 #pragma once
-#include "arm710t.h"
-#include "wind_hw.h"
+#include "arm710.h"
+#include "wind_defs.h"
+#include "hardware.h"
 #include "etna.h"
 #include <unordered_set>
 
-class Emu : public ARM710T {
+class Windermere : public ARM710 {
 public:
     uint8_t ROM[0x1000000];
        uint8_t ROM2[0x40000];
@@ -64,7 +65,7 @@ public:
     bool keyboardKeys[8*7] = {0};
 
 public:
-    Emu();
+       Windermere();
     void loadROM(const char *path);
     void dumpRAM(const char *path);
        void executeUntil(int64_t cycles);
index b9c4fe31565a00da62ea235ce9e28936e66fe9f0..16085dfe771ce7dab1dde3d5fb5abac073cae381 100644 (file)
@@ -1,6 +1,6 @@
 #include "mainwindow.h"
 #include "ui_mainwindow.h"
-#include "../WindCore/wind.h"
+#include "../WindCore/clps7111_defs.h"
 #include <QTimer>
 #include <QKeyEvent>
 #include "../WindCore/decoder.h"
@@ -12,8 +12,8 @@ MainWindow::MainWindow(QWidget *parent) :
     ui->setupUi(this);
        ui->logView->setMaximumBlockCount(1000);
 
-    emu = new Emu;
-       emu->loadROM("/Users/ash/src/psion/Sys$rom.bin");
+       emu = new CLPS7111;
+       emu->loadROM("/Users/ash/src/psion/Osaris.bin");
        emu->setLogger([&](const char *str) {
                ui->logView->appendPlainText(str);
        });
@@ -91,7 +91,7 @@ void MainWindow::updateScreen()
         struct ARMInstructionInfo info;
         char buffer[512];
 
-               auto result = emu->readVirtual(addr, ARM710T::V32);
+               auto result = emu->readVirtual(addr, ARM710::V32);
                if (result.first.has_value()) {
                        uint32_t opcode = result.first.value();
                        ARMDecodeARM(opcode, &info);
@@ -104,9 +104,10 @@ void MainWindow::updateScreen()
     // now, the actual screen
     const uint8_t *lcdBuf = emu->getLCDBuffer();
     if (lcdBuf) {
-        QImage img(640, 240, QImage::Format_Grayscale8);
+#if 0
+               QImage img(640, 240, QImage::Format_Grayscale8);
 
-        // fetch palette
+               // fetch palette
         int bpp = 1 << (lcdBuf[1] >> 4);
         int ppb = 8 / bpp;
         uint16_t palette[16];
@@ -129,6 +130,37 @@ void MainWindow::updateScreen()
                                scanline[x] = palValue ^ 0xFF;
             }
         }
+#else
+               QImage img(320, 200, QImage::Format_Grayscale8);
+
+               uint32_t lcdControl = emu->getLCDControl();
+               uint64_t lcdPalette = emu->getLCDPalette();
+               int bpp = 1;
+               if (lcdControl & 0x40000000) bpp = 2;
+               if (lcdControl & 0x80000000) bpp = 4;
+               int ppb = 8 / bpp;
+
+               // build our image out
+               int lineWidth = (img.width() * bpp) / 8;
+               for (int y = 0; y < img.height(); y++) {
+                       uint8_t *scanline = img.scanLine(y);
+                       int lineOffs = lineWidth * y;
+                       for (int x = 0; x < img.width(); x++) {
+                               uint8_t byte = lcdBuf[lineOffs + (x / ppb)];
+                               int shift = (x & (ppb - 1)) * bpp;
+                               int mask = (1 << bpp) - 1;
+                               int palIdx = (byte >> shift) & mask;
+                               int palValue;
+                               if (bpp == 1)
+                                       palValue = palIdx * 255;
+                               else
+                                       palValue = (lcdPalette >> (palIdx * 4)) & 0xF;
+
+                               palValue |= (palValue << 4);
+                               scanline[x] = palValue ^ 0xFF;
+                       }
+               }
+#endif
 
         ui->screen->setPixmap(QPixmap::fromImage(std::move(img)));
     }
@@ -252,7 +284,7 @@ void MainWindow::on_stopButton_clicked()
 void MainWindow::on_stepTickButton_clicked()
 {
 //    emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED * 2));
-       emu->executeUntil(emu->currentCycles() + 2500000);
+       emu->executeUntil(emu->currentCycles() + 25000000);
        updateScreen();
 }
 
@@ -307,7 +339,7 @@ void MainWindow::updateMemory()
        uint8_t block[0x100];
        if (ok) {
                for (int i = 0; i < 0x100; i++) {
-                       block[i] = emu->readPhysical(physBase + i, ARM710T::V8).value();
+                       block[i] = emu->readPhysical(physBase + i, ARM710::V8).value();
                }
        }
 
@@ -358,7 +390,7 @@ void MainWindow::on_writeByteButton_clicked()
 {
        uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
        uint8_t value = (uint8_t)ui->memoryWriteValue->text().toUInt(nullptr, 16);
-       emu->writeVirtual(value, address, ARM710T::V8);
+       emu->writeVirtual(value, address, ARM710::V8);
        updateMemory();
 }
 
@@ -366,6 +398,6 @@ void MainWindow::on_writeDwordButton_clicked()
 {
        uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
        uint32_t value = ui->memoryWriteValue->text().toUInt(nullptr, 16);
-       emu->writeVirtual(value, address, ARM710T::V32);
+       emu->writeVirtual(value, address, ARM710::V32);
        updateMemory();
 }
index a127ade15d5450ff7eaacf74f93ff310127a4c5e..34071dfaef9ad434cdba9b65462fcb39b89f2299 100644 (file)
@@ -2,7 +2,7 @@
 #define MAINWINDOW_H
 
 #include <QMainWindow>
-#include "../WindCore/emu.h"
+#include "../WindCore/clps7111.h"
 
 namespace Ui {
 class MainWindow;
@@ -44,7 +44,7 @@ private slots:
 
 private:
     Ui::MainWindow *ui;
-    Emu *emu;
+       CLPS7111 *emu;
     QTimer *timer;
     void updateScreen();
     void updateBreakpointsList();