mirror of
https://github.com/libretro/Mu.git
synced 2026-09-23 15:15:43 +00:00
Add timer status lock logic
This commit is contained in:
@@ -333,6 +333,7 @@ uint32_t emulatorGetStateSize(){
|
||||
size += sizeof(uint64_t) * 4;//32.32 fixed point double, timerXCycleCounter and CPU cycle timers
|
||||
size += sizeof(int32_t);//pllWakeWait
|
||||
size += sizeof(uint32_t);//clk32Counter
|
||||
size += sizeof(uint16_t) * 2;//timerStatusReadAcknowledge
|
||||
size += sizeof(uint8_t) * 2;//ads7846
|
||||
size += sizeof(uint16_t);//ads7846
|
||||
size += sizeof(uint8_t) * 7;//palmMisc
|
||||
@@ -432,10 +433,14 @@ void emulatorSaveState(uint8_t* data){
|
||||
offset += sizeof(int32_t);
|
||||
writeStateValueUint32(data + offset, clk32Counter);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValueDouble(data + offset, timer1CycleCounter);
|
||||
writeStateValueDouble(data + offset, timerCycleCounter[0]);
|
||||
offset += sizeof(uint64_t);
|
||||
writeStateValueDouble(data + offset, timer2CycleCounter);
|
||||
writeStateValueDouble(data + offset, timerCycleCounter[1]);
|
||||
offset += sizeof(uint64_t);
|
||||
writeStateValueUint16(data + offset, timerStatusReadAcknowledge[0]);
|
||||
offset += sizeof(uint16_t);
|
||||
writeStateValueUint16(data + offset, timerStatusReadAcknowledge[1]);
|
||||
offset += sizeof(uint16_t);
|
||||
|
||||
//ADS7846
|
||||
writeStateValueUint8(data + offset, ads7846InputBitsLeft);
|
||||
@@ -553,10 +558,14 @@ void emulatorLoadState(uint8_t* data){
|
||||
offset += sizeof(int32_t);
|
||||
clk32Counter = readStateValueUint32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
timer1CycleCounter = readStateValueDouble(data + offset);
|
||||
timerCycleCounter[0] = readStateValueDouble(data + offset);
|
||||
offset += sizeof(uint64_t);
|
||||
timer2CycleCounter = readStateValueDouble(data + offset);
|
||||
timerCycleCounter[1] = readStateValueDouble(data + offset);
|
||||
offset += sizeof(uint64_t);
|
||||
timerStatusReadAcknowledge[0] = readStateValueUint16(data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
timerStatusReadAcknowledge[1] = readStateValueUint16(data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
|
||||
//ADS7846
|
||||
ads7846InputBitsLeft = readStateValueUint8(data + offset);
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
chip_t chips[CHIP_END];
|
||||
int32_t pllWakeWait;
|
||||
uint32_t clk32Counter;
|
||||
double timer1CycleCounter;
|
||||
double timer2CycleCounter;
|
||||
double timerCycleCounter[2];
|
||||
uint16_t timerStatusReadAcknowledge[2];
|
||||
|
||||
|
||||
bool pllIsOn();
|
||||
@@ -435,6 +435,14 @@ unsigned int getHwRegister16(unsigned int address){
|
||||
printUnknownHwAccess(address, 0, 16, false);
|
||||
#endif
|
||||
switch(address){
|
||||
|
||||
case TSTAT1:
|
||||
timerStatusReadAcknowledge[0] = registerArrayRead16(TSTAT1);//active bits acknowledged
|
||||
return registerArrayRead16(TSTAT1);
|
||||
|
||||
case TSTAT2:
|
||||
timerStatusReadAcknowledge[1] = registerArrayRead16(TSTAT2);//active bits acknowledged
|
||||
return registerArrayRead16(TSTAT2);
|
||||
|
||||
//32 bit registers accessed as 16 bit
|
||||
case IMR:
|
||||
@@ -466,8 +474,6 @@ unsigned int getHwRegister16(unsigned int address){
|
||||
case TCMP2:
|
||||
case TPRER1:
|
||||
case TPRER2:
|
||||
case TSTAT1:
|
||||
case TSTAT2:
|
||||
case SPICONT2:
|
||||
case SPIDATA2:
|
||||
//simple read, no actions needed
|
||||
@@ -819,12 +825,20 @@ void setHwRegister16(unsigned int address, unsigned int value){
|
||||
setSpiCont2(value);
|
||||
break;
|
||||
|
||||
case TSTAT1:
|
||||
//preserve any unread bits
|
||||
registerArrayWrite16(TSTAT1, (value & timerStatusReadAcknowledge[0]) | (registerArrayRead16(TSTAT1) & ~timerStatusReadAcknowledge[0]));
|
||||
break;
|
||||
|
||||
case TSTAT2:
|
||||
//preserve any unread bits
|
||||
registerArrayWrite16(TSTAT2, (value & timerStatusReadAcknowledge[1]) | (registerArrayRead16(TSTAT2) & ~timerStatusReadAcknowledge[1]));
|
||||
break;
|
||||
|
||||
case TCMP1:
|
||||
case TCMP2:
|
||||
case TPRER1:
|
||||
case TPRER2:
|
||||
case TSTAT1:
|
||||
case TSTAT2:
|
||||
case SPIDATA2:
|
||||
//simple write, no actions needed
|
||||
registerArrayWrite16(address, value);
|
||||
@@ -891,8 +905,10 @@ void resetHwRegisters(){
|
||||
memset(palmReg, 0x00, REG_SIZE - BOOTLOADER_SIZE);
|
||||
clk32Counter = 0;
|
||||
pllWakeWait = -1;
|
||||
timer1CycleCounter = 0.0;
|
||||
timer2CycleCounter = 0.0;
|
||||
timerCycleCounter[0] = 0.0;
|
||||
timerCycleCounter[1] = 0.0;
|
||||
timerStatusReadAcknowledge[0] = 0x0000;
|
||||
timerStatusReadAcknowledge[1] = 0x0000;
|
||||
for(uint8_t chip = CHIP_BEGIN; chip < CHIP_END; chip++){
|
||||
chips[chip].enable = false;
|
||||
chips[chip].start = 0x00000000;
|
||||
|
||||
@@ -58,8 +58,8 @@ typedef struct{
|
||||
extern chip_t chips[];
|
||||
extern int32_t pllWakeWait;
|
||||
extern uint32_t clk32Counter;
|
||||
extern double timer1CycleCounter;
|
||||
extern double timer2CycleCounter;
|
||||
extern double timerCycleCounter[];
|
||||
extern uint16_t timerStatusReadAcknowledge[];
|
||||
|
||||
//memory accessors
|
||||
unsigned int getHwRegister8(unsigned int address);
|
||||
|
||||
@@ -114,22 +114,22 @@ static inline void timer12Clk32(){
|
||||
|
||||
case 0x0001://SYSCLK / timer prescaler
|
||||
if(pllIsOn())
|
||||
timer1CycleCounter += sysclksPerClk32() / timer1Prescaler;
|
||||
timerCycleCounter[0] += sysclksPerClk32() / timer1Prescaler;
|
||||
break;
|
||||
|
||||
case 0x0002://SYSCLK / 16 / timer prescaler
|
||||
if(pllIsOn())
|
||||
timer1CycleCounter += sysclksPerClk32() / 16.0 / timer1Prescaler;
|
||||
timerCycleCounter[0] += sysclksPerClk32() / 16.0 / timer1Prescaler;
|
||||
break;
|
||||
|
||||
default://CLK32 / timer prescaler
|
||||
timer1CycleCounter += 1.0 / timer1Prescaler;
|
||||
timerCycleCounter[0] += 1.0 / timer1Prescaler;
|
||||
break;
|
||||
}
|
||||
|
||||
if(timer1CycleCounter >= 1.0){
|
||||
timer1Count += (uint16_t)timer1CycleCounter;
|
||||
timer1CycleCounter -= (uint16_t)timer1CycleCounter;
|
||||
if(timerCycleCounter[0] >= 1.0){
|
||||
timer1Count += (uint16_t)timerCycleCounter[0];
|
||||
timerCycleCounter[0] -= (uint16_t)timerCycleCounter[0];
|
||||
}
|
||||
|
||||
if(timer1OldCount < timer1Compare && timer1Count >= timer1Compare){
|
||||
@@ -141,6 +141,7 @@ static inline void timer12Clk32(){
|
||||
|
||||
//set timer triggered bit
|
||||
registerArrayWrite16(TSTAT1, registerArrayRead16(TSTAT1) | 0x0001);
|
||||
timerStatusReadAcknowledge[0] &= 0xFFFE;//lock bit until next read
|
||||
|
||||
if(!(timer1Control & 0x0100)){
|
||||
//not free running, reset to 0, to prevent loss of ticks after compare event just subtract timerXCompare
|
||||
@@ -163,22 +164,22 @@ static inline void timer12Clk32(){
|
||||
|
||||
case 0x0001://SYSCLK / timer prescaler
|
||||
if(pllIsOn())
|
||||
timer2CycleCounter += sysclksPerClk32() / timer2Prescaler;
|
||||
timerCycleCounter[1] += sysclksPerClk32() / timer2Prescaler;
|
||||
break;
|
||||
|
||||
case 0x0002://SYSCLK / 16 / timer prescaler
|
||||
if(pllIsOn())
|
||||
timer2CycleCounter += sysclksPerClk32() / 16.0 / timer2Prescaler;
|
||||
timerCycleCounter[1] += sysclksPerClk32() / 16.0 / timer2Prescaler;
|
||||
break;
|
||||
|
||||
default://CLK32 / timer prescaler
|
||||
timer2CycleCounter += 1.0 / timer2Prescaler;
|
||||
timerCycleCounter[1] += 1.0 / timer2Prescaler;
|
||||
break;
|
||||
}
|
||||
|
||||
if(timer2CycleCounter >= 1.0){
|
||||
timer2Count += (uint16_t)timer2CycleCounter;
|
||||
timer2CycleCounter -= (uint16_t)timer2CycleCounter;
|
||||
if(timerCycleCounter[1] >= 1.0){
|
||||
timer2Count += (uint16_t)timerCycleCounter[1];
|
||||
timerCycleCounter[1] -= (uint16_t)timerCycleCounter[1];
|
||||
}
|
||||
|
||||
if(timer2OldCount < timer2Compare && timer2Count >= timer2Compare){
|
||||
@@ -190,6 +191,7 @@ static inline void timer12Clk32(){
|
||||
|
||||
//set timer triggered bit
|
||||
registerArrayWrite16(TSTAT2, registerArrayRead16(TSTAT2) | 0x0001);
|
||||
timerStatusReadAcknowledge[1] &= 0xFFFE;//lock bit until next read
|
||||
|
||||
if(!(timer2Control & 0x0100)){
|
||||
//not free running, reset to 0, to prevent loss of ticks after compare event just subtract timerXCompare
|
||||
|
||||
@@ -21,7 +21,6 @@ interrupt control register (ICR), POL5 and edge trigger selects
|
||||
ADC7846 temperature sensors
|
||||
ADC7846 dock sensor
|
||||
some undocumented I/O might be on port e and port j
|
||||
timers shouldn't allow comp bits to be cleared until read with a 1 in them and should remain in interrupt state until they are cleared(this is unverified)
|
||||
|
||||
Debug tools:
|
||||
missing icons
|
||||
@@ -41,6 +40,7 @@ Had to modify musashi because the damn NDK isn't C compatible, m68kcpu.h, line 5
|
||||
|
||||
|
||||
Fixed:
|
||||
timers shouldn't allow comp bits to be cleared until read with a 1 in them and should remain in interrupt state until they are cleared(the interrupt state part is unverified)
|
||||
SED1376 byte and word swap bits
|
||||
qt play pause icon not working for emu control button
|
||||
SED1376 register access
|
||||
|
||||
Reference in New Issue
Block a user