mirror of https://github.com/bsnes-emu/bsnes.git
Update to v094r31 release.
byuu says: This WIP scores 448/920 tests passed. Gave a shot at ROM prefetch that failed miserably (ranged from 409 to 494 tests passed. Nowhere near where it would be if it were implemented correctly.) Three remaining issues: - ROM prefetch - DMA timing - timers (I suspect it's a 3-clock delay in starting, not a 3-clock into the future affair) Probably only going to be able to get the timers working without heroic amounts of effort. MUL timing is fixed to use idle cycles. STMIA is fixed to set sequential at the right moments. DMA priority support is added, so DMA 0 can interrupt DMA 1 mid-transfer. In other news ... I'm calling gtk_widget_destroy on the GtkWindow now, so hopefully those Window_configure issues go away. I realize I was leaking Display* handles in the X-video driver while I was looking at it, so I fixed those. I added DT_NOPREFIX so the Windows ListView will show & characters correctly now.
This commit is contained in:
parent
310ff4fa3b
commit
ea02f1e36a
|
@ -8,7 +8,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "094.30";
|
static const string Version = "094.31";
|
||||||
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/";
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace GameBoyAdvance {
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
CPU cpu;
|
CPU cpu;
|
||||||
|
|
||||||
void CPU::Enter() {
|
auto CPU::Enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
if(scheduler.sync == Scheduler::SynchronizeMode::CPU) {
|
if(scheduler.sync == Scheduler::SynchronizeMode::CPU) {
|
||||||
scheduler.sync = Scheduler::SynchronizeMode::All;
|
scheduler.sync = Scheduler::SynchronizeMode::All;
|
||||||
|
@ -21,7 +21,7 @@ void CPU::Enter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::main() {
|
auto CPU::main() -> void {
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
if(crash) {
|
if(crash) {
|
||||||
print(cpsr().t ? disassemble_thumb_instruction(pipeline.execute.address)
|
print(cpsr().t ? disassemble_thumb_instruction(pipeline.execute.address)
|
||||||
|
@ -57,12 +57,12 @@ void CPU::main() {
|
||||||
exec();
|
exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::step(unsigned clocks) {
|
auto CPU::step(unsigned clocks) -> void {
|
||||||
timer_step(clocks);
|
timer_step(clocks);
|
||||||
sync_step(clocks);
|
sync_step(clocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::sync_step(unsigned clocks) {
|
auto CPU::sync_step(unsigned clocks) -> void {
|
||||||
ppu.clock -= clocks;
|
ppu.clock -= clocks;
|
||||||
if(ppu.clock < 0) co_switch(ppu.thread);
|
if(ppu.clock < 0) co_switch(ppu.thread);
|
||||||
|
|
||||||
|
@ -70,26 +70,26 @@ void CPU::sync_step(unsigned clocks) {
|
||||||
if(apu.clock < 0) co_switch(apu.thread);
|
if(apu.clock < 0) co_switch(apu.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::bus_idle(uint32 addr) {
|
auto CPU::bus_idle(uint32 addr) -> void {
|
||||||
step(1);
|
step(1);
|
||||||
return bus.idle(addr);
|
return bus.idle(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 CPU::bus_read(uint32 addr, uint32 size) {
|
auto CPU::bus_read(uint32 addr, uint32 size) -> uint32 {
|
||||||
step(bus.wait(addr, size));
|
step(bus.wait(addr, size));
|
||||||
return bus.read(addr, size);
|
return bus.read(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::bus_write(uint32 addr, uint32 size, uint32 word) {
|
auto CPU::bus_write(uint32 addr, uint32 size, uint32 word) -> void {
|
||||||
step(bus.wait(addr, size));
|
step(bus.wait(addr, size));
|
||||||
return bus.write(addr, size, word);
|
return bus.write(addr, size, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::keypad_run() {
|
auto CPU::keypad_run() -> void {
|
||||||
if(regs.keypad.control.enable == false) return;
|
if(regs.keypad.control.enable == false) return;
|
||||||
|
|
||||||
bool test = regs.keypad.control.condition; //0 = OR, 1 = AND
|
bool test = regs.keypad.control.condition; //0 = OR, 1 = AND
|
||||||
for(unsigned n = 0; n < 10; n++) {
|
for(auto n : range(10)) {
|
||||||
if(regs.keypad.control.flag[n] == false) continue;
|
if(regs.keypad.control.flag[n] == false) continue;
|
||||||
bool input = interface->inputPoll(0, 0, n);
|
bool input = interface->inputPoll(0, 0, n);
|
||||||
if(regs.keypad.control.condition == 0) test |= input;
|
if(regs.keypad.control.condition == 0) test |= input;
|
||||||
|
@ -98,12 +98,12 @@ void CPU::keypad_run() {
|
||||||
if(test) regs.irq.flag.keypad = true;
|
if(test) regs.irq.flag.keypad = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::power() {
|
auto CPU::power() -> void {
|
||||||
create(CPU::Enter, 16777216);
|
create(CPU::Enter, 16777216);
|
||||||
|
|
||||||
ARM::power();
|
ARM::power();
|
||||||
for(unsigned n = 0; n < 32 * 1024; n++) iwram[n] = 0;
|
for(auto n : range( 32 * 1024)) iwram[n] = 0;
|
||||||
for(unsigned n = 0; n < 256 * 1024; n++) ewram[n] = 0;
|
for(auto n : range(256 * 1024)) ewram[n] = 0;
|
||||||
|
|
||||||
for(auto& dma : regs.dma) {
|
for(auto& dma : regs.dma) {
|
||||||
dma.source = 0;
|
dma.source = 0;
|
||||||
|
|
|
@ -1,43 +1,50 @@
|
||||||
struct CPU : Processor::ARM, Thread, MMIO {
|
struct CPU : Processor::ARM, Thread, MMIO {
|
||||||
uint8* iwram;
|
uint8* iwram = nullptr;
|
||||||
uint8* ewram;
|
uint8* ewram = nullptr;
|
||||||
#include "registers.hpp"
|
#include "registers.hpp"
|
||||||
#include "state.hpp"
|
#include "state.hpp"
|
||||||
|
|
||||||
static void Enter();
|
//cpu.cpp
|
||||||
void main();
|
static auto Enter() -> void;
|
||||||
void step(unsigned clocks);
|
|
||||||
void sync_step(unsigned clocks);
|
|
||||||
|
|
||||||
void bus_idle(uint32 addr);
|
auto main() -> void;
|
||||||
uint32 bus_read(uint32 addr, uint32 size);
|
auto step(unsigned clocks) -> void;
|
||||||
void bus_write(uint32 addr, uint32 size, uint32 word);
|
auto sync_step(unsigned clocks) -> void;
|
||||||
|
|
||||||
void keypad_run();
|
auto bus_idle(uint32 addr) -> void;
|
||||||
void power();
|
auto bus_read(uint32 addr, uint32 size) -> uint32;
|
||||||
|
auto bus_write(uint32 addr, uint32 size, uint32 word) -> void;
|
||||||
|
|
||||||
uint8 read(uint32 addr);
|
auto keypad_run() -> void;
|
||||||
void write(uint32 addr, uint8 byte);
|
auto power() -> void;
|
||||||
|
|
||||||
uint32 iwram_read(uint32 addr, uint32 size);
|
|
||||||
void iwram_write(uint32 addr, uint32 size, uint32 word);
|
|
||||||
|
|
||||||
uint32 ewram_read(uint32 addr, uint32 size);
|
|
||||||
void ewram_write(uint32 addr, uint32 size, uint32 word);
|
|
||||||
|
|
||||||
void dma_run();
|
|
||||||
void dma_transfer(Registers::DMA &dma);
|
|
||||||
void dma_vblank();
|
|
||||||
void dma_hblank();
|
|
||||||
void dma_hdma();
|
|
||||||
|
|
||||||
void timer_step(unsigned clocks);
|
|
||||||
void timer_increment(unsigned n);
|
|
||||||
void timer_fifo_run(unsigned n);
|
|
||||||
|
|
||||||
void serialize(serializer&);
|
|
||||||
CPU();
|
CPU();
|
||||||
~CPU();
|
~CPU();
|
||||||
|
|
||||||
|
//mmio.cpp
|
||||||
|
auto read(uint32 addr) -> uint8;
|
||||||
|
auto write(uint32 addr, uint8 byte) -> void;
|
||||||
|
|
||||||
|
auto iwram_read(uint32 addr, uint32 size) -> uint32;
|
||||||
|
auto iwram_write(uint32 addr, uint32 size, uint32 word) -> void;
|
||||||
|
|
||||||
|
auto ewram_read(uint32 addr, uint32 size) -> uint32;
|
||||||
|
auto ewram_write(uint32 addr, uint32 size, uint32 word) -> void;
|
||||||
|
|
||||||
|
//dma.cpp
|
||||||
|
auto dma_run() -> void;
|
||||||
|
auto dma_exec(Registers::DMA& dma) -> void;
|
||||||
|
auto dma_vblank() -> void;
|
||||||
|
auto dma_hblank() -> void;
|
||||||
|
auto dma_hdma() -> void;
|
||||||
|
|
||||||
|
//timer.cpp
|
||||||
|
auto timer_step(unsigned clocks) -> void;
|
||||||
|
auto timer_increment(unsigned n) -> void;
|
||||||
|
auto timer_fifo_run(unsigned n) -> void;
|
||||||
|
|
||||||
|
//serialization.cpp
|
||||||
|
auto serialize(serializer&) -> void;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CPU cpu;
|
extern CPU cpu;
|
||||||
|
|
|
@ -1,60 +1,70 @@
|
||||||
void CPU::dma_run() {
|
auto CPU::dma_run() -> void {
|
||||||
for(unsigned n = 0; n < 4; n++) {
|
while(true) {
|
||||||
auto& dma = regs.dma[n];
|
bool transferred = false;
|
||||||
if(dma.pending) {
|
for(auto n : range(4)) {
|
||||||
dma.pending = false;
|
auto& dma = regs.dma[n];
|
||||||
dma_transfer(dma);
|
if(dma.pending) {
|
||||||
if(dma.control.irq) regs.irq.flag.dma[n] = 1;
|
dma_exec(dma);
|
||||||
if(dma.control.drq && n == 3) regs.irq.flag.cartridge = 1;
|
if(dma.control.irq) regs.irq.flag.dma[n] = 1;
|
||||||
|
if(dma.control.drq && n == 3) regs.irq.flag.cartridge = 1;
|
||||||
|
transferred = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if(!transferred) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::dma_transfer(Registers::DMA& dma) {
|
auto CPU::dma_exec(Registers::DMA& dma) -> void {
|
||||||
unsigned size = dma.control.size ? Word : Half;
|
unsigned size = dma.control.size ? Word : Half;
|
||||||
unsigned seek = dma.control.size ? 4 : 2;
|
unsigned seek = dma.control.size ? 4 : 2;
|
||||||
|
|
||||||
sequential() = false;
|
if(dma.run.length == dma.length) {
|
||||||
do {
|
idle();
|
||||||
step(bus.wait(dma.run.source, size));
|
idle();
|
||||||
uint32 word = bus.read(dma.run.source, size);
|
sequential() = false;
|
||||||
|
} else {
|
||||||
step(bus.wait(dma.run.target, size));
|
|
||||||
bus.write(dma.run.target, size, word);
|
|
||||||
|
|
||||||
sequential() = true;
|
sequential() = true;
|
||||||
|
}
|
||||||
|
|
||||||
switch(dma.control.sourcemode) {
|
step(bus.wait(dma.run.source, size));
|
||||||
case 0: dma.run.source += seek; break;
|
uint32 word = bus.read(dma.run.source, size);
|
||||||
case 1: dma.run.source -= seek; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(dma.control.targetmode) {
|
step(bus.wait(dma.run.target, size));
|
||||||
case 0: dma.run.target += seek; break;
|
bus.write(dma.run.target, size, word);
|
||||||
case 1: dma.run.target -= seek; break;
|
|
||||||
case 3: dma.run.target += seek; break;
|
|
||||||
}
|
|
||||||
} while(--dma.run.length);
|
|
||||||
sequential() = false;
|
|
||||||
|
|
||||||
if(dma.control.targetmode == 3) dma.run.target = dma.target;
|
switch(dma.control.sourcemode) {
|
||||||
if(dma.control.repeat == 1) dma.run.length = dma.length;
|
case 0: dma.run.source += seek; break;
|
||||||
if(dma.control.repeat == 0) dma.control.enable = false;
|
case 1: dma.run.source -= seek; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(dma.control.targetmode) {
|
||||||
|
case 0: dma.run.target += seek; break;
|
||||||
|
case 1: dma.run.target -= seek; break;
|
||||||
|
case 3: dma.run.target += seek; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(--dma.run.length == 0) {
|
||||||
|
dma.pending = false;
|
||||||
|
if(dma.control.targetmode == 3) dma.run.target = dma.target;
|
||||||
|
if(dma.control.repeat == 1) dma.run.length = dma.length;
|
||||||
|
if(dma.control.repeat == 0) dma.control.enable = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::dma_vblank() {
|
auto CPU::dma_vblank() -> void {
|
||||||
for(auto& dma : regs.dma) {
|
for(auto& dma : regs.dma) {
|
||||||
if(dma.control.enable && dma.control.timingmode == 1) dma.pending = true;
|
if(dma.control.enable && dma.control.timingmode == 1) dma.pending = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::dma_hblank() {
|
auto CPU::dma_hblank() -> void {
|
||||||
for(auto& dma : regs.dma) {
|
for(auto& dma : regs.dma) {
|
||||||
if(dma.control.enable && dma.control.timingmode == 2) dma.pending = true;
|
if(dma.control.enable && dma.control.timingmode == 2) dma.pending = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::dma_hdma() {
|
auto CPU::dma_hdma() -> void {
|
||||||
auto& dma = regs.dma[3];
|
auto& dma = regs.dma[3];
|
||||||
if(dma.control.enable && dma.control.timingmode == 3) dma.pending = true;
|
if(dma.control.enable && dma.control.timingmode == 3) dma.pending = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
uint32 CPU::iwram_read(uint32 addr, uint32 size) {
|
auto CPU::iwram_read(uint32 addr, uint32 size) -> uint32 {
|
||||||
if(regs.memory.control.disable) return cpu.pipeline.fetch.instruction;
|
if(regs.memory.control.disable) return cpu.pipeline.fetch.instruction;
|
||||||
|
|
||||||
if(size == Word) return iwram_read(addr &~ 2, Half) << 0 | iwram_read(addr | 2, Half) << 16;
|
if(size == Word) return iwram_read(addr &~ 2, Half) << 0 | iwram_read(addr | 2, Half) << 16;
|
||||||
|
@ -7,7 +7,7 @@ uint32 CPU::iwram_read(uint32 addr, uint32 size) {
|
||||||
return iwram[addr & 0x7fff];
|
return iwram[addr & 0x7fff];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::iwram_write(uint32 addr, uint32 size, uint32 word) {
|
auto CPU::iwram_write(uint32 addr, uint32 size, uint32 word) -> void {
|
||||||
if(regs.memory.control.disable) return;
|
if(regs.memory.control.disable) return;
|
||||||
|
|
||||||
if(size == Word) {
|
if(size == Word) {
|
||||||
|
@ -25,7 +25,7 @@ void CPU::iwram_write(uint32 addr, uint32 size, uint32 word) {
|
||||||
iwram[addr & 0x7fff] = word;
|
iwram[addr & 0x7fff] = word;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 CPU::ewram_read(uint32 addr, uint32 size) {
|
auto CPU::ewram_read(uint32 addr, uint32 size) -> uint32 {
|
||||||
if(regs.memory.control.disable) return cpu.pipeline.fetch.instruction;
|
if(regs.memory.control.disable) return cpu.pipeline.fetch.instruction;
|
||||||
if(regs.memory.control.ewram == false) return iwram_read(addr, size);
|
if(regs.memory.control.ewram == false) return iwram_read(addr, size);
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ uint32 CPU::ewram_read(uint32 addr, uint32 size) {
|
||||||
return ewram[addr & 0x3ffff];
|
return ewram[addr & 0x3ffff];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::ewram_write(uint32 addr, uint32 size, uint32 word) {
|
auto CPU::ewram_write(uint32 addr, uint32 size, uint32 word) -> void {
|
||||||
if(regs.memory.control.disable) return;
|
if(regs.memory.control.disable) return;
|
||||||
if(regs.memory.control.ewram == false) return iwram_write(addr, size, word);
|
if(regs.memory.control.ewram == false) return iwram_write(addr, size, word);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
uint8 CPU::read(uint32 addr) {
|
auto CPU::read(uint32 addr) -> uint8 {
|
||||||
uint8 result = 0;
|
uint8 result = 0;
|
||||||
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
|
@ -137,7 +137,7 @@ uint8 CPU::read(uint32 addr) {
|
||||||
return 0u;
|
return 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::write(uint32 addr, uint8 byte) {
|
auto CPU::write(uint32 addr, uint8 byte) -> void {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
|
|
||||||
//DMA0SAD
|
//DMA0SAD
|
||||||
|
|
|
@ -11,7 +11,7 @@ CPU::Registers::DMAControl::operator uint16() const {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 CPU::Registers::DMAControl::operator=(uint16 source) {
|
auto CPU::Registers::DMAControl::operator=(uint16 source) -> uint16 {
|
||||||
targetmode = source >> 5;
|
targetmode = source >> 5;
|
||||||
sourcemode = source >> 7;
|
sourcemode = source >> 7;
|
||||||
repeat = source >> 9;
|
repeat = source >> 9;
|
||||||
|
@ -32,7 +32,7 @@ CPU::Registers::TimerControl::operator uint16() const {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 CPU::Registers::TimerControl::operator=(uint16 source) {
|
auto CPU::Registers::TimerControl::operator=(uint16 source) -> uint16 {
|
||||||
frequency = source >> 0;
|
frequency = source >> 0;
|
||||||
cascade = source >> 2;
|
cascade = source >> 2;
|
||||||
irq = source >> 6;
|
irq = source >> 6;
|
||||||
|
@ -52,7 +52,7 @@ CPU::Registers::SerialControl::operator uint16() const {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 CPU::Registers::SerialControl::operator=(uint16 source) {
|
auto CPU::Registers::SerialControl::operator=(uint16 source) -> uint16 {
|
||||||
shiftclockselect = source >> 0;
|
shiftclockselect = source >> 0;
|
||||||
shiftclockfrequency = source >> 1;
|
shiftclockfrequency = source >> 1;
|
||||||
transferenablereceive = source >> 2;
|
transferenablereceive = source >> 2;
|
||||||
|
@ -80,7 +80,7 @@ CPU::Registers::KeypadControl::operator uint16() const {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 CPU::Registers::KeypadControl::operator=(uint16 source) {
|
auto CPU::Registers::KeypadControl::operator=(uint16 source) -> uint16 {
|
||||||
flag[0] = source >> 0;
|
flag[0] = source >> 0;
|
||||||
flag[1] = source >> 1;
|
flag[1] = source >> 1;
|
||||||
flag[2] = source >> 2;
|
flag[2] = source >> 2;
|
||||||
|
@ -111,7 +111,7 @@ CPU::Registers::JoybusSettings::operator uint16() const {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 CPU::Registers::JoybusSettings::operator=(uint16 source) {
|
auto CPU::Registers::JoybusSettings::operator=(uint16 source) -> uint16 {
|
||||||
sc = source >> 0;
|
sc = source >> 0;
|
||||||
sd = source >> 1;
|
sd = source >> 1;
|
||||||
si = source >> 2;
|
si = source >> 2;
|
||||||
|
@ -134,7 +134,7 @@ CPU::Registers::JoybusControl::operator uint16() const {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 CPU::Registers::JoybusControl::operator=(uint16 source) {
|
auto CPU::Registers::JoybusControl::operator=(uint16 source) -> uint16 {
|
||||||
resetsignal = source >> 0;
|
resetsignal = source >> 0;
|
||||||
receivecomplete = source >> 1;
|
receivecomplete = source >> 1;
|
||||||
sendcomplete = source >> 2;
|
sendcomplete = source >> 2;
|
||||||
|
@ -150,7 +150,7 @@ CPU::Registers::JoybusStatus::operator uint16() const {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 CPU::Registers::JoybusStatus::operator=(uint16 source) {
|
auto CPU::Registers::JoybusStatus::operator=(uint16 source) -> uint16 {
|
||||||
receiveflag = source >> 1;
|
receiveflag = source >> 1;
|
||||||
sendflag = source >> 3;
|
sendflag = source >> 3;
|
||||||
generalflag = source >> 4;
|
generalflag = source >> 4;
|
||||||
|
@ -176,7 +176,7 @@ CPU::Registers::Interrupt::operator uint16() const {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 CPU::Registers::Interrupt::operator=(uint16 source) {
|
auto CPU::Registers::Interrupt::operator=(uint16 source) -> uint16 {
|
||||||
vblank = source >> 0;
|
vblank = source >> 0;
|
||||||
hblank = source >> 1;
|
hblank = source >> 1;
|
||||||
vcoincidence = source >> 2;
|
vcoincidence = source >> 2;
|
||||||
|
@ -209,7 +209,7 @@ CPU::Registers::WaitControl::operator uint16() const {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 CPU::Registers::WaitControl::operator=(uint16 source) {
|
auto CPU::Registers::WaitControl::operator=(uint16 source) -> uint16 {
|
||||||
nwait[3] = (source >> 0) & 3;
|
nwait[3] = (source >> 0) & 3;
|
||||||
nwait[0] = (source >> 2) & 3;
|
nwait[0] = (source >> 2) & 3;
|
||||||
swait[0] = (source >> 4) & 1;
|
swait[0] = (source >> 4) & 1;
|
||||||
|
@ -234,7 +234,7 @@ CPU::Registers::MemoryControl::operator uint32() const {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 CPU::Registers::MemoryControl::operator=(uint32 source) {
|
auto CPU::Registers::MemoryControl::operator=(uint32 source) -> uint32 {
|
||||||
disable = source >> 0;
|
disable = source >> 0;
|
||||||
unknown1 = source >> 1;
|
unknown1 = source >> 1;
|
||||||
ewram = source >> 5;
|
ewram = source >> 5;
|
||||||
|
|
|
@ -10,8 +10,8 @@ struct Registers {
|
||||||
uint1 enable;
|
uint1 enable;
|
||||||
|
|
||||||
operator uint16() const;
|
operator uint16() const;
|
||||||
uint16 operator=(uint16 source);
|
auto operator=(uint16 source) -> uint16;
|
||||||
DMAControl& operator=(const DMAControl&) = delete;
|
auto operator=(const DMAControl&) -> DMAControl& = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DMA {
|
struct DMA {
|
||||||
|
@ -36,8 +36,8 @@ struct Registers {
|
||||||
uint1 enable;
|
uint1 enable;
|
||||||
|
|
||||||
operator uint16() const;
|
operator uint16() const;
|
||||||
uint16 operator=(uint16 source);
|
auto operator=(uint16 source) -> uint16;
|
||||||
TimerControl& operator=(const TimerControl&) = delete;
|
auto operator=(const TimerControl&) -> TimerControl& = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Timer {
|
struct Timer {
|
||||||
|
@ -56,8 +56,8 @@ struct Registers {
|
||||||
uint1 irqenable;
|
uint1 irqenable;
|
||||||
|
|
||||||
operator uint16() const;
|
operator uint16() const;
|
||||||
uint16 operator=(uint16 source);
|
auto operator=(uint16 source) -> uint16;
|
||||||
SerialControl& operator=(const SerialControl&) = delete;
|
auto operator=(const SerialControl&) -> SerialControl& = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Serial {
|
struct Serial {
|
||||||
|
@ -72,8 +72,8 @@ struct Registers {
|
||||||
uint1 condition;
|
uint1 condition;
|
||||||
|
|
||||||
operator uint16() const;
|
operator uint16() const;
|
||||||
uint16 operator=(uint16 source);
|
auto operator=(uint16 source) -> uint16;
|
||||||
KeypadControl& operator=(const KeypadControl&) = delete;
|
auto operator=(const KeypadControl&) -> KeypadControl& = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Keypad {
|
struct Keypad {
|
||||||
|
@ -93,8 +93,8 @@ struct Registers {
|
||||||
uint2 mode;
|
uint2 mode;
|
||||||
|
|
||||||
operator uint16() const;
|
operator uint16() const;
|
||||||
uint16 operator=(uint16 source);
|
auto operator=(uint16 source) -> uint16;
|
||||||
JoybusSettings& operator=(const JoybusSettings&) = delete;
|
auto operator=(const JoybusSettings&) -> JoybusSettings& = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JoybusControl {
|
struct JoybusControl {
|
||||||
|
@ -104,8 +104,8 @@ struct Registers {
|
||||||
uint1 irqenable;
|
uint1 irqenable;
|
||||||
|
|
||||||
operator uint16() const;
|
operator uint16() const;
|
||||||
uint16 operator=(uint16 source);
|
auto operator=(uint16 source) -> uint16;
|
||||||
JoybusControl& operator=(const JoybusControl&) = delete;
|
auto operator=(const JoybusControl&) -> JoybusControl& = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JoybusStatus {
|
struct JoybusStatus {
|
||||||
|
@ -114,8 +114,8 @@ struct Registers {
|
||||||
uint2 generalflag;
|
uint2 generalflag;
|
||||||
|
|
||||||
operator uint16() const;
|
operator uint16() const;
|
||||||
uint16 operator=(uint16 source);
|
auto operator=(uint16 source) -> uint16;
|
||||||
JoybusStatus& operator=(const JoybusStatus&) = delete;
|
auto operator=(const JoybusStatus&) -> JoybusStatus& = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Joybus {
|
struct Joybus {
|
||||||
|
@ -139,8 +139,8 @@ struct Registers {
|
||||||
uint1 cartridge;
|
uint1 cartridge;
|
||||||
|
|
||||||
operator uint16() const;
|
operator uint16() const;
|
||||||
uint16 operator=(uint16 source);
|
auto operator=(uint16 source) -> uint16;
|
||||||
Interrupt& operator=(const Interrupt&) = delete;
|
auto operator=(const Interrupt&) -> Interrupt& = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IRQ {
|
struct IRQ {
|
||||||
|
@ -156,8 +156,8 @@ struct Registers {
|
||||||
uint1 gametype;
|
uint1 gametype;
|
||||||
|
|
||||||
operator uint16() const;
|
operator uint16() const;
|
||||||
uint16 operator=(uint16 source);
|
auto operator=(uint16 source) -> uint16;
|
||||||
WaitControl& operator=(const WaitControl&) = delete;
|
auto operator=(const WaitControl&) -> WaitControl& = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Wait {
|
struct Wait {
|
||||||
|
@ -172,8 +172,8 @@ struct Registers {
|
||||||
uint4 unknown2;
|
uint4 unknown2;
|
||||||
|
|
||||||
operator uint32() const;
|
operator uint32() const;
|
||||||
uint32 operator=(uint32 source);
|
auto operator=(uint32 source) -> uint32;
|
||||||
MemoryControl& operator=(const MemoryControl&) = delete;
|
auto operator=(const MemoryControl&) -> MemoryControl& = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Memory {
|
struct Memory {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
void CPU::serialize(serializer& s) {
|
auto CPU::serialize(serializer& s) -> void {
|
||||||
ARM::serialize(s);
|
ARM::serialize(s);
|
||||||
Thread::serialize(s);
|
Thread::serialize(s);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
void CPU::timer_step(unsigned clocks) {
|
auto CPU::timer_step(unsigned clocks) -> void {
|
||||||
for(unsigned c = 0; c < clocks; c++) {
|
for(unsigned c = 0; c < clocks; c++) {
|
||||||
for(unsigned n = 0; n < 4; n++) {
|
for(unsigned n = 0; n < 4; n++) {
|
||||||
auto& timer = regs.timer[n];
|
auto& timer = regs.timer[n];
|
||||||
|
@ -14,7 +14,7 @@ void CPU::timer_step(unsigned clocks) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::timer_increment(unsigned n) {
|
auto CPU::timer_increment(unsigned n) -> void {
|
||||||
auto& timer = regs.timer[n];
|
auto& timer = regs.timer[n];
|
||||||
if(++timer.period == 0) {
|
if(++timer.period == 0) {
|
||||||
timer.period = timer.reload;
|
timer.period = timer.reload;
|
||||||
|
@ -30,7 +30,7 @@ void CPU::timer_increment(unsigned n) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::timer_fifo_run(unsigned n) {
|
auto CPU::timer_fifo_run(unsigned n) -> void {
|
||||||
apu.fifo[n].read();
|
apu.fifo[n].read();
|
||||||
if(apu.fifo[n].size > 16) return;
|
if(apu.fifo[n].size > 16) return;
|
||||||
|
|
||||||
|
|
|
@ -30,12 +30,12 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(hiro),gtk)
|
ifeq ($(hiro),gtk)
|
||||||
hiroflags = $(cppflags) $(flags) -DHIRO_GTK `pkg-config --cflags gtk+-2.0 gtksourceview-2.0`
|
hiroflags = $(cppflags) $(flags) -DHIRO_GTK $(shell pkg-config --cflags gtk+-2.0 gtksourceview-2.0)
|
||||||
hirolink = `pkg-config --libs gtk+-2.0 gtksourceview-2.0` -lX11
|
hirolink = -lX11 $(shell pkg-config --libs gtk+-2.0 gtksourceview-2.0)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(hiro),qt)
|
ifeq ($(hiro),qt)
|
||||||
hiroflags = $(cppflags) $(flags) -DHIRO_QT `pkg-config --cflags QtCore QtGui`
|
hiroflags = $(cppflags) $(flags) -DHIRO_QT $(shell pkg-config --cflags QtCore QtGui)
|
||||||
hirolink = `pkg-config --libs QtCore QtGui` -lX11
|
hirolink = -lX11 $(shell pkg-config --libs QtCore QtGui)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -182,6 +182,7 @@ auto pWindow::construct() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::destruct() -> void {
|
auto pWindow::destruct() -> void {
|
||||||
|
gtk_widget_destroy(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pWindow::append(sLayout layout) -> void {
|
auto pWindow::append(sLayout layout) -> void {
|
||||||
|
|
|
@ -307,7 +307,7 @@ auto pListView::onCustomDraw(LPARAM lparam) -> LRESULT {
|
||||||
utf16_t wText(text);
|
utf16_t wText(text);
|
||||||
SetBkMode(hdc, TRANSPARENT);
|
SetBkMode(hdc, TRANSPARENT);
|
||||||
SetTextColor(hdc, selected ? GetSysColor(COLOR_HIGHLIGHTTEXT) : CreateRGB(_foregroundColor(row, column)));
|
SetTextColor(hdc, selected ? GetSysColor(COLOR_HIGHLIGHTTEXT) : CreateRGB(_foregroundColor(row, column)));
|
||||||
auto style = DT_SINGLELINE | DT_END_ELLIPSIS;
|
auto style = DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS;
|
||||||
style |= halign < 0.333 ? DT_LEFT : halign > 0.666 ? DT_RIGHT : DT_CENTER;
|
style |= halign < 0.333 ? DT_LEFT : halign > 0.666 ? DT_RIGHT : DT_CENTER;
|
||||||
style |= valign < 0.333 ? DT_TOP : valign > 0.666 ? DT_BOTTOM : DT_VCENTER;
|
style |= valign < 0.333 ? DT_TOP : valign > 0.666 ? DT_BOTTOM : DT_VCENTER;
|
||||||
rc.right -= 2;
|
rc.right -= 2;
|
||||||
|
|
|
@ -45,10 +45,10 @@ auto ARM::sub(uint32 source, uint32 modify, bool carry) -> uint32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ARM::mul(uint32 product, uint32 multiplicand, uint32 multiplier) -> uint32 {
|
auto ARM::mul(uint32 product, uint32 multiplicand, uint32 multiplier) -> uint32 {
|
||||||
if((multiplier & 0xffffff00) == 0x00000000 || (multiplier & 0xffffff00 == 0xffffff00)) step(1);
|
idle();
|
||||||
else if((multiplier & 0xffff0000) == 0x00000000 || (multiplier & 0xffff0000 == 0xffff0000)) step(2);
|
if((multiplier & 0xffffff00) != 0x00000000 && (multiplier & 0xffffff00) != 0xffffff00) idle();
|
||||||
else if((multiplier & 0xff000000) == 0x00000000 || (multiplier & 0xff000000 == 0xff000000)) step(3);
|
if((multiplier & 0xffff0000) != 0x00000000 && (multiplier & 0xffff0000) != 0xffff0000) idle();
|
||||||
else step(4);
|
if((multiplier & 0xff000000) != 0x00000000 && (multiplier & 0xff000000) != 0xff000000) idle();
|
||||||
|
|
||||||
product += multiplicand * multiplier;
|
product += multiplicand * multiplier;
|
||||||
|
|
||||||
|
|
|
@ -521,9 +521,9 @@ auto ARM::arm_op_move_multiple() {
|
||||||
|
|
||||||
if(usr) processor.setMode(Processor::Mode::USR);
|
if(usr) processor.setMode(Processor::Mode::USR);
|
||||||
|
|
||||||
sequential() = false;
|
|
||||||
for(unsigned m = 0; m < 16; m++) {
|
for(unsigned m = 0; m < 16; m++) {
|
||||||
if(list & (1 << m)) {
|
sequential() = false;
|
||||||
|
if(list & 1 << m) {
|
||||||
if(l == 1) r(m) = read(rn, Word);
|
if(l == 1) r(m) = read(rn, Word);
|
||||||
if(l == 0) write(rn, Word, r(m));
|
if(l == 0) write(rn, Word, r(m));
|
||||||
rn += 4;
|
rn += 4;
|
||||||
|
|
|
@ -5,7 +5,7 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
rubyflags += $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
|
rubyflags += $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
|
||||||
rubyflags += $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`)
|
rubyflags += $(if $(findstring .sdl,$(ruby)),$(shell sdl-config --cflags))
|
||||||
|
|
||||||
rubylink =
|
rubylink =
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ rubylink += $(if $(findstring audio.xaudio2,$(ruby)),-lole32)
|
||||||
rubylink += $(if $(findstring input.udev,$(ruby)),-ludev)
|
rubylink += $(if $(findstring input.udev,$(ruby)),-ludev)
|
||||||
rubylink += $(if $(findstring input.windows,$(ruby)),-ldinput8 -ldxguid)
|
rubylink += $(if $(findstring input.windows,$(ruby)),-ldinput8 -ldxguid)
|
||||||
|
|
||||||
rubylink += $(if $(findstring .sdl,$(ruby)),`sdl-config --libs`)
|
rubylink += $(if $(findstring .sdl,$(ruby)),$(shell sdl-config --libs))
|
||||||
|
|
||||||
ifeq ($(platform),windows)
|
ifeq ($(platform),windows)
|
||||||
rubylink += $(if $(findstring audio.openal,$(ruby)),-lopenal32)
|
rubylink += $(if $(findstring audio.openal,$(ruby)),-lopenal32)
|
||||||
|
|
|
@ -54,7 +54,10 @@ struct VideoXv : Video {
|
||||||
auto cap(const string& name) -> bool {
|
auto cap(const string& name) -> bool {
|
||||||
if(name == Video::Handle) return true;
|
if(name == Video::Handle) return true;
|
||||||
if(name == Video::Synchronize) {
|
if(name == Video::Synchronize) {
|
||||||
return XInternAtom(XOpenDisplay(0), "XV_SYNC_TO_VBLANK", true) != None;
|
Display* display = XOpenDisplay(nullptr);
|
||||||
|
bool result = XInternAtom(display, "XV_SYNC_TO_VBLANK", true) != None;
|
||||||
|
XCloseDisplay(display);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -72,14 +75,16 @@ struct VideoXv : Video {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(name == Video::Synchronize && value.is<bool>()) {
|
if(name == Video::Synchronize && value.is<bool>()) {
|
||||||
Display* display = XOpenDisplay(0);
|
bool result = false;
|
||||||
|
Display* display = XOpenDisplay(nullptr);
|
||||||
Atom atom = XInternAtom(display, "XV_SYNC_TO_VBLANK", true);
|
Atom atom = XInternAtom(display, "XV_SYNC_TO_VBLANK", true);
|
||||||
if(atom != None && device.port >= 0) {
|
if(atom != None && device.port >= 0) {
|
||||||
settings.synchronize = value.get<bool>();
|
settings.synchronize = value.get<bool>();
|
||||||
XvSetPortAttribute(display, device.port, atom, settings.synchronize);
|
XvSetPortAttribute(display, device.port, atom, settings.synchronize);
|
||||||
return true;
|
result = true;
|
||||||
}
|
}
|
||||||
return false;
|
XCloseDisplay(display);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -92,7 +97,7 @@ struct VideoXv : Video {
|
||||||
|
|
||||||
XShmDetach(device.display, &device.shminfo);
|
XShmDetach(device.display, &device.shminfo);
|
||||||
shmdt(device.shminfo.shmaddr);
|
shmdt(device.shminfo.shmaddr);
|
||||||
shmctl(device.shminfo.shmid, IPC_RMID, NULL);
|
shmctl(device.shminfo.shmid, IPC_RMID, nullptr);
|
||||||
XFree(device.image);
|
XFree(device.image);
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
|
|
||||||
|
@ -161,7 +166,7 @@ struct VideoXv : Video {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto init() -> bool {
|
auto init() -> bool {
|
||||||
device.display = XOpenDisplay(0);
|
device.display = XOpenDisplay(nullptr);
|
||||||
|
|
||||||
if(!XShmQueryExtension(device.display)) {
|
if(!XShmQueryExtension(device.display)) {
|
||||||
fprintf(stderr, "VideoXv: XShm extension not found.\n");
|
fprintf(stderr, "VideoXv: XShm extension not found.\n");
|
||||||
|
@ -202,7 +207,7 @@ struct VideoXv : Video {
|
||||||
visualtemplate.depth = device.depth;
|
visualtemplate.depth = device.depth;
|
||||||
visualtemplate.visual = 0;
|
visualtemplate.visual = 0;
|
||||||
signed visualmatches = 0;
|
signed visualmatches = 0;
|
||||||
XVisualInfo *visualinfo = XGetVisualInfo(device.display, VisualIDMask | VisualScreenMask | VisualDepthMask, &visualtemplate, &visualmatches);
|
XVisualInfo* visualinfo = XGetVisualInfo(device.display, VisualIDMask | VisualScreenMask | VisualDepthMask, &visualtemplate, &visualmatches);
|
||||||
if(visualmatches < 1 || !visualinfo->visual) {
|
if(visualmatches < 1 || !visualinfo->visual) {
|
||||||
if(visualinfo) XFree(visualinfo);
|
if(visualinfo) XFree(visualinfo);
|
||||||
fprintf(stderr, "VideoXv: unable to find Xv-compatible visual.\n");
|
fprintf(stderr, "VideoXv: unable to find Xv-compatible visual.\n");
|
||||||
|
@ -323,7 +328,7 @@ struct VideoXv : Video {
|
||||||
auto term() -> void {
|
auto term() -> void {
|
||||||
XShmDetach(device.display, &device.shminfo);
|
XShmDetach(device.display, &device.shminfo);
|
||||||
shmdt(device.shminfo.shmaddr);
|
shmdt(device.shminfo.shmaddr);
|
||||||
shmctl(device.shminfo.shmid, IPC_RMID, NULL);
|
shmctl(device.shminfo.shmid, IPC_RMID, nullptr);
|
||||||
XFree(device.image);
|
XFree(device.image);
|
||||||
|
|
||||||
if(device.window) {
|
if(device.window) {
|
||||||
|
@ -336,6 +341,11 @@ struct VideoXv : Video {
|
||||||
device.colormap = 0;
|
device.colormap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(device.display) {
|
||||||
|
XCloseDisplay(device.display);
|
||||||
|
device.display = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if(buffer) { delete[] buffer; buffer = nullptr; }
|
if(buffer) { delete[] buffer; buffer = nullptr; }
|
||||||
if(ytable) { delete[] ytable; ytable = nullptr; }
|
if(ytable) { delete[] ytable; ytable = nullptr; }
|
||||||
if(utable) { delete[] utable; utable = nullptr; }
|
if(utable) { delete[] utable; utable = nullptr; }
|
||||||
|
|
Loading…
Reference in New Issue