mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
4f5bdfe347
commit
95547f4ff8
|
@ -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
|
||||
|
||||
|
|
60
src/Makefile
60
src/Makefile
|
@ -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 ""
|
||||
|
|
14
src/base.h
14
src/base.h
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
213
src/cart/cart.h
213
src/cart/cart.h
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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());
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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.
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
cl /nologo /O2 dbcreate.cpp
|
||||
@pause
|
||||
@del *.obj
|
|
@ -1 +0,0 @@
|
|||
@del *.exe
|
|
@ -1,2 +0,0 @@
|
|||
dbcreate
|
||||
@copy cart.db ..\..\..\cart.db
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#include "../../base.h"
|
||||
|
||||
#include "bsx_base.cpp"
|
||||
#include "bsx_cart.cpp"
|
||||
#include "bsx_flash.cpp"
|
|
@ -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;
|
|
@ -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(®s, 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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
|
@ -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() {}
|
|
@ -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;
|
|
@ -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,
|
|
@ -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
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -28,7 +28,7 @@ understood.
|
|||
|
||||
************************************************************************/
|
||||
|
||||
#define SDD1_read(__addr) (r_mem->read(__addr))
|
||||
#define SDD1_read(__addr) (bus.read(__addr))
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
|
@ -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);
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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); }
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
};
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue