Update to v101r29 release.

byuu says:

Changelog:

  - SMS: background VDP clips partial tiles on the left (math may not be
    right ... it's hard to reason about)
  - SMS: fix background VDP scroll locks
  - SMS: fix VDP sprite coordinates
  - SMS: paint black after the end of the visible display
      - todo: shouldn't be a brute force at the end of the main VDP
        loop, should happen in each rendering unit
  - higan: removed emulator/debugger.hpp
  - higan: removed privileged: access specifier
  - SFC: removed debugger hooks
      - todo: remove sfc/debugger.hpp
  - Z80: fixed disassembly of (fd,dd) cb (displacement) (opcode)
    instructions
  - Z80: fix to prevent interrupts from firing between ix/iy prefixes
    and opcodes
      - todo: this is a rather hacky fix that could, if exploited, crash
        the stack frame
  - Z80: fix BIT flags
  - Z80: fix ADD hl,reg flags
  - Z80: fix CPD, CPI flags
  - Z80: fix IND, INI flags
  - Z80: fix INDR, INIT loop flag check
  - Z80: fix OUTD, OUTI flags
  - Z80: fix OTDR, OTIR loop flag check
This commit is contained in:
Tim Allen 2017-01-10 08:27:13 +11:00
parent a3aea95e6b
commit 79c83ade70
20 changed files with 56 additions and 73 deletions

View File

@ -1,13 +0,0 @@
#pragma once
namespace Emulator {
#if defined(DEBUGGER)
#define debug(id, ...) if(debugger.id) debugger.id(__VA_ARGS__)
#define privileged public
#else
#define debug(id, ...)
#define privileged private
#endif
}

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator { namespace Emulator {
static const string Name = "higan"; static const string Name = "higan";
static const string Version = "101.28"; static const string Version = "101.29";
static const string Author = "byuu"; static const string Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "http://byuu.org/"; static const string Website = "http://byuu.org/";
@ -29,4 +29,3 @@ namespace Emulator {
} }
#include "interface.hpp" #include "interface.hpp"
#include "debugger.hpp"

View File

@ -4,18 +4,23 @@ auto VDP::Background::scanline() -> void {
} }
auto VDP::Background::run() -> void { auto VDP::Background::run() -> void {
if(state.y >= vdp.vlines()) { uint8 hoffset = state.x++;
uint9 voffset = state.y;
if(voffset >= vdp.vlines()
|| hoffset < (vdp.io.hscroll & 7)
) {
output.color = 0; output.color = 0;
output.palette = 0; output.palette = 0;
output.priority = 0; output.priority = 0;
return; return;
} }
uint8 hoffset = state.x; bool hscroll = !vdp.io.horizontalScrollLock || voffset >= 16;
if(!vdp.io.horizontalScrollLock || hoffset >= 16) hoffset -= vdp.io.hscroll; bool vscroll = !vdp.io.verticalScrollLock || hoffset <= 191;
uint9 voffset = state.y; if(hscroll) hoffset -= vdp.io.hscroll;
if(!vdp.io.verticalScrollLock || hoffset <= 191) voffset += vdp.io.vscroll; if(vscroll) voffset += vdp.io.vscroll;
uint14 nameTableAddress; uint14 nameTableAddress;
if(vdp.vlines() == 192) { if(vdp.vlines() == 192) {
@ -43,8 +48,6 @@ auto VDP::Background::run() -> void {
output.color.bit(1) = vdp.vram[patternAddress + 1].bit(index); output.color.bit(1) = vdp.vram[patternAddress + 1].bit(index);
output.color.bit(2) = vdp.vram[patternAddress + 2].bit(index); output.color.bit(2) = vdp.vram[patternAddress + 2].bit(index);
output.color.bit(3) = vdp.vram[patternAddress + 3].bit(index); output.color.bit(3) = vdp.vram[patternAddress + 3].bit(index);
state.x++;
} }
auto VDP::Background::power() -> void { auto VDP::Background::power() -> void {

View File

@ -32,16 +32,17 @@ auto VDP::Sprite::run() -> void {
if(state.y >= vdp.vlines()) return; if(state.y >= vdp.vlines()) return;
bool large = vdp.io.extendedHeight; bool large = vdp.io.extendedHeight;
uint mask = vdp.io.extendedHeight ? 15 : 7;
for(auto& o : objects) { for(auto& o : objects) {
if(state.x < o.x) continue; if(state.x < o.x) continue;
if(state.x > o.x + 7) continue; if(state.x > o.x + 7) continue;
uint x = o.x - state.x; uint x = state.x - o.x;
uint y = o.y - state.y; uint y = state.y - o.y;
uint14 address = vdp.io.spritePatternTableAddress << 13; uint14 address = vdp.io.spritePatternTableAddress << 13;
address += o.pattern << 5; address += o.pattern << 5;
address += (y & (large ? 15 : 7)) << 2; address += (y & mask) << 2;
auto index = 7 - (x & 7); auto index = 7 - (x & 7);
uint4 color; uint4 color;

View File

@ -41,7 +41,7 @@ auto VDP::main() -> void {
color = cram[16 | sprite.output.color]; color = cram[16 | sprite.output.color];
} }
if(x <= 7 && io.leftClip) color = cram[io.backdropColor]; if(x <= 7 && io.leftClip) color = cram[io.backdropColor];
if(!io.displayEnable) color = 0; if(!io.displayEnable || io.vcounter >= vlines()) color = 0;
buffer[io.vcounter * 256 + x] = color; buffer[io.vcounter * 256 + x] = color;
} }
step(172); step(172);

View File

@ -20,7 +20,7 @@ struct LR35902 {
#include "registers.hpp" #include "registers.hpp"
privileged: private:
auto op_xx(); auto op_xx();
auto op_cb(); auto op_cb();

View File

@ -21,7 +21,7 @@ auto Z80::disassemble(uint16 pc) -> string {
} }
if(code == 0xcb && prefix) { if(code == 0xcb && prefix) {
auto d = (int8)code; auto d = (int8)bus->read(pc++);
code = bus->read(pc++); code = bus->read(pc++);
output = disassembleCBd(pc, prefix, d, code); output = disassembleCBd(pc, prefix, d, code);
} else if(code == 0xcb) { } else if(code == 0xcb) {

View File

@ -1,7 +1,9 @@
auto Z80::instruction() -> void { auto Z80::instruction() -> void {
//todo: return instruction() could cause stack crash from recursion
//but this is needed to prevent IRQs from firing between prefixes and opcodes
auto code = opcode(); auto code = opcode();
if(code == 0xdd) { r.hlp = &r.ix; return; } if(code == 0xdd) { r.hlp = &r.ix; return instruction(); }
if(code == 0xfd) { r.hlp = &r.iy; return; } if(code == 0xfd) { r.hlp = &r.iy; return instruction(); }
if(r.ei) { if(r.ei) {
r.ei = 0; r.ei = 0;

View File

@ -41,9 +41,15 @@ auto Z80::AND(uint8 x, uint8 y) -> uint8 {
} }
auto Z80::BIT(uint3 bit, uint8 x) -> uint8 { auto Z80::BIT(uint3 bit, uint8 x) -> uint8 {
uint8 z = x & 1 << bit;
NF = 0; NF = 0;
PF = parity(z);
XF = z.bit(3);
HF = 1; HF = 1;
ZF = (x & 1 << bit) == 0; YF = z.bit(5);
ZF = z == 0;
SF = z.bit(7);
return x; return x;
} }
@ -293,7 +299,7 @@ auto Z80::instructionADD_a_r(uint8& x) -> void {
} }
auto Z80::instructionADD_hl_rr(uint16& x) -> void { auto Z80::instructionADD_hl_rr(uint16& x) -> void {
auto vf = VF, zf = ZF, sf = SF; bool vf = VF, zf = ZF, sf = SF;
wait(4); wait(4);
auto lo = ADD(HL >> 0, x >> 0); auto lo = ADD(HL >> 0, x >> 0);
wait(3); wait(3);
@ -360,10 +366,12 @@ auto Z80::instructionCP_a_r(uint8& x) -> void {
} }
auto Z80::instructionCPD() -> void { auto Z80::instructionCPD() -> void {
bool cf = CF;
auto data = read(_HL--); auto data = read(_HL--);
SUB(A, data);
VF = --BC > 0;
wait(5); wait(5);
SUB(A, data);
VF = --BC != 0;
CF = cf; //restore unaffected flag
} }
auto Z80::instructionCPDR() -> void { auto Z80::instructionCPDR() -> void {
@ -374,10 +382,12 @@ auto Z80::instructionCPDR() -> void {
} }
auto Z80::instructionCPI() -> void { auto Z80::instructionCPI() -> void {
bool cf = CF;
auto data = read(_HL++); auto data = read(_HL++);
wait(5); wait(5);
SUB(A, data); SUB(A, data);
VF = --BC > 0; VF = --BC != 0;
CF = cf; //restore unaffected flag
} }
auto Z80::instructionCPIR() -> void { auto Z80::instructionCPIR() -> void {
@ -492,12 +502,12 @@ auto Z80::instructionIND() -> void {
auto data = in(C); auto data = in(C);
write(_HL--, data); write(_HL--, data);
NF = 0; NF = 0;
ZF = --B > 0; ZF = --B == 0;
} }
auto Z80::instructionINDR() -> void { auto Z80::instructionINDR() -> void {
instructionIND(); instructionIND();
if(!ZF) return; if(ZF) return;
wait(5); wait(5);
PC -= 2; PC -= 2;
} }
@ -507,12 +517,12 @@ auto Z80::instructionINI() -> void {
auto data = in(C); auto data = in(C);
write(_HL++, data); write(_HL++, data);
NF = 0; NF = 0;
ZF = --B > 0; ZF = --B == 0;
} }
auto Z80::instructionINIR() -> void { auto Z80::instructionINIR() -> void {
instructionINI(); instructionINI();
if(!ZF) return; if(ZF) return;
wait(5); wait(5);
PC -= 2; PC -= 2;
} }
@ -600,7 +610,7 @@ auto Z80::instructionLDD() -> void {
write(DE--, data); write(DE--, data);
wait(2); wait(2);
NF = 0; NF = 0;
VF = --BC > 0; VF = --BC != 0;
HF = 0; HF = 0;
} }
@ -616,7 +626,7 @@ auto Z80::instructionLDI() -> void {
write(DE++, data); write(DE++, data);
wait(2); wait(2);
NF = 0; NF = 0;
VF = --BC > 0; VF = --BC != 0;
HF = 0; HF = 0;
} }
@ -648,14 +658,14 @@ auto Z80::instructionOR_a_r(uint8& x) -> void {
auto Z80::instructionOTDR() -> void { auto Z80::instructionOTDR() -> void {
instructionOUTD(); instructionOUTD();
if(!ZF) return; if(ZF) return;
wait(5); wait(5);
PC -= 2; PC -= 2;
} }
auto Z80::instructionOTIR() -> void { auto Z80::instructionOTIR() -> void {
instructionOUTI(); instructionOUTI();
if(!ZF) return; if(ZF) return;
wait(5); wait(5);
PC -= 2; PC -= 2;
} }
@ -674,7 +684,7 @@ auto Z80::instructionOUTD() -> void {
auto data = read(_HL--); auto data = read(_HL--);
out(C, data); out(C, data);
NF = 1; NF = 1;
ZF = --B > 0; ZF = --B == 0;
} }
auto Z80::instructionOUTI() -> void { auto Z80::instructionOUTI() -> void {
@ -682,7 +692,7 @@ auto Z80::instructionOUTI() -> void {
auto data = read(_HL++); auto data = read(_HL++);
out(C, data); out(C, data);
NF = 1; NF = 1;
ZF = --B > 0; ZF = --B == 0;
} }
auto Z80::instructionPOP_rr(uint16& x) -> void { auto Z80::instructionPOP_rr(uint16& x) -> void {

View File

@ -25,7 +25,7 @@ struct Event : Thread {
enum class Board : uint { CampusChallenge92, Powerfest94 } board; enum class Board : uint { CampusChallenge92, Powerfest94 } board;
uint timer; uint timer;
privileged: private:
uint8 status; uint8 status;
uint8 select; uint8 select;

View File

@ -30,12 +30,10 @@ auto CPU::main() -> void {
status.nmiPending = false; status.nmiPending = false;
r.vector = r.e ? 0xfffa : 0xffea; r.vector = r.e ? 0xfffa : 0xffea;
interrupt(); interrupt();
debug(cpu.nmi);
} else if(status.irqPending) { } else if(status.irqPending) {
status.irqPending = false; status.irqPending = false;
r.vector = r.e ? 0xfffe : 0xffee; r.vector = r.e ? 0xfffe : 0xffee;
interrupt(); interrupt();
debug(cpu.irq);
} else if(status.resetPending) { } else if(status.resetPending) {
status.resetPending = false; status.resetPending = false;
step(132); step(132);
@ -49,7 +47,6 @@ auto CPU::main() -> void {
} }
} }
debug(cpu.execute, r.pc);
instruction(); instruction();
} }

View File

@ -83,7 +83,7 @@ struct CPU : Processor::R65816, Thread, PPUcounter {
vector<Thread*> coprocessors; vector<Thread*> coprocessors;
vector<Thread*> peripherals; vector<Thread*> peripherals;
privileged: private:
uint version = 2; //allowed: 1, 2 uint version = 2; //allowed: 1, 2
struct Status { struct Status {

View File

@ -20,7 +20,6 @@ auto CPU::read(uint24 addr) -> uint8 {
r.mdr = bus.read(addr, r.mdr); r.mdr = bus.read(addr, r.mdr);
step(4); step(4);
aluEdge(); aluEdge();
debug(cpu.read, addr, r.mdr);
return r.mdr; return r.mdr;
} }
@ -30,7 +29,6 @@ auto CPU::write(uint24 addr, uint8 data) -> void {
dmaEdge(); dmaEdge();
step(status.clockCount); step(status.clockCount);
bus.write(addr, r.mdr = data); bus.write(addr, r.mdr = data);
debug(cpu.write, addr, r.mdr);
} }
auto CPU::speed(uint24 addr) const -> uint { auto CPU::speed(uint24 addr) const -> uint {

View File

@ -19,7 +19,7 @@ struct DSP : Thread {
//serialization.cpp //serialization.cpp
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;
privileged: private:
enum GlobalRegister : uint { enum GlobalRegister : uint {
MVOLL = 0x0c, MVOLR = 0x1c, MVOLL = 0x0c, MVOLR = 0x1c,
EVOLL = 0x2c, EVOLR = 0x3c, EVOLL = 0x2c, EVOLR = 0x3c,

View File

@ -12,30 +12,23 @@ auto PPU::addressVRAM() const -> uint16 {
auto PPU::readVRAM() -> uint16 { auto PPU::readVRAM() -> uint16 {
if(!io.displayDisable && vcounter() < vdisp()) return 0x0000; if(!io.displayDisable && vcounter() < vdisp()) return 0x0000;
auto addr = addressVRAM(); auto addr = addressVRAM();
auto data = vram[addr]; return vram[addr];
debug(ppu.vram.read, addr << 1 | 0, data.byte(0));
debug(ppu.vram.read, addr << 1 | 1, data.byte(1));
return data;
} }
auto PPU::writeVRAM(bool byte, uint8 data) -> void { auto PPU::writeVRAM(bool byte, uint8 data) -> void {
if(!io.displayDisable && vcounter() < vdisp()) return; if(!io.displayDisable && vcounter() < vdisp()) return;
auto addr = addressVRAM(); auto addr = addressVRAM();
vram[addr].byte(byte) = data; vram[addr].byte(byte) = data;
debug(ppu.vram.write, addr << 1 | byte, data);
} }
auto PPU::readOAM(uint10 addr) -> uint8 { auto PPU::readOAM(uint10 addr) -> uint8 {
if(!io.displayDisable && vcounter() < vdisp()) addr = latch.oamAddress; if(!io.displayDisable && vcounter() < vdisp()) addr = latch.oamAddress;
auto data = obj.oam.read(addr); return obj.oam.read(addr);
debug(ppu.oam.read, addr, data);
return data;
} }
auto PPU::writeOAM(uint10 addr, uint8 data) -> void { auto PPU::writeOAM(uint10 addr, uint8 data) -> void {
if(!io.displayDisable && vcounter() < vdisp()) addr = latch.oamAddress; if(!io.displayDisable && vcounter() < vdisp()) addr = latch.oamAddress;
obj.oam.write(addr, data); obj.oam.write(addr, data);
debug(ppu.oam.write, addr, data);
} }
auto PPU::readCGRAM(bool byte, uint8 addr) -> uint8 { auto PPU::readCGRAM(bool byte, uint8 addr) -> uint8 {
@ -43,9 +36,7 @@ auto PPU::readCGRAM(bool byte, uint8 addr) -> uint8 {
&& vcounter() > 0 && vcounter() < vdisp() && vcounter() > 0 && vcounter() < vdisp()
&& hcounter() >= 88 && hcounter() < 1096 && hcounter() >= 88 && hcounter() < 1096
) addr = latch.cgramAddress; ) addr = latch.cgramAddress;
auto data = screen.cgram[addr].byte(byte); return screen.cgram[addr].byte(byte);
debug(ppu.cgram.read, addr << 1 | byte, data);
return data;
} }
auto PPU::writeCGRAM(uint8 addr, uint15 data) -> void { auto PPU::writeCGRAM(uint8 addr, uint15 data) -> void {
@ -54,8 +45,6 @@ auto PPU::writeCGRAM(uint8 addr, uint15 data) -> void {
&& hcounter() >= 88 && hcounter() < 1096 && hcounter() >= 88 && hcounter() < 1096
) addr = latch.cgramAddress; ) addr = latch.cgramAddress;
screen.cgram[addr] = data; screen.cgram[addr] = data;
debug(ppu.cgram.write, addr << 1 | 0, data.byte(0));
debug(ppu.cgram.write, addr << 1 | 1, data.byte(1));
} }
auto PPU::readIO(uint24 addr, uint8 data) -> uint8 { auto PPU::readIO(uint24 addr, uint8 data) -> uint8 {

View File

@ -29,7 +29,7 @@ struct PPU : Thread, PPUcounter {
auto latchCounters() -> void; auto latchCounters() -> void;
auto updateVideoMode() -> void; auto updateVideoMode() -> void;
privileged: private:
struct VRAM { struct VRAM {
auto& operator[](uint addr) { return data[addr & mask]; } auto& operator[](uint addr) { return data[addr & mask]; }
uint16 data[64 * 1024]; uint16 data[64 * 1024];

View File

@ -183,7 +183,6 @@ auto SMP::read(uint16 addr) -> uint8 {
uint8 data = readBus(addr); uint8 data = readBus(addr);
step(12); step(12);
cycleEdge(); cycleEdge();
debug(smp.read, addr, data);
return data; return data;
} }
@ -191,7 +190,6 @@ auto SMP::write(uint16 addr, uint8 data) -> void {
step(24); step(24);
writeBus(addr, data); writeBus(addr, data);
cycleEdge(); cycleEdge();
debug(smp.write, addr, data);
} }
auto SMP::readDisassembler(uint16 addr) -> uint8 { auto SMP::readDisassembler(uint16 addr) -> uint8 {

View File

@ -13,7 +13,6 @@ auto SMP::Enter() -> void {
} }
auto SMP::main() -> void { auto SMP::main() -> void {
debug(smp.execute, regs.pc);
instruction(); instruction();
} }

View File

@ -14,7 +14,7 @@ struct SMP : Processor::SPC700, Thread {
uint8 iplrom[64]; uint8 iplrom[64];
uint8 apuram[64 * 1024]; uint8 apuram[64 * 1024];
privileged: private:
struct IO { struct IO {
//timing //timing
uint clockCounter; uint clockCounter;

View File

@ -45,7 +45,7 @@ struct System : IO {
bool rotate; bool rotate;
} keypad; } keypad;
privileged: private:
struct Registers { struct Registers {
//$0060 DISP_MODE //$0060 DISP_MODE
uint5 unknown; uint5 unknown;