Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

md: vdp improvements, dots and stuff #1739

Merged
merged 2 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ares/md/m32x/pwm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ auto M32X::PWM::main() -> void {
while(counter >= 522) {
counter -= 522;
auto left = cycle > 0 ? lsample / (f32)cycle : 0;
auto right = cycle > 0 ? lsample / (f32)cycle : 0;
auto right = cycle > 0 ? rsample / (f32)cycle : 0;
stream->frame(left, right);
}

Expand Down
2 changes: 1 addition & 1 deletion ares/md/system/serialization.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
static const string SerializerVersion = "v135";
static const string SerializerVersion = "v141";

auto System::serialize(bool synchronize) -> serializer {
if(synchronize) scheduler.enter(Scheduler::Mode::Synchronize);
Expand Down
55 changes: 50 additions & 5 deletions ares/md/vdp/dac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,61 @@ template<bool _h40, bool draw> auto VDP::DAC::pixel(u32 x) -> void {
output<_h40>(pixel.backdrop << 11 | mode << 9 | color);
}

auto pixelIndex(n9 hpos) -> maybe<u32> {
if(vdp.h40()) {
if(hpos < 0x00d || hpos > 0x167) return nothing;
return (hpos-0x00d)*4;
} else {
if(hpos < 0x00b || hpos > 0x125) return nothing;
return (hpos-0x00b)*5;
}
}

template<u8 _size, u16 _h32Pos, u16 _h40Pos> inline auto VDP::DAC::fillBorder(n8 ofst) -> void {
if(!pixels) return;
if(ofst >= _size) return;

u32 hpos = (vdp.h40() ? _h40Pos : _h32Pos) + ofst;
u32 idx = pixelIndex(hpos)();
n32 px = 0b101 << 9 | vdp.cram.color(vdp.io.backgroundColor);
for(auto n : range((_size-ofst)*(vdp.h40()?4:5)))
pixels[idx+n] = px;
}

auto VDP::DAC::fillLeftBorder(n8 ofst) -> void {
fillBorder<13,0x00b,0x00d>(ofst);
}

auto VDP::DAC::fillRightBorder(n8 ofst) -> void {
fillBorder<14,0x118,0x15a>(ofst);
}

auto VDP::DAC::dot(n9 hpos, n9 color) -> void {
if(!pixels) return;

if(auto i = pixelIndex(hpos)) {
u32 index = i();
n32 px = 0b101 << 9 | color;
pixels[index++] = px;
pixels[index++] = px;
pixels[index++] = px;
pixels[index++] = px;
if(vdp.h40()) return;
pixels[index++] = px;
}
}

template<bool _h40> auto VDP::DAC::output(n32 color) -> void {
*pixels++ = color;
*pixels++ = color;
*pixels++ = color;
*pixels++ = color;
*active++ = color;
*active++ = color;
*active++ = color;
*active++ = color;
if(_h40) return;
*pixels++ = color;
*active++ = color;
}

auto VDP::DAC::power(bool reset) -> void {
test = {};
pixels = nullptr;
active = nullptr;
}
33 changes: 23 additions & 10 deletions ares/md/vdp/dma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,38 @@ auto VDP::DMA::synchronize() -> void {
}
}

auto VDP::DMA::fetch() -> void {
if(active && !read) {
auto address = mode.bit(0) << 23 | source << 1;
data = bus.read(1, 1, address);
read = 1;
}
}

auto VDP::DMA::run() -> bool {
if(vdp.command.pending && !wait) {
if(mode <= 1 && !vdp.fifo.full()) {
if(mode <= 1 && !vdp.fifo.full() && read) {
return load(), true;
} else if(mode == 2 && vdp.fifo.empty()) {
} else if(mode == 2 && vdp.fifo.empty() && !vdp.state.rambusy) {
return fill(), true;
} else if(mode == 3) {
} else if(mode == 3 && !vdp.state.rambusy) {
return copy(), true;
}
}
return false;
}

auto VDP::DMA::load() -> void {
if(delay > 0) { delay--; return; }
read = 0;
vdp.fifo.write(vdp.command.target, vdp.command.address, data);

auto address = mode.bit(0) << 23 | source << 1;
if(vdp.refreshing()) return; // bus not available
auto data = bus.read(1, 1, address);
vdp.writeDataPort(data);
vdp.debugger.dmaLoad(address, vdp.command.target, vdp.command.address, data);

source.bit(0,15)++;
vdp.command.address += vdp.command.increment;
if(--length == 0) {
vdp.command.pending = 0;
vdp.command.pending = 0; wait = 1; preload = 0;
synchronize();
}
}
Expand All @@ -43,12 +51,14 @@ auto VDP::DMA::fill() -> void {
case 3: vdp.cram.write(vdp.command.address >> 1, data); break;
case 5: vdp.vsram.write(vdp.command.address >> 1, data); break;
}
vdp.state.rambusy = 1;

vdp.debugger.dmaFill(vdp.command.target, vdp.command.address, data);

source.bit(0,15)++;
vdp.command.address += vdp.command.increment;
if(--length == 0) {
vdp.command.pending = 0;
vdp.command.pending = 0; wait = 1;
synchronize();
}
}
Expand All @@ -58,17 +68,20 @@ auto VDP::DMA::copy() -> void {
if(!read) {
read = 1;
data = vdp.vram.readByte(source ^ 1);
vdp.state.rambusy = 1;
return;
}

read = 0;
vdp.vram.writeByte(vdp.command.address ^ 1, data);
vdp.state.rambusy = 1;

vdp.debugger.dmaCopy(source, vdp.command.target, vdp.command.address ^ 1, data);

source.bit(0,15)++;
vdp.command.address += vdp.command.increment;
if(--length == 0) {
vdp.command.pending = 0;
vdp.command.pending = 0; wait = 1;
synchronize();
}
}
Expand Down
34 changes: 18 additions & 16 deletions ares/md/vdp/fifo.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
auto VDP::FIFO::tick() -> void {
for(auto& slot : slots)
if(!slot.empty() && slot.latency > 0)
slot.latency--;
}

auto VDP::FIFO::advance() -> void {
if(vdp.command.pending && vdp.dma.mode == 2) {
if(slots[0].target == 1)
vdp.dma.data = slots[0].data;
else
vdp.dma.data = slots[1].data; // fill data taken from next fifo slot (late fetch)
vdp.dma.read = 1;
vdp.dma.wait = 0; // start pending DMA if necessary
}

swap(slots[0], slots[1]);
swap(slots[1], slots[2]);
swap(slots[2], slots[3]);
}

auto VDP::FIFO::run() -> bool {
if(empty()) return false;
if(slots[0].latency > 0) return false;
if(vdp.dma.active && vdp.dma.preload > 0) return false;

if(slots[0].target == 1 && vdp.vram.mode == 0) {
if(slots[0].lower) {
Expand All @@ -16,10 +33,6 @@ auto VDP::FIFO::run() -> bool {
if(slots[0].upper) {
slots[0].upper = 0;
vdp.vram.writeByte(slots[0].address, slots[0].data.byte(1));
if(vdp.command.pending && vdp.dma.mode == 2) {
vdp.dma.data = slots[0].data;
vdp.dma.wait = 0; // start pending DMA
}
return advance(), true;
}
}
Expand All @@ -36,13 +49,6 @@ auto VDP::FIFO::run() -> bool {
if(slots[0].upper) {
slots[0].upper = 0;
// null action
if(vdp.command.pending && vdp.dma.mode == 2) {
// trigger action here is speculative/untested
// but it follows from the (normal) write case
debug(unusual, "[VDP::FIFO] dma fill start");
vdp.dma.data = slots[0].data;
vdp.dma.wait = 0; // start pending DMA
}
return advance(), true;
}
}
Expand All @@ -56,11 +62,6 @@ auto VDP::FIFO::run() -> bool {
else
debug(unusual, "[VDP::FIFO] write target = 0x", hex(slots[0].target));

if(vdp.command.pending && vdp.dma.mode == 2) {
vdp.dma.data = slots[1].data; // fill data taken from next fifo slot (late fetch)
vdp.dma.wait = 0; // start pending DMA
}

slots[0].lower = 0;
slots[0].upper = 0;
return advance(), true;
Expand All @@ -83,6 +84,7 @@ auto VDP::FIFO::write(n4 target, n17 address, n16 data) -> void {
slot.data = data;
slot.upper = 1;
slot.lower = 1;
slot.latency = 2;
return;
}
}
Expand Down
11 changes: 8 additions & 3 deletions ares/md/vdp/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ auto VDP::readControlPort() -> n16 {
result.bit( 0) = Region::PAL();
result.bit( 1) = command.pending;
result.bit( 2) = hblank();
result.bit( 3) = vblank() || !io.displayEnable;
result.bit( 3) = vblank() || !displayEnable();
result.bit( 4) = io.interlaceMode.bit(0) && field();
result.bit( 5) = sprite.collision;
result.bit( 6) = sprite.overflow;
Expand Down Expand Up @@ -187,8 +187,13 @@ auto VDP::writeControlPort(n16 data) -> void {

prefetch.read(command.target, command.address);

if(command.pending && dma.mode == 1) dma.delay = 4; // based on measurement noted by Mask of Destiny
dma.wait = dma.mode == 2;
if(command.pending && dma.mode != 2) {
// dma preload init is tuned based on Direct Color DMA demos; lower values lead to instability
if(dma.mode < 2) dma.preload = 7;
dma.read = 0;
dma.wait = 0;
}

dma.synchronize();
return;
}
Expand Down
Loading
Loading