Skip to content

Commit

Permalink
Update to ares v120r02 release.
Browse files Browse the repository at this point in the history
This fixes a major issue with the 68K ADD,CMP,SUB instructions not clipping, and
improves the VDP scanline renderer timing somewhat.

This fixes Alien Solder, and I also moved the DMA run below the FIFO/prefetch to
fix Comix Zone's graphics. It regresses several Titan Overdrive 2 screens, but
oh well.

I'm trying to track down a bug in Popful Mail (US) where the CPU crashes right
after the title screen. It seems like the CPU is getting stuck in a loop that
keeps calling the same function, so the stack keeps decrementing until it ends
up overwriting the currently executing code with a bad instruction.

Without an I/O tracer it's really difficult to try and understand what the CPU
is stuck waiting on and looping on. I'll have to add an I/O tracer to the Mega
CD registers.

The CPU fixes sadly didn't improve anything in the 32X space. Metal Head gets in
a loop until it overwrites the stack frame return address with 0x1fff1fff that
causes a return to an unaligned address that crashes the SH2 master.

After Burner Complete doesn't boot at all. Amazing Spider-Man still has screwed
up graphics priority ordering for the 32X VDP.

Space Harrier still shows a bunch of junk lines at the top and bottom of the
screen.

The scanline VDP can now run Lemmings 1&2, Alien Soldier, etc. But it still does
horrifically bad with Titan Overdrive, especially 2.
  • Loading branch information
near-san committed May 10, 2021
1 parent 034468c commit a290c96
Show file tree
Hide file tree
Showing 24 changed files with 457 additions and 302 deletions.
2 changes: 1 addition & 1 deletion ares/ares/ares.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ using namespace nall;

namespace ares {
static const string Name = "ares";
static const string Version = "120.1";
static const string Version = "120.2";
static const string Copyright = "Near";
static const string License = "CC BY-NC-ND 4.0";
static const string LicenseURI = "https://creativecommons.org/licenses/by-nc-nd/4.0/";
Expand Down
52 changes: 31 additions & 21 deletions ares/component/processor/m68k/algorithms.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
template<u32 Size, bool extend> auto M68K::ADD(n32 source, n32 target) -> n32 {
auto result = (n64)source + target;
if(extend) result += r.x;

r.c = sign<Size>(result >> 1) < 0;
r.v = sign<Size>(~(target ^ source) & (target ^ result)) < 0;
target = clip<Size>(target);
source = clip<Size>(source);
u32 result = target + source + (extend ? r.x : 0);
u32 carries = target ^ source ^ result;
u32 overflow = (target ^ result) & (source ^ result);

r.c = (carries ^ overflow) & msb<Size>();
r.v = overflow & msb<Size>();
r.z = clip<Size>(result) ? 0 : (extend ? r.z : 1);
r.n = sign<Size>(result) < 0;
r.x = r.c;
Expand All @@ -12,7 +15,7 @@ template<u32 Size, bool extend> auto M68K::ADD(n32 source, n32 target) -> n32 {
}

template<u32 Size> auto M68K::AND(n32 source, n32 target) -> n32 {
n32 result = target & source;
u32 result = target & source;

r.c = 0;
r.v = 0;
Expand All @@ -24,10 +27,10 @@ template<u32 Size> auto M68K::AND(n32 source, n32 target) -> n32 {

template<u32 Size> auto M68K::ASL(n32 result, u32 shift) -> n32 {
bool carry = false;
n32 overflow = 0;
u32 overflow = 0;
for(auto _ : range(shift)) {
carry = result & msb<Size>();
n32 before = result;
u32 before = result;
result <<= 1;
overflow |= before ^ result;
}
Expand All @@ -43,10 +46,10 @@ template<u32 Size> auto M68K::ASL(n32 result, u32 shift) -> n32 {

template<u32 Size> auto M68K::ASR(n32 result, u32 shift) -> n32 {
bool carry = false;
n32 overflow = 0;
u32 overflow = 0;
for(auto _ : range(shift)) {
carry = result & lsb<Size>();
n32 before = result;
u32 before = result;
result = sign<Size>(result) >> 1;
overflow |= before ^ result;
}
Expand All @@ -61,18 +64,22 @@ template<u32 Size> auto M68K::ASR(n32 result, u32 shift) -> n32 {
}

template<u32 Size> auto M68K::CMP(n32 source, n32 target) -> n32 {
auto result = (n64)target - source;

r.c = sign<Size>(result >> 1) < 0;
r.v = sign<Size>((target ^ source) & (target ^ result)) < 0;
target = clip<Size>(target);
source = clip<Size>(source);
u32 result = target - source;
u32 carries = target ^ source ^ result;
u32 overflow = (target ^ result) & (source ^ target);

r.c = (carries ^ overflow) & msb<Size>();
r.v = overflow & msb<Size>();
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;

return clip<Size>(result);
}

template<u32 Size> auto M68K::EOR(n32 source, n32 target) -> n32 {
n32 result = target ^ source;
u32 result = target ^ source;

r.c = 0;
r.v = 0;
Expand Down Expand Up @@ -115,7 +122,7 @@ template<u32 Size> auto M68K::LSR(n32 result, u32 shift) -> n32 {
}

template<u32 Size> auto M68K::OR(n32 source, n32 target) -> n32 {
auto result = target | source;
u32 result = target | source;

r.c = 0;
r.v = 0;
Expand Down Expand Up @@ -192,11 +199,14 @@ template<u32 Size> auto M68K::ROXR(n32 result, u32 shift) -> n32 {
}

template<u32 Size, bool extend> auto M68K::SUB(n32 source, n32 target) -> n32 {
auto result = (n64)target - source;
if(extend) result -= r.x;

r.c = sign<Size>(result >> 1) < 0;
r.v = sign<Size>((target ^ source) & (target ^ result)) < 0;
target = clip<Size>(target);
source = clip<Size>(source);
u32 result = target - source - (extend ? r.x : 0);
u32 carries = target ^ source ^ result;
u32 overflow = (target ^ result) & (source ^ target);

r.c = (carries ^ overflow) & msb<Size>();
r.v = overflow & msb<Size>();
r.z = clip<Size>(result) ? 0 : (extend ? r.z : 1);
r.n = sign<Size>(result) < 0;
r.x = r.c;
Expand Down
41 changes: 36 additions & 5 deletions ares/component/processor/m68k/disassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ auto M68K::_condition(n4 condition) -> string {

auto M68K::disassembleInstruction(n32 pc) -> string {
_pc = pc;
return {hex(_read<Word>(_pc), 4L), " ", pad(disassembleTable[_readPC()](), -60)}; //todo: exact maximum length unknown (and sub-optimal)
return {hex(_read<Word>(_pc), 4L), " ", pad(disassembleTable[_readPC()](), -49)};
}

auto M68K::disassembleContext() -> string {
Expand Down Expand Up @@ -374,16 +374,32 @@ template<u32 Size> auto M68K::disassembleMOVEA(EffectiveAddress from, AddressReg
return {"movea ", _effectiveAddress<Size>(from), ",", _addressRegister(to)};
}

//longest register list: "d0-d1,d3-d4,d6-d7/a0-a1,a3-a4,a6-a7"
template<u32 Size> auto M68K::disassembleMOVEM_TO_MEM(EffectiveAddress to) -> string {
string op{"movem", _suffix<Size>(), " "};

n16 list = _readPC();
string regs;
for(u32 n : range(8)) if(list.bit(0 + n)) regs.append(_dataRegister(DataRegister{n}), ",");
for(u32 lhs = 0; lhs < 8; lhs++) {
if(!list.bit(0 + lhs)) continue;
regs.append(_dataRegister(DataRegister{lhs}));
if(lhs == 7 || !list.bit(1 + lhs)) { regs.append(","); continue; }
for(u32 rhs = lhs; rhs < 8; rhs++) {
if(rhs == 7 || !list.bit(1 + rhs)) { regs.append("-", _dataRegister(DataRegister{rhs}), ","); lhs = rhs; break; }
}
}
regs.trimRight(",");
if(regs && list >> 8) regs.append("/");
for(u32 n : range(8)) if(list.bit(8 + n)) regs.append(_addressRegister(AddressRegister{n}), ",");
for(u32 lhs = 0; lhs < 8; lhs++) {
if(!list.bit(8 + lhs)) continue;
regs.append(_addressRegister(AddressRegister{lhs}));
if(lhs == 7 || !list.bit(9 + lhs)) { regs.append(","); continue; }
for(u32 rhs = lhs; rhs < 8; rhs++) {
if(rhs == 7 || !list.bit(9 + rhs)) { regs.append("-", _addressRegister(AddressRegister{rhs}), ","); lhs = rhs; break; }
}
}
regs.trimRight(",");
if(!regs) regs = "-";

return {op, regs, ",", _effectiveAddress<Size>(to)};
}
Expand All @@ -393,11 +409,26 @@ template<u32 Size> auto M68K::disassembleMOVEM_TO_REG(EffectiveAddress from) ->

n16 list = _readPC();
string regs;
for(u32 n : range(8)) if(list.bit(0 + n)) regs.append(_dataRegister(DataRegister{n}), ",");
for(u32 lhs = 0; lhs < 8; lhs++) {
if(!list.bit(0 + lhs)) continue;
regs.append(_dataRegister(DataRegister{lhs}));
if(lhs == 7 || !list.bit(1 + lhs)) { regs.append(","); continue; }
for(u32 rhs = lhs; rhs < 8; rhs++) {
if(rhs == 7 || !list.bit(1 + rhs)) { regs.append("-", _dataRegister(DataRegister{rhs}), ","); lhs = rhs; break; }
}
}
regs.trimRight(",");
if(regs && list >> 8) regs.append("/");
for(u32 n : range(8)) if(list.bit(8 + n)) regs.append(_addressRegister(AddressRegister{n}), ",");
for(u32 lhs = 0; lhs < 8; lhs++) {
if(!list.bit(8 + lhs)) continue;
regs.append(_addressRegister(AddressRegister{lhs}));
if(lhs == 7 || !list.bit(9 + lhs)) { regs.append(","); continue; }
for(u32 rhs = lhs; rhs < 8; rhs++) {
if(rhs == 7 || !list.bit(9 + rhs)) { regs.append("-", _addressRegister(AddressRegister{rhs}), ","); lhs = rhs; break; }
}
}
regs.trimRight(",");
if(!regs) regs = "-";

return {op, _effectiveAddress<Size>(from), ",", regs};
}
Expand Down
22 changes: 16 additions & 6 deletions ares/component/processor/m68k/registers.cpp
Original file line number Diff line number Diff line change
@@ -1,31 +1,41 @@
template<u32 Size> auto M68K::read(DataRegister reg) -> n32 {
return clip<Size>(r.d[reg.number]);
if constexpr(Size == Byte) return (u8 )r.d[reg.number];
if constexpr(Size == Word) return (u16)r.d[reg.number];
if constexpr(Size == Long) return (u32)r.d[reg.number];
unreachable;
}

template<u32 Size> auto M68K::write(DataRegister reg, n32 data) -> void {
r.d[reg.number] = (r.d[reg.number] & ~mask<Size>()) | (data & mask<Size>());
if constexpr(Size == Byte) r.d[reg.number] = r.d[reg.number] & ~0xff | data & 0xff;
if constexpr(Size == Word) r.d[reg.number] = r.d[reg.number] & ~0xffff | data & 0xffff;
if constexpr(Size == Long) r.d[reg.number] = data;
}

//

template<u32 Size> auto M68K::read(AddressRegister reg) -> n32 {
return sign<Size>(r.a[reg.number]);
if constexpr(Size == Byte) return (s8 )r.a[reg.number];
if constexpr(Size == Word) return (s16)r.a[reg.number];
if constexpr(Size == Long) return (s32)r.a[reg.number];
unreachable;
}

template<u32 Size> auto M68K::write(AddressRegister reg, n32 data) -> void {
r.a[reg.number] = sign<Size>(data);
if constexpr(Size == Byte) r.a[reg.number] = (s8 )data;
if constexpr(Size == Word) r.a[reg.number] = (s16)data;
if constexpr(Size == Long) r.a[reg.number] = (s32)data;
}

//

//CCR,SR unused bits cannot be set; always read out as 0
//CCR/SR unused bits cannot be set; always read out as 0

auto M68K::readCCR() -> n8 {
return r.c << 0 | r.v << 1 | r.z << 2 | r.n << 3 | r.x << 4;
}

auto M68K::readSR() -> n16 {
return readCCR() << 0 | r.i << 8 | r.s << 13 | r.t << 15;
return r.c << 0 | r.v << 1 | r.z << 2 | r.n << 3 | r.x << 4 | r.i << 8 | r.s << 13 | r.t << 15;
}

auto M68K::writeCCR(n8 ccr) -> void {
Expand Down
33 changes: 16 additions & 17 deletions ares/md/vdp-performance/dma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ auto VDP::DMA::poll() -> void {
}

auto VDP::DMA::run() -> bool {
if(!io.enable || io.wait) return false;
if(!vdp.io.command.bit(5)) return false;
if(io.mode <= 1) return load(), true;
if(io.mode == 2) return fill(), true;
if(!vdp.io.command.bit(4)) return false;
if(io.mode == 3) return copy(), true;
if(vdp.command.pending && !io.wait) {
if(io.mode <= 1) return load(), true;
if(io.mode == 2) return fill(), true;
if(io.mode == 3) return copy(), true;
}
return false;
}

Expand All @@ -27,37 +26,37 @@ auto VDP::DMA::load() -> void {

io.source.bit(0,15)++;
if(--io.length == 0) {
vdp.io.command.bit(5) = 0;
vdp.command.pending = 0;
active = 0;
}
}

auto VDP::DMA::fill() -> void {
switch(vdp.io.command.bit(0,3)) {
case 1: vdp.vram .writeByte(vdp.io.address, io.fill); break;
case 5: vdp.vsram.writeByte(vdp.io.address, io.fill); break;
case 3: vdp.cram .writeByte(vdp.io.address, io.fill); break;
switch(vdp.command.target) {
case 1: vdp.vram .writeByte(vdp.command.address, io.fill); break;
case 5: vdp.vsram.writeByte(vdp.command.address, io.fill); break;
case 3: vdp.cram .writeByte(vdp.command.address, io.fill); break;
default:
debug(unusual, "[VDP] DMA::fill: io.command = 0b", binary(vdp.io.command, 6L));
debug(unusual, "[VDP::DMA::fill]: command.target = 0x", hex(vdp.command.target));
break;
}

io.source.bit(0,15)++;
vdp.io.address += vdp.io.dataIncrement;
vdp.command.address += vdp.command.increment;
if(--io.length == 0) {
vdp.io.command.bit(5) = 0;
vdp.command.pending = 0;
}
}

//note: this can only copy to VRAM
auto VDP::DMA::copy() -> void {
auto data = vdp.vram.readByte(io.source);
vdp.vram.writeByte(vdp.io.address, data);
vdp.vram.writeByte(vdp.command.address, data);

io.source.bit(0,15)++;
vdp.io.address += vdp.io.dataIncrement;
vdp.command.address += vdp.command.increment;
if(--io.length == 0) {
vdp.io.command.bit(5) = 0;
vdp.command.pending = 0;
}
}

Expand Down
Loading

0 comments on commit a290c96

Please sign in to comment.