mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
a3aea95e6b
commit
79c83ade70
|
@ -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
|
||||
|
||||
}
|
|
@ -12,7 +12,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
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 License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
@ -29,4 +29,3 @@ namespace Emulator {
|
|||
}
|
||||
|
||||
#include "interface.hpp"
|
||||
#include "debugger.hpp"
|
||||
|
|
|
@ -4,18 +4,23 @@ auto VDP::Background::scanline() -> 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.palette = 0;
|
||||
output.priority = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 hoffset = state.x;
|
||||
if(!vdp.io.horizontalScrollLock || hoffset >= 16) hoffset -= vdp.io.hscroll;
|
||||
bool hscroll = !vdp.io.horizontalScrollLock || voffset >= 16;
|
||||
bool vscroll = !vdp.io.verticalScrollLock || hoffset <= 191;
|
||||
|
||||
uint9 voffset = state.y;
|
||||
if(!vdp.io.verticalScrollLock || hoffset <= 191) voffset += vdp.io.vscroll;
|
||||
if(hscroll) hoffset -= vdp.io.hscroll;
|
||||
if(vscroll) voffset += vdp.io.vscroll;
|
||||
|
||||
uint14 nameTableAddress;
|
||||
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(2) = vdp.vram[patternAddress + 2].bit(index);
|
||||
output.color.bit(3) = vdp.vram[patternAddress + 3].bit(index);
|
||||
|
||||
state.x++;
|
||||
}
|
||||
|
||||
auto VDP::Background::power() -> void {
|
||||
|
|
|
@ -32,16 +32,17 @@ auto VDP::Sprite::run() -> void {
|
|||
if(state.y >= vdp.vlines()) return;
|
||||
|
||||
bool large = vdp.io.extendedHeight;
|
||||
uint mask = vdp.io.extendedHeight ? 15 : 7;
|
||||
for(auto& o : objects) {
|
||||
if(state.x < o.x) continue;
|
||||
if(state.x > o.x + 7) continue;
|
||||
|
||||
uint x = o.x - state.x;
|
||||
uint y = o.y - state.y;
|
||||
uint x = state.x - o.x;
|
||||
uint y = state.y - o.y;
|
||||
|
||||
uint14 address = vdp.io.spritePatternTableAddress << 13;
|
||||
address += o.pattern << 5;
|
||||
address += (y & (large ? 15 : 7)) << 2;
|
||||
address += (y & mask) << 2;
|
||||
|
||||
auto index = 7 - (x & 7);
|
||||
uint4 color;
|
||||
|
|
|
@ -41,7 +41,7 @@ auto VDP::main() -> void {
|
|||
color = cram[16 | sprite.output.color];
|
||||
}
|
||||
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;
|
||||
}
|
||||
step(172);
|
||||
|
|
|
@ -20,7 +20,7 @@ struct LR35902 {
|
|||
|
||||
#include "registers.hpp"
|
||||
|
||||
privileged:
|
||||
private:
|
||||
auto op_xx();
|
||||
auto op_cb();
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ auto Z80::disassemble(uint16 pc) -> string {
|
|||
}
|
||||
|
||||
if(code == 0xcb && prefix) {
|
||||
auto d = (int8)code;
|
||||
auto d = (int8)bus->read(pc++);
|
||||
code = bus->read(pc++);
|
||||
output = disassembleCBd(pc, prefix, d, code);
|
||||
} else if(code == 0xcb) {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
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();
|
||||
if(code == 0xdd) { r.hlp = &r.ix; return; }
|
||||
if(code == 0xfd) { r.hlp = &r.iy; return; }
|
||||
if(code == 0xdd) { r.hlp = &r.ix; return instruction(); }
|
||||
if(code == 0xfd) { r.hlp = &r.iy; return instruction(); }
|
||||
|
||||
if(r.ei) {
|
||||
r.ei = 0;
|
||||
|
|
|
@ -41,9 +41,15 @@ auto Z80::AND(uint8 x, uint8 y) -> uint8 {
|
|||
}
|
||||
|
||||
auto Z80::BIT(uint3 bit, uint8 x) -> uint8 {
|
||||
uint8 z = x & 1 << bit;
|
||||
|
||||
NF = 0;
|
||||
PF = parity(z);
|
||||
XF = z.bit(3);
|
||||
HF = 1;
|
||||
ZF = (x & 1 << bit) == 0;
|
||||
YF = z.bit(5);
|
||||
ZF = z == 0;
|
||||
SF = z.bit(7);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
@ -293,7 +299,7 @@ auto Z80::instructionADD_a_r(uint8& 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);
|
||||
auto lo = ADD(HL >> 0, x >> 0);
|
||||
wait(3);
|
||||
|
@ -360,10 +366,12 @@ auto Z80::instructionCP_a_r(uint8& x) -> void {
|
|||
}
|
||||
|
||||
auto Z80::instructionCPD() -> void {
|
||||
bool cf = CF;
|
||||
auto data = read(_HL--);
|
||||
SUB(A, data);
|
||||
VF = --BC > 0;
|
||||
wait(5);
|
||||
SUB(A, data);
|
||||
VF = --BC != 0;
|
||||
CF = cf; //restore unaffected flag
|
||||
}
|
||||
|
||||
auto Z80::instructionCPDR() -> void {
|
||||
|
@ -374,10 +382,12 @@ auto Z80::instructionCPDR() -> void {
|
|||
}
|
||||
|
||||
auto Z80::instructionCPI() -> void {
|
||||
bool cf = CF;
|
||||
auto data = read(_HL++);
|
||||
wait(5);
|
||||
SUB(A, data);
|
||||
VF = --BC > 0;
|
||||
VF = --BC != 0;
|
||||
CF = cf; //restore unaffected flag
|
||||
}
|
||||
|
||||
auto Z80::instructionCPIR() -> void {
|
||||
|
@ -492,12 +502,12 @@ auto Z80::instructionIND() -> void {
|
|||
auto data = in(C);
|
||||
write(_HL--, data);
|
||||
NF = 0;
|
||||
ZF = --B > 0;
|
||||
ZF = --B == 0;
|
||||
}
|
||||
|
||||
auto Z80::instructionINDR() -> void {
|
||||
instructionIND();
|
||||
if(!ZF) return;
|
||||
if(ZF) return;
|
||||
wait(5);
|
||||
PC -= 2;
|
||||
}
|
||||
|
@ -507,12 +517,12 @@ auto Z80::instructionINI() -> void {
|
|||
auto data = in(C);
|
||||
write(_HL++, data);
|
||||
NF = 0;
|
||||
ZF = --B > 0;
|
||||
ZF = --B == 0;
|
||||
}
|
||||
|
||||
auto Z80::instructionINIR() -> void {
|
||||
instructionINI();
|
||||
if(!ZF) return;
|
||||
if(ZF) return;
|
||||
wait(5);
|
||||
PC -= 2;
|
||||
}
|
||||
|
@ -600,7 +610,7 @@ auto Z80::instructionLDD() -> void {
|
|||
write(DE--, data);
|
||||
wait(2);
|
||||
NF = 0;
|
||||
VF = --BC > 0;
|
||||
VF = --BC != 0;
|
||||
HF = 0;
|
||||
}
|
||||
|
||||
|
@ -616,7 +626,7 @@ auto Z80::instructionLDI() -> void {
|
|||
write(DE++, data);
|
||||
wait(2);
|
||||
NF = 0;
|
||||
VF = --BC > 0;
|
||||
VF = --BC != 0;
|
||||
HF = 0;
|
||||
}
|
||||
|
||||
|
@ -648,14 +658,14 @@ auto Z80::instructionOR_a_r(uint8& x) -> void {
|
|||
|
||||
auto Z80::instructionOTDR() -> void {
|
||||
instructionOUTD();
|
||||
if(!ZF) return;
|
||||
if(ZF) return;
|
||||
wait(5);
|
||||
PC -= 2;
|
||||
}
|
||||
|
||||
auto Z80::instructionOTIR() -> void {
|
||||
instructionOUTI();
|
||||
if(!ZF) return;
|
||||
if(ZF) return;
|
||||
wait(5);
|
||||
PC -= 2;
|
||||
}
|
||||
|
@ -674,7 +684,7 @@ auto Z80::instructionOUTD() -> void {
|
|||
auto data = read(_HL--);
|
||||
out(C, data);
|
||||
NF = 1;
|
||||
ZF = --B > 0;
|
||||
ZF = --B == 0;
|
||||
}
|
||||
|
||||
auto Z80::instructionOUTI() -> void {
|
||||
|
@ -682,7 +692,7 @@ auto Z80::instructionOUTI() -> void {
|
|||
auto data = read(_HL++);
|
||||
out(C, data);
|
||||
NF = 1;
|
||||
ZF = --B > 0;
|
||||
ZF = --B == 0;
|
||||
}
|
||||
|
||||
auto Z80::instructionPOP_rr(uint16& x) -> void {
|
||||
|
|
|
@ -25,7 +25,7 @@ struct Event : Thread {
|
|||
enum class Board : uint { CampusChallenge92, Powerfest94 } board;
|
||||
uint timer;
|
||||
|
||||
privileged:
|
||||
private:
|
||||
uint8 status;
|
||||
uint8 select;
|
||||
|
||||
|
|
|
@ -30,12 +30,10 @@ auto CPU::main() -> void {
|
|||
status.nmiPending = false;
|
||||
r.vector = r.e ? 0xfffa : 0xffea;
|
||||
interrupt();
|
||||
debug(cpu.nmi);
|
||||
} else if(status.irqPending) {
|
||||
status.irqPending = false;
|
||||
r.vector = r.e ? 0xfffe : 0xffee;
|
||||
interrupt();
|
||||
debug(cpu.irq);
|
||||
} else if(status.resetPending) {
|
||||
status.resetPending = false;
|
||||
step(132);
|
||||
|
@ -49,7 +47,6 @@ auto CPU::main() -> void {
|
|||
}
|
||||
}
|
||||
|
||||
debug(cpu.execute, r.pc);
|
||||
instruction();
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ struct CPU : Processor::R65816, Thread, PPUcounter {
|
|||
vector<Thread*> coprocessors;
|
||||
vector<Thread*> peripherals;
|
||||
|
||||
privileged:
|
||||
private:
|
||||
uint version = 2; //allowed: 1, 2
|
||||
|
||||
struct Status {
|
||||
|
|
|
@ -20,7 +20,6 @@ auto CPU::read(uint24 addr) -> uint8 {
|
|||
r.mdr = bus.read(addr, r.mdr);
|
||||
step(4);
|
||||
aluEdge();
|
||||
debug(cpu.read, addr, r.mdr);
|
||||
return r.mdr;
|
||||
}
|
||||
|
||||
|
@ -30,7 +29,6 @@ auto CPU::write(uint24 addr, uint8 data) -> void {
|
|||
dmaEdge();
|
||||
step(status.clockCount);
|
||||
bus.write(addr, r.mdr = data);
|
||||
debug(cpu.write, addr, r.mdr);
|
||||
}
|
||||
|
||||
auto CPU::speed(uint24 addr) const -> uint {
|
||||
|
|
|
@ -19,7 +19,7 @@ struct DSP : Thread {
|
|||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
privileged:
|
||||
private:
|
||||
enum GlobalRegister : uint {
|
||||
MVOLL = 0x0c, MVOLR = 0x1c,
|
||||
EVOLL = 0x2c, EVOLR = 0x3c,
|
||||
|
|
|
@ -12,30 +12,23 @@ auto PPU::addressVRAM() const -> uint16 {
|
|||
auto PPU::readVRAM() -> uint16 {
|
||||
if(!io.displayDisable && vcounter() < vdisp()) return 0x0000;
|
||||
auto addr = addressVRAM();
|
||||
auto data = vram[addr];
|
||||
debug(ppu.vram.read, addr << 1 | 0, data.byte(0));
|
||||
debug(ppu.vram.read, addr << 1 | 1, data.byte(1));
|
||||
return data;
|
||||
return vram[addr];
|
||||
}
|
||||
|
||||
auto PPU::writeVRAM(bool byte, uint8 data) -> void {
|
||||
if(!io.displayDisable && vcounter() < vdisp()) return;
|
||||
auto addr = addressVRAM();
|
||||
vram[addr].byte(byte) = data;
|
||||
debug(ppu.vram.write, addr << 1 | byte, data);
|
||||
}
|
||||
|
||||
auto PPU::readOAM(uint10 addr) -> uint8 {
|
||||
if(!io.displayDisable && vcounter() < vdisp()) addr = latch.oamAddress;
|
||||
auto data = obj.oam.read(addr);
|
||||
debug(ppu.oam.read, addr, data);
|
||||
return data;
|
||||
return obj.oam.read(addr);
|
||||
}
|
||||
|
||||
auto PPU::writeOAM(uint10 addr, uint8 data) -> void {
|
||||
if(!io.displayDisable && vcounter() < vdisp()) addr = latch.oamAddress;
|
||||
obj.oam.write(addr, data);
|
||||
debug(ppu.oam.write, addr, data);
|
||||
}
|
||||
|
||||
auto PPU::readCGRAM(bool byte, uint8 addr) -> uint8 {
|
||||
|
@ -43,9 +36,7 @@ auto PPU::readCGRAM(bool byte, uint8 addr) -> uint8 {
|
|||
&& vcounter() > 0 && vcounter() < vdisp()
|
||||
&& hcounter() >= 88 && hcounter() < 1096
|
||||
) addr = latch.cgramAddress;
|
||||
auto data = screen.cgram[addr].byte(byte);
|
||||
debug(ppu.cgram.read, addr << 1 | byte, data);
|
||||
return data;
|
||||
return screen.cgram[addr].byte(byte);
|
||||
}
|
||||
|
||||
auto PPU::writeCGRAM(uint8 addr, uint15 data) -> void {
|
||||
|
@ -54,8 +45,6 @@ auto PPU::writeCGRAM(uint8 addr, uint15 data) -> void {
|
|||
&& hcounter() >= 88 && hcounter() < 1096
|
||||
) addr = latch.cgramAddress;
|
||||
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 {
|
||||
|
|
|
@ -29,7 +29,7 @@ struct PPU : Thread, PPUcounter {
|
|||
auto latchCounters() -> void;
|
||||
auto updateVideoMode() -> void;
|
||||
|
||||
privileged:
|
||||
private:
|
||||
struct VRAM {
|
||||
auto& operator[](uint addr) { return data[addr & mask]; }
|
||||
uint16 data[64 * 1024];
|
||||
|
|
|
@ -183,7 +183,6 @@ auto SMP::read(uint16 addr) -> uint8 {
|
|||
uint8 data = readBus(addr);
|
||||
step(12);
|
||||
cycleEdge();
|
||||
debug(smp.read, addr, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -191,7 +190,6 @@ auto SMP::write(uint16 addr, uint8 data) -> void {
|
|||
step(24);
|
||||
writeBus(addr, data);
|
||||
cycleEdge();
|
||||
debug(smp.write, addr, data);
|
||||
}
|
||||
|
||||
auto SMP::readDisassembler(uint16 addr) -> uint8 {
|
||||
|
|
|
@ -13,7 +13,6 @@ auto SMP::Enter() -> void {
|
|||
}
|
||||
|
||||
auto SMP::main() -> void {
|
||||
debug(smp.execute, regs.pc);
|
||||
instruction();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ struct SMP : Processor::SPC700, Thread {
|
|||
uint8 iplrom[64];
|
||||
uint8 apuram[64 * 1024];
|
||||
|
||||
privileged:
|
||||
private:
|
||||
struct IO {
|
||||
//timing
|
||||
uint clockCounter;
|
||||
|
|
|
@ -45,7 +45,7 @@ struct System : IO {
|
|||
bool rotate;
|
||||
} keypad;
|
||||
|
||||
privileged:
|
||||
private:
|
||||
struct Registers {
|
||||
//$0060 DISP_MODE
|
||||
uint5 unknown;
|
||||
|
|
Loading…
Reference in New Issue