mdec: hack: added MDECout chopped transfer support

Fixes Final Fantasy IX boot
This commit is contained in:
Jakub Czekański 2021-04-10 16:16:59 +02:00
parent 1dc4c8edba
commit 401fed3d02
6 changed files with 37 additions and 10 deletions

View file

@ -7,4 +7,6 @@ DMA1Channel::DMA1Channel(Channel channel, System* sys, mdec::MDEC* mdec) : DMACh
uint32_t DMA1Channel::readDevice() { return mdec->read(0); }
bool DMA1Channel::dataRequest() { return mdec->dataOutRequest(); }
bool DMA1Channel::hack_supportChoppedTransfer() const { return true; }
} // namespace device::dma

View file

@ -13,6 +13,7 @@ class DMA1Channel : public DMAChannel {
protected:
bool dataRequest() override;
bool hack_supportChoppedTransfer() const override;
public:
DMA1Channel(Channel channel, System* sys, mdec::MDEC* mdec);

View file

@ -94,6 +94,8 @@ void DMAChannel::syncBlockTransfer() {
canLog = false;
}
hack_transferLoop:
// TODO: DREQ DACK for MDEC
// TODO: Execute sync with chopping
if (control.direction == CHCR::Direction::toRam) {
@ -112,6 +114,9 @@ void DMAChannel::syncBlockTransfer() {
irqFlag = true;
control.enabled = CHCR::Enabled::completed;
}
if (!hack_supportChoppedTransfer() && count.syncMode1.blockCount > 0) {
goto hack_transferLoop;
}
}
void DMAChannel::linkedListTransfer() {

View file

@ -99,6 +99,7 @@ class DMAChannel {
// DACK/DREQ
virtual bool dataRequest() { return true; }
virtual bool hack_supportChoppedTransfer() const { return false; }
public:
bool irqFlag = false;

View file

@ -28,6 +28,9 @@ uint32_t MDEC::read(uint32_t address) {
// 2: b g r B
// 3: B G R <- cycle continues
if (output.empty() || outputPtr >= output.size()) {
return 0;
}
uint32_t data = 0;
if (status.colorDepth == Status::ColorDepth::bit_24) {
if (part == 0)
@ -55,15 +58,15 @@ uint32_t MDEC::read(uint32_t address) {
}
if (outputPtr >= output.size()) {
outputPtr = 0;
output.clear();
}
return data;
}
if (address >= 4 && address < 8) {
// TODO: Handle fifo bits
status.dataOutFifoEmpty = outputPtr >= output.size();
status.dataInFifoFull = 0;
status.commandBusy = 0;
status.dataOutFifoEmpty = output.empty();
status.dataInFifoFull = !input.empty();
status.commandBusy = !output.empty();
return status._reg;
}
@ -138,6 +141,7 @@ void MDEC::write(uint32_t address, uint32_t data) {
if (paramCount == 1) {
// TODO: Pass macroblock, not raw pointer
decodeMacroblocks();
input.clear();
}
break;
@ -182,11 +186,11 @@ void MDEC::write(uint32_t address, uint32_t data) {
return;
}
if (address >= 4 && address < 8) {
_control._reg = data;
control._reg = data;
if (_control.getBit(31)) reset();
status.dataInRequest = _control.getBit(28);
status.dataOutRequest = _control.getBit(27);
if (control.reset) reset();
status.dataInRequest = control.enableDataIn;
status.dataOutRequest = control.enableDataOut;
return;
}

View file

@ -41,12 +41,24 @@ class MDEC {
Status() : _reg(0) {}
};
union Control {
struct {
uint32_t : 29;
uint32_t enableDataOut : 1; // Enables DMA1 and DataOut Request status bit
uint32_t enableDataIn : 1; // Enables DMA0 and DataIn Request status bit
uint32_t reset : 1;
};
uint32_t _reg;
uint8_t _byte[4];
Control() : _reg(0) {}
};
int verbose;
Command command;
Reg32 data;
Status status;
Reg32 _control;
Control control;
Commands cmd;
std::array<uint8_t, 64> luminanceQuantTable;
@ -75,10 +87,12 @@ class MDEC {
uint32_t read(uint32_t address);
void handleCommand(uint8_t cmd, uint32_t data);
void write(uint32_t address, uint32_t data);
bool dataInRequest() const { return status.dataInRequest && output.empty(); }
bool dataOutRequest() const { return status.dataOutRequest && !output.empty(); }
template <class Archive>
void serialize(Archive& ar) {
ar(command._reg, data, status._reg, _control, cmd);
ar(command._reg, data, status._reg, control._reg, cmd);
ar(luminanceQuantTable, colorQuantTable, idctTable);
ar(color, paramCount, cnt);
ar(input, output, outputPtr);