mirror of https://github.com/bsnes-emu/bsnes.git
Updated to v067r23 release.
byuu says: Fixed bsnes launcher on Windows XP Fixed Windows bsnes launcher internationalization support (emulator can be in a folder with spaces and Japanese characters, and you can drag a Japanese file name onto the launcher, and it will load it properly) Moved fast CPU to use a switch table for MMIO, unfortunately for no speed gain Bus::read/write take uint24 parameters for address, luckily no speed penalty MMIOAccess gained a handle() function, and hid the mmio[] table. Makes hooking it cleaner Added malloc.h header to nall/function.hpp to fix a ridiculous GCC 4.5.0 error Fixed a fairly large bug in the fast CPU IRQ handler, which fixes Robocop et al Forgot to bump revision to .24 in the compiled binaries, too lazy to recompile or hex edit to change them Unfortunately, in order to add nice battery usage, I have to add the sleep calls to the video and audio wait loops. But they don't know anything about the GUI and its settings, nor do I really want to make them know about this setting. I do not want to force allow it. Even with the media timer trick, Sleep(0) makes Vsync+Async fail a lot more frequently than never sleeping at all. I would rather laptop users suffer 100% utilization of a single core than for all users to not be able to get good audio+video sync. Not sure what to do about that, so I'll probably just remove the battery usage comment from performance mode for now.
This commit is contained in:
parent
70429285ba
commit
b16fe19793
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
|||
include nall/Makefile
|
||||
snes := snes
|
||||
profile := performance
|
||||
profile := accuracy
|
||||
ui := qt
|
||||
|
||||
# compiler
|
||||
|
|
|
@ -7,54 +7,42 @@
|
|||
#include <nall/string.hpp>
|
||||
using namespace nall;
|
||||
|
||||
#if defined(PLATFORM_X) || defined(PLATFORM_OSX)
|
||||
#if !defined(PLATFORM_WIN)
|
||||
char* userpath(char *path) {
|
||||
*path = 0;
|
||||
struct passwd *userinfo = getpwuid(getuid());
|
||||
if(userinfo) strcpy(path, userinfo->pw_dir);
|
||||
return path;
|
||||
}
|
||||
|
||||
char *getcwd(char *path) {
|
||||
return getcwd(path, PATH_MAX);
|
||||
}
|
||||
#elif defined(PLATFORM_WIN)
|
||||
#else
|
||||
#include <nall/utf8.hpp>
|
||||
#include <process.h>
|
||||
#include <wchar.h>
|
||||
#include <windows.h>
|
||||
|
||||
char* realpath(const char *filename, char *resolvedname) {
|
||||
wchar_t fn[_MAX_PATH] = L"";
|
||||
_wfullpath(fn, nall::utf16_t(filename), _MAX_PATH);
|
||||
wchar_t fn[PATH_MAX] = L"";
|
||||
_wfullpath(fn, nall::utf16_t(filename), PATH_MAX);
|
||||
strcpy(resolvedname, nall::utf8_t(fn));
|
||||
return resolvedname;
|
||||
}
|
||||
|
||||
char* userpath(char *path) {
|
||||
wchar_t fp[_MAX_PATH] = L"";
|
||||
wchar_t fp[PATH_MAX] = L"";
|
||||
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, fp);
|
||||
strcpy(path, nall::utf8_t(fp));
|
||||
return path;
|
||||
}
|
||||
|
||||
char* getcwd(char *path) {
|
||||
wchar_t fp[_MAX_PATH] = L"";
|
||||
_wgetcwd(fp, _MAX_PATH);
|
||||
strcpy(path, nall::utf8_t(fp));
|
||||
return path;
|
||||
}
|
||||
|
||||
intptr_t execv(const char *cmdname, const char *const *argv) {
|
||||
int argc = __argc;
|
||||
wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
return _wexecv(nall::utf16_t(cmdname), wargv);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char path[PATH_MAX], *unused;
|
||||
#if !defined(PLATFORM_WIN)
|
||||
unused = realpath(argv[0], path);
|
||||
#else
|
||||
wchar_t **argw = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
unused = realpath(nall::utf8_t(argw[0]), path);
|
||||
#endif
|
||||
string realPath = dir(path);
|
||||
string basePath = string(dir(path), "bsnes.cfg");
|
||||
unused = userpath(path);
|
||||
|
@ -71,19 +59,24 @@ int main(int argc, char **argv) {
|
|||
#if defined(PLATFORM_WIN)
|
||||
binaryName << ".dll";
|
||||
#endif
|
||||
string fileName = string(realPath, binaryName);
|
||||
|
||||
string fileName = string("/usr/local/bin/", binaryName);
|
||||
if(!file::exists(fileName)) fileName = string("/usr/bin/", binaryName);
|
||||
if(!file::exists(fileName)) fileName = string(realPath, binaryName);
|
||||
if(!file::exists(fileName)) {
|
||||
#if defined(PLATFORM_WIN)
|
||||
MessageBox(0, string("Error: unable to locate binary file :", binaryName), "bsnes", MB_OK);
|
||||
#else
|
||||
print("[bsnes] Error: unable to locate binary file: ", binaryName, "\n");
|
||||
#endif
|
||||
return 0;
|
||||
#if !defined(PLATFORM_WIN)
|
||||
char **args = new char*[argc + 1];
|
||||
args[0] = strdup(binaryName);
|
||||
for(unsigned i = 1; i < argc; i++) args[i] = strdup(argv[i]);
|
||||
args[argc] = 0;
|
||||
execvp(args[0], args);
|
||||
execv(fileName, args);
|
||||
print("[bsnes] Error: unable to locate binary file: ", binaryName, "\n");
|
||||
#else
|
||||
STARTUPINFOW si;
|
||||
PROCESS_INFORMATION pi;
|
||||
memset(&si, 0, sizeof(STARTUPINFOW));
|
||||
if(!CreateProcessW(nall::utf16_t(fileName), GetCommandLineW(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
|
||||
MessageBox(0, string("Error: unable to locate binary file: ", binaryName), "bsnes", MB_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
execv(fileName, argv);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef NALL_FUNCTION_HPP
|
||||
#define NALL_FUNCTION_HPP
|
||||
|
||||
#include <malloc.h>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ void SDD1::enable() {
|
|||
//hook S-CPU DMA MMIO registers to gather information for struct dma[];
|
||||
//buffer address and transfer size information for use in SDD1::read()
|
||||
for(unsigned i = 0x4300; i <= 0x437f; i++) {
|
||||
cpu_mmio[i & 0x7f] = memory::mmio.mmio[i - 0x2000];
|
||||
cpu_mmio[i & 0x7f] = memory::mmio.handle(i);
|
||||
memory::mmio.map(i, *this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,10 +73,10 @@ void Serial::init() {
|
|||
}
|
||||
|
||||
void Serial::enable() {
|
||||
r4016 = memory::mmio.mmio[0x4016 - 0x2000];
|
||||
r4017 = memory::mmio.mmio[0x4017 - 0x2000];
|
||||
memory::mmio.mmio[0x4016 - 0x2000] = this;
|
||||
memory::mmio.mmio[0x4017 - 0x2000] = this;
|
||||
r4016 = memory::mmio.handle(0x4016);
|
||||
r4017 = memory::mmio.handle(0x4017);
|
||||
memory::mmio.map(0x4016, *this);
|
||||
memory::mmio.map(0x4017, *this);
|
||||
|
||||
if(opened()) close();
|
||||
string name = notdir(cartridge.basename());
|
||||
|
|
|
@ -103,10 +103,9 @@ void SuperGameBoy::init() {
|
|||
}
|
||||
|
||||
void SuperGameBoy::enable() {
|
||||
mmio[0] = memory::mmio.mmio[0x2181 - 0x2000];
|
||||
mmio[1] = memory::mmio.mmio[0x2182 - 0x2000];
|
||||
mmio[2] = memory::mmio.mmio[0x420b - 0x2000];
|
||||
|
||||
mmio[0] = memory::mmio.handle(0x2181);
|
||||
mmio[1] = memory::mmio.handle(0x2182);
|
||||
mmio[2] = memory::mmio.handle(0x420b);
|
||||
memory::mmio.map(0x2181, *this);
|
||||
memory::mmio.map(0x2182, *this);
|
||||
memory::mmio.map(0x420b, *this);
|
||||
|
|
|
@ -1,303 +1,303 @@
|
|||
#ifdef CPU_CPP
|
||||
|
||||
uint8 CPU::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if((addr & 0xffc0) == 0x2140) {
|
||||
synchronize_smp();
|
||||
return smp.port_read(addr & 3);
|
||||
}
|
||||
|
||||
if(addr == 0x2180) {
|
||||
uint8 result = bus.read(0x7e0000 | status.wram_addr);
|
||||
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
|
||||
return result;
|
||||
switch(addr & 0xffff) {
|
||||
case 0x2180: {
|
||||
uint8 result = bus.read(0x7e0000 | status.wram_addr);
|
||||
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
|
||||
return result;
|
||||
}
|
||||
|
||||
case 0x4016: {
|
||||
uint8 result = regs.mdr & 0xfc;
|
||||
result |= input.port_read(0) & 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
case 0x4017: {
|
||||
uint8 result = (regs.mdr & 0xe0) | 0x1c;
|
||||
result |= input.port_read(1) & 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
case 0x4210: {
|
||||
uint8 result = (regs.mdr & 0x70);
|
||||
result |= status.nmi_line << 7;
|
||||
result |= 0x02; //CPU revision
|
||||
status.nmi_line = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
case 0x4211: {
|
||||
uint8 result = (regs.mdr & 0x7f);
|
||||
result |= status.irq_line << 7;
|
||||
status.irq_line = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
case 0x4212: {
|
||||
uint8 result = (regs.mdr & 0x3e);
|
||||
unsigned vbstart = ppu.overscan() == false ? 225 : 240;
|
||||
|
||||
if(vcounter() >= vbstart && vcounter() <= vbstart + 2) result |= 0x01;
|
||||
if(hcounter() <= 2 || hcounter() >= 1096) result |= 0x40;
|
||||
if(vcounter() >= vbstart) result |= 0x80;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
case 0x4213: return status.pio;
|
||||
|
||||
case 0x4214: return status.rddiv >> 0;
|
||||
case 0x4215: return status.rddiv >> 8;
|
||||
case 0x4216: return status.rdmpy >> 0;
|
||||
case 0x4217: return status.rdmpy >> 8;
|
||||
|
||||
case 0x4218: return status.joy1l;
|
||||
case 0x4219: return status.joy1h;
|
||||
case 0x421a: return status.joy2l;
|
||||
case 0x421b: return status.joy2h;
|
||||
case 0x421c: return status.joy3l;
|
||||
case 0x421d: return status.joy3h;
|
||||
case 0x421e: return status.joy4l;
|
||||
case 0x421f: return status.joy4h;
|
||||
}
|
||||
|
||||
if(addr == 0x4016) {
|
||||
uint8 result = regs.mdr & 0xfc;
|
||||
result |= input.port_read(0) & 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
if(addr == 0x4017) {
|
||||
uint8 result = (regs.mdr & 0xe0) | 0x1c;
|
||||
result |= input.port_read(1) & 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
if(addr == 0x4210) {
|
||||
uint8 result = (regs.mdr & 0x70);
|
||||
result |= status.nmi_line << 7;
|
||||
result |= 0x02; //CPU revision
|
||||
status.nmi_line = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
if(addr == 0x4211) {
|
||||
uint8 result = (regs.mdr & 0x7f);
|
||||
result |= status.irq_line << 7;
|
||||
status.irq_line = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
if(addr == 0x4212) {
|
||||
uint8 result = (regs.mdr & 0x3e);
|
||||
unsigned vbstart = ppu.overscan() == false ? 225 : 240;
|
||||
|
||||
if(vcounter() >= vbstart && vcounter() <= vbstart + 2) result |= 0x01;
|
||||
if(hcounter() <= 2 || hcounter() >= 1096) result |= 0x40;
|
||||
if(vcounter() >= vbstart) result |= 0x80;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if(addr == 0x4213) return status.pio;
|
||||
|
||||
if(addr == 0x4214) return status.rddiv >> 0;
|
||||
if(addr == 0x4215) return status.rddiv >> 8;
|
||||
if(addr == 0x4216) return status.rdmpy >> 0;
|
||||
if(addr == 0x4217) return status.rdmpy >> 8;
|
||||
|
||||
if(addr == 0x4218) return status.joy1l;
|
||||
if(addr == 0x4219) return status.joy1h;
|
||||
if(addr == 0x421a) return status.joy2l;
|
||||
if(addr == 0x421b) return status.joy2h;
|
||||
if(addr == 0x421c) return status.joy3l;
|
||||
if(addr == 0x421d) return status.joy3h;
|
||||
if(addr == 0x421e) return status.joy4l;
|
||||
if(addr == 0x421f) return status.joy4h;
|
||||
|
||||
if((addr & 0xff80) == 0x4300) {
|
||||
unsigned i = (addr >> 4) & 7;
|
||||
addr &= 0xff8f;
|
||||
switch(addr & 0xff8f) {
|
||||
case 0x4300: {
|
||||
return (channel[i].direction << 7)
|
||||
| (channel[i].indirect << 6)
|
||||
| (channel[i].unused << 5)
|
||||
| (channel[i].reverse_transfer << 4)
|
||||
| (channel[i].fixed_transfer << 3)
|
||||
| (channel[i].transfer_mode << 0);
|
||||
}
|
||||
|
||||
if(addr == 0x4300) {
|
||||
return (channel[i].direction << 7)
|
||||
| (channel[i].indirect << 6)
|
||||
| (channel[i].unused << 5)
|
||||
| (channel[i].reverse_transfer << 4)
|
||||
| (channel[i].fixed_transfer << 3)
|
||||
| (channel[i].transfer_mode << 0);
|
||||
case 0x4301: return channel[i].dest_addr;
|
||||
case 0x4302: return channel[i].source_addr >> 0;
|
||||
case 0x4303: return channel[i].source_addr >> 8;
|
||||
case 0x4304: return channel[i].source_bank;
|
||||
case 0x4305: return channel[i].transfer_size >> 0;
|
||||
case 0x4306: return channel[i].transfer_size >> 8;
|
||||
case 0x4307: return channel[i].indirect_bank;
|
||||
case 0x4308: return channel[i].hdma_addr >> 0;
|
||||
case 0x4309: return channel[i].hdma_addr >> 8;
|
||||
case 0x430a: return channel[i].line_counter;
|
||||
case 0x430b: case 0x430f: return channel[i].unknown;
|
||||
}
|
||||
|
||||
if(addr == 0x4301) return channel[i].dest_addr;
|
||||
if(addr == 0x4302) return channel[i].source_addr >> 0;
|
||||
if(addr == 0x4303) return channel[i].source_addr >> 8;
|
||||
if(addr == 0x4304) return channel[i].source_bank;
|
||||
if(addr == 0x4305) return channel[i].transfer_size >> 0;
|
||||
if(addr == 0x4306) return channel[i].transfer_size >> 8;
|
||||
if(addr == 0x4307) return channel[i].indirect_bank;
|
||||
if(addr == 0x4308) return channel[i].hdma_addr >> 0;
|
||||
if(addr == 0x4309) return channel[i].hdma_addr >> 8;
|
||||
if(addr == 0x430a) return channel[i].line_counter;
|
||||
if(addr == 0x430b || addr == 0x430f) return channel[i].unknown;
|
||||
}
|
||||
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
void CPU::mmio_write(unsigned addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if((addr & 0xffc0) == 0x2140) {
|
||||
synchronize_smp();
|
||||
port_write(addr & 3, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x2180) {
|
||||
bus.write(0x7e0000 | status.wram_addr, data);
|
||||
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x2181) {
|
||||
status.wram_addr = (status.wram_addr & 0x01ff00) | (data << 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x2182) {
|
||||
status.wram_addr = (status.wram_addr & 0x0100ff) | (data << 8);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x2183) {
|
||||
status.wram_addr = (status.wram_addr & 0x00ffff) | ((data & 1) << 16);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4016) {
|
||||
bool old_latch = status.joypad_strobe_latch;
|
||||
bool new_latch = data & 1;
|
||||
status.joypad_strobe_latch = new_latch;
|
||||
if(old_latch != new_latch) input.poll();
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4200) {
|
||||
bool nmi_enabled = status.nmi_enabled;
|
||||
bool virq_enabled = status.virq_enabled;
|
||||
bool hirq_enabled = status.hirq_enabled;
|
||||
|
||||
status.nmi_enabled = data & 0x80;
|
||||
status.virq_enabled = data & 0x20;
|
||||
status.hirq_enabled = data & 0x10;
|
||||
status.auto_joypad_poll_enabled = data & 0x01;
|
||||
|
||||
if(!nmi_enabled && status.nmi_enabled && status.nmi_line) {
|
||||
status.nmi_transition = true;
|
||||
switch(addr & 0xffff) {
|
||||
case 0x2180: {
|
||||
bus.write(0x7e0000 | status.wram_addr, data);
|
||||
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
|
||||
return;
|
||||
}
|
||||
|
||||
if(status.virq_enabled && !status.hirq_enabled && status.irq_line) {
|
||||
status.irq_transition = true;
|
||||
case 0x2181: {
|
||||
status.wram_addr = (status.wram_addr & 0x01ff00) | (data << 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!status.virq_enabled && !status.hirq_enabled) {
|
||||
status.irq_line = false;
|
||||
status.irq_transition = false;
|
||||
case 0x2182: {
|
||||
status.wram_addr = (status.wram_addr & 0x0100ff) | (data << 8);
|
||||
return;
|
||||
}
|
||||
|
||||
status.irq_lock = true;
|
||||
return;
|
||||
}
|
||||
case 0x2183: {
|
||||
status.wram_addr = (status.wram_addr & 0x00ffff) | ((data & 1) << 16);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4201) {
|
||||
if((status.pio & 0x80) && !(data & 0x80)) ppu.latch_counters();
|
||||
status.pio = data;
|
||||
}
|
||||
case 0x4016: {
|
||||
bool old_latch = status.joypad_strobe_latch;
|
||||
bool new_latch = data & 1;
|
||||
status.joypad_strobe_latch = new_latch;
|
||||
if(old_latch != new_latch) input.poll();
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4202) {
|
||||
status.wrmpya = data;
|
||||
return;
|
||||
}
|
||||
case 0x4200: {
|
||||
bool nmi_enabled = status.nmi_enabled;
|
||||
bool virq_enabled = status.virq_enabled;
|
||||
bool hirq_enabled = status.hirq_enabled;
|
||||
|
||||
if(addr == 0x4203) {
|
||||
status.wrmpyb = data;
|
||||
status.rdmpy = status.wrmpya * status.wrmpyb;
|
||||
return;
|
||||
}
|
||||
status.nmi_enabled = data & 0x80;
|
||||
status.virq_enabled = data & 0x20;
|
||||
status.hirq_enabled = data & 0x10;
|
||||
status.auto_joypad_poll_enabled = data & 0x01;
|
||||
|
||||
if(addr == 0x4204) {
|
||||
status.wrdiva = (status.wrdiva & 0xff00) | (data << 0);
|
||||
return;
|
||||
}
|
||||
if(!nmi_enabled && status.nmi_enabled && status.nmi_line) {
|
||||
status.nmi_transition = true;
|
||||
}
|
||||
|
||||
if(addr == 0x4205) {
|
||||
status.wrdiva = (data << 8) | (status.wrdiva & 0x00ff);
|
||||
return;
|
||||
}
|
||||
if(status.virq_enabled && !status.hirq_enabled && status.irq_line) {
|
||||
status.irq_transition = true;
|
||||
}
|
||||
|
||||
if(addr == 0x4206) {
|
||||
status.wrdivb = data;
|
||||
status.rddiv = status.wrdivb ? status.wrdiva / status.wrdivb : 0xffff;
|
||||
status.rdmpy = status.wrdivb ? status.wrdiva % status.wrdivb : status.wrdiva;
|
||||
return;
|
||||
}
|
||||
if(!status.virq_enabled && !status.hirq_enabled) {
|
||||
status.irq_line = false;
|
||||
status.irq_transition = false;
|
||||
}
|
||||
|
||||
if(addr == 0x4207) {
|
||||
status.htime = (status.htime & 0x0100) | (data << 0);
|
||||
return;
|
||||
}
|
||||
status.irq_lock = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4208) {
|
||||
status.htime = ((data & 1) << 8) | (status.htime & 0x00ff);
|
||||
return;
|
||||
}
|
||||
case 0x4201: {
|
||||
if((status.pio & 0x80) && !(data & 0x80)) ppu.latch_counters();
|
||||
status.pio = data;
|
||||
}
|
||||
|
||||
if(addr == 0x4209) {
|
||||
status.vtime = (status.vtime & 0x0100) | (data << 0);
|
||||
return;
|
||||
}
|
||||
case 0x4202: {
|
||||
status.wrmpya = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x420a) {
|
||||
status.vtime = ((data & 1) << 8) | (status.vtime & 0x00ff);
|
||||
return;
|
||||
}
|
||||
case 0x4203: {
|
||||
status.wrmpyb = data;
|
||||
status.rdmpy = status.wrmpya * status.wrmpyb;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x420b) {
|
||||
for(unsigned i = 0; i < 8; i++) channel[i].dma_enabled = data & (1 << i);
|
||||
if(data) dma_run();
|
||||
return;
|
||||
}
|
||||
case 0x4204: {
|
||||
status.wrdiva = (status.wrdiva & 0xff00) | (data << 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x420c) {
|
||||
for(unsigned i = 0; i < 8; i++) channel[i].hdma_enabled = data & (1 << i);
|
||||
return;
|
||||
}
|
||||
case 0x4205: {
|
||||
status.wrdiva = (data << 8) | (status.wrdiva & 0x00ff);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x420d) {
|
||||
status.rom_speed = data & 1 ? 6 : 8;
|
||||
return;
|
||||
case 0x4206: {
|
||||
status.wrdivb = data;
|
||||
status.rddiv = status.wrdivb ? status.wrdiva / status.wrdivb : 0xffff;
|
||||
status.rdmpy = status.wrdivb ? status.wrdiva % status.wrdivb : status.wrdiva;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x4207: {
|
||||
status.htime = (status.htime & 0x0100) | (data << 0);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x4208: {
|
||||
status.htime = ((data & 1) << 8) | (status.htime & 0x00ff);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x4209: {
|
||||
status.vtime = (status.vtime & 0x0100) | (data << 0);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x420a: {
|
||||
status.vtime = ((data & 1) << 8) | (status.vtime & 0x00ff);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x420b: {
|
||||
for(unsigned i = 0; i < 8; i++) channel[i].dma_enabled = data & (1 << i);
|
||||
if(data) dma_run();
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x420c: {
|
||||
for(unsigned i = 0; i < 8; i++) channel[i].hdma_enabled = data & (1 << i);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x420d: {
|
||||
status.rom_speed = data & 1 ? 6 : 8;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if((addr & 0xff80) == 0x4300) {
|
||||
unsigned i = (addr >> 4) & 7;
|
||||
addr &= 0xff8f;
|
||||
switch(addr & 0xff8f) {
|
||||
case 0x4300: {
|
||||
channel[i].direction = data & 0x80;
|
||||
channel[i].indirect = data & 0x40;
|
||||
channel[i].unused = data & 0x20;
|
||||
channel[i].reverse_transfer = data & 0x10;
|
||||
channel[i].fixed_transfer = data & 0x08;
|
||||
channel[i].transfer_mode = data & 0x07;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4300) {
|
||||
channel[i].direction = data & 0x80;
|
||||
channel[i].indirect = data & 0x40;
|
||||
channel[i].unused = data & 0x20;
|
||||
channel[i].reverse_transfer = data & 0x10;
|
||||
channel[i].fixed_transfer = data & 0x08;
|
||||
channel[i].transfer_mode = data & 0x07;
|
||||
return;
|
||||
}
|
||||
case 0x4301: {
|
||||
channel[i].dest_addr = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4301) {
|
||||
channel[i].dest_addr = data;
|
||||
return;
|
||||
}
|
||||
case 0x4302: {
|
||||
channel[i].source_addr = (channel[i].source_addr & 0xff00) | (data << 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4302) {
|
||||
channel[i].source_addr = (channel[i].source_addr & 0xff00) | (data << 0);
|
||||
return;
|
||||
}
|
||||
case 0x4303: {
|
||||
channel[i].source_addr = (data << 8) | (channel[i].source_addr & 0x00ff);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4303) {
|
||||
channel[i].source_addr = (data << 8) | (channel[i].source_addr & 0x00ff);
|
||||
return;
|
||||
}
|
||||
case 0x4304: {
|
||||
channel[i].source_bank = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4304) {
|
||||
channel[i].source_bank = data;
|
||||
return;
|
||||
}
|
||||
case 0x4305: {
|
||||
channel[i].transfer_size = (channel[i].transfer_size & 0xff00) | (data << 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4305) {
|
||||
channel[i].transfer_size = (channel[i].transfer_size & 0xff00) | (data << 0);
|
||||
return;
|
||||
}
|
||||
case 0x4306: {
|
||||
channel[i].transfer_size = (data << 8) | (channel[i].transfer_size & 0x00ff);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4306) {
|
||||
channel[i].transfer_size = (data << 8) | (channel[i].transfer_size & 0x00ff);
|
||||
return;
|
||||
}
|
||||
case 0x4307: {
|
||||
channel[i].indirect_bank = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4307) {
|
||||
channel[i].indirect_bank = data;
|
||||
return;
|
||||
}
|
||||
case 0x4308: {
|
||||
channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | (data << 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4308) {
|
||||
channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | (data << 0);
|
||||
return;
|
||||
}
|
||||
case 0x4309: {
|
||||
channel[i].hdma_addr = (data << 8) | (channel[i].hdma_addr & 0x00ff);
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x4309) {
|
||||
channel[i].hdma_addr = (data << 8) | (channel[i].hdma_addr & 0x00ff);
|
||||
return;
|
||||
}
|
||||
case 0x430a: {
|
||||
channel[i].line_counter = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x430a) {
|
||||
channel[i].line_counter = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x430b || addr == 0x430f) {
|
||||
channel[i].unknown = data;
|
||||
return;
|
||||
case 0x430b: case 0x430f: {
|
||||
channel[i].unknown = data;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ void CPU::add_clocks(unsigned clocks) {
|
|||
status.irq_valid = vcounter() == status.vtime;
|
||||
if(!irq_valid && status.irq_valid) status.irq_line = true;
|
||||
if(status.irq_line) status.irq_transition = true;
|
||||
} else {
|
||||
status.irq_valid = false;
|
||||
}
|
||||
|
||||
tick(clocks);
|
||||
|
|
|
@ -51,7 +51,7 @@ MappedRAM::MappedRAM() : data_(0), size_(-1U), write_protect_(false) {}
|
|||
|
||||
//Bus
|
||||
|
||||
uint8 Bus::read(unsigned addr) {
|
||||
uint8 Bus::read(uint24 addr) {
|
||||
#if defined(CHEAT_SYSTEM)
|
||||
if(cheat.active() && cheat.exists(addr)) {
|
||||
uint8 r;
|
||||
|
@ -63,7 +63,7 @@ uint8 Bus::read(unsigned addr) {
|
|||
return p.access->read(p.offset + addr);
|
||||
}
|
||||
|
||||
void Bus::write(unsigned addr, uint8 data) {
|
||||
void Bus::write(uint24 addr, uint8 data) {
|
||||
Page &p = page[addr >> 8];
|
||||
return p.access->write(p.offset + addr, data);
|
||||
}
|
||||
|
|
|
@ -9,14 +9,14 @@ Bus bus;
|
|||
|
||||
namespace memory {
|
||||
MMIOAccess mmio;
|
||||
StaticRAM wram(128 * 1024);
|
||||
StaticRAM apuram(64 * 1024);
|
||||
StaticRAM vram(64 * 1024);
|
||||
StaticRAM oam(544);
|
||||
StaticRAM cgram(512);
|
||||
StaticRAM wram(128 * 1024);
|
||||
StaticRAM apuram(64 * 1024);
|
||||
StaticRAM vram(64 * 1024);
|
||||
StaticRAM oam(544);
|
||||
StaticRAM cgram(512);
|
||||
|
||||
UnmappedMemory memory_unmapped;
|
||||
UnmappedMMIO mmio_unmapped;
|
||||
UnmappedMMIO mmio_unmapped;
|
||||
};
|
||||
|
||||
unsigned UnmappedMemory::size() const { return 16 * 1024 * 1024; }
|
||||
|
@ -26,6 +26,10 @@ void UnmappedMemory::write(unsigned, uint8) {}
|
|||
uint8 UnmappedMMIO::mmio_read(unsigned) { return cpu.regs.mdr; }
|
||||
void UnmappedMMIO::mmio_write(unsigned, uint8) {}
|
||||
|
||||
MMIO* MMIOAccess::handle(unsigned addr) {
|
||||
return mmio[(addr - 0x2000) & 0x3fff];
|
||||
}
|
||||
|
||||
void MMIOAccess::map(unsigned addr, MMIO &access) {
|
||||
//MMIO: $[00-3f]:[2000-5fff]
|
||||
mmio[(addr - 0x2000) & 0x3fff] = &access;
|
||||
|
|
|
@ -58,10 +58,12 @@ private:
|
|||
};
|
||||
|
||||
struct MMIOAccess : Memory {
|
||||
MMIO* handle(unsigned addr);
|
||||
void map(unsigned addr, MMIO &access);
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
private:
|
||||
MMIO *mmio[0x4000];
|
||||
};
|
||||
|
||||
|
@ -74,8 +76,8 @@ struct Bus {
|
|||
uint16 addr_lo, uint16 addr_hi,
|
||||
Memory &access, unsigned offset = 0, unsigned size = 0);
|
||||
|
||||
alwaysinline uint8 read(unsigned addr);
|
||||
alwaysinline void write(unsigned addr, uint8 data);
|
||||
alwaysinline uint8 read(uint24 addr);
|
||||
alwaysinline void write(uint24 addr, uint8 data);
|
||||
|
||||
bool load_cart();
|
||||
void unload_cart();
|
||||
|
@ -97,15 +99,15 @@ private:
|
|||
};
|
||||
|
||||
namespace memory {
|
||||
extern MMIOAccess mmio; //S-CPU, S-PPU
|
||||
extern StaticRAM wram; //S-CPU
|
||||
extern StaticRAM apuram; //S-SMP, S-DSP
|
||||
extern StaticRAM vram; //S-PPU
|
||||
extern StaticRAM oam; //S-PPU
|
||||
extern StaticRAM cgram; //S-PPU
|
||||
extern MMIOAccess mmio; //S-CPU, S-PPU
|
||||
extern StaticRAM wram; //S-CPU
|
||||
extern StaticRAM apuram; //S-SMP, S-DSP
|
||||
extern StaticRAM vram; //S-PPU
|
||||
extern StaticRAM oam; //S-PPU
|
||||
extern StaticRAM cgram; //S-PPU
|
||||
|
||||
extern UnmappedMemory memory_unmapped;
|
||||
extern UnmappedMMIO mmio_unmapped;
|
||||
extern UnmappedMMIO mmio_unmapped;
|
||||
};
|
||||
|
||||
extern Bus bus;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "bsnes";
|
||||
static const char Version[] = "067.23";
|
||||
static const char Version[] = "067.24";
|
||||
static const unsigned SerializerVersion = 12;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue