From efe157cfcb22ae6c5484fa5c1632d9f81a1c1bb3 Mon Sep 17 00:00:00 2001 From: Sour Date: Fri, 9 Aug 2019 00:04:01 -0400 Subject: [PATCH] SA-1: Added variable bit length data support --- Core/Sa1.cpp | 48 +++++++++++++++++++++++++++++++++++++----------- Core/Sa1.h | 5 +++++ Core/Sa1Types.h | 7 ++++--- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/Core/Sa1.cpp b/Core/Sa1.cpp index a105bbf..4241e54 100644 --- a/Core/Sa1.cpp +++ b/Core/Sa1.cpp @@ -188,16 +188,21 @@ void Sa1::Sa1RegisterWrite(uint16_t addr, uint8_t value) case 0x2258: //VBD (Variable length bit processing) - _state.VariableLengthAutoIncrement = (value & 0x80) != 0; - _state.VariableLength = value & 0x0F; - if(value) { - LogDebug("Variable length"); + _state.VarLenAutoInc = (value & 0x80) != 0; + _state.VarLenBitCount = value == 0 ? 16 : (value & 0x0F); + + if(!_state.VarLenAutoInc) { + IncVarLenPosition(); } break; - case 0x2259: _state.VariableLengthAddress = (_state.VariableLengthAddress & 0xFFFF00) | value; break; //VDA (Variable length data address - Low) - case 0x225A: _state.VariableLengthAddress = (_state.VariableLengthAddress & 0xFF00FF) | (value << 8); break; //VDA (Variable length data address - Mid) - case 0x225B: _state.VariableLengthAddress = (_state.VariableLengthAddress & 0x00FFFF) | (value << 16); break; //VDA (Variable length data address - High) + case 0x2259: _state.VarLenAddress = (_state.VarLenAddress & 0xFFFF00) | value; break; //VDA (Variable length data address - Low) + case 0x225A: _state.VarLenAddress = (_state.VarLenAddress & 0xFF00FF) | (value << 8); break; //VDA (Variable length data address - Mid) + case 0x225B: + //VDA (Variable length data address - High) + _state.VarLenAddress = (_state.VarLenAddress & 0x00FFFF) | (value << 16); + _state.VarLenCurrentBit = 0; + break; } } @@ -347,8 +352,21 @@ uint8_t Sa1::Sa1RegisterRead(uint16_t addr) case 0x230B: return _state.MathOverflow; break; //OF (Arithmetic overflow flag) - case 0x230C: break; //VDP (Variable length data port - Low) - case 0x230D: break; //VDP (Variable length data port - High) + case 0x230C: { + //VDP (Variable length data port - Low) + uint32_t data = ReadSa1(_state.VarLenAddress) | (ReadSa1(_state.VarLenAddress + 1) << 8) | (ReadSa1(_state.VarLenAddress + 2) << 16); + return data >> _state.VarLenCurrentBit; + } + + case 0x230D: { + //VDP (Variable length data port - High) + uint32_t data = ReadSa1(_state.VarLenAddress) | (ReadSa1(_state.VarLenAddress + 1) << 8) | (ReadSa1(_state.VarLenAddress + 2) << 16); + uint8_t value = data >> (_state.VarLenCurrentBit + 8); + if(_state.VarLenAutoInc) { + IncVarLenPosition(); + } + return value; + } } LogDebug("[Debug] Read SA1 - missing register: $" + HexUtilities::ToHex(addr)); @@ -588,6 +606,13 @@ void Sa1::UpdateSaveRamMappings() } } +void Sa1::IncVarLenPosition() +{ + _state.VarLenCurrentBit += _state.VarLenBitCount; + _state.VarLenAddress += _state.VarLenCurrentBit >> 3; + _state.VarLenCurrentBit &= 0x07; +} + void Sa1::CalculateMathOpResult() { if((int)_state.MathOp & (int)Sa1MathOp::Sum) { @@ -754,13 +779,14 @@ void Sa1::Serialize(Serializer &s) _state.CpuIRamWriteProtect, _state.Sa1IRamWriteProtect, _state.DmaSrcAddr, _state.DmaDestAddr, _state.DmaSize, _state.DmaEnabled, _state.DmaPriority, _state.DmaCharConv, _state.DmaCharConvAuto, _state.DmaDestDevice, _state.DmaSrcDevice, _state.DmaRunning, _state.DmaIrqFlag, _state.HorizontalTimerEnabled, _state.VerticalTimerEnabled, _state.UseLinearTimer, _state.HTimer, _state.VTimer, _state.LinearTimerValue, _state.MathOp, _state.MultiplicandDividend, - _state.MultiplierDivisor, _state.MathOpResult, _state.MathOverflow, _state.VariableLengthAutoIncrement, _state.VariableLength, _state.VariableLengthAddress, + _state.MultiplierDivisor, _state.MathOpResult, _state.MathOverflow, _state.VarLenAutoInc, _state.VarLenBitCount, _state.VarLenAddress, _state.Banks[0], _state.Banks[1], _state.Banks[2], _state.Banks[3], _state.BitmapRegister1[0], _state.BitmapRegister1[1], _state.BitmapRegister1[2], _state.BitmapRegister1[3], _state.BitmapRegister1[4], _state.BitmapRegister1[5], _state.BitmapRegister1[6], _state.BitmapRegister1[7], _state.BitmapRegister2[0], _state.BitmapRegister2[1], _state.BitmapRegister2[2], _state.BitmapRegister2[3], _state.BitmapRegister2[4], _state.BitmapRegister2[5], _state.BitmapRegister2[6], _state.BitmapRegister2[7], - _state.CharConvDmaActive, _state.CharConvBpp, _state.CharConvFormat, _state.CharConvWidth, _state.CharConvCounter + _state.CharConvDmaActive, _state.CharConvBpp, _state.CharConvFormat, _state.CharConvWidth, _state.CharConvCounter, + _state.VarLenCurrentBit ); s.Stream(_lastAccessMemType, _openBus); diff --git a/Core/Sa1.h b/Core/Sa1.h index 7c34313..b5ec97d 100644 --- a/Core/Sa1.h +++ b/Core/Sa1.h @@ -10,6 +10,10 @@ class Sa1Cpu; class MemoryManager; class BaseCartridge; +//TODO: Implement write protection flags +//TODO: Bitmap projection at $6000 +//TODO: Timers + class Sa1 : public BaseCoprocessor { private: @@ -40,6 +44,7 @@ private: void UpdateVectorMappings(); void UpdateSaveRamMappings(); + void IncVarLenPosition(); void CalculateMathOpResult(); void RunCharConvertType2(); diff --git a/Core/Sa1Types.h b/Core/Sa1Types.h index 5f732fb..45469df 100644 --- a/Core/Sa1Types.h +++ b/Core/Sa1Types.h @@ -99,9 +99,10 @@ struct Sa1State uint64_t MathOpResult; uint8_t MathOverflow; - bool VariableLengthAutoIncrement; - uint8_t VariableLength; - uint32_t VariableLengthAddress; + bool VarLenAutoInc; + uint8_t VarLenBitCount; + uint32_t VarLenAddress; + uint8_t VarLenCurrentBit; uint8_t Banks[4]; };