mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-19 18:51:42 +02:00
Compare commits
26 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
95547f4ff8 | ||
|
4f5bdfe347 | ||
|
49b0bed1a6 | ||
|
1554170312 | ||
|
ec137d6fb9 | ||
|
aee683a475 | ||
|
cdbf07b642 | ||
|
8a857dada3 | ||
|
ab1975a6cb | ||
|
476a1c819a | ||
|
42d3f2a37f | ||
|
c58e3af1b5 | ||
|
8226e243b8 | ||
|
9ab3fa6227 | ||
|
85fa3cc968 | ||
|
d1fcddee9c | ||
|
9fd379613a | ||
|
aabf52d678 | ||
|
c9ca01fe20 | ||
|
becf122aaa | ||
|
1e130d7872 | ||
|
c57c733d7d | ||
|
e41aa25887 | ||
|
435f7d4371 | ||
|
a1980fab09 | ||
|
ebb234ba5f |
86
license.txt
Normal file
86
license.txt
Normal file
@@ -0,0 +1,86 @@
|
||||
bsnes (TM) Open Source Reference License
|
||||
Copyright (C) 2004 - 2007 byuu
|
||||
All rights reserved
|
||||
|
||||
1. Definitions
|
||||
|
||||
The terms "reproduce", "reproduction", "distribute" and "distribution" have the
|
||||
same meaning here as under U.S. copyright law.
|
||||
|
||||
"The software" means this software package as a whole, including, but not
|
||||
limited to, this license, binaries, source code, documentation, and data.
|
||||
|
||||
"You" means the licensee of the software.
|
||||
|
||||
"The licensor" means the copyright holder of the software, byuu.
|
||||
|
||||
2. Grant of Rights
|
||||
|
||||
Subject to the terms of this license, the licensor grants you a
|
||||
non-transferable, non-exclusive, worldwide, royalty-free copyright license to
|
||||
reproduce the software for non-commercial use only, provided the software
|
||||
remains unmodified, and there is no charge for the software itself, its' use,
|
||||
nor for the medium upon which the software is distributed. The reproduction of
|
||||
modified or derivative works of the software is strictly prohibited, except when
|
||||
transmitted solely to the licensor.
|
||||
|
||||
3. Limitations
|
||||
|
||||
This license does not grant you any rights to use the licensor's name, logo or
|
||||
trademarks.
|
||||
|
||||
The software is provided "as is", and any express or implied warranties,
|
||||
including, but not limited to, the implied warranties of merchantability and
|
||||
fitness for a particular purpose are disclaimed. In no event shall the licensor
|
||||
be liable for any direct, indirect, incidental, special, exemplary, or
|
||||
consequential damages (including, but not limited to, procurement of substitute
|
||||
goods or services; loss of use, data, or profits; or business interruption)
|
||||
however caused and on any theory of liability, whether in contract, strict
|
||||
liability, or tort (including negligence or otherwise) arising in any way out of
|
||||
the use of the software, even if advised of the possibility of such damage.
|
||||
|
||||
In the event that this license is determined to be invalid or unenforceable, the
|
||||
Grant of Rights will become null and void, and no rights shall be granted to the
|
||||
licensee, within the scope of U.S. copyright law.
|
||||
|
||||
4. Exemptions
|
||||
|
||||
The software includes the work of other copyright holders, which is licensed
|
||||
under different agreements, and exempt from this license. Below is a complete
|
||||
list of all such software, and their respective copyright holders and licenses.
|
||||
Further, respective source code files are labeled with their correct licensing
|
||||
information in the header. The lack of such a header indicates said file falls
|
||||
under the bsnes license.
|
||||
|
||||
HQ2x filter, author: MaxST, license: LGPL
|
||||
JMA decompressor, author: NSRT Team, license: GPL (*)
|
||||
NTSC filter, author: blargg, license: LGPL
|
||||
zlib decompressor, license: zlib license
|
||||
|
||||
(*) bsnes has received an exemption from the copyright holder to use this work.
|
||||
|
||||
The software also includes works which have been released to the public domain,
|
||||
which are not bound to any licensing agreements. Below is a complete list of all
|
||||
such software.
|
||||
|
||||
libco, author: byuu
|
||||
libui, author: byuu
|
||||
OBC-1 emu, author: byuu
|
||||
S-DD1 emu, author: Andreas Naive
|
||||
S-RTC emu, author: byuu
|
||||
|
||||
Any software listed above as exemptions may be relicensed individually from
|
||||
bsnes under their respective terms. However, no bsnes licensed portions can be
|
||||
combined with such a derivative work.
|
||||
|
||||
The software also includes the work of other copyright holders, which is
|
||||
licensed under the terms of the bsnes license, with permission to do so from the
|
||||
respective authors. Below is a complete list of all such software.
|
||||
|
||||
Cx4 emu, authors: anomie, Overload, zsKnight, Nach
|
||||
DSP-1 emu, authors: Overload, John Weidman, Neviksti, Andreas Naive
|
||||
DSP-2 emu, author: Overload
|
||||
DSP-3 emu, authors: John Weidman, Kris Bleakley, Lancer, z80 gaiden
|
||||
DSP-4 emu, authors: Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden
|
||||
S-DSP emu, author: blargg
|
||||
ST-010 emu, authors: John Weidman, Matthew Kendora, Overload, Feather
|
84
readme.txt
Normal file
84
readme.txt
Normal file
@@ -0,0 +1,84 @@
|
||||
bsnes
|
||||
Version 0.026
|
||||
Author: byuu
|
||||
|
||||
--------
|
||||
General:
|
||||
--------
|
||||
bsnes is a Super Nintendo / Super Famicom emulator that began on
|
||||
October 14th, 2004.
|
||||
|
||||
The latest version can be downloaded from:
|
||||
http://byuu.org/
|
||||
|
||||
Please see license.txt for important licensing information.
|
||||
|
||||
--------------
|
||||
Shortcut Keys:
|
||||
--------------
|
||||
Esc - Toggle menubar visibility
|
||||
F11 - Toggle fullscreen mode
|
||||
|
||||
------------------
|
||||
Known Limitations:
|
||||
------------------
|
||||
S-CPU
|
||||
- Invalid DMA / HDMA transfers not fully emulated
|
||||
- Multiply / Divide register delays not implemented
|
||||
|
||||
S-PPU
|
||||
- Uses scanline-based renderer. This is very inaccurate, but few (if any)
|
||||
games rely on mid-scanline writes to function correctly
|
||||
- Does not support FirstSprite+Y priority
|
||||
- OAM / CGRAM accesses during active display not supported correctly
|
||||
- RTO flags are not calculated on frames that are skipped when frameskipping
|
||||
is enabled. This provides a major speedup, however it will cause in issues
|
||||
in games that test these flags, eg the SNES Test Program Electronics Test.
|
||||
Turning frameskipping off will allow RTO flag calculation on every frame
|
||||
|
||||
Hardware Bugs
|
||||
- S-CPU.r1 HDMA crashing bug not emulated
|
||||
- S-CPU<>S-SMP communication bus conflicts not emulated
|
||||
|
||||
---------------------
|
||||
Unsupported Hardware:
|
||||
---------------------
|
||||
SA-1
|
||||
Coprocessor used in many popular games, including:
|
||||
- Dragon Ball Z Hyper Dimension
|
||||
- Kirby Super Star
|
||||
- Kirby's Dreamland 3
|
||||
- Marvelous
|
||||
- SD Gundam G-NEXT
|
||||
- Super Mario RPG
|
||||
|
||||
Super FX
|
||||
Coprocessor used in many popular games, including:
|
||||
- Doom
|
||||
- Star Fox
|
||||
- Star Fox 2 (unreleased beta)
|
||||
- Super Mario World 2: Yoshi's Island
|
||||
|
||||
SPC7110
|
||||
Coprocessor used only by the following games:
|
||||
- Far East of Eden Zero
|
||||
- Far East of Eden Zero: Shounen Jump no Shou
|
||||
- Momotarou Densetsu Happy
|
||||
- Super Power League 4
|
||||
|
||||
ST-011
|
||||
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
|
||||
|
||||
Super Gameboy
|
||||
Cartridge passthrough used for playing Gameboy games
|
||||
|
||||
------------------------
|
||||
Unsupported Controllers:
|
||||
------------------------
|
||||
Mouse
|
||||
Super Scope
|
||||
Justifier
|
||||
Multitap (4-port and 5-port)
|
85
src/Makefile
85
src/Makefile
@@ -13,7 +13,7 @@ endif
|
||||
ifeq ($(PLATFORM),x-gcc-lui)
|
||||
OS = unix
|
||||
CC = gcc
|
||||
CFLAGS = -O3 -fomit-frame-pointer -ffast-math -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI `pkg-config --cflags gtk+-2.0`
|
||||
CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI `pkg-config --cflags gtk+-2.0`
|
||||
AS = nasm
|
||||
ASFLAGS = -f elf
|
||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
||||
@@ -24,7 +24,7 @@ endif
|
||||
ifeq ($(PLATFORM),x-gcc-lui-x64)
|
||||
OS = unix
|
||||
CC = gcc
|
||||
CFLAGS = -O3 -fomit-frame-pointer -ffast-math -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86_64 -DUI_LUI `pkg-config --cflags gtk+-2.0`
|
||||
CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86_64 -DUI_LUI `pkg-config --cflags gtk+-2.0`
|
||||
AS = yasm
|
||||
ASFLAGS = -f elf64
|
||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
||||
@@ -38,7 +38,7 @@ CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
@@ -49,7 +49,7 @@ CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
LINK = /link /PGD:bsnes.pgd /LTCG:PGINSTRUMENT
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
@@ -61,12 +61,23 @@ CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
LINK = /link /PGD:bsnes.pgd /LTCG:PGOPTIMIZE
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-mingw-lui)
|
||||
OS = win
|
||||
CC = mingw32-gcc
|
||||
CFLAGS = -mwindows -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 ###
|
||||
#####################################
|
||||
@@ -79,6 +90,14 @@ CARGS = -c $< -o $@
|
||||
DEFINE = -D
|
||||
endif
|
||||
|
||||
ifeq ($(CC),mingw32-gcc)
|
||||
OUT = -obsnes
|
||||
CPP = mingw32-g++
|
||||
OBJ = o
|
||||
CARGS = -c $< -o $@
|
||||
DEFINE = -D
|
||||
endif
|
||||
|
||||
ifeq ($(CC),cl)
|
||||
OUT = /Febsnes
|
||||
CPP = cl
|
||||
@@ -106,7 +125,6 @@ endif
|
||||
ifeq ($(OS),win)
|
||||
OUT := $(OUT).exe
|
||||
RM = del
|
||||
LIBS += kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
endif
|
||||
|
||||
####################################
|
||||
@@ -115,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) srtc.$(OBJ) sdd1.$(OBJ) c4.$(OBJ) dsp1.$(OBJ) \
|
||||
dsp2.$(OBJ) obc1.$(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) \
|
||||
@@ -137,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 ###
|
||||
@@ -156,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 ###
|
||||
@@ -189,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 ###
|
||||
@@ -222,12 +251,17 @@ snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* sne
|
||||
#####################
|
||||
### special chips ###
|
||||
#####################
|
||||
srtc.$(OBJ): chip/srtc/srtc.cpp chip/srtc/*
|
||||
sdd1.$(OBJ): chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
c4.$(OBJ) : chip/c4/c4.cpp chip/c4/*
|
||||
dsp1.$(OBJ): chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
dsp2.$(OBJ): chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
obc1.$(OBJ): chip/obc1/obc1.cpp chip/obc1/*
|
||||
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/*
|
||||
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/*
|
||||
dsp4.$(OBJ) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obc1.$(OBJ) : chip/obc1/obc1.cpp chip/obc1/*
|
||||
st010.$(OBJ) : chip/st010/st010.cpp chip/st010/*
|
||||
|
||||
############
|
||||
### zlib ###
|
||||
@@ -271,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 ""
|
||||
|
21
src/base.h
21
src/base.h
@@ -1,7 +1,7 @@
|
||||
#define BSNES_VERSION "0.020"
|
||||
#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,18 +25,17 @@
|
||||
#error "unsupported processor"
|
||||
#endif
|
||||
|
||||
#include "lib/libinterp.h"
|
||||
#include "lib/libsort.h"
|
||||
#include "lib/libbase.h"
|
||||
#include "lib/libfunction.h"
|
||||
#include "lib/libarray.h"
|
||||
#include "lib/libvector.h"
|
||||
#include "lib/libfile.h"
|
||||
#include "lib/libstring.h"
|
||||
#include "lib/libconfig.h"
|
||||
|
||||
//platform-specific global functions
|
||||
void alert(char*, ...);
|
||||
void dprintf(char*, ...);
|
||||
void dprintf(uint, char*, ...);
|
||||
void alert(const char*, ...);
|
||||
void dprintf(const char*, ...);
|
||||
void dprintf(uint, const char*, ...);
|
||||
|
||||
namespace source {
|
||||
enum {
|
||||
|
@@ -1,156 +1,119 @@
|
||||
#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;
|
||||
|
||||
void Cartridge::load_begin(uint cart_type) {
|
||||
if(loaded() == true)return;
|
||||
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) {
|
||||
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.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.c4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
info.obc1 = false;
|
||||
info.bsxbase = false;
|
||||
info.bsxcart = false;
|
||||
info.bsxflash = false;
|
||||
info.st = false;
|
||||
|
||||
info.dsp1_mapper = 0;
|
||||
info.superfx = false;
|
||||
info.sa1 = false;
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.cx4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
info.dsp3 = false;
|
||||
info.dsp4 = false;
|
||||
info.obc1 = false;
|
||||
info.st010 = false;
|
||||
info.st011 = false;
|
||||
info.st018 = false;
|
||||
|
||||
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.cart_mmio = false;
|
||||
|
||||
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 CART_NORMAL: {
|
||||
load_rom_normal();
|
||||
load_ram_normal();
|
||||
} break;
|
||||
case CART_ST: {
|
||||
load_rom_st();
|
||||
load_ram_st();
|
||||
} break;
|
||||
case CART_STDUAL: {
|
||||
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 CART_NORMAL: {
|
||||
save_ram_normal();
|
||||
} break;
|
||||
case CART_ST: {
|
||||
save_ram_st();
|
||||
} break;
|
||||
case CART_STDUAL: {
|
||||
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();
|
||||
}
|
||||
|
209
src/cart/cart.h
209
src/cart/cart.h
@@ -1,125 +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 {
|
||||
CART_NORMAL,
|
||||
CART_ST,
|
||||
CART_STDUAL,
|
||||
};
|
||||
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,
|
||||
LICENSE = 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();
|
||||
|
||||
//set to true for games that need cart MMIO mapping (c4, dsp-n, ...),
|
||||
//for games that map outside the standard MMIO range of $2000-$5fff
|
||||
bool cart_mmio;
|
||||
bool srtc;
|
||||
bool sdd1;
|
||||
bool c4;
|
||||
bool dsp1;
|
||||
bool dsp2;
|
||||
bool obc1;
|
||||
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(uint cart_type);
|
||||
void load(const char *rom_fn);
|
||||
bool load_end();
|
||||
bool unload();
|
||||
bool load_file(const char *fn, uint8 *&data, uint &size);
|
||||
bool save_file(const char *fn, uint8 *data, uint size);
|
||||
char* modify_extension(char *filename, const char *extension);
|
||||
char* get_save_filename(const char *source, const char *extension);
|
||||
|
||||
Cartridge();
|
||||
~Cartridge();
|
||||
|
||||
private:
|
||||
char savefn[PATH_MAX];
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern MappedRAM cartrom, cartram;
|
||||
extern MappedRAM bscram;
|
||||
extern MappedRAM stArom, stAram;
|
||||
extern MappedRAM stBrom, stBram;
|
||||
};
|
||||
|
||||
extern Cartridge cartridge;
|
||||
|
41
src/cart/cart_bsc.cpp
Normal file
41
src/cart/cart_bsc.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
void Cartridge::load_cart_bsc(const char *base, const char *slot) {
|
||||
if(!base || !*base) return;
|
||||
|
||||
strcpy(cart.fn, base);
|
||||
strcpy(bs.fn, slot ? slot : "");
|
||||
load_begin(CartridgeBSC);
|
||||
|
||||
uint8 *data;
|
||||
uint size;
|
||||
load_file(cart.fn, data, size);
|
||||
cart.rom = data, cart.rom_size = size;
|
||||
|
||||
if(*bs.fn) {
|
||||
if(load_file(bs.fn, data, size) == true) {
|
||||
info.bsxflash = true;
|
||||
bs.ram = data, bs.ram_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
find_header();
|
||||
read_header();
|
||||
|
||||
info.mapper = cartridge.info.header_index == 0x7fc0 ? BSCLoROM : BSCHiROM;
|
||||
info.region = NTSC;
|
||||
|
||||
if(info.ram_size > 0) {
|
||||
cart.ram = (uint8*)malloc(cart.ram_size = info.ram_size);
|
||||
memset(cart.ram, 0xff, cart.ram_size);
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
|
||||
memcpy(cart.ram, data, min(size, cart.ram_size));
|
||||
safe_free(data);
|
||||
}
|
||||
}
|
||||
|
||||
load_end();
|
||||
}
|
||||
|
||||
void Cartridge::unload_cart_bsc() {
|
||||
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
|
||||
}
|
45
src/cart/cart_bsx.cpp
Normal file
45
src/cart/cart_bsx.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
void Cartridge::load_cart_bsx(const char *base, const char *slot) {
|
||||
if(!base || !*base) return;
|
||||
|
||||
strcpy(cart.fn, base);
|
||||
strcpy(bs.fn, slot ? slot : "");
|
||||
|
||||
load_begin(CartridgeBSX);
|
||||
info.bsxbase = true;
|
||||
info.bsxcart = true;
|
||||
info.mapper = BSXROM;
|
||||
info.region = NTSC;
|
||||
|
||||
uint8 *data;
|
||||
uint size;
|
||||
load_file(cart.fn, data, size);
|
||||
cart.rom = data, cart.rom_size = size;
|
||||
cart.ram = 0, cart.ram_size = 0;
|
||||
|
||||
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
|
||||
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
|
||||
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
|
||||
safe_free(data);
|
||||
}
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "psr"), data, size) == true) {
|
||||
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
|
||||
safe_free(data);
|
||||
}
|
||||
|
||||
if(*bs.fn) {
|
||||
if(load_file(bs.fn, data, size) == true) {
|
||||
info.bsxflash = true;
|
||||
bs.ram = data, bs.ram_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
load_end();
|
||||
}
|
||||
|
||||
void Cartridge::unload_cart_bsx() {
|
||||
save_file(get_save_filename(cart.fn, "srm"), bsxcart.sram.handle (), bsxcart.sram.size ());
|
||||
save_file(get_save_filename(cart.fn, "psr"), bsxcart.psram.handle(), bsxcart.psram.size());
|
||||
}
|
@@ -9,6 +9,44 @@
|
||||
#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);
|
||||
|
||||
|
@@ -1,32 +1,46 @@
|
||||
void Cartridge::read_header() {
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.c4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
info.obc1 = false;
|
||||
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;
|
||||
|
||||
info.dsp1_mapper = 0;
|
||||
|
||||
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");
|
||||
//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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if(mapper == 0x23 && (rom_type == 0x34 || rom_type == 0x35)) {
|
||||
info.sa1 = true;
|
||||
}
|
||||
|
||||
uint8 mapper = rom[info.header_index + MAPPER];
|
||||
uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
||||
if(mapper == 0x35 && rom_type == 0x55) {
|
||||
info.srtc = true;
|
||||
}
|
||||
@@ -36,14 +50,14 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||
info.c4 = true;
|
||||
info.cx4 = true;
|
||||
}
|
||||
|
||||
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x05) {
|
||||
if(mapper == 0x30 && rom_type == 0x05 && company != 0xb2) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
@@ -52,12 +66,12 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,11 +79,28 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
||||
info.dsp2 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x05 && company == 0xb2) {
|
||||
info.dsp3 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x03) {
|
||||
info.dsp4 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x25) {
|
||||
info.obc1 = true;
|
||||
}
|
||||
|
||||
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
|
||||
if(mapper == 0x30 && rom_type == 0xf6) {
|
||||
//TODO: both ST010 and ST011 share the same mapper + rom_type
|
||||
//need way to determine which is which
|
||||
//for now, default to supported ST010
|
||||
info.st010 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0xf5) {
|
||||
info.st018 = true;
|
||||
}
|
||||
|
||||
if(rom[info.header_index + RAM_SIZE] & 7) {
|
||||
info.ram_size = 1024 << (rom[info.header_index + RAM_SIZE] & 7);
|
||||
@@ -77,6 +108,9 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
||||
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;
|
||||
|
||||
@@ -91,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;
|
||||
@@ -113,8 +148,8 @@ int32 score_lo = 0,
|
||||
if(rom[0x7fc0 + REGION] < 14)score_lo++;
|
||||
if(rom[0xffc0 + REGION] < 14)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
|
||||
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
|
||||
if(rom[0x7fc0 + COMPANY] < 3)score_lo++;
|
||||
if(rom[0xffc0 + COMPANY] < 3)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
|
||||
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;
|
||||
@@ -132,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,66 +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.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.c4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
info.obc1 = false;
|
||||
|
||||
info.dsp1_mapper = 0;
|
||||
|
||||
info.header_index = 0xffc0;
|
||||
info.mapper = PCB;
|
||||
strcpy(info.name, dbi.name);
|
||||
strcpy(info.pcb, dbi.pcb);
|
||||
info.region = NTSC;
|
||||
info.cart_mmio = false;
|
||||
|
||||
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,113 +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
|
||||
|
||||
[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++) {
|
||||
uint pos;
|
||||
if(strpos(line[i], ";", pos) == true) {
|
||||
strset(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,3 +1,6 @@
|
||||
@make -r PLATFORM=win-visualc-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
|
||||
@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
|
||||
|
5
src/chip/bsx/bsx.cpp
Normal file
5
src/chip/bsx/bsx.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "../../base.h"
|
||||
|
||||
#include "bsx_base.cpp"
|
||||
#include "bsx_cart.cpp"
|
||||
#include "bsx_flash.cpp"
|
77
src/chip/bsx/bsx.h
Normal file
77
src/chip/bsx/bsx.h
Normal file
@@ -0,0 +1,77 @@
|
||||
class BSXBase : public MMIO {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mmio_read(uint addr);
|
||||
void mmio_write(uint addr, uint8 data);
|
||||
|
||||
private:
|
||||
struct {
|
||||
uint8 r2188, r2189, r218a, r218b;
|
||||
uint8 r218c, r218d, r218e, r218f;
|
||||
uint8 r2190, r2191, r2192, r2193;
|
||||
uint8 r2194, r2195, r2196, r2197;
|
||||
uint8 r2198, r2199, r219a, r219b;
|
||||
uint8 r219c, r219d, r219e, r219f;
|
||||
|
||||
uint8 r2192_counter;
|
||||
uint8 r2192_hour, r2192_minute, r2192_second;
|
||||
} regs;
|
||||
};
|
||||
|
||||
class BSXCart : public MMIO {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mmio_read(uint addr);
|
||||
void mmio_write(uint addr, uint8 data);
|
||||
|
||||
MappedRAM sram;
|
||||
MappedRAM psram;
|
||||
|
||||
BSXCart();
|
||||
~BSXCart();
|
||||
|
||||
private:
|
||||
uint8 *sram_data; //256kbit SRAM
|
||||
uint8 *psram_data; // 4mbit PSRAM
|
||||
|
||||
struct {
|
||||
uint8 r[16];
|
||||
} regs;
|
||||
|
||||
void update_memory_map();
|
||||
};
|
||||
|
||||
class BSXFlash : public Memory {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint size();
|
||||
uint8 read(uint addr);
|
||||
void write(uint addr, uint8 data);
|
||||
|
||||
private:
|
||||
struct {
|
||||
uint command;
|
||||
uint8 write_old;
|
||||
uint8 write_new;
|
||||
|
||||
bool flash_enable;
|
||||
bool read_enable;
|
||||
bool write_enable;
|
||||
} regs;
|
||||
};
|
||||
|
||||
extern BSXBase bsxbase;
|
||||
extern BSXCart bsxcart;
|
||||
extern BSXFlash bsxflash;
|
133
src/chip/bsx/bsx_base.cpp
Normal file
133
src/chip/bsx/bsx_base.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
void BSXBase::init() {
|
||||
}
|
||||
|
||||
void BSXBase::enable() {
|
||||
for(uint16 i = 0x2188; i <= 0x219f; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
void BSXBase::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void BSXBase::reset() {
|
||||
memset(®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;
|
||||
}
|
||||
}
|
95
src/chip/bsx/bsx_cart.cpp
Normal file
95
src/chip/bsx/bsx_cart.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
void BSXCart::init() {
|
||||
}
|
||||
|
||||
void BSXCart::enable() {
|
||||
for(uint16 i = 0x5000; i <= 0x5fff; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
void BSXCart::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void BSXCart::reset() {
|
||||
for(uint i = 0; i < 16; i++) regs.r[i] = 0x00;
|
||||
regs.r[0x07] = 0x80;
|
||||
regs.r[0x08] = 0x80;
|
||||
|
||||
update_memory_map();
|
||||
}
|
||||
|
||||
void BSXCart::update_memory_map() {
|
||||
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram;
|
||||
|
||||
if((regs.r[0x02] & 0x80) == 0x00) { //LoROM mapping
|
||||
bus.map(Bus::MapLinear, 0x00, 0x7d, 0x8000, 0xffff, cart);
|
||||
bus.map(Bus::MapLinear, 0x80, 0xff, 0x8000, 0xffff, cart);
|
||||
} else { //HiROM mapping
|
||||
bus.map(Bus::MapShadow, 0x00, 0x3f, 0x8000, 0xffff, cart);
|
||||
bus.map(Bus::MapLinear, 0x40, 0x7d, 0x0000, 0xffff, cart);
|
||||
bus.map(Bus::MapShadow, 0x80, 0xbf, 0x8000, 0xffff, cart);
|
||||
bus.map(Bus::MapLinear, 0xc0, 0xff, 0x0000, 0xffff, cart);
|
||||
}
|
||||
|
||||
if(regs.r[0x03] & 0x80) {
|
||||
bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, psram);
|
||||
//bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
|
||||
}
|
||||
|
||||
if((regs.r[0x05] & 0x80) == 0x00) {
|
||||
bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, psram);
|
||||
}
|
||||
|
||||
if((regs.r[0x06] & 0x80) == 0x00) {
|
||||
bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, psram);
|
||||
}
|
||||
|
||||
if(regs.r[0x07] & 0x80) {
|
||||
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
|
||||
}
|
||||
|
||||
if(regs.r[0x08] & 0x80) {
|
||||
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
|
||||
}
|
||||
|
||||
bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, psram);
|
||||
bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
|
||||
}
|
||||
|
||||
uint8 BSXCart::mmio_read(uint addr) {
|
||||
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
||||
uint8 n = (addr >> 16) & 15;
|
||||
return regs.r[n];
|
||||
}
|
||||
|
||||
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
|
||||
return sram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff));
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void BSXCart::mmio_write(uint addr, uint8 data) {
|
||||
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
||||
uint8 n = (addr >> 16) & 15;
|
||||
regs.r[n] = data;
|
||||
if(n == 0x0e && data & 0x80) update_memory_map();
|
||||
return;
|
||||
}
|
||||
|
||||
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
|
||||
return sram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
|
||||
}
|
||||
}
|
||||
|
||||
BSXCart::BSXCart() {
|
||||
sram_data = (uint8*)malloc( 32 * 1024);
|
||||
psram_data = (uint8*)malloc(512 * 1024);
|
||||
|
||||
sram.map (sram_data, 32 * 1024);
|
||||
psram.map(psram_data, 512 * 1024);
|
||||
}
|
||||
|
||||
BSXCart::~BSXCart() {
|
||||
safe_free(sram_data);
|
||||
safe_free(psram_data);
|
||||
}
|
109
src/chip/bsx/bsx_flash.cpp
Normal file
109
src/chip/bsx/bsx_flash.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
void BSXFlash::init() {}
|
||||
void BSXFlash::enable() {}
|
||||
|
||||
void BSXFlash::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void BSXFlash::reset() {
|
||||
regs.command = 0;
|
||||
regs.write_old = 0x00;
|
||||
regs.write_new = 0x00;
|
||||
|
||||
regs.flash_enable = false;
|
||||
regs.read_enable = false;
|
||||
regs.write_enable = false;
|
||||
}
|
||||
|
||||
uint BSXFlash::size() {
|
||||
return memory::bscram.size();
|
||||
}
|
||||
|
||||
uint8 BSXFlash::read(uint addr) {
|
||||
if(addr == 0x0002) {
|
||||
if(regs.flash_enable) return 0x80;
|
||||
}
|
||||
|
||||
if(addr == 0x5555) {
|
||||
if(regs.flash_enable) return 0x80;
|
||||
}
|
||||
|
||||
if(regs.read_enable && addr >= 0xff00 && addr <= 0xff13) {
|
||||
//read flash cartridge vendor information
|
||||
switch(addr - 0xff00) {
|
||||
case 0x00: return 0x4d;
|
||||
case 0x01: return 0x00;
|
||||
case 0x02: return 0x50;
|
||||
case 0x03: return 0x00;
|
||||
case 0x04: return 0x00;
|
||||
case 0x05: return 0x00;
|
||||
case 0x06: return 0x2a; //0x2a = 8mbit, 0x2b = 16mbit (not known to exist, though BIOS recognizes ID)
|
||||
case 0x07: return 0x00;
|
||||
default: return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
return memory::bscram.read(addr);
|
||||
}
|
||||
|
||||
void BSXFlash::write(uint addr, uint8 data) {
|
||||
//there exist both read-only and read-write BS-X flash cartridges ...
|
||||
//unfortunately, the vendor info is not stored inside memory dumps
|
||||
//of BS-X flashcarts, so it is impossible to determine whether a
|
||||
//given flashcart is writeable.
|
||||
//however, it has been observed that LoROM-mapped BS-X carts always
|
||||
//use read-write flashcarts, and HiROM-mapped BS-X carts always use
|
||||
//read-only flashcarts.
|
||||
//below is an unfortunately necessary workaround to this problem.
|
||||
if(cartridge.mapper() == Cartridge::BSCHiROM) return;
|
||||
|
||||
if((addr & 0xff0000) == 0) {
|
||||
regs.write_old = regs.write_new;
|
||||
regs.write_new = data;
|
||||
|
||||
if(regs.write_enable && regs.write_old == regs.write_new) {
|
||||
return memory::bscram.write(addr, data);
|
||||
}
|
||||
} else {
|
||||
if(regs.write_enable) {
|
||||
return memory::bscram.write(addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
if(addr == 0x0000) {
|
||||
regs.command <<= 8;
|
||||
regs.command |= data;
|
||||
|
||||
if((regs.command & 0xffff) == 0x38d0) {
|
||||
regs.flash_enable = true;
|
||||
regs.read_enable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(addr == 0x2aaa) {
|
||||
regs.command <<= 8;
|
||||
regs.command |= data;
|
||||
}
|
||||
|
||||
if(addr == 0x5555) {
|
||||
regs.command <<= 8;
|
||||
regs.command |= data;
|
||||
|
||||
if((regs.command & 0xffffff) == 0xaa5570) {
|
||||
regs.write_enable = false;
|
||||
}
|
||||
|
||||
if((regs.command & 0xffffff) == 0xaa55a0) {
|
||||
regs.write_old = 0x00;
|
||||
regs.write_new = 0x00;
|
||||
regs.flash_enable = true;
|
||||
regs.write_enable = true;
|
||||
}
|
||||
|
||||
if((regs.command & 0xffffff) == 0xaa55f0) {
|
||||
regs.flash_enable = false;
|
||||
regs.read_enable = false;
|
||||
regs.write_enable = false;
|
||||
}
|
||||
}
|
||||
}
|
11
src/chip/chip.h
Normal file
11
src/chip/chip.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "bsx/bsx.h"
|
||||
#include "superfx/superfx.h"
|
||||
#include "srtc/srtc.h"
|
||||
#include "sdd1/sdd1.h"
|
||||
#include "cx4/cx4.h"
|
||||
#include "dsp1/dsp1.h"
|
||||
#include "dsp2/dsp2.h"
|
||||
#include "dsp3/dsp3.h"
|
||||
#include "dsp4/dsp4.h"
|
||||
#include "obc1/obc1.h"
|
||||
#include "st010/st010.h"
|
@@ -7,29 +7,27 @@
|
||||
|
||||
#include "../../base.h"
|
||||
|
||||
C4 *c4;
|
||||
#include "cx4data.cpp"
|
||||
#include "cx4fn.cpp"
|
||||
#include "cx4oam.cpp"
|
||||
#include "cx4ops.cpp"
|
||||
|
||||
#include "c4data.cpp"
|
||||
#include "c4fn.cpp"
|
||||
#include "c4oam.cpp"
|
||||
#include "c4ops.cpp"
|
||||
void Cx4::init() {}
|
||||
void Cx4::enable() {}
|
||||
|
||||
void C4::init() {}
|
||||
void C4::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;
|
||||
@@ -41,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;
|
||||
@@ -52,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];
|
||||
}
|
||||
@@ -67,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);
|
||||
@@ -75,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) {
|
||||
@@ -111,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) {
|
||||
@@ -172,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);
|
||||
}
|
@@ -1,7 +1,5 @@
|
||||
#include "../../base.h"
|
||||
|
||||
DSP1 *dsp1;
|
||||
|
||||
#include "dsp1emu.cpp"
|
||||
|
||||
void DSP1::init() {}
|
||||
@@ -28,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;
|
||||
extern DSP1 dsp1;
|
||||
|
@@ -1,7 +1,5 @@
|
||||
#include "../../base.h"
|
||||
|
||||
DSP2 *dsp2;
|
||||
|
||||
#include "dsp2_op.cpp"
|
||||
|
||||
void DSP2::init() {}
|
||||
@@ -30,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++];
|
||||
@@ -42,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,43 +1,44 @@
|
||||
class DSP2 {
|
||||
class DSP2 : public Memory {
|
||||
public:
|
||||
struct {
|
||||
bool waiting_for_command;
|
||||
uint command;
|
||||
uint in_count, in_index;
|
||||
uint out_count, out_index;
|
||||
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;
|
||||
extern DSP2 dsp2;
|
||||
|
33
src/chip/dsp3/dsp3.cpp
Normal file
33
src/chip/dsp3/dsp3.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "../../base.h"
|
||||
|
||||
namespace DSP3i {
|
||||
#define bool8 uint8
|
||||
#include "dsp3emu.c"
|
||||
#undef bool8
|
||||
};
|
||||
|
||||
void DSP3::init() {
|
||||
}
|
||||
|
||||
void DSP3::enable() {
|
||||
}
|
||||
|
||||
void DSP3::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void DSP3::reset() {
|
||||
DSP3i::DSP3_Reset();
|
||||
}
|
||||
|
||||
uint8 DSP3::read(uint addr) {
|
||||
DSP3i::dsp3_address = addr & 0xffff;
|
||||
DSP3i::DSP3GetByte();
|
||||
return DSP3i::dsp3_byte;
|
||||
}
|
||||
|
||||
void DSP3::write(uint addr, uint8 data) {
|
||||
DSP3i::dsp3_address = addr & 0xffff;
|
||||
DSP3i::dsp3_byte = data;
|
||||
DSP3i::DSP3SetByte();
|
||||
}
|
12
src/chip/dsp3/dsp3.h
Normal file
12
src/chip/dsp3/dsp3.h
Normal file
@@ -0,0 +1,12 @@
|
||||
class DSP3 : public Memory {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read (uint addr);
|
||||
void write(uint addr, uint8 data);
|
||||
};
|
||||
|
||||
extern DSP3 dsp3;
|
1142
src/chip/dsp3/dsp3emu.c
Normal file
1142
src/chip/dsp3/dsp3emu.c
Normal file
File diff suppressed because it is too large
Load Diff
53
src/chip/dsp4/dsp4.cpp
Normal file
53
src/chip/dsp4/dsp4.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "../../base.h"
|
||||
|
||||
namespace DSP4i {
|
||||
inline uint16 READ_WORD(uint8 *addr) {
|
||||
return (addr[0]) + (addr[1] << 8);
|
||||
}
|
||||
|
||||
inline uint32 READ_DWORD(uint8 *addr) {
|
||||
return (addr[0]) + (addr[1] << 8) + (addr[2] << 16) + (addr[3] << 24);
|
||||
}
|
||||
|
||||
inline void WRITE_WORD(uint8 *addr, uint16 data) {
|
||||
addr[0] = data;
|
||||
addr[1] = data >> 8;
|
||||
}
|
||||
|
||||
#define bool8 uint8
|
||||
#include "dsp4emu.c"
|
||||
#undef bool8
|
||||
};
|
||||
|
||||
void DSP4::init() {
|
||||
}
|
||||
|
||||
void DSP4::enable() {
|
||||
}
|
||||
|
||||
void DSP4::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void DSP4::reset() {
|
||||
DSP4i::InitDSP4();
|
||||
}
|
||||
|
||||
uint8 DSP4::read(uint addr) {
|
||||
addr &= 0xffff;
|
||||
if(addr < 0xc000) {
|
||||
DSP4i::dsp4_address = addr;
|
||||
DSP4i::DSP4GetByte();
|
||||
return DSP4i::dsp4_byte;
|
||||
}
|
||||
return 0x80;
|
||||
}
|
||||
|
||||
void DSP4::write(uint addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
if(addr < 0xc000) {
|
||||
DSP4i::dsp4_address = addr;
|
||||
DSP4i::dsp4_byte = data;
|
||||
DSP4i::DSP4SetByte();
|
||||
}
|
||||
}
|
12
src/chip/dsp4/dsp4.h
Normal file
12
src/chip/dsp4/dsp4.h
Normal file
@@ -0,0 +1,12 @@
|
||||
class DSP4 : public Memory {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read (uint addr);
|
||||
void write(uint addr, uint8 data);
|
||||
};
|
||||
|
||||
extern DSP4 dsp4;
|
2146
src/chip/dsp4/dsp4emu.c
Normal file
2146
src/chip/dsp4/dsp4emu.c
Normal file
File diff suppressed because it is too large
Load Diff
108
src/chip/dsp4/dsp4emu.h
Normal file
108
src/chip/dsp4/dsp4emu.h
Normal file
@@ -0,0 +1,108 @@
|
||||
//DSP-4 emulator code
|
||||
//Copyright (c) 2004-2006 Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden
|
||||
|
||||
#ifndef DSP4EMU_H
|
||||
#define DSP4EMU_H
|
||||
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
#define TRUE true
|
||||
#define FALSE false
|
||||
|
||||
struct DSP4_t
|
||||
{
|
||||
bool8 waiting4command;
|
||||
bool8 half_command;
|
||||
uint16 command;
|
||||
uint32 in_count;
|
||||
uint32 in_index;
|
||||
uint32 out_count;
|
||||
uint32 out_index;
|
||||
uint8 parameters[512];
|
||||
uint8 output[512];
|
||||
};
|
||||
|
||||
extern struct DSP4_t DSP4;
|
||||
|
||||
struct DSP4_vars_t
|
||||
{
|
||||
// op control
|
||||
int8 DSP4_Logic; // controls op flow
|
||||
|
||||
|
||||
// projection format
|
||||
int16 lcv; // loop-control variable
|
||||
int16 distance; // z-position into virtual world
|
||||
int16 raster; // current raster line
|
||||
int16 segments; // number of raster lines drawn
|
||||
|
||||
// 1.15.16 or 1.15.0 [sign, integer, fraction]
|
||||
int32 world_x; // line of x-projection in world
|
||||
int32 world_y; // line of y-projection in world
|
||||
int32 world_dx; // projection line x-delta
|
||||
int32 world_dy; // projection line y-delta
|
||||
int16 world_ddx; // x-delta increment
|
||||
int16 world_ddy; // y-delta increment
|
||||
int32 world_xenv; // world x-shaping factor
|
||||
int16 world_yofs; // world y-vertical scroll
|
||||
|
||||
int16 view_x1; // current viewer-x
|
||||
int16 view_y1; // current viewer-y
|
||||
int16 view_x2; // future viewer-x
|
||||
int16 view_y2; // future viewer-y
|
||||
int16 view_dx; // view x-delta factor
|
||||
int16 view_dy; // view y-delta factor
|
||||
int16 view_xofs1; // current viewer x-vertical scroll
|
||||
int16 view_yofs1; // current viewer y-vertical scroll
|
||||
int16 view_xofs2; // future viewer x-vertical scroll
|
||||
int16 view_yofs2; // future viewer y-vertical scroll
|
||||
int16 view_yofsenv; // y-scroll shaping factor
|
||||
int16 view_turnoff_x; // road turnoff data
|
||||
int16 view_turnoff_dx; // road turnoff delta factor
|
||||
|
||||
|
||||
// drawing area
|
||||
|
||||
int16 viewport_cx; // x-center of viewport window
|
||||
int16 viewport_cy; // y-center of render window
|
||||
int16 viewport_left; // x-left of viewport
|
||||
int16 viewport_right; // x-right of viewport
|
||||
int16 viewport_top; // y-top of viewport
|
||||
int16 viewport_bottom; // y-bottom of viewport
|
||||
|
||||
|
||||
// sprite structure
|
||||
|
||||
int16 sprite_x; // projected x-pos of sprite
|
||||
int16 sprite_y; // projected y-pos of sprite
|
||||
int16 sprite_attr; // obj attributes
|
||||
bool8 sprite_size; // sprite size: 8x8 or 16x16
|
||||
int16 sprite_clipy; // visible line to clip pixels off
|
||||
int16 sprite_count;
|
||||
|
||||
// generic projection variables designed for
|
||||
// two solid polygons + two polygon sides
|
||||
|
||||
int16 poly_clipLf[2][2]; // left clip boundary
|
||||
int16 poly_clipRt[2][2]; // right clip boundary
|
||||
int16 poly_ptr[2][2]; // HDMA structure pointers
|
||||
int16 poly_raster[2][2]; // current raster line below horizon
|
||||
int16 poly_top[2][2]; // top clip boundary
|
||||
int16 poly_bottom[2][2]; // bottom clip boundary
|
||||
int16 poly_cx[2][2]; // center for left/right points
|
||||
int16 poly_start[2]; // current projection points
|
||||
int16 poly_plane[2]; // previous z-plane distance
|
||||
|
||||
|
||||
// OAM
|
||||
int16 OAM_attr[16]; // OAM (size,MSB) data
|
||||
int16 OAM_index; // index into OAM table
|
||||
int16 OAM_bits; // offset into OAM table
|
||||
|
||||
int16 OAM_RowMax; // maximum number of tiles per 8 aligned pixels (row)
|
||||
int16 OAM_Row[32]; // current number of tiles per row
|
||||
};
|
||||
|
||||
extern struct DSP4_vars_t DSP4_vars;
|
||||
|
||||
#endif
|
@@ -1,7 +1,5 @@
|
||||
#include "../../base.h"
|
||||
|
||||
OBC1 *obc1;
|
||||
|
||||
void OBC1::init() {}
|
||||
void OBC1::enable() {}
|
||||
|
||||
@@ -10,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;
|
||||
extern OBC1 obc1;
|
||||
|
@@ -1,15 +1,11 @@
|
||||
#include "../../base.h"
|
||||
|
||||
SDD1 *sdd1;
|
||||
|
||||
#include "sdd1emu.cpp"
|
||||
|
||||
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() {
|
||||
@@ -17,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;
|
||||
@@ -82,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;
|
||||
extern SDD1 sdd1;
|
||||
|
@@ -28,7 +28,7 @@ understood.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
#define SDD1_read(__addr) (r_mem->read(__addr))
|
||||
#define SDD1_read(__addr) (bus.read(__addr))
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
|
@@ -52,8 +52,6 @@
|
||||
|
||||
#include "../../base.h"
|
||||
|
||||
SRTC *srtc;
|
||||
|
||||
void SRTC::set_time() {
|
||||
time_t rawtime;
|
||||
tm *t;
|
||||
@@ -79,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() {
|
||||
@@ -93,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) {
|
||||
@@ -118,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
|
||||
@@ -126,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,10 +43,10 @@ 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();
|
||||
};
|
||||
|
||||
extern SRTC *srtc;
|
||||
extern SRTC srtc;
|
||||
|
84
src/chip/st010/st010.cpp
Normal file
84
src/chip/st010/st010.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "../../base.h"
|
||||
#include "st010_data.h"
|
||||
#include "st010_op.cpp"
|
||||
|
||||
int16 ST010::sin(int16 theta) {
|
||||
return sin_table[(theta >> 8) & 0xff];
|
||||
}
|
||||
|
||||
int16 ST010::cos(int16 theta) {
|
||||
return sin_table[((theta + 0x4000) >> 8) & 0xff];
|
||||
}
|
||||
|
||||
uint8 ST010::readb(uint16 addr) {
|
||||
return ram[addr & 0xfff];
|
||||
}
|
||||
|
||||
uint16 ST010::readw(uint16 addr) {
|
||||
return (readb(addr + 0) << 0) |
|
||||
(readb(addr + 1) << 8);
|
||||
}
|
||||
|
||||
uint32 ST010::readd(uint16 addr) {
|
||||
return (readb(addr + 0) << 0) |
|
||||
(readb(addr + 1) << 8) |
|
||||
(readb(addr + 2) << 16) |
|
||||
(readb(addr + 3) << 24);
|
||||
}
|
||||
|
||||
void ST010::writeb(uint16 addr, uint8 data) {
|
||||
ram[addr & 0xfff] = data;
|
||||
}
|
||||
|
||||
void ST010::writew(uint16 addr, uint16 data) {
|
||||
writeb(addr + 0, data);
|
||||
writeb(addr + 1, data >> 8);
|
||||
}
|
||||
|
||||
void ST010::writed(uint16 addr, uint32 data) {
|
||||
writeb(addr + 0, data);
|
||||
writeb(addr + 1, data >> 8);
|
||||
writeb(addr + 2, data >> 16);
|
||||
writeb(addr + 3, data >> 24);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void ST010::init() {
|
||||
}
|
||||
|
||||
void ST010::enable() {
|
||||
}
|
||||
|
||||
void ST010::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void ST010::reset() {
|
||||
memset(ram, 0x00, sizeof ram);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
uint8 ST010::read(uint addr) {
|
||||
return readb(addr);
|
||||
}
|
||||
|
||||
void ST010::write(uint addr, uint8 data) {
|
||||
writeb(addr, data);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ram[0x0021] &= ~0x80;
|
||||
}
|
||||
}
|
42
src/chip/st010/st010.h
Normal file
42
src/chip/st010/st010.h
Normal file
@@ -0,0 +1,42 @@
|
||||
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);
|
||||
|
||||
//interfaces to ram buffer
|
||||
uint8 readb (uint16 addr);
|
||||
uint16 readw (uint16 addr);
|
||||
uint32 readd (uint16 addr);
|
||||
void writeb(uint16 addr, uint8 data);
|
||||
void writew(uint16 addr, uint16 data);
|
||||
void writed(uint16 addr, uint32 data);
|
||||
|
||||
//opcodes
|
||||
void op_01();
|
||||
void op_02();
|
||||
void op_03();
|
||||
void op_04();
|
||||
void op_05();
|
||||
void op_06();
|
||||
void op_07();
|
||||
void op_08();
|
||||
|
||||
void op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta);
|
||||
};
|
||||
|
||||
extern ST010 st010;
|
126
src/chip/st010/st010_data.h
Normal file
126
src/chip/st010/st010_data.h
Normal file
@@ -0,0 +1,126 @@
|
||||
const int16 ST010::sin_table[256] = {
|
||||
0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2,
|
||||
0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11,
|
||||
0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a,
|
||||
0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842,
|
||||
0x5a82, 0x5cb3, 0x5ed7, 0x60eb, 0x62f1, 0x64e8, 0x66cf, 0x68a6,
|
||||
0x6a6d, 0x6c23, 0x6dc9, 0x6f5e, 0x70e2, 0x7254, 0x73b5, 0x7504,
|
||||
0x7641, 0x776b, 0x7884, 0x7989, 0x7a7c, 0x7b5c, 0x7c29, 0x7ce3,
|
||||
0x7d89, 0x7e1d, 0x7e9c, 0x7f09, 0x7f61, 0x7fa6, 0x7fd8, 0x7ff5,
|
||||
0x7fff, 0x7ff5, 0x7fd8, 0x7fa6, 0x7f61, 0x7f09, 0x7e9c, 0x7e1d,
|
||||
0x7d89, 0x7ce3, 0x7c29, 0x7b5c, 0x7a7c, 0x7989, 0x7884, 0x776b,
|
||||
0x7641, 0x7504, 0x73b5, 0x7254, 0x70e2, 0x6f5e, 0x6dc9, 0x6c23,
|
||||
0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f1, 0x60eb, 0x5ed7, 0x5cb3,
|
||||
0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4,
|
||||
0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33df,
|
||||
0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f1a, 0x1c0b,
|
||||
0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8c, 0x096a, 0x0648, 0x0324,
|
||||
0x0000, -0x0324, -0x0648, -0x096b, -0x0c8c, -0x0fab, -0x12c8, -0x15e2,
|
||||
-0x18f9, -0x1c0b, -0x1f1a, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11,
|
||||
-0x30fb, -0x33df, -0x36ba, -0x398d, -0x3c56, -0x3f17, -0x41ce, -0x447a,
|
||||
-0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842,
|
||||
-0x5a82, -0x5cb3, -0x5ed7, -0x60ec, -0x62f1, -0x64e8, -0x66cf, -0x68a6,
|
||||
-0x6a6d, -0x6c23, -0x6dc9, -0x6f5e, -0x70e2, -0x7254, -0x73b5, -0x7504,
|
||||
-0x7641, -0x776b, -0x7884, -0x7989, -0x7a7c, -0x7b5c, -0x7c29, -0x7ce3,
|
||||
-0x7d89, -0x7e1d, -0x7e9c, -0x7f09, -0x7f61, -0x7fa6, -0x7fd8, -0x7ff5,
|
||||
-0x7fff, -0x7ff5, -0x7fd8, -0x7fa6, -0x7f61, -0x7f09, -0x7e9c, -0x7e1d,
|
||||
-0x7d89, -0x7ce3, -0x7c29, -0x7b5c, -0x7a7c, -0x7989, -0x7883, -0x776b,
|
||||
-0x7641, -0x7504, -0x73b5, -0x7254, -0x70e2, -0x6f5e, -0x6dc9, -0x6c23,
|
||||
-0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f1, -0x60eb, -0x5ed7, -0x5cb3,
|
||||
-0x5a82, -0x5842, -0x55f5, -0x539a, -0x5133, -0x4ebf, -0x4c3f, -0x49b3,
|
||||
-0x471c, -0x447a, -0x41cd, -0x3f17, -0x3c56, -0x398c, -0x36b9, -0x33de,
|
||||
-0x30fb, -0x2e10, -0x2b1f, -0x2826, -0x2527, -0x2223, -0x1f19, -0x1c0b,
|
||||
-0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324
|
||||
};
|
||||
|
||||
const int16 ST010::mode7_scale[176] = {
|
||||
0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3,
|
||||
0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b,
|
||||
0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8,
|
||||
0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6,
|
||||
0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5,
|
||||
0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d,
|
||||
0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c,
|
||||
0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e,
|
||||
0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063,
|
||||
0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a,
|
||||
0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052,
|
||||
0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c,
|
||||
0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047,
|
||||
0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042,
|
||||
0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e,
|
||||
0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a,
|
||||
0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037,
|
||||
0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034,
|
||||
0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031,
|
||||
0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f,
|
||||
0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d,
|
||||
0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b
|
||||
};
|
||||
|
||||
const uint8 ST010::arctan[32][32] = {
|
||||
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
|
||||
{ 0x80, 0xa0, 0xad, 0xb3, 0xb6, 0xb8, 0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf },
|
||||
{ 0x80, 0x93, 0xa0, 0xa8, 0xad, 0xb0, 0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd },
|
||||
{ 0x80, 0x8d, 0x98, 0xa0, 0xa6, 0xaa, 0xad, 0xb0, 0xb1, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb7, 0xb8,
|
||||
0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc },
|
||||
{ 0x80, 0x8a, 0x93, 0x9a, 0xa0, 0xa5, 0xa8, 0xab, 0xad, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xb5, 0xb5,
|
||||
0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb },
|
||||
{ 0x80, 0x88, 0x90, 0x96, 0x9b, 0xa0, 0xa4, 0xa7, 0xa9, 0xab, 0xad, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
|
||||
0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9 },
|
||||
{ 0x80, 0x87, 0x8d, 0x93, 0x98, 0x9c, 0xa0, 0xa3, 0xa6, 0xa8, 0xaa, 0xac, 0xad, 0xae, 0xb0, 0xb0,
|
||||
0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8 },
|
||||
{ 0x80, 0x86, 0x8b, 0x90, 0x95, 0x99, 0x9d, 0xa0, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xad, 0xae,
|
||||
0xaf, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7 },
|
||||
{ 0x80, 0x85, 0x8a, 0x8f, 0x93, 0x97, 0x9a, 0x9d, 0xa0, 0xa2, 0xa5, 0xa6, 0xa8, 0xaa, 0xab, 0xac,
|
||||
0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5 },
|
||||
{ 0x80, 0x85, 0x89, 0x8d, 0x91, 0x95, 0x98, 0x9b, 0x9e, 0xa0, 0xa0, 0xa4, 0xa6, 0xa7, 0xa9, 0xaa,
|
||||
0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4 },
|
||||
{ 0x80, 0x84, 0x88, 0x8c, 0x90, 0x93, 0x96, 0x99, 0x9b, 0x9e, 0xa0, 0xa2, 0xa4, 0xa5, 0xa7, 0xa8,
|
||||
0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3 },
|
||||
{ 0x80, 0x84, 0x87, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, 0xa6,
|
||||
0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2 },
|
||||
{ 0x80, 0x83, 0x87, 0x8a, 0x8d, 0x90, 0x93, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5,
|
||||
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1 },
|
||||
{ 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x94, 0x96, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa2, 0xa3,
|
||||
0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xb0 },
|
||||
{ 0x80, 0x83, 0x86, 0x89, 0x8b, 0x8e, 0x90, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa1,
|
||||
0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf },
|
||||
{ 0x80, 0x83, 0x85, 0x88, 0x8b, 0x8d, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9b, 0x9d, 0x9f, 0xa0,
|
||||
0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae },
|
||||
{ 0x80, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8f, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9a, 0x9c, 0x9d, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xab, 0xac, 0xad },
|
||||
{ 0x80, 0x82, 0x85, 0x87, 0x89, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97, 0x99, 0x9b, 0x9c, 0x9d,
|
||||
0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac },
|
||||
{ 0x80, 0x82, 0x85, 0x87, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x93, 0x95, 0x96, 0x98, 0x99, 0x9b, 0x9c,
|
||||
0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab },
|
||||
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x9a, 0x9b,
|
||||
0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa },
|
||||
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x99, 0x9a,
|
||||
0x9b, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9 },
|
||||
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8f, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x99,
|
||||
0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8 },
|
||||
{ 0x80, 0x82, 0x84, 0x86, 0x87, 0x89, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x98,
|
||||
0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7 },
|
||||
{ 0x80, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x96, 0x98,
|
||||
0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6 },
|
||||
{ 0x80, 0x82, 0x83, 0x85, 0x87, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5 },
|
||||
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x94, 0x95, 0x96,
|
||||
0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4 },
|
||||
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x89, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x95,
|
||||
0x96, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4 },
|
||||
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x87, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x95,
|
||||
0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3 },
|
||||
{ 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94,
|
||||
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2 },
|
||||
{ 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93,
|
||||
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa1 },
|
||||
{ 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8b, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93,
|
||||
0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1 },
|
||||
{ 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
|
||||
0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0 }
|
||||
};
|
257
src/chip/st010/st010_op.cpp
Normal file
257
src/chip/st010/st010_op.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
//ST-010 emulation code - Copyright (C) 2003 The Dumper, Matthew Kendora, Overload, Feather
|
||||
//bsnes port - Copyright (C) 2007 byuu
|
||||
|
||||
void ST010::op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta) {
|
||||
if((x0 < 0) && (y0 < 0)) {
|
||||
x1 = -x0;
|
||||
y1 = -y0;
|
||||
quadrant = -0x8000;
|
||||
} else if(x0 < 0) {
|
||||
x1 = y0;
|
||||
y1 = -x0;
|
||||
quadrant = -0x4000;
|
||||
} else if(y0 < 0) {
|
||||
x1 = -y0;
|
||||
y1 = x0;
|
||||
quadrant = 0x4000;
|
||||
} else {
|
||||
x1 = x0;
|
||||
y1 = y0;
|
||||
quadrant = 0x0000;
|
||||
}
|
||||
|
||||
while((x1 > 0x1f) || (y1 > 0x1f)) {
|
||||
if(x1 > 1) { x1 >>= 1; }
|
||||
if(y1 > 1) { y1 >>= 1; }
|
||||
}
|
||||
|
||||
if(y1 == 0) { quadrant += 0x4000; }
|
||||
|
||||
theta = (arctan[y1][x1] << 8) ^ quadrant;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void ST010::op_01() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 x1, y1, quadrant, theta;
|
||||
|
||||
op_01(x0, y0, x1, y1, quadrant, theta);
|
||||
|
||||
writew(0x0000, x1);
|
||||
writew(0x0002, y1);
|
||||
writew(0x0004, quadrant);
|
||||
//writew(0x0006, y0); //Overload's docs note this write occurs, SNES9x disagrees
|
||||
writew(0x0010, theta);
|
||||
}
|
||||
|
||||
void ST010::op_02() {
|
||||
int16 positions = readw(0x0024);
|
||||
uint16 *places = (uint16*)(ram + 0x0040);
|
||||
uint16 *drivers = (uint16*)(ram + 0x0080);
|
||||
|
||||
bool sorted;
|
||||
uint16 temp;
|
||||
if(positions > 1) {
|
||||
do {
|
||||
sorted = true;
|
||||
for(int i = 0; i < positions - 1; i++) {
|
||||
if(places[i] < places[i + 1]) {
|
||||
temp = places[i + 1];
|
||||
places[i + 1] = places[i];
|
||||
places[i] = temp;
|
||||
|
||||
temp = drivers[i + 1];
|
||||
drivers[i + 1] = drivers[i];
|
||||
drivers[i] = temp;
|
||||
|
||||
sorted = false;
|
||||
}
|
||||
}
|
||||
positions--;
|
||||
} while(!sorted);
|
||||
}
|
||||
}
|
||||
|
||||
void ST010::op_03() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 multiplier = readw(0x0004);
|
||||
int32 x1, y1;
|
||||
|
||||
x1 = x0 * multiplier << 1;
|
||||
y1 = y0 * multiplier << 1;
|
||||
|
||||
writed(0x0010, x1);
|
||||
writed(0x0014, y1);
|
||||
}
|
||||
|
||||
void ST010::op_04() {
|
||||
int16 x = readw(0x0000);
|
||||
int16 y = readw(0x0002);
|
||||
int16 square;
|
||||
//calculate the vector length of (x,y)
|
||||
square = (int16)sqrt((double)(y * y + x * x));
|
||||
|
||||
writew(0x0010, square);
|
||||
}
|
||||
|
||||
void ST010::op_05() {
|
||||
int32 dx, dy;
|
||||
int16 a1, b1, c1;
|
||||
uint16 o1;
|
||||
bool wrap = false;
|
||||
|
||||
//target (x,y) coordinates
|
||||
int16 ypos_max = readw(0x00c0);
|
||||
int16 xpos_max = readw(0x00c2);
|
||||
|
||||
//current coordinates and direction
|
||||
int32 ypos = readd(0x00c4);
|
||||
int32 xpos = readd(0x00c8);
|
||||
uint16 rot = readw(0x00cc);
|
||||
|
||||
//physics
|
||||
uint16 speed = readw(0x00d4);
|
||||
uint16 accel = readw(0x00d6);
|
||||
uint16 speed_max = readw(0x00d8);
|
||||
|
||||
//special condition acknowledgement
|
||||
int16 system = readw(0x00da);
|
||||
int16 flags = readw(0x00dc);
|
||||
|
||||
//new target coordinates
|
||||
int16 ypos_new = readw(0x00de);
|
||||
int16 xpos_new = readw(0x00e0);
|
||||
|
||||
//mask upper bit
|
||||
xpos_new &= 0x7fff;
|
||||
|
||||
//get the current distance
|
||||
dx = xpos_max - (xpos >> 16);
|
||||
dy = ypos_max - (ypos >> 16);
|
||||
|
||||
//quirk: clear and move in9
|
||||
writew(0x00d2, 0xffff);
|
||||
writew(0x00da, 0x0000);
|
||||
|
||||
//grab the target angle
|
||||
op_01(dy, dx, a1, b1, c1, (int16&)o1);
|
||||
|
||||
//check for wrapping
|
||||
if(abs(o1 - rot) > 0x8000) {
|
||||
o1 += 0x8000;
|
||||
rot += 0x8000;
|
||||
wrap = true;
|
||||
}
|
||||
|
||||
uint16 old_speed = speed;
|
||||
|
||||
//special case
|
||||
if(abs(o1 - rot) == 0x8000) {
|
||||
speed = 0x100;
|
||||
}
|
||||
|
||||
//slow down for sharp curves
|
||||
else if(abs(o1 - rot) >= 0x1000) {
|
||||
uint32 slow = abs(o1 - rot);
|
||||
slow >>= 4; //scaling
|
||||
speed -= slow;
|
||||
}
|
||||
|
||||
//otherwise accelerate
|
||||
else {
|
||||
speed += accel;
|
||||
if(speed > speed_max) {
|
||||
speed = speed_max; //clip speed
|
||||
}
|
||||
}
|
||||
|
||||
//prevent negative/positive overflow
|
||||
if(abs(old_speed - speed) > 0x8000) {
|
||||
if(old_speed < speed) { speed = 0; }
|
||||
else speed = 0xff00;
|
||||
}
|
||||
|
||||
//adjust direction by so many degrees
|
||||
//be careful of negative adjustments
|
||||
if((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) {
|
||||
if(o1 < rot) { rot -= 0x280; }
|
||||
else if(o1 > rot) { rot += 0x280; }
|
||||
}
|
||||
|
||||
//turn of wrapping
|
||||
if(wrap) { rot -= 0x8000; }
|
||||
|
||||
//now check the distances (store for later)
|
||||
dx = (xpos_max << 16) - xpos;
|
||||
dy = (ypos_max << 16) - ypos;
|
||||
dx >>= 16;
|
||||
dy >>= 16;
|
||||
|
||||
//if we're in so many units of the target, signal it
|
||||
if((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) {
|
||||
//announce our new destination and flag it
|
||||
xpos_max = xpos_new & 0x7fff;
|
||||
ypos_max = ypos_new;
|
||||
flags |= 0x08;
|
||||
}
|
||||
|
||||
//update position
|
||||
xpos -= (cos(rot) * 0x400 >> 15) * (speed >> 8) << 1;
|
||||
ypos -= (sin(rot) * 0x400 >> 15) * (speed >> 8) << 1;
|
||||
|
||||
//quirk: mask upper byte
|
||||
xpos &= 0x1fffffff;
|
||||
ypos &= 0x1fffffff;
|
||||
|
||||
writew(0x00c0, ypos_max);
|
||||
writew(0x00c2, xpos_max);
|
||||
writed(0x00c4, ypos);
|
||||
writed(0x00c8, xpos);
|
||||
writew(0x00cc, rot);
|
||||
writew(0x00d4, speed);
|
||||
writew(0x00dc, flags);
|
||||
}
|
||||
|
||||
void ST010::op_06() {
|
||||
int16 multiplicand = readw(0x0000);
|
||||
int16 multiplier = readw(0x0002);
|
||||
int32 product;
|
||||
|
||||
product = multiplicand * multiplier << 1;
|
||||
|
||||
writed(0x0010, product);
|
||||
}
|
||||
|
||||
void ST010::op_07() {
|
||||
int16 theta = readw(0x0000);
|
||||
|
||||
int16 data;
|
||||
for(int i = 0, offset = 0; i < 176; i++) {
|
||||
data = mode7_scale[i] * cos(theta) >> 15;
|
||||
writew(0x00f0 + offset, data);
|
||||
writew(0x0510 + offset, data);
|
||||
|
||||
data = mode7_scale[i] * sin(theta) >> 15;
|
||||
writew(0x0250 + offset, data);
|
||||
if(data) { data = ~data; }
|
||||
writew(0x03b0 + offset, data);
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void ST010::op_08() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 theta = readw(0x0004);
|
||||
int16 x1, y1;
|
||||
|
||||
x1 = (y0 * sin(theta) >> 15) + (x0 * cos(theta) >> 15);
|
||||
y1 = (y0 * cos(theta) >> 15) - (x0 * sin(theta) >> 15);
|
||||
|
||||
writew(0x0010, x1);
|
||||
writew(0x0012, y1);
|
||||
}
|
3
src/chip/superfx/core/core.h
Normal file
3
src/chip/superfx/core/core.h
Normal file
@@ -0,0 +1,3 @@
|
||||
void op_unknown() {}
|
||||
|
||||
void op_00();
|
7
src/chip/superfx/core/op0x.cpp
Normal file
7
src/chip/superfx/core/op0x.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
//STOP
|
||||
void SuperFX::op_00() {
|
||||
regs.sfr.g = 0;
|
||||
regs.sfr.b = 0;
|
||||
regs.sfr.alt1 = 0;
|
||||
regs.sfr.alt2 = 0;
|
||||
}
|
66
src/chip/superfx/memory/read.cpp
Normal file
66
src/chip/superfx/memory/read.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
uint8 SuperFX::mmio_read(uint addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
case 0x3000: return regs.r0.l;
|
||||
case 0x3001: return regs.r0.h;
|
||||
case 0x3002: return regs.r1.l;
|
||||
case 0x3003: return regs.r1.h;
|
||||
case 0x3004: return regs.r2.l;
|
||||
case 0x3005: return regs.r2.h;
|
||||
case 0x3006: return regs.r3.l;
|
||||
case 0x3007: return regs.r3.h;
|
||||
case 0x3008: return regs.r4.l;
|
||||
case 0x3009: return regs.r4.h;
|
||||
case 0x300a: return regs.r5.l;
|
||||
case 0x300b: return regs.r5.h;
|
||||
case 0x300c: return regs.r6.l;
|
||||
case 0x300d: return regs.r6.h;
|
||||
case 0x300e: return regs.r7.l;
|
||||
case 0x300f: return regs.r7.h;
|
||||
|
||||
case 0x3010: return regs.r8.l;
|
||||
case 0x3011: return regs.r8.h;
|
||||
case 0x3012: return regs.r9.l;
|
||||
case 0x3013: return regs.r9.h;
|
||||
case 0x3014: return regs.r10.l;
|
||||
case 0x3015: return regs.r10.h;
|
||||
case 0x3016: return regs.r11.l;
|
||||
case 0x3017: return regs.r11.h;
|
||||
case 0x3018: return regs.r12.l;
|
||||
case 0x3019: return regs.r12.h;
|
||||
case 0x301a: return regs.r13.l;
|
||||
case 0x301b: return regs.r13.h;
|
||||
case 0x301c: return regs.r14.l;
|
||||
case 0x301d: return regs.r14.h;
|
||||
case 0x301e: return regs.r15.l;
|
||||
case 0x301f: return regs.r15.h;
|
||||
|
||||
//0x3020 - 0x302f unused
|
||||
|
||||
case 0x3030: return regs.sfr;
|
||||
case 0x3031: return regs.sfr >> 8;
|
||||
case 0x3032: return 0x00; //unused
|
||||
case 0x3033: return 0x00; //BRAMR (write only)
|
||||
case 0x3034: return regs.pbr;
|
||||
case 0x3035: return 0x00; //unused
|
||||
case 0x3036: return regs.rombr;
|
||||
case 0x3037: return 0x00; //CFGR (write only)
|
||||
case 0x3038: return 0x00; //SCBR (write only)
|
||||
case 0x3039: return 0x00; //CLSR (write only)
|
||||
case 0x303a: return 0x00; //SCMR (write only)
|
||||
case 0x303b: return regs.vcr;
|
||||
case 0x303c: return regs.rambr;
|
||||
case 0x303d: return 0x00; //unused
|
||||
case 0x303e: return regs.cbr;
|
||||
case 0x303f: return regs.cbr >> 8;
|
||||
|
||||
//0x3040 - 0x30ff unused
|
||||
}
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
return cache[addr - 0x3100];
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
65
src/chip/superfx/memory/write.cpp
Normal file
65
src/chip/superfx/memory/write.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
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;
|
||||
case 0x3002: regs.r1.l = data; return;
|
||||
case 0x3003: regs.r1.h = data; return;
|
||||
case 0x3004: regs.r2.l = data; return;
|
||||
case 0x3005: regs.r2.h = data; return;
|
||||
case 0x3006: regs.r3.l = data; return;
|
||||
case 0x3007: regs.r3.h = data; return;
|
||||
case 0x3008: regs.r4.l = data; return;
|
||||
case 0x3009: regs.r4.h = data; return;
|
||||
case 0x300a: regs.r5.l = data; return;
|
||||
case 0x300b: regs.r5.h = data; return;
|
||||
case 0x300c: regs.r6.l = data; return;
|
||||
case 0x300d: regs.r6.h = data; return;
|
||||
case 0x300e: regs.r7.l = data; return;
|
||||
case 0x300f: regs.r7.h = data; return;
|
||||
|
||||
case 0x3010: regs.r8.l = data; return;
|
||||
case 0x3011: regs.r8.h = data; return;
|
||||
case 0x3012: regs.r9.l = data; return;
|
||||
case 0x3013: regs.r9.h = data; return;
|
||||
case 0x3014: regs.r10.l = data; return;
|
||||
case 0x3015: regs.r10.h = data; return;
|
||||
case 0x3016: regs.r11.l = data; return;
|
||||
case 0x3017: regs.r11.h = data; return;
|
||||
case 0x3018: regs.r12.l = data; return;
|
||||
case 0x3019: regs.r12.h = data; return;
|
||||
case 0x301a: regs.r13.l = data; return;
|
||||
case 0x301b: regs.r13.h = data; return;
|
||||
case 0x301c: regs.r14.l = data; return;
|
||||
case 0x301d: regs.r14.h = data; return;
|
||||
case 0x301e: regs.r15.l = data; return;
|
||||
case 0x301f: regs.r15.h = data; return;
|
||||
|
||||
//0x3020 - 0x302f unused
|
||||
|
||||
case 0x3030: regs.sfr.l = data & 0x7e; return; //mask invalid bits
|
||||
case 0x3031: regs.sfr.h = data & 0x9f; return; //mask invalid bits
|
||||
case 0x3032: return; //unused
|
||||
case 0x3033: regs.bramr = data; return;
|
||||
case 0x3034: regs.pbr = data; return;
|
||||
case 0x3035: return; //unused
|
||||
case 0x3036: return; //ROMBR (read only)
|
||||
case 0x3037: regs.cfgr = data; return;
|
||||
case 0x3038: regs.scbr = data; return;
|
||||
case 0x3039: regs.clsr = data; return;
|
||||
case 0x303a: regs.scmr = data; return;
|
||||
case 0x303b: return; //VCR (read only)
|
||||
case 0x303c: return; //RAMBR (read only)
|
||||
case 0x303d: return; //unused
|
||||
case 0x303e: return; //CBR low (read only)
|
||||
case 0x303f: return; //CBR high (read only)
|
||||
|
||||
//0x3040 - 0x30ff unused
|
||||
}
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
cache[addr - 0x3100] = data;
|
||||
return;
|
||||
}
|
||||
}
|
174
src/chip/superfx/regs.h
Normal file
174
src/chip/superfx/regs.h
Normal file
@@ -0,0 +1,174 @@
|
||||
struct Reg16 {
|
||||
union {
|
||||
uint16 w;
|
||||
struct { uint8 order_lsb2(l, h); };
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return w; }
|
||||
inline unsigned operator=(const unsigned i) { return w = i; }
|
||||
|
||||
Reg16() : w(0) {}
|
||||
};
|
||||
|
||||
template<int bit> struct RegFlag8 {
|
||||
uint8 data;
|
||||
|
||||
inline operator bool() const { return data & bit; }
|
||||
inline bool operator=(const bool i) { i ? data |= bit : data &= ~bit; return i; }
|
||||
};
|
||||
|
||||
template<int bit> struct RegFlag16 {
|
||||
uint16 data;
|
||||
|
||||
inline operator bool() const { return data & bit; }
|
||||
inline bool operator=(const bool i) { i ? data |= bit : data &= ~bit; return i; }
|
||||
};
|
||||
|
||||
struct SFR {
|
||||
union {
|
||||
uint16 w;
|
||||
struct { uint8 order_lsb2(l, h); };
|
||||
RegFlag16<0x0002> z; //zero flag
|
||||
RegFlag16<0x0004> c; //carry flag
|
||||
RegFlag16<0x0008> s; //sign flag
|
||||
RegFlag16<0x0010> v; //overflow flag
|
||||
RegFlag16<0x0020> g; //go flag
|
||||
RegFlag16<0x0040> r; //ROM read using r14 flag
|
||||
RegFlag16<0x0100> alt1; //alternate instruction 1 flag
|
||||
RegFlag16<0x0200> alt2; //alternate instruction 2 flag
|
||||
RegFlag16<0x0400> il; //immediate lower 8-bit flag
|
||||
RegFlag16<0x0800> ih; //immediate upper 8-bit flag
|
||||
RegFlag16<0x1000> b; //WITH instruction flag
|
||||
RegFlag16<0x8000> irq; //interrupt flag
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return w & 0x9f7e; } //invalid flag bits always return 0 when read
|
||||
inline unsigned operator=(const unsigned i) { return w = i & 0x9f7e; }
|
||||
|
||||
SFR() : w(0) {}
|
||||
};
|
||||
|
||||
struct RAMBR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x01> bank;
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b & 0x01; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i & 0x01; }
|
||||
|
||||
RAMBR() : b(0) {}
|
||||
};
|
||||
|
||||
struct CBR {
|
||||
uint16 w;
|
||||
|
||||
inline operator unsigned() const { return w & 0xfff0; }
|
||||
inline unsigned operator=(const unsigned i) { return w = i & 0xfff0; }
|
||||
|
||||
CBR() : w(0) {}
|
||||
};
|
||||
|
||||
struct SCMR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x01> md0; //color mode low
|
||||
RegFlag8<0x02> md1; //color mode high
|
||||
RegFlag8<0x04> ht0; //height low
|
||||
RegFlag8<0x08> ran; //ram enable
|
||||
RegFlag8<0x10> ron; //rom enable
|
||||
RegFlag8<0x20> ht1; //height high
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i; }
|
||||
|
||||
SCMR() : b(0) {}
|
||||
};
|
||||
|
||||
struct BRAMR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x01> flag;
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i; }
|
||||
|
||||
BRAMR() : b(0) {}
|
||||
};
|
||||
|
||||
struct CFGR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x20> ms0; //multiplier speed selection
|
||||
RegFlag8<0x80> irq; //irq mask flag
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i; }
|
||||
|
||||
CFGR() : b(0) {}
|
||||
};
|
||||
|
||||
struct CLSR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x01> flag;
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i; }
|
||||
|
||||
CLSR() : b(0) {}
|
||||
};
|
||||
|
||||
struct POR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x01> transparent; //transparent flag
|
||||
RegFlag8<0x02> dither; //dither flag
|
||||
RegFlag8<0x04> highnibble; //high nibble flag
|
||||
RegFlag8<0x08> freezehigh; //freeze high flag
|
||||
RegFlag8<0x10> obj; //OBJ flag
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i; }
|
||||
|
||||
POR() : b(0) {}
|
||||
};
|
||||
|
||||
struct Regs {
|
||||
Reg16 r0; //default source/destination register
|
||||
Reg16 r1; //pixel plot X position register
|
||||
Reg16 r2; //pixel plot Y position register
|
||||
Reg16 r3;
|
||||
Reg16 r4; //lower 16-bit result of lmult
|
||||
Reg16 r5;
|
||||
Reg16 r6; //multiplier for fmult and lmult
|
||||
Reg16 r7; //fixed point texel X position for merge
|
||||
Reg16 r8; //fixed point texel Y position for merge
|
||||
Reg16 r9;
|
||||
Reg16 r10;
|
||||
Reg16 r11; //return address set by link
|
||||
Reg16 r12; //loop counter
|
||||
Reg16 r13; //loop point address
|
||||
Reg16 r14; //rom address for getb, getbh, getbl, getbs
|
||||
Reg16 r15; //program counter
|
||||
|
||||
SFR sfr; //status/flag register
|
||||
uint8 pbr; //program bank register
|
||||
uint8 rombr; //rom bank register
|
||||
RAMBR rambr; //ram bank register
|
||||
CBR cbr; //cache base register
|
||||
uint8 scbr; //screen base register
|
||||
SCMR scmr; //screen mode register
|
||||
BRAMR bramr; //backup ram register
|
||||
uint8 vcr; //version code register
|
||||
CFGR cfgr; //config register
|
||||
CLSR clsr; //clock select register
|
||||
|
||||
uint8 colr; //color register
|
||||
POR por; //plot option register
|
||||
} regs;
|
42
src/chip/superfx/superfx.cpp
Normal file
42
src/chip/superfx/superfx.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "../../base.h"
|
||||
|
||||
#include "core/op0x.cpp"
|
||||
|
||||
#include "memory/read.cpp"
|
||||
#include "memory/write.cpp"
|
||||
|
||||
void SuperFX::init() {
|
||||
}
|
||||
|
||||
void SuperFX::enable() {
|
||||
for(uint i = 0x3000; i <= 0x32ff; i++) {
|
||||
memory::mmio.map(i, *this);
|
||||
}
|
||||
}
|
||||
|
||||
void SuperFX::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void SuperFX::reset() {
|
||||
regs.r0 = 0;
|
||||
regs.r1 = 0;
|
||||
regs.r2 = 0;
|
||||
regs.r3 = 0;
|
||||
regs.r4 = 0;
|
||||
regs.r5 = 0;
|
||||
regs.r6 = 0;
|
||||
regs.r7 = 0;
|
||||
regs.r8 = 0;
|
||||
regs.r9 = 0;
|
||||
regs.r10 = 0;
|
||||
regs.r11 = 0;
|
||||
regs.r12 = 0;
|
||||
regs.r13 = 0;
|
||||
regs.r14 = 0;
|
||||
regs.r15 = 0;
|
||||
|
||||
regs.sfr = 0;
|
||||
|
||||
memset(cache, 0, sizeof cache);
|
||||
}
|
17
src/chip/superfx/superfx.h
Normal file
17
src/chip/superfx/superfx.h
Normal file
@@ -0,0 +1,17 @@
|
||||
class SuperFX : public MMIO { public:
|
||||
#include "core/core.h"
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mmio_read (uint addr);
|
||||
void mmio_write(uint addr, uint8 data);
|
||||
|
||||
private:
|
||||
#include "regs.h"
|
||||
uint8 cache[512]; //cache RAM
|
||||
};
|
||||
|
||||
extern SuperFX superfx;
|
@@ -1 +1,2 @@
|
||||
@make PLATFORM=win-visualc-lui clean
|
||||
@make PLATFORM=win-mingw-lui clean
|
||||
::@make PLATFORM=win-visualc-lui clean
|
||||
|
@@ -1,7 +1,10 @@
|
||||
Config config_file;
|
||||
|
||||
namespace config {
|
||||
|
||||
Config& config() {
|
||||
static Config config;
|
||||
return config;
|
||||
}
|
||||
|
||||
string file_updatepath(const char *req_file, const char *req_path) {
|
||||
string file(req_file);
|
||||
replace(file, "\\", "/");
|
||||
@@ -25,70 +28,92 @@ 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_file, "path.rom",
|
||||
StringSetting Path::rom(&config(), "path.rom",
|
||||
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
||||
StringSetting Path::save(&config_file, "path.save",
|
||||
StringSetting Path::save(&config(), "path.save",
|
||||
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
|
||||
StringSetting Path::bios(&config_file, "path.bios",
|
||||
"Path where BIOS file(s) are located\n"
|
||||
"Supported BIOS files:\n"
|
||||
"stbios.bin - Bandai Sufami Turbo"
|
||||
"", "./bios");
|
||||
StringSetting Path::bsx(&config(), "path.bsx", "", "");
|
||||
StringSetting Path::st(&config(), "path.st", "", "");
|
||||
|
||||
StringSetting Path::save_ext(&config_file, "path.save_ext",
|
||||
"Extension to be used for all save RAM files", "srm");
|
||||
|
||||
IntegerSetting SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
|
||||
IntegerSetting SNES::gamma_ramp(&config(), "snes.colorfilter.gamma_ramp",
|
||||
"Use precalculated TV-style gamma ramp", IntegerSetting::Boolean, true);
|
||||
IntegerSetting SNES::sepia(&config_file, "snes.colorfilter.sepia",
|
||||
IntegerSetting SNES::sepia(&config(), "snes.colorfilter.sepia",
|
||||
"Convert color to sepia tone", IntegerSetting::Boolean, false);
|
||||
IntegerSetting SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
|
||||
IntegerSetting SNES::grayscale(&config(), "snes.colorfilter.grayscale",
|
||||
"Convert color to grayscale tone", IntegerSetting::Boolean, false);
|
||||
IntegerSetting SNES::invert(&config_file, "snes.colorfilter.invert",
|
||||
IntegerSetting SNES::invert(&config(), "snes.colorfilter.invert",
|
||||
"Invert output image colors", IntegerSetting::Boolean, false);
|
||||
IntegerSetting SNES::contrast(&config_file, "snes.colorfilter.contrast",
|
||||
IntegerSetting SNES::contrast(&config(), "snes.colorfilter.contrast",
|
||||
"Contrast", IntegerSetting::Decimal, 0);
|
||||
IntegerSetting SNES::brightness(&config_file, "snes.colorfilter.brightness",
|
||||
IntegerSetting SNES::brightness(&config(), "snes.colorfilter.brightness",
|
||||
"Brightness", IntegerSetting::Decimal, 0);
|
||||
IntegerSetting SNES::gamma(&config_file, "snes.colorfilter.gamma",
|
||||
IntegerSetting SNES::gamma(&config(), "snes.colorfilter.gamma",
|
||||
"Gamma", IntegerSetting::Decimal, 80);
|
||||
|
||||
IntegerSetting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields",
|
||||
IntegerSetting SNES::ntsc_merge_fields(&config(), "snes.ntsc_merge_fields",
|
||||
"Merge fields in NTSC video filter\n"
|
||||
"Set to true if using filter at any refresh rate other than 60hz\n"
|
||||
"", IntegerSetting::Boolean, true);
|
||||
|
||||
IntegerSetting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
|
||||
IntegerSetting SNES::mute(&config(), "snes.mute", "Mutes SNES audio output when enabled",
|
||||
IntegerSetting::Boolean, false);
|
||||
|
||||
IntegerSetting SNES::controller_port0(&config_file, "snes.controller_port_1",
|
||||
IntegerSetting SNES::controller_port0(&config(), "snes.controller_port_1",
|
||||
"Controller attached to SNES port 1", IntegerSetting::Decimal, ::SNES::DEVICEID_JOYPAD1);
|
||||
IntegerSetting SNES::controller_port1(&config_file, "snes.controller_port_2",
|
||||
IntegerSetting SNES::controller_port1(&config(), "snes.controller_port_2",
|
||||
"Controller attached to SNES port 2", IntegerSetting::Decimal, ::SNES::DEVICEID_JOYPAD2);
|
||||
|
||||
IntegerSetting CPU::ntsc_clock_rate(&config_file, "cpu.ntsc_clock_rate",
|
||||
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_file, "cpu.pal_clock_rate",
|
||||
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);
|
||||
|
||||
IntegerSetting SMP::ntsc_clock_rate(&config_file, "smp.ntsc_clock_rate",
|
||||
IntegerSetting SMP::ntsc_clock_rate(&config(), "smp.ntsc_clock_rate",
|
||||
"NTSC S-SMP clock rate (in hz)", IntegerSetting::Decimal, 24606720);
|
||||
IntegerSetting SMP::pal_clock_rate(&config_file, "smp.pal_clock_rate",
|
||||
IntegerSetting SMP::pal_clock_rate(&config(), "smp.pal_clock_rate",
|
||||
"PAL S-SMP clock rate (in hz)", IntegerSetting::Decimal, 24606720);
|
||||
|
||||
IntegerSetting PPU::Hack::render_scanline_position(&config_file, "ppu.hack.render_scanline_position",
|
||||
IntegerSetting PPU::Hack::render_scanline_position(&config(), "ppu.hack.render_scanline_position",
|
||||
"Approximate HCLOCK position to render at for scanline-based renderers",
|
||||
IntegerSetting::Decimal, 512);
|
||||
IntegerSetting PPU::Hack::obj_cache(&config_file, "ppu.hack.obj_cache",
|
||||
IntegerSetting PPU::Hack::obj_cache(&config(), "ppu.hack.obj_cache",
|
||||
"Cache OAM OBJ attributes one scanline before rendering\n"
|
||||
"This is technically closer to the actual operation of the SNES,\n"
|
||||
"but can cause problems in some games if enabled",
|
||||
IntegerSetting::Boolean, false);
|
||||
IntegerSetting PPU::Hack::oam_address_invalidation(&config(), "ppu.hack.oam_address_invalidation",
|
||||
"OAM access address changes during active display, as the S-PPU reads\n"
|
||||
"data to render the display. Thusly, the address retrieved when accessing\n"
|
||||
"OAM during active display is unpredictable. Unfortunately, the exact\n"
|
||||
"algorithm for this is completely unknown at this time. It is more hardware\n"
|
||||
"accurate to enable this setting, but one must *not* rely on the actual\n"
|
||||
"address to match hardware under emulation.",
|
||||
IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::Hack::cgram_address_invalidation(&config(), "ppu.hack.cgram_address_invalidation",
|
||||
"CGRAM access address changes during active display (excluding hblank), as\n"
|
||||
"the S-PPU reads data to render the display. Thusly, as with OAM, the access\n"
|
||||
"address is unpredictable. Again, enabling this setting is more hardware\n"
|
||||
"accurate, but one must *not* rely on the actual address to match hardware\n"
|
||||
"under emulation.",
|
||||
IntegerSetting::Boolean, true);
|
||||
|
||||
IntegerSetting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", IntegerSetting::Boolean, true);
|
||||
|
@@ -1,12 +1,12 @@
|
||||
extern Config config_file;
|
||||
|
||||
namespace config {
|
||||
|
||||
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;
|
||||
|
||||
@@ -30,6 +31,8 @@ extern struct PPU {
|
||||
struct Hack {
|
||||
static IntegerSetting render_scanline_position;
|
||||
static IntegerSetting obj_cache;
|
||||
static IntegerSetting oam_address_invalidation;
|
||||
static IntegerSetting cgram_address_invalidation;
|
||||
} hack;
|
||||
|
||||
static IntegerSetting opt_enable;
|
||||
|
5
src/configure
vendored
Normal file
5
src/configure
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
echo "Warning: bsnes does not use a configure script"
|
||||
echo "To compile bsnes, use make ..."
|
||||
echo ""
|
||||
make #prints make usage instructions
|
@@ -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);
|
||||
@@ -83,8 +83,8 @@ 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());
|
||||
if(cartridge.info.sdd1 == true && sdd1.dma_active() == true) {
|
||||
bus.write(0x2100 | bbus, sdd1.dma_read());
|
||||
} else {
|
||||
dma_transfer(0, bbus, dma_addr(i));
|
||||
}
|
||||
@@ -111,8 +111,7 @@ void sCPU::dma_run() {
|
||||
dma_add_clocks(8);
|
||||
|
||||
if(cartridge.info.sdd1 == true) {
|
||||
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
|
||||
channel[i].xfersize);
|
||||
sdd1.dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr), channel[i].xfersize);
|
||||
}
|
||||
|
||||
if(tracer.enabled() == true && tracer.cpudma_enabled() == true) {
|
||||
@@ -168,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;
|
||||
|
@@ -1,8 +1,6 @@
|
||||
class sCPU : public CPU {
|
||||
public:
|
||||
class sCPU : public CPU { public:
|
||||
void enter();
|
||||
|
||||
public:
|
||||
#include "core/core.h"
|
||||
#include "dma/dma.h"
|
||||
#include "memory/memory.h"
|
||||
|
@@ -90,7 +90,7 @@ void sCPU::scanline() {
|
||||
status.line_rendered = false;
|
||||
status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true;
|
||||
|
||||
r_ppu->scanline();
|
||||
ppu.scanline();
|
||||
snes.scanline();
|
||||
|
||||
update_interrupts();
|
||||
@@ -117,7 +117,7 @@ void sCPU::frame() {
|
||||
status.hdmainit_trigger_position = 12 + dma_counter();
|
||||
}
|
||||
|
||||
r_ppu->frame();
|
||||
ppu.frame();
|
||||
snes.frame();
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ void sCPU::cycle_edge() {
|
||||
if(status.line_rendered == false) {
|
||||
if(status.hclock >= status.line_render_position) {
|
||||
status.line_rendered = true;
|
||||
r_ppu->render_scanline();
|
||||
ppu.render_scanline();
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
src/data/bsnes.png
Normal file
BIN
src/data/bsnes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB |
BIN
src/doc/base.dia
Normal file
BIN
src/doc/base.dia
Normal file
Binary file not shown.
@@ -660,9 +660,11 @@ 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 );
|
||||
//memcpy( m.regs, initial_regs, sizeof m.regs );
|
||||
memset(m.regs, 0, sizeof m.regs);
|
||||
REG(flg) = 0xe0;
|
||||
|
||||
// Internal state
|
||||
for ( int i = voice_count; --i >= 0; )
|
||||
|
@@ -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,44 +15,22 @@
|
||||
#include "ppu/bppu/bppu.h"
|
||||
|
||||
#include "snes/snes.h"
|
||||
#include "chip/chip.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/obc1/obc1.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,9 +1,9 @@
|
||||
/*
|
||||
libarray : version 0.08 ~byuu (2006-12-16)
|
||||
libarray : version 0.09 ~byuu (2007-03-06)
|
||||
*/
|
||||
|
||||
#ifndef __LIBARRAY
|
||||
#define __LIBARRAY
|
||||
#ifndef LIBARRAY_H
|
||||
#define LIBARRAY_H
|
||||
|
||||
template<typename T> class array {
|
||||
protected:
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
libbase : version 0.10 ~byuu (2007-05-27)
|
||||
libbase : version 0.11a ~byuu (2007-10-14)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <new>
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <shlobj.h>
|
||||
@@ -32,6 +34,10 @@
|
||||
|
||||
#define NOMINMAX
|
||||
#define PATH_MAX _MAX_PATH
|
||||
#define va_copy(dst, src) ((dst) = (src))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#define getcwd _getcwd
|
||||
#define ftruncate _chsize
|
||||
#define mkdir _mkdir
|
||||
@@ -39,11 +45,10 @@
|
||||
#define rmdir _rmdir
|
||||
#define vsnprintf _vsnprintf
|
||||
|
||||
#define va_copy(dst, src) ((dst) = (src))
|
||||
static char *realpath(const char *file_name, char *resolved_name) {
|
||||
return _fullpath(resolved_name, file_name, PATH_MAX);
|
||||
}
|
||||
#elif defined(__GNUC__)
|
||||
#else
|
||||
#define mkdir(path) (mkdir)(path, 0755);
|
||||
#endif
|
||||
|
||||
@@ -55,17 +60,14 @@
|
||||
#define noinline __declspec(noinline)
|
||||
#define inline inline
|
||||
#define alwaysinline __forceinline
|
||||
#define fastcall __fastcall
|
||||
#elif defined(__GNUC__)
|
||||
#define noinline __attribute__((noinline))
|
||||
#define inline inline
|
||||
#define alwaysinline __attribute__((always_inline))
|
||||
#define fastcall __attribute__((fastcall))
|
||||
#else
|
||||
#define noinline
|
||||
#define inline inline
|
||||
#define alwaysinline inline
|
||||
#define fastcall
|
||||
#endif
|
||||
|
||||
/*****
|
||||
@@ -91,13 +93,13 @@ typedef int64_t int64;
|
||||
//userpath(output) retrieves path to user's home folder
|
||||
//output must be at least as large as PATH_MAX
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
static char *userpath(char *output) {
|
||||
strcpy(output, "."); //failsafe
|
||||
SHGetFolderPath(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, output);
|
||||
return output;
|
||||
}
|
||||
#elif defined(__GNUC__)
|
||||
#else
|
||||
static char *userpath(char *output) {
|
||||
strcpy(output, "."); //failsafe
|
||||
struct passwd *userinfo = getpwuid(getuid());
|
||||
@@ -137,14 +139,10 @@ T z = x;
|
||||
y = z;
|
||||
}
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#define max(x, y) (((x) > (y)) ? (x) : (y))
|
||||
|
||||
template<int min, int max, typename T> inline T minmax(const T x) {
|
||||
@@ -171,34 +169,6 @@ enum { b = 1U << (bits - 1), m = (1U << bits) - 1 };
|
||||
return ((x & m) ^ b) - b;
|
||||
}
|
||||
|
||||
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,14 +1,14 @@
|
||||
;*****
|
||||
;libco_x86 : version 0.10 ~byuu (2007-04-18)
|
||||
;libco_x86 : version 0.10 ~byuu (2007-09-08)
|
||||
;cross-platform x86 implementation of libco
|
||||
;special thanks to Aaron Giles and Joel Yliluoma for various optimizations
|
||||
;
|
||||
;[ABI compatibility]
|
||||
;- visual c++; windows-x86
|
||||
;- mingw; windows-x86
|
||||
;- gcc; osx86
|
||||
;- gcc; linux-x86
|
||||
;- gcc; freebsd-x86
|
||||
;- visual c++; windows; x86
|
||||
;- mingw; windows; x86
|
||||
;- gcc; mac os x; x86
|
||||
;- gcc; linux; x86
|
||||
;- gcc; freebsd; x86
|
||||
;
|
||||
;[nonvolatile registers]
|
||||
;- esp, ebp, edi, esi, ebx
|
||||
@@ -28,7 +28,7 @@
|
||||
%define free _free
|
||||
|
||||
%define co_active @co_active@0
|
||||
%define co_create @co_create@12
|
||||
%define co_create @co_create@8
|
||||
%define co_delete @co_delete@4
|
||||
%define co_switch @co_switch@4
|
||||
%endif
|
||||
@@ -76,11 +76,10 @@ co_active:
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)(void *data), void *data);
|
||||
;ecx = heapsize
|
||||
;edx = coentry
|
||||
;[esp+4] = data
|
||||
;return = eax
|
||||
;extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)());
|
||||
;ecx = heapsize
|
||||
;edx = coentry
|
||||
;return = eax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
@@ -101,7 +100,7 @@ co_create:
|
||||
and ecx,-16 ;force 16-byte alignment of stack heap
|
||||
|
||||
;store thread entry point + registers, so that first call to co_switch will execute coentry
|
||||
mov dword[ecx-4],co_entrypoint ;entry point
|
||||
mov dword[ecx-4],edx ;entry point
|
||||
mov dword[ecx-8],0 ;ebp
|
||||
mov dword[ecx-12],0 ;esi
|
||||
mov dword[ecx-16],0 ;edi
|
||||
@@ -109,11 +108,8 @@ co_create:
|
||||
sub ecx,20
|
||||
|
||||
;initialize context memory heap and return
|
||||
mov [eax],ecx ;cothread_t[ 0- 3] = stack heap pointer (esp)
|
||||
mov [eax+4],edx ;cothread_t[ 4- 7] = coentry
|
||||
mov ecx,[esp+4]
|
||||
mov [eax+8],ecx ;cothread_t[ 8-11] = data
|
||||
ret 4 ;return allocated memory block as thread handle
|
||||
mov [eax],ecx ;*cothread_t = stack heap pointer (esp)
|
||||
ret ;return allocated memory block as thread handle
|
||||
|
||||
;*****
|
||||
;extern "C" void fastcall co_delete(cothread_t cothread);
|
||||
@@ -150,18 +146,3 @@ co_switch:
|
||||
pop ebp
|
||||
|
||||
ret
|
||||
|
||||
;*****
|
||||
;void fastcall co_entrypoint();
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_entrypoint:
|
||||
mov ebp,esp
|
||||
.loop
|
||||
mov eax,[co_active_context]
|
||||
mov ecx,[eax+8] ;fastcall
|
||||
push ecx ;stdcall
|
||||
call [eax+4]
|
||||
mov esp,ebp ;cdecl
|
||||
jmp .loop
|
||||
|
@@ -1,16 +1,26 @@
|
||||
/*
|
||||
libco_x86 : version 0.10 ~byuu (2007-04-18)
|
||||
libco_x86 : version 0.10 ~byuu (2007-09-08)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBCO_H
|
||||
#define LIBCO_H
|
||||
|
||||
#define cocall fastcall
|
||||
typedef void (*cothread_t);
|
||||
#if !defined(fastcall)
|
||||
#if defined(_MSC_VER)
|
||||
#define fastcall __fastcall
|
||||
#elif defined(__GNUC__)
|
||||
#define fastcall __attribute__((fastcall))
|
||||
#else
|
||||
#error "fastcall undefined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern "C" cothread_t cocall co_active();
|
||||
extern "C" cothread_t cocall co_create(unsigned int heapsize, void (cocall *coentry)(void *data), void *data);
|
||||
extern "C" void cocall co_delete(cothread_t cothread);
|
||||
extern "C" void cocall co_switch(cothread_t cothread);
|
||||
typedef void *cothread_t;
|
||||
|
||||
extern "C" cothread_t fastcall co_active();
|
||||
extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)());
|
||||
extern "C" void fastcall co_delete(cothread_t cothread);
|
||||
extern "C" void fastcall co_switch(cothread_t cothread);
|
||||
|
||||
#endif
|
||||
|
@@ -1,12 +1,12 @@
|
||||
;*****
|
||||
;libco_x86_64 : version 0.10 ~byuu (2007-04-18)
|
||||
;libco_x86_64 : version 0.10 ~byuu (2007-09-08)
|
||||
;cross-platform x86-64 implementation of libco
|
||||
;special thanks to Aaron Giles and Joel Yliluoma for various optimizations
|
||||
;
|
||||
;[ABI compatibility]
|
||||
;- SystemV ( http://refspecs.freestandards.org/elf/x86_64-SysV-psABI.pdf )
|
||||
;- gcc; linux-x86-64
|
||||
;- gcc; freebsd-x86-64
|
||||
;- gcc; linux; x86-64
|
||||
;- gcc; freebsd; x86-64
|
||||
;
|
||||
;[nonvolatile registers]
|
||||
;- rsp, rbp, rbx, r12, r13, r14, r15
|
||||
@@ -50,10 +50,9 @@ co_active:
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)(void *data), void *data);
|
||||
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
|
||||
;rdi = heapsize
|
||||
;rsi = coentry
|
||||
;rdx = data
|
||||
;return = rax
|
||||
;*****
|
||||
|
||||
@@ -63,11 +62,9 @@ co_create:
|
||||
add rdi,512 ;allocate extra memory for contextual info
|
||||
push rdi
|
||||
push rsi
|
||||
push rdx
|
||||
|
||||
call malloc ;rax = malloc(rdi)
|
||||
|
||||
pop rdx
|
||||
pop rsi
|
||||
pop rdi
|
||||
|
||||
@@ -75,7 +72,7 @@ co_create:
|
||||
and rdi,-16 ;force 16-byte alignment of stack heap
|
||||
|
||||
;store thread entry point + registers, so that first call to co_switch will execute coentry
|
||||
mov qword[rdi-8],co_entrypoint ;entry point
|
||||
mov qword[rdi-8],rsi ;entry point
|
||||
mov qword[rdi-16],0 ;r15
|
||||
mov qword[rdi-24],0 ;r14
|
||||
mov qword[rdi-32],0 ;r13
|
||||
@@ -85,9 +82,7 @@ co_create:
|
||||
sub rdi,56
|
||||
|
||||
;initialize context memory heap and return
|
||||
mov [rax],rdi ;cothread_t[ 0- 7] = stack heap pointer (rsp)
|
||||
mov [rax+8],rsi ;cothread_t[ 8-15] = coentry
|
||||
mov [rax+16],rdx ;cothread_t[16-23] = data
|
||||
mov [rax],rdi ;*cothread_t = stack heap pointer (rsp)
|
||||
ret ;return allocated memory block as thread handle
|
||||
|
||||
;*****
|
||||
@@ -126,14 +121,3 @@ co_switch:
|
||||
pop rbp
|
||||
|
||||
ret
|
||||
|
||||
;*****
|
||||
;void co_entrypoint();
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_entrypoint:
|
||||
mov rax,[co_active_context wrt rip]
|
||||
mov rdi,[rax+16]
|
||||
call [rax+8]
|
||||
jmp co_entrypoint
|
||||
|
@@ -1,15 +1,15 @@
|
||||
/*
|
||||
libco_x86_64 : version 0.10 ~byuu (2007-04-18)
|
||||
libco_x86_64 : version 0.10 ~byuu (2007-09-08)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBCO_H
|
||||
#define LIBCO_H
|
||||
|
||||
#define cocall
|
||||
typedef void (*cothread_t);
|
||||
typedef void *cothread_t;
|
||||
|
||||
extern "C" cothread_t co_active();
|
||||
extern "C" cothread_t co_create(unsigned int heapsize, void (cocall *coentry)(void *data), void *data);
|
||||
extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
|
||||
extern "C" void co_delete(cothread_t cothread);
|
||||
extern "C" void co_switch(cothread_t cothread);
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
libconfig : version 0.14 ~byuu (2007-05-27)
|
||||
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; }
|
||||
@@ -72,7 +72,7 @@ enum Format {
|
||||
template<typename T> bool operator<=(T x) { return (T(data) <= x); }
|
||||
template<typename T> bool operator< (T x) { return (T(data) < x); }
|
||||
|
||||
IntegerSetting(Config *parent, char *r_name, char *r_desc, uint r_format, uint r_data) {
|
||||
IntegerSetting(Config *parent, const char *r_name, const char *r_desc, uint r_format, uint r_data) {
|
||||
type = Setting::Integer;
|
||||
name = strdup(r_name);
|
||||
desc = strdup(r_desc);
|
||||
@@ -103,7 +103,7 @@ string data;
|
||||
bool operator==(const char *x) { return !strcmp(data, x); }
|
||||
bool operator!=(const char *x) { return strcmp(data, x); }
|
||||
|
||||
StringSetting(Config *parent, char *r_name, char *r_desc, char *r_data) {
|
||||
StringSetting(Config *parent, const char *r_name, const char *r_desc, const char *r_data) {
|
||||
type = Setting::String;
|
||||
name = strdup(r_name);
|
||||
desc = strdup(r_desc);
|
||||
|
@@ -1,455 +0,0 @@
|
||||
/*
|
||||
libfile : version 0.07 ~byuu (2007-03-01)
|
||||
*/
|
||||
|
||||
#ifndef __LIBFILE
|
||||
#define __LIBFILE
|
||||
|
||||
//FreeBSD fix: do not use defines for libc functions
|
||||
#undef feof
|
||||
#undef ferror
|
||||
|
||||
/*****
|
||||
* file object
|
||||
*****/
|
||||
|
||||
class file {
|
||||
public:
|
||||
enum { mode_read, mode_write, mode_readwrite, mode_writeread };
|
||||
enum { seek_start, seek_end, seek_back, seek_forward };
|
||||
virtual void read(uint8 *data, uint length) = 0;
|
||||
virtual uint8 read() = 0;
|
||||
|
||||
virtual void write(uint8 *data, uint length) = 0;
|
||||
virtual void write(uint8 data) = 0;
|
||||
|
||||
virtual uint32 crc32();
|
||||
|
||||
virtual void seek(uint offset, uint mode = seek_start) = 0;
|
||||
virtual void resize(uint size) = 0;
|
||||
virtual uint offset() = 0;
|
||||
virtual uint size() = 0;
|
||||
virtual bool eof() = 0;
|
||||
|
||||
virtual bool open(const char *filename, uint mode) = 0;
|
||||
virtual bool open() = 0;
|
||||
virtual bool flush() = 0;
|
||||
virtual bool close() = 0;
|
||||
};
|
||||
|
||||
inline uint32 file::crc32() {
|
||||
uint pos = offset(), i = size();
|
||||
seek(0);
|
||||
uint32 crc32 = 0xffffffff;
|
||||
while(i--) {
|
||||
crc32 = crc32_adjust(crc32, read());
|
||||
}
|
||||
seek(pos);
|
||||
return ~crc32;
|
||||
}
|
||||
|
||||
/*****
|
||||
* c++ wrappers
|
||||
*****/
|
||||
|
||||
inline void fread(file &s, uint8 *data, uint length) { s.read(data, length); }
|
||||
inline uint8 fread(file &s) { return s.read(); }
|
||||
inline uint8 fgetc(file &s) { return s.read(); }
|
||||
inline uint fgetb(file &s) { return s.read(); }
|
||||
|
||||
inline void fwrite(file &s, uint8 *data, uint length) { s.write(data, length); }
|
||||
inline void fwrite(file &s, uint8 data) { s.write(data); }
|
||||
inline void fputc(uint8 data, file &s) { s.write(data); }
|
||||
inline void fputb(file &s, uint8 data) { s.write(data); }
|
||||
|
||||
inline uint32 fcrc32(file &s) { return s.crc32(); }
|
||||
|
||||
inline void fseek(file &s, uint offset, uint mode = file::seek_start) { s.seek(offset, mode); }
|
||||
inline void fresize(file &s, uint size) { s.resize(size); }
|
||||
inline uint ftell(file &s) { return s.offset(); }
|
||||
inline uint fsize(file &s) { return s.size(); }
|
||||
inline bool feof(file &s) { return s.eof(); }
|
||||
|
||||
inline bool fopen(file &s, const char *filename, uint mode) { return s.open(filename, mode); }
|
||||
inline bool fopen(file &s) { return s.open(); }
|
||||
inline bool fflush(file &s) { return s.flush(); }
|
||||
inline bool fclose(file &s) { return s.close(); }
|
||||
|
||||
|
||||
/*****
|
||||
* endian wrappers
|
||||
*****/
|
||||
|
||||
inline uint8 fgetlb(file &s) { return fgetc(s); }
|
||||
inline uint8 fgetmb(file &s) { return fgetc(s); }
|
||||
|
||||
inline uint16 fgetlw(file &s) {
|
||||
return (fgetc(s)) | (fgetc(s) << 8);
|
||||
}
|
||||
|
||||
inline uint16 fgetmw(file &s) {
|
||||
return (fgetc(s) << 8) | (fgetc(s) << 8);
|
||||
}
|
||||
|
||||
inline uint32 fgetld(file &s) {
|
||||
return (fgetc(s)) | (fgetc(s) << 8) | (fgetc(s) << 16) | (fgetc(s) << 24);
|
||||
}
|
||||
|
||||
inline uint32 fgetmd(file &s) {
|
||||
return (fgetc(s) << 24) | (fgetc(s) << 16) | (fgetc(s) << 8) | (fgetc(s));
|
||||
}
|
||||
|
||||
inline uint64 fgetlq(file &s) {
|
||||
return ((uint64)fgetc(s) << 0) | ((uint64)fgetc(s) << 8) |
|
||||
((uint64)fgetc(s) << 16) | ((uint64)fgetc(s) << 24) |
|
||||
((uint64)fgetc(s) << 32) | ((uint64)fgetc(s) << 40) |
|
||||
((uint64)fgetc(s) << 48) | ((uint64)fgetc(s) << 56);
|
||||
}
|
||||
|
||||
inline uint64 fgetmq(file &s) {
|
||||
return ((uint64)fgetc(s) << 56) | ((uint64)fgetc(s) << 48) |
|
||||
((uint64)fgetc(s) << 40) | ((uint64)fgetc(s) << 32) |
|
||||
((uint64)fgetc(s) << 24) | ((uint64)fgetc(s) << 16) |
|
||||
((uint64)fgetc(s) << 8) | ((uint64)fgetc(s) << 0);
|
||||
}
|
||||
|
||||
inline void fputlb(file &s, uint8 data) { fputc(data, s); }
|
||||
inline void fputmb(file &s, uint8 data) { fputc(data, s); }
|
||||
|
||||
inline void fputlw(file &s, uint16 data) {
|
||||
fputc(data >> 0, s);
|
||||
fputc(data >> 8, s);
|
||||
}
|
||||
|
||||
inline void fputmw(file &s, uint16 data) {
|
||||
fputc(data >> 8, s);
|
||||
fputc(data >> 0, s);
|
||||
}
|
||||
|
||||
inline void fputld(file &s, uint32 data) {
|
||||
fputc(data >> 0, s);
|
||||
fputc(data >> 8, s);
|
||||
fputc(data >> 16, s);
|
||||
fputc(data >> 24, s);
|
||||
}
|
||||
|
||||
inline void fputmd(file &s, uint32 data) {
|
||||
fputc(data >> 24, s);
|
||||
fputc(data >> 16, s);
|
||||
fputc(data >> 8, s);
|
||||
fputc(data >> 0, s);
|
||||
}
|
||||
|
||||
inline void fputlq(file &s, uint64 data) {
|
||||
fputc(data >> 0, s);
|
||||
fputc(data >> 8, s);
|
||||
fputc(data >> 16, s);
|
||||
fputc(data >> 24, s);
|
||||
fputc(data >> 32, s);
|
||||
fputc(data >> 40, s);
|
||||
fputc(data >> 48, s);
|
||||
fputc(data >> 56, s);
|
||||
}
|
||||
|
||||
inline void fputmq(file &s, uint64 data) {
|
||||
fputc(data >> 56, s);
|
||||
fputc(data >> 48, s);
|
||||
fputc(data >> 40, s);
|
||||
fputc(data >> 32, s);
|
||||
fputc(data >> 24, s);
|
||||
fputc(data >> 16, s);
|
||||
fputc(data >> 8, s);
|
||||
fputc(data >> 0, s);
|
||||
}
|
||||
|
||||
/*****
|
||||
* ramfile
|
||||
*****/
|
||||
|
||||
class ramfile : public file {
|
||||
private:
|
||||
FILE *fp;
|
||||
array<uint8> filedata;
|
||||
char filename[1024];
|
||||
uint filepos;
|
||||
uint filesize;
|
||||
uint filemode;
|
||||
bool fileopen;
|
||||
bool filevirtual;
|
||||
|
||||
public:
|
||||
void read(uint8 *data, uint length) {
|
||||
if(!fileopen || filemode == mode_write) { return; }
|
||||
|
||||
memcpy(data, filedata.get(filepos + length) + filepos, length);
|
||||
filepos += length;
|
||||
if(filepos > filesize)filepos = filesize;
|
||||
}
|
||||
|
||||
uint8 read() {
|
||||
if(!fileopen || filemode == mode_write) { return 0; }
|
||||
|
||||
if(eof() == true) { return 0xff; }
|
||||
return filedata[filepos++];
|
||||
}
|
||||
|
||||
void write(uint8 *data, uint length) {
|
||||
if(!fileopen || filemode == mode_read) { return; }
|
||||
|
||||
memcpy(filedata.get(filepos + length) + filepos, data, length);
|
||||
filepos += length;
|
||||
if(filepos > filesize)filesize = filepos;
|
||||
}
|
||||
|
||||
void write(uint8 data) {
|
||||
if(!fileopen || filemode == mode_read) { return; }
|
||||
|
||||
filedata[filepos++] = data;
|
||||
if(filepos > filesize)filesize = filepos;
|
||||
}
|
||||
|
||||
void seek(uint offset, uint mode = seek_start) {
|
||||
if(!fileopen) { return; }
|
||||
|
||||
switch(mode) {
|
||||
case seek_start: filepos = offset; break;
|
||||
case seek_end: filepos = filesize + offset; break;
|
||||
case seek_back: filepos -= offset; break;
|
||||
case seek_forward: filepos += offset; break;
|
||||
}
|
||||
|
||||
if(filemode == mode_read) {
|
||||
if(filepos > filesize)filepos = filesize;
|
||||
} else {
|
||||
if(filepos > filesize)filesize = filepos;
|
||||
}
|
||||
}
|
||||
|
||||
void resize(uint size) {
|
||||
filesize = size;
|
||||
if(filepos > filesize)filepos = filesize;
|
||||
}
|
||||
|
||||
uint offset() {
|
||||
if(!fileopen) { return 0; }
|
||||
|
||||
return filepos;
|
||||
}
|
||||
|
||||
uint size() {
|
||||
if(!fileopen) { return 0; }
|
||||
|
||||
return filesize;
|
||||
}
|
||||
|
||||
bool eof() {
|
||||
if(!fileopen) { return true; }
|
||||
|
||||
return (filepos >= filesize);
|
||||
}
|
||||
|
||||
bool open(const char *fn, uint mode) {
|
||||
if(fileopen) { return false; }
|
||||
|
||||
strcpy(filename, fn ? fn : "");
|
||||
filevirtual = (*filename == 0);
|
||||
filemode = mode;
|
||||
switch(filemode) {
|
||||
case mode_read:
|
||||
case mode_readwrite:
|
||||
if(filevirtual == true) {
|
||||
filesize = 0;
|
||||
} else {
|
||||
fp = fopen(filename, "rb");
|
||||
if(!fp) { return false; }
|
||||
filesize = fsize(fp);
|
||||
fread(filedata.get(filesize), 1, filesize, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
filesize = 0;
|
||||
break;
|
||||
}
|
||||
filepos = 0;
|
||||
fileopen = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool open() {
|
||||
return fileopen;
|
||||
}
|
||||
|
||||
bool flush() {
|
||||
if(!fileopen) { return false; }
|
||||
|
||||
switch(filemode) {
|
||||
case mode_readwrite:
|
||||
case mode_write:
|
||||
case mode_writeread:
|
||||
if(filevirtual == false) {
|
||||
fp = fopen(filename, "wb");
|
||||
if(!fp) { return false; }
|
||||
fwrite(filedata.get(filesize), 1, filesize, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool close() {
|
||||
if(!fileopen) { return false; }
|
||||
|
||||
bool result = flush();
|
||||
fileopen = false;
|
||||
filedata.reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
ramfile() {
|
||||
fileopen = false;
|
||||
}
|
||||
|
||||
~ramfile() {
|
||||
if(fileopen) { close(); }
|
||||
}
|
||||
};
|
||||
|
||||
/*****
|
||||
* diskfile
|
||||
*****/
|
||||
|
||||
class diskfile : public file {
|
||||
private:
|
||||
FILE *fp;
|
||||
uint filemode;
|
||||
|
||||
public:
|
||||
void read(uint8 *data, uint length) {
|
||||
if(!fp || filemode == mode_write) { return; }
|
||||
|
||||
fread(data, 1, length, fp);
|
||||
}
|
||||
|
||||
uint8 read() {
|
||||
if(!fp || filemode == mode_write) { return 0; }
|
||||
|
||||
if(eof() == true) { return 0xff; }
|
||||
return fgetc(fp);
|
||||
}
|
||||
|
||||
void write(uint8 *data, uint length) {
|
||||
if(!fp || filemode == mode_read) { return; }
|
||||
|
||||
fwrite(data, 1, length, fp);
|
||||
}
|
||||
|
||||
void write(uint8 data) {
|
||||
if(!fp || filemode == mode_read) { return; }
|
||||
|
||||
fputc(data, fp);
|
||||
}
|
||||
|
||||
void seek(uint offset, uint mode = seek_start) {
|
||||
if(!fp) { return; }
|
||||
|
||||
switch(mode) {
|
||||
default:
|
||||
case seek_start: fseek(fp, offset, SEEK_SET); break;
|
||||
case seek_end: fseek(fp, offset, SEEK_END); break;
|
||||
case seek_back: fseek(fp, offset, SEEK_CUR); break;
|
||||
case seek_forward: fseek(fp, offset, SEEK_CUR); break;
|
||||
}
|
||||
}
|
||||
|
||||
void resize(uint size) {
|
||||
if(!fp) { return; }
|
||||
|
||||
fresize(fp, size);
|
||||
}
|
||||
|
||||
uint offset() {
|
||||
if(!fp) { return 0; }
|
||||
|
||||
return ftell(fp);
|
||||
}
|
||||
|
||||
uint size() {
|
||||
if(!fp) { return 0; }
|
||||
|
||||
uint pos = ftell(fp);
|
||||
fseek(fp, 0, SEEK_END);
|
||||
uint filesize = ftell(fp);
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
return filesize;
|
||||
}
|
||||
|
||||
bool eof() {
|
||||
if(!fp) { return true; }
|
||||
|
||||
if(feof(fp)) {
|
||||
seek(size(), seek_start);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool open(const char *filename, uint mode) {
|
||||
if(fp) { return false; }
|
||||
|
||||
filemode = mode;
|
||||
char m[8];
|
||||
switch(filemode) {
|
||||
default:
|
||||
case mode_read: strcpy(m, "rb"); break;
|
||||
case mode_write: strcpy(m, "wb"); break;
|
||||
case mode_readwrite: strcpy(m, "rb+"); break;
|
||||
case mode_writeread: strcpy(m, "wb+"); break;
|
||||
}
|
||||
fp = fopen(filename, m);
|
||||
if(!fp) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool open() {
|
||||
return (fp != 0);
|
||||
}
|
||||
|
||||
bool flush() {
|
||||
if(!fp) { return false; }
|
||||
|
||||
fflush(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool close() {
|
||||
if(!fp) { return false; }
|
||||
|
||||
fclose(fp);
|
||||
fp = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
diskfile() {
|
||||
fp = 0;
|
||||
}
|
||||
|
||||
~diskfile() {
|
||||
if(fp) { fclose(fp); }
|
||||
}
|
||||
};
|
||||
|
||||
/*****
|
||||
* directory object
|
||||
*****/
|
||||
|
||||
class directory {
|
||||
public:
|
||||
void open(const char *path) {}
|
||||
void close() {}
|
||||
uint read(char *filename, uint maxlength) { return 0; }
|
||||
};
|
||||
|
||||
#endif
|
182
src/lib/libfunction.h
Normal file
182
src/lib/libfunction.h
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
libfunction : version 0.06 ~byuu (2007-10-14)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBFUNCTION_H
|
||||
#define LIBFUNCTION_H
|
||||
|
||||
//prologue
|
||||
|
||||
#define TN typename
|
||||
|
||||
template<typename T> class function;
|
||||
|
||||
//parameters = 0
|
||||
|
||||
#define cat(n) n
|
||||
#define TL typename R
|
||||
#define PL
|
||||
#define CL
|
||||
|
||||
#include "libfunction.h"
|
||||
|
||||
//parameters = 1
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1
|
||||
#define PL P1 p1
|
||||
#define CL p1
|
||||
|
||||
#include "libfunction.h"
|
||||
|
||||
//parameters = 2
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2
|
||||
#define PL P1 p1, P2 p2
|
||||
#define CL p1, p2
|
||||
|
||||
#include "libfunction.h"
|
||||
|
||||
//parameters = 3
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3
|
||||
#define PL P1 p1, P2 p2, P3 p3
|
||||
#define CL p1, p2, p3
|
||||
|
||||
#include "libfunction.h"
|
||||
|
||||
//parameters = 4
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4
|
||||
#define CL p1, p2, p3, p4
|
||||
|
||||
#include "libfunction.h"
|
||||
|
||||
//parameters = 5
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5
|
||||
#define CL p1, p2, p3, p4, p5
|
||||
|
||||
#include "libfunction.h"
|
||||
|
||||
//parameters = 6
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6
|
||||
#define CL p1, p2, p3, p4, p5, p6
|
||||
|
||||
#include "libfunction.h"
|
||||
|
||||
//parameters = 7
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7
|
||||
#define CL p1, p2, p3, p4, p5, p6, p7
|
||||
|
||||
#include "libfunction.h"
|
||||
|
||||
//parameters = 8
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7, TN P8
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8
|
||||
#define CL p1, p2, p3, p4, p5, p6, p7, p8
|
||||
|
||||
#include "libfunction.h"
|
||||
|
||||
//epilogue
|
||||
|
||||
#undef TN
|
||||
|
||||
#else //defined(LIBFUNCTION_H)
|
||||
|
||||
//function implementation template class
|
||||
|
||||
template<TL>
|
||||
class function<R (PL)> {
|
||||
private:
|
||||
struct base1 { virtual void func1(PL) {} };
|
||||
struct base2 { virtual void func2(PL) {} };
|
||||
struct derived : base1, virtual base2 {};
|
||||
|
||||
struct data_t {
|
||||
R (*fn_call)(const data_t& cat(PL));
|
||||
union {
|
||||
R (*fn_global)(PL);
|
||||
struct {
|
||||
R (derived::*fn_member)(PL);
|
||||
void *object;
|
||||
};
|
||||
};
|
||||
} data;
|
||||
|
||||
static R fn_call_global(const data_t &d cat(PL)) {
|
||||
return d.fn_global(CL);
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
static R fn_call_member(const data_t &d cat(PL)) {
|
||||
return (((C*)d.object)->*((R (C::*&)(PL))d.fn_member))(CL);
|
||||
}
|
||||
|
||||
public:
|
||||
R operator()(PL) const { return data.fn_call(data cat(CL)); }
|
||||
operator bool() const { return data.fn_call; }
|
||||
|
||||
function() { data.fn_call = 0; }
|
||||
|
||||
function(R (*fn)(PL)) {
|
||||
data.fn_call = &fn_call_global;
|
||||
data.fn_global = fn;
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
function(R (C::*fn)(PL), C *obj) {
|
||||
data.fn_call = &fn_call_member<C>;
|
||||
(R (C::*&)(PL))data.fn_member = fn;
|
||||
assert(sizeof data.fn_member >= sizeof fn);
|
||||
data.object = obj;
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
function(R (C::*fn)(PL) const, C *obj) {
|
||||
data.fn_call = &fn_call_member<C>;
|
||||
(R (C::*&)(PL))data.fn_member = (R (C::*&)(PL))fn;
|
||||
assert(sizeof data.fn_member >= sizeof fn);
|
||||
data.object = obj;
|
||||
}
|
||||
|
||||
function &operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
|
||||
function(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); }
|
||||
};
|
||||
|
||||
template<TL>
|
||||
function<R (PL)> bind(R (*fn)(PL)) {
|
||||
return function<R (PL)>(fn);
|
||||
}
|
||||
|
||||
template<typename C, TL>
|
||||
function<R (PL)> bind(R (C::*fn)(PL), C *obj) {
|
||||
return function<R (PL)>(fn, obj);
|
||||
}
|
||||
|
||||
template<typename C, TL>
|
||||
function<R (PL)> bind(R (C::*fn)(PL) const, C *obj) {
|
||||
return function<R (PL)>(fn, obj);
|
||||
}
|
||||
|
||||
#undef cat
|
||||
#undef TL
|
||||
#undef PL
|
||||
#undef CL
|
||||
|
||||
#endif
|
@@ -1,341 +0,0 @@
|
||||
/*
|
||||
libfunctor : version 0.01 ~byuu (2007-01-04)
|
||||
*/
|
||||
|
||||
#ifndef __LIBFUNCTOR
|
||||
#define __LIBFUNCTOR
|
||||
|
||||
template<typename T> struct functor;
|
||||
template<typename T> struct functor_t;
|
||||
|
||||
/*****
|
||||
* macros
|
||||
*****/
|
||||
|
||||
#define base_functor \
|
||||
functor *f; \
|
||||
virtual operator bool() const { return f && (bool)(*f); } \
|
||||
virtual functor *copy() const { return f->copy(); } \
|
||||
functor &operator=(const functor *source) { if(f) { delete f; } f = (source->f) ? source->copy() : 0; return *this; } \
|
||||
functor &operator=(const functor &source) { if(f) { delete f; } f = (source.f) ? source.copy() : 0; return *this; } \
|
||||
functor(const functor &source) { /* ........................ */ f = (source.f) ? source.copy() : 0; } \
|
||||
functor() : f(0) {} \
|
||||
~functor() { if(f && f != this) { delete f; } }
|
||||
|
||||
#define base_global_functor \
|
||||
operator bool() const { return proc; } \
|
||||
functor_t *copy() const { return new functor_t(*this); } \
|
||||
functor_t(const functor_t &source) { proc = source.proc; }
|
||||
|
||||
#define base_member_functor \
|
||||
operator bool() const { return obj && proc; } \
|
||||
functor_t *copy() const { return new functor_t(*this); } \
|
||||
functor_t(const functor_t &source) { obj = source.obj; proc = source.proc; } \
|
||||
C *obj;
|
||||
|
||||
/*****
|
||||
* parameters = 0
|
||||
*****/
|
||||
|
||||
template<typename R>
|
||||
struct functor<R (*)()> { base_functor
|
||||
virtual R operator()() const { return (*f)(); }
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
struct functor_t<R (*)()> : public functor<R (*)()> { base_global_functor
|
||||
R (*proc)();
|
||||
R operator()() const { return (*proc)(); }
|
||||
functor_t(R (*_proc)()) : proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename C, typename R>
|
||||
struct functor_t<R (C::*)()> : public functor<R (*)()> { base_member_functor
|
||||
R (C::*proc)();
|
||||
R operator()() const { return (obj->*proc)(); }
|
||||
functor_t(C *_obj, R (C::*_proc)()) : obj(_obj), proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
functor_t<R (*)()> make_functor(R (*proc)()) {
|
||||
return functor_t<R (*)()>(proc);
|
||||
}
|
||||
|
||||
template<typename C, typename R>
|
||||
functor_t<R (C::*)()> make_functor(C *obj, R (C::*proc)()) {
|
||||
return functor_t<R (C::*)()>(obj, proc);
|
||||
}
|
||||
|
||||
/*****
|
||||
* parameters = 1
|
||||
*****/
|
||||
|
||||
template<typename R, typename P1>
|
||||
struct functor<R (*)(P1)> { base_functor
|
||||
virtual R operator()(P1 p1) const { return (*f)(p1); }
|
||||
};
|
||||
|
||||
template<typename R, typename P1>
|
||||
struct functor_t<R (*)(P1)> : public functor<R (*)(P1)> { base_global_functor
|
||||
R (*proc)(P1);
|
||||
R operator()(P1 p1) const { return (*proc)(p1); }
|
||||
functor_t(R (*_proc)(P1)) : proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename C, typename R, typename P1>
|
||||
struct functor_t<R (C::*)(P1)> : public functor<R (*)(P1)> { base_member_functor
|
||||
R (C::*proc)(P1);
|
||||
R operator()(P1 p1) const { return (obj->*proc)(p1); }
|
||||
functor_t(C *_obj, R (C::*_proc)(P1)) : obj(_obj), proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename R, typename P1>
|
||||
functor_t<R (*)(P1)> make_functor(R (*proc)(P1)) {
|
||||
return functor_t<R (*)(P1)>(proc);
|
||||
}
|
||||
|
||||
template<typename C, typename R, typename P1>
|
||||
functor_t<R (C::*)(P1)> make_functor(C *obj, R (C::*proc)(P1)) {
|
||||
return functor_t<R (C::*)(P1)>(obj, proc);
|
||||
}
|
||||
|
||||
/*****
|
||||
* parameters = 2
|
||||
*****/
|
||||
|
||||
template<typename R, typename P1, typename P2>
|
||||
struct functor<R (*)(P1, P2)> { base_functor
|
||||
virtual R operator()(P1 p1, P2 p2) const { return (*f)(p1, p2); }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2>
|
||||
struct functor_t<R (*)(P1, P2)> : public functor<R (*)(P1, P2)> { base_global_functor
|
||||
R (*proc)(P1, P2);
|
||||
R operator()(P1 p1, P2 p2) const { return (*proc)(p1, p2); }
|
||||
functor_t(R (*_proc)(P1, P2)) : proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2>
|
||||
struct functor_t<R (C::*)(P1, P2)> : public functor<R (*)(P1, P2)> { base_member_functor
|
||||
R (C::*proc)(P1, P2);
|
||||
R operator()(P1 p1, P2 p2) const { return (obj->*proc)(p1, p2); }
|
||||
functor_t(C *_obj, R (C::*_proc)(P1, P2)) : obj(_obj), proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2>
|
||||
functor_t<R (*)(P1, P2)> make_functor(R (*proc)(P1, P2)) {
|
||||
return functor_t<R (*)(P1, P2)>(proc);
|
||||
}
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2>
|
||||
functor_t<R (C::*)(P1, P2)> make_functor(C *obj, R (C::*proc)(P1, P2)) {
|
||||
return functor_t<R (C::*)(P1, P2)>(obj, proc);
|
||||
}
|
||||
|
||||
/*****
|
||||
* parameters = 3
|
||||
*****/
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3>
|
||||
struct functor<R (*)(P1, P2, P3)> { base_functor
|
||||
virtual R operator()(P1 p1, P2 p2, P3 p3) const { return (*f)(p1, p2, p3); }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3>
|
||||
struct functor_t<R (*)(P1, P2, P3)> : public functor<R (*)(P1, P2, P3)> { base_global_functor
|
||||
R (*proc)(P1, P2, P3);
|
||||
R operator()(P1 p1, P2 p2, P3 p3) const { return (*proc)(p1, p2, p3); }
|
||||
functor_t(R (*_proc)(P1, P2, P3)) : proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3>
|
||||
struct functor_t<R (C::*)(P1, P2, P3)> : public functor<R (*)(P1, P2, P3)> { base_member_functor
|
||||
R (C::*proc)(P1, P2, P3);
|
||||
R operator()(P1 p1, P2 p2, P3 p3) const { return (obj->*proc)(p1, p2, p3); }
|
||||
functor_t(C *_obj, R (C::*_proc)(P1, P2, P3)) : obj(_obj), proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3>
|
||||
functor_t<R (*)(P1, P2, P3)> make_functor(R (*proc)(P1, P2, P3)) {
|
||||
return functor_t<R (*)(P1, P2, P3)>(proc);
|
||||
}
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3>
|
||||
functor_t<R (C::*)(P1, P2, P3)> make_functor(C *obj, R (C::*proc)(P1, P2, P3)) {
|
||||
return functor_t<R (C::*)(P1, P2, P3)>(obj, proc);
|
||||
}
|
||||
|
||||
/*****
|
||||
* parameters = 4
|
||||
*****/
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4>
|
||||
struct functor<R (*)(P1, P2, P3, P4)> { base_functor
|
||||
virtual R operator()(P1 p1, P2 p2, P3 p3, P4 p4) const { return (*f)(p1, p2, p3, p4); }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4>
|
||||
struct functor_t<R (*)(P1, P2, P3, P4)> : public functor<R (*)(P1, P2, P3, P4)> { base_global_functor
|
||||
R (*proc)(P1, P2, P3, P4);
|
||||
R operator()(P1 p1, P2 p2, P3 p3, P4 p4) const { return (*proc)(p1, p2, p3, p4); }
|
||||
functor_t(R (*_proc)(P1, P2, P3, P4)) : proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3, typename P4>
|
||||
struct functor_t<R (C::*)(P1, P2, P3, P4)> : public functor<R (*)(P1, P2, P3, P4)> { base_member_functor
|
||||
R (C::*proc)(P1, P2, P3, P4);
|
||||
R operator()(P1 p1, P2 p2, P3 p3, P4 p4) const { return (obj->*proc)(p1, p2, p3, p4); }
|
||||
functor_t(C *_obj, R (C::*_proc)(P1, P2, P3, P4)) : obj(_obj), proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4>
|
||||
functor_t<R (*)(P1, P2, P3, P4)> make_functor(R (*proc)(P1, P2, P3, P4)) {
|
||||
return functor_t<R (*)(P1, P2, P3, P4)>(proc);
|
||||
}
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3, typename P4>
|
||||
functor_t<R (C::*)(P1, P2, P3, P4)> make_functor(C *obj, R (C::*proc)(P1, P2, P3, P4)) {
|
||||
return functor_t<R (C::*)(P1, P2, P3, P4)>(obj, proc);
|
||||
}
|
||||
|
||||
/*****
|
||||
* parameters = 5
|
||||
*****/
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||
struct functor<R (*)(P1, P2, P3, P4, P5)> { base_functor
|
||||
virtual R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const { return (*f)(p1, p2, p3, p4, p5); }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||
struct functor_t<R (*)(P1, P2, P3, P4, P5)> : public functor<R (*)(P1, P2, P3, P4, P5)> { base_global_functor
|
||||
R (*proc)(P1, P2, P3, P4, P5);
|
||||
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const { return (*proc)(p1, p2, p3, p4, p5); }
|
||||
functor_t(R (*_proc)(P1, P2, P3, P4, P5)) : proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||
struct functor_t<R (C::*)(P1, P2, P3, P4, P5)> : public functor<R (*)(P1, P2, P3, P4, P5)> { base_member_functor
|
||||
R (C::*proc)(P1, P2, P3, P4, P5);
|
||||
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const { return (obj->*proc)(p1, p2, p3, p4, p5); }
|
||||
functor_t(C *_obj, R (C::*_proc)(P1, P2, P3, P4, P5)) : obj(_obj), proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||
functor_t<R (*)(P1, P2, P3, P4, P5)> make_functor(R (*proc)(P1, P2, P3, P4, P5)) {
|
||||
return functor_t<R (*)(P1, P2, P3, P4, P5)>(proc);
|
||||
}
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||
functor_t<R (C::*)(P1, P2, P3, P4, P5)> make_functor(C *obj, R (C::*proc)(P1, P2, P3, P4, P5)) {
|
||||
return functor_t<R (C::*)(P1, P2, P3, P4, P5)>(obj, proc);
|
||||
}
|
||||
|
||||
/*****
|
||||
* parameters = 6
|
||||
*****/
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||
struct functor<R (*)(P1, P2, P3, P4, P5, P6)> { base_functor
|
||||
virtual R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const { return (*f)(p1, p2, p3, p4, p5, p6); }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||
struct functor_t<R (*)(P1, P2, P3, P4, P5, P6)> : public functor<R (*)(P1, P2, P3, P4, P5, P6)> { base_global_functor
|
||||
R (*proc)(P1, P2, P3, P4, P5, P6);
|
||||
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const { return (*proc)(p1, p2, p3, p4, p5, p6); }
|
||||
functor_t(R (*_proc)(P1, P2, P3, P4, P5, P6)) : proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||
struct functor_t<R (C::*)(P1, P2, P3, P4, P5, P6)> : public functor<R (*)(P1, P2, P3, P4, P5, P6)> { base_member_functor
|
||||
R (C::*proc)(P1, P2, P3, P4, P5, P6);
|
||||
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const { return (obj->*proc)(p1, p2, p3, p4, p5, p6); }
|
||||
functor_t(C *_obj, R (C::*_proc)(P1, P2, P3, P4, P5, P6)) : obj(_obj), proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||
functor_t<R (*)(P1, P2, P3, P4, P5, P6)> make_functor(R (*proc)(P1, P2, P3, P4, P5, P6)) {
|
||||
return functor_t<R (*)(P1, P2, P3, P4, P5, P6)>(proc);
|
||||
}
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||
functor_t<R (C::*)(P1, P2, P3, P4, P5, P6)> make_functor(C *obj, R (C::*proc)(P1, P2, P3, P4, P5, P6)) {
|
||||
return functor_t<R (C::*)(P1, P2, P3, P4, P5, P6)>(obj, proc);
|
||||
}
|
||||
|
||||
/*****
|
||||
* parameters = 7
|
||||
*****/
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||
struct functor<R (*)(P1, P2, P3, P4, P5, P6, P7)> { base_functor
|
||||
virtual R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const { return (*f)(p1, p2, p3, p4, p5, p6, p7); }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||
struct functor_t<R (*)(P1, P2, P3, P4, P5, P6, P7)> : public functor<R (*)(P1, P2, P3, P4, P5, P6, P7)> { base_global_functor
|
||||
R (*proc)(P1, P2, P3, P4, P5, P6, P7);
|
||||
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const { return (*proc)(p1, p2, p3, p4, p5, p6, p7); }
|
||||
functor_t(R (*_proc)(P1, P2, P3, P4, P5, P6, P7)) : proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||
struct functor_t<R (C::*)(P1, P2, P3, P4, P5, P6, P7)> : public functor<R (*)(P1, P2, P3, P4, P5, P6, P7)> { base_member_functor
|
||||
R (C::*proc)(P1, P2, P3, P4, P5, P6, P7);
|
||||
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const { return (obj->*proc)(p1, p2, p3, p4, p5, p6, p7); }
|
||||
functor_t(C *_obj, R (C::*_proc)(P1, P2, P3, P4, P5, P6, P7)) : obj(_obj), proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||
functor_t<R (*)(P1, P2, P3, P4, P5, P6, P7)> make_functor(R (*proc)(P1, P2, P3, P4, P5, P6, P7)) {
|
||||
return functor_t<R (*)(P1, P2, P3, P4, P5, P6, P7)>(proc);
|
||||
}
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||
functor_t<R (C::*)(P1, P2, P3, P4, P5, P6, P7)> make_functor(C *obj, R (C::*proc)(P1, P2, P3, P4, P5, P6, P7)) {
|
||||
return functor_t<R (C::*)(P1, P2, P3, P4, P5, P6, P7)>(obj, proc);
|
||||
}
|
||||
|
||||
/*****
|
||||
* parameters = 8
|
||||
*****/
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||
struct functor<R (*)(P1, P2, P3, P4, P5, P6, P7, P8)> { base_functor
|
||||
virtual R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const { return (*f)(p1, p2, p3, p4, p5, p6, p7, p8); }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||
struct functor_t<R (*)(P1, P2, P3, P4, P5, P6, P7, P8)> : public functor<R (*)(P1, P2, P3, P4, P5, P6, P7, P8)> { base_global_functor
|
||||
R (*proc)(P1, P2, P3, P4, P5, P6, P7, P8);
|
||||
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const { return (*proc)(p1, p2, p3, p4, p5, p6, p7, p8); }
|
||||
functor_t(R (*_proc)(P1, P2, P3, P4, P5, P6, P7, P8)) : proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||
struct functor_t<R (C::*)(P1, P2, P3, P4, P5, P6, P7, P8)> : public functor<R (*)(P1, P2, P3, P4, P5, P6, P7, P8)> { base_member_functor
|
||||
R (C::*proc)(P1, P2, P3, P4, P5, P6, P7, P8);
|
||||
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const { return (obj->*proc)(p1, p2, p3, p4, p5, p6, p7, p8); }
|
||||
functor_t(C *_obj, R (C::*_proc)(P1, P2, P3, P4, P5, P6, P7, P8)) : obj(_obj), proc(_proc) { this->f = this; }
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||
functor_t<R (*)(P1, P2, P3, P4, P5, P6, P7, P8)> make_functor(R (*proc)(P1, P2, P3, P4, P5, P6, P7, P8)) {
|
||||
return functor_t<R (*)(P1, P2, P3, P4, P5, P6, P7, P8)>(proc);
|
||||
}
|
||||
|
||||
template<typename C, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||
functor_t<R (C::*)(P1, P2, P3, P4, P5, P6, P7, P8)> make_functor(C *obj, R (C::*proc)(P1, P2, P3, P4, P5, P6, P7, P8)) {
|
||||
return functor_t<R (C::*)(P1, P2, P3, P4, P5, P6, P7, P8)>(obj, proc);
|
||||
}
|
||||
|
||||
/*****
|
||||
* epilogue
|
||||
*****/
|
||||
|
||||
#undef base_functor
|
||||
#undef base_global_functor
|
||||
#undef base_member_functor
|
||||
|
||||
#endif
|
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
libinterp : version 0.01 ~byuu (2007-02-03)
|
||||
*/
|
||||
|
||||
#ifndef __LIBINTERP
|
||||
#define __LIBINTERP
|
||||
|
||||
static inline
|
||||
double interpolate_point(
|
||||
double mu,
|
||||
double y0, double y1
|
||||
) {
|
||||
return mu < 0.5 ? y0 : y1;
|
||||
}
|
||||
|
||||
static inline
|
||||
double interpolate_linear(
|
||||
double mu,
|
||||
double y0, double y1
|
||||
) {
|
||||
return y0 + mu * (y1 - y0);
|
||||
}
|
||||
|
||||
static inline
|
||||
double interpolate_cosine(
|
||||
double mu,
|
||||
double y0, double y1
|
||||
) {
|
||||
mu = (1.0 - cos(mu * 3.14159265)) / 2.0;
|
||||
return y0 + mu * (y1 - y0);
|
||||
}
|
||||
|
||||
static inline
|
||||
double interpolate_cubic(
|
||||
double mu,
|
||||
double y0, double y1, double y2, double y3
|
||||
) {
|
||||
double a0 = y3 - y2 - y0 + y1;
|
||||
double a1 = y0 - y1 - a0;
|
||||
double a2 = y2 - y0;
|
||||
double a3 = y1;
|
||||
return a0 * mu * mu * mu +
|
||||
a1 * mu * mu +
|
||||
a2 * mu +
|
||||
a3;
|
||||
}
|
||||
|
||||
/*
|
||||
tension: (0 = normal, -1 = low, +1 = high)
|
||||
bias: (0 = even, -n = left, +n = right)
|
||||
*/
|
||||
static inline
|
||||
double interpolate_hermite(
|
||||
double mu, double tension, double bias,
|
||||
double y0, double y1, double y2, double y3
|
||||
) {
|
||||
double mu0 = ( (y1 - y0) * (1.0 + bias) * (1.0 - tension) / 2.0 ) +
|
||||
( (y2 - y1) * (1.0 - bias) * (1.0 - tension) / 2.0 );
|
||||
double mu1 = ( (y2 - y1) * (1.0 + bias) * (1.0 - tension) / 2.0 ) +
|
||||
( (y3 - y2) * (1.0 - bias) * (1.0 - tension) / 2.0 );
|
||||
double mu2 = mu * mu;
|
||||
double mu3 = mu * mu * mu;
|
||||
double a0 = 2.0 * mu3 - 3.0 * mu2 + 1.0;
|
||||
double a1 = mu3 - 2.0 * mu2 + mu;
|
||||
double a2 = mu3 - mu2;
|
||||
double a3 = -2.0 * mu3 + 3.0 * mu2;
|
||||
return a0 * y1 +
|
||||
a1 * mu0 +
|
||||
a2 * mu1 +
|
||||
a3 * y2;
|
||||
}
|
||||
|
||||
#endif
|
@@ -7,6 +7,28 @@
|
||||
|
||||
namespace keymap {
|
||||
|
||||
//TODO: use lookup table for find() functions
|
||||
static char keytable[][64] = {
|
||||
"none",
|
||||
"esc",
|
||||
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12",
|
||||
"print_screen", "sys_req", "scroll_lock", "pause", "brk",
|
||||
"grave", "tilde",
|
||||
"num_1", "exclamation",
|
||||
"num_2", "at",
|
||||
"num_3", "pound",
|
||||
"num_4", "dollar",
|
||||
"num_5", "percent",
|
||||
"num_6", "power",
|
||||
"num_7", "ampersand",
|
||||
"num_8", "asterisk",
|
||||
"num_9", "lparenthesis",
|
||||
"num_0", "rparenthesis",
|
||||
"minus", "underscore",
|
||||
"equal", "plus",
|
||||
"backspace",
|
||||
};
|
||||
|
||||
enum {
|
||||
none = 0x0000,
|
||||
|
||||
@@ -108,6 +130,8 @@ enum {
|
||||
rsuper,
|
||||
menu,
|
||||
|
||||
limit, //not an actual key -- marks the end of linear key entries
|
||||
|
||||
joypad_flag = 0x8000,
|
||||
joypad_nummask = 0x7f00,
|
||||
joypad_keymask = 0x00ff,
|
||||
|
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
libsort : version 0.01 ~byuu (2006-11-15)
|
||||
*/
|
||||
|
||||
#ifndef __LIBSORT
|
||||
#define __LIBSORT
|
||||
|
||||
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,9 +1,9 @@
|
||||
/*
|
||||
libstring : version 0.17 ~byuu (2007-05-20)
|
||||
libstring : version 0.18 ~byuu (2007-06-06)
|
||||
*/
|
||||
|
||||
#ifndef __LIBSTRING
|
||||
#define __LIBSTRING
|
||||
#ifndef LIBSTRING_H
|
||||
#define LIBSTRING_H
|
||||
|
||||
#include "libbase.h"
|
||||
#include "libvector.h"
|
||||
@@ -189,35 +189,32 @@ uint size;
|
||||
|
||||
~string() { safe_free(s); }
|
||||
|
||||
const char *operator()();
|
||||
char &operator[](const uint);
|
||||
string &operator= (const int);
|
||||
string &operator= (const char *);
|
||||
string &operator= (const string &);
|
||||
string &operator+=(const int);
|
||||
string &operator+=(const char *);
|
||||
string &operator+=(const string &);
|
||||
bool operator==(const char *);
|
||||
bool operator==(const string &);
|
||||
bool operator!=(const char *);
|
||||
bool operator!=(const string &);
|
||||
bool operator< (const char *);
|
||||
bool operator< (const string &);
|
||||
bool operator<=(const char *);
|
||||
bool operator<=(const string &);
|
||||
bool operator> (const char *);
|
||||
bool operator> (const string &);
|
||||
bool operator>=(const char *);
|
||||
bool operator>=(const string &);
|
||||
operator const char*() const { return s; }
|
||||
const char* operator()() const { return s; }
|
||||
char& operator[](const uint);
|
||||
|
||||
string operator+(const int);
|
||||
string operator+(const char *);
|
||||
string operator+(const string &);
|
||||
string& operator=(const int);
|
||||
string& operator=(const char*);
|
||||
string& operator=(const string&);
|
||||
|
||||
string& operator<<(const int);
|
||||
string& operator<<(const char*);
|
||||
string& operator<<(const string&);
|
||||
|
||||
bool operator==(const char*);
|
||||
bool operator==(const string&);
|
||||
bool operator!=(const char*);
|
||||
bool operator!=(const string&);
|
||||
bool operator< (const char*);
|
||||
bool operator< (const string&);
|
||||
bool operator<=(const char*);
|
||||
bool operator<=(const string&);
|
||||
bool operator> (const char*);
|
||||
bool operator> (const string&);
|
||||
bool operator>=(const char*);
|
||||
bool operator>=(const string&);
|
||||
};
|
||||
|
||||
string operator+(const int, const string &);
|
||||
string operator+(const char *, const string &);
|
||||
|
||||
inline void swap(string &x, string &y) { x.swap(y); }
|
||||
|
||||
#endif //__LIBSTRING
|
||||
#endif //LIBSTRING_H
|
||||
|
@@ -1,7 +1,3 @@
|
||||
const char *string::operator()() {
|
||||
return s;
|
||||
}
|
||||
|
||||
char &string::operator[](const uint index) {
|
||||
reserve(index);
|
||||
return s[index];
|
||||
@@ -22,17 +18,17 @@ string &string::operator=(const string &str) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &string::operator+=(const int num) {
|
||||
string& string::operator<<(const int num) {
|
||||
strcat(*this, strfmt("%d", num));
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &string::operator+=(const char *str) {
|
||||
string& string::operator<<(const char* str) {
|
||||
strcat(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &string::operator+=(const string &str) {
|
||||
string& string::operator<<(const string& str) {
|
||||
strcat(*this, str);
|
||||
return *this;
|
||||
}
|
||||
@@ -49,35 +45,3 @@ bool string::operator> (const char *str) { return strcmp(strptr(*this), str)
|
||||
bool string::operator> (const string &str) { return strcmp(strptr(*this), strptr(str)) > 0; }
|
||||
bool string::operator>=(const char *str) { return strcmp(strptr(*this), str) >= 0; }
|
||||
bool string::operator>=(const string &str) { return strcmp(strptr(*this), strptr(str)) >= 0; }
|
||||
|
||||
string string::operator+(const int num) {
|
||||
string temp(*this);
|
||||
strcat(temp, strfmt("%d", num));
|
||||
return temp;
|
||||
}
|
||||
|
||||
string string::operator+(const char *str) {
|
||||
string temp(*this);
|
||||
strcat(temp, str);
|
||||
return temp;
|
||||
}
|
||||
|
||||
string string::operator+(const string &str) {
|
||||
string temp(*this);
|
||||
strcat(temp, str);
|
||||
return temp;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
string operator+(const int x, const string &y) {
|
||||
string temp(strfmt("%d", x));
|
||||
strcat(temp, y);
|
||||
return temp;
|
||||
}
|
||||
|
||||
string operator+(const char *x, const string &y) {
|
||||
string temp(x);
|
||||
strcat(temp, y);
|
||||
return temp;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -40,13 +40,14 @@ uint get_screen_height() { return gdk_screen_height(); }
|
||||
|
||||
//
|
||||
|
||||
noinline bool gtk_file_load(Window &owner, char *filename, const char *filter, const char *path) {
|
||||
bool file_load(Window *owner, char *filename, const char *filter, const char *path) {
|
||||
strcpy(filename, "");
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new("Load File",
|
||||
GTK_WINDOW(owner.info.window), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
owner ? GTK_WINDOW(owner->info.window) : (GtkWindow*)0,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, 0);
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, (const gchar*)0);
|
||||
|
||||
if(path && strcmp(path, "")) {
|
||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
@@ -62,13 +63,14 @@ GtkWidget *dialog = gtk_file_chooser_dialog_new("Load File",
|
||||
return strcmp(filename, ""); //return true if filename != ""
|
||||
}
|
||||
|
||||
noinline bool gtk_file_save(Window &owner, char *filename, const char *filter, const char *path) {
|
||||
bool file_save(Window *owner, char *filename, const char *filter, const char *path) {
|
||||
strcpy(filename, "");
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new("Save File",
|
||||
GTK_WINDOW(owner.info.window), GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
owner ? GTK_WINDOW(owner->info.window) : (GtkWindow*)0,
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, 0);
|
||||
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, (const gchar*)0);
|
||||
|
||||
if(path && strcmp(path, "")) {
|
||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
@@ -85,19 +87,6 @@ GtkWidget *dialog = gtk_file_chooser_dialog_new("Save File",
|
||||
return strcmp(filename, ""); //return true if filename != ""
|
||||
}
|
||||
|
||||
//FreeBSD 6.2-amd64 bug workaround for file_load() + file_save()
|
||||
//gdb reveals stack corruption when calling gtk_file_chooset_dialog_new() from inside
|
||||
//a member function. however, calling function with nesting sidesteps the bug ...
|
||||
//gdb shows that the corruption occurs inside a GTK+ internal library function ...
|
||||
|
||||
bool file_load(Window &owner, char *filename, const char *filter, const char *path) {
|
||||
return gtk_file_load(owner, filename, filter, path);
|
||||
}
|
||||
|
||||
bool file_save(Window &owner, char *filename, const char *filter, const char *path) {
|
||||
return gtk_file_save(owner, filename, filter, path);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
uint16 translate_key(uint key) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user