mirror of https://github.com/bsnes-emu/bsnes.git
Update to v094r34 release.
byuu says: Fixes SuperFX fmult, lmult timings; rambr, bramr and clsr assignment masking. Implements true GBA ROM prefetch (buggy, lower test score, but runs Mario & Luigi without crashing on battles anymore.)
This commit is contained in:
parent
4c9266d18f
commit
7ff7f64482
|
@ -8,7 +8,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "094.33";
|
||||
static const string Version = "094.34";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
@ -33,7 +33,7 @@ template<typename R, typename... P> struct hook<R (P...)> {
|
|||
|
||||
auto operator()(P... p) const -> R {
|
||||
#if defined(DEBUGGER)
|
||||
if(callback) return callback(std::forward<P>(p)...);
|
||||
if(callback) return callback(forward<P>(p)...);
|
||||
#endif
|
||||
return R();
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ struct Interface {
|
|||
unsigned id;
|
||||
unsigned type; //0 = digital, 1 = analog (relative), 2 = rumble
|
||||
string name;
|
||||
uintptr_t guid;
|
||||
uintptr_t guid; //user data field
|
||||
};
|
||||
vector<Input> input;
|
||||
vector<unsigned> order;
|
||||
|
@ -57,7 +57,6 @@ struct Interface {
|
|||
virtual auto inputRumble(unsigned, unsigned, unsigned, bool) -> void {}
|
||||
virtual auto dipSettings(const Markup::Node&) -> unsigned { return 0; }
|
||||
virtual auto path(unsigned) -> string { return ""; }
|
||||
virtual auto server() -> string { return ""; }
|
||||
virtual auto notify(string text) -> void { print(text, "\n"); }
|
||||
};
|
||||
Bind* bind = nullptr;
|
||||
|
@ -73,7 +72,6 @@ struct Interface {
|
|||
auto inputRumble(unsigned port, unsigned device, unsigned input, bool enable) -> void { return bind->inputRumble(port, device, input, enable); }
|
||||
auto dipSettings(const Markup::Node& node) -> unsigned { return bind->dipSettings(node); }
|
||||
auto path(unsigned group) -> string { return bind->path(group); }
|
||||
auto server() -> string { return bind->server(); }
|
||||
template<typename... P> auto notify(P&&... p) -> void { return bind->notify({forward<P>(p)...}); }
|
||||
|
||||
//information
|
||||
|
|
107
gba/cpu/cpu.cpp
107
gba/cpu/cpu.cpp
|
@ -63,6 +63,72 @@ auto CPU::step(unsigned clocks) -> void {
|
|||
sync_step(clocks);
|
||||
}
|
||||
|
||||
auto CPU::bus_idle(uint32 addr) -> void {
|
||||
step(1);
|
||||
prefetch_step(1);
|
||||
}
|
||||
|
||||
auto CPU::bus_read(uint32 addr, uint32 size, bool mode) -> uint32 {
|
||||
unsigned wait = bus.wait(addr, size, mode);
|
||||
|
||||
if(addr < 0x0800'0000) {
|
||||
unsigned word = bus.read(addr, size);
|
||||
step(wait);
|
||||
prefetch_step(wait);
|
||||
return word;
|
||||
}
|
||||
|
||||
if(addr < 0x0e00'0000) {
|
||||
if(regs.wait.control.prefetch) {
|
||||
if(mode == Nonsequential) prefetch_start(addr);
|
||||
unsigned word = prefetch_take();
|
||||
if(size == Byte) word = (addr & 1) ? (word >> 8) : (word & 0xff);
|
||||
if(size == Word) word |= prefetch_take() << 16;
|
||||
return word;
|
||||
}
|
||||
|
||||
unsigned word = cartridge.read(addr, size);
|
||||
step(wait);
|
||||
return word;
|
||||
}
|
||||
|
||||
if(addr < 0x1000'0000) {
|
||||
prefetch_stall();
|
||||
unsigned word = bus.read(addr, size);
|
||||
step(wait);
|
||||
return word;
|
||||
}
|
||||
|
||||
step(wait);
|
||||
prefetch_step(wait);
|
||||
return 0x0000'0000; //open bus?
|
||||
}
|
||||
|
||||
auto CPU::bus_write(uint32 addr, uint32 size, bool mode, uint32 word) -> void {
|
||||
unsigned wait = bus.wait(addr, size, mode);
|
||||
|
||||
if(addr < 0x0800'0000) {
|
||||
step(wait);
|
||||
prefetch_step(wait);
|
||||
return bus.write(addr, size, word);
|
||||
}
|
||||
|
||||
if(addr < 0x0e00'0000) {
|
||||
prefetch_stall();
|
||||
step(wait);
|
||||
return bus.write(addr, size, word);
|
||||
}
|
||||
|
||||
if(addr < 0x1000'0000) {
|
||||
prefetch_stall();
|
||||
step(wait);
|
||||
return bus.write(addr, size, word);
|
||||
}
|
||||
|
||||
step(wait);
|
||||
prefetch_step(wait);
|
||||
}
|
||||
|
||||
auto CPU::sync_step(unsigned clocks) -> void {
|
||||
ppu.clock -= clocks;
|
||||
if(ppu.clock < 0) co_switch(ppu.thread);
|
||||
|
@ -71,43 +137,6 @@ auto CPU::sync_step(unsigned clocks) -> void {
|
|||
if(apu.clock < 0) co_switch(apu.thread);
|
||||
}
|
||||
|
||||
auto CPU::bus_idle(uint32 addr) -> void {
|
||||
if(regs.wait.control.prefetch) prefetch_run();
|
||||
step(1);
|
||||
}
|
||||
|
||||
auto CPU::bus_read(uint32 addr, uint32 size, bool mode) -> uint32 {
|
||||
if(regs.wait.control.prefetch) {
|
||||
if((addr & 0x0fffffff) >= 0x08000000 && (addr & 0x0fffffff) <= 0x0dffffff) {
|
||||
if(auto word = prefetch_read(addr, size)) {
|
||||
step(1 + (size == Word));
|
||||
return *word;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned wait = bus.wait(addr, size, mode);
|
||||
unsigned word = bus.read(addr, size);
|
||||
step(wait);
|
||||
return word;
|
||||
}
|
||||
|
||||
auto CPU::bus_load(uint32 addr, uint32 size, bool mode) -> uint32 {
|
||||
if(regs.wait.control.prefetch) prefetch_run();
|
||||
return bus_read(addr, size, mode);
|
||||
}
|
||||
|
||||
auto CPU::bus_write(uint32 addr, uint32 size, bool mode, uint32 word) -> void {
|
||||
unsigned wait = bus.wait(addr, size, mode);
|
||||
step(wait);
|
||||
bus.write(addr, size, word);
|
||||
}
|
||||
|
||||
auto CPU::bus_store(uint32 addr, uint32 size, bool mode, uint32 word) -> void {
|
||||
if(regs.wait.control.prefetch) prefetch_run();
|
||||
return bus_write(addr, size, mode, word);
|
||||
}
|
||||
|
||||
auto CPU::keypad_run() -> void {
|
||||
if(regs.keypad.control.enable == false) return;
|
||||
|
||||
|
@ -122,7 +151,7 @@ auto CPU::keypad_run() -> void {
|
|||
}
|
||||
|
||||
auto CPU::power() -> void {
|
||||
create(CPU::Enter, 16777216);
|
||||
create(CPU::Enter, 16'777'216);
|
||||
|
||||
ARM::power();
|
||||
for(auto n : range( 32 * 1024)) iwram[n] = 0;
|
||||
|
@ -152,7 +181,7 @@ auto CPU::power() -> void {
|
|||
regs.postboot = 0;
|
||||
regs.mode = Registers::Mode::Normal;
|
||||
regs.clock = 0;
|
||||
regs.memory.control = 0x0d000020;
|
||||
regs.memory.control = 0x0d00'0020;
|
||||
|
||||
pending.dma.vblank = 0;
|
||||
pending.dma.hblank = 0;
|
||||
|
|
|
@ -12,15 +12,13 @@ struct CPU : Processor::ARM, Thread, MMIO {
|
|||
static auto Enter() -> void;
|
||||
|
||||
auto main() -> void;
|
||||
auto step(unsigned clocks) -> void;
|
||||
|
||||
auto step(unsigned clocks) -> void override;
|
||||
auto bus_idle(uint32 addr) -> void override;
|
||||
auto bus_read(uint32 addr, uint32 size, bool mode) -> uint32 override;
|
||||
auto bus_write(uint32 addr, uint32 size, bool mode, uint32 word) -> void override;
|
||||
|
||||
auto sync_step(unsigned clocks) -> void;
|
||||
|
||||
auto bus_idle(uint32 addr) -> void;
|
||||
auto bus_read(uint32 addr, uint32 size, bool mode) -> uint32;
|
||||
auto bus_load(uint32 addr, uint32 size, bool mode) -> uint32;
|
||||
auto bus_write(uint32 addr, uint32 size, bool mode, uint32 word) -> void;
|
||||
auto bus_store(uint32 addr, uint32 size, bool mode, uint32 word) -> void;
|
||||
|
||||
auto keypad_run() -> void;
|
||||
auto power() -> void;
|
||||
|
||||
|
|
|
@ -1,17 +1,43 @@
|
|||
auto CPU::prefetch_run() -> void {
|
||||
if(prefetch.slots == 8) return;
|
||||
prefetch.slots++;
|
||||
auto CPU::prefetch_stall() -> void {
|
||||
prefetch.stalled = true;
|
||||
}
|
||||
|
||||
auto CPU::prefetch_read(uint32 addr, uint32 size) -> maybe<uint32> {
|
||||
if(prefetch.slots >= (size == Word ? 2 : 1)) {
|
||||
prefetch.slots -= (size == Word ? 2 : 1);
|
||||
return cartridge.read(addr, size);
|
||||
auto CPU::prefetch_start(uint32 addr) -> void {
|
||||
prefetch.stalled = false;
|
||||
prefetch.slots = 0;
|
||||
prefetch.input = 0;
|
||||
prefetch.output = 0;
|
||||
prefetch.addr = addr;
|
||||
prefetch.wait = bus.wait(addr, Half, Nonsequential);
|
||||
}
|
||||
|
||||
auto CPU::prefetch_step(unsigned clocks) -> void {
|
||||
if(!regs.wait.control.prefetch || prefetch.stalled) return;
|
||||
|
||||
prefetch.wait -= clocks;
|
||||
while(prefetch.wait <= 0) {
|
||||
if(prefetch.slots < 8) {
|
||||
prefetch.slot[prefetch.output++] = cartridge.read(prefetch.addr, Half);
|
||||
prefetch.slots++;
|
||||
prefetch.addr += 2;
|
||||
}
|
||||
prefetch.wait += bus.wait(prefetch.addr, Half, Sequential);
|
||||
}
|
||||
prefetch.slots = 0;
|
||||
return nothing;
|
||||
}
|
||||
|
||||
auto CPU::prefetch_wait() -> void {
|
||||
step(prefetch.wait);
|
||||
prefetch_step(prefetch.wait);
|
||||
}
|
||||
|
||||
auto CPU::prefetch_take() -> uint16 {
|
||||
return 0;
|
||||
if(prefetch.slots) {
|
||||
step(1);
|
||||
prefetch_step(1);
|
||||
} else {
|
||||
prefetch_wait();
|
||||
}
|
||||
|
||||
prefetch.slots--;
|
||||
return prefetch.slot[prefetch.input++];
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
struct Prefetch {
|
||||
struct Slot {
|
||||
uint32 addr;
|
||||
uint16 half;
|
||||
} slot[8];
|
||||
uint16 slot[8] = {0};
|
||||
uint3 input = 0;
|
||||
uint3 output = 0;
|
||||
|
||||
bool stalled = true;
|
||||
unsigned slots = 0;
|
||||
signed wait = 0;
|
||||
uint32 addr = 0;
|
||||
} prefetch;
|
||||
|
||||
auto prefetch_run() -> void;
|
||||
auto prefetch_read(uint32 addr, uint32 size) -> maybe<uint32>;
|
||||
auto prefetch_stall() -> void;
|
||||
auto prefetch_start(uint32 addr) -> void;
|
||||
auto prefetch_step(unsigned clocks) -> void;
|
||||
auto prefetch_wait() -> void;
|
||||
auto prefetch_take() -> uint16;
|
||||
|
|
|
@ -221,6 +221,9 @@ auto CPU::Registers::WaitControl::operator=(uint16 source) -> uint16 {
|
|||
prefetch = (source >> 14) & 1;
|
||||
gametype = (source >> 15) & 1;
|
||||
swait[3] = nwait[3];
|
||||
|
||||
cpu.prefetch.stalled = true;
|
||||
|
||||
return operator uint16();
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ auto mMenuRadioItem::setChecked() -> type& {
|
|||
auto mMenuRadioItem::setGroup(sGroup group) -> type& {
|
||||
state.group = group;
|
||||
signal(setGroup, group);
|
||||
if(group && group->objects() == 1) setChecked();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ auto mRadioButton::setChecked() -> type& {
|
|||
auto mRadioButton::setGroup(sGroup group) -> type& {
|
||||
state.group = group;
|
||||
signal(setGroup, group);
|
||||
if(group && group->objects() == 1) setChecked();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ auto mRadioLabel::setChecked() -> type& {
|
|||
auto mRadioLabel::setGroup(sGroup group) -> type& {
|
||||
state.group = group;
|
||||
signal(setGroup, group);
|
||||
if(group && group->objects() == 1) setChecked();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ auto ARM::read(uint32 addr, uint32 size, bool mode) -> uint32 {
|
|||
|
||||
auto ARM::load(uint32 addr, uint32 size, bool mode) -> uint32 {
|
||||
if(processor.nonsequential) processor.nonsequential = false, mode = Nonsequential;
|
||||
uint32 word = bus_load(addr, size, mode);
|
||||
uint32 word = bus_read(addr, size, mode);
|
||||
|
||||
if(size == Half) { word &= 0xffff; word |= word << 16; }
|
||||
if(size == Byte) { word &= 0xff; word |= word << 8; word |= word << 16; }
|
||||
|
@ -63,7 +63,7 @@ auto ARM::store(uint32 addr, uint32 size, bool mode, uint32 word) -> void {
|
|||
if(size == Byte) { word &= 0xff; word |= word << 8; word |= word << 16; }
|
||||
|
||||
if(processor.nonsequential) processor.nonsequential = false, mode = Nonsequential;
|
||||
bus_store(addr, size, mode, word);
|
||||
bus_write(addr, size, mode, word);
|
||||
processor.nonsequential = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,7 @@ struct ARM {
|
|||
virtual auto step(unsigned clocks) -> void = 0;
|
||||
virtual auto bus_idle(uint32 addr) -> void = 0;
|
||||
virtual auto bus_read(uint32 addr, uint32 size, bool mode) -> uint32 = 0;
|
||||
virtual auto bus_load(uint32 addr, uint32 size, bool mode) -> uint32 = 0;
|
||||
virtual auto bus_write(uint32 addr, uint32 size, bool mode, uint32 word) -> void = 0;
|
||||
virtual auto bus_store(uint32 addr, uint32 size, bool mode, uint32 word) -> void = 0;
|
||||
|
||||
//arm.cpp
|
||||
auto power() -> void;
|
||||
|
|
|
@ -1,27 +1,16 @@
|
|||
#include <processor/processor.hpp>
|
||||
#include "gsu.hpp"
|
||||
|
||||
//note: multiplication results *may* sometimes be invalid when both CLSR and MS0 are set
|
||||
//the product of multiplication in this mode (21mhz + fast-multiply) has not been analyzed;
|
||||
//however, the timing of this mode has been confirmed to work as specified below
|
||||
|
||||
namespace Processor {
|
||||
|
||||
#include "instructions.cpp"
|
||||
#include "table.cpp"
|
||||
#include "serialization.cpp"
|
||||
|
||||
//note: multiplication results *may* sometimes be invalid when both CLSR and MS0 are set
|
||||
//the product of multiplication in this mode (21mhz + fast-multiply) has not been analyzed;
|
||||
//however, the timing of this mode has been confirmed to work as specified below
|
||||
auto GSU::cache_access_speed() -> unsigned {
|
||||
if(clockmode == 1) return 2;
|
||||
if(clockmode == 2) return 1;
|
||||
return regs.clsr ? 1 : 2;
|
||||
}
|
||||
|
||||
auto GSU::memory_access_speed() -> unsigned {
|
||||
if(clockmode == 1) return 6;
|
||||
if(clockmode == 2) return 5;
|
||||
return regs.clsr ? 5 : 6;
|
||||
}
|
||||
|
||||
auto GSU::power() -> void {
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
namespace Processor {
|
||||
|
||||
struct GSU {
|
||||
unsigned clockmode; //0 = selectable; 1 = force 10.74mhz; 2 = force 21.48mhz
|
||||
#include "registers.hpp"
|
||||
|
||||
virtual auto step(unsigned clocks) -> void = 0;
|
||||
|
@ -23,9 +22,6 @@ struct GSU {
|
|||
virtual auto cache_flush() -> void = 0;
|
||||
|
||||
//gsu.cpp
|
||||
auto cache_access_speed() -> unsigned;
|
||||
auto memory_access_speed() -> unsigned;
|
||||
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
|
|
|
@ -383,7 +383,7 @@ auto GSU::op_mult_r() {
|
|||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
if(!regs.cfgr.ms0) step(cache_access_speed());
|
||||
if(!regs.cfgr.ms0) step(regs.clsr ? 1 : 2);
|
||||
}
|
||||
|
||||
//$80-8f(alt1): umult rN
|
||||
|
@ -393,7 +393,7 @@ auto GSU::op_umult_r() {
|
|||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
if(!regs.cfgr.ms0) step(cache_access_speed());
|
||||
if(!regs.cfgr.ms0) step(regs.clsr ? 1 : 2);
|
||||
}
|
||||
|
||||
//$80-8f(alt2): mult #N
|
||||
|
@ -403,7 +403,7 @@ auto GSU::op_mult_i() {
|
|||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
if(!regs.cfgr.ms0) step(cache_access_speed());
|
||||
if(!regs.cfgr.ms0) step(regs.clsr ? 1 : 2);
|
||||
}
|
||||
|
||||
//$80-8f(alt3): umult #N
|
||||
|
@ -413,7 +413,7 @@ auto GSU::op_umult_i() {
|
|||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
if(!regs.cfgr.ms0) step(cache_access_speed());
|
||||
if(!regs.cfgr.ms0) step(regs.clsr ? 1 : 2);
|
||||
}
|
||||
|
||||
//$90: sbk
|
||||
|
@ -499,7 +499,7 @@ auto GSU::op_fmult() {
|
|||
regs.sfr.cy = (result & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
step(4 + (regs.cfgr.ms0 << 2));
|
||||
step((regs.cfgr.ms0 ? 3 : 7) * (regs.clsr ? 1 : 2));
|
||||
}
|
||||
|
||||
//$9f(alt1): lmult
|
||||
|
@ -511,7 +511,7 @@ auto GSU::op_lmult() {
|
|||
regs.sfr.cy = (result & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
step(4 + (regs.cfgr.ms0 << 2));
|
||||
step((regs.cfgr.ms0 ? 3 : 7) * (regs.clsr ? 1 : 2));
|
||||
}
|
||||
|
||||
//$a0-af(alt0): ibt rN,#pp
|
||||
|
@ -618,7 +618,7 @@ auto GSU::op_getc() {
|
|||
//$df(alt2): ramb
|
||||
auto GSU::op_ramb() {
|
||||
rambuffer_sync();
|
||||
regs.rambr = regs.sr();
|
||||
regs.rambr = regs.sr() & 0x01;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ struct reg16_t {
|
|||
|
||||
inline auto operator = (const reg16_t& i) { return assign(i); }
|
||||
|
||||
reg16_t() = default;
|
||||
reg16_t(const reg16_t&) = delete;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
auto GSU::serialize(serializer& s) -> void {
|
||||
s.integer(clockmode);
|
||||
|
||||
s.integer(regs.pipeline);
|
||||
s.integer(regs.ramaddr);
|
||||
|
||||
|
|
|
@ -10,12 +10,10 @@ struct ArmDSP : Processor::ARM, Coprocessor {
|
|||
static void Enter();
|
||||
void enter();
|
||||
|
||||
void step(unsigned clocks);
|
||||
void bus_idle(uint32 addr);
|
||||
uint32 bus_read(uint32 addr, uint32 size, bool mode);
|
||||
uint32 bus_load(uint32 addr, uint32 size, bool mode);
|
||||
void bus_write(uint32 addr, uint32 size, bool mode, uint32 word);
|
||||
void bus_store(uint32 addr, uint32 size, bool mode, uint32 word);
|
||||
void step(unsigned clocks) override;
|
||||
void bus_idle(uint32 addr) override;
|
||||
uint32 bus_read(uint32 addr, uint32 size, bool mode) override;
|
||||
void bus_write(uint32 addr, uint32 size, bool mode, uint32 word) override;
|
||||
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#ifdef ARMDSP_CPP
|
||||
|
||||
//note: timings are completely unverified
|
||||
//due to the ST018 chip design (on-die ROM), testing is nearly impossible
|
||||
|
||||
void ArmDSP::bus_idle(uint32 addr) {
|
||||
step(1);
|
||||
}
|
||||
|
@ -44,10 +47,6 @@ uint32 ArmDSP::bus_read(uint32 addr, uint32 size, bool mode) {
|
|||
return 0u;
|
||||
}
|
||||
|
||||
uint32 ArmDSP::bus_load(uint32 addr, uint32 size, bool mode) {
|
||||
return bus_read(addr, size, mode);
|
||||
}
|
||||
|
||||
void ArmDSP::bus_write(uint32 addr, uint32 size, bool mode, uint32 word) {
|
||||
step(1);
|
||||
|
||||
|
@ -102,8 +101,4 @@ void ArmDSP::bus_write(uint32 addr, uint32 size, bool mode, uint32 word) {
|
|||
}
|
||||
}
|
||||
|
||||
void ArmDSP::bus_store(uint32 addr, uint32 size, bool mode, uint32 word) {
|
||||
return bus_write(addr, size, mode, word);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -60,7 +60,7 @@ void Event::submitScore() {
|
|||
data.append("ba:", ba[0], ",", ba[1], "\n");
|
||||
}
|
||||
|
||||
lstring side = interface->server().split<1>("@");
|
||||
/*lstring side = interface->server().split<1>("@");
|
||||
string username = side(0).split<1>(":")(0);
|
||||
string password = side(0).split<1>(":")(1);
|
||||
side(1).ltrim("http://");
|
||||
|
@ -71,7 +71,7 @@ void Event::submitScore() {
|
|||
string hostport = side(1);
|
||||
if(hostport.empty()) hostport = "80";
|
||||
|
||||
/*http server;
|
||||
http server;
|
||||
if(server.connect(hostname, decimal(hostport))) {
|
||||
string content = {
|
||||
"username:", username, "\n",
|
||||
|
|
|
@ -66,7 +66,7 @@ auto SuperFX::rpix(uint8 x, uint8 y) -> uint8 {
|
|||
|
||||
for(unsigned n = 0; n < bpp; n++) {
|
||||
unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||
step(memory_access_speed());
|
||||
step(regs.clsr ? 5 : 6);
|
||||
data |= ((bus_read(addr + byte) >> x) & 1) << n;
|
||||
}
|
||||
|
||||
|
@ -94,11 +94,11 @@ auto SuperFX::pixelcache_flush(pixelcache_t& cache) -> void {
|
|||
uint8 data = 0x00;
|
||||
for(unsigned x = 0; x < 8; x++) data |= ((cache.data[x] >> n) & 1) << x;
|
||||
if(cache.bitpend != 0xff) {
|
||||
step(memory_access_speed());
|
||||
step(regs.clsr ? 5 : 6);
|
||||
data &= cache.bitpend;
|
||||
data |= bus_read(addr + byte) & ~cache.bitpend;
|
||||
}
|
||||
step(memory_access_speed());
|
||||
step(regs.clsr ? 5 : 6);
|
||||
bus_write(addr + byte, data);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,12 +43,12 @@ auto SuperFX::op_read(uint16 addr) -> uint8 {
|
|||
unsigned dp = offset & 0xfff0;
|
||||
unsigned sp = (regs.pbr << 16) + ((regs.cbr + dp) & 0xfff0);
|
||||
for(unsigned n = 0; n < 16; n++) {
|
||||
step(memory_access_speed());
|
||||
step(regs.clsr ? 5 : 6);
|
||||
cache.buffer[dp++] = bus_read(sp++);
|
||||
}
|
||||
cache.valid[offset >> 4] = true;
|
||||
} else {
|
||||
step(cache_access_speed());
|
||||
step(regs.clsr ? 1 : 2);
|
||||
}
|
||||
return cache.buffer[offset];
|
||||
}
|
||||
|
@ -56,12 +56,12 @@ auto SuperFX::op_read(uint16 addr) -> uint8 {
|
|||
if(regs.pbr <= 0x5f) {
|
||||
//$[00-5f]:[0000-ffff] ROM
|
||||
rombuffer_sync();
|
||||
step(memory_access_speed());
|
||||
step(regs.clsr ? 5 : 6);
|
||||
return bus_read((regs.pbr << 16) + addr);
|
||||
} else {
|
||||
//$[60-7f]:[0000-ffff] RAM
|
||||
rambuffer_sync();
|
||||
step(memory_access_speed());
|
||||
step(regs.clsr ? 5 : 6);
|
||||
return bus_read((regs.pbr << 16) + addr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ auto SuperFX::mmio_write(unsigned addr, uint8 data) -> void {
|
|||
} break;
|
||||
|
||||
case 0x3033: {
|
||||
regs.bramr = data;
|
||||
regs.bramr = data & 0x01;
|
||||
} break;
|
||||
|
||||
case 0x3034: {
|
||||
|
@ -104,7 +104,7 @@ auto SuperFX::mmio_write(unsigned addr, uint8 data) -> void {
|
|||
} break;
|
||||
|
||||
case 0x3039: {
|
||||
regs.clsr = data;
|
||||
regs.clsr = data & 0x01;
|
||||
} break;
|
||||
|
||||
case 0x303a: {
|
||||
|
|
|
@ -5,7 +5,6 @@ auto SuperFX::serialize(serializer& s) -> void {
|
|||
Thread::serialize(s);
|
||||
|
||||
s.array(ram.data(), ram.size());
|
||||
s.integer(instruction_counter);
|
||||
s.integer(r15_modified);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,17 +25,12 @@ auto SuperFX::enter() -> void {
|
|||
|
||||
if(regs.sfr.g == 0) {
|
||||
step(6);
|
||||
synchronize_cpu();
|
||||
continue;
|
||||
}
|
||||
|
||||
(this->*opcode_table[(regs.sfr & 0x0300) + peekpipe()])();
|
||||
unsigned opcode = (regs.sfr & 0x0300) + peekpipe();
|
||||
(this->*opcode_table[opcode])();
|
||||
if(r15_modified == false) regs.r[15]++;
|
||||
|
||||
if(++instruction_counter >= 128) {
|
||||
instruction_counter = 0;
|
||||
synchronize_cpu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +55,6 @@ auto SuperFX::power() -> void {
|
|||
auto SuperFX::reset() -> void {
|
||||
GSU::reset();
|
||||
create(SuperFX::Enter, system.cpu_frequency());
|
||||
instruction_counter = 0;
|
||||
memory_reset();
|
||||
timing_reset();
|
||||
}
|
||||
|
|
|
@ -21,9 +21,6 @@ struct SuperFX : Processor::GSU, Coprocessor {
|
|||
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
privileged:
|
||||
unsigned instruction_counter = 0;
|
||||
};
|
||||
|
||||
extern SuperFX superfx;
|
||||
|
|
|
@ -26,7 +26,7 @@ auto SuperFX::rombuffer_sync() -> void {
|
|||
|
||||
auto SuperFX::rombuffer_update() -> void {
|
||||
regs.sfr.r = 1;
|
||||
regs.romcl = memory_access_speed();
|
||||
regs.romcl = regs.clsr ? 5 : 6;
|
||||
}
|
||||
|
||||
auto SuperFX::rombuffer_read() -> uint8 {
|
||||
|
@ -45,7 +45,7 @@ auto SuperFX::rambuffer_read(uint16 addr) -> uint8 {
|
|||
|
||||
auto SuperFX::rambuffer_write(uint16 addr, uint8 data) -> void {
|
||||
rambuffer_sync();
|
||||
regs.ramcl = memory_access_speed();
|
||||
regs.ramcl = regs.clsr ? 5 : 6;
|
||||
regs.ramar = addr;
|
||||
regs.ramdr = data;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue