Update to bsnes v026 release.

- Major source code cleanup
    - Completely rewrote memory mapper to support runtime MMCs
    - Updated S-DD1 MMC to use new memory mapping interface
    - Improved S-DD1 emulation, thanks to information from orwannon
    - Added support for SameGame -- load via "Load Special -> Load BS-X Slotted Cart" menu option
    - Completely rewrote cartridge loader to support BS-X, BS-X slotted carts and ST carts
    - Created custom dialog windows for multicart loading
    - Improved generic memory mapper, which eliminates the need for cart.db [Nach]
    - Added BS-X slotted cart detection to generic memory mapper [Nach]
    - Linux port will now ignore keypresses when window is inactive
    - Linux port will use much less CPU power when idle
    - Added detailed compilation instructions to Makefile for Linux port
    - Added "make install" target and PNG program icon for Linux port
    - Switched Windows compiler to MinGW/GCC4
    - Windows executable is now packed with UPX to decrease filesize
    - Removed .ufo, .gd7 and .078 ROM extensions; added .bs extension
    - Added preliminary support for the BS-X base unit, BS-X base cartridge + MMC, and BS-X flash I/O
This commit is contained in:
byuu 2007-11-18 21:49:20 +00:00
parent 4f5bdfe347
commit 95547f4ff8
120 changed files with 2585 additions and 2726 deletions

BIN
cart.db

Binary file not shown.

View File

@ -1,5 +1,5 @@
bsnes
Version 0.025
Version 0.026
Author: byuu
--------
@ -72,13 +72,6 @@ SETA DSP used only by Quick-move Shogi Match with Nidan Rank-holder Morita
ST-018
SETA RISC CPU used only by Quick-move Shogi Match with Nidan Rank-holder Morita 2
BS-X (Broadcast Satellite)
Add-on unit sold only in Japan that played specially-made games that were
downloaded via satellite
BS-X Flashcart
Flash cartridge used by BS-X, as well as some standalone games by Asciisoft
Super Gameboy
Cartridge passthrough used for playing Gameboy games

View File

@ -78,17 +78,6 @@ LIBCO = libco_x86
LIBUI = libui_win
endif
ifeq ($(PLATFORM),win-mingw4-lui)
OS = win
CC = mingw32-gcc-sjlj
CFLAGS = -mconsole -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI
AS = nasm
ASFLAGS = -f win32 -DWIN32
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
LIBCO = libco_x86
LIBUI = libui_win
endif
#####################################
### compiler / assembler switches ###
#####################################
@ -109,14 +98,6 @@ CARGS = -c $< -o $@
DEFINE = -D
endif
ifeq ($(CC),mingw32-gcc-sjlj)
OUT = -obsnes
CPP = mingw32-g++-sjlj
OBJ = o
CARGS = -c $< -o $@
DEFINE = -D
endif
ifeq ($(CC),cl)
OUT = /Febsnes
CPP = cl
@ -152,10 +133,11 @@ endif
OBJECTS = main.$(OBJ) $(LIBCO).$(OBJ) $(LIBUI).$(OBJ) \
libstring.$(OBJ) \
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) bmemory.$(OBJ) \
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) smemory.$(OBJ) \
cpu.$(OBJ) scpu.$(OBJ) smp.$(OBJ) ssmp.$(OBJ) bdsp.$(OBJ) ppu.$(OBJ) \
bppu.$(OBJ) snes.$(OBJ) superfx.$(OBJ) srtc.$(OBJ) sdd1.$(OBJ) c4.$(OBJ) \
dsp1.$(OBJ) dsp2.$(OBJ) dsp3.$(OBJ) dsp4.$(OBJ) obc1.$(OBJ) st010.$(OBJ)
bppu.$(OBJ) snes.$(OBJ) bsx.$(OBJ) superfx.$(OBJ) srtc.$(OBJ) \
sdd1.$(OBJ) cx4.$(OBJ) dsp1.$(OBJ) dsp2.$(OBJ) dsp3.$(OBJ) dsp4.$(OBJ) \
obc1.$(OBJ) st010.$(OBJ)
ifeq ($(GZIP_SUPPORT),true)
OBJECTS += adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) \
@ -174,11 +156,18 @@ ifeq ($(OS),win)
ifeq ($(CC),cl)
OBJECTS += bsnes.res
endif
ifeq ($(CC),mingw32-gcc)
OBJECTS += bsnesrc.o
endif
endif
all: $(OBJECTS)
$(CPP) $(OUT) $(CFLAGS) $(OBJECTS) $(LIBS) $(LINK)
# mt -nologo -manifest bsnes.exe.manifest -outputresource:bsnes.exe;1
install:
cp bsnes /usr/local/bin/bsnes
cp data/bsnes.png /usr/local/share/icons/bsnes.png
chmod 775 /usr/local/bin/bsnes /usr/local/share/icons/bsnes.png
######################
### implicit rules ###
@ -193,9 +182,11 @@ all: $(OBJECTS)
### platform-specific ###
#########################
main.$(OBJ): ui/main.cpp config/* ui/* ui/video/* ui/audio/* ui/input/* \
ui/lui/* ui/lui/settings/* \
ui/lui/* ui/lui/loader/* ui/lui/settings/* \
ui/win/* ui/win/settings/* ui/win/debugger/*
bsnes.res : ui/bsnes.rc ; rc /r /fobsnes.res ui/bsnes.rc
bsnes.res: ui/bsnes.rc ; rc /r /fobsnes.res ui/bsnes.rc
bsnesrc.o: ui/bsnes.rc ; windres -I data ui/bsnes.rc bsnesrc.o
#############
### libco ###
@ -226,6 +217,7 @@ cheat.$(OBJ) : cheat/cheat.cpp cheat/*
##############
memory.$(OBJ) : memory/memory.cpp memory/*
bmemory.$(OBJ): memory/bmemory/bmemory.cpp memory/bmemory/* memory/bmemory/mapper/*
smemory.$(OBJ): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/*
###########
### cpu ###
@ -259,10 +251,11 @@ snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* sne
#####################
### special chips ###
#####################
bsx.$(OBJ) : chip/bsx/bsx.cpp chip/bsx/*
superfx.$(OBJ): chip/superfx/superfx.cpp chip/superfx/* chip/superfx/core/* chip/superfx/memory/*
srtc.$(OBJ) : chip/srtc/srtc.cpp chip/srtc/*
sdd1.$(OBJ) : chip/sdd1/sdd1.cpp chip/sdd1/*
c4.$(OBJ) : chip/c4/c4.cpp chip/c4/*
cx4.$(OBJ) : chip/cx4/cx4.cpp chip/cx4/*
dsp1.$(OBJ) : chip/dsp1/dsp1.cpp chip/dsp1/*
dsp2.$(OBJ) : chip/dsp2/dsp2.cpp chip/dsp2/*
dsp3.$(OBJ) : chip/dsp3/dsp3.cpp chip/dsp3/*
@ -312,4 +305,17 @@ clean:
-@$(RM) *.manifest
help:
@echo Please specify which platform to compile for with PLATFORM=platform_name
@echo "Usage: $(MAKE) PLATFORM=platform [options]"
@echo ""
@echo "Available platform targets:"
@echo " x-gcc-lui - Linux / BSD (i386) (requires nasm)"
@echo " x-gcc-lui-x64 - Linux / BSD (amd64) (requires yasm)"
@echo " win-mingw-lui - Windows (i386) (requires nasm)"
@echo " win-visualc-lui - Windows (i386) (requires nasm)"
@echo ""
@echo "Available options:"
@echo " GZIP_SUPPORT=[true|false] - Enable ZIP / GZ support (default=false)"
@echo " JMA_SUPPORT=[true|false] - Enable JMA support (default=false)"
@echo ""
@echo "Example: $(MAKE) PLATFORM=x-gcc-lui GZIP_SUPPORT=true"
@echo ""

View File

@ -1,7 +1,7 @@
#define BSNES_VERSION "0.025"
#define BSNES_VERSION "0.026"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define MEMCORE bMemBus
#define BUSCORE sBus
#define CPUCORE sCPU
#define SMPCORE sSMP
#define DSPCORE bDSP
@ -13,12 +13,6 @@
//game genie + pro action replay code support (~1-3% speed hit)
#define CHEAT_SYSTEM
//snes core polymorphism
//(allow runtime cpu/smp/dsp/ppu/bus selection, ~10% speed hit)
//#define POLYMORPHISM
#include "lib/libbase.h"
#if defined(PROCESSOR_X86)
#define ARCH_LSB
#include "lib/libco_x86.h"
@ -31,8 +25,8 @@
#error "unsupported processor"
#endif
#include "lib/libfunctor.h"
#include "lib/libsort.h"
#include "lib/libbase.h"
#include "lib/libfunction.h"
#include "lib/libarray.h"
#include "lib/libvector.h"
#include "lib/libstring.h"

View File

@ -1,25 +1,50 @@
#include "../base.h"
#include "database.cpp"
#include "cart_normal.cpp"
#include "cart_bsx.cpp"
#include "cart_bsc.cpp"
#include "cart_st.cpp"
#include "cart_stdual.cpp"
#include "cart_file.cpp"
#include "cart_header.cpp"
namespace memory {
MappedRAM cartrom, cartram;
MappedRAM bscram;
MappedRAM stArom, stAram;
MappedRAM stBrom, stBram;
};
Cartridge cartridge;
Cartridge::MemoryMapper Cartridge::mapper() { return info.mapper; }
Cartridge::Region Cartridge::region() { return info.region; }
bool Cartridge::loaded() { return cart.loaded; }
void Cartridge::load_begin(CartridgeType cart_type) {
if(loaded() == true)return;
cart.rom = cart.ram = 0;
bs.ram = 0;
stA.rom = stA.ram = 0;
stB.rom = stB.ram = 0;
cart.rom_size = cart.ram_size = 0;
bs.ram_size = 0;
stA.rom_size = stA.ram_size = 0;
stB.rom_size = stB.ram_size = 0;
info.type = cart_type;
info.bsxbase = false;
info.bsxcart = false;
info.bsxflash = false;
info.st = false;
info.superfx = false;
info.sa1 = false;
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.cx4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.dsp3 = false;
@ -29,134 +54,66 @@ void Cartridge::load_begin(CartridgeType cart_type) {
info.st011 = false;
info.st018 = false;
info.dsp1_mapper = 0;
info.dsp1_mapper = DSP1Unmapped;
info.header_index = 0xffc0;
info.mapper = PCB;
strcpy(info.name, "");
strcpy(info.pcb, "");
info.mapper = LoROM;
info.name[0] = 0;
info.region = NTSC;
info.rom_size = 0;
info.ram_size = 0;
file.count = 0;
for(int i = 0; i < 8; i++) {
strcpy(file.rom_name[i], "");
strcpy(file.ram_name[i], "");
file.rom_size[i] = 0;
file.ram_size[i] = 0;
file.rom_data[i] = 0;
file.ram_data[i] = 0;
}
}
void Cartridge::load(const char *rom_fn) {
if(!rom_fn || !*rom_fn)return;
void Cartridge::load_end() {
memory::cartrom.map(cart.rom, cart.rom_size);
memory::cartram.map(cart.ram, cart.ram_size);
memory::bscram.map(bs.ram, bs.ram_size);
memory::stArom.map(stA.rom, stA.rom_size);
memory::stAram.map(stA.ram, stA.ram_size);
memory::stBrom.map(stB.rom, stB.rom_size);
memory::stBram.map(stB.ram, stB.ram_size);
char fn[4096], ram_fn[4096];
strcpy(fn, rom_fn);
//correct folder slashes
for(int i = strlen(fn) - 1; i >= 0; i--) {
if(fn[i] == '\\')fn[i] = '/';
}
memory::cartrom.write_protect(true);
memory::cartram.write_protect(false);
memory::bscram.write_protect(true);
memory::stArom.write_protect(true);
memory::stAram.write_protect(false);
memory::stBrom.write_protect(true);
memory::stBram.write_protect(false);
uint i = file.count++;
strcpy(file.rom_name[i], fn);
strcpy(fn, rom_fn);
//remove ROM extension
for(int i = strlen(fn) - 1; i >= 0; i--) {
if(fn[i] == '.') {
fn[i] = 0;
break;
}
}
if(i == 0) {
strcpy(file.patch_name, fn);
strcat(file.patch_name, ".ups");
}
strcpy(fn, strptr(config::file_updatepath(fn, config::path.save)));
if(i == 0) {
strcpy(file.cheat_name, fn);
strcat(file.cheat_name, ".cht");
}
strcpy(file.ram_name[i], fn);
strcat(file.ram_name[i], ".");
strcat(file.ram_name[i], config::path.save_ext);
}
bool Cartridge::load_end() {
for(int i = 0; i < file.count; i++) {
load_file(file.rom_name[i], file.rom_data[i], file.rom_size[i]);
}
if(fexists(file.cheat_name) == true) {
cheat.clear();
cheat.load(file.cheat_name);
}
switch(info.type) {
case CartridgeNormal: {
load_rom_normal();
load_ram_normal();
} break;
case CartridgeSufamiTurbo: {
load_rom_st();
load_ram_st();
} break;
case CartridgeSufamiTurboDual: {
load_rom_stdual();
load_ram_stdual();
} break;
}
cart_loaded = true;
r_mem->load_cart();
return true;
cart.loaded = true;
bus.load_cart();
}
bool Cartridge::unload() {
if(cart_loaded == false)return false;
if(cart.loaded == false) return false;
r_mem->unload_cart();
bus.unload_cart();
switch(info.type) {
case CartridgeNormal: {
save_ram_normal();
} break;
case CartridgeSufamiTurbo: {
save_ram_st();
} break;
case CartridgeSufamiTurboDual: {
save_ram_stdual();
} break;
case CartridgeNormal: unload_cart_normal(); break;
case CartridgeBSX: unload_cart_bsx(); break;
case CartridgeBSC: unload_cart_bsc(); break;
case CartridgeSufamiTurbo: unload_cart_st(); break;
}
safe_free(rom);
safe_free(ram);
safe_free(cart.rom);
safe_free(cart.ram);
safe_free(bs.ram);
safe_free(stA.rom);
safe_free(stA.ram);
safe_free(stB.rom);
safe_free(stB.ram);
if(cheat.count() > 0 || fexists(file.cheat_name) == true) {
cheat.save(file.cheat_name);
cheat.clear();
}
cart_loaded = false;
cart.loaded = false;
return true;
}
Cartridge::Cartridge() {
load_database();
cart_loaded = false;
rom = 0;
ram = 0;
cart.loaded = false;
}
Cartridge::~Cartridge() {
if(cart_loaded == true) {
unload();
}
if(cart.loaded == true) unload();
}

View File

@ -1,129 +1,142 @@
class Cartridge {
public:
enum CartridgeType {
CartridgeNormal,
CartridgeBSX,
CartridgeBSC,
CartridgeSufamiTurbo,
};
/*****
* cart database
*****/
enum HeaderField {
CART_NAME = 0x00,
MAPPER = 0x15,
ROM_TYPE = 0x16,
ROM_SIZE = 0x17,
RAM_SIZE = 0x18,
REGION = 0x19,
COMPANY = 0x1a,
VERSION = 0x1b,
ICKSUM = 0x1c,
CKSUM = 0x1e,
RESL = 0x3c,
RESH = 0x3d,
};
#include "db/db.h"
db_item dbi;
uint8 *database;
uint database_size;
uint database_blocksize;
void load_database();
bool read_database();
enum Region {
NTSC,
PAL,
};
//
enum MemoryMapper {
LoROM,
HiROM,
ExLoROM,
ExHiROM,
BSXROM,
BSCLoROM,
BSCHiROM,
STROM,
};
enum CartridgeType {
CartridgeNormal,
CartridgeSufamiTurbo,
CartridgeSufamiTurboDual,
};
enum DSP1MemoryMapper {
DSP1Unmapped,
DSP1LoROM1MB,
DSP1LoROM2MB,
DSP1HiROM,
};
bool cart_loaded;
struct {
bool loaded;
char fn[PATH_MAX];
uint8 *rom, *ram;
uint rom_size, ram_size;
} cart;
uint8 rom_header[512], *rom, *ram;
struct {
char fn[PATH_MAX];
uint8 *ram;
uint ram_size;
} bs;
enum {
//header fields
CART_NAME = 0x00,
MAPPER = 0x15,
ROM_TYPE = 0x16,
ROM_SIZE = 0x17,
RAM_SIZE = 0x18,
REGION = 0x19,
COMPANY = 0x1a,
VERSION = 0x1b,
ICKSUM = 0x1c,
CKSUM = 0x1e,
RESL = 0x3c,
RESH = 0x3d,
struct {
char fn[PATH_MAX];
uint8 *rom, *ram;
uint rom_size, ram_size;
} stA, stB;
//regions
NTSC = 0,
PAL = 1,
struct {
CartridgeType type;
//memory mappers
PCB = 0x00,
LOROM = 0x20,
HIROM = 0x21,
EXLOROM = 0x22,
EXHIROM = 0x25,
uint32 crc32;
char name[128];
//special chip memory mappers
DSP1_LOROM_1MB = 1,
DSP1_LOROM_2MB = 2,
DSP1_HIROM = 3,
};
Region region;
MemoryMapper mapper;
uint rom_size;
uint ram_size;
struct {
uint count;
char cheat_name[4096], patch_name[4096];
char rom_name[8][4096], ram_name[8][4096];
uint rom_size[8], ram_size[8];
uint8 *rom_data[8], *ram_data[8];
} file;
bool bsxbase;
bool bsxcart;
bool bsxflash;
bool st;
bool superfx;
bool sa1;
bool srtc;
bool sdd1;
bool cx4;
bool dsp1;
bool dsp2;
bool dsp3;
bool dsp4;
bool obc1;
bool st010;
bool st011;
bool st018;
struct {
uint type;
DSP1MemoryMapper dsp1_mapper;
//cart information
uint32 crc32;
char name[128];
char pcb[32];
uint header_index;
} info;
uint region;
uint mapper;
uint rom_size;
uint ram_size;
MemoryMapper mapper();
Region region();
bool superfx;
bool sa1;
bool srtc;
bool sdd1;
bool c4;
bool dsp1;
bool dsp2;
bool dsp3;
bool dsp4;
bool obc1;
bool st010;
bool st011;
bool st018;
void load_cart_normal(const char*);
void load_cart_bsx(const char*, const char*);
void load_cart_bsc(const char*, const char*);
void load_cart_st(const char*, const char*, const char*);
uint dsp1_mapper;
void unload_cart_normal();
void unload_cart_bsx();
void unload_cart_bsc();
void unload_cart_st();
//HiROM / LoROM specific code
uint header_index;
} info;
bool load_file(const char *fn, uint8 *&data, uint &size);
bool save_file(const char *fn, uint8 *data, uint size);
void load_rom_normal();
void load_ram_normal();
void save_ram_normal();
void load_rom_st();
void load_ram_st();
void save_ram_st();
void load_rom_stdual();
void load_ram_stdual();
void save_ram_stdual();
bool loaded();
void load_begin(CartridgeType);
void load_end();
bool unload();
void find_header();
void read_header();
void read_extended_header();
bool loaded() { return cart_loaded; }
void load_begin(CartridgeType cart_type);
void load(const char *rom_fn);
bool load_end();
bool unload();
bool load_file(const char *fn, uint8 *&data, uint &size);
bool save_file(const char *fn, uint8 *data, uint size);
char* modify_extension(char *filename, const char *extension);
char* get_save_filename(const char *source, const char *extension);
Cartridge();
~Cartridge();
private:
char savefn[PATH_MAX];
};
namespace memory {
extern MappedRAM cartrom, cartram;
extern MappedRAM bscram;
extern MappedRAM stArom, stAram;
extern MappedRAM stBrom, stBram;
};
extern Cartridge cartridge;

41
src/cart/cart_bsc.cpp Normal file
View File

@ -0,0 +1,41 @@
void Cartridge::load_cart_bsc(const char *base, const char *slot) {
if(!base || !*base) return;
strcpy(cart.fn, base);
strcpy(bs.fn, slot ? slot : "");
load_begin(CartridgeBSC);
uint8 *data;
uint size;
load_file(cart.fn, data, size);
cart.rom = data, cart.rom_size = size;
if(*bs.fn) {
if(load_file(bs.fn, data, size) == true) {
info.bsxflash = true;
bs.ram = data, bs.ram_size = size;
}
}
find_header();
read_header();
info.mapper = cartridge.info.header_index == 0x7fc0 ? BSCLoROM : BSCHiROM;
info.region = NTSC;
if(info.ram_size > 0) {
cart.ram = (uint8*)malloc(cart.ram_size = info.ram_size);
memset(cart.ram, 0xff, cart.ram_size);
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
memcpy(cart.ram, data, min(size, cart.ram_size));
safe_free(data);
}
}
load_end();
}
void Cartridge::unload_cart_bsc() {
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
}

45
src/cart/cart_bsx.cpp Normal file
View File

@ -0,0 +1,45 @@
void Cartridge::load_cart_bsx(const char *base, const char *slot) {
if(!base || !*base) return;
strcpy(cart.fn, base);
strcpy(bs.fn, slot ? slot : "");
load_begin(CartridgeBSX);
info.bsxbase = true;
info.bsxcart = true;
info.mapper = BSXROM;
info.region = NTSC;
uint8 *data;
uint size;
load_file(cart.fn, data, size);
cart.rom = data, cart.rom_size = size;
cart.ram = 0, cart.ram_size = 0;
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
safe_free(data);
}
if(load_file(get_save_filename(cart.fn, "psr"), data, size) == true) {
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
safe_free(data);
}
if(*bs.fn) {
if(load_file(bs.fn, data, size) == true) {
info.bsxflash = true;
bs.ram = data, bs.ram_size = size;
}
}
load_end();
}
void Cartridge::unload_cart_bsx() {
save_file(get_save_filename(cart.fn, "srm"), bsxcart.sram.handle (), bsxcart.sram.size ());
save_file(get_save_filename(cart.fn, "psr"), bsxcart.psram.handle(), bsxcart.psram.size());
}

View File

@ -9,11 +9,48 @@
#include "../reader/jmareader.h"
#endif
char* Cartridge::modify_extension(char *filename, const char *extension) {
int i;
for(i = strlen(filename); i >= 0; i--) {
if(filename[i] == '.') break;
if(filename[i] == '/') break;
if(filename[i] == '\\') break;
}
if(i > 0 && filename[i] == '.') filename[i] = 0;
strcat(filename, ".");
strcat(filename, extension);
return filename;
}
char* Cartridge::get_save_filename(const char *source, const char *extension) {
strcpy(savefn, source);
for(char *p = savefn; *p; p++) { if(*p == '\\') *p = '/'; }
modify_extension(savefn, extension);
//override path with user-specified folder, if one was defined
if(config::path.save != "") {
stringarray part;
split(part, "/", savefn);
string fn = config::path.save();
if(strend(fn, "/") == false) strcat(fn, "/");
strcat(fn, part[count(part) - 1]);
strcpy(savefn, fn);
//resolve relative path, if found
if(strbegin(fn, "./") == true) {
strltrim(fn, "./");
strcpy(savefn, config::path.base);
strcat(savefn, fn);
}
}
return savefn;
}
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
dprintf("* Loading \"%s\"...", fn);
if(fexists(fn) == false) {
alert("Error: file '%s' not found!", fn);
return false;
}

View File

@ -1,24 +1,37 @@
void Cartridge::read_header() {
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0 && rom[info.header_index + MAPPER] == 0x32) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0) {
info.mapper = LOROM;
strcpy(info.pcb, "UNL-LOROM");
} else if(info.header_index == 0xffc0) {
info.mapper = HIROM;
strcpy(info.pcb, "UNL-HIROM");
} else { //info.header_index == 0x40ffc0
info.mapper = EXHIROM;
strcpy(info.pcb, "UNL-EXHIROM");
uint8 *rom = cart.rom;
uint index = info.header_index;
uint8 mapper = rom[index + MAPPER];
uint8 rom_type = rom[index + ROM_TYPE];
uint8 company = rom[index + COMPANY];
uint8 region = rom[index + REGION] & 0x7f;
//detect presence of BS-X flash cartridge connector (reads extended header information)
bool has_bsxflash = false;
if(rom[index - 14] == 'Z') {
if(rom[index - 11] == 'J') {
uint8 n13 = rom[index - 13];
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
if(company == 0x33 || (rom[index - 10] == 0x00 && rom[index - 4] == 0x00)) {
has_bsxflash = true;
}
}
}
}
uint8 mapper = rom[info.header_index + MAPPER];
uint8 rom_type = rom[info.header_index + ROM_TYPE];
uint8 company = rom[info.header_index + COMPANY];
if(has_bsxflash == true) {
info.mapper = index == 0x7fc0 ? BSCLoROM : BSCHiROM;
} else if(index == 0x7fc0 && cart.rom_size >= 0x401000) {
info.mapper = ExLoROM;
} else if(index == 0x7fc0 && mapper == 0x32) {
info.mapper = ExLoROM;
} else if(index == 0x7fc0) {
info.mapper = LoROM;
} else if(index == 0xffc0) {
info.mapper = HiROM;
} else { //index == 0x40ffc0
info.mapper = ExHiROM;
}
if(mapper == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
info.superfx = true;
@ -37,7 +50,7 @@ uint8 company = rom[info.header_index + COMPANY];
}
if(mapper == 0x20 && rom_type == 0xf3) {
info.c4 = true;
info.cx4 = true;
}
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
@ -53,12 +66,12 @@ uint8 company = rom[info.header_index + COMPANY];
}
if(info.dsp1 == true) {
if((mapper & 0x2f) == 0x20 && info.rom_size <= 0x100000) {
info.dsp1_mapper = DSP1_LOROM_1MB;
if((mapper & 0x2f) == 0x20 && cart.rom_size <= 0x100000) {
info.dsp1_mapper = DSP1LoROM1MB;
} else if((mapper & 0x2f) == 0x20) {
info.dsp1_mapper = DSP1_LOROM_2MB;
info.dsp1_mapper = DSP1LoROM2MB;
} else if((mapper & 0x2f) == 0x21) {
info.dsp1_mapper = DSP1_HIROM;
info.dsp1_mapper = DSP1HiROM;
}
}
@ -95,6 +108,9 @@ uint8 company = rom[info.header_index + COMPANY];
info.ram_size = 0;
}
//0, 1, 13 = NTSC; 2 - 12 = PAL
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
info.name[21] = 0;
@ -109,8 +125,9 @@ void Cartridge::find_header() {
int32 score_lo = 0,
score_hi = 0,
score_ex = 0;
uint8 *rom = cart.rom;
if(info.rom_size < 0x010000) {
if(cart.rom_size < 0x010000) {
//cart too small to be anything but lorom
info.header_index = 0x007fc0;
return;
@ -150,7 +167,7 @@ uint16 cksum, icksum;
score_hi += 8;
}
if(info.rom_size < 0x401000) {
if(cart.rom_size < 0x401000) {
score_ex = 0;
} else {
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;

View File

@ -1,56 +1,41 @@
void Cartridge::load_rom_normal() {
uint size = 0;
for(int i = 0; i < file.count; i++) {
size += file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
}
info.rom_size = size;
rom = (uint8*)malloc(info.rom_size);
memset(rom, 0, info.rom_size);
uint offset = 0;
for(int i = 0; i < file.count; i++) {
uint8 *data = file.rom_data[i] + (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
uint size = file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
memcpy(rom + offset, data, size);
offset += size;
safe_free(file.rom_data[i]);
}
info.crc32 = crc32_calculate(rom, info.rom_size);
if(read_database() == true) {
info.header_index = 0xffc0;
info.mapper = PCB;
strcpy(info.name, dbi.name);
strcpy(info.pcb, dbi.pcb);
info.region = NTSC;
info.rom_size = dbi.rom;
info.ram_size = dbi.ram;
} else {
find_header();
read_header();
}
}
void Cartridge::load_ram_normal() {
if(info.ram_size == 0) {
ram = 0;
return;
}
ram = (uint8*)malloc(info.ram_size);
memset(ram, 0xff, info.ram_size);
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
memcpy(ram, file.ram_data[0], min(info.ram_size, file.ram_size[0]));
safe_free(file.ram_data[0]);
}
}
void Cartridge::save_ram_normal() {
if(info.ram_size == 0)return;
save_file(file.ram_name[0], ram, info.ram_size);
}
void Cartridge::load_cart_normal(const char *filename) {
if(!filename || !*filename) return;
uint8 *data;
uint size;
if(load_file(filename, data, size) == false) return;
strcpy(cart.fn, filename);
load_begin(CartridgeNormal);
//load ROM data, ignore 512-byte header if detected
if((size & 0x7fff) != 512) {
cart.rom = (uint8*)malloc(cart.rom_size = size);
memcpy(cart.rom, data, size);
} else {
cart.rom = (uint8*)malloc(cart.rom_size = size - 512);
memcpy(cart.rom, data + 512, size - 512);
}
safe_free(data);
info.crc32 = crc32_calculate(cart.rom, cart.rom_size);
find_header();
read_header();
if(info.ram_size > 0) {
cart.ram = (uint8*)malloc(cart.ram_size = info.ram_size);
memset(cart.ram, 0xff, cart.ram_size);
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
memcpy(cart.ram, data, min(size, cart.ram_size));
safe_free(data);
}
}
load_end();
}
void Cartridge::unload_cart_normal() {
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
}

View File

@ -1,45 +1,59 @@
void Cartridge::load_rom_st() {
uint8 *data;
uint size;
string bios = config::file_updatepath("stbios.bin", config::path.bios);
info.rom_size = 0x200000;
rom = (uint8*)malloc(info.rom_size);
memset(rom, 0, info.rom_size);
load_file(strptr(bios), data, size);
memcpy(rom, data, min(size, 0x040000));
safe_free(data);
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
safe_free(file.rom_data[0]);
//
strcpy(info.name, "???");
strcpy(info.pcb, "STC-SOLO");
info.mapper = PCB;
info.region = NTSC;
info.rom_size = 0x200000;
info.ram_size = 0x020000;
//
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
if(read_database() == true) {
strcpy(info.name, dbi.name);
}
}
void Cartridge::load_ram_st() {
ram = (uint8*)malloc(info.ram_size);
memset(ram, 0xff, info.ram_size);
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
memcpy(ram, file.ram_data[0], min(file.ram_size[0], 0x020000));
safe_free(file.ram_data[0]);
}
}
void Cartridge::save_ram_st() {
save_file(file.ram_name[0], ram, 0x020000);
}
void Cartridge::load_cart_st(const char *base, const char *slotA, const char *slotB) {
if(!base || !*base) return;
strcpy(cart.fn, base);
strcpy(stA.fn, slotA ? slotA : "");
strcpy(stB.fn, slotB ? slotB : "");
load_begin(CartridgeSufamiTurbo);
info.st = true;
info.mapper = STROM;
info.region = NTSC;
uint8 *data;
uint size;
if(load_file(cart.fn, data, size) == true) {
cart.rom = (uint8*)malloc(cart.rom_size = 0x040000);
memcpy(cart.rom, data, min(size, cart.rom_size));
safe_free(data);
}
if(*stA.fn) {
if(load_file(stA.fn, data, size) == true) {
stA.rom = (uint8*)malloc(stA.rom_size = 0x100000);
memcpy(stA.rom, data, min(size, stA.rom_size));
safe_free(data);
stA.ram = (uint8*)malloc(stA.ram_size = 0x020000);
memset(stA.ram, 0xff, stA.ram_size);
if(load_file(get_save_filename(stA.fn, "srm"), data, size) == true) {
memcpy(stA.ram, data, min(size, 0x020000));
safe_free(data);
}
}
}
if(*stB.fn) {
if(load_file(stB.fn, data, size) == true) {
stB.rom = (uint8*)malloc(stB.rom_size = 0x100000);
memcpy(stB.rom, data, min(size, stB.rom_size));
safe_free(data);
stB.ram = (uint8*)malloc(stB.ram_size = 0x020000);
memset(stB.ram, 0xff, stB.ram_size);
if(load_file(get_save_filename(stB.fn, "srm"), data, size) == true) {
memcpy(stB.ram, data, min(size, 0x020000));
safe_free(data);
}
}
}
load_end();
}
void Cartridge::unload_cart_st() {
if(stA.ram) save_file(get_save_filename(stA.fn, "srm"), stA.ram, stA.ram_size);
if(stB.ram) save_file(get_save_filename(stB.fn, "srm"), stB.ram, stB.ram_size);
}

View File

@ -1,66 +0,0 @@
void Cartridge::load_rom_stdual() {
uint8 *data;
uint size;
string bios = config::file_updatepath("stbios.bin", config::path.bios);
info.rom_size = 0x300000;
rom = (uint8*)malloc(info.rom_size);
memset(rom, 0, info.rom_size);
load_file(strptr(bios), data, size);
memcpy(rom, data, min(size, 0x040000));
safe_free(data);
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
safe_free(file.rom_data[0]);
memcpy(rom + 0x200000, file.rom_data[1], min(file.rom_size[1], 0x100000));
safe_free(file.rom_data[1]);
char name_a[4096], name_b[4096];
strcpy(name_a, "???");
strcpy(name_b, "???");
//
info.mapper = PCB;
info.region = NTSC;
info.rom_size = 0x300000;
info.ram_size = 0x040000;
//
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
if(read_database() == true) {
strcpy(name_a, dbi.name);
}
info.crc32 = crc32_calculate(rom + 0x200000, file.rom_size[1]);
if(read_database() == true) {
strcpy(name_b, dbi.name);
}
//
info.crc32 = 0;
strcpy(info.name, name_a);
strcat(info.name, " + ");
strcat(info.name, name_b);
strcpy(info.pcb, "STC-DUAL");
}
void Cartridge::load_ram_stdual() {
ram = (uint8*)malloc(info.ram_size);
memset(ram, 0xff, info.ram_size);
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
memcpy(ram + 0x000000, file.ram_data[0], min(file.ram_size[0], 0x020000));
safe_free(file.ram_data[0]);
}
if(load_file(file.ram_name[1], file.ram_data[1], file.ram_size[1]) == true) {
memcpy(ram + 0x020000, file.ram_data[1], min(file.ram_size[1], 0x020000));
safe_free(file.ram_data[1]);
}
}
void Cartridge::save_ram_stdual() {
save_file(file.ram_name[0], ram + 0x000000, 0x020000);
save_file(file.ram_name[1], ram + 0x020000, 0x020000);
}

View File

@ -1,37 +0,0 @@
void Cartridge::load_database() {
database = 0;
database_size = 0;
FILE *fp;
fp = fopen("cart.db", "rb");
if(!fp)return;
uint size = fsize(fp);
if(size < 8) {
fclose(fp);
return;
}
database = (uint8*)malloc(size);
fread(database, 1, size, fp);
fclose(fp);
database_blocksize = (database[6] << 0) | (database[7] << 8);
database_size = (size - 8) / database_blocksize;
}
bool Cartridge::read_database() {
uint i, crc32;
for(i = 0; i < database_size; i++) {
uint8 *p = database + 8 + (i * database_blocksize);
crc32 = *(p++) << 0;
crc32 |= *(p++) << 8;
crc32 |= *(p++) << 16;
crc32 |= *(p++) << 24;
if(crc32 == cartridge.info.crc32)break;
}
if(i >= database_size)return false;
db_read(dbi, database + 8 + (i * database_blocksize));
return true;
}

Binary file not shown.

View File

@ -1,119 +0,0 @@
[0xbb5c4238]
name = "Bishoujo Senshi Sailor Moon Sailor Stars - Fuwa Fuwa Panic 2 (Japan)"
pcb = "STC-????"
rom = 8mbit
ram = 32kbit
[0x8eb753f3]
name = "Crayon Shin-chan - Nagagutsu Dobon!! (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x7aedd703]
name = "Der Langrisser (Japan) [!]"
pcb = "SHVC-1A3M-30"
rom = 16mbit
ram = 64kbit
[0x19bdcb19]
name = "Derby Stallion '96 (Japan) [!]"
pcb = "BSC-1A5M-01"
rom = 24mbit
ram = 256kbit
[0x4296500d]
name = "Gegege no Kitarou - Youkai Donjara (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 16kbit
[0x14c66fca]
name = "Gekisou Sentai Car Rangers (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x32b2b3dd]
name = "Poi Poi Ninja World (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x9684526d]
name = "Romancing SaGa (Japan) (V1.1) [!]"
pcb = "SHVC-1A3B-12"
rom = 8mbit
ram = 64kbit
[0xafd74dcb]
name = "SD Gundam Generation A - Ichinen Sensouki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x48ecae44]
name = "SD Gundam Generation B - Grips Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x72b4235f]
name = "SD Gundam Generation C - Axis Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x792d884c]
name = "SD Gundam Generation D - Babylonia Kenkoku Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0xefd3a865]
name = "SD Gundam Generation E - Zanskar Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0xc5dfa8fd]
name = "SD Gundam Generation F - Colony Kakutouki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x43ad5a45]
name = "SD Ultra Battle - Seven Densetsu (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x04939d14]
name = "SD Ultra Battle - Ultra Densetsu (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0xa5c0045e]
name = "Secret of Evermore (USA) [!]"
pcb = "SHVC-1J3M-20"
rom = 32mbit
ram = 64kbit
[0x5ebf7246]
name = "Sound Novel Tsukuru (Japan) [!]"
pcb = "BSC-1A7M-10"
rom = 24mbit
ram = 512kbit
[0xcf98ddaa]
name = "Super Mario World 2: Yoshi's Island (USA)"
pcb = "SHVC-1CB5B-01"
rom = 16mbit
ram = 256kbit
[0x64a91e64]
name = "Wanderers from Ys (USA) [!]"
pcb = "SHVC-1A3B-12"
rom = 8mbit
ram = 64kbit

View File

@ -1,3 +0,0 @@
cl /nologo /O2 dbcreate.cpp
@pause
@del *.obj

View File

@ -1 +0,0 @@
@del *.exe

View File

@ -1,2 +0,0 @@
dbcreate
@copy cart.db ..\..\..\cart.db

View File

@ -1,47 +0,0 @@
struct db_item {
uint32 crc32;
char name[128];
char pcb [32];
uint32 rom;
uint32 ram;
};
void db_write(FILE *fp, db_item &dbi) {
fputc(dbi.crc32 >> 0, fp);
fputc(dbi.crc32 >> 8, fp);
fputc(dbi.crc32 >> 16, fp);
fputc(dbi.crc32 >> 24, fp);
fwrite(dbi.name, 1, 128, fp);
fwrite(dbi.pcb, 1, 32, fp);
fputc(dbi.rom >> 0, fp);
fputc(dbi.rom >> 8, fp);
fputc(dbi.rom >> 16, fp);
fputc(dbi.rom >> 24, fp);
fputc(dbi.ram >> 0, fp);
fputc(dbi.ram >> 8, fp);
fputc(dbi.ram >> 16, fp);
fputc(dbi.ram >> 24, fp);
}
void db_read(db_item &dbi, uint8 *data) {
dbi.crc32 = (*data++) << 0;
dbi.crc32 |= (*data++) << 8;
dbi.crc32 |= (*data++) << 16;
dbi.crc32 |= (*data++) << 24;
memcpy(dbi.name, data, 128); dbi.name[127] = 0; data += 128;
memcpy(dbi.pcb, data, 32); dbi.pcb [ 31] = 0; data += 32;
dbi.rom = (*data++) << 0;
dbi.rom |= (*data++) << 8;
dbi.rom |= (*data++) << 16;
dbi.rom |= (*data++) << 24;
dbi.ram = (*data++) << 0;
dbi.ram |= (*data++) << 8;
dbi.ram |= (*data++) << 16;
dbi.ram |= (*data++) << 24;
}

View File

@ -1,117 +0,0 @@
#include "../../lib/libbase.h"
#include "../../lib/libvector.h"
#include "../../lib/libstring.h"
#include "../../lib/libstring.cpp"
#include "db.h"
FILE *fp;
uint decode_size(string &str) {
//hex encoding
if(strbegin(str, "0x")) {
strltrim(str, "0x");
return strhex(str);
}
//mbit encoding
if(strend(str, "mbit")) {
strrtrim(str, "mbit");
return strdec(str) * 1024 * 1024 / 8;
}
//kbit encoding
if(strend(str, "kbit")) {
strrtrim(str, "kbit");
return strdec(str) * 1024 / 8;
}
//decimal encoding
return strdec(str);
}
void build_block(string &block) {
stringarray line, hashpart, part;
split(line, "\n", block);
if(strbegin(line[0], "[") == false) {
printf("error: invalid block detected: '%s'\n", strptr(line[0]));
return;
}
strltrim(line[0], "[");
strrtrim(line[0], "]");
replace(line[0], "0x", "");
split(hashpart, ",", line[0]);
db_item dbi;
dbi.crc32 = 0;
*dbi.name = 0;
*dbi.pcb = 0;
dbi.rom = 0;
dbi.ram = 0;
for(int i = 1; i < count(line); i++) {
int pos = strpos(line[i], ";");
if(pos >= 0) {
strptr(line[i])[pos] = 0;
}
if(line[i] == "")continue;
split(part, "=", line[i]);
strunquote(part[1]);
if(part[0] == "name") {
strncpy(dbi.name, strptr(part[1]), 128);
dbi.name[128] = 0;
}
if(part[0] == "pcb") {
strncpy(dbi.pcb, strptr(part[1]), 32);
dbi.pcb[31] = 0;
}
if(part[0] == "rom") {
dbi.rom = decode_size(part[1]);
}
if(part[0] == "ram") {
dbi.ram = decode_size(part[1]);
}
}
for(int i = 0; i < count(hashpart); i++) {
dbi.crc32 = strhex(hashpart[i]);
db_write(fp, dbi);
}
}
void build_database() {
stringarray data, block;
if(strfread(data, "cartdb.txt") == false)return;
fp = fopen("cart.db", "wb");
fprintf(fp, "SNESDB");
uint blocksize = 4 + 128 + 32 + 4 + 4;
fputc(blocksize >> 0, fp);
fputc(blocksize >> 8, fp);
replace (data, "\r", "");
qreplace(data, " ", "");
qreplace(data, "\t", "");
split(block, "\n\n", data);
for(int i = 0; i < count(block); i++) {
build_block(block[i]);
}
fclose(fp);
}
int main() {
build_database();
return 0;
}

View File

@ -1,5 +1,6 @@
::@make -r PLATFORM=win-mingw4-lui
@make -r PLATFORM=win-mingw-lui
::@make -r PLATFORM=win-mingw-lui GZIP_SUPPORT=true JMA_SUPPORT=true
::@make -r PLATFORM=win-visualc-lui
@make -r PLATFORM=win-visualc-lui GZIP_SUPPORT=true JMA_SUPPORT=true
::@make -r PLATFORM=win-visualc-lui GZIP_SUPPORT=true JMA_SUPPORT=true
@move bsnes.exe ../bsnes.exe>nul
@pause

View File

@ -1,2 +1,3 @@
#!/bin/sh
make PLATFORM=x-gcc-lui
make PLATFORM=x-gcc-lui
#make PLATFORM=x-gcc-lui GZIP_SUPPORT=true JMA_SUPPORT=true

5
src/chip/bsx/bsx.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "../../base.h"
#include "bsx_base.cpp"
#include "bsx_cart.cpp"
#include "bsx_flash.cpp"

77
src/chip/bsx/bsx.h Normal file
View File

@ -0,0 +1,77 @@
class BSXBase : public MMIO {
public:
void init();
void enable();
void power();
void reset();
uint8 mmio_read(uint addr);
void mmio_write(uint addr, uint8 data);
private:
struct {
uint8 r2188, r2189, r218a, r218b;
uint8 r218c, r218d, r218e, r218f;
uint8 r2190, r2191, r2192, r2193;
uint8 r2194, r2195, r2196, r2197;
uint8 r2198, r2199, r219a, r219b;
uint8 r219c, r219d, r219e, r219f;
uint8 r2192_counter;
uint8 r2192_hour, r2192_minute, r2192_second;
} regs;
};
class BSXCart : public MMIO {
public:
void init();
void enable();
void power();
void reset();
uint8 mmio_read(uint addr);
void mmio_write(uint addr, uint8 data);
MappedRAM sram;
MappedRAM psram;
BSXCart();
~BSXCart();
private:
uint8 *sram_data; //256kbit SRAM
uint8 *psram_data; // 4mbit PSRAM
struct {
uint8 r[16];
} regs;
void update_memory_map();
};
class BSXFlash : public Memory {
public:
void init();
void enable();
void power();
void reset();
uint size();
uint8 read(uint addr);
void write(uint addr, uint8 data);
private:
struct {
uint command;
uint8 write_old;
uint8 write_new;
bool flash_enable;
bool read_enable;
bool write_enable;
} regs;
};
extern BSXBase bsxbase;
extern BSXCart bsxcart;
extern BSXFlash bsxflash;

133
src/chip/bsx/bsx_base.cpp Normal file
View File

@ -0,0 +1,133 @@
void BSXBase::init() {
}
void BSXBase::enable() {
for(uint16 i = 0x2188; i <= 0x219f; i++) memory::mmio.map(i, *this);
}
void BSXBase::power() {
reset();
}
void BSXBase::reset() {
memset(&regs, 0x00, sizeof regs);
}
uint8 BSXBase::mmio_read(uint addr) {
addr &= 0xffff;
switch(addr) {
case 0x2188: return regs.r2188;
case 0x2189: return regs.r2189;
case 0x218a: return regs.r218a;
case 0x218c: return regs.r218c;
case 0x218e: return regs.r218e;
case 0x218f: return regs.r218f;
case 0x2190: return regs.r2190;
case 0x2192: {
uint counter = regs.r2192_counter++;
if(regs.r2192_counter >= 18) regs.r2192_counter = 0;
if(counter == 0) {
time_t rawtime;
time(&rawtime);
tm *t = localtime(&rawtime);
regs.r2192_hour = t->tm_hour;
regs.r2192_minute = t->tm_min;
regs.r2192_second = t->tm_sec;
}
switch(counter) {
case 0: return 0x00; //???
case 1: return 0x00; //???
case 2: return 0x00; //???
case 3: return 0x00; //???
case 4: return 0x00; //???
case 5: return 0x01;
case 6: return 0x01;
case 7: return 0x00;
case 8: return 0x00;
case 9: return 0x00;
case 10: return regs.r2192_second;
case 11: return regs.r2192_minute;
case 12: return regs.r2192_hour;
case 13: return 0x00; //???
case 14: return 0x00; //???
case 15: return 0x00; //???
case 16: return 0x00; //???
case 17: return 0x00; //???
}
} break;
case 0x2193: return regs.r2193 & ~0x0c;
case 0x2194: return regs.r2194;
case 0x2196: return regs.r2196;
case 0x2197: return regs.r2197;
case 0x2199: return regs.r2199;
}
return cpu.regs.mdr;
}
void BSXBase::mmio_write(uint addr, uint8 data) {
addr &= 0xffff;
switch(addr) {
case 0x2188: {
regs.r2188 = data;
} break;
case 0x2189: {
regs.r2189 = data;
} break;
case 0x218a: {
regs.r218a = data;
} break;
case 0x218b: {
regs.r218b = data;
} break;
case 0x218c: {
regs.r218c = data;
} break;
case 0x218e: {
regs.r218e = data;
} break;
case 0x218f: {
regs.r218e >>= 1;
regs.r218e = regs.r218f - regs.r218e;
regs.r218f >>= 1;
} break;
case 0x2191: {
regs.r2191 = data;
regs.r2192_counter = 0;
} break;
case 0x2192: {
regs.r2190 = 0x80;
} break;
case 0x2193: {
regs.r2193 = data;
} break;
case 0x2194: {
regs.r2194 = data;
} break;
case 0x2197: {
regs.r2197 = data;
} break;
case 0x2199: {
regs.r2199 = data;
} break;
}
}

95
src/chip/bsx/bsx_cart.cpp Normal file
View File

@ -0,0 +1,95 @@
void BSXCart::init() {
}
void BSXCart::enable() {
for(uint16 i = 0x5000; i <= 0x5fff; i++) memory::mmio.map(i, *this);
}
void BSXCart::power() {
reset();
}
void BSXCart::reset() {
for(uint i = 0; i < 16; i++) regs.r[i] = 0x00;
regs.r[0x07] = 0x80;
regs.r[0x08] = 0x80;
update_memory_map();
}
void BSXCart::update_memory_map() {
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram;
if((regs.r[0x02] & 0x80) == 0x00) { //LoROM mapping
bus.map(Bus::MapLinear, 0x00, 0x7d, 0x8000, 0xffff, cart);
bus.map(Bus::MapLinear, 0x80, 0xff, 0x8000, 0xffff, cart);
} else { //HiROM mapping
bus.map(Bus::MapShadow, 0x00, 0x3f, 0x8000, 0xffff, cart);
bus.map(Bus::MapLinear, 0x40, 0x7d, 0x0000, 0xffff, cart);
bus.map(Bus::MapShadow, 0x80, 0xbf, 0x8000, 0xffff, cart);
bus.map(Bus::MapLinear, 0xc0, 0xff, 0x0000, 0xffff, cart);
}
if(regs.r[0x03] & 0x80) {
bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, psram);
//bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
}
if((regs.r[0x05] & 0x80) == 0x00) {
bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, psram);
}
if((regs.r[0x06] & 0x80) == 0x00) {
bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, psram);
}
if(regs.r[0x07] & 0x80) {
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
}
if(regs.r[0x08] & 0x80) {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
}
bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, psram);
bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
}
uint8 BSXCart::mmio_read(uint addr) {
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
uint8 n = (addr >> 16) & 15;
return regs.r[n];
}
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
return sram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff));
}
return 0x00;
}
void BSXCart::mmio_write(uint addr, uint8 data) {
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
uint8 n = (addr >> 16) & 15;
regs.r[n] = data;
if(n == 0x0e && data & 0x80) update_memory_map();
return;
}
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
return sram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
}
}
BSXCart::BSXCart() {
sram_data = (uint8*)malloc( 32 * 1024);
psram_data = (uint8*)malloc(512 * 1024);
sram.map (sram_data, 32 * 1024);
psram.map(psram_data, 512 * 1024);
}
BSXCart::~BSXCart() {
safe_free(sram_data);
safe_free(psram_data);
}

109
src/chip/bsx/bsx_flash.cpp Normal file
View File

@ -0,0 +1,109 @@
void BSXFlash::init() {}
void BSXFlash::enable() {}
void BSXFlash::power() {
reset();
}
void BSXFlash::reset() {
regs.command = 0;
regs.write_old = 0x00;
regs.write_new = 0x00;
regs.flash_enable = false;
regs.read_enable = false;
regs.write_enable = false;
}
uint BSXFlash::size() {
return memory::bscram.size();
}
uint8 BSXFlash::read(uint addr) {
if(addr == 0x0002) {
if(regs.flash_enable) return 0x80;
}
if(addr == 0x5555) {
if(regs.flash_enable) return 0x80;
}
if(regs.read_enable && addr >= 0xff00 && addr <= 0xff13) {
//read flash cartridge vendor information
switch(addr - 0xff00) {
case 0x00: return 0x4d;
case 0x01: return 0x00;
case 0x02: return 0x50;
case 0x03: return 0x00;
case 0x04: return 0x00;
case 0x05: return 0x00;
case 0x06: return 0x2a; //0x2a = 8mbit, 0x2b = 16mbit (not known to exist, though BIOS recognizes ID)
case 0x07: return 0x00;
default: return 0x00;
}
}
return memory::bscram.read(addr);
}
void BSXFlash::write(uint addr, uint8 data) {
//there exist both read-only and read-write BS-X flash cartridges ...
//unfortunately, the vendor info is not stored inside memory dumps
//of BS-X flashcarts, so it is impossible to determine whether a
//given flashcart is writeable.
//however, it has been observed that LoROM-mapped BS-X carts always
//use read-write flashcarts, and HiROM-mapped BS-X carts always use
//read-only flashcarts.
//below is an unfortunately necessary workaround to this problem.
if(cartridge.mapper() == Cartridge::BSCHiROM) return;
if((addr & 0xff0000) == 0) {
regs.write_old = regs.write_new;
regs.write_new = data;
if(regs.write_enable && regs.write_old == regs.write_new) {
return memory::bscram.write(addr, data);
}
} else {
if(regs.write_enable) {
return memory::bscram.write(addr, data);
}
}
if(addr == 0x0000) {
regs.command <<= 8;
regs.command |= data;
if((regs.command & 0xffff) == 0x38d0) {
regs.flash_enable = true;
regs.read_enable = true;
}
}
if(addr == 0x2aaa) {
regs.command <<= 8;
regs.command |= data;
}
if(addr == 0x5555) {
regs.command <<= 8;
regs.command |= data;
if((regs.command & 0xffffff) == 0xaa5570) {
regs.write_enable = false;
}
if((regs.command & 0xffffff) == 0xaa55a0) {
regs.write_old = 0x00;
regs.write_new = 0x00;
regs.flash_enable = true;
regs.write_enable = true;
}
if((regs.command & 0xffffff) == 0xaa55f0) {
regs.flash_enable = false;
regs.read_enable = false;
regs.write_enable = false;
}
}
}

11
src/chip/chip.h Normal file
View File

@ -0,0 +1,11 @@
#include "bsx/bsx.h"
#include "superfx/superfx.h"
#include "srtc/srtc.h"
#include "sdd1/sdd1.h"
#include "cx4/cx4.h"
#include "dsp1/dsp1.h"
#include "dsp2/dsp2.h"
#include "dsp3/dsp3.h"
#include "dsp4/dsp4.h"
#include "obc1/obc1.h"
#include "st010/st010.h"

View File

@ -7,27 +7,27 @@
#include "../../base.h"
#include "c4data.cpp"
#include "c4fn.cpp"
#include "c4oam.cpp"
#include "c4ops.cpp"
#include "cx4data.cpp"
#include "cx4fn.cpp"
#include "cx4oam.cpp"
#include "cx4ops.cpp"
void C4::init() {}
void C4::enable() {}
void Cx4::init() {}
void Cx4::enable() {}
uint32 C4::ldr(uint8 r) {
uint32 Cx4::ldr(uint8 r) {
uint16 addr = 0x0080 + (r * 3);
return (reg[addr]) | (reg[addr + 1] << 8) | (reg[addr + 2] << 16);
}
void C4::str(uint8 r, uint32 data) {
void Cx4::str(uint8 r, uint32 data) {
uint16 addr = 0x0080 + (r * 3);
reg[addr ] = (data);
reg[addr + 1] = (data >> 8);
reg[addr + 2] = (data >> 16);
}
void C4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
int64 rx = x & 0xffffff;
int64 ry = y & 0xffffff;
if(rx & 0x800000)rx |= ~0x7fffff;
@ -39,7 +39,7 @@ int64 ry = y & 0xffffff;
rh = (rx >> 24) & 0xffffff;
}
uint32 C4::sin(uint32 rx) {
uint32 Cx4::sin(uint32 rx) {
r0 = rx & 0x1ff;
if(r0 & 0x100)r0 ^= 0x1ff;
if(r0 & 0x080)r0 ^= 0x0ff;
@ -50,13 +50,13 @@ uint32 C4::sin(uint32 rx) {
}
}
uint32 C4::cos(uint32 rx) {
uint32 Cx4::cos(uint32 rx) {
return sin(rx + 0x080);
}
void C4::immediate_reg(uint32 start) {
void Cx4::immediate_reg(uint32 start) {
r0 = ldr(0);
for(uint32 i=start;i<48;i++) {
for(uint32 i = start; i < 48; i++) {
if((r0 & 0x0fff) < 0x0c00) {
ram[r0 & 0x0fff] = immediate_data[i];
}
@ -65,7 +65,7 @@ void C4::immediate_reg(uint32 start) {
str(0, r0);
}
void C4::transfer_data() {
void Cx4::transfer_data() {
uint32 src;
uint16 dest, count;
src = (reg[0x40]) | (reg[0x41] << 8) | (reg[0x42] << 16);
@ -73,11 +73,11 @@ uint16 dest, count;
dest = (reg[0x45]) | (reg[0x46] << 8);
for(uint32 i=0;i<count;i++) {
write(dest++, r_mem->read(src++));
write(dest++, bus.read(src++));
}
}
void C4::write(uint16 addr, uint8 data) {
void Cx4::write(uint addr, uint8 data) {
addr &= 0x1fff;
if(addr < 0x0c00) {
@ -109,57 +109,57 @@ void C4::write(uint16 addr, uint8 data) {
}
switch(data) {
case 0x00:op00();break;
case 0x01:op01();break;
case 0x05:op05();break;
case 0x0d:op0d();break;
case 0x10:op10();break;
case 0x13:op13();break;
case 0x15:op15();break;
case 0x1f:op1f();break;
case 0x22:op22();break;
case 0x25:op25();break;
case 0x2d:op2d();break;
case 0x40:op40();break;
case 0x54:op54();break;
case 0x5c:op5c();break;
case 0x5e:op5e();break;
case 0x60:op60();break;
case 0x62:op62();break;
case 0x64:op64();break;
case 0x66:op66();break;
case 0x68:op68();break;
case 0x6a:op6a();break;
case 0x6c:op6c();break;
case 0x6e:op6e();break;
case 0x70:op70();break;
case 0x72:op72();break;
case 0x74:op74();break;
case 0x76:op76();break;
case 0x78:op78();break;
case 0x7a:op7a();break;
case 0x7c:op7c();break;
case 0x89:op89();break;
case 0x00: op00(); break;
case 0x01: op01(); break;
case 0x05: op05(); break;
case 0x0d: op0d(); break;
case 0x10: op10(); break;
case 0x13: op13(); break;
case 0x15: op15(); break;
case 0x1f: op1f(); break;
case 0x22: op22(); break;
case 0x25: op25(); break;
case 0x2d: op2d(); break;
case 0x40: op40(); break;
case 0x54: op54(); break;
case 0x5c: op5c(); break;
case 0x5e: op5e(); break;
case 0x60: op60(); break;
case 0x62: op62(); break;
case 0x64: op64(); break;
case 0x66: op66(); break;
case 0x68: op68(); break;
case 0x6a: op6a(); break;
case 0x6c: op6c(); break;
case 0x6e: op6e(); break;
case 0x70: op70(); break;
case 0x72: op72(); break;
case 0x74: op74(); break;
case 0x76: op76(); break;
case 0x78: op78(); break;
case 0x7a: op7a(); break;
case 0x7c: op7c(); break;
case 0x89: op89(); break;
}
}
}
void C4::writeb(uint16 addr, uint8 data) {
void Cx4::writeb(uint16 addr, uint8 data) {
write(addr, data);
}
void C4::writew(uint16 addr, uint16 data) {
void Cx4::writew(uint16 addr, uint16 data) {
write(addr, data);
write(addr + 1, data >> 8);
}
void C4::writel(uint16 addr, uint32 data) {
void Cx4::writel(uint16 addr, uint32 data) {
write(addr, data);
write(addr + 1, data >> 8);
write(addr + 2, data >> 16);
}
uint8 C4::read(uint16 addr) {
uint8 Cx4::read(uint addr) {
addr &= 0x1fff;
if(addr < 0x0c00) {
@ -170,28 +170,26 @@ uint8 C4::read(uint16 addr) {
return reg[addr & 0xff];
}
return r_cpu->regs.mdr;
return cpu.regs.mdr;
}
uint8 C4::readb(uint16 addr) {
uint8 Cx4::readb(uint16 addr) {
return read(addr);
}
uint16 C4::readw(uint16 addr) {
uint16 Cx4::readw(uint16 addr) {
return read(addr) | (read(addr + 1) << 8);
}
uint32 C4::readl(uint16 addr) {
uint32 Cx4::readl(uint16 addr) {
return read(addr) | (read(addr + 1) << 8) + (read(addr + 2) << 16);
}
void C4::power() {
void Cx4::power() {
reset();
}
void C4::reset() {
void Cx4::reset() {
memset(ram, 0, 0x0c00);
memset(reg, 0, 0x0100);
}
C4::C4() {}

View File

@ -1,29 +1,29 @@
class C4 {
class Cx4 : public Memory {
private:
uint8 ram[0x0c00];
uint8 reg[0x0100];
uint32 r0, r1, r2, r3, r4, r5, r6, r7,
r8, r9, r10, r11, r12, r13, r14, r15;
uint8 ram[0x0c00];
uint8 reg[0x0100];
uint32 r0, r1, r2, r3, r4, r5, r6, r7,
r8, r9, r10, r11, r12, r13, r14, r15;
static const uint8 immediate_data[48];
static const uint16 wave_data[40];
static const uint32 sin_table[256];
static const uint8 immediate_data[48];
static const uint16 wave_data[40];
static const uint32 sin_table[256];
static const int16 SinTable[512];
static const int16 CosTable[512];
static const int16 SinTable[512];
static const int16 CosTable[512];
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
double tanval;
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
double tanval;
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
void C4TransfWireFrame();
void C4TransfWireFrame2();
void C4CalcWireFrame();
void C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color);
void C4DrawWireFrame();
void C4DoScaleRotate(int row_padding);
void C4TransfWireFrame();
void C4TransfWireFrame2();
void C4CalcWireFrame();
void C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color);
void C4DrawWireFrame();
void C4DoScaleRotate(int row_padding);
public:
uint32 ldr(uint8 r);
@ -75,22 +75,23 @@ public:
void op7c();
void op89();
uint8 readb(uint16 addr);
uint16 readw(uint16 addr);
uint32 readl(uint16 addr);
void writeb(uint16 addr, uint8 data);
void writew(uint16 addr, uint16 data);
void writel(uint16 addr, uint32 data);
//
void init();
void enable();
void power();
void reset();
void write (uint16 addr, uint8 data);
void writeb(uint16 addr, uint8 data);
void writew(uint16 addr, uint16 data);
void writel(uint16 addr, uint32 data);
uint8 read (uint16 addr);
uint8 readb(uint16 addr);
uint16 readw(uint16 addr);
uint32 readl(uint16 addr);
C4();
uint8 read (uint addr);
void write(uint addr, uint8 data);
};
extern C4 c4;
extern Cx4 cx4;

View File

@ -1,11 +1,11 @@
const uint8 C4::immediate_data[48] = {
const uint8 Cx4::immediate_data[48] = {
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f,
0x00, 0x80, 0x00, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0xff,
0x00, 0x00, 0x01, 0xff, 0xff, 0xfe, 0x00, 0x01, 0x00, 0xff, 0xfe, 0x00
};
const uint16 C4::wave_data[40] = {
const uint16 Cx4::wave_data[40] = {
0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020a, 0x020c, 0x020e,
0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e,
@ -13,7 +13,7 @@ const uint16 C4::wave_data[40] = {
0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080a, 0x080c, 0x080e
};
const uint32 C4::sin_table[256] = {
const uint32 Cx4::sin_table[256] = {
0x000000, 0x000324, 0x000648, 0x00096c, 0x000c8f, 0x000fb2, 0x0012d5, 0x0015f6,
0x001917, 0x001c37, 0x001f56, 0x002273, 0x002590, 0x0028aa, 0x002bc4, 0x002edb,
0x0031f1, 0x003505, 0x003817, 0x003b26, 0x003e33, 0x00413e, 0x004447, 0x00474d,
@ -48,7 +48,7 @@ const uint32 C4::sin_table[256] = {
0xff013b, 0xff00f1, 0xff00b1, 0xff007b, 0xff004e, 0xff002c, 0xff0013, 0xff0004
};
const int16 C4::SinTable[512] = {
const int16 Cx4::SinTable[512] = {
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
@ -115,7 +115,7 @@ const int16 C4::SinTable[512] = {
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402
};
const int16 C4::CosTable[512] = {
const int16 Cx4::CosTable[512] = {
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,

View File

@ -7,7 +7,7 @@
#define PI 3.1415926535897932384626433832795
//Wireframe Helpers
void C4::C4TransfWireFrame() {
void Cx4::C4TransfWireFrame() {
c4x = (double)C4WFXVal;
c4y = (double)C4WFYVal;
c4z = (double)C4WFZVal - 0x95;
@ -32,7 +32,7 @@ void C4::C4TransfWireFrame() {
C4WFYVal = (int16)(c4y * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
}
void C4::C4CalcWireFrame() {
void Cx4::C4CalcWireFrame() {
C4WFXVal = C4WFX2Val - C4WFXVal;
C4WFYVal = C4WFY2Val - C4WFYVal;
@ -49,7 +49,7 @@ void C4::C4CalcWireFrame() {
}
}
void C4::C4TransfWireFrame2() {
void Cx4::C4TransfWireFrame2() {
c4x = (double)C4WFXVal;
c4y = (double)C4WFYVal;
c4z = (double)C4WFZVal;
@ -74,34 +74,34 @@ void C4::C4TransfWireFrame2() {
C4WFYVal = (int16)(c4y * C4WFScale / 0x100);
}
void C4::C4DrawWireFrame() {
void Cx4::C4DrawWireFrame() {
uint32 line = readl(0x1f80);
uint32 point1, point2;
int16 X1, Y1, Z1;
int16 X2, Y2, Z2;
uint8 Color;
for(int32 i = ram[0x0295]; i > 0; i--, line += 5) {
if(r_mem->read(line) == 0xff && r_mem->read(line + 1) == 0xff) {
if(bus.read(line) == 0xff && bus.read(line + 1) == 0xff) {
int32 tmp = line - 5;
while(r_mem->read(tmp + 2) == 0xff && r_mem->read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
point1 = (read(0x1f82) << 16) | (r_mem->read(tmp + 2) << 8) | r_mem->read(tmp + 3);
while(bus.read(tmp + 2) == 0xff && bus.read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
point1 = (read(0x1f82) << 16) | (bus.read(tmp + 2) << 8) | bus.read(tmp + 3);
} else {
point1 = (read(0x1f82) << 16) | (r_mem->read(line) << 8) | r_mem->read(line + 1);
point1 = (read(0x1f82) << 16) | (bus.read(line) << 8) | bus.read(line + 1);
}
point2 = (read(0x1f82) << 16) | (r_mem->read(line + 2) << 8) | r_mem->read(line + 3);
point2 = (read(0x1f82) << 16) | (bus.read(line + 2) << 8) | bus.read(line + 3);
X1=(r_mem->read(point1 + 0) << 8) | r_mem->read(point1 + 1);
Y1=(r_mem->read(point1 + 2) << 8) | r_mem->read(point1 + 3);
Z1=(r_mem->read(point1 + 4) << 8) | r_mem->read(point1 + 5);
X2=(r_mem->read(point2 + 0) << 8) | r_mem->read(point2 + 1);
Y2=(r_mem->read(point2 + 2) << 8) | r_mem->read(point2 + 3);
Z2=(r_mem->read(point2 + 4) << 8) | r_mem->read(point2 + 5);
Color = r_mem->read(line + 4);
X1=(bus.read(point1 + 0) << 8) | bus.read(point1 + 1);
Y1=(bus.read(point1 + 2) << 8) | bus.read(point1 + 3);
Z1=(bus.read(point1 + 4) << 8) | bus.read(point1 + 5);
X2=(bus.read(point2 + 0) << 8) | bus.read(point2 + 1);
Y2=(bus.read(point2 + 2) << 8) | bus.read(point2 + 3);
Z2=(bus.read(point2 + 4) << 8) | bus.read(point2 + 5);
Color = bus.read(line + 4);
C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color);
}
}
void C4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
//Transform coordinates
C4WFXVal = (int16)X1;
C4WFYVal = (int16)Y1;
@ -145,7 +145,7 @@ void C4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2,
}
}
void C4::C4DoScaleRotate(int row_padding) {
void Cx4::C4DoScaleRotate(int row_padding) {
int16 A, B, C, D;
//Calculate matrix

View File

@ -1,5 +1,5 @@
//Build OAM
void C4::op00_00() {
void Cx4::op00_00() {
uint32 oamptr = ram[0x626] << 2;
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
//clear oam-to-be
@ -27,28 +27,28 @@ uint32 srcptr = 0x220;
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
uint32 spraddr = readl(srcptr + 7);
if(r_mem->read(spraddr)) {
if(bus.read(spraddr)) {
int16 x, y;
for(int sprcnt = r_mem->read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
x = (int8)r_mem->read(spraddr + 1);
for(int sprcnt = bus.read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
x = (int8)bus.read(spraddr + 1);
if(sprattr & 0x40) {
x = -x - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
x = -x - ((bus.read(spraddr) & 0x20) ? 16 : 8);
}
x += sprx;
if(x >= -16 && x <= 272) {
y = (int8)r_mem->read(spraddr + 2);
y = (int8)bus.read(spraddr + 2);
if(sprattr & 0x80) {
y = -y - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
y = -y - ((bus.read(spraddr) & 0x20) ? 16 : 8);
}
y += spry;
if(y >= -16 && y <= 224) {
ram[oamptr ] = (uint8)x;
ram[oamptr + 1] = (uint8)y;
ram[oamptr + 2] = sprname + r_mem->read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (r_mem->read(spraddr) & 0xc0);
ram[oamptr + 2] = sprname + bus.read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (bus.read(spraddr) & 0xc0);
ram[oamptr2] &= ~(3 << offset);
if(x & 0x100)ram[oamptr2] |= 1 << offset;
if(r_mem->read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
if(bus.read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
@ -73,12 +73,12 @@ uint32 srcptr = 0x220;
}
//Scale and Rotate
void C4::op00_03() {
void Cx4::op00_03() {
C4DoScaleRotate(0);
}
//Transform Lines
void C4::op00_05() {
void Cx4::op00_05() {
C4WFX2Val = read(0x1f83);
C4WFY2Val = read(0x1f86);
C4WFDist = read(0x1f89);
@ -119,17 +119,17 @@ uint32 ptr2 = 0;
}
//Scale and Rotate
void C4::op00_07() {
void Cx4::op00_07() {
C4DoScaleRotate(64);
}
//Draw Wireframe
void C4::op00_08() {
void Cx4::op00_08() {
C4DrawWireFrame();
}
//Disintegrate
void C4::op00_0b() {
void Cx4::op00_0b() {
uint8 width, height;
uint32 startx, starty;
uint32 srcptr;
@ -169,7 +169,7 @@ int32 i, j;
}
//Bitplane Wave
void C4::op00_0c() {
void Cx4::op00_0c() {
uint32 destptr = 0;
uint32 waveptr = read(0x1f83);
uint16 mask1 = 0xc0c0;

View File

@ -1,5 +1,5 @@
//Sprite Functions
void C4::op00() {
void Cx4::op00() {
switch(reg[0x4d]) {
case 0x00:op00_00();break;
case 0x03:op00_03();break;
@ -12,13 +12,13 @@ void C4::op00() {
}
//Draw Wireframe
void C4::op01() {
void Cx4::op01() {
memset(ram + 0x300, 0, 2304);
C4DrawWireFrame();
}
//Propulsion
void C4::op05() {
void Cx4::op05() {
int32 temp = 0x10000;
if(readw(0x1f83)) {
temp = sar((temp / readw(0x1f83)) * readw(0x1f81), 8);
@ -27,7 +27,7 @@ int32 temp = 0x10000;
}
//Set Vector length
void C4::op0d() {
void Cx4::op0d() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
C41FDistVal = readw(0x1f86);
@ -40,7 +40,7 @@ void C4::op0d() {
}
//Triangle
void C4::op10() {
void Cx4::op10() {
r0 = ldr(0);
r1 = ldr(1);
@ -64,7 +64,7 @@ void C4::op10() {
}
//Triangle
void C4::op13() {
void Cx4::op13() {
r0 = ldr(0);
r1 = ldr(1);
@ -87,7 +87,7 @@ void C4::op13() {
}
//Pythagorean
void C4::op15() {
void Cx4::op15() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
C41FDist = (int16)sqrt((double)C41FXVal * (double)C41FXVal + (double)C41FYVal * (double)C41FYVal);
@ -95,7 +95,7 @@ void C4::op15() {
}
//Calculate distance
void C4::op1f() {
void Cx4::op1f() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
if(!C41FXVal) {
@ -113,7 +113,7 @@ void C4::op1f() {
}
//Trapezoid
void C4::op22() {
void Cx4::op22() {
int16 angle1 = readw(0x1f8c) & 0x1ff;
int16 angle2 = readw(0x1f8f) & 0x1ff;
int32 tan1 = Tan(angle1);
@ -152,7 +152,7 @@ int16 left, right;
}
//Multiply
void C4::op25() {
void Cx4::op25() {
r0 = ldr(0);
r1 = ldr(1);
mul(r0, r1, r0, r1);
@ -161,7 +161,7 @@ void C4::op25() {
}
//Transform Coords
void C4::op2d() {
void Cx4::op2d() {
C4WFXVal = readw(0x1f81);
C4WFYVal = readw(0x1f84);
C4WFZVal = readw(0x1f87);
@ -175,7 +175,7 @@ void C4::op2d() {
}
//Sum
void C4::op40() {
void Cx4::op40() {
r0 = 0;
for(uint32 i=0;i<0x800;i++) {
r0 += ram[i];
@ -184,7 +184,7 @@ void C4::op40() {
}
//Square
void C4::op54() {
void Cx4::op54() {
r0 = ldr(0);
mul(r0, r0, r1, r2);
str(1, r1);
@ -192,31 +192,31 @@ void C4::op54() {
}
//Immediate Register
void C4::op5c() {
void Cx4::op5c() {
str(0, 0x000000);
immediate_reg(0);
}
//Immediate Register (Multiple)
void C4::op5e() { immediate_reg( 0); }
void C4::op60() { immediate_reg( 3); }
void C4::op62() { immediate_reg( 6); }
void C4::op64() { immediate_reg( 9); }
void C4::op66() { immediate_reg(12); }
void C4::op68() { immediate_reg(15); }
void C4::op6a() { immediate_reg(18); }
void C4::op6c() { immediate_reg(21); }
void C4::op6e() { immediate_reg(24); }
void C4::op70() { immediate_reg(27); }
void C4::op72() { immediate_reg(30); }
void C4::op74() { immediate_reg(33); }
void C4::op76() { immediate_reg(36); }
void C4::op78() { immediate_reg(39); }
void C4::op7a() { immediate_reg(42); }
void C4::op7c() { immediate_reg(45); }
void Cx4::op5e() { immediate_reg( 0); }
void Cx4::op60() { immediate_reg( 3); }
void Cx4::op62() { immediate_reg( 6); }
void Cx4::op64() { immediate_reg( 9); }
void Cx4::op66() { immediate_reg(12); }
void Cx4::op68() { immediate_reg(15); }
void Cx4::op6a() { immediate_reg(18); }
void Cx4::op6c() { immediate_reg(21); }
void Cx4::op6e() { immediate_reg(24); }
void Cx4::op70() { immediate_reg(27); }
void Cx4::op72() { immediate_reg(30); }
void Cx4::op74() { immediate_reg(33); }
void Cx4::op76() { immediate_reg(36); }
void Cx4::op78() { immediate_reg(39); }
void Cx4::op7a() { immediate_reg(42); }
void Cx4::op7c() { immediate_reg(45); }
//Immediate ROM
void C4::op89() {
void Cx4::op89() {
str(0, 0x054336);
str(1, 0xffffff);
}

View File

@ -26,29 +26,30 @@ void DSP1::reset() {
*****/
bool DSP1::addr_decode(uint16 addr) {
switch(cartridge.info.dsp1_mapper) {
case Cartridge::DSP1LoROM1MB: {
//$[20-3f]:[8000-bfff] = DR, $[20-3f]:[c000-ffff] = SR
return (addr >= 0xc000);
}
case Cartridge::DSP1_LOROM_1MB:
//$[20-3f]:[8000-bfff] = DR, $[20-3f]:[c000-ffff] = SR
return (addr >= 0xc000);
case Cartridge::DSP1_LOROM_2MB:
//$[60-6f]:[0000-3fff] = DR, $[60-6f]:[4000-7fff] = SR
return (addr >= 0x4000);
case Cartridge::DSP1_HIROM:
//$[00-1f]:[6000-6fff] = DR, $[00-1f]:[7000-7fff] = SR
return (addr >= 0x7000);
case Cartridge::DSP1LoROM2MB: {
//$[60-6f]:[0000-3fff] = DR, $[60-6f]:[4000-7fff] = SR
return (addr >= 0x4000);
}
case Cartridge::DSP1HiROM: {
//$[00-1f]:[6000-6fff] = DR, $[00-1f]:[7000-7fff] = SR
return (addr >= 0x7000);
}
}
return 0;
}
uint8 DSP1::read(uint16 addr) {
uint8 DSP1::read(uint addr) {
return (addr_decode(addr) == 0) ? dsp1.getDr() : dsp1.getSr();
}
void DSP1::write(uint16 addr, uint8 data) {
void DSP1::write(uint addr, uint8 data) {
if(addr_decode(addr) == 0) {
dsp1.setDr(data);
}

View File

@ -1,18 +1,18 @@
#include "dsp1emu.h"
class DSP1 {
class DSP1 : public Memory {
private:
Dsp1 dsp1;
Dsp1 dsp1;
bool addr_decode(uint16 addr);
public:
void init();
void enable();
void power();
void reset();
void init();
void enable();
void power();
void reset();
bool addr_decode(uint16 addr);
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
uint8 read(uint addr);
void write(uint addr, uint8 data);
};
extern DSP1 dsp1;

View File

@ -28,7 +28,7 @@ void DSP2::reset() {
status.op0dinlen = 0;
}
uint8 DSP2::read(uint16 addr) {
uint8 DSP2::read(uint addr) {
uint8 r = 0xff;
if(status.out_count) {
r = status.output[status.out_index++];
@ -40,7 +40,7 @@ uint8 r = 0xff;
return r;
}
void DSP2::write(uint16 addr, uint8 data) {
void DSP2::write(uint addr, uint8 data) {
if(status.waiting_for_command) {
status.command = data;
status.in_index = 0;

View File

@ -1,42 +1,44 @@
class DSP2 { public:
struct {
bool waiting_for_command;
uint command;
uint in_count, in_index;
uint out_count, out_index;
class DSP2 : public Memory {
public:
struct {
bool waiting_for_command;
uint command;
uint in_count, in_index;
uint out_count, out_index;
uint8 parameters[512];
uint8 output[512];
uint8 parameters[512];
uint8 output[512];
uint8 op05transparent;
bool op05haslen;
int op05len;
bool op06haslen;
int op06len;
uint16 op09word1;
uint16 op09word2;
bool op0dhaslen;
int op0doutlen;
int op0dinlen;
} status;
uint8 op05transparent;
bool op05haslen;
int op05len;
bool op06haslen;
int op06len;
uint16 op09word1;
uint16 op09word2;
bool op0dhaslen;
int op0doutlen;
int op0dinlen;
} status;
void init();
void enable();
void power();
void reset();
void init();
void enable();
void power();
void reset();
void op01();
void op03();
void op05();
void op06();
void op09();
void op0d();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
uint8 read(uint addr);
void write(uint addr, uint8 data);
DSP2();
~DSP2();
protected:
void op01();
void op03();
void op05();
void op06();
void op09();
void op0d();
};
extern DSP2 dsp2;

View File

@ -1,7 +1,7 @@
#include "../../base.h"
namespace DSP3i {
#define bool8 bool
#define bool8 uint8
#include "dsp3emu.c"
#undef bool8
};
@ -20,14 +20,14 @@ void DSP3::reset() {
DSP3i::DSP3_Reset();
}
uint8 DSP3::read(uint16 addr) {
DSP3i::dsp3_address = addr;
uint8 DSP3::read(uint addr) {
DSP3i::dsp3_address = addr & 0xffff;
DSP3i::DSP3GetByte();
return DSP3i::dsp3_byte;
}
void DSP3::write(uint16 addr, uint8 data) {
DSP3i::dsp3_address = addr;
void DSP3::write(uint addr, uint8 data) {
DSP3i::dsp3_address = addr & 0xffff;
DSP3i::dsp3_byte = data;
DSP3i::DSP3SetByte();
}

View File

@ -1,11 +1,12 @@
class DSP3 { public:
class DSP3 : public Memory {
public:
void init();
void enable();
void power();
void reset();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
uint8 read (uint addr);
void write(uint addr, uint8 data);
};
extern DSP3 dsp3;

View File

@ -14,7 +14,7 @@ namespace DSP4i {
addr[1] = data >> 8;
}
#define bool8 bool
#define bool8 uint8
#include "dsp4emu.c"
#undef bool8
};
@ -33,7 +33,8 @@ void DSP4::reset() {
DSP4i::InitDSP4();
}
uint8 DSP4::read(uint16 addr) {
uint8 DSP4::read(uint addr) {
addr &= 0xffff;
if(addr < 0xc000) {
DSP4i::dsp4_address = addr;
DSP4i::DSP4GetByte();
@ -42,7 +43,8 @@ uint8 DSP4::read(uint16 addr) {
return 0x80;
}
void DSP4::write(uint16 addr, uint8 data) {
void DSP4::write(uint addr, uint8 data) {
addr &= 0xffff;
if(addr < 0xc000) {
DSP4i::dsp4_address = addr;
DSP4i::dsp4_byte = data;

View File

@ -1,11 +1,12 @@
class DSP4 { public:
class DSP4 : public Memory {
public:
void init();
void enable();
void power();
void reset();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
uint8 read (uint addr);
void write(uint addr, uint8 data);
};
extern DSP4 dsp4;

View File

@ -8,81 +8,82 @@ void OBC1::power() {
}
void OBC1::reset() {
memset(cartridge.ram, 0xff, 0x2000);
status.baseptr = (cartridge.ram[0x1ff5] & 1) ? 0x1800 : 0x1c00;
status.address = (cartridge.ram[0x1ff6] & 0x7f);
status.shift = (cartridge.ram[0x1ff6] & 3) << 1;
for(uint i = 0x0000; i <= 0x1fff; i++) ram_write(i, 0xff);
status.baseptr = (ram_read(0x1ff5) & 1) ? 0x1800 : 0x1c00;
status.address = (ram_read(0x1ff6) & 0x7f);
status.shift = (ram_read(0x1ff6) & 3) << 1;
}
uint8 OBC1::read(uint16 addr) {
uint8 OBC1::read(uint addr) {
addr &= 0x1fff;
if((addr & 0x1ff8) != 0x1ff0) {
return cartridge.ram[addr];
}
if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr);
switch(addr) {
case 0x1ff0:
return cartridge.ram[status.baseptr + (status.address << 2) + 0];
return ram_read(status.baseptr + (status.address << 2) + 0);
case 0x1ff1:
return cartridge.ram[status.baseptr + (status.address << 2) + 1];
return ram_read(status.baseptr + (status.address << 2) + 1);
case 0x1ff2:
return cartridge.ram[status.baseptr + (status.address << 2) + 2];
return ram_read(status.baseptr + (status.address << 2) + 2);
case 0x1ff3:
return cartridge.ram[status.baseptr + (status.address << 2) + 3];
return ram_read(status.baseptr + (status.address << 2) + 3);
case 0x1ff4:
return cartridge.ram[status.baseptr + (status.address >> 2) + 0x200];
return ram_read(status.baseptr + (status.address >> 2) + 0x200);
case 0x1ff5:
case 0x1ff6:
case 0x1ff7:
return cartridge.ram[addr];
return ram_read(addr);
}
//never used, blocks compiler warning
return 0x00;
return 0x00; //never used, avoids compiler warning
}
void OBC1::write(uint16 addr, uint8 data) {
void OBC1::write(uint addr, uint8 data) {
addr &= 0x1fff;
if((addr & 0x1ff8) != 0x1ff0) {
cartridge.ram[addr] = data;
return;
}
if((addr & 0x1ff8) != 0x1ff0) return ram_write(addr, data);
switch(addr) {
case 0x1ff0:
cartridge.ram[status.baseptr + (status.address << 2) + 0] = data;
ram_write(status.baseptr + (status.address << 2) + 0, data);
break;
case 0x1ff1:
cartridge.ram[status.baseptr + (status.address << 2) + 1] = data;
ram_write(status.baseptr + (status.address << 2) + 1, data);
break;
case 0x1ff2:
cartridge.ram[status.baseptr + (status.address << 2) + 2] = data;
ram_write(status.baseptr + (status.address << 2) + 2, data);
break;
case 0x1ff3:
cartridge.ram[status.baseptr + (status.address << 2) + 3] = data;
ram_write(status.baseptr + (status.address << 2) + 3, data);
break;
case 0x1ff4: {
uint8 temp;
temp = cartridge.ram[status.baseptr + (status.address >> 2) + 0x200];
temp = ram_read(status.baseptr + (status.address >> 2) + 0x200);
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
cartridge.ram[status.baseptr + (status.address >> 2) + 0x200] = temp;
ram_write(status.baseptr + (status.address >> 2) + 0x200, temp);
} break;
case 0x1ff5:
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
cartridge.ram[addr] = data;
ram_write(addr, data);
break;
case 0x1ff6:
status.address = (data & 0x7f);
status.shift = (data & 3) << 1;
cartridge.ram[addr] = data;
ram_write(addr, data);
break;
case 0x1ff7:
cartridge.ram[addr] = data;
ram_write(addr, data);
break;
}
}
uint8 OBC1::ram_read(uint addr) {
return memory::cartram.read(addr & 0x1fff);
}
void OBC1::ram_write(uint addr, uint8 data) {
memory::cartram.write(addr & 0x1fff, data);
}
OBC1::OBC1() {}
OBC1::~OBC1() {}

View File

@ -1,20 +1,25 @@
class OBC1 {
class OBC1 : public Memory {
public:
struct {
uint16 address;
uint16 baseptr;
uint16 shift;
} status;
void init();
void enable();
void power();
void reset();
void init();
void enable();
void power();
void reset();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
uint8 read(uint addr);
void write(uint addr, uint8 data);
OBC1();
~OBC1();
private:
uint8 ram_read(uint addr);
void ram_write(uint addr, uint8 data);
struct {
uint16 address;
uint16 baseptr;
uint16 shift;
} status;
};
extern OBC1 obc1;

View File

@ -5,9 +5,7 @@
void SDD1::init() {}
void SDD1::enable() {
for(int i = 0x4800; i <= 0x4807; i++) {
r_mem->set_mmio_mapper(i, this);
}
for(int i = 0x4800; i <= 0x4807; i++) memory::mmio.map(i, *this);
}
void SDD1::power() {
@ -15,59 +13,80 @@ void SDD1::power() {
}
void SDD1::reset() {
sdd1.index[0] = 0x000000;
sdd1.index[1] = 0x100000;
sdd1.index[2] = 0x200000;
sdd1.index[3] = 0x300000;
for(int i=0;i<8;i++) {
sdd1.active[i] = false;
}
sdd1.dma_active = false;
regs.r4800 = 0x00;
regs.r4801 = 0x00;
regs.r4804 = 0x00;
regs.r4805 = 0x01;
regs.r4806 = 0x02;
regs.r4807 = 0x03;
bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, memory::cartrom, (regs.r4804 & 7) << 20);
bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff, memory::cartrom, (regs.r4805 & 7) << 20);
bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff, memory::cartrom, (regs.r4806 & 7) << 20);
bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff, memory::cartrom, (regs.r4807 & 7) << 20);
}
uint32 SDD1::offset(uint32 addr) {
uint8 b = (addr >> 16) & 0xff;
if(b <= 0xbf)return 0;
b -= 0xc0; //b = 0x00-0x3f
b >>= 4; //b = 0-3
b &= 3; //bitmask
return sdd1.index[b] + (addr & 0x0fffff);
}
uint8 SDD1::mmio_read(uint16 addr) {
switch(addr) {
//>>20 == 0x100000 == 1mb
case 0x4804: return (sdd1.index[0] >> 20) & 7;
case 0x4805: return (sdd1.index[1] >> 20) & 7;
case 0x4806: return (sdd1.index[2] >> 20) & 7;
case 0x4807: return (sdd1.index[3] >> 20) & 7;
uint8 SDD1::mmio_read(uint addr) {
switch(addr & 0xffff) {
case 0x4804: return regs.r4804;
case 0x4805: return regs.r4805;
case 0x4806: return regs.r4806;
case 0x4807: return regs.r4807;
}
return r_cpu->regs.mdr;
return cpu.regs.mdr;
}
void SDD1::mmio_write(uint16 addr, uint8 data) {
switch(addr) {
case 0x4801:
for(int i = 0; i < 8; i++) {
sdd1.active[i] = !!(data & (1 << i));
}
break;
//<<20 == 0x100000 == 1mb
case 0x4804: sdd1.index[0] = (data & 7) << 20; break;
case 0x4805: sdd1.index[1] = (data & 7) << 20; break;
case 0x4806: sdd1.index[2] = (data & 7) << 20; break;
case 0x4807: sdd1.index[3] = (data & 7) << 20; break;
void SDD1::mmio_write(uint addr, uint8 data) {
switch(addr & 0xffff) {
case 0x4800: {
regs.r4800 = data;
} break;
case 0x4801: {
regs.r4801 = data;
} break;
case 0x4804: {
if(regs.r4804 != data) {
regs.r4804 = data;
bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff,
memory::cartrom, (regs.r4804 & 7) << 20);
}
} break;
case 0x4805: {
if(regs.r4805 != data) {
regs.r4805 = data;
bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff,
memory::cartrom, (regs.r4805 & 7) << 20);
}
} break;
case 0x4806: {
if(regs.r4806 != data) {
regs.r4806 = data;
bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff,
memory::cartrom, (regs.r4806 & 7) << 20);
}
} break;
case 0x4807: {
if(regs.r4807 != data) {
regs.r4807 = data;
bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff,
memory::cartrom, (regs.r4807 & 7) << 20);
}
} break;
}
}
void SDD1::dma_begin(uint8 channel, uint32 addr, uint16 length) {
if(sdd1.active[channel] == true) {
sdd1.active[channel] = false;
if(regs.r4800 & (1 << channel) && regs.r4801 & (1 << channel)) {
regs.r4801 &= ~(1 << channel);
sdd1.dma_active = true;
sdd1.buffer_index = 0;
sdd1.buffer_size = length;
@ -80,9 +99,7 @@ bool SDD1::dma_active() {
}
uint8 SDD1::dma_read() {
if(--sdd1.buffer_size == 0) {
sdd1.dma_active = false;
}
if(--sdd1.buffer_size == 0) sdd1.dma_active = false;
//sdd1.buffer[] is 65536 bytes, and sdd1.buffer_index
//is of type uint16, so no buffer overflow is possible

View File

@ -2,31 +2,38 @@
class SDD1 : public MMIO {
public:
SDD1emu sdd1emu;
void init();
void enable();
void power();
void reset();
struct {
uint32 index[4]; //memory mapping registers
uint8 buffer[65536]; //pointer to decompressed S-DD1 data,
//max. DMA length is 65536
uint16 buffer_index; //DMA read index into S-DD1 decompression buffer
uint16 buffer_size;
bool active[8]; //true when DMA channel should pass through S-DD1
bool dma_active;
} sdd1;
void init();
void enable();
void power();
void reset();
uint32 offset(uint32 addr);
uint8 mmio_read (uint addr);
void mmio_write(uint addr, uint8 data);
void dma_begin(uint8 channel, uint32 addr, uint16 length);
bool dma_active();
uint8 dma_read();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void dma_begin(uint8 channel, uint32 addr, uint16 length);
bool dma_active();
uint8 dma_read();
SDD1();
private:
SDD1emu sdd1emu;
struct {
uint8 buffer[65536]; //pointer to decompressed S-DD1 data, max DMA length is 65536
uint16 buffer_index; //DMA read index into S-DD1 decompression buffer
uint16 buffer_size;
bool dma_active;
} sdd1;
struct {
uint8 r4800;
uint8 r4801;
uint8 r4804;
uint8 r4805;
uint8 r4806;
uint8 r4807;
} regs;
};
extern SDD1 sdd1;

View File

@ -28,7 +28,7 @@ understood.
************************************************************************/
#define SDD1_read(__addr) (r_mem->read(__addr))
#define SDD1_read(__addr) (bus.read(__addr))
////////////////////////////////////////////////////

View File

@ -77,8 +77,8 @@ tm *t;
void SRTC::init() {}
void SRTC::enable() {
r_mem->set_mmio_mapper(0x2800, this);
r_mem->set_mmio_mapper(0x2801, this);
memory::mmio.map(0x2800, *this);
memory::mmio.map(0x2801, *this);
}
void SRTC::power() {
@ -91,8 +91,8 @@ void SRTC::reset() {
srtc.mode = SRTC_READ;
}
uint8 SRTC::mmio_read(uint16 addr) {
switch(addr) {
uint8 SRTC::mmio_read(uint addr) {
switch(addr & 0xffff) {
case 0x2800: {
if(srtc.mode == SRTC_READ) {
@ -116,7 +116,7 @@ uint8 SRTC::mmio_read(uint16 addr) {
}
return r_cpu->regs.mdr;
return cpu.regs.mdr;
}
//Please see notes above about the implementation of the S-RTC
@ -124,8 +124,8 @@ uint8 SRTC::mmio_read(uint16 addr) {
//as reads will refresh the data array with the current system
//time. The write method is only here for the sake of faux
//emulation of the real hardware.
void SRTC::mmio_write(uint16 addr, uint8 data) {
switch(addr) {
void SRTC::mmio_write(uint addr, uint8 data) {
switch(addr & 0xffff) {
case 0x2800: {
} break;

View File

@ -43,8 +43,8 @@ struct {
void power();
void reset();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
uint8 mmio_read (uint addr);
void mmio_write(uint addr, uint8 data);
SRTC();
};

View File

@ -60,23 +60,23 @@ void ST010::reset() {
//
uint8 ST010::read(uint16 addr) {
uint8 ST010::read(uint addr) {
return readb(addr);
}
void ST010::write(uint16 addr, uint8 data) {
void ST010::write(uint addr, uint8 data) {
writeb(addr, data);
if(addr == 0x0021 && data & 0x80) {
if((addr & 0xfff) == 0x0021 && (data & 0x80)) {
switch(ram[0x0020]) {
case 0x01: op_01(); break;
case 0x02: op_02(); break;
case 0x03: op_03(); break;
case 0x04: op_04(); break;
case 0x05: op_05(); break;
case 0x06: op_06(); break;
case 0x07: op_07(); break;
case 0x08: op_08(); break;
case 0x01: op_01(); break;
case 0x02: op_02(); break;
case 0x03: op_03(); break;
case 0x04: op_04(); break;
case 0x05: op_05(); break;
case 0x06: op_06(); break;
case 0x07: op_07(); break;
case 0x08: op_08(); break;
}
ram[0x0021] &= ~0x80;

View File

@ -1,8 +1,19 @@
class ST010 { public:
uint8 ram[0x1000];
static const int16 sin_table[256];
static const int16 mode7_scale[176];
static const uint8 arctan[32][32];
class ST010 : public Memory {
public:
void init();
void enable();
void power();
void reset();
uint8 read (uint addr);
void write(uint addr, uint8 data);
private:
uint8 ram[0x1000];
static const int16 sin_table[256];
static const int16 mode7_scale[176];
static const uint8 arctan[32][32];
//interfaces to sin table
int16 sin(int16 theta);
int16 cos(int16 theta);
@ -26,15 +37,6 @@ static const uint8 arctan[32][32];
void op_08();
void op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta);
//base
void init();
void enable();
void power();
void reset();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
};
extern ST010 st010;

View File

@ -1,4 +1,6 @@
uint8 SuperFX::mmio_read(uint16 addr) {
uint8 SuperFX::mmio_read(uint addr) {
addr &= 0xffff;
switch(addr) {
case 0x3000: return regs.r0.l;
case 0x3001: return regs.r0.h;

View File

@ -1,4 +1,6 @@
void SuperFX::mmio_write(uint16 addr, uint8 data) {
void SuperFX::mmio_write(uint addr, uint8 data) {
addr &= 0xffff;
switch(addr) {
case 0x3000: regs.r0.l = data; return;
case 0x3001: regs.r0.h = data; return;

View File

@ -10,7 +10,7 @@ void SuperFX::init() {
void SuperFX::enable() {
for(uint i = 0x3000; i <= 0x32ff; i++) {
r_mem->set_mmio_mapper(i, this);
memory::mmio.map(i, *this);
}
}

View File

@ -6,8 +6,8 @@ class SuperFX : public MMIO { public:
void power();
void reset();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
uint8 mmio_read (uint addr);
void mmio_write(uint addr, uint8 data);
private:
#include "regs.h"

View File

@ -1,2 +1,2 @@
::@make PLATFORM=win-mingw4-lui clean
@make PLATFORM=win-visualc-lui clean
@make PLATFORM=win-mingw-lui clean
::@make PLATFORM=win-visualc-lui clean

View File

@ -28,20 +28,14 @@ stringarray part;
return path;
}
StringSetting Path::base(0, "fs.base_path",
StringSetting Path::base(0, "path.base",
"Path that bsnes resides in", "");
StringSetting Path::rom(&config(), "path.rom",
"Default path to look for ROM files in (\"\" = use default directory)", "");
StringSetting Path::save(&config(), "path.save",
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
StringSetting Path::bios(&config(), "path.bios",
"Path where BIOS file(s) are located\n"
"Supported BIOS files:\n"
"stbios.bin - Bandai Sufami Turbo"
"", "./bios");
StringSetting Path::save_ext(&config(), "path.save_ext",
"Extension to be used for all save RAM files", "srm");
StringSetting Path::bsx(&config(), "path.bsx", "", "");
StringSetting Path::st(&config(), "path.st", "", "");
IntegerSetting SNES::gamma_ramp(&config(), "snes.colorfilter.gamma_ramp",
"Use precalculated TV-style gamma ramp", IntegerSetting::Boolean, true);
@ -75,6 +69,19 @@ IntegerSetting CPU::ntsc_clock_rate(&config(), "cpu.ntsc_clock_rate",
"NTSC S-CPU clock rate (in hz)", IntegerSetting::Decimal, 21477272);
IntegerSetting CPU::pal_clock_rate(&config(), "cpu.pal_clock_rate",
"PAL S-CPU clock rate (in hz)", IntegerSetting::Decimal, 21281370);
IntegerSetting CPU::wram_init_value(&config(), "cpu.wram_init_value",
"Value to initialize 128k WRAM to upon power cycle.\n"
"Note that on real hardware, this value is undefined; meaning it can vary\n"
"per power-on, and per SNES unit. Such randomness is undesirable for an\n"
"emulator, so a static value is needed. There is also some form of pattern\n"
"to the randomness that has yet to be determined, which some games rely upon.\n"
"A value of 0x55 is safe for all known commercial software, and should be used.\n"
"However, some software written for SNES copiers, or backup units, relies on\n"
"WRAM being initialized to 0x00; which was a side-effect of the BIOS program\n"
"which executed on these copiers. Using 0x00 will therefore fix many homebrew\n"
"programs, but *will* break some poorly programmed commercial software titles,\n"
"which do not properly initialize WRAM upon power cycle.\n",
IntegerSetting::Hex, 0x55);
IntegerSetting CPU::hdma_enable(0, "cpu.hdma_enable",
"Enable HDMA effects", IntegerSetting::Boolean, true);

View File

@ -5,8 +5,8 @@ extern Config& config();
string file_updatepath(const char *, const char *);
extern struct Path {
static StringSetting base, rom, save, bios;
static StringSetting save_ext;
static StringSetting base, rom, save;
static StringSetting bsx, st;
} path;
extern struct SNES {
@ -19,6 +19,7 @@ extern struct SNES {
extern struct CPU {
static IntegerSetting ntsc_clock_rate, pal_clock_rate;
static IntegerSetting wram_init_value;
static IntegerSetting hdma_enable;
} cpu;

5
src/configure vendored Normal file
View File

@ -0,0 +1,5 @@
#!/bin/sh
echo "Warning: bsnes does not use a configure script"
echo "To compile bsnes, use make ..."
echo ""
make #prints make usage instructions

View File

@ -4,7 +4,7 @@ uint8 CPU::dreadb(uint32 addr) {
//do not read MMIO registers within debugger
return 0x00;
}
return r_mem->read(addr);
return bus.read(addr);
}
uint16 CPU::dreadw(uint32 addr) {

View File

@ -19,19 +19,19 @@ uint8 r;
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
r = regs.mdr;
} else {
r = r_mem->read(abus);
r = bus.read(abus);
}
r_mem->write(0x2100 | bbus, r);
bus.write(0x2100 | bbus, r);
} else { //b->a
if(bbus == 0x80 && ((abus & 0x7e0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
//prevent WRAM->WRAM transfers
r = regs.mdr;
} else {
r = r_mem->read(0x2100 | bbus);
r = bus.read(0x2100 | bbus);
}
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c)return;
r_mem->write(abus, r);
bus.write(abus, r);
}
dma_add_clocks(8);
@ -84,7 +84,7 @@ inline uint32 sCPU::hdma_iaddr(uint8 i) {
void sCPU::dma_transfertobusb(uint8 i, uint8 bbus) {
if(cartridge.info.sdd1 == true && sdd1.dma_active() == true) {
r_mem->write(0x2100 | bbus, sdd1.dma_read());
bus.write(0x2100 | bbus, sdd1.dma_read());
} else {
dma_transfer(0, bbus, dma_addr(i));
}
@ -167,19 +167,19 @@ uint8 r = 0;
}
void sCPU::hdma_update(uint8 i) {
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
channel[i].hdma_line_counter = bus.read(hdma_addr(i));
dma_add_clocks(8);
channel[i].hdma_completed = (channel[i].hdma_line_counter == 0);
channel[i].hdma_do_transfer = !channel[i].hdma_completed;
if(channel[i].hdma_indirect) {
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
channel[i].hdma_iaddr = bus.read(hdma_addr(i)) << 8;
dma_add_clocks(8);
if(!channel[i].hdma_completed || hdma_active_after(i)) {
channel[i].hdma_iaddr >>= 8;
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
channel[i].hdma_iaddr |= bus.read(hdma_addr(i)) << 8;
dma_add_clocks(8);
}
}

View File

@ -14,21 +14,21 @@ void sCPU::op_io() {
}
uint8 sCPU::op_read(uint32 addr) {
status.clock_count = r_mem->speed(addr);
status.clock_count = bus.speed(addr);
precycle_edge();
add_clocks(status.clock_count - 4);
regs.mdr = r_mem->read(addr);
regs.mdr = bus.read(addr);
add_clocks(4);
cycle_edge();
return regs.mdr;
}
void sCPU::op_write(uint32 addr, uint8 data) {
status.clock_count = r_mem->speed(addr);
status.clock_count = bus.speed(addr);
precycle_edge();
add_clocks(status.clock_count);
regs.mdr = data;
r_mem->write(addr, regs.mdr);
bus.write(addr, regs.mdr);
cycle_edge();
}

View File

@ -4,14 +4,14 @@ uint8 sCPU::pio_status() {
//WMDATA
uint8 sCPU::mmio_r2180() {
uint8 r = r_mem->read(0x7e0000 | status.wram_addr);
uint8 r = bus.read(0x7e0000 | status.wram_addr);
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
return r;
}
//WMDATA
void sCPU::mmio_w2180(uint8 data) {
r_mem->write(0x7e0000 | status.wram_addr, data);
bus.write(0x7e0000 | status.wram_addr, data);
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
}
@ -76,7 +76,7 @@ void sCPU::mmio_w4200(uint8 data) {
//WRIO
void sCPU::mmio_w4201(uint8 data) {
if((status.pio & 0x80) && !(data & 0x80)) {
r_ppu->latch_counters();
ppu.latch_counters();
}
status.pio = data;
}
@ -159,7 +159,7 @@ void sCPU::mmio_w420c(uint8 data) {
//MEMSEL
void sCPU::mmio_w420d(uint8 data) {
r_mem->set_speed(data & 1);
bus.set_speed(data & 1);
}
//RDNMI
@ -419,11 +419,13 @@ void sCPU::mmio_reset() {
status.joy4h = 0x00;
}
uint8 sCPU::mmio_read(uint16 addr) {
uint8 sCPU::mmio_read(uint addr) {
addr &= 0xffff;
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
scheduler.sync_cpusmp();
return r_smp->port_read(addr & 3);
return smp.port_read(addr & 3);
}
//DMA
@ -474,7 +476,9 @@ uint8 sCPU::mmio_read(uint16 addr) {
return regs.mdr;
}
void sCPU::mmio_write(uint16 addr, uint8 data) {
void sCPU::mmio_write(uint addr, uint8 data) {
addr &= 0xffff;
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
scheduler.sync_cpusmp();

View File

@ -1,7 +1,7 @@
void mmio_power();
void mmio_reset();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
uint8 mmio_read (uint addr);
void mmio_write(uint addr, uint8 data);
uint8 pio_status();

View File

@ -21,8 +21,8 @@ void sCPU::power() {
void sCPU::reset() {
regs.pc.d = 0x000000;
regs.pc.l = r_mem->read(0xfffc);
regs.pc.h = r_mem->read(0xfffd);
regs.pc.l = bus.read(0xfffc);
regs.pc.h = bus.read(0xfffd);
//note: some registers are not fully reset by SNES
regs.x.h = 0x00;

View File

@ -90,7 +90,7 @@ void sCPU::scanline() {
status.line_rendered = false;
status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true;
r_ppu->scanline();
ppu.scanline();
snes.scanline();
update_interrupts();
@ -117,7 +117,7 @@ void sCPU::frame() {
status.hdmainit_trigger_position = 12 + dma_counter();
}
r_ppu->frame();
ppu.frame();
snes.frame();
}
@ -143,7 +143,7 @@ void sCPU::cycle_edge() {
if(status.line_rendered == false) {
if(status.hclock >= status.line_render_position) {
status.line_rendered = true;
r_ppu->render_scanline();
ppu.render_scanline();
}
}

BIN
src/data/bsnes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/doc/base.dia Normal file

Binary file not shown.

View File

@ -660,7 +660,7 @@ static uint8 const initial_regs [bDSP::register_count] =
void bDSP::power()
{
ram = (uint8*) r_smp->get_spcram_handle();
ram = (uint8*) smp.get_spcram_handle();
memset( &m, 0, sizeof m );
//memcpy( m.regs, initial_regs, sizeof m.regs );
memset(m.regs, 0, sizeof m.regs);

View File

@ -10,7 +10,12 @@ public:
bDSP();
~bDSP();
template<int n, typename T> inline T asr(const T x) {
enum { bits = (sizeof(T) << 3) - n };
return sclip<bits>(x >> n);
}
public:
enum { echo_hist_size = 8 };

View File

@ -1,22 +1,5 @@
#ifdef POLYMORPHISM
#define ref(x) x
#else
#define ref(x) (&x)
#endif
#define deref(x) __##x
#define r_mem ref(deref(mem))
#define r_cpu ref(deref(cpu))
#define r_smp ref(deref(smp))
#define r_dsp ref(deref(dsp))
#define r_ppu ref(deref(ppu))
#include "reader/reader.h"
#include "cart/cart.h"
#include "cheat/cheat.h"
#include "memory/memory.h"
#include "memory/bmemory/bmemory.h"
#include "memory/smemory/smemory.h"
#include "cpu/cpu.h"
#include "cpu/scpu/scpu.h"
@ -32,48 +15,22 @@
#include "ppu/bppu/bppu.h"
#include "snes/snes.h"
#include "chip/chip.h"
#include "chip/superfx/superfx.h"
#include "chip/srtc/srtc.h"
#include "chip/sdd1/sdd1.h"
#include "chip/c4/c4.h"
#include "chip/dsp1/dsp1.h"
#include "chip/dsp2/dsp2.h"
#include "chip/dsp3/dsp3.h"
#include "chip/dsp4/dsp4.h"
#include "chip/obc1/obc1.h"
#include "chip/st010/st010.h"
extern MMIO mmio_unmapped;
#ifdef POLYMORPHISM
extern MemBus *deref(mem);
extern CPU *deref(cpu);
extern SMP *deref(smp);
extern DSP *deref(dsp);
extern PPU *deref(ppu);
#else
extern MEMCORE deref(mem);
extern CPUCORE deref(cpu);
extern SMPCORE deref(smp);
extern DSPCORE deref(dsp);
extern PPUCORE deref(ppu);
#endif
#include "reader/reader.h"
#include "cart/cart.h"
#include "cheat/cheat.h"
#include "config/config.h"
#ifdef INTERFACE_MAIN
#include "config/config.cpp"
#ifdef POLYMORPHISM
MemBus *deref(mem);
CPU *deref(cpu);
APU *deref(smp);
DSP *deref(dsp);
PPU *deref(ppu);
#else
MEMCORE deref(mem);
CPUCORE deref(cpu);
SMPCORE deref(smp);
DSPCORE deref(dsp);
PPUCORE deref(ppu);
#endif
#define extern
#endif
extern BUSCORE bus;
extern CPUCORE cpu;
extern SMPCORE smp;
extern DSPCORE dsp;
extern PPUCORE ppu;
#undef extern

View File

@ -1,5 +1,5 @@
/*
libbase : version 0.11 ~byuu (2007-09-08)
libbase : version 0.11a ~byuu (2007-10-14)
license: public domain
*/
@ -169,36 +169,6 @@ enum { b = 1U << (bits - 1), m = (1U << bits) - 1 };
return ((x & m) ^ b) - b;
}
//bit shifting functions are deprecated
template<int n, typename T> inline T rol(const T x) {
enum { s = (sizeof(T) << 3) - n };
return (x << n) | (x >> s);
}
template<int n, typename T> inline T ror(const T x) {
enum { s = (sizeof(T) << 3) - n };
return (x >> n) | (x << s);
}
template<int n, typename T> inline T asl(const T x) {
return (x << n);
}
template<int n, typename T> inline T asr(const T x) {
enum { bits = (sizeof(T) << 3) - n };
return sclip<bits>(x >> n);
}
template<int n, typename T> inline T lsl(const T x) {
return (x << n);
}
template<int n, typename T> inline T lsr(const T x) {
enum { bits = (sizeof(T) << 3) - n };
return uclip<bits>(x >> n);
}
/*****
* endian wrappers
*****/
@ -241,6 +211,11 @@ enum { bits = (sizeof(T) << 3) - n };
* libc extensions
*****/
//static uint random() {
//static uint n = 0;
// return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
//}
static uint64 fget(FILE *fp, uint length = 1) {
uint64 data = 0;
for(uint i = 0; i < length; i++) {

View File

@ -1,5 +1,5 @@
/*
libconfig : version 0.14 ~byuu (2007-06-12)
libconfig : version 0.15 ~byuu (2007-11-01)
license: public domain
*/
@ -59,7 +59,7 @@ enum Format {
void get(string &output) {
if(ifmt == Boolean) { sprintf(output, "%s", data ? "true" : "false"); }
if(ifmt == Decimal) { sprintf(output, "%d", data); }
if(ifmt == Hex) { sprintf(output, "%x", data); }
if(ifmt == Hex) { sprintf(output, "0x%x", data); }
}
uint operator()() { return data; }

182
src/lib/libfunction.h Normal file
View File

@ -0,0 +1,182 @@
/*
libfunction : version 0.06 ~byuu (2007-10-14)
license: public domain
*/
#ifndef LIBFUNCTION_H
#define LIBFUNCTION_H
//prologue
#define TN typename
template<typename T> class function;
//parameters = 0
#define cat(n) n
#define TL typename R
#define PL
#define CL
#include "libfunction.h"
//parameters = 1
#define cat(n) , n
#define TL TN R, TN P1
#define PL P1 p1
#define CL p1
#include "libfunction.h"
//parameters = 2
#define cat(n) , n
#define TL TN R, TN P1, TN P2
#define PL P1 p1, P2 p2
#define CL p1, p2
#include "libfunction.h"
//parameters = 3
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3
#define PL P1 p1, P2 p2, P3 p3
#define CL p1, p2, p3
#include "libfunction.h"
//parameters = 4
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4
#define PL P1 p1, P2 p2, P3 p3, P4 p4
#define CL p1, p2, p3, p4
#include "libfunction.h"
//parameters = 5
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5
#define CL p1, p2, p3, p4, p5
#include "libfunction.h"
//parameters = 6
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6
#define CL p1, p2, p3, p4, p5, p6
#include "libfunction.h"
//parameters = 7
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7
#define CL p1, p2, p3, p4, p5, p6, p7
#include "libfunction.h"
//parameters = 8
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7, TN P8
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8
#define CL p1, p2, p3, p4, p5, p6, p7, p8
#include "libfunction.h"
//epilogue
#undef TN
#else //defined(LIBFUNCTION_H)
//function implementation template class
template<TL>
class function<R (PL)> {
private:
struct base1 { virtual void func1(PL) {} };
struct base2 { virtual void func2(PL) {} };
struct derived : base1, virtual base2 {};
struct data_t {
R (*fn_call)(const data_t& cat(PL));
union {
R (*fn_global)(PL);
struct {
R (derived::*fn_member)(PL);
void *object;
};
};
} data;
static R fn_call_global(const data_t &d cat(PL)) {
return d.fn_global(CL);
}
template<typename C>
static R fn_call_member(const data_t &d cat(PL)) {
return (((C*)d.object)->*((R (C::*&)(PL))d.fn_member))(CL);
}
public:
R operator()(PL) const { return data.fn_call(data cat(CL)); }
operator bool() const { return data.fn_call; }
function() { data.fn_call = 0; }
function(R (*fn)(PL)) {
data.fn_call = &fn_call_global;
data.fn_global = fn;
}
template<typename C>
function(R (C::*fn)(PL), C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
template<typename C>
function(R (C::*fn)(PL) const, C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = (R (C::*&)(PL))fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
function &operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
function(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); }
};
template<TL>
function<R (PL)> bind(R (*fn)(PL)) {
return function<R (PL)>(fn);
}
template<typename C, TL>
function<R (PL)> bind(R (C::*fn)(PL), C *obj) {
return function<R (PL)>(fn, obj);
}
template<typename C, TL>
function<R (PL)> bind(R (C::*fn)(PL) const, C *obj) {
return function<R (PL)>(fn, obj);
}
#undef cat
#undef TL
#undef PL
#undef CL
#endif

View File

@ -1,100 +0,0 @@
/*
libfunctor : version 0.05 ~byuu (2007-09-08)
license: public domain
*/
#ifndef LIBFUNCTOR_H
#define LIBFUNCTOR_H
//prologue
#define TN typename
template<typename T> class functor;
//parameters = 0
#define cat(n) n
#define TL typename R
#define PL
#define CL
#include "libfunctor_impl.h"
//parameters = 1
#define cat(n) , n
#define TL TN R, TN P1
#define PL P1 p1
#define CL p1
#include "libfunctor_impl.h"
//parameters = 2
#define cat(n) , n
#define TL TN R, TN P1, TN P2
#define PL P1 p1, P2 p2
#define CL p1, p2
#include "libfunctor_impl.h"
//parameters = 3
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3
#define PL P1 p1, P2 p2, P3 p3
#define CL p1, p2, p3
#include "libfunctor_impl.h"
//parameters = 4
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4
#define PL P1 p1, P2 p2, P3 p3, P4 p4
#define CL p1, p2, p3, p4
#include "libfunctor_impl.h"
//parameters = 5
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5
#define CL p1, p2, p3, p4, p5
#include "libfunctor_impl.h"
//parameters = 6
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6
#define CL p1, p2, p3, p4, p5, p6
#include "libfunctor_impl.h"
//parameters = 7
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7
#define CL p1, p2, p3, p4, p5, p6, p7
#include "libfunctor_impl.h"
//parameters = 8
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7, TN P8
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8
#define CL p1, p2, p3, p4, p5, p6, p7, p8
#include "libfunctor_impl.h"
//epilogue
#undef TN
#endif

View File

@ -1,81 +0,0 @@
#ifdef LIBFUNCTOR_H
template<TL>
class functor<R (PL)> {
private:
struct base1 { virtual void func1(PL) {} };
struct base2 { virtual void func2(PL) {} };
struct derived : base1, virtual base2 {};
struct data_t {
R (*fn_call)(const data_t& cat(PL));
union {
R (*fn_global)(PL);
struct {
R (derived::*fn_member)(PL);
void *object;
};
};
} data;
static R fn_call_global(const data_t &d cat(PL)) {
return d.fn_global(CL);
}
template<typename C>
static R fn_call_member(const data_t &d cat(PL)) {
return (((C*)d.object)->*((R (C::*&)(PL))d.fn_member))(CL);
}
public:
R operator()(PL) const { return data.fn_call(data cat(CL)); }
operator bool() const { return data.fn_call; }
functor() { data.fn_call = 0; }
functor(R (*fn)(PL)) {
data.fn_call = &fn_call_global;
data.fn_global = fn;
}
template<typename C>
functor(R (C::*fn)(PL), C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
template<typename C>
functor(R (C::*fn)(PL) const, C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = (R (C::*&)(PL))fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
functor &operator=(const functor &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
functor(const functor &source) { memcpy(&data, &source.data, sizeof(data_t)); }
};
template<TL>
functor<R (PL)> bind(R (*fn)(PL)) {
return functor<R (PL)>(fn);
}
template<typename C, TL>
functor<R (PL)> bind(R (C::*fn)(PL), C *obj) {
return functor<R (PL)>(fn, obj);
}
template<typename C, TL>
functor<R (PL)> bind(R (C::*fn)(PL) const, C *obj) {
return functor<R (PL)>(fn, obj);
}
#undef cat
#undef TL
#undef PL
#undef CL
#endif

View File

@ -1,34 +0,0 @@
/*
libsort : version 0.01 ~byuu (2006-11-15)
*/
#ifndef LIBSORT_H
#define LIBSORT_H
template<typename T>
void sort(T list[], uint length) {
for(uint d = 0; d < length; d++) {
uint min = d;
for(uint s = d + 1; s < length; s++) {
if(list[s] < list[min]) { min = s; }
}
if(min != d) {
swap(list[d], list[min]);
}
}
}
template<typename T, typename Tcmp>
void sort(T list[], uint length, Tcmp comparator) {
for(uint d = 0; d < length; d++) {
uint min = d;
for(uint s = d + 1; s < length; s++) {
if(comparator(list[s], list[min]) == true) { min = s; }
}
if(min != d) {
swap(list[d], list[min]);
}
}
}
#endif

View File

@ -1,7 +1,8 @@
uint vsprintf(string &str, const char *s, va_list args) {
va_list temp;
va_copy(temp, args);
uint length = vsnprintf(0, 0, s, temp);
int length = vsnprintf(0, 0, s, temp);
if(length < 0) length = 16 * 1024; //temp fix for non-C99-complaint vsnprintf
va_end(temp);
str.reserve(length);

View File

@ -57,7 +57,7 @@ void Window::focus() {
}
bool Window::focused() {
return GTK_WIDGET_HAS_FOCUS(info.window);
return gtk_window_is_active(GTK_WINDOW(info.window));
}
void Window::move(uint x, uint y) {

View File

@ -1,214 +0,0 @@
#include "../../base.h"
#include "mapper/mapper.cpp"
#include "bmemory_rw.cpp"
#include "bmemory_mapper_generic.cpp"
void bMemBus::load_cart() {
if(rom_loaded == true)return;
cart_map_reset();
switch(cartridge.info.mapper) {
case Cartridge::PCB:
if(cart_map_pcb(cartridge.info.pcb) == false) {
dprintf("* PCB mapper not found, cartridge load failed");
return;
}
break;
case Cartridge::LOROM:
case Cartridge::HIROM:
case Cartridge::EXLOROM:
case Cartridge::EXHIROM:
cart_map_generic(cartridge.info.mapper);
break;
default:
dprintf("* Generic mapper not found, cartridge load failed");
return;
}
if(cartridge.info.sdd1) cart_map_sdd1();
if(cartridge.info.c4) cart_map_c4();
if(cartridge.info.dsp1) cart_map_dsp1();
if(cartridge.info.dsp2) cart_map_dsp2();
if(cartridge.info.dsp3) cart_map_dsp3();
if(cartridge.info.dsp4) cart_map_dsp4();
if(cartridge.info.obc1) cart_map_obc1();
if(cartridge.info.st010)cart_map_st010();
cart_map_system();
uint region = read(0xffd9) & 0x7f;
cartridge.info.region = (region <= 1 || region >= 13) ? Cartridge::NTSC : Cartridge::PAL;
if(cartridge.info.region == Cartridge::NTSC) {
snes.set_region(SNES::NTSC);
} else {
snes.set_region(SNES::PAL);
}
rom_loaded = true;
//print cartridge info to debug console
char t[256];
dprintf("* CRC32 : %0.8x", cartridge.info.crc32);
dprintf("* Name : \"%s\"", cartridge.info.name);
dprintf("* PCB : %s", cartridge.info.pcb);
calc_size(t, cartridge.info.rom_size);
dprintf("* ROM Size : %s", t);
calc_size(t, cartridge.info.ram_size);
dprintf("* RAM Size : %s", t);
dprintf("* Region : %s", (cartridge.info.region == Cartridge::NTSC) ? "NTSC" : "PAL");
strcpy(t, "");
if(cartridge.info.superfx)strcat(t, "SuperFX, ");
if(cartridge.info.sa1) strcat(t, "SA-1, ");
if(cartridge.info.srtc) strcat(t, "S-RTC, ");
if(cartridge.info.sdd1) strcat(t, "S-DD1, ");
if(cartridge.info.c4) strcat(t, "Cx4, ");
if(cartridge.info.dsp1) strcat(t, "DSP-1, ");
if(cartridge.info.dsp2) strcat(t, "DSP-2, ");
if(cartridge.info.dsp3) strcat(t, "DSP-3, ");
if(cartridge.info.dsp4) strcat(t, "DSP-4, ");
if(cartridge.info.obc1) strcat(t, "OBC-1, ");
if(cartridge.info.st010) strcat(t, "ST010, ");
if(cartridge.info.st011) strcat(t, "ST011, ");
if(cartridge.info.st018) strcat(t, "ST018, ");
strrtrim(t, ", ");
dprintf("* Coprocessor(s) : %s", (strlen(t) == 0) ? "None" : t);
dprintf("* Reset:%0.4x NMI[n]:%0.4x IRQ[n]:%0.4x BRK[n]:%0.4x COP[n]:%0.4x",
(read(0xfffc) << 0) | (read(0xfffd) << 8), //Reset
(read(0xffea) << 0) | (read(0xffeb) << 8), //NMI
(read(0xffee) << 0) | (read(0xffef) << 8), //IRQ
(read(0xffe6) << 0) | (read(0xffe7) << 8), //BRK
(read(0xffe4) << 0) | (read(0xffe5) << 8) //COP
);
//BRK[e] should be $fff6, however emulation mode brk is technically not supported.
//this needs verification, but I believe brk jumps to IRQ[e] vector.
dprintf("* NMI[e]:%0.4x IRQ[e]:%0.4x BRK[e]:%0.4x COP[e]:%0.4x",
(read(0xfffa) << 0) | (read(0xfffb) << 8), //NMI
(read(0xfffe) << 0) | (read(0xffff) << 8), //IRQ
(read(0xfffe) << 0) | (read(0xffff) << 8), //BRK
(read(0xfff4) << 0) | (read(0xfff5) << 8) //COP
);
dprintf("");
}
void bMemBus::unload_cart() {
if(rom_loaded == false)return;
rom_loaded = false;
}
/***********************
*** SNES Memory Map ***
*****************************************
*** 00-3f 0000-1fff First 8k WRAM ***
*** 2000-5fff MMIO ***
*** 6000-7fff /Cart Expansion ***
*** 8000-ffff /Cart ***
*** 40-7d 0000-ffff /Cart ***
*** 7e-7f 0000-ffff 128k WRAM ***
*** 80-bf 0000-1fff First 8k WRAM ***
*** 2000-5fff MMIO ***
*** 6000-7fff /Cart Expansion ***
*** 8000-ffff /Cart ***
*** c0-ff 0000-ffff /Cart ***
*****************************************/
uint8 bMemBus::memory_type(uint32 addr) {
uint8 bank = addr >> 16;
addr &= 0xffff;
if((bank & 0x40) == 0x00) {
//$[00-3f|80-bf]:[0000-ffff]
if(addr >= 0x0000 && addr <= 0x1fff)return TYPE_WRAM;
if(addr >= 0x2000 && addr <= 0x5fff)return TYPE_MMIO;
return TYPE_CART;
}
if((bank & 0xfe) == 0x7e) {
//$[7e-7f]:[0000-ffff]
return TYPE_WRAM;
}
//$[40-7d|c0-ff]:[0000-ffff]
return TYPE_CART;
}
uint8 bMemBus::read(uint32 addr) {
uint8 r;
#ifdef CHEAT_SYSTEM
if(cheat.enabled()) {
if(cheat.exists(addr)) {
if(cheat.read(addr, r) == true)return r;
}
}
#endif
r = (this->*page_read[addr >> 8])(addr);
return r;
}
void bMemBus::write(uint32 addr, uint8 data) {
(this->*page_write[addr >> 8])(addr, data);
}
void bMemBus::cart_map_reset() {
for(int i = 0x0000; i <= 0xffff; i++) {
page_handle[i] = 0;
page_read [i] = &bMemBus::read_unmapped;
page_write [i] = &bMemBus::write_unmapped;
}
}
void bMemBus::cart_map_system() {
//map $[00-3f|80-bf]:[0000-1fff] to WRAM
for(int b = 0x00; b <= 0x3f; b++) {
for(int p = 0x00; p <= 0x1f; p++) {
page_handle[0x0000 + (b << 8) + p] = wram + (p << 8);
page_handle[0x8000 + (b << 8) + p] = wram + (p << 8);
page_read [0x0000 + (b << 8) + p] = &bMemBus::read_ram;
page_read [0x8000 + (b << 8) + p] = &bMemBus::read_ram;
page_write [0x0000 + (b << 8) + p] = &bMemBus::write_ram;
page_write [0x8000 + (b << 8) + p] = &bMemBus::write_ram;
}
}
//map $[7e-7f]:[0000-ffff] to WRAM
for(int b = 0x7e; b <= 0x7f; b++) {
for(int p = 0x00; p <= 0xff; p++) {
page_handle[(b << 8) + p] = wram + ((b & 1) << 16) + (p << 8);
page_read [(b << 8) + p] = &bMemBus::read_ram;
page_write [(b << 8) + p] = &bMemBus::write_ram;
}
}
//map $[00-3f|80-bf]:[2000-5fff] to MMIO
for(int b = 0x00; b <= 0x3f; b++) {
for(int p = 0x20; p <= 0x5f; p++) {
page_read [0x0000 + (b << 8) + p] = &bMemBus::read_mmio;
page_read [0x8000 + (b << 8) + p] = &bMemBus::read_mmio;
page_write[0x0000 + (b << 8) + p] = &bMemBus::write_mmio;
page_write[0x8000 + (b << 8) + p] = &bMemBus::write_mmio;
}
}
}
void bMemBus::power() {
cart_write_protect(true);
memset(wram, 0x55, 0x020000);
reset();
}
void bMemBus::reset() {
set_speed(0);
}
bMemBus::bMemBus() {
wram = (uint8*)malloc(0x020000);
rom_loaded = false;
}
bMemBus::~bMemBus() {
safe_free(wram);
}

View File

@ -1,79 +0,0 @@
class bMemBus : public MemBus {
public:
uint8 *wram;
bool rom_loaded;
uint8 *page_handle[65536];
uint8 (bMemBus::*page_read [65536])(uint32 addr);
void (bMemBus::*page_write[65536])(uint32 addr, uint8 data);
#include "mapper/mapper.h"
enum { LOROM = 0x20, HIROM = 0x21, EXLOROM = 0x22, EXHIROM = 0x25 };
enum { TYPE_WRAM, TYPE_MMIO, TYPE_CART };
uint8 memory_type(uint32 addr);
uint8 read (uint32 addr);
void write(uint32 addr, uint8 data);
void load_cart();
void unload_cart();
bool cart_loaded() { return rom_loaded; }
//bmemory_rw.cpp
uint8 read_unmapped (uint32 addr);
void write_unmapped(uint32 addr, uint8 data);
uint8 read_mmio (uint32 addr);
void write_mmio (uint32 addr, uint8 data);
uint8 read_rom (uint32 addr);
void write_rom (uint32 addr, uint8 data);
uint8 read_ram (uint32 addr);
void write_ram (uint32 addr, uint8 data);
uint8 read_sdd1 (uint32 addr);
void write_sdd1 (uint32 addr, uint8 data);
uint8 read_c4 (uint32 addr);
void write_c4 (uint32 addr, uint8 data);
uint8 read_dsp1 (uint32 addr);
void write_dsp1 (uint32 addr, uint8 data);
uint8 read_dsp2 (uint32 addr);
void write_dsp2 (uint32 addr, uint8 data);
uint8 read_dsp3 (uint32 addr);
void write_dsp3 (uint32 addr, uint8 data);
uint8 read_dsp4 (uint32 addr);
void write_dsp4 (uint32 addr, uint8 data);
uint8 read_obc1 (uint32 addr);
void write_obc1 (uint32 addr, uint8 data);
uint8 read_st010 (uint32 addr);
void write_st010 (uint32 addr, uint8 data);
void cart_map_reset();
void cart_map_system();
void cart_map_generic(uint type);
void cart_map_sdd1();
void cart_map_c4();
void cart_map_dsp1();
void cart_map_dsp2();
void cart_map_dsp3();
void cart_map_dsp4();
void cart_map_obc1();
void cart_map_st010();
void power();
void reset();
//load_cart() helper
void calc_size(char *t, uint size) {
size *= 8; //bytes -> bits
if(size < 1024) { sprintf(t, "%dbit", size); return; }
size /= 1024;
if(size < 1024) { sprintf(t, "%dkbit", size); return; }
size /= 1024;
sprintf(t, "%dmbit", size);
}
bMemBus();
~bMemBus();
};

View File

@ -1,216 +0,0 @@
/*****
* Generic LoROM / HiROM / ExHiROM / ExLoROM mapping
*
* Must map the following regions :
* $[00-3f]:[6000-ffff]
* $[40-7d]:[0000-ffff]
* $[80-bf]:[6000-ffff]
* $[c0-ff]:[0000-ffff]
*
* The following regions will be ignored / overwritten :
* $[00-3f]:[0000-1fff] WRAM
* $[00-3f]:[2000-5fff] MMIO
* $[7e-7f]:[0000-ffff] WRAM
* $[80-bf]:[0000-1fff] WRAM
* $[80-bf]:[2000-5fff] MMIO
*****/
void bMemBus::cart_map_generic(uint type) {
uint rom_size = cartridge.info.rom_size;
uint ram_size = cartridge.info.ram_size;
for(uint page = 0x0000; page <= 0xffff; page++) {
if(memory_type(page << 8) != TYPE_CART)continue;
uint addr = page << 8;
uint bank = page >> 8;
//RAM mapping is incorrect in several games, this is the most compatible
//layout I can create using only ROM header information. Additional accuracy
//requires PCB identification.
//Unmapped region
//$[00-1f|80-9f]:[6000-7fff]
if((bank & 0x7f) >= 0x00 && (bank & 0x7f) <= 0x1f && (addr & 0xe000) == 0x6000) {
continue;
}
//HiROM RAM region
//$[20-3f|a0-bf]:[6000-7fff]
if((bank & 0x7f) >= 0x20 && (bank & 0x7f) <= 0x3f && (addr & 0xe000) == 0x6000) {
if(ram_size == 0)continue;
addr = ((bank & 0x7f) - 0x20) * 0x2000 + ((addr & 0xffff) - 0x6000);
addr %= ram_size;
page_handle[page] = cartridge.ram + addr;
page_read [page] = &bMemBus::read_ram;
page_write [page] = &bMemBus::write_ram;
continue;
}
//LoROM RAM region
//$[70-7f|f0-ff]:[0000-7fff]
//Note: WRAM is remapped over $[7e-7f]:[0000-ffff]
if((bank & 0x7f) >= 0x70 && (bank & 0x7f) <= 0x7f && (addr & 0x8000) == 0x0000) {
if(!(bank & 0x80) || type == Cartridge::LOROM) {
//HiROM maps $[f0-ff]:[0000-7fff] to ROM
if(ram_size == 0)continue;
addr = ((bank & 0x7f) - 0x70) * 0x8000 + (addr & 0x7fff);
addr %= ram_size;
page_handle[page] = cartridge.ram + addr;
page_read [page] = &bMemBus::read_ram;
page_write [page] = &bMemBus::write_ram;
continue;
}
}
//ROM region
switch(type) {
case Cartridge::LOROM: {
addr = (bank & 0x7f) * 0x8000 + (addr & 0x7fff);
addr = mirror(rom_size, addr);
} break;
case Cartridge::HIROM: {
addr = mirror(rom_size, addr);
} break;
case Cartridge::EXLOROM: {
if(!(bank & 0x40)) {
bank &= 0x7f;
addr = (bank << 15) | (addr & 0x7fff);
} else {
addr &= 0x3fffff;
}
addr = mirror(rom_size, addr);
} break;
case Cartridge::EXHIROM: {
addr &= 0x3fffff;
addr += (bank < 0x80) ? 0x400000 : 0x000000;
addr = mirror(rom_size, addr);
} break;
}
page_handle[page] = cartridge.rom + addr;
page_read [page] = &bMemBus::read_rom;
page_write [page] = &bMemBus::write_rom;
}
}
void bMemBus::cart_map_sdd1() {
//$[c0-ff]:[0000-ffff]
for(uint page = 0xc000; page <= 0xffff; page++) {
page_read [page] = &bMemBus::read_sdd1;
page_write[page] = &bMemBus::write_sdd1;
}
}
void bMemBus::cart_map_c4() {
//$[00-3f|80-bf]:[6000-7fff]
for(uint bank = 0x00; bank <= 0x3f; bank++) {
for(uint page = 0x60; page <= 0x7f; page++) {
page_read [0x0000 + (bank << 8) + page] = &bMemBus::read_c4;
page_read [0x8000 + (bank << 8) + page] = &bMemBus::read_c4;
page_write[0x0000 + (bank << 8) + page] = &bMemBus::write_c4;
page_write[0x8000 + (bank << 8) + page] = &bMemBus::write_c4;
}
}
}
void bMemBus::cart_map_dsp1() {
if(cartridge.info.dsp1_mapper == Cartridge::DSP1_LOROM_1MB) {
//$[20-3f|a0-bf]:[8000-ffff]
for(uint bank = 0x20; bank <= 0x3f; bank++) {
for(uint page = 0x80; page <= 0xff; page++) {
page_read [0x0000 + (bank << 8) + page] = &bMemBus::read_dsp1;
page_read [0x8000 + (bank << 8) + page] = &bMemBus::read_dsp1;
page_write[0x0000 + (bank << 8) + page] = &bMemBus::write_dsp1;
page_write[0x8000 + (bank << 8) + page] = &bMemBus::write_dsp1;
}
}
} else if(cartridge.info.dsp1_mapper == Cartridge::DSP1_LOROM_2MB) {
//$[60-6f|e0-ef]:[0000-7fff]
for(uint bank = 0x60; bank <= 0x6f; bank++) {
for(uint page = 0x00; page <= 0x7f; page++) {
page_read [0x0000 + (bank << 8) + page] = &bMemBus::read_dsp1;
page_read [0x8000 + (bank << 8) + page] = &bMemBus::read_dsp1;
page_write[0x0000 + (bank << 8) + page] = &bMemBus::write_dsp1;
page_write[0x8000 + (bank << 8) + page] = &bMemBus::write_dsp1;
}
}
} else if(cartridge.info.dsp1_mapper == Cartridge::DSP1_HIROM) {
//$[00-1f|80-9f]:[6000-7fff]
for(uint bank = 0x00; bank <= 0x1f; bank++) {
for(uint page = 0x60; page <= 0x7f; page++) {
page_read [0x0000 + (bank << 8) + page] = &bMemBus::read_dsp1;
page_read [0x8000 + (bank << 8) + page] = &bMemBus::read_dsp1;
page_write[0x0000 + (bank << 8) + page] = &bMemBus::write_dsp1;
page_write[0x8000 + (bank << 8) + page] = &bMemBus::write_dsp1;
}
}
}
}
void bMemBus::cart_map_dsp2() {
//$[20-3f|a0-bf]:[6000-6fff|8000-bfff]
for(uint bank = 0x20; bank <= 0x3f; bank++) {
for(uint page = 0x60; page <= 0xbf; page++) {
if(page >= 0x70 && page <= 0x7f)continue;
page_read [0x0000 + (bank << 8) + page] = &bMemBus::read_dsp2;
page_read [0x8000 + (bank << 8) + page] = &bMemBus::read_dsp2;
page_write[0x0000 + (bank << 8) + page] = &bMemBus::write_dsp2;
page_write[0x8000 + (bank << 8) + page] = &bMemBus::write_dsp2;
}
}
}
void bMemBus::cart_map_dsp3() {
//$[20-3f|a0-bf]:[8000-ffff]
for(uint bank = 0x20; bank <= 0x3f; bank++) {
for(uint page = 0x80; page <= 0xff; page++) {
page_read [0x0000 + (bank << 8) + page] = &bMemBus::read_dsp3;
page_read [0x8000 + (bank << 8) + page] = &bMemBus::read_dsp3;
page_write[0x0000 + (bank << 8) + page] = &bMemBus::write_dsp3;
page_write[0x8000 + (bank << 8) + page] = &bMemBus::write_dsp3;
}
}
}
void bMemBus::cart_map_dsp4() {
//$[30-3f|b0-bf]:[8000-ffff]
for(uint bank = 0x30; bank <= 0x3f; bank++) {
for(uint page = 0x80; page <= 0xff; page++) {
page_read [0x0000 + (bank << 8) + page] = &bMemBus::read_dsp4;
page_read [0x8000 + (bank << 8) + page] = &bMemBus::read_dsp4;
page_write[0x0000 + (bank << 8) + page] = &bMemBus::write_dsp4;
page_write[0x8000 + (bank << 8) + page] = &bMemBus::write_dsp4;
}
}
}
void bMemBus::cart_map_obc1() {
//$[00-3f|80-bf]:[6000-7fff]
for(uint bank = 0x00; bank <= 0x3f; bank++) {
for(uint page = 0x60; page <= 0x7f; page++) {
page_read [0x0000 + (bank << 8) + page] = &bMemBus::read_obc1;
page_read [0x8000 + (bank << 8) + page] = &bMemBus::read_obc1;
page_write[0x0000 + (bank << 8) + page] = &bMemBus::write_obc1;
page_write[0x8000 + (bank << 8) + page] = &bMemBus::write_obc1;
}
}
}
void bMemBus::cart_map_st010() {
//$[68-6f|e8-ef]:[0000-0fff]
for(uint bank = 0x68; bank <= 0x6f; bank++) {
for(uint page = 0x00; page <= 0x0f; page++) {
page_read [0x0000 + (bank << 8) + page] = &bMemBus::read_st010;
page_read [0x8000 + (bank << 8) + page] = &bMemBus::read_st010;
page_write[0x0000 + (bank << 8) + page] = &bMemBus::write_st010;
page_write[0x8000 + (bank << 8) + page] = &bMemBus::write_st010;
}
}
}

View File

@ -1,73 +0,0 @@
uint8 bMemBus::read_unmapped(uint32 addr) {
return r_cpu->regs.mdr;
}
void bMemBus::write_unmapped(uint32 addr, uint8 data) {
}
//
uint8 bMemBus::read_mmio(uint32 addr) {
return mmio[(addr - 0x2000) & 0x3fff]->mmio_read(addr & 0x7fff);
}
void bMemBus::write_mmio(uint32 addr, uint8 data) {
mmio[(addr - 0x2000) & 0x3fff]->mmio_write(addr & 0x7fff, data);
}
//
uint8 bMemBus::read_rom(uint32 addr) {
return page_handle[addr >> 8][addr & 0xff];
}
void bMemBus::write_rom(uint32 addr, uint8 data) {
if(cart_write_protect_enabled == true)return;
page_handle[addr >> 8][addr & 0xff] = data;
}
//
uint8 bMemBus::read_ram(uint32 addr) {
return page_handle[addr >> 8][addr & 0xff];
}
void bMemBus::write_ram(uint32 addr, uint8 data) {
page_handle[addr >> 8][addr & 0xff] = data;
}
//
uint8 bMemBus::read_sdd1(uint32 addr) {
addr = sdd1.offset(addr) % cartridge.info.rom_size;
return cartridge.rom[addr];
}
void bMemBus::write_sdd1(uint32 addr, uint8 data) {
if(cart_write_protect_enabled == true)return;
addr = sdd1.offset(addr) % cartridge.info.rom_size;
cartridge.rom[addr] = data;
}
//
uint8 bMemBus::read_c4 (uint32 addr) { return c4.read(addr); }
void bMemBus::write_c4(uint32 addr, uint8 data) { c4.write(addr, data); }
uint8 bMemBus::read_dsp1 (uint32 addr) { return dsp1.read(addr); }
void bMemBus::write_dsp1(uint32 addr, uint8 data) { dsp1.write(addr, data); }
uint8 bMemBus::read_dsp2 (uint32 addr) { return dsp2.read(addr); }
void bMemBus::write_dsp2(uint32 addr, uint8 data) { dsp2.write(addr, data); }
uint8 bMemBus::read_dsp3 (uint32 addr) { return dsp3.read(addr); }
void bMemBus::write_dsp3(uint32 addr, uint8 data) { dsp3.write(addr, data); }
uint8 bMemBus::read_dsp4 (uint32 addr) { return dsp4.read(addr); }
void bMemBus::write_dsp4(uint32 addr, uint8 data) { dsp4.write(addr, data); }
uint8 bMemBus::read_obc1 (uint32 addr) { return obc1.read(addr); }
void bMemBus::write_obc1(uint32 addr, uint8 data) { obc1.write(addr, data); }
uint8 bMemBus::read_st010 (uint32 addr) { return st010.read(addr); }
void bMemBus::write_st010(uint32 addr, uint8 data) { st010.write(addr, data); }

View File

@ -1,111 +0,0 @@
bool bMemBus::cart_map_pcb(const char *pcb) {
if(!strcmp(pcb, "SHVC-1CB5B-01")) { cart_map_shvc_1cb5b_20(); return true; }
if(!strcmp(pcb, "SHVC-1CB5B-20")) { cart_map_shvc_1cb5b_20(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-01")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-11")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-12")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-13")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-20")) { cart_map_shvc_1a3b_20(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-10")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-20")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-21")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-30")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-01")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-10")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-11")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-20")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "BSC-1A5M-01")) { cart_map_bsc_1a5m_01(); return true; }
if(!strcmp(pcb, "BSC-1A7M-01")) { cart_map_bsc_1a7m_01(); return true; }
if(!strcmp(pcb, "BSC-1A7M-10")) { cart_map_bsc_1a7m_10(); return true; }
if(!strcmp(pcb, "STC-SOLO")) { cart_map_stc_solo(); return true; }
if(!strcmp(pcb, "STC-DUAL")) { cart_map_stc_dual(); return true; }
return false;
}
uint bMemBus::mirror(uint size, uint pos) {
if(size == 0)return 0;
if(pos < size)return pos;
uint mask = 1 << 31;
while(!(pos & mask))mask >>= 1;
if(size <= (pos & mask)) {
return mirror(size, pos - mask);
} else {
return mask + mirror(size - mask, pos - mask);
}
}
void bMemBus::cart_map_range(
uint mode,
uint8 bank_lo, uint8 bank_hi,
uint16 addr_lo, uint16 addr_hi,
uint type, uint offset
) {
uint8 *data = 0;
uint size = 0;
uint index = 0;
uint8 page_lo = (addr_lo >> 8) & 255;
uint8 page_hi = (addr_hi >> 8) & 255;
switch(type) {
case MAP_ROM: {
data = cartridge.rom;
size = cartridge.info.rom_size;
} break;
case MAP_RAM: {
data = cartridge.ram;
size = cartridge.info.ram_size;
} break;
}
if(size) { index = (index + offset) % size; }
for(uint bank = bank_lo; bank <= bank_hi; bank++) {
if(mode == SHADOW && size) { index = (index + page_lo * 256) % size; }
for(uint page = page_lo; page <= page_hi; page++) {
uint16 n = (bank << 8) + page;
page_handle[n] = data + mirror(size, index);
if(size) { index = (index + 256) % size; }
switch(type) {
case MAP_ROM: {
page_read [n] = &bMemBus::read_rom;
page_write[n] = &bMemBus::write_rom;
} break;
case MAP_RAM: {
page_read [n] = &bMemBus::read_ram;
page_write[n] = &bMemBus::write_ram;
} break;
}
}
if(mode == SHADOW && size) { index = (index + (255 - page_hi) * 256) % size; }
}
}
#define mapper(name) void bMemBus::cart_map_##name()
#define map cart_map_range
#include "mapper_pcb.cpp"
#undef map
#undef mapper

View File

@ -1,32 +0,0 @@
enum {
LINEAR,
SHADOW,
};
enum {
MAP_ROM,
MAP_RAM,
MAP_BSX,
MAP_SDD1,
MAP_CX4,
MAP_DSP1,
MAP_DSP2,
MAP_OBC1,
};
uint mirror(uint size, uint pos);
bool cart_map_pcb(const char *pcb);
void cart_map_range(uint mode, uint8 bank_lo, uint8 bank_hi, uint16 addr_lo, uint16 addr_hi, uint type, uint offset = 0);
#define mapper(name) void cart_map_##name()
mapper(shvc_1cb5b_20);
mapper(shvc_1a3b_13);
mapper(shvc_1a3b_20);
mapper(shvc_1a3m_30);
mapper(shvc_1j3m_20);
mapper(bsc_1a5m_01);
mapper(bsc_1a7m_01);
mapper(bsc_1a7m_10);
mapper(stc_solo);
mapper(stc_dual);
#undef mapper

View File

@ -1,114 +0,0 @@
//SHVC-1CB5B-01
//SHVC-1CB5B-20
mapper(shvc_1cb5b_20) {
cartridge.info.superfx = true; //TODO: make this more elegant
map(LINEAR, 0x00, 0x3f, 0x6000, 0x7fff, MAP_RAM);
map(LINEAR, 0x00, 0x3f, 0x8000, 0xffff, MAP_ROM);
map(LINEAR, 0x40, 0x5f, 0x0000, 0xffff, MAP_ROM);
map(LINEAR, 0x70, 0x71, 0x0000, 0xffff, MAP_RAM);
map(LINEAR, 0x80, 0xbf, 0x6000, 0x7fff, MAP_RAM);
}
//SHVC-1A3B-01
//SHVC-1A3B-11
//SHVC-1A3B-12
//SHVC-1A3B-13
mapper(shvc_1a3b_13) {
map(LINEAR, 0x00, 0x1f, 0x8000, 0xffff, MAP_ROM);
map(LINEAR, 0x70, 0x7f, 0x0000, 0xffff, MAP_RAM);
map(LINEAR, 0x80, 0x9f, 0x8000, 0xffff, MAP_ROM);
map(LINEAR, 0xf0, 0xff, 0x0000, 0xffff, MAP_RAM);
}
//SHVC-1A3B-20
mapper(shvc_1a3b_20) {
map(LINEAR, 0x00, 0x7f, 0x8000, 0xffff, MAP_ROM);
map(LINEAR, 0x70, 0x7f, 0x0000, 0x7fff, MAP_RAM);
map(LINEAR, 0x80, 0xff, 0x8000, 0xffff, MAP_ROM);
map(LINEAR, 0xf0, 0xff, 0x0000, 0x7fff, MAP_RAM);
}
//SHVC-1A3M-10
//SHVC-1A3M-20
//SHVC-1A3M-21
//SHVC-1A3M-30
mapper(shvc_1a3m_30) {
map(LINEAR, 0x00, 0x7f, 0x8000, 0xffff, MAP_ROM);
map(LINEAR, 0x70, 0x7f, 0x0000, 0x7fff, MAP_RAM);
map(LINEAR, 0x80, 0xff, 0x8000, 0xffff, MAP_ROM);
map(LINEAR, 0xf0, 0xff, 0x0000, 0x7fff, MAP_RAM);
}
//SHVC-1J3M-01
//SHVC-1J3M-10
//SHVC-1J3M-11
//SHVC-1J3M-20
mapper(shvc_1j3m_20) {
map(SHADOW, 0x00, 0x3f, 0x8000, 0xffff, MAP_ROM);
map(LINEAR, 0x20, 0x3f, 0x6000, 0x7fff, MAP_RAM);
map(LINEAR, 0x40, 0x7f, 0x0000, 0xffff, MAP_ROM);
map(SHADOW, 0x80, 0xbf, 0x8000, 0xffff, MAP_ROM);
map(LINEAR, 0xa0, 0xbf, 0x6000, 0x7fff, MAP_RAM);
map(LINEAR, 0xc0, 0xff, 0x0000, 0xffff, MAP_ROM);
}
//BSC-1A5M-01
//
//$[c0-ef]:[0000-ffff] BSX
mapper(bsc_1a5m_01) {
map(LINEAR, 0x00, 0x1f, 0x8000, 0xffff, MAP_ROM, 0x000000);
map(LINEAR, 0x20, 0x3f, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0x70, 0x7f, 0x0000, 0x7fff, MAP_RAM);
map(LINEAR, 0x80, 0x9f, 0x8000, 0xffff, MAP_ROM, 0x200000);
map(LINEAR, 0xa0, 0xbf, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0xf0, 0xff, 0x0000, 0x7fff, MAP_RAM);
}
//BSC-1A7M-01
//
//$[c0-ef]:[0000-ffff] BSX
mapper(bsc_1a7m_01) {
map(LINEAR, 0x00, 0x1f, 0x8000, 0xffff, MAP_ROM, 0x000000);
map(LINEAR, 0x20, 0x3f, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0x70, 0x7f, 0x0000, 0x7fff, MAP_RAM);
map(LINEAR, 0x80, 0x9f, 0x8000, 0xffff, MAP_ROM, 0x000000);
map(LINEAR, 0xa0, 0xbf, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0xf0, 0xff, 0x0000, 0x7fff, MAP_RAM);
}
//BSC-1A7M-10
//
//$[c0-ef]:[0000-ffff] BSX
mapper(bsc_1a7m_10) {
map(LINEAR, 0x00, 0x1f, 0x8000, 0xffff, MAP_ROM, 0x000000);
map(LINEAR, 0x20, 0x3f, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0x70, 0x7f, 0x0000, 0x7fff, MAP_RAM);
map(LINEAR, 0x80, 0x9f, 0x8000, 0xffff, MAP_ROM, 0x200000);
map(LINEAR, 0xa0, 0xbf, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0xf0, 0xff, 0x0000, 0x7fff, MAP_RAM);
}
//STC-SOLO
mapper(stc_solo) {
map(LINEAR, 0x00, 0x1f, 0x8000, 0xffff, MAP_ROM, 0x000000);
map(LINEAR, 0x20, 0x3f, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0x60, 0x63, 0x8000, 0xffff, MAP_RAM, 0x000000);
map(LINEAR, 0x80, 0x9f, 0x8000, 0xffff, MAP_ROM, 0x000000);
map(LINEAR, 0xa0, 0xbf, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0xe0, 0xe3, 0x8000, 0xffff, MAP_RAM, 0x000000);
}
//STC-DUAL
mapper(stc_dual) {
map(LINEAR, 0x00, 0x1f, 0x8000, 0xffff, MAP_ROM, 0x000000);
map(LINEAR, 0x20, 0x3f, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0x40, 0x5f, 0x8000, 0xffff, MAP_ROM, 0x200000);
map(LINEAR, 0x60, 0x63, 0x8000, 0xffff, MAP_RAM, 0x000000);
map(LINEAR, 0x70, 0x73, 0x8000, 0xffff, MAP_RAM, 0x020000);
map(LINEAR, 0x80, 0x9f, 0x8000, 0xffff, MAP_ROM, 0x000000);
map(LINEAR, 0xa0, 0xbf, 0x8000, 0xffff, MAP_ROM, 0x100000);
map(LINEAR, 0xc0, 0xdf, 0x8000, 0xffff, MAP_ROM, 0x200000);
map(LINEAR, 0xe0, 0xe3, 0x8000, 0xffff, MAP_RAM, 0x000000);
map(LINEAR, 0xf0, 0xf3, 0x8000, 0xffff, MAP_RAM, 0x020000);
}

View File

@ -1,107 +1,104 @@
#include "../base.h"
uint16 Memory::read_word(uint32 addr, uint wrap) {
uint16 r;
switch(wrap) {
case WRAP_NONE:
r = read(addr);
r |= read(addr + 1) << 8;
break;
case WRAP_BANK:
r = read(addr);
r |= read((addr & 0xff0000) | ((addr + 1) & 0xffff)) << 8;
break;
case WRAP_PAGE:
r = read(addr);
r |= read((addr & 0xffff00) | ((addr + 1) & 0xff)) << 8;
break;
}
return r;
}
void Memory::write_word(uint32 addr, uint16 data, uint wrap) {
switch(wrap) {
case WRAP_NONE:
write(addr, data);
write(addr + 1, data >> 8);
return;
case WRAP_BANK:
write(addr, data);
write((addr & 0xff0000) | ((addr + 1) & 0xffff), data >> 8);
return;
case WRAP_PAGE:
write(addr, data);
write((addr & 0xffff00) | ((addr + 1) & 0xff), data >> 8);
return;
}
}
uint32 Memory::read_long(uint32 addr, uint wrap) {
uint32 r;
switch(wrap) {
case WRAP_NONE:
r = read(addr);
r |= read(addr + 1) << 8;
r |= read(addr + 2) << 16;
break;
case WRAP_BANK:
r = read(addr);
r |= read((addr & 0xff0000) | ((addr + 1) & 0xffff)) << 8;
r |= read((addr & 0xff0000) | ((addr + 2) & 0xffff)) << 16;
break;
case WRAP_PAGE:
r = read(addr);
r |= read((addr & 0xffff00) | ((addr + 1) & 0xff)) << 8;
r |= read((addr & 0xffff00) | ((addr + 2) & 0xff)) << 16;
break;
}
return r;
}
void Memory::write_long(uint32 addr, uint32 data, uint wrap) {
switch(wrap) {
case WRAP_NONE:
write(addr, data);
write(addr + 1, data >> 8);
write(addr + 2, data >> 16);
return;
case WRAP_BANK:
write(addr, data);
write((addr & 0xff0000) | ((addr + 1) & 0xffff), data >> 8);
write((addr & 0xff0000) | ((addr + 2) & 0xffff), data >> 16);
return;
case WRAP_PAGE:
write(addr, data);
write((addr & 0xffff00) | ((addr + 1) & 0xff), data >> 8);
write((addr & 0xffff00) | ((addr + 2) & 0xff), data >> 16);
return;
}
}
MMIO mmio_unmapped;
uint8 MMIO::mmio_read (uint16 addr) { return r_cpu->regs.mdr; }
void MMIO::mmio_write(uint16 addr, uint8 data) {}
void MemBus::set_speed(bool fast) {
fastROM = fast;
fastSpeed = fast ? 6 : 8;
}
void MemBus::flush_mmio_mappers() {
for(int i = 0; i < 0x4000; i++) {
mmio[i] = &mmio_unmapped;
}
}
bool MemBus::set_mmio_mapper(uint16 addr, MMIO *mapper) {
//out of range?
if(addr < 0x2000 || addr >= 0x6000)return false;
mmio[(addr - 0x2000) & 0x3fff] = mapper;
return true;
}
MemBus::MemBus() {
set_speed(false);
flush_mmio_mappers();
}
#include "../base.h"
#include "memory_rw.cpp"
namespace memory {
MMIOAccess mmio;
StaticRAM wram(128 * 1024);
UnmappedMemory memory_unmapped;
UnmappedMMIO mmio_unmapped;
};
uint8 UnmappedMemory::read(uint) { return cpu.regs.mdr; }
void UnmappedMemory::write(uint, uint8) {}
uint8 UnmappedMMIO::mmio_read(uint) { return cpu.regs.mdr; }
void UnmappedMMIO::mmio_write(uint, uint8) {}
void MMIOAccess::map(uint addr, MMIO &access) {
//MMIO: $[00-3f]:[2000-5fff]
mmio[(addr - 0x2000) & 0x3fff] = &access;
}
uint8 MMIOAccess::read(uint addr) {
return mmio[(addr - 0x2000) & 0x3fff]->mmio_read(addr);
}
void MMIOAccess::write(uint addr, uint8 data) {
mmio[(addr - 0x2000) & 0x3fff]->mmio_write(addr, data);
}
uint Bus::mirror(uint addr, uint size) {
uint base = 0;
if(size) {
uint mask = 1 << 23;
while(addr >= size) {
while(!(addr & mask)) mask >>= 1;
addr -= mask;
if(size > mask) {
size -= mask;
base += mask;
}
mask >>= 1;
}
base += addr;
}
return base;
}
void Bus::map(uint addr, Memory &access, uint offset) {
page[addr >> 8].access = &access;
page[addr >> 8].offset = offset - addr;
}
void Bus::map(
MapMode mode,
uint8 bank_lo, uint8 bank_hi,
uint16 addr_lo, uint16 addr_hi,
Memory &access, uint offset, uint size
) {
assert(bank_lo <= bank_hi);
assert(addr_lo <= addr_hi);
if(access.size() == -1U) return;
uint8 page_lo = addr_lo >> 8;
uint8 page_hi = addr_hi >> 8;
uint index = 0;
switch(mode) {
case MapDirect: {
for(uint bank = bank_lo; bank <= bank_hi; bank++) {
for(uint page = page_lo; page <= page_hi; page++) {
map((bank << 16) + (page << 8), access, (bank << 16) + (page << 8));
}
}
} break;
case MapLinear: {
for(uint bank = bank_lo; bank <= bank_hi; bank++) {
for(uint page = page_lo; page <= page_hi; page++) {
map((bank << 16) + (page << 8), access, mirror(offset + index, access.size()));
index += 256;
if(size) index %= size;
}
}
} break;
case MapShadow: {
for(uint bank = bank_lo; bank <= bank_hi; bank++) {
index += page_lo * 256;
if(size) index %= size;
for(uint page = page_lo; page <= page_hi; page++) {
map((bank << 16) + (page << 8), access, mirror(offset + index, access.size()));
index += 256;
if(size) index %= size;
}
index += (255 - page_hi) * 256;
if(size) index %= size;
}
} break;
}
}

View File

@ -1,30 +1,91 @@
class Memory {
public:
struct Memory {
virtual uint size() { return 0; }
virtual uint8 read(uint addr) = 0;
virtual void write(uint addr, uint8 data) = 0;
enum { WRAP_NONE = 0, WRAP_BANK = 1, WRAP_PAGE = 2 };
virtual uint8 read (uint32 addr) = 0;
virtual void write (uint32 addr, uint8 data) = 0;
virtual uint16 read_word (uint32 addr, uint wrap = WRAP_NONE);
virtual void write_word(uint32 addr, uint16 data, uint wrap = WRAP_NONE);
virtual uint32 read_long (uint32 addr, uint wrap = WRAP_NONE);
virtual void write_long(uint32 addr, uint32 data, uint wrap = WRAP_NONE);
virtual uint16 read_word(uint addr, uint wrap = WRAP_NONE);
virtual void write_word(uint addr, uint16 data, uint wrap = WRAP_NONE);
virtual uint32 read_long(uint addr, uint wrap = WRAP_NONE);
virtual void write_long(uint addr, uint32 data, uint wrap = WRAP_NONE);
};
class MMIO {
public:
virtual uint8 mmio_read (uint16 addr);
virtual void mmio_write(uint16 addr, uint8 data);
struct MMIO {
virtual uint8 mmio_read(uint addr) = 0;
virtual void mmio_write(uint addr, uint8 data) = 0;
};
class MemBus : public Memory {
public:
MMIO *mmio[0x4000]; //mapped to $[00-3f|80-bf]:[2000-5fff]
bool fastROM;
uint fastSpeed;
void flush_mmio_mappers();
bool set_mmio_mapper(uint16 addr, MMIO *mapper);
struct UnmappedMemory : Memory {
uint8 read(uint);
void write(uint, uint8);
};
public:
inline uint8 speed(uint32 addr) {
struct UnmappedMMIO : MMIO {
uint8 mmio_read(uint);
void mmio_write(uint, uint8);
};
struct StaticRAM : Memory {
uint8 *data;
uint data_size;
uint size() { return data_size; }
uint8 read(uint addr) { return data[addr]; }
void write(uint addr, uint8 n) { data[addr] = n; }
StaticRAM(uint n) : data_size(n) { data = (uint8*)malloc(data_size); }
~StaticRAM() { free(data); }
};
struct MappedRAM : Memory {
uint8 *data;
uint data_size;
bool write_protection;
void map(uint8 *source, uint length) { data = source; data_size = length > 0 ? length : -1U; }
void write_protect(bool status) { write_protection = status; }
uint8* handle() { return data; }
uint size() { return data_size; }
uint8 read(uint addr) { return data[addr]; }
void write(uint addr, uint8 n) { if(!write_protection) data[addr] = n; }
MappedRAM() : data(0), data_size(0), write_protection(false) {}
};
struct MMIOAccess : Memory {
MMIO *mmio[0x4000];
void map(uint addr, MMIO &access);
uint8 read(uint addr);
void write(uint addr, uint8 data);
};
class Bus { public:
struct Page {
Memory *access;
uint offset;
} page[65536];
uint fastSpeed;
uint mirror(uint addr, uint size);
void map(uint addr, Memory &access, uint offset);
enum MapMode { MapDirect, MapLinear, MapShadow };
void map(MapMode mode,
uint8 bank_lo, uint8 bank_hi,
uint16 addr_lo, uint16 addr_hi,
Memory &access, uint offset = 0, uint size = 0);
alwaysinline uint8 read(uint addr) {
Page &p = page[addr >> 8];
return p.access->read(p.offset + addr);
}
alwaysinline void write(uint addr, uint8 data) {
Page &p = page[addr >> 8];
return p.access->write(p.offset + addr, data);
}
void set_speed(bool fast) { fastSpeed = fast ? 6 : 8; }
alwaysinline uint speed(uint addr) {
if(addr & 0x408000) {
if(addr & 0x800000) { return fastSpeed; }
return 8;
@ -34,25 +95,21 @@ public:
return 12;
}
void set_speed(bool fast);
virtual void load_cart() = 0;
virtual void unload_cart() = 0;
virtual bool cart_loaded() = 0;
//set to true to block writes to cartridge ROM data,
//set to false to allow writes. ROM cannot be written
//on true SNES, however the debugger should be able to
//set this to false, write to the cartridge, and then
//set this back to true.
//
//needs to be set to true on power.
bool cart_write_protect_enabled;
virtual void cart_write_protect(bool status) { cart_write_protect_enabled = status; }
virtual void power() = 0;
virtual void reset() = 0;
MemBus();
virtual ~MemBus() {}
Bus() {}
virtual ~Bus() {}
};
namespace memory {
extern MMIOAccess mmio;
extern StaticRAM wram;
extern UnmappedMemory memory_unmapped;
extern UnmappedMMIO mmio_unmapped;
};

77
src/memory/memory_rw.cpp Normal file
View File

@ -0,0 +1,77 @@
uint16 Memory::read_word(uint addr, uint wrap) {
uint16 r;
switch(wrap) {
case WRAP_NONE:
r = read(addr);
r |= read(addr + 1) << 8;
break;
case WRAP_BANK:
r = read(addr);
r |= read((addr & 0xff0000) | ((addr + 1) & 0xffff)) << 8;
break;
case WRAP_PAGE:
r = read(addr);
r |= read((addr & 0xffff00) | ((addr + 1) & 0xff)) << 8;
break;
}
return r;
}
void Memory::write_word(uint addr, uint16 data, uint wrap) {
switch(wrap) {
case WRAP_NONE:
write(addr, data);
write(addr + 1, data >> 8);
return;
case WRAP_BANK:
write(addr, data);
write((addr & 0xff0000) | ((addr + 1) & 0xffff), data >> 8);
return;
case WRAP_PAGE:
write(addr, data);
write((addr & 0xffff00) | ((addr + 1) & 0xff), data >> 8);
return;
}
}
uint32 Memory::read_long(uint addr, uint wrap) {
uint32 r;
switch(wrap) {
case WRAP_NONE:
r = read(addr);
r |= read(addr + 1) << 8;
r |= read(addr + 2) << 16;
break;
case WRAP_BANK:
r = read(addr);
r |= read((addr & 0xff0000) | ((addr + 1) & 0xffff)) << 8;
r |= read((addr & 0xff0000) | ((addr + 2) & 0xffff)) << 16;
break;
case WRAP_PAGE:
r = read(addr);
r |= read((addr & 0xffff00) | ((addr + 1) & 0xff)) << 8;
r |= read((addr & 0xffff00) | ((addr + 2) & 0xff)) << 16;
break;
}
return r;
}
void Memory::write_long(uint addr, uint32 data, uint wrap) {
switch(wrap) {
case WRAP_NONE:
write(addr, data);
write(addr + 1, data >> 8);
write(addr + 2, data >> 16);
return;
case WRAP_BANK:
write(addr, data);
write((addr & 0xff0000) | ((addr + 1) & 0xffff), data >> 8);
write((addr & 0xff0000) | ((addr + 2) & 0xffff), data >> 16);
return;
case WRAP_PAGE:
write(addr, data);
write((addr & 0xffff00) | ((addr + 1) & 0xff), data >> 8);
write((addr & 0xffff00) | ((addr + 2) & 0xff), data >> 16);
return;
}
}

View File

@ -0,0 +1,50 @@
void sBus::map_cx4() {
map(MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, cx4);
map(MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, cx4);
}
void sBus::map_dsp1() {
switch(cartridge.info.dsp1_mapper) {
case Cartridge::DSP1LoROM1MB: {
map(MapDirect, 0x20, 0x3f, 0x8000, 0xffff, dsp1);
map(MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, dsp1);
} break;
case Cartridge::DSP1LoROM2MB: {
map(MapDirect, 0x60, 0x6f, 0x0000, 0x7fff, dsp1);
map(MapDirect, 0xe0, 0xef, 0x0000, 0x7fff, dsp1);
} break;
case Cartridge::DSP1HiROM: {
map(MapDirect, 0x00, 0x1f, 0x6000, 0x7fff, dsp1);
map(MapDirect, 0x80, 0x9f, 0x6000, 0x7fff, dsp1);
} break;
}
}
void sBus::map_dsp2() {
map(MapDirect, 0x20, 0x3f, 0x6000, 0x6fff, dsp2);
map(MapDirect, 0x20, 0x3f, 0x8000, 0xbfff, dsp2);
map(MapDirect, 0xa0, 0xbf, 0x6000, 0x6fff, dsp2);
map(MapDirect, 0xa0, 0xbf, 0x8000, 0xbfff, dsp2);
}
void sBus::map_dsp3() {
map(MapDirect, 0x20, 0x3f, 0x8000, 0xffff, dsp3);
map(MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, dsp3);
}
void sBus::map_dsp4() {
map(MapDirect, 0x30, 0x3f, 0x8000, 0xffff, dsp4);
map(MapDirect, 0xb0, 0xbf, 0x8000, 0xffff, dsp4);
}
void sBus::map_obc1() {
map(MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, obc1);
map(MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, obc1);
}
void sBus::map_st010() {
map(MapDirect, 0x68, 0x6f, 0x0000, 0x0fff, st010);
map(MapDirect, 0xe8, 0xef, 0x0000, 0x0fff, st010);
}

View File

@ -0,0 +1,90 @@
void sBus::map_generic() {
switch(cartridge.mapper()) {
case Cartridge::LoROM: {
map(MapLinear, 0x00, 0x7f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x80, 0xff, 0x8000, 0xffff, memory::cartrom);
map_generic_sram();
} break;
case Cartridge::HiROM: {
map(MapShadow, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom);
map(MapShadow, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
map_generic_sram();
} break;
case Cartridge::ExLoROM: {
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom);
map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
map_generic_sram();
} break;
case Cartridge::ExHiROM: {
map(MapShadow, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x400000);
map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom, 0x400000);
map(MapShadow, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x000000);
map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom, 0x000000);
map_generic_sram();
} break;
case Cartridge::BSXROM: {
//full map is dynamically mapped by:
//src/chip/bsx/bsx_cart.cpp : BSXCart::update_memory_map();
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
} break;
case Cartridge::BSCLoROM: {
map(MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000);
map(MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000);
map(MapLinear, 0x70, 0x7f, 0x0000, 0x7fff, memory::cartram, 0x000000);
map(MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom, 0x200000);
map(MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x100000);
map(MapLinear, 0xc0, 0xef, 0x0000, 0xffff, bsxflash);
map(MapLinear, 0xf0, 0xff, 0x0000, 0x7fff, memory::cartram, 0x000000);
} break;
case Cartridge::BSCHiROM: {
map(MapShadow, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x20, 0x3f, 0x6000, 0x7fff, memory::cartram);
map(MapShadow, 0x20, 0x3f, 0x8000, 0xffff, bsxflash);
map(MapLinear, 0x40, 0x5f, 0x0000, 0xffff, memory::cartrom);
map(MapLinear, 0x60, 0x7f, 0x0000, 0xffff, bsxflash);
map(MapShadow, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0xa0, 0xbf, 0x6000, 0x7fff, memory::cartram);
map(MapShadow, 0xa0, 0xbf, 0x8000, 0xffff, bsxflash);
map(MapLinear, 0xc0, 0xdf, 0x0000, 0xffff, memory::cartrom);
map(MapLinear, 0xe0, 0xff, 0x0000, 0xffff, bsxflash);
} break;
case Cartridge::STROM: {
map(MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::stArom);
map(MapLinear, 0x40, 0x5f, 0x8000, 0xffff, memory::stBrom);
map(MapLinear, 0x60, 0x63, 0x8000, 0xffff, memory::stAram);
map(MapLinear, 0x70, 0x73, 0x8000, 0xffff, memory::stBram);
map(MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::stArom);
map(MapLinear, 0xc0, 0xdf, 0x8000, 0xffff, memory::stBrom);
map(MapLinear, 0xe0, 0xe3, 0x8000, 0xffff, memory::stAram);
map(MapLinear, 0xf0, 0xf3, 0x8000, 0xffff, memory::stBram);
} break;
}
}
void sBus::map_generic_sram() {
if(memory::cartram.size() == 0 || memory::cartram.size() == -1U) { return; }
map(MapLinear, 0x20, 0x3f, 0x6000, 0x7fff, memory::cartram);
map(MapLinear, 0xa0, 0xbf, 0x6000, 0x7fff, memory::cartram);
//research shows only games with very large ROM/RAM sizes require MAD-1 memory mapping of SRAM
//otherwise, default to safer, larger SRAM address window
uint16 addr_hi = (memory::cartrom.size() > 0x200000 || memory::cartram.size() > 32 * 1024) ? 0x7fff : 0xffff;
map(MapLinear, 0x70, 0x7f, 0x0000, addr_hi, memory::cartram);
if(cartridge.info.mapper != Cartridge::LoROM) return;
map(MapLinear, 0xf0, 0xff, 0x0000, addr_hi, memory::cartram);
}

View File

@ -0,0 +1,17 @@
void sBus::map_reset() {
for(uint i = 0x0000; i <= 0xffff; i++)
map(i << 8, memory::memory_unmapped, 0);
for(uint i = 0x2000; i <= 0x5fff; i++)
memory::mmio.map(i, memory::mmio_unmapped);
}
void sBus::map_system() {
map(MapDirect, 0x00, 0x3f, 0x2000, 0x5fff, memory::mmio);
map(MapDirect, 0x80, 0xbf, 0x2000, 0x5fff, memory::mmio);
map(MapLinear, 0x00, 0x3f, 0x0000, 0x1fff, memory::wram, 0x000000, 0x002000);
map(MapLinear, 0x80, 0xbf, 0x0000, 0x1fff, memory::wram, 0x000000, 0x002000);
map(MapLinear, 0x7e, 0x7f, 0x0000, 0xffff, memory::wram);
}

View File

@ -0,0 +1,52 @@
#include "../../base.h"
#include "mapper/system.cpp"
#include "mapper/generic.cpp"
#include "mapper/chip.cpp"
void sBus::power() {
for(uint i = 0x2000; i <= 0x5fff; i++) memory::mmio.map(i, memory::mmio_unmapped);
memset(memory::wram.data, config::cpu.wram_init_value, memory::wram.size());
reset();
}
void sBus::reset() {
set_speed(false);
}
void sBus::load_cart() {
if(is_cart_loaded == true) return;
map_reset();
map_generic();
map_system();
if(cartridge.info.cx4) map_cx4();
if(cartridge.info.dsp1) map_dsp1();
if(cartridge.info.dsp2) map_dsp2();
if(cartridge.info.dsp3) map_dsp3();
if(cartridge.info.dsp4) map_dsp4();
if(cartridge.info.obc1) map_obc1();
if(cartridge.info.st010) map_st010();
snes.set_region(cartridge.region());
is_cart_loaded = true;
}
void sBus::unload_cart() {
if(is_cart_loaded == false) return;
is_cart_loaded = false;
}
bool sBus::cart_loaded() {
return is_cart_loaded;
}
sBus::sBus() {
is_cart_loaded = false;
}
sBus::~sBus() {
unload_cart();
}

View File

@ -0,0 +1,28 @@
class sBus : public Bus {
public:
void load_cart();
void unload_cart();
bool cart_loaded();
void power();
void reset();
sBus();
~sBus();
private:
bool is_cart_loaded;
void map_reset();
void map_system();
void map_generic();
void map_generic_sram();
void map_cx4();
void map_dsp1();
void map_dsp2();
void map_dsp3();
void map_dsp4();
void map_obc1();
void map_st010();
};

View File

@ -5,9 +5,9 @@
void bPPU::run() {}
void bPPU::scanline() {
line.y = r_cpu->vcounter();
line.interlace = r_cpu->interlace();
line.interlace_field = r_cpu->interlace_field();
line.y = cpu.vcounter();
line.interlace = cpu.interlace();
line.interlace_field = cpu.interlace_field();
if(line.y == 0) {
//RTO flag reset
@ -38,7 +38,7 @@ void bPPU::scanline() {
//note: this should actually occur at V=225,HC=10.
//this is a limitation of the scanline-based renderer.
if(line.y == (!r_cpu->overscan() ? 225 : 240)) {
if(line.y == (!cpu.overscan() ? 225 : 240)) {
if(regs.display_disabled == false) {
//OAM address reset
regs.oam_addr = regs.oam_baseaddr << 1;
@ -47,14 +47,14 @@ void bPPU::scanline() {
}
if(line.y == 241 && line.interlace_field == 1) {
if(regs.interlace != r_cpu->interlace()) {
if(regs.interlace != cpu.interlace()) {
//clear entire frame so that odd scanlines are empty
//this should be handled better, but one blank frame looks
//better than one improperly interlaced frame...
memset(output, 0, 512 * 480 * sizeof(uint16));
}
//r_cpu->set_overscan(regs.overscan);
r_cpu->set_interlace(regs.interlace);
//cpu.set_overscan(regs.overscan);
cpu.set_interlace(regs.interlace);
regs.scanlines = (regs.overscan == false) ? 224 : 239;
}
}
@ -65,7 +65,7 @@ void bPPU::render_scanline() {
if(status.render_output == false)return;
#endif
if(line.y >= 0 && line.y < (r_cpu->overscan() ? 240 : 225)) {
if(line.y >= 0 && line.y < (cpu.overscan() ? 240 : 225)) {
if(config::ppu.hack.obj_cache == false) {
if(line.y != 0) {
render_line_oam_rto();

View File

@ -220,8 +220,8 @@ struct {
uint8 mmio_r213e(); //STAT77
uint8 mmio_r213f(); //STAT78
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
uint8 mmio_read (uint addr);
void mmio_write(uint addr, uint8 data);
void latch_counters();
@ -243,8 +243,8 @@ uint16 mosaic_table[16][4096];
void power();
void reset();
bool scanline_is_hires() { return (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6); }
bool scanline_is_hires() { return (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6); }
inline uint16 read16(uint8 *addr, uint pos) {
#if defined(ARCH_LSB)
return *((uint16*)(addr + pos));

View File

@ -1,6 +1,6 @@
void bPPU::latch_counters() {
regs.hcounter = r_cpu->hcounter();
regs.vcounter = r_cpu->vcounter();
regs.hcounter = cpu.hcounter();
regs.vcounter = cpu.vcounter();
regs.counters_latched = true;
}
@ -26,20 +26,20 @@ uint8 bPPU::vram_mmio_read(uint16 addr) {
return vram_read(addr);
}
uint16 v = r_cpu->vcounter();
uint16 hc = r_cpu->hclock();
uint16 ls = (r_cpu->region_scanlines() >> 1) - 1;
if(r_cpu->interlace() && !r_cpu->interlace_field())ls++;
uint16 v = cpu.vcounter();
uint16 hc = cpu.hclock();
uint16 ls = (cpu.region_scanlines() >> 1) - 1;
if(cpu.interlace() && !cpu.interlace_field())ls++;
if(v == ls && hc == 1362) {
return 0x00;
}
if(v < (!r_cpu->overscan() ? 224 : 239)) {
if(v < (!cpu.overscan() ? 224 : 239)) {
return 0x00;
}
if(v == (!r_cpu->overscan() ? 224 : 239)) {
if(v == (!cpu.overscan() ? 224 : 239)) {
if(hc == 1362) {
return vram_read(addr);
}
@ -54,23 +54,23 @@ void bPPU::vram_mmio_write(uint16 addr, uint8 data) {
return vram_write(addr, data);
}
uint16 v = r_cpu->vcounter();
uint16 hc = r_cpu->hclock();
uint16 v = cpu.vcounter();
uint16 hc = cpu.hclock();
if(v == 0) {
if(hc <= 4) {
return vram_write(addr, data);
}
if(hc == 6) {
return vram_write(addr, r_cpu->regs.mdr);
return vram_write(addr, cpu.regs.mdr);
}
return;
}
if(v < (!r_cpu->overscan() ? 225 : 240)) {
if(v < (!cpu.overscan() ? 225 : 240)) {
return;
}
if(v == (!r_cpu->overscan() ? 225 : 240)) {
if(v == (!cpu.overscan() ? 225 : 240)) {
if(hc <= 4) {
return;
}
@ -100,8 +100,8 @@ uint8 bPPU::oam_mmio_read(uint16 addr) {
return oam_read(addr);
}
uint16 v = r_cpu->vcounter();
if(v < (!r_cpu->overscan() ? 225 : 240)) {
uint16 v = cpu.vcounter();
if(v < (!cpu.overscan() ? 225 : 240)) {
return oam_read(0x0218);
}
@ -113,8 +113,8 @@ void bPPU::oam_mmio_write(uint16 addr, uint8 data) {
return oam_write(addr, data);
}
uint16 v = r_cpu->vcounter();
if(v < (!r_cpu->overscan() ? 225 : 240)) {
uint16 v = cpu.vcounter();
if(v < (!cpu.overscan() ? 225 : 240)) {
return oam_write(0x0218, data);
}
@ -132,9 +132,9 @@ uint8 bPPU::cgram_mmio_read(uint16 addr) {
return cgram_read(addr);
}
uint16 v = r_cpu->vcounter();
uint16 hc = r_cpu->hclock();
if(v < (!r_cpu->overscan() ? 225 : 240) && hc >= 72 && hc < 1096) {
uint16 v = cpu.vcounter();
uint16 hc = cpu.hclock();
if(v < (!cpu.overscan() ? 225 : 240) && hc >= 72 && hc < 1096) {
return cgram_read(0x01ff);
}
@ -146,9 +146,9 @@ void bPPU::cgram_mmio_write(uint16 addr, uint8 data) {
return cgram_write(addr, data);
}
uint16 v = r_cpu->vcounter();
uint16 hc = r_cpu->hclock();
if(v < (!r_cpu->overscan() ? 225 : 240) && hc >= 72 && hc < 1096) {
uint16 v = cpu.vcounter();
uint16 hc = cpu.hclock();
if(v < (!cpu.overscan() ? 225 : 240) && hc >= 72 && hc < 1096) {
return cgram_write(0x01ff, data);
}
@ -157,7 +157,7 @@ uint16 hc = r_cpu->hclock();
//INIDISP
void bPPU::mmio_w2100(uint8 value) {
if(regs.display_disabled == true && r_cpu->vcounter() == (!r_cpu->overscan() ? 225 : 240)) {
if(regs.display_disabled == true && cpu.vcounter() == (!cpu.overscan() ? 225 : 240)) {
regs.oam_addr = regs.oam_baseaddr << 1;
regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127;
}
@ -579,7 +579,7 @@ void bPPU::mmio_w2133(uint8 value) {
regs.oam_interlace = !!(value & 0x02);
regs.interlace = !!(value & 0x01);
r_cpu->set_overscan(regs.overscan);
cpu.set_overscan(regs.overscan);
}
//MPYL
@ -608,10 +608,10 @@ uint32 r;
//SLHV
uint8 bPPU::mmio_r2137() {
if(r_cpu->pio_status() & 0x80) {
if(cpu.pio_status() & 0x80) {
latch_counters();
}
return r_cpu->regs.mdr;
return cpu.regs.mdr;
}
//OAMDATAREAD
@ -707,8 +707,8 @@ uint8 r = 0x00;
regs.latch_hcounter = 0;
regs.latch_vcounter = 0;
r |= r_cpu->interlace_field() << 7;
if(!(r_cpu->pio_status() & 0x80)) {
r |= cpu.interlace_field() << 7;
if(!(cpu.pio_status() & 0x80)) {
r |= 0x40;
} else if(regs.counters_latched == true) {
r |= 0x40;
@ -721,8 +721,8 @@ uint8 r = 0x00;
return regs.ppu2_mdr;
}
uint8 bPPU::mmio_read(uint16 addr) {
switch(addr) {
uint8 bPPU::mmio_read(uint addr) {
switch(addr & 0xffff) {
case 0x2104:
case 0x2105:
case 0x2106:
@ -757,11 +757,11 @@ uint8 bPPU::mmio_read(uint16 addr) {
}
//return 0x00;
return r_cpu->regs.mdr;
return cpu.regs.mdr;
}
void bPPU::mmio_write(uint16 addr, uint8 data) {
switch(addr) {
void bPPU::mmio_write(uint addr, uint8 data) {
switch(addr & 0xffff) {
case 0x2100: mmio_w2100(data); return; //INIDISP
case 0x2101: mmio_w2101(data); return; //OBSEL
case 0x2102: mmio_w2102(data); return; //OAMADDL

View File

@ -2,7 +2,7 @@
void PPU::get_scanline_info(scanline_info *info) {
info->hires = scanline_is_hires();
info->interlace = r_cpu->interlace();
info->interlace = cpu.interlace();
}
void PPU::enable_renderer(bool r) { status.render_output = r; }

View File

@ -46,7 +46,7 @@ uint8 r;
case 0xf3: { //DSPDATA
//0x80-0xff are read-only mirrors of 0x00-0x7f
r = r_dsp->read(status.dsp_addr & 0x7f);
r = dsp.read(status.dsp_addr & 0x7f);
} break;
case 0xf4: //CPUIO0
@ -54,7 +54,7 @@ uint8 r;
case 0xf6: //CPUIO2
case 0xf7: { //CPUIO3
scheduler.sync_smpcpu();
r = r_cpu->port_read(addr & 3);
r = cpu.port_read(addr & 3);
} break;
case 0xf8: { //???
@ -135,12 +135,12 @@ void sSMP::op_buswrite(uint16 addr, uint8 data) {
//emulated by simulating CPU writes of 0x00
scheduler.sync_smpcpu();
if(data & 0x20) {
r_cpu->port_write(2, 0x00);
r_cpu->port_write(3, 0x00);
cpu.port_write(2, 0x00);
cpu.port_write(3, 0x00);
}
if(data & 0x10) {
r_cpu->port_write(0, 0x00);
r_cpu->port_write(1, 0x00);
cpu.port_write(0, 0x00);
cpu.port_write(1, 0x00);
}
}
@ -171,7 +171,7 @@ void sSMP::op_buswrite(uint16 addr, uint8 data) {
case 0xf3: { //DSPDATA
//0x80-0xff is a read-only mirror of 0x00-0x7f
if(!(status.dsp_addr & 0x80)) {
r_dsp->write(status.dsp_addr & 0x7f, data);
dsp.write(status.dsp_addr & 0x7f, data);
}
} break;

Some files were not shown because too many files have changed in this diff Show More