mirror of
https://github.com/libretro/potator.git
synced 2024-11-23 08:29:41 +00:00
* Get rid of all non-libretro platform code
* Allows us to get rid of all remaining file I/O paths and get rid of unnecessary stdio.h includes * Allows us to bypass some needless wrapper functions * Smaller code size for binary as a result
This commit is contained in:
parent
3e3bfd7873
commit
0220ce3acb
@ -1,53 +0,0 @@
|
||||
# Potator2x makefile
|
||||
|
||||
# Global definitions
|
||||
|
||||
CCPREFIX = arm-linux-
|
||||
CC = ${CCPREFIX}gcc
|
||||
CPP = ${CCPREFIX}g++
|
||||
STRIP = ${CCPREFIX}strip
|
||||
AS = ${CCPREFIX}as
|
||||
PLATFORM =./platform/GP2X
|
||||
|
||||
PREFIX = /c/devkitPro/devkitGP2X/
|
||||
OBJS = controls.o gpu.o \
|
||||
memorymap.o sound.o \
|
||||
timer.o watara.o m6502/m6502.o \
|
||||
${PLATFORM}/main.o ${PLATFORM}/menues.o \
|
||||
${PLATFORM}/memcmp.o ${PLATFORM}/memcpy.o \
|
||||
${PLATFORM}/memset.o ${PLATFORM}/strcmp.o \
|
||||
${PLATFORM}/strlen.o ${PLATFORM}/strncmp.o \
|
||||
${PLATFORM}/lib/minimal.o
|
||||
ASMOBJS = arm_stub.S
|
||||
BIN = Potator2x
|
||||
|
||||
# Platform specific definitions
|
||||
|
||||
VPATH += common/
|
||||
CFLAGS += -O3 -Wall
|
||||
# NOTE: -funroll-loops will slow down compiling considerably
|
||||
CFLAGS += -funroll-loops -fstrength-reduce -fstrict-aliasing -fexpensive-optimizations -falign-functions -fweb -frename-registers -fomit-frame-pointer -ffast-math -fno-builtin -fno-common -finline -finline-functions
|
||||
#CFLAGS += -fsigned-char
|
||||
CXXFLAGS = ${CFLAGS} -fno-exceptions -fno-rtti
|
||||
ASFLAGS = ${CFLAGS}
|
||||
INCLUDES = -I${PLATFORM} -I${PLATFORM}/lib -I./common -I${PREFIX}/include
|
||||
LIBS = -L${PREFIX}/lib -static -lpthread -lm
|
||||
|
||||
# Compilation:
|
||||
|
||||
.SUFFIXES: .c
|
||||
|
||||
%.o: %.c
|
||||
${CC} ${CFLAGS} ${INCLUDES} -c $<
|
||||
|
||||
%.o: %.cpp
|
||||
$(CPP) $(CXXFLAGS) ${INCLUDES} -c $<
|
||||
%.o: %.S
|
||||
$(CC) ${CFLAGS} -s -c $<
|
||||
all: ${OBJS}
|
||||
${CC} *.o ${LIBS} -o ${BIN}.gpe
|
||||
${STRIP} ${BIN}.gpe
|
||||
gpecomp ${BIN}.gpe ${BIN}_comp.gpe
|
||||
|
||||
clean:
|
||||
rm -f *.o ${BIN}.gpe ${BIN}_comp.gpe
|
138
Makefile.nds
138
Makefile.nds
@ -1,138 +0,0 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := PotatorDS
|
||||
BUILD := build
|
||||
SOURCES := common common/m6502 platform/NDS
|
||||
INCLUDES := common common/m6502 platform/NDS
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -mthumb -mthumb-interwork
|
||||
|
||||
# note: arm9tdmi isn't the correct CPU arch, but anything newer and LD
|
||||
# *insists* it has a FPU or VFP, and it won't take no for an answer!
|
||||
#CFLAGS := -g -Wall -O3\
|
||||
# -mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\
|
||||
# -ffast-math \
|
||||
# $(ARCH)
|
||||
|
||||
CFLAGS := -DNDS -g -Wall -O3 -march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
|
||||
#CFLAGS := -g -Wall -O3 -march=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\
|
||||
-Wwrite-strings -Wpointer-arith -Wconversion \
|
||||
-ffast-math \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM9
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
#-mno-fpu
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lfat -lnds9
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(LIBNDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.bin)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(BINFILES:.bin=.o) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.nds
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).arm9 $(TARGET).ds.gba
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
#
|
||||
$(OUTPUT).ds.gba : $(OUTPUT).nds
|
||||
$(OUTPUT).nds : $(OUTPUT).arm9
|
||||
ndstool -c $(OUTPUT).nds -9 $(OUTPUT).arm9
|
||||
$(OUTPUT).arm9 : $(OUTPUT).elf
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
77
Makefile.od
77
Makefile.od
@ -1,77 +0,0 @@
|
||||
# Define compilation type
|
||||
OSTYPE = msys
|
||||
#OSTYPE = oda320
|
||||
#OSTYPE = odgcw
|
||||
|
||||
PRGNAME = potator-od
|
||||
|
||||
# define regarding OS, which compiler to use
|
||||
ifeq "$(OSTYPE)" "msys"
|
||||
EXESUFFIX = .exe
|
||||
TOOLCHAIN = /c/MinGW32
|
||||
CC = $(TOOLCHAIN)/bin/gcc
|
||||
CCP = $(TOOLCHAIN)/bin/g++
|
||||
LD = $(TOOLCHAIN)/bin/g++
|
||||
else
|
||||
ifeq "$(OSTYPE)" "oda320"
|
||||
TOOLCHAIN = /opt/opendingux-toolchain/usr
|
||||
else
|
||||
TOOLCHAIN = /opt/gcw0-toolchain/usr
|
||||
endif
|
||||
EXESUFFIX = .dge
|
||||
CC = $(TOOLCHAIN)/bin/mipsel-linux-gcc
|
||||
CCP = $(TOOLCHAIN)/bin/mipsel-linux-g++
|
||||
LD = $(TOOLCHAIN)/bin/mipsel-linux-g++
|
||||
endif
|
||||
|
||||
# add SDL dependencies
|
||||
SDL_LIB = $(TOOLCHAIN)/lib
|
||||
SDL_INCLUDE = $(TOOLCHAIN)/include
|
||||
|
||||
# change compilation / linking flag options
|
||||
ifeq "$(OSTYPE)" "msys"
|
||||
F_OPTS = -fomit-frame-pointer -ffunction-sections -ffast-math -fsingle-precision-constant
|
||||
CC_OPTS = -O2 -DMAX__PATH=1024 -g $(F_OPTS)
|
||||
CFLAGS = -I$(SDL_INCLUDE) $(CC_OPTS)
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
LDFLAGS = -L$(SDL_LIB) -lmingw32 -lSDLmain -lSDL -mwindows
|
||||
else
|
||||
F_OPTS = -fomit-frame-pointer -ffunction-sections -ffast-math -fsingle-precision-constant
|
||||
ifeq "$(OSTYPE)" "oda320"
|
||||
CC_OPTS = -O2 -mips32 -msoft-float -G0 -DMAX__PATH=1024 $(F_OPTS)
|
||||
else
|
||||
CC_OPTS = -O2 -mips32 -mhard-float -G0 -DMAX__PATH=1024 $(F_OPTS)
|
||||
endif
|
||||
CFLAGS = -I$(SDL_INCLUDE) -D_OPENDINGUX_ $(CC_OPTS)
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
LDFLAGS = -L$(SDL_LIB) $(CC_OPTS) -lSDL
|
||||
endif
|
||||
|
||||
CFLAGS += -Wall -Wextra
|
||||
CXXFLAGS += -Wall -Wextra
|
||||
|
||||
# Files to be compiled
|
||||
SRCDIR = ./common/m6502 ./common ./platform/opendingux
|
||||
VPATH = $(SRCDIR)
|
||||
SRC_C = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.c))
|
||||
SRC_CP = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.cpp))
|
||||
OBJ_C = $(notdir $(patsubst %.c, %.o, $(SRC_C)))
|
||||
OBJ_CP = $(notdir $(patsubst %.cpp, %.o, $(SRC_CP)))
|
||||
OBJS = $(OBJ_C) $(OBJ_CP)
|
||||
|
||||
# Rules to make executable
|
||||
$(PRGNAME)$(EXESUFFIX): $(OBJS)
|
||||
ifeq "$(OSTYPE)" "msys"
|
||||
$(LD) $(CFLAGS) -o $(PRGNAME)$(EXESUFFIX) $^ $(LDFLAGS)
|
||||
else
|
||||
$(LD) $(LDFLAGS) -o $(PRGNAME)$(EXESUFFIX) $^
|
||||
endif
|
||||
|
||||
$(OBJ_C) : %.o : %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJ_CP) : %.o : %.cpp
|
||||
$(CCP) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f $(PRGNAME)$(EXESUFFIX) *.o
|
@ -1,57 +0,0 @@
|
||||
# Project: PotatorSDL
|
||||
# Makefile created by Dev-C++ 4.9.9.2
|
||||
|
||||
CPP = g++.exe
|
||||
CC = gcc.exe
|
||||
WINDRES = windres.exe
|
||||
RES =
|
||||
OBJ = win/platform/SDL/main.o win/common/controls.o win/common/gpu.o win/common/memorymap.o win/common/sound.o win/common/timer.o win/common/watara.o win/common/m6502/m6502.o $(RES)
|
||||
LINKOBJ = win/platform/SDL/main.o win/common/controls.o win/common/gpu.o win/common/memorymap.o win/common/sound.o win/common/timer.o win/common/watara.o win/common/m6502/m6502.o $(RES)
|
||||
LIBS = -L"D:/GP2XSDK/lib" -lmingw32 -liconv -lgp2x -lSDL_image -lSDL_mixer -lSDL_ttf -lSDL_inifile -lSDLmain -lSDL -lpng -ljpeg -lvorbisidec -lmad -lfreetype -lz -lunicodefont -lgmon -pg -mwindows
|
||||
INCS = -I"D:/GP2XSDK/include/GP2X" -I"D:/GP2XSDK/include/SDL" -I"D:/GP2XSDK/include"
|
||||
CXXINCS = -I"D:/GP2XSDK/include/GP2X" -I"D:/GP2XSDK/include/SDL" -I"D:/GP2XSDK/lib/gcc/mingw32/3.4.2/include" -I"D:/GP2XSDK/include/c++/3.4.2/backward" -I"D:/GP2XSDK/include/c++/3.4.2/mingw32" -I"D:/GP2XSDK/include/c++/3.4.2" -I"D:/GP2XSDK/include"
|
||||
BIN = PotatorSDL.exe
|
||||
CXXFLAGS = $(CXXINCS) -DWIN32 -DWINDOWS -D_SDL_ -fexpensive-optimizations -O3 -pg -mwindows
|
||||
CFLAGS = $(INCS) -D_REENTRANT -DWIN32 -DWINDOWS -D_SDL_ -fexpensive-optimizations -O3 -pg -mwindows
|
||||
RM = rm -f
|
||||
MKDIR = cygwin-mkdir -p
|
||||
|
||||
.PHONY: all all-before all-after clean clean-custom
|
||||
|
||||
all: all-before PotatorSDL.exe all-after
|
||||
|
||||
all-before:
|
||||
$(MKDIR) "win/platform/SDL"
|
||||
$(MKDIR) "win/common"
|
||||
$(MKDIR) "win/common/m6502"
|
||||
|
||||
|
||||
clean: clean-custom
|
||||
${RM} $(OBJ) $(BIN)
|
||||
|
||||
$(BIN): $(OBJ)
|
||||
$(CC) $(LINKOBJ) -o $@ $(LIBS)
|
||||
|
||||
win/platform/SDL/main.o: platform/SDL/main.c
|
||||
$(CC) -c platform/SDL/main.c -o win/platform/SDL/main.o $(CFLAGS)
|
||||
|
||||
win/common/controls.o: common/controls.c
|
||||
$(CC) -c common/controls.c -o win/common/controls.o $(CFLAGS)
|
||||
|
||||
win/common/gpu.o: common/gpu.c
|
||||
$(CC) -c common/gpu.c -o win/common/gpu.o $(CFLAGS)
|
||||
|
||||
win/common/memorymap.o: common/memorymap.c
|
||||
$(CC) -c common/memorymap.c -o win/common/memorymap.o $(CFLAGS)
|
||||
|
||||
win/common/sound.o: common/sound.c
|
||||
$(CC) -c common/sound.c -o win/common/sound.o $(CFLAGS)
|
||||
|
||||
win/common/timer.o: common/timer.c
|
||||
$(CC) -c common/timer.c -o win/common/timer.o $(CFLAGS)
|
||||
|
||||
win/common/watara.o: common/watara.c
|
||||
$(CC) -c common/watara.c -o win/common/watara.o $(CFLAGS)
|
||||
|
||||
win/common/m6502/m6502.o: common/m6502/m6502.c
|
||||
$(CC) -c common/m6502/m6502.c -o win/common/m6502/m6502.o $(CFLAGS)
|
136
common/gpu.c
136
common/gpu.c
@ -200,7 +200,45 @@ static int ghostCount = 0;
|
||||
static uint8 *screenBuffers[SB_MAX];
|
||||
static uint8 screenBufferInnerX[SB_MAX];
|
||||
|
||||
static void add_ghosting(uint32 scanline, uint16 *backbuffer, uint8 start_x, uint8 end_x);
|
||||
static void add_ghosting(uint32 scanline, uint16 *backbuffer, uint8 innerx, uint8 size)
|
||||
{
|
||||
static int curSB = 0;
|
||||
static int lineCount = 0;
|
||||
|
||||
uint8 *vram_line = memorymap_getUpperRamPointer() + scanline;
|
||||
uint8 x, i, j;
|
||||
|
||||
screenBufferInnerX[curSB] = innerx;
|
||||
memset(screenBuffers[curSB] + lineCount * SV_W / 4, 0, SV_W / 4);
|
||||
for (j = innerx, x = 0; x < size; x++, j++) {
|
||||
uint8 b = vram_line[j >> 2];
|
||||
uint8 innerInd = (j & 3) * 2;
|
||||
uint8 c = (b >> innerInd) & 3;
|
||||
int pixInd = (x + lineCount * SV_W) / 4;
|
||||
if (c != 3) {
|
||||
for (i = 0; i < ghostCount; i++) {
|
||||
uint8 sbInd = (curSB + (SB_MAX - 1) - i) % SB_MAX;
|
||||
uint8 innerInd_ = ((screenBufferInnerX[sbInd] + x) & 3) * 2;
|
||||
uint8 c_ = (screenBuffers[sbInd][pixInd] >> innerInd_) & 3;
|
||||
if (c_ > c) {
|
||||
uint8 r = palettes[paletteIndex][c_ * 3 + 0];
|
||||
uint8 g = palettes[paletteIndex][c_ * 3 + 1];
|
||||
uint8 b = palettes[paletteIndex][c_ * 3 + 2];
|
||||
r = r + (palettes[paletteIndex][c * 3 + 0] - r) * i / ghostCount;
|
||||
g = g + (palettes[paletteIndex][c * 3 + 1] - g) * i / ghostCount;
|
||||
b = b + (palettes[paletteIndex][c * 3 + 2] - b) * i / ghostCount;
|
||||
backbuffer[x] = mapRGB(r, g, b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
screenBuffers[curSB][pixInd] |= c << innerInd;
|
||||
}
|
||||
|
||||
if (lineCount == SV_H - 1)
|
||||
curSB = (curSB + 1) % SB_MAX;
|
||||
lineCount = (lineCount + 1) % SV_H;
|
||||
}
|
||||
|
||||
void gpu_init(void)
|
||||
{
|
||||
@ -223,17 +261,15 @@ void gpu_done(void)
|
||||
void gpu_set_map_func(SV_MapRGBFunc func)
|
||||
{
|
||||
mapRGB = func;
|
||||
if (mapRGB == NULL) {
|
||||
if (mapRGB == NULL)
|
||||
mapRGB = rgb555;
|
||||
}
|
||||
}
|
||||
|
||||
void gpu_set_color_scheme(int colorScheme)
|
||||
{
|
||||
int i;
|
||||
if (colorScheme < 0 || colorScheme >= SV_COLOR_SCHEME_COUNT) {
|
||||
if (colorScheme < 0 || colorScheme >= SV_COLOR_SCHEME_COUNT)
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
palette[i] = mapRGB(palettes[colorScheme][i * 3 + 0],
|
||||
palettes[colorScheme][i * 3 + 1],
|
||||
@ -242,48 +278,26 @@ void gpu_set_color_scheme(int colorScheme)
|
||||
paletteIndex = colorScheme;
|
||||
}
|
||||
|
||||
// Faster but it's not accurate
|
||||
//void gpu_render_scanline(uint32 scanline, uint16 *backbuffer)
|
||||
//{
|
||||
// uint8 *vram_line = memorymap_getUpperRamPointer() + scanline;
|
||||
// uint8 x;
|
||||
//
|
||||
// for (x = 0; x < SV_W; x += 4) {
|
||||
// uint8 b = *(vram_line++);
|
||||
// backbuffer[0] = palette[((b >> 0) & 0x03)];
|
||||
// backbuffer[1] = palette[((b >> 2) & 0x03)];
|
||||
// backbuffer[2] = palette[((b >> 4) & 0x03)];
|
||||
// backbuffer[3] = palette[((b >> 6) & 0x03)];
|
||||
// backbuffer += 4;
|
||||
// }
|
||||
//}
|
||||
|
||||
void gpu_render_scanline(uint32 scanline, uint16 *backbuffer, uint8 innerx, uint8 size)
|
||||
{
|
||||
uint8 *vram_line = memorymap_getUpperRamPointer() + scanline;
|
||||
uint8 x, j = innerx, b = 0;
|
||||
|
||||
// #1
|
||||
if (j & 3) {
|
||||
if (j & 3)
|
||||
{
|
||||
b = *vram_line++;
|
||||
b >>= (j & 3) * 2;
|
||||
}
|
||||
for (x = 0; x < size; x++, j++) {
|
||||
if (!(j & 3)) {
|
||||
for (x = 0; x < size; x++, j++)
|
||||
{
|
||||
if (!(j & 3))
|
||||
b = *(vram_line++);
|
||||
}
|
||||
backbuffer[x] = palette[b & 3];
|
||||
b >>= 2;
|
||||
}
|
||||
// #2 Slow
|
||||
/*for (x = 0; x < size; x++, j++) {
|
||||
b = vram_line[j >> 2];
|
||||
backbuffer[x] = palette[(b >> ((j & 3) * 2)) & 3];
|
||||
}*/
|
||||
|
||||
if (ghostCount != 0) {
|
||||
if (ghostCount != 0)
|
||||
add_ghosting(scanline, backbuffer, innerx, size);
|
||||
}
|
||||
}
|
||||
|
||||
void gpu_set_ghosting(int frameCount)
|
||||
@ -297,17 +311,17 @@ void gpu_set_ghosting(int frameCount)
|
||||
ghostCount = frameCount;
|
||||
|
||||
if (ghostCount != 0) {
|
||||
if (screenBuffers[0] == NULL) {
|
||||
for (i = 0; i < SB_MAX; i++) {
|
||||
if (screenBuffers[0] == NULL)
|
||||
{
|
||||
for (i = 0; i < SB_MAX; i++)
|
||||
{
|
||||
screenBuffers[i] = malloc(SV_H * SV_W / 4);
|
||||
if (screenBuffers[i] == NULL) {
|
||||
if (screenBuffers[i] == NULL)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < SB_MAX; i++) {
|
||||
for (i = 0; i < SB_MAX; i++)
|
||||
memset(screenBuffers[i], 0, SV_H * SV_W / 4);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < SB_MAX; i++) {
|
||||
@ -317,47 +331,3 @@ void gpu_set_ghosting(int frameCount)
|
||||
}
|
||||
}
|
||||
|
||||
static void add_ghosting(uint32 scanline, uint16 *backbuffer, uint8 innerx, uint8 size)
|
||||
{
|
||||
static int curSB = 0;
|
||||
static int lineCount = 0;
|
||||
|
||||
uint8 *vram_line = memorymap_getUpperRamPointer() + scanline;
|
||||
uint8 x, i, j;
|
||||
|
||||
screenBufferInnerX[curSB] = innerx;
|
||||
memset(screenBuffers[curSB] + lineCount * SV_W / 4, 0, SV_W / 4);
|
||||
for (j = innerx, x = 0; x < size; x++, j++) {
|
||||
uint8 b = vram_line[j >> 2];
|
||||
uint8 innerInd = (j & 3) * 2;
|
||||
uint8 c = (b >> innerInd) & 3;
|
||||
int pixInd = (x + lineCount * SV_W) / 4;
|
||||
if (c != 3) {
|
||||
for (i = 0; i < ghostCount; i++) {
|
||||
uint8 sbInd = (curSB + (SB_MAX - 1) - i) % SB_MAX;
|
||||
uint8 innerInd_ = ((screenBufferInnerX[sbInd] + x) & 3) * 2;
|
||||
uint8 c_ = (screenBuffers[sbInd][pixInd] >> innerInd_) & 3;
|
||||
if (c_ > c) {
|
||||
#if 0
|
||||
backbuffer[x] = palette[3 - 3 * i / ghostCount];
|
||||
#else
|
||||
uint8 r = palettes[paletteIndex][c_ * 3 + 0];
|
||||
uint8 g = palettes[paletteIndex][c_ * 3 + 1];
|
||||
uint8 b = palettes[paletteIndex][c_ * 3 + 2];
|
||||
r = r + (palettes[paletteIndex][c * 3 + 0] - r) * i / ghostCount;
|
||||
g = g + (palettes[paletteIndex][c * 3 + 1] - g) * i / ghostCount;
|
||||
b = b + (palettes[paletteIndex][c * 3 + 2] - b) * i / ghostCount;
|
||||
backbuffer[x] = mapRGB(r, g, b);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
screenBuffers[curSB][pixInd] |= c << innerInd;
|
||||
}
|
||||
|
||||
if (lineCount == SV_H - 1) {
|
||||
curSB = (curSB + 1) % SB_MAX;
|
||||
}
|
||||
lineCount = (lineCount + 1) % SV_H;
|
||||
}
|
||||
|
@ -21,23 +21,12 @@
|
||||
|
||||
#include "m6502.h"
|
||||
#include "tables.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/** INLINE ***************************************************/
|
||||
/** Different compilers inline C functions differently. **/
|
||||
/*************************************************************/
|
||||
/* #define INLINE inline */
|
||||
|
||||
/** System-Dependent Stuff ***********************************/
|
||||
/** This is system-dependent code put here to speed things **/
|
||||
/** up. It has to stay inlined to be fast. **/
|
||||
/*************************************************************/
|
||||
#ifdef INES
|
||||
#define FAST_RDOP
|
||||
extern byte *Page[];
|
||||
INLINE byte Op6502(register word A) { return(Page[A >> 13][A & 0x1FFF]); }
|
||||
#endif
|
||||
|
||||
/** FAST_RDOP ************************************************/
|
||||
/** With this #define not present, Rd6502() should perform **/
|
||||
/** the functions of Rd6502(). **/
|
||||
@ -512,10 +501,6 @@ word Run6502(M6502 *R)
|
||||
case 0xFD: MR_Ax(I); M_SBC(I); break; /* SBC $ssss,x ABS,x */
|
||||
case 0xFE: MM_Ax(M_INC); break; /* INC $ssss,x ABS,x */
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf("[M65C02] Unrecognized instruction: $%02X at PC=$%04X\n",
|
||||
Op6502(R->PC.W - 1), (word)(R->PC.W - 1));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -100,12 +100,10 @@ uint8 memorymap_registers_read(uint32 Addr)
|
||||
break;
|
||||
case 0x27:
|
||||
data &= ~3;
|
||||
if (timer_shot) {
|
||||
if (timer_shot)
|
||||
data |= 1;
|
||||
}
|
||||
if (dma_finished) {
|
||||
if (dma_finished)
|
||||
data |= 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return data;
|
||||
@ -160,12 +158,10 @@ static void dma_write(uint32 Addr, uint8 Value)
|
||||
static void update_lowerRomBank(void)
|
||||
{
|
||||
uint32 bankOffset = 0;
|
||||
if (isMAGNUM) {
|
||||
if (isMAGNUM)
|
||||
bankOffset = (((regs[BANK] & 0x20) << 9) | ((regs[0x21] & 0xf) << 15));
|
||||
}
|
||||
else {
|
||||
else
|
||||
bankOffset = ((regs[BANK] & 0xe0) << 9);
|
||||
}
|
||||
lowerRomBank = programRom + bankOffset % programRomSize;
|
||||
}
|
||||
|
||||
@ -260,43 +256,14 @@ byte Rd6502(register word Addr)
|
||||
|
||||
BOOL memorymap_load(const uint8 *rom, uint32 size)
|
||||
{
|
||||
if ((size & 0x3fff) || size == 0 || rom == NULL) {
|
||||
if ((size & 0x3fff) || size == 0 || rom == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
programRomSize = size;
|
||||
programRom = rom;
|
||||
isMAGNUM = size > 131072;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void memorymap_save_state(FILE *fp)
|
||||
{
|
||||
uint8 ibank = 0;
|
||||
fwrite(regs, 0x2000, 1, fp);
|
||||
fwrite(lowerRam, 0x2000, 1, fp);
|
||||
fwrite(upperRam, 0x2000, 1, fp);
|
||||
|
||||
ibank = (uint8)((lowerRomBank - programRom) / 0x4000);
|
||||
WRITE_uint8(ibank, fp);
|
||||
|
||||
WRITE_BOOL(dma_finished, fp);
|
||||
WRITE_BOOL(timer_shot, fp);
|
||||
}
|
||||
|
||||
void memorymap_load_state(FILE *fp)
|
||||
{
|
||||
uint8 ibank = 0;
|
||||
fread(regs, 0x2000, 1, fp);
|
||||
fread(lowerRam, 0x2000, 1, fp);
|
||||
fread(upperRam, 0x2000, 1, fp);
|
||||
|
||||
READ_uint8(ibank, fp);
|
||||
lowerRomBank = programRom + ibank * 0x4000;
|
||||
|
||||
READ_BOOL(dma_finished, fp);
|
||||
READ_BOOL(timer_shot, fp);
|
||||
}
|
||||
|
||||
uint32 memorymap_save_state_buf_size(void)
|
||||
{
|
||||
return 0x2000 +
|
||||
|
@ -3,11 +3,8 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
enum {
|
||||
XSIZE = 0x00 /*
|
||||
, YSIZE = 0x01 */
|
||||
XSIZE = 0x00
|
||||
, XPOS = 0x02
|
||||
, YPOS = 0x03
|
||||
, BANK = 0x26
|
||||
@ -23,9 +20,6 @@ uint8 memorymap_registers_read(uint32 Addr);
|
||||
void memorymap_registers_write(uint32 Addr, uint8 Value);
|
||||
BOOL memorymap_load(const uint8 *rom, uint32 size);
|
||||
|
||||
void memorymap_save_state(FILE *fp);
|
||||
void memorymap_load_state(FILE *fp);
|
||||
|
||||
uint32 memorymap_save_state_buf_size(void);
|
||||
void memorymap_save_state_buf(uint8 *data);
|
||||
void memorymap_load_state_buf(const uint8 *data);
|
||||
|
@ -81,23 +81,19 @@ void sound_stream_update(uint8 *stream, uint32 len)
|
||||
break;
|
||||
}
|
||||
s = on ? ch[j].volume : 0;
|
||||
if (j == 0) {
|
||||
if (j == 0)
|
||||
*right += s;
|
||||
}
|
||||
else {
|
||||
else
|
||||
*left += s;
|
||||
}
|
||||
}
|
||||
ch[j].pos++;
|
||||
if (ch[j].pos >= ch[j].size) {
|
||||
ch[j].pos = 0;
|
||||
#ifndef SV_DISABLE_SUPER_DUPER_WAVE
|
||||
// Transition from off to on
|
||||
if (channel->on) {
|
||||
memcpy(&ch[j], channel, sizeof(ch[j]));
|
||||
channel->on = FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,38 +165,28 @@ void sound_wave_write(int which, int offset, uint8 data)
|
||||
// if size == 0 then channel->size == 0
|
||||
channel->size = (uint16)((real)SV_SAMPLE_RATE * ((size + 1) << 5) / UNSCALED_CLOCK);
|
||||
channel->pos = 0;
|
||||
#ifndef SV_DISABLE_SUPER_DUPER_WAVE
|
||||
// Popo Team
|
||||
if (channel->count != 0 || ch[which].size == 0 || channel->size == 0) {
|
||||
ch[which].size = channel->size;
|
||||
if (channel->count == 0)
|
||||
ch[which].pos = 0;
|
||||
}
|
||||
#else
|
||||
memcpy(&ch[which], channel, sizeof(ch[which]));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
channel->on = data & 0x40;
|
||||
channel->waveform = (data & 0x30) >> 4;
|
||||
channel->volume = data & 0x0f;
|
||||
#ifndef SV_DISABLE_SUPER_DUPER_WAVE
|
||||
if (!channel->on || ch[which].size == 0 || channel->size == 0) {
|
||||
uint16 pos = ch[which].pos;
|
||||
memcpy(&ch[which], channel, sizeof(ch[which]));
|
||||
if (channel->count != 0) // Journey to the West
|
||||
ch[which].pos = pos;
|
||||
}
|
||||
#else
|
||||
memcpy(&ch[which], channel, sizeof(ch[which]));
|
||||
#endif
|
||||
break;
|
||||
case 3:
|
||||
channel->count = data + 1;
|
||||
#ifndef SV_DISABLE_SUPER_DUPER_WAVE
|
||||
ch[which].size = channel->size; // Sonny Xpress!
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -239,15 +225,8 @@ void sound_noise_write(int offset, uint8 data)
|
||||
m_noise.reg[offset] = data;
|
||||
switch (offset) {
|
||||
case 0: {
|
||||
// Wataroo >= v0.7.1.0
|
||||
uint32 divisor = 8 << (data >> 4);
|
||||
// EQU_Watara.asm from Wataroo
|
||||
//uint32 divisor = 16 << (data >> 4);
|
||||
//if ((data >> 4) == 0) divisor = 8; // 500KHz are too many anyway
|
||||
//else if ((data >> 4) > 0xd) divisor >>= 2;
|
||||
m_noise.step = UNSCALED_CLOCK / ((real)SV_SAMPLE_RATE * divisor);
|
||||
// MESS/MAME. Wrong
|
||||
//m_noise.step = UNSCALED_CLOCK / (256.0 * SV_SAMPLE_RATE * (1 + (data >> 4)));
|
||||
m_noise.volume = data & 0xf;
|
||||
}
|
||||
break;
|
||||
@ -299,49 +278,6 @@ void sound_noise_write(int offset, uint8 data)
|
||||
X(real, pos) \
|
||||
X(real, step)
|
||||
|
||||
void sound_save_state(FILE *fp)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 2; i++) {
|
||||
fwrite(m_channel[i].reg, sizeof(m_channel[i].reg), 1, fp);
|
||||
#define X(type, member) WRITE_##type(m_channel[i].member, fp);
|
||||
EXPAND_CHANNEL
|
||||
#undef X
|
||||
}
|
||||
|
||||
fwrite(m_noise.reg, sizeof(m_noise.reg), 1, fp);
|
||||
#define X(type, member) WRITE_##type(m_noise.member, fp);
|
||||
EXPAND_NOISE
|
||||
#undef X
|
||||
fwrite(m_dma.reg, sizeof(m_dma.reg), 1, fp);
|
||||
#define X(type, member) WRITE_##type(m_dma.member, fp);
|
||||
EXPAND_DMA
|
||||
#undef X
|
||||
}
|
||||
|
||||
void sound_load_state(FILE *fp)
|
||||
{
|
||||
int i;
|
||||
|
||||
sound_reset();
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
fread(m_channel[i].reg, sizeof(m_channel[i].reg), 1, fp);
|
||||
#define X(type, member) READ_##type(m_channel[i].member, fp);
|
||||
EXPAND_CHANNEL
|
||||
#undef X
|
||||
}
|
||||
|
||||
fread(m_noise.reg, sizeof(m_noise.reg), 1, fp);
|
||||
#define X(type, member) READ_##type(m_noise.member, fp);
|
||||
EXPAND_NOISE
|
||||
#undef X
|
||||
fread(m_dma.reg, sizeof(m_dma.reg), 1, fp);
|
||||
#define X(type, member) READ_##type(m_dma.member, fp);
|
||||
EXPAND_DMA
|
||||
#undef X
|
||||
}
|
||||
|
||||
uint32 sound_save_state_buf_size(void)
|
||||
{
|
||||
uint32 size = 0;
|
||||
|
@ -3,8 +3,6 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void sound_reset(void);
|
||||
/*!
|
||||
* Generate U8 (0 - 45), 2 channels.
|
||||
@ -16,9 +14,6 @@ void sound_wave_write(int which, int offset, uint8 data);
|
||||
void sound_dma_write(int offset, uint8 data);
|
||||
void sound_noise_write(int offset, uint8 data);
|
||||
|
||||
void sound_save_state(FILE *fp);
|
||||
void sound_load_state(FILE *fp);
|
||||
|
||||
uint32 sound_save_state_buf_size(void);
|
||||
void sound_save_state_buf(uint8 *data);
|
||||
void sound_load_state_buf(const uint8 *data);
|
||||
|
@ -77,7 +77,6 @@ void supervision_done(void);
|
||||
* \return TRUE - success, FALSE - error
|
||||
*/
|
||||
BOOL supervision_load(const uint8 *rom, uint32 romSize);
|
||||
void supervision_exec(uint16 *backbuffer, BOOL skipFrame);
|
||||
void supervision_exec_ex(uint16 *backbuffer, int16 backbufferWidth, BOOL skipFrame);
|
||||
|
||||
/*!
|
||||
@ -98,22 +97,6 @@ void supervision_set_color_scheme(int colorScheme);
|
||||
* \param frameCount in range [0, SV_GHOSTING_MAX]. 0 - disable.
|
||||
*/
|
||||
void supervision_set_ghosting(int frameCount);
|
||||
/*!
|
||||
* Generate U8 (0 - 45), 2 channels.
|
||||
* \param len in bytes.
|
||||
*/
|
||||
void supervision_update_sound(uint8 *stream, uint32 len);
|
||||
|
||||
/*!
|
||||
* Save state to '{statePath}{id}.svst' if id >= 0, otherwise '{statePath}'.
|
||||
* \return TRUE - success, FALSE - error
|
||||
*/
|
||||
BOOL supervision_save_state(const char *statePath, int8 id);
|
||||
/*!
|
||||
* Load state from '{statePath}{id}.svst' if id >= 0, otherwise '{statePath}'.
|
||||
* \return TRUE - success, FALSE - error
|
||||
*/
|
||||
BOOL supervision_load_state(const char *statePath, int8 id);
|
||||
|
||||
uint32 supervision_save_state_buf_size(void);
|
||||
BOOL supervision_save_state_buf(uint8 *data, uint32 size);
|
||||
|
@ -14,12 +14,10 @@ void timer_reset(void)
|
||||
void timer_write(uint8 data)
|
||||
{
|
||||
uint32 d = data ? data : 0x100; // Dancing Block. d = data; ???
|
||||
if ((memorymap_getRegisters()[BANK] >> 4) & 1) {
|
||||
if ((memorymap_getRegisters()[BANK] >> 4) & 1)
|
||||
timer_cycles = d * 0x4000; // Bubble World, Eagle Plan...
|
||||
}
|
||||
else {
|
||||
else
|
||||
timer_cycles = d * 0x100;
|
||||
}
|
||||
timer_activated = TRUE;
|
||||
}
|
||||
|
||||
@ -35,18 +33,6 @@ void timer_exec(uint32 cycles)
|
||||
}
|
||||
}
|
||||
|
||||
void timer_save_state(FILE *fp)
|
||||
{
|
||||
WRITE_int32(timer_cycles, fp);
|
||||
WRITE_BOOL(timer_activated, fp);
|
||||
}
|
||||
|
||||
void timer_load_state(FILE *fp)
|
||||
{
|
||||
READ_int32(timer_cycles, fp);
|
||||
READ_BOOL(timer_activated, fp);
|
||||
}
|
||||
|
||||
uint32 timer_save_state_buf_size(void)
|
||||
{
|
||||
return sizeof(int32) +
|
||||
|
@ -3,15 +3,12 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void timer_reset(void);
|
||||
void timer_write(uint8 data);
|
||||
void timer_exec(uint32 cycles);
|
||||
|
||||
void timer_save_state(FILE *fp);
|
||||
void timer_load_state(FILE *fp);
|
||||
|
||||
uint32 timer_save_state_buf_size(void);
|
||||
void timer_save_state_buf(uint8 *data);
|
||||
void timer_load_state_buf(const uint8 *data);
|
||||
|
115
common/types.h
115
common/types.h
@ -1,6 +1,7 @@
|
||||
#ifndef __TYPES_H__
|
||||
#define __TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h> /* For memcpy() */
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -9,29 +10,12 @@ extern "C" {
|
||||
|
||||
#ifndef _uint8_DEFINED
|
||||
#define _uint8_DEFINED
|
||||
|
||||
# if (__STDC_VERSION__ >= 199901L) || \
|
||||
(__cplusplus >= 201103L) || (_MSC_VER >= 1600)
|
||||
# include <stdint.h>
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32; /*
|
||||
typedef uint64_t uint64; */
|
||||
typedef int8_t int8;
|
||||
typedef int16_t int16;
|
||||
typedef int32_t int32; /*
|
||||
typedef int64_t int64; */
|
||||
# else
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint32; /*
|
||||
typedef unsigned long long uint64; C99 */
|
||||
typedef signed char int8;
|
||||
typedef signed short int16;
|
||||
typedef signed int int32; /*
|
||||
typedef signed long long int64; C99 */
|
||||
# endif
|
||||
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
typedef int8_t int8;
|
||||
typedef int16_t int16;
|
||||
typedef int32_t int32;
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
@ -49,91 +33,6 @@ typedef float real;
|
||||
typedef double real;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Endian
|
||||
*/
|
||||
|
||||
/* Don't forget LSB_FIRST in m6502.h */
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
static uint16 SV_Swap16(uint16 x)
|
||||
{
|
||||
return (uint16)((x << 8) | (x >> 8));
|
||||
}
|
||||
|
||||
static uint32 SV_Swap32(uint32 x)
|
||||
{
|
||||
return (uint32)((x << 24) | ((x << 8) & 0x00FF0000) |
|
||||
((x >> 8) & 0x0000FF00) | (x >> 24));
|
||||
}
|
||||
|
||||
static double SV_SwapDouble(const double x)
|
||||
{
|
||||
double res;
|
||||
char *dinp = (char*)&x;
|
||||
char *dout = (char*)&res;
|
||||
dout[0] = dinp[7]; dout[1] = dinp[6];
|
||||
dout[2] = dinp[5]; dout[3] = dinp[4];
|
||||
dout[4] = dinp[3]; dout[5] = dinp[2];
|
||||
dout[6] = dinp[1]; dout[7] = dinp[0];
|
||||
return res;
|
||||
}
|
||||
#define SV_SwapLE16(X) SV_Swap16(X)
|
||||
#define SV_SwapLE32(X) SV_Swap32(X)
|
||||
#define SV_SwapLEDouble(X) SV_SwapDouble(X)
|
||||
#else
|
||||
#define SV_SwapLE16(X) (X)
|
||||
#define SV_SwapLE32(X) (X)
|
||||
#define SV_SwapLEDouble(X) (X)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* File
|
||||
*/
|
||||
|
||||
#define WRITE_BOOL(x, fp) do { \
|
||||
uint8 _ = x ? 1 : 0; \
|
||||
fwrite(&_, 1, 1, fp); } while (0)
|
||||
#define READ_BOOL(x, fp) do { \
|
||||
uint8 _; \
|
||||
fread(&_, 1, 1, fp); \
|
||||
x = _ ? TRUE : FALSE; } while (0)
|
||||
|
||||
#define WRITE_uint8(x, fp) do { \
|
||||
fwrite(&x, sizeof(x), 1, fp); } while (0)
|
||||
#define READ_uint8(x, fp) do { \
|
||||
fread(&x, sizeof(x), 1, fp); } while (0)
|
||||
|
||||
#define WRITE_int8(x, fp) WRITE_uint8(x, fp)
|
||||
#define READ_int8(x, fp) READ_uint8(x, fp)
|
||||
|
||||
#define WRITE_uint16(x, fp) do { \
|
||||
uint16 _ = SV_SwapLE16(x); \
|
||||
fwrite(&_, sizeof(x), 1, fp); } while (0)
|
||||
#define READ_uint16(x, fp) do { \
|
||||
fread(&x, sizeof(x), 1, fp); \
|
||||
x = SV_SwapLE16(x); } while (0)
|
||||
|
||||
#define WRITE_int16(x, fp) WRITE_uint16(x, fp)
|
||||
#define READ_int16(x, fp) READ_uint16(x, fp)
|
||||
|
||||
#define WRITE_uint32(x, fp) do { \
|
||||
uint32 _ = SV_SwapLE32(x); \
|
||||
fwrite(&_, sizeof(x), 1, fp); } while (0)
|
||||
#define READ_uint32(x, fp) do { \
|
||||
fread(&x, sizeof(x), 1, fp); \
|
||||
x = SV_SwapLE32(x); } while (0)
|
||||
|
||||
#define WRITE_int32(x, fp) WRITE_uint32(x, fp)
|
||||
#define READ_int32(x, fp) READ_uint32(x, fp)
|
||||
|
||||
#define WRITE_real(x, fp) do { \
|
||||
double _ = SV_SwapLEDouble(x); \
|
||||
fwrite(&_, sizeof(_), 1, fp); } while (0)
|
||||
#define READ_real(x, fp) do { \
|
||||
double _; \
|
||||
fread(&_, sizeof(_), 1, fp); \
|
||||
x = (real)SV_SwapLEDouble(_); } while (0)
|
||||
|
||||
/*
|
||||
* Buffer
|
||||
*/
|
||||
|
@ -63,18 +63,12 @@ void supervision_done(void)
|
||||
|
||||
BOOL supervision_load(const uint8 *rom, uint32 romSize)
|
||||
{
|
||||
if (!memorymap_load(rom, romSize)) {
|
||||
if (!memorymap_load(rom, romSize))
|
||||
return FALSE;
|
||||
}
|
||||
supervision_reset();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void supervision_exec(uint16 *backbuffer, BOOL skipFrame)
|
||||
{
|
||||
supervision_exec_ex(backbuffer, SV_W, skipFrame);
|
||||
}
|
||||
|
||||
void supervision_exec_ex(uint16 *backbuffer, int16 backbufferWidth, BOOL skipFrame)
|
||||
{
|
||||
uint32 i, scan;
|
||||
@ -88,7 +82,6 @@ void supervision_exec_ex(uint16 *backbuffer, int16 backbufferWidth, BOOL skipFra
|
||||
}
|
||||
|
||||
if (!skipFrame) {
|
||||
//if (!(regs[BANK] & 0x8)) { printf("LCD off\n"); }
|
||||
scan = regs[XPOS] / 4 + regs[YPOS] * 0x30;
|
||||
innerx = regs[XPOS] & 3;
|
||||
size = regs[XSIZE]; // regs[XSIZE] <= SV_W
|
||||
@ -130,25 +123,6 @@ void supervision_set_input(uint8 data)
|
||||
controls_state_write(data);
|
||||
}
|
||||
|
||||
void supervision_update_sound(uint8 *stream, uint32 len)
|
||||
{
|
||||
sound_stream_update(stream, len);
|
||||
}
|
||||
|
||||
static void get_state_path(const char *statePath, int8 id, char **newPath)
|
||||
{
|
||||
if (id < 0) {
|
||||
*newPath = (char*)statePath;
|
||||
}
|
||||
else {
|
||||
size_t newPathLen;
|
||||
newPathLen = strlen(statePath);
|
||||
*newPath = (char *)malloc(newPathLen + 8 + 1); // strlen("XXX.svst") + 1
|
||||
strcpy(*newPath, statePath);
|
||||
sprintf(*newPath + newPathLen, "%d.svst", id);
|
||||
}
|
||||
}
|
||||
|
||||
#define EXPAND_M6502 \
|
||||
X(uint8, A) \
|
||||
X(uint8, P) \
|
||||
@ -163,61 +137,6 @@ static void get_state_path(const char *statePath, int8 id, char **newPath)
|
||||
X(uint8, AfterCLI) \
|
||||
X(int32, IBackup)
|
||||
|
||||
BOOL supervision_save_state(const char *statePath, int8 id)
|
||||
{
|
||||
FILE *fp;
|
||||
char *newPath;
|
||||
|
||||
get_state_path(statePath, id, &newPath);
|
||||
fp = fopen(newPath, "wb");
|
||||
if (id >= 0)
|
||||
free(newPath);
|
||||
if (fp) {
|
||||
memorymap_save_state(fp);
|
||||
sound_save_state(fp);
|
||||
timer_save_state(fp);
|
||||
|
||||
#define X(type, member) WRITE_##type(m6502_registers.member, fp);
|
||||
EXPAND_M6502
|
||||
#undef X
|
||||
WRITE_BOOL(irq, fp);
|
||||
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL supervision_load_state(const char *statePath, int8 id)
|
||||
{
|
||||
FILE *fp;
|
||||
char *newPath;
|
||||
|
||||
get_state_path(statePath, id, &newPath);
|
||||
fp = fopen(newPath, "rb");
|
||||
if (id >= 0)
|
||||
free(newPath);
|
||||
if (fp) {
|
||||
memorymap_load_state(fp);
|
||||
sound_load_state(fp);
|
||||
timer_load_state(fp);
|
||||
|
||||
#define X(type, member) READ_##type(m6502_registers.member, fp);
|
||||
EXPAND_M6502
|
||||
#undef X
|
||||
READ_BOOL(irq, fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
uint32 supervision_save_state_buf_size(void)
|
||||
{
|
||||
return memorymap_save_state_buf_size() +
|
||||
|
@ -1,52 +0,0 @@
|
||||
Potator2x
|
||||
________________________
|
||||
Copyright (C) 2006-2007 Normmatt
|
||||
Copyright (C) 2005 Cal2
|
||||
|
||||
|
||||
1) Introduction
|
||||
2) Change Log
|
||||
3) Credits/Thanks
|
||||
4) Contact information
|
||||
|
||||
|
||||
1 Introduction________________________________________________
|
||||
|
||||
Potator is a Watara Supervision emulator.
|
||||
|
||||
Potator2x is a port of this once windows only emulator to the GP2X.
|
||||
|
||||
|
||||
2 Change Log_______________________________________________
|
||||
|
||||
Private Build #1
|
||||
-Initial Port
|
||||
-File Selector
|
||||
-Menu
|
||||
|
||||
Private Build #2
|
||||
-Added restart option to Menu
|
||||
-Added savestates to the emulator (probably not 100%)
|
||||
|
||||
Public Build #1
|
||||
-Added Sound
|
||||
-Added Options menu
|
||||
-Updated to Minimal Lib 0.C
|
||||
-Added NDS Port (very slow)
|
||||
NOTE: DS support is minimal at the moment and will only boot a rom named test.sv in the folder sv in the root of your cf/sd card
|
||||
|
||||
3 Credits/Thanks___________________________________________
|
||||
|
||||
Liranuna - the fileselector was based off his fileselector code for nds
|
||||
Ryleh - Thanks for the great Minimal Lib
|
||||
Cal2 - for writting the original emulator this is based on
|
||||
And to anyone i may have missed
|
||||
|
||||
4 Contact information________________________________________
|
||||
|
||||
E-mail: normmatt234@gmail.com
|
||||
Web: http://normmatt.com
|
||||
Web: http://sourceforge.net/projects/potator/
|
||||
|
||||
Please don't ask for roms, bios files or any other
|
||||
copyrighted stuff.
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
File diff suppressed because it is too large
Load Diff
@ -1,508 +0,0 @@
|
||||
/* GP2X minimal library v0.C
|
||||
Written by rlyeh, (c) 2005-2007.
|
||||
|
||||
Please check readme for licensing and other conditions. */
|
||||
|
||||
#ifndef __MINIMAL_H__
|
||||
#define __MINIMAL_H__
|
||||
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
#include <math.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <linux/keyboard.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/joystick.h>
|
||||
|
||||
|
||||
#define MINILIB_VERSION "GP2X minimal library v0.C by rlyeh, (c) 2005-2007."
|
||||
|
||||
|
||||
#ifndef GP2X_DEBUG_LEVEL
|
||||
#define GP2X_DEBUG_LEVEL 0
|
||||
#endif
|
||||
|
||||
#ifdef GP2X_PROFILE_DISABLE
|
||||
#define GP2X_PROFILE 0
|
||||
#else
|
||||
#define GP2X_PROFILE 1
|
||||
#endif
|
||||
|
||||
#define gp2x_debug(level, ...) if(GP2X_DEBUG_LEVEL & level) { __VA_ARGS__ ;}
|
||||
|
||||
#define gp2x_profile( ... ) \
|
||||
if(GP2X_PROFILE) { \
|
||||
static gp2x_profiles *prf = NULL; \
|
||||
\
|
||||
if(prf == NULL) { prf = gp2x_profile_register(); \
|
||||
sprintf(prf->fname, __FILE__ ":%d:%s", __LINE__, __func__ ); \
|
||||
prf->time = prf->calls = 0; } \
|
||||
\
|
||||
prf->calls++; \
|
||||
prf->time -= gp2x_memregl[0x0A00>>2]; \
|
||||
{ __VA_ARGS__ ;} \
|
||||
prf->time += gp2x_memregl[0x0A00>>2]; } else { __VA_ARGS__ ;}
|
||||
|
||||
#define isUp(x)
|
||||
#define isDown(x)
|
||||
#define isPress(x)
|
||||
|
||||
enum { RECT_RGB8=1, RECT_RGB16=2, RECT_YUV=4 };
|
||||
|
||||
enum { GP2X_UP=(0x1L<<0), GP2X_LEFT=(0x1L<<2), GP2X_DOWN=(0x1L<<4), GP2X_RIGHT=(0x1L<<6),
|
||||
GP2X_START=(1L<<8), GP2X_SELECT=(1L<<9), GP2X_L=(1L<<10), GP2X_R=(1L<<11),
|
||||
GP2X_A=(1L<<12), GP2X_B=(1L<<13), GP2X_X=(1L<<14), GP2X_Y=(1L<<15),
|
||||
GP2X_VOL_UP=(1L<<23), GP2X_VOL_DOWN=(1L<<22), GP2X_PUSH=(1L<<27),
|
||||
GP2X_HOME=(1L<<8), GP2X_TOUCH=(1L<<28) };
|
||||
|
||||
enum { LCD = 0, PAL = 4, NTSC = 3 };
|
||||
|
||||
typedef struct gp2x_font { int x,y,w,wmask,h,fg,bg,solid; unsigned char *data; } gp2x_font;
|
||||
typedef struct gp2x_queue { volatile unsigned long head, tail, items, max_items; unsigned long *place920t, *place940t; } gp2x_queue;
|
||||
typedef struct gp2x_rect { int x,y,w,h,solid,type; void *data; } gp2x_rect;
|
||||
|
||||
typedef struct gp2x_video_layer { void *screen;
|
||||
|
||||
unsigned long i[8]; //physical addresses of each buffer. they might have other usages too
|
||||
void *p[8]; //virtual address of each buffer
|
||||
} gp2x_video_layer;
|
||||
|
||||
typedef struct gp2x_file { int size, compressed; void *data; } gp2x_file;
|
||||
|
||||
typedef struct gp2x_profiles { char fname[56]; unsigned long calls, time; } gp2x_profiles;
|
||||
|
||||
extern gp2x_video_layer gp2x_video_RGB[1], gp2x_video_YUV[4];
|
||||
extern volatile unsigned long *gp2x_dualcore_ram, *gp2x_memregl, *gp2x_blitter;
|
||||
extern volatile unsigned short *gp2x_memregs;
|
||||
extern unsigned long gp2x_usbjoys, gp2x_f200;
|
||||
extern gp2x_font gp2x_default_font;
|
||||
//extern gp2x_profiles *gp2x_profiles;
|
||||
|
||||
|
||||
extern void gp2x_video_setgammacorrection(float);
|
||||
extern void gp2x_video_setdithering(int);
|
||||
extern void gp2x_video_setluminance(int, int);
|
||||
extern void gp2x_video_waitvsync(void);
|
||||
extern void gp2x_video_waithsync(void);
|
||||
extern void gp2x_video_cursor_show(int);
|
||||
extern void gp2x_video_cursor_move(int, int);
|
||||
extern void gp2x_video_cursor_setalpha(int, int);
|
||||
extern void gp2x_video_cursor_setup(unsigned char *, int, unsigned char, int, int, int, int, unsigned char, int, int, int, int);
|
||||
extern void gp2x_video_logo_enable(int);
|
||||
|
||||
extern void gp2x_video_RGB_color8 (int, int, int, int);
|
||||
extern unsigned short gp2x_video_RGB_color15(int, int, int, int);
|
||||
extern unsigned short gp2x_video_RGB_color16(int, int, int);
|
||||
extern void gp2x_video_RGB_setpalette(void);
|
||||
extern void gp2x_video_RGB_setcolorkey(int, int, int);
|
||||
extern void gp2x_video_RGB_setscaling(int, int);
|
||||
extern void gp2x_video_RGB_flip(int);
|
||||
extern void gp2x_video_RGB_setwindows(int, int, int, int, int, int);
|
||||
|
||||
extern unsigned long gp2x_video_YUV_color(int, int, int);
|
||||
extern void gp2x_video_YUV_setscaling(int, int, int);
|
||||
extern void gp2x_video_YUV_flip(int);
|
||||
extern void gp2x_video_YUV_setparts(int, int, int, int, int, int);
|
||||
|
||||
extern void gp2x_blitter_rect(gp2x_rect *);
|
||||
extern void gp2x_blitter_wait(void);
|
||||
extern void gp2x_blitter_send(gp2x_rect *);
|
||||
|
||||
extern unsigned long gp2x_joystick_read(int);
|
||||
extern char *gp2x_joystick_name(int);
|
||||
extern void gp2x_joystick_wait(int, unsigned long);
|
||||
extern void gp2x_joystick_scan(void);
|
||||
|
||||
extern void gp2x_touchscreen_update(void);
|
||||
|
||||
/*writeme : raw -> timer, timer -> counter ? */
|
||||
extern void gp2x_timer_reset(void);
|
||||
extern void gp2x_timer_delay(unsigned long);
|
||||
extern unsigned long gp2x_timer_read_raw(void);
|
||||
extern unsigned long gp2x_timer_read(void);
|
||||
extern unsigned long gp2x_timer_raw_to_ticks(unsigned long);
|
||||
extern unsigned long gp2x_timer_raw_one_second(void);
|
||||
|
||||
extern void gp2x_counter_init(int);
|
||||
extern void gp2x_counter_start(int);
|
||||
extern unsigned long long gp2x_counter_read(int);
|
||||
extern void gp2x_counter_pause(int);
|
||||
|
||||
extern gp2x_profiles *gp2x_profile_register(void);
|
||||
extern char *gp2x_profile_analyze(void);
|
||||
|
||||
extern void gp2x_tv_setmode(unsigned char);
|
||||
extern void gp2x_tv_adjust(signed char, signed char);
|
||||
|
||||
extern void gp2x_sound_frame (void *, void *, int);
|
||||
extern void gp2x_sound_volume(int, int);
|
||||
extern void gp2x_sound_pause(int);
|
||||
extern void gp2x_sound_stereo(int);
|
||||
extern void gp2x_sound_3Dboost(int);
|
||||
extern void gp2x_sound_attenuation(int);
|
||||
extern void gp2x_sound_setintensity(int, int, int);
|
||||
|
||||
extern void gp2x_i2c_write(unsigned char, unsigned char, unsigned char);
|
||||
extern unsigned char gp2x_i2c_read(unsigned char, unsigned char);
|
||||
|
||||
extern void gp2x_dualcore_clock(int);
|
||||
extern void gp2x_dualcore_pause(int);
|
||||
extern void gp2x_dualcore_sync(void);
|
||||
extern void gp2x_dualcore_exec(unsigned long);
|
||||
extern void gp2x_dualcore_launch_program(unsigned long *, unsigned long);
|
||||
extern void gp2x_dualcore_launch_program_from_disk(char *, unsigned long, unsigned long);
|
||||
extern void gp2x_dualcore_launch_HH(char *);
|
||||
|
||||
extern void gp2x_printf(gp2x_font *, int, int, const char *, ...);
|
||||
extern void gp2x_printf_init(gp2x_font *, int, int, void *, int, int, int);
|
||||
|
||||
extern void gp2x_misc_led(int);
|
||||
extern void gp2x_misc_lcd(int);
|
||||
extern int gp2x_misc_battery(void);
|
||||
extern void gp2x_misc_flushcache(void);
|
||||
extern int gp2x_misc_headphones(void);
|
||||
extern void gp2x_misc_memcard(void);
|
||||
|
||||
extern int gp2x_image_tga(FILE *fp, gp2x_rect *r);
|
||||
extern int gp2x_image_bmp(FILE *fp, gp2x_rect *r, unsigned char paletteIndex);
|
||||
extern void gp2x_unimage(gp2x_rect *r);
|
||||
|
||||
extern void gp2x_init(int, int, int, int, int, int, int);
|
||||
extern void gp2x_deinit(void);
|
||||
extern void gp2x_reboot(void);
|
||||
|
||||
|
||||
/* for our minimal kernel module */
|
||||
#define MINIMAL_I2C_WRITE 0x0
|
||||
#define MINIMAL_I2C_READ 0x1
|
||||
#define MINIMAL_MMU_FLUSHCACHE 0x2
|
||||
#define MINIMAL_MMU_INSTALLHACK 0x3
|
||||
#define MINIMAL_MMU_INSTALLHACK_32 0x4
|
||||
#define MINIMAL_MMU_INSTALLHACK_48 0x5
|
||||
#define MINIMAL_MMU_UNINSTALLHACK 0x6
|
||||
#define MINIMAL_MMU_R001 0x100
|
||||
#define MINIMAL_MMU_R100 0x101
|
||||
#define MINIMAL_MMU_W100 0x102
|
||||
#define MINIMAL_MMU_R200 0x103
|
||||
#define MINIMAL_MMU_W200 0x104
|
||||
#define MINIMAL_MMU_R300 0x105
|
||||
#define MINIMAL_MMU_W300 0x106
|
||||
#define MINIMAL_MMU_R500 0x107
|
||||
#define MINIMAL_MMU_W500 0x108
|
||||
#define MINIMAL_MMU_R501 0x109
|
||||
#define MINIMAL_MMU_W501 0x10a
|
||||
#define MINIMAL_MMU_R600 0x10b
|
||||
#define MINIMAL_MMU_W600 0x10c
|
||||
#define MINIMAL_MMU_W750 0x10d
|
||||
#define MINIMAL_MMU_W760 0x10e
|
||||
#define MINIMAL_MMU_W770 0x10f
|
||||
#define MINIMAL_MMU_W751 0x110
|
||||
#define MINIMAL_MMU_W7131 0x111
|
||||
#define MINIMAL_MMU_W761 0x112
|
||||
#define MINIMAL_MMU_W7101 0x113
|
||||
#define MINIMAL_MMU_W7141 0x114
|
||||
#define MINIMAL_MMU_W7102 0x115
|
||||
#define MINIMAL_MMU_W7104 0x116
|
||||
#define MINIMAL_MMU_W7142 0x117
|
||||
#define MINIMAL_MMU_W704 0x118
|
||||
#define MINIMAL_MMU_W870 0x119
|
||||
#define MINIMAL_MMU_W850 0x11a
|
||||
#define MINIMAL_MMU_W851 0x11b
|
||||
#define MINIMAL_MMU_W860 0x11c
|
||||
#define MINIMAL_MMU_W861 0x11d
|
||||
#define MINIMAL_MMU_R900 0x11e
|
||||
#define MINIMAL_MMU_W900 0x11f
|
||||
#define MINIMAL_MMU_R901 0x120
|
||||
#define MINIMAL_MMU_W901 0x121
|
||||
#define MINIMAL_MMU_R1000 0x122
|
||||
#define MINIMAL_MMU_W1000 0x123
|
||||
#define MINIMAL_MMU_R1001 0x124
|
||||
#define MINIMAL_MMU_W1001 0x125
|
||||
#define MINIMAL_MMU_R1300 0x126
|
||||
#define MINIMAL_MMU_W1300 0x127
|
||||
#define MINIMAL_MMU_DRAINWRITEBUFFER MINIMAL_MMU_W7104
|
||||
#define MINIMAL_MMU_INVALIDATEICACHE MINIMAL_MMU_W750
|
||||
#define MINIMAL_MMU_INVALIDATEDCACHE MINIMAL_MMU_W760
|
||||
|
||||
|
||||
|
||||
//for blitter usage
|
||||
|
||||
#define BLITTER_DST_BPP(r,a) gp2x_blitter[0x00 >> 2] = ((r)<<6)|((a)<<5) //r=1 reads dest then ROP // a=0,1 (8,16 bpp)
|
||||
#define BLITTER_DST_PTR(a) gp2x_blitter[0x04 >> 2] = (unsigned int)(a) //manejar puntero de la forma &kk[offset]
|
||||
#define BLITTER_DST_BPL(a) gp2x_blitter[0x08 >> 2] = (a) //bytes per line (320, 640, 1280...)
|
||||
|
||||
#define BLITTER_SRC_BPP(r,a) gp2x_blitter[0x0C >> 2] = ((r)<<7)|((a)<<5) //r=1 reads src after ROP // a=0,1 (8,16 bpp)
|
||||
#define BLITTER_SRC_PTR(a) gp2x_blitter[0x10 >> 2] = (unsigned int)(a) //manejar puntero de la forma &kk[offset]
|
||||
#define BLITTER_SRC_BPL(a) gp2x_blitter[0x14 >> 2] = (a) //bytes per line (320, 640, 1280...)
|
||||
|
||||
#define BLITTER_DIM(w,h) gp2x_blitter[0x2c >> 2] = ((h)<<16) | (w)
|
||||
|
||||
#define NO_MIRROR 0
|
||||
#define MIRROR_W 1
|
||||
#define MIRROR_H 2
|
||||
|
||||
#define ROP_P (0xF0) /*PATERN*/
|
||||
#define ROP_S (0xCC) /*SOURCE*/
|
||||
#define ROP_D (0xAA) /*DESTINATION*/
|
||||
#define ROP_0 (0x00) /*FALSE*/
|
||||
#define ROP_1 (0xFF) /*TRUE*/
|
||||
|
||||
#define BLITTER_ROP(transp_color,transp_on,fifoclear,ydirxdir,rop) gp2x_blitter[0x30 >> 2] = (((transp_color)<<16)|((transp_on)<<11)|((fifoclear)<<10)|((ydirxdir)<<8)|((rop)<<0))
|
||||
#define BLITTER_GO() gp2x_blitter[0x34 >> 2] = 1
|
||||
|
||||
#define BLITTER_FG(fg) gp2x_blitter[0x18 >> 2] = fg
|
||||
#define BLITTER_BG(bg) gp2x_blitter[0x1c >> 2] = bg
|
||||
|
||||
#define BLITTER_PATTERN_FG_COLOR(fg565) gp2x_blitter[0x24 >> 2] = fg565
|
||||
#define BLITTER_PATTERN_BG_COLOR(bg565) gp2x_blitter[0x28 >> 2] = bg565
|
||||
|
||||
#define BLITTER_PATTERN(mono, on, bpp, offset) gp2x_blitter[0x20 >> 2] = (((mono)<<6)|((on)<<5)|((bpp)<<3)|((offset)<<0))
|
||||
|
||||
#define BLITTER_PATTERN_SET(x) gp2x_blitter[0x80 >> 2] = x
|
||||
|
||||
|
||||
#if 0
|
||||
examples
|
||||
for a custom ROP to do destination = (source & ~destination ) ^ ~pattern;
|
||||
I'd use this: #define MYROP ((ROP_S & ~ROP_D ) ^ ~ROP_P)
|
||||
|
||||
more examples using this:
|
||||
PATCOPY : D = P
|
||||
PATINVERT : D = P ^ D
|
||||
DSTINVERT : D = ~D
|
||||
SRCCOPY : D = S
|
||||
NOTSRCCOPY : D = ~S
|
||||
SRCINVERT : D = S ^ D
|
||||
SRCAND : D = S & D
|
||||
SRCPAINT : D = S | D
|
||||
SRCERASE : D = S & ~D
|
||||
NOTSRCERASE : D = ~S & ~D
|
||||
MERGEPAINT : D = ~S | D
|
||||
MERGECOPY : D = S & P
|
||||
PATPAINT : D = D | P | ~S
|
||||
#endif
|
||||
|
||||
|
||||
//for our dualcore solution
|
||||
|
||||
#define GP2X_QUEUE_MAX_ITEMS ((4096 - sizeof(gp2x_queue)) / 4)
|
||||
#define GP2X_QUEUE_STRUCT_PTR (0 + 0x1000)
|
||||
#define GP2X_QUEUE_DATA_PTR (sizeof(gp2x_queue) + 0x1000)
|
||||
|
||||
#define gp2x_2ndcore_code(v) (*(volatile unsigned long *)(v))
|
||||
#define gp2x_1stcore_code(v) gp2x_dualcore_ram[(v)>>2]
|
||||
#define gp2x_2ndcore_data(v) gp2x_2ndcore_code((v)+0x1ff6000)
|
||||
#define gp2x_1stcore_data(v) gp2x_1stcore_code((v)+0x1ff6000)
|
||||
|
||||
#define gp2x_2ndcore_code_ptr(v) ((volatile unsigned long *)(v))
|
||||
#define gp2x_1stcore_code_ptr(v) (&gp2x_dualcore_ram[(v)>>2])
|
||||
#define gp2x_2ndcore_data_ptr(v) gp2x_2ndcore_code_ptr((v)+0x1ff6000)
|
||||
#define gp2x_1stcore_data_ptr(v) gp2x_1stcore_code_ptr((v)+0x1ff6000)
|
||||
|
||||
#define gp2x_dualcore_data(v) gp2x_1stcore_data((v)<<2)
|
||||
#define gp2x_dualcore_data_ptr(v) gp2x_1stcore_data_ptr((v)<<2)
|
||||
|
||||
#define gp2x_dualcore_declare_subprogram(name) extern void gp2x_dualcore_launch_## name ##_subprogram(void);
|
||||
#define gp2x_dualcore_launch_subprogram(name) gp2x_dualcore_launch_## name ##_subprogram()
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef MINIMAL_940T
|
||||
|
||||
#undef gp2x_dualcore_data
|
||||
#define gp2x_dualcore_data(v) gp2x_2ndcore_data((v)<<2)
|
||||
|
||||
#undef gp2x_dualcore_data_ptr
|
||||
#define gp2x_dualcore_data_ptr(v) gp2x_2ndcore_data_ptr((v)<<2)
|
||||
|
||||
#define main gp2x_2ndcore_run
|
||||
|
||||
static void gp2x_2ndcore_start(void) __attribute__((naked));
|
||||
|
||||
static void gp2x_2ndcore_start(void)
|
||||
{
|
||||
unsigned long gp2x_dequeue(gp2x_queue *q)
|
||||
{
|
||||
unsigned long data;
|
||||
|
||||
while(!q->items); //waiting for head to increase...
|
||||
|
||||
data=q->place940t[q->tail = (q->tail < q->max_items ? q->tail+1 : 0)];
|
||||
q->items--;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#define gp2x_dualcore_name_subprogram(name) \
|
||||
/* 00000020 <_start>: */ \
|
||||
/* 0:*/ asm volatile (".word 0xe59ff02c"); /* ldr pc, [pc, #44] ; 34 <ioffset> */ \
|
||||
/* 4:*/ asm volatile (".word 0xe59ff028"); /* ldr pc, [pc, #40] ; 34 <ioffset> */ \
|
||||
/* 8:*/ asm volatile (".word 0xe59ff024"); /* ldr pc, [pc, #36] ; 34 <ioffset> */ \
|
||||
/* c:*/ asm volatile (".word 0xe59ff020"); /* ldr pc, [pc, #32] ; 34 <ioffset> */ \
|
||||
/* 10:*/ asm volatile (".word 0xe59ff01c"); /* ldr pc, [pc, #28] ; 34 <ioffset> */ \
|
||||
/* 14:*/ asm volatile (".word 0xe59ff018"); /* ldr pc, [pc, #24] ; 34 <ioffset> */ \
|
||||
/* 18:*/ asm volatile (".word 0xe59ff014"); /* ldr pc, [pc, #20] ; 34 <ioffset> */ \
|
||||
/* 1c:*/ asm volatile (".word 0xe59ff010"); /* ldr pc, [pc, #16] ; 34 <ioffset> */ \
|
||||
/* 00000020 <_init>: */ \
|
||||
/* 20:*/ asm volatile (".word 0xe59fd010"); /* ldr sp, [pc, #16] ; 38 <stack> */ \
|
||||
/* 24:*/ asm volatile (".word 0xe59fc010"); /* ldr ip, [pc, #16] ; 3c <deadbeef> */ \
|
||||
/* 28:*/ asm volatile (".word 0xe59fb010"); /* ldr fp, [pc, #16] ; 40 <leetface> */ \
|
||||
/* 2c:*/ asm volatile (".word 0xe92d1800"); /* stmdb sp!, {fp, ip} */ \
|
||||
/* 30:*/ asm volatile (".word 0xea000004"); /* b 48 <realinit> */ \
|
||||
/* 00000034 <ioffset>: */ \
|
||||
/* 34:*/ asm volatile (".word 0x00000020"); /* */ \
|
||||
/* 00000038 <stack>: */ \
|
||||
/* 38:*/ asm volatile (".word 0x01fffffc"); /* */ \
|
||||
/* 0000003c <deadbeef>: */ \
|
||||
/* 3c:*/ asm volatile (".word 0xdeadbeef"); /* */ \
|
||||
/* 00000040 <leetface>: */ \
|
||||
/* 40:*/ asm volatile (".word 0x1ee7face"); /* */ \
|
||||
/* 00000044 <area1>: */ \
|
||||
/* 44:*/ asm volatile (".word 0x01ff6019"); /* */ \
|
||||
/* 00000048 <realinit>: */ \
|
||||
/* our main code starts here... */ \
|
||||
/* 48:*/ asm volatile (".word 0xe3a0003f"); /* mov r0, #63 ; 0x3f */ \
|
||||
/* 4c:*/ asm volatile (".word 0xee060f10"); /* mcr 15, 0, r0, cr6, cr0, {0} */ \
|
||||
/* 50:*/ asm volatile (".word 0xee060f30"); /* mcr 15, 0, r0, cr6, cr0, {1} */ \
|
||||
/* 54:*/ asm volatile (".word 0xe3a0001f"); /* mov r0, #31 ; 0x1f */ \
|
||||
/* 58:*/ asm volatile (".word 0xe38004be"); /* orr r0, r0, #-1107296256 ; 0xbe000000 */ \
|
||||
/* 5c:*/ asm volatile (".word 0xee060f11"); /* mcr 15, 0, r0, cr6, cr1, {0} */ \
|
||||
/* 60:*/ asm volatile (".word 0xe51f0024"); /* ldr r0, [pc, #-36] ; 44 <area> */ \
|
||||
/* 64:*/ asm volatile (".word 0xee060f12"); /* mcr 15, 0, r0, cr6, cr2, {0} */ \
|
||||
/* 68:*/ asm volatile (".word 0xe3a00001"); /* mov r0, #1 ; 0x1 */ \
|
||||
/* 6c:*/ asm volatile (".word 0xee020f10"); /* mcr 15, 0, r0, cr2, cr0, {0} */ \
|
||||
/* 70:*/ asm volatile (".word 0xe3a00001"); /* mov r0, #1 ; 0x1 */ \
|
||||
/* 74:*/ asm volatile (".word 0xee020f30"); /* mcr 15, 0, r0, cr2, cr0, {1} */ \
|
||||
/* 78:*/ asm volatile (".word 0xe3a00001"); /* mov r0, #1 ; 0x1 */ \
|
||||
/* 7c:*/ asm volatile (".word 0xee030f10"); /* mcr 15, 0, r0, cr3, cr0, {0} */ \
|
||||
/* 80:*/ asm volatile (".word 0xe3a000ff"); /* mov r0, #255 ; 0xff */ \
|
||||
/* 84:*/ asm volatile (".word 0xee050f10"); /* mcr 15, 0, r0, cr5, cr0, {0} */ \
|
||||
/* 88:*/ asm volatile (".word 0xe3a00003"); /* mov r0, #3 ; 0x3 */ \
|
||||
/* 8c:*/ asm volatile (".word 0xee050f30"); /* mcr 15, 0, r0, cr5, cr0, {1} */ \
|
||||
/* 90:*/ asm volatile (".word 0xe3a00000"); /* mov r0, #0 ; 0x0 */ \
|
||||
/* 94:*/ asm volatile (".word 0xe3800001"); /* orr r0, r0, #1 ; 0x1 */ \
|
||||
/* 98:*/ asm volatile (".word 0xe380007c"); /* orr r0, r0, #124 ; 0x7c */ \
|
||||
/* 9c:*/ asm volatile (".word 0xe3800a01"); /* orr r0, r0, #4096 ; 0x1000 */ \
|
||||
/* a0:*/ asm volatile (".word 0xe3800103"); /* orr r0, r0, #-1073741824 ; 0xc0000000 */ \
|
||||
/* a4:*/ asm volatile (".word 0xee010f10"); /* mcr 15, 0, r0, cr1, cr0, {0} */ \
|
||||
asm volatile ("mcr p15, 0, r0, c7, c10, 4" ::: "r0"); \
|
||||
while(1) gp2x_2ndcore_run(gp2x_dequeue((gp2x_queue *)gp2x_2ndcore_data_ptr(GP2X_QUEUE_STRUCT_PTR))); \
|
||||
} \
|
||||
void gp2x_dualcore_launch_##name##_subprogram(void) { gp2x_dualcore_launch_program((unsigned long *)&gp2x_2ndcore_start, ((int)&gp2x_dualcore_launch_##name##_subprogram)-((int)&gp2x_2ndcore_start)); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
@ 940Tcrt0.s for the fake-crt0s naked boombastic code in minimal_940t.h
|
||||
@ Written by rlyeh, (c) 2005-2006.
|
||||
|
||||
|
||||
.section".init"
|
||||
.code 32
|
||||
.align
|
||||
.global _start
|
||||
|
||||
_start:
|
||||
LDR PC, [pc, #44] @ Reset
|
||||
LDR PC, [pc, #40] @ Undefined instruction
|
||||
LDR PC, [pc, #36] @ Software Interrupt
|
||||
LDR PC, [pc, #32] @ Prefetch abort
|
||||
LDR PC, [pc, #28] @ Data abort
|
||||
LDR PC, [pc, #24] @ Reserved
|
||||
LDR PC, [pc, #20] @ IRQ
|
||||
LDR PC, [pc, #16] @ FIQ
|
||||
|
||||
_init:
|
||||
LDR SP, stack @ Load our stack at top of 64mb (32mb from 940t)
|
||||
LDR IP, deadbeef @ Load deadbeef
|
||||
LDR FP, leetface @ Load face0000
|
||||
STMDB R13!, {R11,R12}
|
||||
.word 0xea000004 @ B realinit
|
||||
@ putting B instead of .word may causes some troubles
|
||||
@ in *our* specific circumstances.
|
||||
ioffset:
|
||||
.word 0x00000020
|
||||
stack:
|
||||
.word 0x01fffffc
|
||||
deadbeef:
|
||||
.word 0xdeadbeef @ Squidge's legacy :-)
|
||||
leetface:
|
||||
.word 0x1ee7face
|
||||
|
||||
area:
|
||||
.word 0x01ff6019 @ at 920t's relative offset 0x4000000-0x8000(stack)-0x2000(shared area, where I map to)
|
||||
@ 00000011000b = 8kb | 00000000001b = enable
|
||||
|
||||
realinit:
|
||||
MOV R0, #0x3F @ 4Gb page starting at 0x000000
|
||||
MCR p15, 0, R0,c6,c0, 0 @ Set as data memory region 0
|
||||
MCR p15, 0, R0,c6,c0, 1 @ Set as instruction memory region 0
|
||||
|
||||
MOV R0, #0x1F @ Region 1 for MP registers, 0xc0000000-0x2000000
|
||||
ORR R0, R0, #0xBE000000 @ Base at registers start
|
||||
MCR p15, 0, r0,c6,c1, 0 @ Set as data memory region 1
|
||||
|
||||
LDR R0, area @ 8kb page. This is our dualcore FIFO queue
|
||||
MCR p15, 0, R0,c6,c2, 0 @ Set as data memory region 2
|
||||
@MCR p15, 0, R0,c6,c2, 1 @ Set as instruction memory region 2
|
||||
|
||||
@Region 0 is cacheable/bufferable
|
||||
@Region 1 is uncacheable/unbufferable
|
||||
@Region 2 is uncacheable/bufferable
|
||||
|
||||
MOV R0, #0x01 @ Region 0 is cachable/bufferable
|
||||
MCR p15, 0, R0,c2,c0, 0 @ Write data cachable bits
|
||||
MOV R0, #0x01
|
||||
MCR p15, 0, R0,c2,c0, 1 @ Write instruction cachable bits
|
||||
MOV R0, #0x01
|
||||
MCR p15, 0, R0,c3,c0, 0 @ Write bufferable bits
|
||||
|
||||
MOV R0, #0xFF @ Full access in all areas (read+write)
|
||||
MCR p15, 0, R0,c5,c0, 0 @ Write dataspace access permissions
|
||||
MOV R0, #0x03 @ Only region 1 has inst permissions
|
||||
MCR p15, 0, R0,c5,c0, 1 @ Write inst space access permissions to region 1
|
||||
|
||||
MOV R0, #0x00
|
||||
@MRC p15, 0, R0,c1,c0, 0 @ Read control register
|
||||
ORR R0, R0, #1 @ Protection unit enabled
|
||||
ORR R0, R0, #0x7C @ DCache enabled (should be #0x4?)
|
||||
ORR R0, R0, #0x1000 @ ICache enabled
|
||||
ORR R0, R0, #0xC0000000 @ Async clocking + FastBus
|
||||
MCR p15, 0, R0,c1,c0, 0 @ Set control register
|
||||
|
||||
.pool
|
||||
.end
|
||||
|
||||
|
||||
@Improvement:
|
||||
@Maybe I should enable cache at shared area, and flush cache
|
||||
@before checking/droping dualcore messages.
|
||||
|
||||
@some tools for this:
|
||||
@MOV R0, #0
|
||||
@MCR p15, 0, R0, c7, c5, 0 @Flush ICache
|
||||
@MCR p15, 0, R0, c7, c6, 0 @Flush DCache
|
||||
@MCR p15, 0, R0, c7, c10, 4 @Drain write buffer
|
||||
@MOV R0, address to prefetch
|
||||
@MCR p15, 0, R0, c7, c13, 1 @ICache prefetch
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,211 +0,0 @@
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "supervision.h"
|
||||
|
||||
#include "minimal.h"
|
||||
#include "menues.h"
|
||||
|
||||
BOOL paused = FALSE;
|
||||
|
||||
uint8 *buffer;
|
||||
unsigned int bufferSize = 0;
|
||||
|
||||
volatile unsigned char svFrm = 0;
|
||||
volatile unsigned char xFrm = 0;
|
||||
volatile unsigned char FPS = 0;
|
||||
|
||||
unsigned short *screen16;
|
||||
unsigned short screenbuffer[161 * 161];
|
||||
|
||||
const char *romname;
|
||||
|
||||
currentConfig_t currentConfig;
|
||||
|
||||
uint16 mapRGB(uint8 r, uint8 g, uint8 b)
|
||||
{
|
||||
return gp2x_video_RGB_color16(r, g, b);
|
||||
}
|
||||
|
||||
int LoadROM(const char *filename)
|
||||
{
|
||||
if (buffer != NULL) {
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
romname = filename;
|
||||
|
||||
FILE *romfile = fopen(filename, "rb");
|
||||
if (romfile == NULL) {
|
||||
printf("fopen(): Unable to open file!\n");
|
||||
return 1;
|
||||
}
|
||||
fseek(romfile, 0, SEEK_END);
|
||||
bufferSize = ftell(romfile);
|
||||
fseek(romfile, 0, SEEK_SET);
|
||||
|
||||
buffer = (uint8 *)malloc(bufferSize);
|
||||
|
||||
fread(buffer, bufferSize, 1, romfile);
|
||||
|
||||
if (fclose(romfile) == EOF) {
|
||||
printf("fclose(): Unable to close file!\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CheckKeys(void)
|
||||
{
|
||||
unsigned long pad = gp2x_joystick_read(0);
|
||||
|
||||
uint8 controls_state = 0;
|
||||
if (pad & GP2X_UP) controls_state |= 0x08;
|
||||
if (pad & GP2X_RIGHT) controls_state |= 0x01;
|
||||
if (pad & GP2X_LEFT) controls_state |= 0x02;
|
||||
if (pad & GP2X_DOWN) controls_state |= 0x04;
|
||||
if (pad & GP2X_UP) controls_state |= 0x08;
|
||||
if (pad & GP2X_X) controls_state |= 0x10;
|
||||
if (pad & GP2X_A) controls_state |= 0x20;
|
||||
if (pad & GP2X_START) controls_state |= 0x80;
|
||||
if (pad & GP2X_SELECT) controls_state |= 0x40;
|
||||
|
||||
supervision_set_input(controls_state);
|
||||
|
||||
if ((pad & GP2X_VOL_DOWN) && (pad & GP2X_START)) {
|
||||
supervision_done();
|
||||
//gp2x_deinit();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ((pad & GP2X_L) && (pad & GP2X_R)) {
|
||||
supervision_reset();
|
||||
supervision_set_map_func(mapRGB);
|
||||
}
|
||||
|
||||
if ((pad & GP2X_L) && (pad & GP2X_LEFT))
|
||||
supervision_set_color_scheme(SV_COLOR_SCHEME_DEFAULT);
|
||||
|
||||
if ((pad & GP2X_L) && (pad & GP2X_RIGHT))
|
||||
supervision_set_color_scheme(SV_COLOR_SCHEME_AMBER);
|
||||
|
||||
if ((pad & GP2X_L) && (pad & GP2X_UP))
|
||||
supervision_set_color_scheme(SV_COLOR_SCHEME_GREEN);
|
||||
|
||||
if ((pad & GP2X_L) && (pad & GP2X_DOWN))
|
||||
supervision_set_color_scheme(SV_COLOR_SCHEME_BLUE);
|
||||
|
||||
if (pad & GP2X_Y) {
|
||||
paused = TRUE;
|
||||
textClear();
|
||||
handleMainMenu();
|
||||
paused = FALSE;
|
||||
}
|
||||
|
||||
if (pad & (GP2X_VOL_UP | GP2X_VOL_DOWN)) {
|
||||
int vol = currentConfig.volume;
|
||||
if (pad & GP2X_VOL_UP) {
|
||||
if (vol < 255) vol++;
|
||||
} else {
|
||||
if (vol > 0) vol--;
|
||||
}
|
||||
gp2x_sound_volume(vol, vol);
|
||||
currentConfig.volume = vol;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
gp2x_init(1000, 16, 11025, 16, 1, 60, 1);
|
||||
|
||||
screen16 = (unsigned short *)gp2x_video_RGB[0].screen;
|
||||
|
||||
//char temp[255];
|
||||
|
||||
if (argc <= 1) {
|
||||
printf("\nNot enough arguments.\n");
|
||||
} else {
|
||||
romname = strdup(argv[1]);
|
||||
FILE *in = NULL;
|
||||
in = fopen(romname, "r");
|
||||
if (in == NULL) {
|
||||
printf("The file %s doesn't exist.\n", romname);
|
||||
}
|
||||
fclose(in);
|
||||
}
|
||||
|
||||
supervision_init();
|
||||
|
||||
getRunDir();
|
||||
|
||||
if (romname != NULL){
|
||||
LoadROM(romname);
|
||||
supervision_load(buffer, (uint32)bufferSize);
|
||||
supervision_set_map_func(mapRGB);
|
||||
} else {
|
||||
handleFileMenu();
|
||||
}
|
||||
|
||||
emu_ReadConfig();
|
||||
|
||||
gp2x_sound_volume(255, 255);
|
||||
gp2x_sound_pause(0);
|
||||
|
||||
while(1)
|
||||
{
|
||||
CheckKeys();
|
||||
|
||||
while(!paused)
|
||||
{
|
||||
CheckKeys(); //key control
|
||||
|
||||
switch(currentConfig.videoMode){
|
||||
case 0: {
|
||||
int j;
|
||||
supervision_exec(screenbuffer, FALSE);
|
||||
for (j = 0; j < 160; j++)
|
||||
gp2x_memcpy(screen16+(80+(j+40)*320), screenbuffer+(j * 160), 160*2);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
supervision_exec(screen16, FALSE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*gp2x_video_waitvsync();
|
||||
|
||||
sprintf(temp,"FPS: %3d", FPS);
|
||||
gp2x_printf(NULL,0,0,temp);
|
||||
++svFrm;*/
|
||||
|
||||
gp2x_video_RGB_flip(0);
|
||||
}
|
||||
}
|
||||
supervision_done();
|
||||
gp2x_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gp2x_sound_frame(void *blah, void *buffer, int samples)
|
||||
{
|
||||
short *buffer16 = (short*)buffer;
|
||||
|
||||
while (samples--) {
|
||||
if(currentConfig.enable_sound){
|
||||
// TODO:
|
||||
} else {
|
||||
*buffer16++ = 0; //Left
|
||||
*buffer16++ = 0; //Right
|
||||
}
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 ARM Ltd
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the company may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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 THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Adapted for uClibc from NetBSD memcmp.S, version 1.2 2003/04/05
|
||||
* by Erik Andersen <andersen@codepoet.org>
|
||||
*/
|
||||
|
||||
|
||||
.text
|
||||
.global memcmp;
|
||||
.type memcmp,%function
|
||||
.align 4; \
|
||||
|
||||
memcmp:
|
||||
/* if ((len - 1) < 0) return 0 */
|
||||
subs r2, r2, #1
|
||||
movmi r0, #0
|
||||
movmi pc, lr
|
||||
|
||||
/* ip == last src address to compare */
|
||||
add ip, r0, r2
|
||||
1:
|
||||
ldrb r2, [r0], #1
|
||||
ldrb r3, [r1], #1
|
||||
cmp ip, r0
|
||||
cmpcs r2, r3
|
||||
beq 1b
|
||||
sub r0, r2, r3
|
||||
mov pc, lr
|
||||
|
||||
.weak bcmp;
|
||||
bcmp = memcmp
|
||||
|
@ -1,498 +0,0 @@
|
||||
/* $NetBSD: memcpy.S,v 1.3 1997/11/22 03:27:12 mark Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Neil A. Carson and Mark Brinicombe
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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 THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This was modified by Jay Monkman <jmonkman@smoothsmoothie.com> to
|
||||
* save and restore r12. This is necessary for RTEMS.
|
||||
*/
|
||||
/* #include <machine/asm.h>*/
|
||||
|
||||
#define ENTRY(_LABEL) \
|
||||
.global _LABEL; _LABEL:
|
||||
/*
|
||||
.globl memcpy
|
||||
memcpy:
|
||||
*/
|
||||
ENTRY(gp2x_memcpy)
|
||||
stmfd sp!, {r0, r12, lr}
|
||||
bl _gp2x_memcpy
|
||||
ldmfd sp!, {r0, r12, pc}
|
||||
|
||||
|
||||
/*
|
||||
.globl memove
|
||||
memmove:
|
||||
*/
|
||||
ENTRY(gp2x_memmove)
|
||||
stmfd sp!, {r0, r12, lr}
|
||||
bl _gp2x_memcpy
|
||||
ldmfd sp!, {r0, r12, pc}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This is one fun bit of code ...
|
||||
* Some easy listening music is suggested while trying to understand this
|
||||
* code e.g. Iron Maiden
|
||||
*
|
||||
* For anyone attempting to understand it :
|
||||
*
|
||||
* The core code is implemented here with simple stubs for memcpy()
|
||||
* memmove() and bcopy().
|
||||
*
|
||||
* All local labels are prefixed with Lmemcpy_
|
||||
* Following the prefix a label starting f is used in the forward copy code
|
||||
* while a label using b is used in the backwards copy code
|
||||
* The source and destination addresses determine whether a forward or
|
||||
* backward copy is performed.
|
||||
* Separate bits of code are used to deal with the following situations
|
||||
* for both the forward and backwards copy.
|
||||
* unaligned source address
|
||||
* unaligned destination address
|
||||
* Separate copy routines are used to produce an optimised result for each
|
||||
* of these cases.
|
||||
* The copy code will use LDM/STM instructions to copy up to 32 bytes at
|
||||
* a time where possible.
|
||||
*
|
||||
* Note: r12 (aka ip) can be trashed during the function along with
|
||||
* r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out.
|
||||
* Additional registers are preserved prior to use i.e. r4, r5 & lr
|
||||
*
|
||||
* Apologies for the state of the comments;-)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
_memcpy:
|
||||
*/
|
||||
ENTRY(_gp2x_memcpy)
|
||||
/* Determine copy direction */
|
||||
cmp r1, r0
|
||||
bcc Lmemcpy_backwards
|
||||
|
||||
moveq r0, #0 /* Quick abort for len=0 */
|
||||
moveq pc, lr
|
||||
|
||||
stmdb sp!, {r0, lr} /* memcpy() returns dest addr */
|
||||
subs r2, r2, #4
|
||||
blt Lmemcpy_fl4 /* less than 4 bytes */
|
||||
ands r12, r0, #3
|
||||
bne Lmemcpy_fdestul /* oh unaligned destination addr */
|
||||
ands r12, r1, #3
|
||||
bne Lmemcpy_fsrcul /* oh unaligned source addr */
|
||||
|
||||
Lmemcpy_ft8:
|
||||
/* We have aligned source and destination */
|
||||
subs r2, r2, #8
|
||||
blt Lmemcpy_fl12 /* less than 12 bytes (4 from above) */
|
||||
subs r2, r2, #0x14
|
||||
blt Lmemcpy_fl32 /* less than 32 bytes (12 from above) */
|
||||
stmdb sp!, {r4} /* borrow r4 */
|
||||
|
||||
/* blat 32 bytes at a time */
|
||||
/* XXX for really big copies perhaps we should use more registers */
|
||||
Lmemcpy_floop32:
|
||||
ldmia r1!, {r3, r4, r12, lr}
|
||||
stmia r0!, {r3, r4, r12, lr}
|
||||
ldmia r1!, {r3, r4, r12, lr}
|
||||
stmia r0!, {r3, r4, r12, lr}
|
||||
subs r2, r2, #0x20
|
||||
bge Lmemcpy_floop32
|
||||
|
||||
cmn r2, #0x10
|
||||
ldmgeia r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
|
||||
stmgeia r0!, {r3, r4, r12, lr}
|
||||
subge r2, r2, #0x10
|
||||
ldmia sp!, {r4} /* return r4 */
|
||||
|
||||
Lmemcpy_fl32:
|
||||
adds r2, r2, #0x14
|
||||
|
||||
/* blat 12 bytes at a time */
|
||||
Lmemcpy_floop12:
|
||||
ldmgeia r1!, {r3, r12, lr}
|
||||
stmgeia r0!, {r3, r12, lr}
|
||||
subges r2, r2, #0x0c
|
||||
bge Lmemcpy_floop12
|
||||
|
||||
Lmemcpy_fl12:
|
||||
adds r2, r2, #8
|
||||
blt Lmemcpy_fl4
|
||||
|
||||
subs r2, r2, #4
|
||||
ldrlt r3, [r1], #4
|
||||
strlt r3, [r0], #4
|
||||
ldmgeia r1!, {r3, r12}
|
||||
stmgeia r0!, {r3, r12}
|
||||
subge r2, r2, #4
|
||||
|
||||
Lmemcpy_fl4:
|
||||
/* less than 4 bytes to go */
|
||||
adds r2, r2, #4
|
||||
ldmeqia sp!, {r0, pc} /* done */
|
||||
|
||||
/* copy the crud byte at a time */
|
||||
cmp r2, #2
|
||||
ldrb r3, [r1], #1
|
||||
strb r3, [r0], #1
|
||||
ldrgeb r3, [r1], #1
|
||||
strgeb r3, [r0], #1
|
||||
ldrgtb r3, [r1], #1
|
||||
strgtb r3, [r0], #1
|
||||
ldmia sp!, {r0, pc}
|
||||
|
||||
/* erg - unaligned destination */
|
||||
Lmemcpy_fdestul:
|
||||
rsb r12, r12, #4
|
||||
cmp r12, #2
|
||||
|
||||
/* align destination with byte copies */
|
||||
ldrb r3, [r1], #1
|
||||
strb r3, [r0], #1
|
||||
ldrgeb r3, [r1], #1
|
||||
strgeb r3, [r0], #1
|
||||
ldrgtb r3, [r1], #1
|
||||
strgtb r3, [r0], #1
|
||||
subs r2, r2, r12
|
||||
blt Lmemcpy_fl4 /* less the 4 bytes */
|
||||
|
||||
ands r12, r1, #3
|
||||
beq Lmemcpy_ft8 /* we have an aligned source */
|
||||
|
||||
/* erg - unaligned source */
|
||||
/* This is where it gets nasty ... */
|
||||
Lmemcpy_fsrcul:
|
||||
bic r1, r1, #3
|
||||
ldr lr, [r1], #4
|
||||
cmp r12, #2
|
||||
bgt Lmemcpy_fsrcul3
|
||||
beq Lmemcpy_fsrcul2
|
||||
cmp r2, #0x0c
|
||||
blt Lmemcpy_fsrcul1loop4
|
||||
sub r2, r2, #0x0c
|
||||
stmdb sp!, {r4, r5}
|
||||
|
||||
Lmemcpy_fsrcul1loop16:
|
||||
mov r3, lr, lsr #8
|
||||
ldmia r1!, {r4, r5, r12, lr}
|
||||
orr r3, r3, r4, lsl #24
|
||||
mov r4, r4, lsr #8
|
||||
orr r4, r4, r5, lsl #24
|
||||
mov r5, r5, lsr #8
|
||||
orr r5, r5, r12, lsl #24
|
||||
mov r12, r12, lsr #8
|
||||
orr r12, r12, lr, lsl #24
|
||||
stmia r0!, {r3-r5, r12}
|
||||
subs r2, r2, #0x10
|
||||
bge Lmemcpy_fsrcul1loop16
|
||||
ldmia sp!, {r4, r5}
|
||||
adds r2, r2, #0x0c
|
||||
blt Lmemcpy_fsrcul1l4
|
||||
|
||||
Lmemcpy_fsrcul1loop4:
|
||||
mov r12, lr, lsr #8
|
||||
ldr lr, [r1], #4
|
||||
orr r12, r12, lr, lsl #24
|
||||
str r12, [r0], #4
|
||||
subs r2, r2, #4
|
||||
bge Lmemcpy_fsrcul1loop4
|
||||
|
||||
Lmemcpy_fsrcul1l4:
|
||||
sub r1, r1, #3
|
||||
b Lmemcpy_fl4
|
||||
|
||||
Lmemcpy_fsrcul2:
|
||||
cmp r2, #0x0c
|
||||
blt Lmemcpy_fsrcul2loop4
|
||||
sub r2, r2, #0x0c
|
||||
stmdb sp!, {r4, r5}
|
||||
|
||||
Lmemcpy_fsrcul2loop16:
|
||||
mov r3, lr, lsr #16
|
||||
ldmia r1!, {r4, r5, r12, lr}
|
||||
orr r3, r3, r4, lsl #16
|
||||
mov r4, r4, lsr #16
|
||||
orr r4, r4, r5, lsl #16
|
||||
mov r5, r5, lsr #16
|
||||
orr r5, r5, r12, lsl #16
|
||||
mov r12, r12, lsr #16
|
||||
orr r12, r12, lr, lsl #16
|
||||
stmia r0!, {r3-r5, r12}
|
||||
subs r2, r2, #0x10
|
||||
bge Lmemcpy_fsrcul2loop16
|
||||
ldmia sp!, {r4, r5}
|
||||
adds r2, r2, #0x0c
|
||||
blt Lmemcpy_fsrcul2l4
|
||||
|
||||
Lmemcpy_fsrcul2loop4:
|
||||
mov r12, lr, lsr #16
|
||||
ldr lr, [r1], #4
|
||||
orr r12, r12, lr, lsl #16
|
||||
str r12, [r0], #4
|
||||
subs r2, r2, #4
|
||||
bge Lmemcpy_fsrcul2loop4
|
||||
|
||||
Lmemcpy_fsrcul2l4:
|
||||
sub r1, r1, #2
|
||||
b Lmemcpy_fl4
|
||||
|
||||
Lmemcpy_fsrcul3:
|
||||
cmp r2, #0x0c
|
||||
blt Lmemcpy_fsrcul3loop4
|
||||
sub r2, r2, #0x0c
|
||||
stmdb sp!, {r4, r5}
|
||||
|
||||
Lmemcpy_fsrcul3loop16:
|
||||
mov r3, lr, lsr #24
|
||||
ldmia r1!, {r4, r5, r12, lr}
|
||||
orr r3, r3, r4, lsl #8
|
||||
mov r4, r4, lsr #24
|
||||
orr r4, r4, r5, lsl #8
|
||||
mov r5, r5, lsr #24
|
||||
orr r5, r5, r12, lsl #8
|
||||
mov r12, r12, lsr #24
|
||||
orr r12, r12, lr, lsl #8
|
||||
stmia r0!, {r3-r5, r12}
|
||||
subs r2, r2, #0x10
|
||||
bge Lmemcpy_fsrcul3loop16
|
||||
ldmia sp!, {r4, r5}
|
||||
adds r2, r2, #0x0c
|
||||
blt Lmemcpy_fsrcul3l4
|
||||
|
||||
Lmemcpy_fsrcul3loop4:
|
||||
mov r12, lr, lsr #24
|
||||
ldr lr, [r1], #4
|
||||
orr r12, r12, lr, lsl #8
|
||||
str r12, [r0], #4
|
||||
subs r2, r2, #4
|
||||
bge Lmemcpy_fsrcul3loop4
|
||||
|
||||
Lmemcpy_fsrcul3l4:
|
||||
sub r1, r1, #1
|
||||
b Lmemcpy_fl4
|
||||
|
||||
Lmemcpy_backwards:
|
||||
add r1, r1, r2
|
||||
add r0, r0, r2
|
||||
subs r2, r2, #4
|
||||
blt Lmemcpy_bl4 /* less than 4 bytes */
|
||||
ands r12, r0, #3
|
||||
bne Lmemcpy_bdestul /* oh unaligned destination addr */
|
||||
ands r12, r1, #3
|
||||
bne Lmemcpy_bsrcul /* oh unaligned source addr */
|
||||
|
||||
Lmemcpy_bt8:
|
||||
/* We have aligned source and destination */
|
||||
subs r2, r2, #8
|
||||
blt Lmemcpy_bl12 /* less than 12 bytes (4 from above) */
|
||||
stmdb sp!, {r4, lr}
|
||||
subs r2, r2, #0x14 /* less than 32 bytes (12 from above) */
|
||||
blt Lmemcpy_bl32
|
||||
|
||||
/* blat 32 bytes at a time */
|
||||
/* XXX for really big copies perhaps we should use more registers */
|
||||
Lmemcpy_bloop32:
|
||||
ldmdb r1!, {r3, r4, r12, lr}
|
||||
stmdb r0!, {r3, r4, r12, lr}
|
||||
ldmdb r1!, {r3, r4, r12, lr}
|
||||
stmdb r0!, {r3, r4, r12, lr}
|
||||
subs r2, r2, #0x20
|
||||
bge Lmemcpy_bloop32
|
||||
|
||||
Lmemcpy_bl32:
|
||||
cmn r2, #0x10
|
||||
ldmgedb r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
|
||||
stmgedb r0!, {r3, r4, r12, lr}
|
||||
subge r2, r2, #0x10
|
||||
adds r2, r2, #0x14
|
||||
ldmgedb r1!, {r3, r12, lr} /* blat a remaining 12 bytes */
|
||||
stmgedb r0!, {r3, r12, lr}
|
||||
subge r2, r2, #0x0c
|
||||
ldmia sp!, {r4, lr}
|
||||
|
||||
Lmemcpy_bl12:
|
||||
adds r2, r2, #8
|
||||
blt Lmemcpy_bl4
|
||||
subs r2, r2, #4
|
||||
ldrlt r3, [r1, #-4]!
|
||||
strlt r3, [r0, #-4]!
|
||||
ldmgedb r1!, {r3, r12}
|
||||
stmgedb r0!, {r3, r12}
|
||||
subge r2, r2, #4
|
||||
|
||||
Lmemcpy_bl4:
|
||||
/* less than 4 bytes to go */
|
||||
adds r2, r2, #4
|
||||
moveq pc, lr /* done */
|
||||
|
||||
/* copy the crud byte at a time */
|
||||
cmp r2, #2
|
||||
ldrb r3, [r1, #-1]!
|
||||
strb r3, [r0, #-1]!
|
||||
ldrgeb r3, [r1, #-1]!
|
||||
strgeb r3, [r0, #-1]!
|
||||
ldrgtb r3, [r1, #-1]!
|
||||
strgtb r3, [r0, #-1]!
|
||||
mov pc, lr
|
||||
|
||||
/* erg - unaligned destination */
|
||||
Lmemcpy_bdestul:
|
||||
cmp r12, #2
|
||||
|
||||
/* align destination with byte copies */
|
||||
ldrb r3, [r1, #-1]!
|
||||
strb r3, [r0, #-1]!
|
||||
ldrgeb r3, [r1, #-1]!
|
||||
strgeb r3, [r0, #-1]!
|
||||
ldrgtb r3, [r1, #-1]!
|
||||
strgtb r3, [r0, #-1]!
|
||||
subs r2, r2, r12
|
||||
blt Lmemcpy_bl4 /* less than 4 bytes to go */
|
||||
ands r12, r1, #3
|
||||
beq Lmemcpy_bt8 /* we have an aligned source */
|
||||
|
||||
/* erg - unaligned source */
|
||||
/* This is where it gets nasty ... */
|
||||
Lmemcpy_bsrcul:
|
||||
bic r1, r1, #3
|
||||
ldr r3, [r1, #0]
|
||||
cmp r12, #2
|
||||
blt Lmemcpy_bsrcul1
|
||||
beq Lmemcpy_bsrcul2
|
||||
cmp r2, #0x0c
|
||||
blt Lmemcpy_bsrcul3loop4
|
||||
sub r2, r2, #0x0c
|
||||
stmdb sp!, {r4, r5, lr}
|
||||
|
||||
Lmemcpy_bsrcul3loop16:
|
||||
mov lr, r3, lsl #8
|
||||
ldmdb r1!, {r3-r5, r12}
|
||||
orr lr, lr, r12, lsr #24
|
||||
mov r12, r12, lsl #8
|
||||
orr r12, r12, r5, lsr #24
|
||||
mov r5, r5, lsl #8
|
||||
orr r5, r5, r4, lsr #24
|
||||
mov r4, r4, lsl #8
|
||||
orr r4, r4, r3, lsr #24
|
||||
stmdb r0!, {r4, r5, r12, lr}
|
||||
subs r2, r2, #0x10
|
||||
bge Lmemcpy_bsrcul3loop16
|
||||
ldmia sp!, {r4, r5, lr}
|
||||
adds r2, r2, #0x0c
|
||||
blt Lmemcpy_bsrcul3l4
|
||||
|
||||
Lmemcpy_bsrcul3loop4:
|
||||
mov r12, r3, lsl #8
|
||||
ldr r3, [r1, #-4]!
|
||||
orr r12, r12, r3, lsr #24
|
||||
str r12, [r0, #-4]!
|
||||
subs r2, r2, #4
|
||||
bge Lmemcpy_bsrcul3loop4
|
||||
|
||||
Lmemcpy_bsrcul3l4:
|
||||
add r1, r1, #3
|
||||
b Lmemcpy_bl4
|
||||
|
||||
Lmemcpy_bsrcul2:
|
||||
cmp r2, #0x0c
|
||||
blt Lmemcpy_bsrcul2loop4
|
||||
sub r2, r2, #0x0c
|
||||
stmdb sp!, {r4, r5, lr}
|
||||
|
||||
Lmemcpy_bsrcul2loop16:
|
||||
mov lr, r3, lsl #16
|
||||
ldmdb r1!, {r3-r5, r12}
|
||||
orr lr, lr, r12, lsr #16
|
||||
mov r12, r12, lsl #16
|
||||
orr r12, r12, r5, lsr #16
|
||||
mov r5, r5, lsl #16
|
||||
orr r5, r5, r4, lsr #16
|
||||
mov r4, r4, lsl #16
|
||||
orr r4, r4, r3, lsr #16
|
||||
stmdb r0!, {r4, r5, r12, lr}
|
||||
subs r2, r2, #0x10
|
||||
bge Lmemcpy_bsrcul2loop16
|
||||
ldmia sp!, {r4, r5, lr}
|
||||
adds r2, r2, #0x0c
|
||||
blt Lmemcpy_bsrcul2l4
|
||||
|
||||
Lmemcpy_bsrcul2loop4:
|
||||
mov r12, r3, lsl #16
|
||||
ldr r3, [r1, #-4]!
|
||||
orr r12, r12, r3, lsr #16
|
||||
str r12, [r0, #-4]!
|
||||
subs r2, r2, #4
|
||||
bge Lmemcpy_bsrcul2loop4
|
||||
|
||||
Lmemcpy_bsrcul2l4:
|
||||
add r1, r1, #2
|
||||
b Lmemcpy_bl4
|
||||
|
||||
Lmemcpy_bsrcul1:
|
||||
cmp r2, #0x0c
|
||||
blt Lmemcpy_bsrcul1loop4
|
||||
sub r2, r2, #0x0c
|
||||
stmdb sp!, {r4, r5, lr}
|
||||
|
||||
Lmemcpy_bsrcul1loop32:
|
||||
mov lr, r3, lsl #24
|
||||
ldmdb r1!, {r3-r5, r12}
|
||||
orr lr, lr, r12, lsr #8
|
||||
mov r12, r12, lsl #24
|
||||
orr r12, r12, r5, lsr #8
|
||||
mov r5, r5, lsl #24
|
||||
orr r5, r5, r4, lsr #8
|
||||
mov r4, r4, lsl #24
|
||||
orr r4, r4, r3, lsr #8
|
||||
stmdb r0!, {r4, r5, r12, lr}
|
||||
subs r2, r2, #0x10
|
||||
bge Lmemcpy_bsrcul1loop32
|
||||
ldmia sp!, {r4, r5, lr}
|
||||
adds r2, r2, #0x0c
|
||||
blt Lmemcpy_bsrcul1l4
|
||||
|
||||
Lmemcpy_bsrcul1loop4:
|
||||
mov r12, r3, lsl #24
|
||||
ldr r3, [r1, #-4]!
|
||||
orr r12, r12, r3, lsr #8
|
||||
str r12, [r0, #-4]!
|
||||
subs r2, r2, #4
|
||||
bge Lmemcpy_bsrcul1loop4
|
||||
|
||||
Lmemcpy_bsrcul1l4:
|
||||
add r1, r1, #1
|
||||
b Lmemcpy_bl4
|
@ -1,72 +0,0 @@
|
||||
/* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Philip Blundell <philb@gnu.org>
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/*#include <sys/syscall.h>*/
|
||||
|
||||
.text
|
||||
.global gp2x_memset;
|
||||
.type memset,%function
|
||||
.align 4; \
|
||||
|
||||
gp2x_memset:
|
||||
mov a4, a1
|
||||
cmp a3, $8 @ at least 8 bytes to do?
|
||||
blt 2f
|
||||
orr a2, a2, a2, lsl $8
|
||||
orr a2, a2, a2, lsl $16
|
||||
1:
|
||||
tst a4, $3 @ aligned yet?
|
||||
strneb a2, [a4], $1
|
||||
subne a3, a3, $1
|
||||
bne 1b
|
||||
mov ip, a2
|
||||
1:
|
||||
cmp a3, $8 @ 8 bytes still to do?
|
||||
blt 2f
|
||||
stmia a4!, {a2, ip}
|
||||
sub a3, a3, $8
|
||||
cmp a3, $8 @ 8 bytes still to do?
|
||||
blt 2f
|
||||
stmia a4!, {a2, ip}
|
||||
sub a3, a3, $8
|
||||
cmp a3, $8 @ 8 bytes still to do?
|
||||
blt 2f
|
||||
stmia a4!, {a2, ip}
|
||||
sub a3, a3, $8
|
||||
cmp a3, $8 @ 8 bytes still to do?
|
||||
stmgeia a4!, {a2, ip}
|
||||
subge a3, a3, $8
|
||||
bge 1b
|
||||
2:
|
||||
movs a3, a3 @ anything left?
|
||||
moveq pc, lr @ nope
|
||||
rsb a3, a3, $7
|
||||
add pc, pc, a3, lsl $2
|
||||
mov r0, r0
|
||||
strb a2, [a4], $1
|
||||
strb a2, [a4], $1
|
||||
strb a2, [a4], $1
|
||||
strb a2, [a4], $1
|
||||
strb a2, [a4], $1
|
||||
strb a2, [a4], $1
|
||||
strb a2, [a4], $1
|
||||
mov pc, lr
|
||||
|
||||
.size gp2x_memset,.-memset;
|
||||
|
@ -1,577 +0,0 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "menues.h"
|
||||
#include "minimal.h"
|
||||
|
||||
#include "memorymap.h"
|
||||
#include "supervision.h"
|
||||
#include "types.h"
|
||||
|
||||
FileEntry FileList[1024];
|
||||
uint32 fileCounter;
|
||||
|
||||
extern uint8* buffer;
|
||||
extern unsigned int bufferSize;
|
||||
extern void LoadROM(char* filename);
|
||||
extern uint16 mapRGB(uint8 r, uint8 g, uint8 b);
|
||||
|
||||
#define IOBASE 0xC0000000
|
||||
#define FPLLSETVREG (0x0910 >> 1)
|
||||
#define SYS_CLK_FREQ 7372800
|
||||
static const int clocklist[] = {166, 200, 220, 235, 250, 260, 266, 275, 285, 295, 300};
|
||||
void CPUSetting(int speed);
|
||||
|
||||
char runPath[MAXPATHLEN];
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void exitMenu(void)
|
||||
{
|
||||
supervision_done(); //shutsdown the system
|
||||
gp2x_deinit();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void getRunDir(void)
|
||||
{
|
||||
//char path[MAXPATHLEN];
|
||||
getcwd(runPath, MAXPATHLEN);
|
||||
printf("runDir -> %s\n", runPath);
|
||||
}
|
||||
|
||||
void emu_ReadConfig(void)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
getcwd(currentConfig.lastRomDir, MAXPATHLEN);
|
||||
printf("currentDir -> %s\n", currentConfig.lastRomDir);
|
||||
|
||||
chdir(runPath); //change to dir where you launched app
|
||||
|
||||
// set default config
|
||||
memset(¤tConfig, 0, sizeof(currentConfig));
|
||||
//currentConfig.lastRomDir[0] = 0;
|
||||
currentConfig.videoMode = 0;
|
||||
currentConfig.show_fps = 0;
|
||||
currentConfig.enable_sound = 0;
|
||||
currentConfig.SoundRate = 11025;
|
||||
currentConfig.Frameskip = 0; // auto
|
||||
currentConfig.CPUclock = 1;
|
||||
currentConfig.volume = 255;
|
||||
gp2x_sound_volume(currentConfig.volume,currentConfig.volume);
|
||||
|
||||
f = fopen("Potator2x.cfg", "rb");
|
||||
if (f) {
|
||||
fread(¤tConfig, 1, sizeof(currentConfig), f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
chdir(currentConfig.lastRomDir); // change back to last dir (where you loaded the rom from)
|
||||
|
||||
if(currentConfig.videoMode==2)
|
||||
gp2x_video_RGB_setscaling(160, 160);
|
||||
else
|
||||
gp2x_video_RGB_setscaling(320, 240);
|
||||
|
||||
CPUSetting(clocklist[currentConfig.CPUclock]);
|
||||
//gp2x_sound_rate(currentConfig.SoundRate);
|
||||
gp2x_sound_volume(currentConfig.volume,currentConfig.volume);
|
||||
gp2x_sound_pause(1^currentConfig.enable_sound);
|
||||
}
|
||||
|
||||
|
||||
void emu_WriteConfig(void)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
getcwd(currentConfig.lastRomDir, MAXPATHLEN);
|
||||
printf("currentDir -> %s\n", currentConfig.lastRomDir);
|
||||
|
||||
chdir(runPath); //change to dir where you launched app
|
||||
|
||||
f = fopen("Potator2x.cfg", "wb");
|
||||
if (f) {
|
||||
fwrite(¤tConfig, 1, sizeof(currentConfig), f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
sync();
|
||||
}
|
||||
|
||||
chdir(currentConfig.lastRomDir); // change back to last dir (where you loaded the rom from)
|
||||
|
||||
if(currentConfig.videoMode==2)
|
||||
gp2x_video_RGB_setscaling(160, 160);
|
||||
else
|
||||
gp2x_video_RGB_setscaling(320, 240);
|
||||
|
||||
CPUSetting(clocklist[currentConfig.CPUclock]);
|
||||
//gp2x_sound_rate(currentConfig.SoundRate);
|
||||
gp2x_sound_volume(currentConfig.volume,currentConfig.volume);
|
||||
gp2x_sound_pause(1^currentConfig.enable_sound);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void fillList(void)
|
||||
{
|
||||
textClear();
|
||||
int curFile = 0;
|
||||
DIR *dir = opendir(".");
|
||||
|
||||
if(dir)
|
||||
{
|
||||
struct dirent *ent;
|
||||
while((ent = readdir(dir)) != NULL)
|
||||
{
|
||||
sprintf(FileList[curFile].fName,"%s",ent->d_name);
|
||||
if(ent->d_type==DT_DIR)
|
||||
FileList[curFile].fType = FT_DIR;
|
||||
else
|
||||
FileList[curFile].fType = FT_FILE;
|
||||
|
||||
FileList[curFile].isRunable = !strcasestr(FileList[curFile].fName, ".sv");
|
||||
++curFile;
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
/*struct dirent **namelist;
|
||||
int i,k,l,n;
|
||||
|
||||
n = scandir(".", &namelist, 0, alphasort);
|
||||
if (n < 0) printf("scandir");
|
||||
|
||||
for(i=0;i<n-1;i++)
|
||||
{
|
||||
l=strlen(namelist[i]->d_name);
|
||||
if(namelist[i]->d_type==DT_DIR)
|
||||
FileList[curFile].fType = FT_DIR;
|
||||
else
|
||||
FileList[curFile].fType = FT_FILE;
|
||||
strncat (FileList[curFile].fName, namelist[i]->d_name, strlen(namelist[i]->d_name));
|
||||
++curFile;
|
||||
|
||||
FileList[curFile].isRunable = !strcasestr(FileList[curFile].fName, ".sv");
|
||||
}
|
||||
closedir(dir);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
gp2x_printf(0,10,2,"Error opening directory\n");
|
||||
gp2x_video_RGB_flip(0);
|
||||
}
|
||||
|
||||
fileCounter = curFile;
|
||||
}
|
||||
|
||||
void printList(uint32 startPos)
|
||||
{
|
||||
uint32 i = startPos;
|
||||
uint32 shown;
|
||||
|
||||
if(fileCounter > 18)
|
||||
shown = 19;
|
||||
else
|
||||
shown = fileCounter;
|
||||
|
||||
gp2x_printf(0, 1, 1, "Potator2x 1.0 by Normmatt\n\n");
|
||||
|
||||
for(; i < startPos + shown; ++i) {
|
||||
if(FileList[i].fType == FT_DIR){
|
||||
gp2x_printf(0, 15, 15 + ((i-startPos)+1)*8, "\n<%s>", FileList[i].fName);
|
||||
} else if(FileList[i].fType == FT_FILE) {
|
||||
gp2x_printf(0, 15, 15 + ((i-startPos)+1)*8, "\n%s", FileList[i].fName);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void handleFileMenu(void)
|
||||
{
|
||||
|
||||
BOOL isSelected = FALSE;
|
||||
int32 curFile = 0;
|
||||
int virtualFile = 0;
|
||||
|
||||
fillList();
|
||||
textClear();
|
||||
while(!isSelected) {
|
||||
unsigned long pad = gp2x_joystick_read(0);
|
||||
printList(curFile);
|
||||
gp2x_printf(0, 170, 1, "VirtualFile = %d",virtualFile);
|
||||
gp2x_printf(0, 170, 10, "File Count = %d",fileCounter);
|
||||
|
||||
if(FileList[virtualFile].isRunable){
|
||||
gp2x_default_font.fg = 0x6700;
|
||||
gp2x_printf(NULL, 0, (33 + (virtualFile*8)), "->");
|
||||
} else {
|
||||
gp2x_default_font.fg = 0xFFFF;
|
||||
gp2x_printf(NULL, 0, (33 + (virtualFile*8)), "->");
|
||||
}
|
||||
|
||||
gp2x_default_font.fg = 0xFFFF;
|
||||
|
||||
if(curFile)
|
||||
gp2x_printf(NULL, 200, 22, "^\n|");
|
||||
|
||||
if((curFile + 18 != fileCounter) && fileCounter > 19)
|
||||
gp2x_printf(NULL, 200, 200, "|\nv");
|
||||
|
||||
gp2x_video_RGB_flip(0);
|
||||
|
||||
if(pad & GP2X_RIGHT) {
|
||||
virtualFile += 5;
|
||||
if(virtualFile > 18)
|
||||
curFile += virtualFile - 18;
|
||||
textClear();
|
||||
}
|
||||
|
||||
if(pad & GP2X_LEFT) {
|
||||
virtualFile -= 5;
|
||||
if(virtualFile < 0)
|
||||
curFile += virtualFile;
|
||||
textClear();
|
||||
}
|
||||
|
||||
if(pad & GP2X_DOWN) {
|
||||
virtualFile++;
|
||||
textClear();
|
||||
}
|
||||
|
||||
if(pad & GP2X_UP) {
|
||||
virtualFile--;
|
||||
textClear();
|
||||
}
|
||||
|
||||
if(pad & GP2X_VOL_DOWN) if(pad & GP2X_START)
|
||||
exitMenu();
|
||||
|
||||
if(pad & GP2X_X) {
|
||||
if(FileList[curFile + virtualFile].fType == FT_DIR) {
|
||||
chdir(FileList[curFile + virtualFile].fName);
|
||||
fillList();
|
||||
virtualFile = curFile = 0;
|
||||
} else if(FileList[curFile + virtualFile].isRunable) {
|
||||
//textClear();
|
||||
//gp2x_printf(0, 1, 1, "Loading...\n\n%s", FileList[curFile + virtualFile].fName);
|
||||
//gp2x_video_RGB_flip(0);
|
||||
RESIZE();
|
||||
LoadROM(FileList[curFile + virtualFile].fName);
|
||||
textClear();
|
||||
supervision_load(buffer, (uint32)bufferSize);
|
||||
supervision_set_map_func(mapRGB);
|
||||
textClear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//if(pad & GP2X_A) return;
|
||||
|
||||
if(virtualFile < 0) {
|
||||
virtualFile = 0;
|
||||
--curFile;
|
||||
if(curFile < 0)
|
||||
curFile = 0;
|
||||
}
|
||||
|
||||
if(fileCounter < 19) {
|
||||
if(virtualFile >= fileCounter)
|
||||
virtualFile = fileCounter-1;
|
||||
} else {
|
||||
if(virtualFile > 18) {
|
||||
virtualFile = 18;
|
||||
++curFile;
|
||||
if(curFile + 18 > fileCounter)
|
||||
curFile = fileCounter - 19;
|
||||
}
|
||||
}
|
||||
|
||||
while(pad == gp2x_joystick_read(0));
|
||||
pad = gp2x_joystick_read(0);
|
||||
|
||||
textClear();
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define OPTION_VIDEOMODE 0
|
||||
#define OPTION_SHOWFPS 1
|
||||
#define OPTION_ENABLESOUND 2
|
||||
#define OPTION_SOUNDRATE 3
|
||||
#define OPTION_FRAMESKIP 4
|
||||
#define OPTION_CPUCLOCK 5
|
||||
#define OPTION_VOLUME 6
|
||||
#define OPTION_SAVEEXIT 7
|
||||
#define OPTION_EXIT 8
|
||||
|
||||
char videoMode[512];
|
||||
void handleMainMenu(void);
|
||||
|
||||
void handleOptionsMenu(void)
|
||||
{
|
||||
|
||||
BOOL isSelected = FALSE;
|
||||
int menuOption = 0;
|
||||
|
||||
emu_ReadConfig();
|
||||
gp2x_video_RGB_setscaling(320, 240);
|
||||
textClear();
|
||||
while(!isSelected) {
|
||||
int clock = currentConfig.CPUclock;
|
||||
int frameskip = currentConfig.Frameskip;
|
||||
int videomode = currentConfig.videoMode;
|
||||
int vol = currentConfig.volume;
|
||||
unsigned long pad = gp2x_joystick_read(0);
|
||||
|
||||
gp2x_printf(0, 1, 1, "Potator2x 1.0 by Normmatt\n\n");
|
||||
|
||||
gp2x_printf(0, 15, 15 + 2*8, "videoMode %s",videoMode);
|
||||
gp2x_printf(0, 15, 15 + 3*8, "show_fps %d",currentConfig.show_fps);
|
||||
gp2x_printf(0, 15, 15 + 4*8, "enable_sound %d",currentConfig.enable_sound);
|
||||
gp2x_printf(0, 15, 15 + 5*8, "SoundRate %d",currentConfig.SoundRate);
|
||||
gp2x_printf(0, 15, 15 + 6*8, "Frameskip %d",currentConfig.Frameskip);
|
||||
gp2x_printf(0, 15, 15 + 7*8, "CPUclock %d",clocklist[currentConfig.CPUclock]);
|
||||
gp2x_printf(0, 15, 15 + 8*8, "volume %d",currentConfig.volume);
|
||||
gp2x_printf(0, 15, 15 + 9*8, "Save and Exit");
|
||||
gp2x_printf(0, 15, 15 + 10*8, "Exit");
|
||||
|
||||
gp2x_printf(0, 170, 1, "MenuOption = %d",menuOption);
|
||||
|
||||
gp2x_printf(0, 0, (31 + (menuOption*8)), "->");
|
||||
|
||||
gp2x_video_RGB_flip(0);
|
||||
|
||||
if(pad & GP2X_RIGHT) {
|
||||
if(menuOption == OPTION_VIDEOMODE) if(videomode < 2) currentConfig.videoMode++;
|
||||
if(menuOption == OPTION_SHOWFPS) currentConfig.show_fps^=1;
|
||||
if(menuOption == OPTION_ENABLESOUND) currentConfig.enable_sound^=1;
|
||||
if(menuOption == OPTION_SOUNDRATE) currentConfig.SoundRate*=2;
|
||||
if(menuOption == OPTION_FRAMESKIP) if (frameskip < 9) frameskip++;
|
||||
if(menuOption == OPTION_CPUCLOCK) if(clock < sizeof(clocklist)) clock++;
|
||||
if(menuOption == OPTION_VOLUME) if (vol < 255) vol+= (pad & GP2X_RIGHT) ? 1 : 0;
|
||||
}
|
||||
|
||||
if(pad & GP2X_LEFT) {
|
||||
if(menuOption == OPTION_VIDEOMODE) if(videomode > 0) currentConfig.videoMode--;
|
||||
if(menuOption == OPTION_SHOWFPS) currentConfig.show_fps^=1;
|
||||
if(menuOption == OPTION_ENABLESOUND) currentConfig.enable_sound^=1;
|
||||
if(menuOption == OPTION_SOUNDRATE) currentConfig.SoundRate/=2;
|
||||
if(menuOption == OPTION_FRAMESKIP) if (frameskip > 0) frameskip--;
|
||||
if(menuOption == OPTION_CPUCLOCK) if(clock > 0) clock--;
|
||||
if(menuOption == OPTION_VOLUME) if (vol > 0) vol-= (pad & GP2X_LEFT) ? 1 : 0;
|
||||
}
|
||||
|
||||
if(pad & GP2X_DOWN) {
|
||||
menuOption++;
|
||||
textClear();
|
||||
}
|
||||
|
||||
if(pad & GP2X_UP) {
|
||||
menuOption--;
|
||||
textClear();
|
||||
}
|
||||
|
||||
if(pad & GP2X_VOL_DOWN) if(pad & GP2X_START)
|
||||
exitMenu();
|
||||
|
||||
if(pad & GP2X_X) {
|
||||
switch(menuOption){
|
||||
case OPTION_SAVEEXIT:
|
||||
emu_WriteConfig();
|
||||
return;
|
||||
case OPTION_EXIT:
|
||||
//gp2x_sound_rate(currentConfig.SoundRate);
|
||||
return;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(currentConfig.videoMode)
|
||||
{
|
||||
case 0: sprintf(videoMode,"Slow"); break;
|
||||
case 1: sprintf(videoMode,"Quick"); break;
|
||||
case 2: sprintf(videoMode,"Full Screen"); break;
|
||||
default: sprintf(videoMode,""); break;
|
||||
}
|
||||
|
||||
if(currentConfig.SoundRate <= 11025) currentConfig.SoundRate = 11025;
|
||||
if(currentConfig.SoundRate >= 44100) currentConfig.SoundRate = 44100;
|
||||
|
||||
currentConfig.Frameskip = frameskip;
|
||||
currentConfig.CPUclock = clock;
|
||||
|
||||
currentConfig.volume = vol;
|
||||
|
||||
if(menuOption < 0) menuOption = 0;
|
||||
if(menuOption > 8) menuOption = 8;
|
||||
|
||||
while(pad == gp2x_joystick_read(0));
|
||||
pad = gp2x_joystick_read(0);
|
||||
|
||||
textClear();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int saveSlot = 0;
|
||||
|
||||
#define MMOPTION_CONTINUE 0
|
||||
#define MMOPTION_RESTART 1
|
||||
#define MMOPTION_SELECTOR 2
|
||||
#define MMOPTION_OPTIONS 3
|
||||
#define MMOPTION_SAVESTATE 4
|
||||
#define MMOPTION_LOADSTATE 5
|
||||
#define MMOPTION_EXIT 6
|
||||
|
||||
void printMenuOptions()
|
||||
{
|
||||
gp2x_printf(0, 1, 1, "Potator2x 1.0 by Normmatt\n\n");
|
||||
|
||||
gp2x_printf(0, 15, 15 + 2*8, "Continue");
|
||||
gp2x_printf(0, 15, 15 + 3*8, "Reset");
|
||||
gp2x_printf(0, 15, 15 + 4*8, "File Selector");
|
||||
gp2x_printf(0, 15, 15 + 5*8, "Options");
|
||||
gp2x_printf(0, 15, 15 + 6*8, "Save State %d",saveSlot);
|
||||
gp2x_printf(0, 15, 15 + 7*8, "Load State %d",saveSlot);
|
||||
gp2x_printf(0, 15, 15 + 8*8, "Exit");
|
||||
}
|
||||
|
||||
void handleMainMenu(void)
|
||||
{
|
||||
|
||||
BOOL isSelected = FALSE;
|
||||
int menuOption = 0;
|
||||
|
||||
textClear();
|
||||
gp2x_video_RGB_setscaling(320, 240);
|
||||
while(!isSelected) {
|
||||
unsigned long pad = gp2x_joystick_read(0);
|
||||
printMenuOptions();
|
||||
gp2x_printf(0, 170, 1, "MenuOption = %d",menuOption);
|
||||
|
||||
gp2x_printf(0, 0, (31 + (menuOption*8)), "->");
|
||||
|
||||
gp2x_video_RGB_flip(0);
|
||||
|
||||
if(pad & GP2X_RIGHT) {
|
||||
if((menuOption == MMOPTION_SAVESTATE) || (menuOption == MMOPTION_LOADSTATE))
|
||||
saveSlot++;
|
||||
}
|
||||
|
||||
if(pad & GP2X_LEFT) {
|
||||
if((menuOption == MMOPTION_SAVESTATE) || (menuOption == MMOPTION_LOADSTATE))
|
||||
saveSlot--;
|
||||
}
|
||||
|
||||
if(pad & GP2X_DOWN) {
|
||||
menuOption++;
|
||||
textClear();
|
||||
}
|
||||
|
||||
if(pad & GP2X_UP) {
|
||||
menuOption--;
|
||||
textClear();
|
||||
}
|
||||
|
||||
if(pad & GP2X_VOL_DOWN) if(pad & GP2X_START)
|
||||
exitMenu();
|
||||
|
||||
if(pad & GP2X_X) {
|
||||
switch(menuOption){
|
||||
case MMOPTION_CONTINUE: RESIZE(); textClear(); return;
|
||||
case MMOPTION_RESTART: {
|
||||
RESIZE();
|
||||
supervision_reset();
|
||||
supervision_set_map_func(mapRGB);
|
||||
textClear();
|
||||
return;
|
||||
}
|
||||
case MMOPTION_SELECTOR: handleFileMenu(); return;
|
||||
case MMOPTION_OPTIONS: handleOptionsMenu(); textClear(); return;
|
||||
case MMOPTION_SAVESTATE: {
|
||||
gp2x_video_RGB_flip(0);
|
||||
supervision_save_state(romname,saveSlot);
|
||||
sync();
|
||||
sleep(1);
|
||||
textClear();
|
||||
return;
|
||||
}
|
||||
case MMOPTION_LOADSTATE: {
|
||||
gp2x_video_RGB_flip(0);
|
||||
supervision_load_state(romname,saveSlot);
|
||||
sleep(1);
|
||||
textClear();
|
||||
return;
|
||||
}
|
||||
case MMOPTION_EXIT: exitMenu(); break;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
/*if(pad & GP2X_B) {
|
||||
textClear();
|
||||
return;
|
||||
}*/
|
||||
|
||||
if(menuOption < 0) menuOption = 0;
|
||||
if(menuOption > 6) menuOption = 6;
|
||||
|
||||
if(saveSlot < 0) saveSlot = 0;
|
||||
if(saveSlot > 9) saveSlot = 9;
|
||||
|
||||
while(pad == gp2x_joystick_read(0));
|
||||
pad = gp2x_joystick_read(0);
|
||||
|
||||
textClear();
|
||||
}
|
||||
}
|
||||
|
||||
void CPUSetting(int speed)
|
||||
{
|
||||
volatile unsigned short *value;
|
||||
unsigned short mdiv = 0;
|
||||
unsigned short pdiv = 3;
|
||||
unsigned short scale = 0;
|
||||
unsigned short wrt;
|
||||
static int last_speed = -1;
|
||||
int adjusted;
|
||||
int mem_fd;
|
||||
|
||||
if(speed == last_speed)
|
||||
return;
|
||||
|
||||
mdiv = (pdiv * speed*1000*1000) / SYS_CLK_FREQ;
|
||||
adjusted = (mdiv * SYS_CLK_FREQ) / (pdiv * 1000*1000);
|
||||
mdiv = ((mdiv-8)<<8) & 0xff00;
|
||||
pdiv = ((pdiv-2)<<2) & 0xfc;
|
||||
scale &= 3;
|
||||
wrt = mdiv | pdiv | scale;
|
||||
|
||||
mem_fd = open("/dev/mem", O_RDWR|O_SYNC);
|
||||
if(mem_fd > 0) {
|
||||
value = (unsigned short *) mmap( 0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, IOBASE );
|
||||
if(value) {
|
||||
value[FPLLSETVREG] = wrt;
|
||||
printf ("Clock Adjust : %d MHz(%d MHz)\n", speed, adjusted);
|
||||
//INI_WriteInt("system", "clock", speed);
|
||||
last_speed = speed;
|
||||
munmap((void*)value, 0x10000);
|
||||
}
|
||||
close(mem_fd);
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __MENUES_H__
|
||||
#define __MENUES_H__
|
||||
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "minimal.h"
|
||||
|
||||
extern unsigned short *screen16;
|
||||
|
||||
// Resume
|
||||
#define RESIZE() \
|
||||
if(currentConfig.videoMode==2) \
|
||||
gp2x_video_RGB_setscaling(160, 160); \
|
||||
else \
|
||||
gp2x_video_RGB_setscaling(320, 240)
|
||||
|
||||
// Clear
|
||||
#define textClear() \
|
||||
gp2x_memset(screen16, 0, 320*240*2); \
|
||||
gp2x_video_RGB_flip(0); \
|
||||
gp2x_memset(screen16, 0, 320*240*2); \
|
||||
gp2x_video_RGB_flip(0)
|
||||
#define strcasestr(x, y) (strcasecmp(&x[strlen(x) - strlen(y)], y))
|
||||
// Directory Constants
|
||||
typedef enum {FT_NONE, FT_FILE, FT_DIR} FILE_TYPE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char fName[256];
|
||||
FILE_TYPE fType;
|
||||
BOOL isRunable;
|
||||
|
||||
} FileEntry, *pFileEntry;
|
||||
|
||||
extern FileEntry FileList[1024];
|
||||
extern uint32 fileCounter;
|
||||
extern const char *romname;
|
||||
|
||||
typedef struct {
|
||||
char lastRomDir[MAXPATHLEN];
|
||||
unsigned char videoMode;
|
||||
unsigned char show_fps;
|
||||
unsigned char enable_sound;
|
||||
unsigned short SoundRate;
|
||||
unsigned char Frameskip;
|
||||
unsigned char CPUclock;
|
||||
unsigned char volume;
|
||||
} currentConfig_t;
|
||||
|
||||
extern currentConfig_t currentConfig;
|
||||
|
||||
void handleFileMenu(void);
|
||||
void handleMainMenu(void);
|
||||
void handleOptionsMenu(void);
|
||||
|
||||
void getRunDir(void);
|
||||
void emu_ReadConfig(void);
|
||||
void emu_WriteConfig(void);
|
||||
|
||||
#endif
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 ARM Ltd
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the company may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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 THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Adapted for uClibc from NetBSD strcmp.S, version 1.3 2003/04/05
|
||||
* by Erik Andersen <andersen@codepoet.org>
|
||||
*/
|
||||
|
||||
.text
|
||||
.global strcmp;
|
||||
.type strcmp,%function
|
||||
.align 4; \
|
||||
|
||||
strcmp:
|
||||
1:
|
||||
ldrb r2, [r0], #1
|
||||
ldrb r3, [r1], #1
|
||||
cmp r2, #1
|
||||
cmpcs r2, r3
|
||||
beq 1b
|
||||
sub r0, r2, r3
|
||||
mov pc, lr
|
||||
|
||||
.weak strcoll;
|
||||
strcoll = strcmp
|
||||
|
@ -1,60 +0,0 @@
|
||||
/* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Code contributed by Matthew Wilcox <willy@odie.barnet.ac.uk>
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* size_t strlen(const char *S)
|
||||
* entry: r0 -> string
|
||||
* exit: r0 = len
|
||||
*/
|
||||
|
||||
.text
|
||||
.global strlen;
|
||||
.type strlen,%function
|
||||
.align 4; \
|
||||
|
||||
strlen:
|
||||
bic r1, r0, $3 @ addr of word containing first byte
|
||||
ldr r2, [r1], $4 @ get the first word
|
||||
ands r3, r0, $3 @ how many bytes are duff?
|
||||
rsb r0, r3, $0 @ get - that number into counter.
|
||||
beq Laligned @ skip into main check routine if no
|
||||
@ more
|
||||
orr r2, r2, $0x000000ff @ set this byte to non-zero
|
||||
subs r3, r3, $1 @ any more to do?
|
||||
orrgt r2, r2, $0x0000ff00 @ if so, set this byte
|
||||
subs r3, r3, $1 @ more?
|
||||
orrgt r2, r2, $0x00ff0000 @ then set.
|
||||
Laligned: @ here, we have a word in r2. Does it
|
||||
tst r2, $0x000000ff @ contain any zeroes?
|
||||
tstne r2, $0x0000ff00 @
|
||||
tstne r2, $0x00ff0000 @
|
||||
tstne r2, $0xff000000 @
|
||||
addne r0, r0, $4 @ if not, the string is 4 bytes longer
|
||||
ldrne r2, [r1], $4 @ and we continue to the next word
|
||||
bne Laligned @
|
||||
Llastword: @ drop through to here once we find a
|
||||
tst r2, $0x000000ff @
|
||||
addne r0, r0, $1 @
|
||||
tstne r2, $0x0000ff00 @ and add up to 3 bytes on to it
|
||||
addne r0, r0, $1 @
|
||||
tstne r2, $0x00ff0000 @ (if first three all non-zero, 4th
|
||||
addne r0, r0, $1 @ must be zero)
|
||||
mov pc,lr
|
||||
|
||||
.size strlen,.-strlen;
|
||||
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 ARM Ltd
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the company may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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 THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Adapted for uClibc from NetBSD strncmp.S, version 1.2 2003/04/05
|
||||
* by Erik Andersen <andersen@codepoet.org>
|
||||
*/
|
||||
|
||||
.text
|
||||
.global strncmp;
|
||||
.type strncmp,%function
|
||||
.align 4; \
|
||||
|
||||
strncmp:
|
||||
/* if ((len - 1) < 0) return 0 */
|
||||
subs r2, r2, #1
|
||||
movmi r0, #0
|
||||
movmi pc, lr
|
||||
|
||||
/* ip == last src address to compare */
|
||||
add ip, r0, r2
|
||||
1:
|
||||
ldrb r2, [r0], #1
|
||||
ldrb r3, [r1], #1
|
||||
cmp ip, r0
|
||||
cmpcs r2, #1
|
||||
cmpcs r2, r3
|
||||
beq 1b
|
||||
sub r0, r2, r3
|
||||
mov pc, lr
|
@ -1,148 +0,0 @@
|
||||
#include <nds.h>
|
||||
#include <fat.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../common/supervision.h"
|
||||
|
||||
uint8 *buffer;
|
||||
uint32 bufferSize = 0;
|
||||
uint16 screenBuffer[160 * 160];
|
||||
|
||||
int LoadROM(const char *filename)
|
||||
{
|
||||
if (buffer != NULL) {
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
FILE *romfile = fopen(filename, "rb");
|
||||
if (romfile == NULL) {
|
||||
//printf("fopen(): Unable to open file!\n");
|
||||
return 1;
|
||||
}
|
||||
fseek(romfile, 0, SEEK_END);
|
||||
bufferSize = ftell(romfile);
|
||||
fseek(romfile, 0, SEEK_SET);
|
||||
|
||||
buffer = (uint8 *)malloc(bufferSize);
|
||||
|
||||
fread(buffer, bufferSize, 1, romfile);
|
||||
|
||||
if (fclose(romfile) == EOF) {
|
||||
//printf("fclose(): Unable to close file!\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InitVideo(void)
|
||||
{
|
||||
powerOn(POWER_ALL); // POWER_ALL_2D
|
||||
|
||||
//irqInit(); // ARM7
|
||||
//irqSet(IRQ_VBLANK, 0);
|
||||
|
||||
videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
|
||||
// videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
|
||||
|
||||
vramSetPrimaryBanks(VRAM_A_MAIN_BG_0x06000000, VRAM_B_LCD,
|
||||
VRAM_C_SUB_BG, VRAM_D_LCD);
|
||||
|
||||
// Draw chessboard on second screen
|
||||
// uint16* map0 = (uint16*)SCREEN_BASE_BLOCK_SUB(1);
|
||||
// REG_BG0CNT_SUB = BG_COLOR_256 | (1 << MAP_BASE_SHIFT);
|
||||
// BG_PALETTE_SUB[0] = RGB15(10,10,10);
|
||||
// BG_PALETTE_SUB[1] = RGB15( 0,16, 0);
|
||||
// for (int iy = 0; iy < 24; iy++) {
|
||||
// for (int ix = 0; ix < 32; ix++) {
|
||||
// map0[iy * 32 + ix] = (ix ^ iy) & 1;
|
||||
// }
|
||||
// }
|
||||
// for (int i = 0; i < 64 / 2; i++) {
|
||||
// BG_GFX_SUB[i+32] = 0x0101;
|
||||
// }
|
||||
|
||||
REG_BG3CNT = BG_BMP16_256x256;
|
||||
REG_BG3PA = 1 << 8;
|
||||
REG_BG3PB = 0; // BG SCALING X
|
||||
REG_BG3PC = 0; // BG SCALING Y
|
||||
REG_BG3PD = 1 << 8;
|
||||
REG_BG3X = -48 * 256;
|
||||
REG_BG3Y = -16 * 256;
|
||||
}
|
||||
|
||||
void CheckKeys(void)
|
||||
{
|
||||
scanKeys();
|
||||
uint32 keys = keysHeld();
|
||||
|
||||
uint8 controls_state = 0;
|
||||
if (keys & KEY_RIGHT ) controls_state|=0x01;
|
||||
if (keys & KEY_LEFT ) controls_state|=0x02;
|
||||
if (keys & KEY_DOWN ) controls_state|=0x04;
|
||||
if (keys & KEY_UP ) controls_state|=0x08;
|
||||
if (keys & KEY_B ) controls_state|=0x10;
|
||||
if (keys & KEY_A ) controls_state|=0x20;
|
||||
if (keys & KEY_SELECT) controls_state|=0x40;
|
||||
if (keys & KEY_START ) controls_state|=0x80;
|
||||
supervision_set_input(controls_state);
|
||||
|
||||
if (keys & KEY_L && keys & KEY_LEFT)
|
||||
supervision_set_color_scheme(0);
|
||||
if (keys & KEY_L && keys & KEY_RIGHT)
|
||||
supervision_set_color_scheme(1);
|
||||
if (keys & KEY_L && keys & KEY_UP)
|
||||
supervision_set_color_scheme(2);
|
||||
if (keys & KEY_L && keys & KEY_DOWN)
|
||||
supervision_set_color_scheme(3);
|
||||
}
|
||||
|
||||
void FailedLoop(void)
|
||||
{
|
||||
while (true) {
|
||||
swiWaitForVBlank();
|
||||
scanKeys();
|
||||
if (keysDown() & KEY_START)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
consoleDemoInit();
|
||||
|
||||
if (fatInitDefault()) {
|
||||
InitVideo();
|
||||
iprintf("Potator NDS\n");
|
||||
supervision_init();
|
||||
if (LoadROM("fat:/test.sv") == 1 && LoadROM("fat:/sv/test.sv") == 1) {
|
||||
iprintf("Unable to open ROM: test.sv\n");
|
||||
FailedLoop();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
iprintf("fatInitDefault() failure\n");
|
||||
FailedLoop();
|
||||
return 1;
|
||||
}
|
||||
|
||||
supervision_load(buffer, bufferSize);
|
||||
|
||||
while (true) {
|
||||
CheckKeys();
|
||||
|
||||
supervision_exec(screenBuffer, FALSE);
|
||||
|
||||
for (int j = 0; j < 160; j++) {
|
||||
// Copy frame buffer to screen
|
||||
dmaCopyWordsAsynch(3, screenBuffer + (j * 160), BG_GFX + (j * 256), 160 * 2);
|
||||
}
|
||||
}
|
||||
supervision_done();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
TARGET = PotatorPSP
|
||||
SVROOT = ../../
|
||||
|
||||
OBJS = \
|
||||
main.o \
|
||||
callbacks.o \
|
||||
vram.o \
|
||||
$(SVROOT)common/controls.o \
|
||||
$(SVROOT)common/gpu.o \
|
||||
$(SVROOT)common/memorymap.o \
|
||||
$(SVROOT)common/sound.o \
|
||||
$(SVROOT)common/timer.o \
|
||||
$(SVROOT)common/watara.o \
|
||||
$(SVROOT)common/m6502/m6502.o
|
||||
|
||||
INCDIR = $(SVROOT)common $(SVROOT)common/m6502
|
||||
|
||||
CFLAGS = -G0 -Wall -O2 -DPERFORMANCE -DSV_USE_FLOATS
|
||||
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti $(INCLUDE)
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
LIBDIR =
|
||||
LDFLAGS =
|
||||
LIBS= -lintraFont \
|
||||
-lpspgu -lpspaudiolib -lpspaudio -lpsppower -lpsprtc -lm
|
||||
|
||||
EXTRA_TARGETS = EBOOT.PBP
|
||||
PSP_EBOOT_TITLE = Potator PSP
|
||||
PSP_EBOOT_ICON = icon0.png
|
||||
|
||||
PSPSDK=$(shell psp-config --pspsdk-path)
|
||||
include $(PSPSDK)/lib/build.mak
|
@ -1,38 +0,0 @@
|
||||
#include <pspkernel.h>
|
||||
|
||||
static int exitRequest = 0;
|
||||
|
||||
int running()
|
||||
{
|
||||
return !exitRequest;
|
||||
}
|
||||
|
||||
static int exitCallback(int arg1, int arg2, void *common)
|
||||
{
|
||||
exitRequest = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int callbackThread(SceSize args, void *argp)
|
||||
{
|
||||
int cbid;
|
||||
|
||||
cbid = sceKernelCreateCallback("Exit Callback", exitCallback, NULL);
|
||||
sceKernelRegisterExitCallback(cbid);
|
||||
|
||||
sceKernelSleepThreadCB();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setupCallbacks(void)
|
||||
{
|
||||
int thid = 0;
|
||||
|
||||
thid = sceKernelCreateThread("update_thread", callbackThread, 0x11, 0xFA0, 0, NULL);
|
||||
if(thid >= 0) {
|
||||
sceKernelStartThread(thid, 0, 0);
|
||||
}
|
||||
|
||||
return thid;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
#ifndef common_callbacks_h
|
||||
#define common_callbacks_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int running();
|
||||
int setupCallbacks(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Binary file not shown.
Before Width: | Height: | Size: 6.5 KiB |
1025
platform/PSP/main.c
1025
platform/PSP/main.c
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
||||
#include "vram.h"
|
||||
|
||||
#include <pspge.h>
|
||||
#include <pspgu.h>
|
||||
|
||||
static unsigned int staticOffset = 0;
|
||||
|
||||
static unsigned int getMemorySize(unsigned int width, unsigned int height, unsigned int psm)
|
||||
{
|
||||
switch (psm)
|
||||
{
|
||||
case GU_PSM_T4:
|
||||
return (width * height) >> 1;
|
||||
|
||||
case GU_PSM_T8:
|
||||
return width * height;
|
||||
|
||||
case GU_PSM_5650:
|
||||
case GU_PSM_5551:
|
||||
case GU_PSM_4444:
|
||||
case GU_PSM_T16:
|
||||
return 2 * width * height;
|
||||
|
||||
case GU_PSM_8888:
|
||||
case GU_PSM_T32:
|
||||
return 4 * width * height;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void* getStaticVramBuffer(unsigned int width, unsigned int height, unsigned int psm)
|
||||
{
|
||||
unsigned int memSize = getMemorySize(width, height, psm);
|
||||
void* result = (void*)staticOffset;
|
||||
staticOffset += memSize;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void* getStaticVramTexture(unsigned int width, unsigned int height, unsigned int psm)
|
||||
{
|
||||
void* result = getStaticVramBuffer(width, height, psm);
|
||||
return (void*)(((unsigned int)result) + ((unsigned int)sceGeEdramGetAddr()));
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#ifndef common_vram_h
|
||||
#define common_vram_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
The following are a few helperfunctions to help manage vram in gu-examples.
|
||||
Do not use for your own code, it's better you manage it in your own way.
|
||||
*/
|
||||
|
||||
/* make a static allocation of vram memory and return pointer relative to vram start */
|
||||
void* getStaticVramBuffer(unsigned int width, unsigned int height, unsigned int psm);
|
||||
/* make a static allocation of vram memory and return absolute pointer */
|
||||
void* getStaticVramTexture(unsigned int width, unsigned int height, unsigned int psm);
|
||||
|
||||
// the following is not yet implemented
|
||||
/*
|
||||
void beginDynamicVramFrame();
|
||||
void endDynamicVramFrame();
|
||||
|
||||
void* getDynamicVramBuffer(unsigned int width, unsigned int height, unsigned int psm);
|
||||
void* getDynamicVramTexture(unsigned int width, unsigned int height, unsigned int psm);
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,372 +0,0 @@
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "../../common/supervision.h"
|
||||
|
||||
#define VERSION "1.0.1"
|
||||
|
||||
#define OR_DIE(cond) \
|
||||
if (cond) { \
|
||||
fprintf(stderr, "[Error] SDL: %s\n", SDL_GetError()); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define UPDATE_RATE 60
|
||||
|
||||
SDL_bool done = SDL_FALSE;
|
||||
|
||||
uint8_t *buffer;
|
||||
uint32_t bufferSize = 0;
|
||||
|
||||
uint16_t screenBuffer[SV_W * SV_H];
|
||||
SDL_Surface *PrimarySurface;
|
||||
int windowScale = 4;
|
||||
int windowWidth = 0;
|
||||
int windowHeight = 0;
|
||||
int maxWindowWidth = 0;
|
||||
int maxWindowHeight = 0;
|
||||
SDL_bool isFullscreen = SDL_FALSE;
|
||||
void ToggleFullscreen(void);
|
||||
void NextPalette(void);
|
||||
void UpdateWindowSize(void);
|
||||
void IncreaseWindowSize(void);
|
||||
void DecreaseWindowSize(void);
|
||||
int currentGhosting = 0;
|
||||
void IncreaseGhosting(void);
|
||||
void DecreaseGhosting(void);
|
||||
|
||||
char romName[64];
|
||||
void SetRomName(const char *path)
|
||||
{
|
||||
const char *p = path + strlen(path);
|
||||
while (p != path) {
|
||||
if (*p == '\\' || *p == '/') {
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
p--;
|
||||
}
|
||||
strncpy(romName, p, sizeof(romName));
|
||||
romName[sizeof(romName) - 1] = '\0';
|
||||
}
|
||||
|
||||
int LoadROM(const char *filename)
|
||||
{
|
||||
if (buffer != NULL) {
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
SDL_RWops *romfile = SDL_RWFromFile(filename, "rb");
|
||||
if (romfile == NULL) {
|
||||
fprintf(stderr, "SDL_RWFromFile(): Unable to open file! (%s)\n", filename);
|
||||
return 1;
|
||||
}
|
||||
SDL_RWseek(romfile, 0, RW_SEEK_END);
|
||||
bufferSize = (uint32_t)SDL_RWtell(romfile);
|
||||
SDL_RWseek(romfile, 0, RW_SEEK_SET);
|
||||
buffer = (uint8_t *)malloc(bufferSize);
|
||||
SDL_RWread(romfile, buffer, bufferSize, 1);
|
||||
if (SDL_RWclose(romfile) != 0) {
|
||||
fprintf(stderr, "SDL_RWclose(): Unable to close file! (%s)\n", filename);
|
||||
return 1;
|
||||
}
|
||||
SetRomName(filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PollEvents(void)
|
||||
{
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
done = SDL_TRUE;
|
||||
}
|
||||
else if (event.type == SDL_KEYDOWN) {
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_RETURN:
|
||||
ToggleFullscreen();
|
||||
break;
|
||||
case SDLK_TAB:
|
||||
supervision_load(buffer, bufferSize);
|
||||
break;
|
||||
case SDLK_1:
|
||||
supervision_save_state(romName, 0);
|
||||
break;
|
||||
case SDLK_2:
|
||||
supervision_load_state(romName, 0);
|
||||
break;
|
||||
case SDLK_p:
|
||||
NextPalette();
|
||||
break;
|
||||
case SDLK_MINUS:
|
||||
DecreaseWindowSize();
|
||||
break;
|
||||
case SDLK_EQUALS:
|
||||
IncreaseWindowSize();
|
||||
break;
|
||||
case SDLK_LEFTBRACKET:
|
||||
DecreaseGhosting();
|
||||
break;
|
||||
case SDLK_RIGHTBRACKET:
|
||||
IncreaseGhosting();
|
||||
break;
|
||||
case SDLK_m:
|
||||
SDL_PauseAudio(SDL_GetAudioStatus() == SDL_AUDIO_PLAYING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (event.type == SDL_VIDEORESIZE) {
|
||||
if (!isFullscreen) {
|
||||
int mins = event.resize.w < event.resize.h ? event.resize.w : event.resize.h;
|
||||
windowScale = mins / SV_W;
|
||||
UpdateWindowSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleInput(void)
|
||||
{
|
||||
uint8_t controls_state = 0;
|
||||
uint8_t *keystate = SDL_GetKeyState(NULL);
|
||||
|
||||
if (keystate[SDLK_RIGHT]) controls_state |= 0x01;
|
||||
if (keystate[SDLK_LEFT]) controls_state |= 0x02;
|
||||
if (keystate[SDLK_DOWN]) controls_state |= 0x04;
|
||||
if (keystate[SDLK_UP]) controls_state |= 0x08;
|
||||
if (keystate[SDLK_x]) controls_state |= 0x10;
|
||||
if (keystate[SDLK_c]) controls_state |= 0x20;
|
||||
if (keystate[SDLK_z]) controls_state |= 0x40;
|
||||
if (keystate[SDLK_SPACE]) controls_state |= 0x80;
|
||||
|
||||
supervision_set_input(controls_state);
|
||||
}
|
||||
|
||||
void Draw()
|
||||
{
|
||||
SDL_LockSurface(PrimarySurface);
|
||||
uint32_t *pDest = (uint32_t *)PrimarySurface->pixels;
|
||||
uint16_t *pSrc = screenBuffer;
|
||||
|
||||
if (isFullscreen) {
|
||||
// Center
|
||||
pDest += (windowWidth - SV_W * windowScale) / 2 + (windowHeight - SV_H * windowScale) / 2 * windowWidth;
|
||||
}
|
||||
for (int y = 0; y < SV_H; y++) {
|
||||
for (int x = 0; x < SV_W; x++) {
|
||||
// RGB555 (R: 0-4 bits) -> BGRA8888 (SDL 32-bit)
|
||||
// or SDL_MapRGB()
|
||||
uint32_t color = ((*pSrc & 0x7C00) >> (10 - 3))
|
||||
| ((*pSrc & 0x03E0) << ( 3 + 3))
|
||||
| ((*pSrc & 0x001F) << (16 + 3));
|
||||
// -> SDL 16-bit
|
||||
//((*pSrc & 0x7C00) >> 10) | ((*pSrc & 0x03E0) << 1) | ((*pSrc & 0x001F) << 11);
|
||||
pSrc++;
|
||||
for (int i = y * windowScale; i < windowScale + y * windowScale; i++) {
|
||||
for (int j = x * windowScale; j < windowScale + x * windowScale; j++) {
|
||||
pDest[i * windowWidth + j] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(PrimarySurface);
|
||||
SDL_Flip(PrimarySurface);
|
||||
}
|
||||
|
||||
// Audio
|
||||
void AudioCallback(void *userdata, uint8_t *stream, int len)
|
||||
{
|
||||
supervision_update_sound(stream, len);
|
||||
}
|
||||
|
||||
static double nextTime;
|
||||
void InitCounter(void)
|
||||
{
|
||||
nextTime = SDL_GetTicks() + 1000.0 / UPDATE_RATE;
|
||||
}
|
||||
|
||||
void Wait(void)
|
||||
{
|
||||
uint32_t now = SDL_GetTicks();
|
||||
uint32_t wait = 0;
|
||||
if (nextTime <= now) {
|
||||
if (now - nextTime > 100.0) {
|
||||
nextTime = now;
|
||||
}
|
||||
}
|
||||
else {
|
||||
wait = (uint32_t)nextTime - now;
|
||||
}
|
||||
SDL_Delay(wait);
|
||||
nextTime += 1000.0 / UPDATE_RATE;
|
||||
}
|
||||
|
||||
// SDL Fix
|
||||
#ifdef main
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
OR_DIE(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0);
|
||||
|
||||
char title[64] = { 0 };
|
||||
snprintf(title, sizeof(title), "Potator (SDL1) %s (core: %u.%u.%u)",
|
||||
VERSION, SV_CORE_VERSION_MAJOR, SV_CORE_VERSION_MINOR, SV_CORE_VERSION_PATCH);
|
||||
SDL_WM_SetCaption(title, NULL);
|
||||
|
||||
UpdateWindowSize();
|
||||
SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
|
||||
maxWindowWidth = modes[0]->w;
|
||||
maxWindowHeight = modes[0]->h;
|
||||
|
||||
SDL_FillRect(PrimarySurface, NULL, 0);
|
||||
|
||||
SDL_AudioSpec audio_spec;
|
||||
memset(&audio_spec, 0, sizeof(audio_spec));
|
||||
audio_spec.freq = SV_SAMPLE_RATE;
|
||||
audio_spec.channels = 2;
|
||||
audio_spec.samples = 512;
|
||||
audio_spec.format = AUDIO_S8;
|
||||
audio_spec.callback = AudioCallback;
|
||||
audio_spec.userdata = NULL;
|
||||
OR_DIE(SDL_OpenAudio(&audio_spec, NULL) < 0);
|
||||
|
||||
printf("# Controls\n\
|
||||
Right: Right\n\
|
||||
Left: Left\n\
|
||||
Down: Down\n\
|
||||
Up: Up\n\
|
||||
B: X\n\
|
||||
A: C\n\
|
||||
Select: Z\n\
|
||||
Start: Space\n\
|
||||
Toggle Fullscreen: Return\n\
|
||||
Reset: Tab\n\
|
||||
Save State: 1\n\
|
||||
Load State: 2\n\
|
||||
Next Palette: P\n\
|
||||
Decrease Window Size: -\n\
|
||||
Increase Window Size: =\n\
|
||||
Decrease Ghosting: [\n\
|
||||
Increase Ghosting: ]\n\
|
||||
Mute Audio: M\n");
|
||||
|
||||
supervision_init();
|
||||
|
||||
if (LoadROM(argc <= 1 ? "rom.sv" : argv[1]) == 0) {
|
||||
done = !supervision_load(buffer, bufferSize);
|
||||
}
|
||||
else {
|
||||
done = SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
InitCounter();
|
||||
while (!done) {
|
||||
PollEvents();
|
||||
HandleInput();
|
||||
supervision_exec(screenBuffer, FALSE);
|
||||
Draw();
|
||||
Wait();
|
||||
}
|
||||
supervision_done();
|
||||
|
||||
SDL_CloseAudio();
|
||||
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
#define VIDEOMODE_FLAGS (SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE)
|
||||
|
||||
void ToggleFullscreen(void)
|
||||
{
|
||||
static int lastWidth = 0;
|
||||
static int lastHeight = 0;
|
||||
static int lastScale = 0;
|
||||
|
||||
uint32_t flags = VIDEOMODE_FLAGS;
|
||||
if (isFullscreen) {
|
||||
windowWidth = lastWidth;
|
||||
windowHeight = lastHeight;
|
||||
windowScale = lastScale;
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
}
|
||||
else {
|
||||
lastWidth = windowWidth;
|
||||
lastHeight = windowHeight;
|
||||
lastScale = windowScale;
|
||||
|
||||
flags |= SDL_FULLSCREEN;
|
||||
windowScale = maxWindowHeight / SV_H;
|
||||
windowWidth = maxWindowWidth;
|
||||
windowHeight = maxWindowHeight;
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
}
|
||||
PrimarySurface = SDL_SetVideoMode(windowWidth, windowHeight, 32, flags);
|
||||
OR_DIE(PrimarySurface == NULL);
|
||||
|
||||
isFullscreen = !isFullscreen;
|
||||
}
|
||||
|
||||
void NextPalette(void)
|
||||
{
|
||||
static int currentPalette = 0;
|
||||
currentPalette = (currentPalette + 1) % SV_COLOR_SCHEME_COUNT;
|
||||
supervision_set_color_scheme(currentPalette);
|
||||
}
|
||||
|
||||
void UpdateWindowSize(void)
|
||||
{
|
||||
windowWidth = SV_W * windowScale;
|
||||
windowHeight = SV_H * windowScale;
|
||||
PrimarySurface = SDL_SetVideoMode(windowWidth, windowHeight, 32, VIDEOMODE_FLAGS);
|
||||
OR_DIE(PrimarySurface == NULL);
|
||||
}
|
||||
|
||||
void IncreaseWindowSize(void)
|
||||
{
|
||||
if (isFullscreen)
|
||||
return;
|
||||
|
||||
if (SV_W * (windowScale + 1) <= maxWindowWidth && SV_H * (windowScale + 1) <= maxWindowHeight) {
|
||||
windowScale++;
|
||||
UpdateWindowSize();
|
||||
}
|
||||
}
|
||||
|
||||
void DecreaseWindowSize(void)
|
||||
{
|
||||
if (isFullscreen)
|
||||
return;
|
||||
|
||||
if (windowScale > 1) {
|
||||
windowScale--;
|
||||
UpdateWindowSize();
|
||||
}
|
||||
}
|
||||
|
||||
void IncreaseGhosting(void)
|
||||
{
|
||||
if (currentGhosting < SV_GHOSTING_MAX) {
|
||||
currentGhosting++;
|
||||
supervision_set_ghosting(currentGhosting);
|
||||
}
|
||||
}
|
||||
|
||||
void DecreaseGhosting(void)
|
||||
{
|
||||
if (currentGhosting > 0) {
|
||||
currentGhosting--;
|
||||
supervision_set_ghosting(currentGhosting);
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
project(PotatorSDL2)
|
||||
|
||||
find_package(SDL2 REQUIRED)
|
||||
|
||||
include_directories(${SDL2_INCLUDE_DIR})
|
||||
|
||||
add_executable(PotatorSDL2
|
||||
main.c
|
||||
../../common/m6502/m6502.c
|
||||
../../common/m6502/m6502.h
|
||||
../../common/m6502/tables.h
|
||||
../../common/controls.c
|
||||
../../common/controls.h
|
||||
../../common/gpu.c
|
||||
../../common/gpu.h
|
||||
../../common/memorymap.c
|
||||
../../common/memorymap.h
|
||||
../../common/sound.c
|
||||
../../common/sound.h
|
||||
../../common/supervision.h
|
||||
../../common/timer.c
|
||||
../../common/timer.h
|
||||
../../common/types.h
|
||||
../../common/watara.c
|
||||
)
|
||||
|
||||
target_link_libraries(PotatorSDL2 ${SDL2_LIBRARY})
|
@ -1,720 +0,0 @@
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
#include "../../common/supervision.h"
|
||||
|
||||
#define VERSION "1.0.3"
|
||||
|
||||
#define OR_DIE(cond) \
|
||||
if (cond) { \
|
||||
fprintf(stderr, "[Error] SDL: %s\n", SDL_GetError()); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
|
||||
|
||||
#define UPDATE_RATE 60
|
||||
|
||||
typedef enum {
|
||||
MENUSTATE_NONE,
|
||||
MENUSTATE_DROP_ROM,
|
||||
MENUSTATE_EMULATION,
|
||||
MENUSTATE_PAUSE,
|
||||
MENUSTATE_SET_KEY
|
||||
} MenuState;
|
||||
|
||||
SDL_bool done = SDL_FALSE;
|
||||
uint16_t screenBuffer[SV_W * SV_H];
|
||||
SDL_Window *sdlScreen;
|
||||
SDL_Renderer *sdlRenderer;
|
||||
SDL_Texture *sdlTexture;
|
||||
|
||||
uint8_t *romBuffer;
|
||||
uint32_t romBufferSize = 0;
|
||||
|
||||
SDL_GameController *controller = NULL;
|
||||
|
||||
SDL_bool IsFullscreen(void);
|
||||
void ToggleFullscreen(void);
|
||||
uint64_t startCounter = 0;
|
||||
SDL_bool isRefreshRate60 = SDL_FALSE;
|
||||
void InitCounter(void);
|
||||
SDL_bool NeedUpdate(void);
|
||||
void DrawDropROM(void);
|
||||
|
||||
int nextMenuState = 0;
|
||||
#define MENUSTATE_STACK_SIZE 4
|
||||
MenuState menuStates[MENUSTATE_STACK_SIZE];
|
||||
void PushMenuState(MenuState state);
|
||||
void PopMenuState(void);
|
||||
MenuState GetMenuState(void);
|
||||
|
||||
void Reset(void);
|
||||
|
||||
int currentPalette = 0;
|
||||
void NextPalette(void);
|
||||
|
||||
int windowScale = 4;
|
||||
void IncreaseWindowSize(void);
|
||||
void DecreaseWindowSize(void);
|
||||
|
||||
void SaveState(void);
|
||||
void LoadState(void);
|
||||
|
||||
int audioVolume = SDL_MIX_MAXVOLUME;
|
||||
int lastVolume = -1;
|
||||
void SetVolume(int volume);
|
||||
void MuteAudio(void);
|
||||
|
||||
int currentGhosting = 0;
|
||||
void IncreaseGhosting(void);
|
||||
void DecreaseGhosting(void);
|
||||
void SetGhosting(int frameCount);
|
||||
|
||||
char *keysNames[] = {
|
||||
"Right",
|
||||
"Left",
|
||||
"Down",
|
||||
"Up",
|
||||
"B",
|
||||
"A",
|
||||
"Select",
|
||||
"Start",
|
||||
|
||||
"Toggle Fullscreen",
|
||||
"Reset",
|
||||
"Save State",
|
||||
"Load State",
|
||||
"Next Palette",
|
||||
"Decrease Window Size",
|
||||
"Increase Window Size",
|
||||
"Decrease Ghosting",
|
||||
"Increase Ghosting",
|
||||
"Mute Audio",
|
||||
};
|
||||
// Warning: Emscripten and Android use default values
|
||||
int keysMapping[] = {
|
||||
SDL_SCANCODE_RIGHT,
|
||||
SDL_SCANCODE_LEFT,
|
||||
SDL_SCANCODE_DOWN,
|
||||
SDL_SCANCODE_UP,
|
||||
SDL_SCANCODE_X, // B
|
||||
SDL_SCANCODE_C, // A
|
||||
SDL_SCANCODE_Z, // Select
|
||||
SDL_SCANCODE_SPACE, // Start
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
SDL_SCANCODE_UNKNOWN,
|
||||
#else
|
||||
SDL_SCANCODE_F11,
|
||||
#endif
|
||||
SDL_SCANCODE_TAB,
|
||||
SDL_SCANCODE_1,
|
||||
SDL_SCANCODE_2,
|
||||
SDL_SCANCODE_P,
|
||||
SDL_SCANCODE_MINUS,
|
||||
SDL_SCANCODE_EQUALS,
|
||||
SDL_SCANCODE_LEFTBRACKET,
|
||||
SDL_SCANCODE_RIGHTBRACKET,
|
||||
SDL_SCANCODE_M,
|
||||
};
|
||||
void (*keysFuncs[])(void) = {
|
||||
ToggleFullscreen,
|
||||
Reset,
|
||||
SaveState,
|
||||
LoadState,
|
||||
NextPalette,
|
||||
DecreaseWindowSize,
|
||||
IncreaseWindowSize,
|
||||
DecreaseGhosting,
|
||||
IncreaseGhosting,
|
||||
MuteAudio,
|
||||
};
|
||||
int setButton = -1;
|
||||
void SetKey(int button);
|
||||
|
||||
char romName[64];
|
||||
void SetRomName(const char *path)
|
||||
{
|
||||
const char *p = path + strlen(path);
|
||||
while (p != path) {
|
||||
if (*p == '\\' || *p == '/') {
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
p--;
|
||||
}
|
||||
strncpy(romName, p, sizeof(romName));
|
||||
romName[sizeof(romName) - 1] = '\0';
|
||||
}
|
||||
|
||||
int LoadROM(const char *filename)
|
||||
{
|
||||
if (romBuffer != NULL) {
|
||||
free(romBuffer);
|
||||
romBuffer = NULL;
|
||||
}
|
||||
|
||||
SDL_RWops *romfile = SDL_RWFromFile(filename, "rb");
|
||||
if (romfile == NULL) {
|
||||
fprintf(stderr, "SDL_RWFromFile(): Unable to open file!\n");
|
||||
return 1;
|
||||
}
|
||||
romBufferSize = (uint32_t)SDL_RWsize(romfile);
|
||||
romBuffer = (uint8_t *)malloc(romBufferSize);
|
||||
SDL_RWread(romfile, romBuffer, romBufferSize, 1);
|
||||
if (SDL_RWclose(romfile) != 0) {
|
||||
fprintf(stderr, "SDL_RWclose(): Unable to close file!\n");
|
||||
return 1;
|
||||
}
|
||||
SetRomName(filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ReturnToDropROM(void)
|
||||
{
|
||||
SDL_memset(screenBuffer, 0, sizeof(screenBuffer));
|
||||
while (GetMenuState() != MENUSTATE_NONE) {
|
||||
PopMenuState();
|
||||
}
|
||||
PushMenuState(MENUSTATE_DROP_ROM);
|
||||
SDL_PauseAudio(1);
|
||||
}
|
||||
|
||||
void LoadBuffer(void)
|
||||
{
|
||||
if (!supervision_load(romBuffer, romBufferSize)) {
|
||||
ReturnToDropROM();
|
||||
return;
|
||||
}
|
||||
MenuState prevState = GetMenuState();
|
||||
PopMenuState();
|
||||
PushMenuState(MENUSTATE_EMULATION);
|
||||
if (prevState == MENUSTATE_PAUSE) { // Focus wasn't gained
|
||||
PushMenuState(MENUSTATE_PAUSE);
|
||||
}
|
||||
supervision_set_color_scheme(currentPalette);
|
||||
supervision_set_ghosting(currentGhosting);
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
|
||||
void AudioCallback(void *userdata, uint8_t *stream, int len)
|
||||
{
|
||||
if (GetMenuState() != MENUSTATE_EMULATION) {
|
||||
SDL_memset(stream, ((SDL_AudioSpec*)userdata)->silence, len);
|
||||
return;
|
||||
}
|
||||
|
||||
// U8 to F32
|
||||
supervision_update_sound(stream, len / 4);
|
||||
float *s = (float*)stream;
|
||||
for (int i = len / 4 - 1; i >= 0; i--) {
|
||||
// 45 - max
|
||||
s[i] = stream[i] / 63.0f * audioVolume / (float)SDL_MIX_MAXVOLUME;
|
||||
}
|
||||
|
||||
// Mono
|
||||
//for (int i = 0; i < len / 4; i += 2) {
|
||||
// s[i] = s[i + 1] = (s[i] + s[i + 1]) / 2;
|
||||
//}
|
||||
|
||||
// U8 or S8. Don't use SDL_PauseAudio() with AUDIO_U8
|
||||
/*supervision_update_sound(stream, len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
stream[i] = (uint8_t)((stream[i] << 1) * audioVolume / (float)SDL_MIX_MAXVOLUME) + ((SDL_AudioSpec*)userdata)->silence;
|
||||
}*/
|
||||
}
|
||||
|
||||
void HandleInput(void)
|
||||
{
|
||||
uint8_t controls_state = 0;
|
||||
const uint8_t *keystate = SDL_GetKeyboardState(NULL);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (keystate[keysMapping[i]]) {
|
||||
controls_state |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_GameControllerGetAttached(controller)) {
|
||||
if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) controls_state |= 0x01;
|
||||
if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) controls_state |= 0x02;
|
||||
if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) controls_state |= 0x04;
|
||||
if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_UP)) controls_state |= 0x08;
|
||||
if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_A)) controls_state |= 0x10;
|
||||
if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_X)) controls_state |= 0x20;
|
||||
if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_BACK)) controls_state |= 0x40;
|
||||
if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_START)) controls_state |= 0x80;
|
||||
// 31130/32768 == 0.95
|
||||
if (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) > 31130) controls_state |= 0x01;
|
||||
if (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) < -31130) controls_state |= 0x02;
|
||||
if (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) > 31130) controls_state |= 0x04;
|
||||
if (SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) < -31130) controls_state |= 0x08;
|
||||
}
|
||||
|
||||
supervision_set_input(controls_state);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
char romPath[1024];
|
||||
#endif
|
||||
|
||||
void PollEvents(void)
|
||||
{
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
done = SDL_TRUE;
|
||||
}
|
||||
else if (event.type == SDL_KEYDOWN) {
|
||||
if (GetMenuState() == MENUSTATE_SET_KEY) {
|
||||
if (event.key.keysym.scancode != SDL_SCANCODE_ESCAPE)
|
||||
keysMapping[setButton] = event.key.keysym.scancode;
|
||||
PopMenuState();
|
||||
SDL_PauseAudio(0);
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < COUNT_OF(keysFuncs); i++) {
|
||||
if (keysMapping[i + 8] == event.key.keysym.scancode) {
|
||||
keysFuncs[i]();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (event.key.keysym.scancode == SDL_SCANCODE_RETURN
|
||||
&& (SDL_GetModState() & KMOD_ALT)) {
|
||||
ToggleFullscreen();
|
||||
}
|
||||
if (event.key.keysym.scancode == SDL_SCANCODE_AC_BACK) {
|
||||
#ifdef __ANDROID__
|
||||
supervision_save_state(romPath, 9);
|
||||
#endif
|
||||
done = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
// SDL_CONTROLLERBUTTONDOWN doesn't work
|
||||
else if (event.type == SDL_JOYBUTTONDOWN) {
|
||||
if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_LEFTSHOULDER)) {
|
||||
SaveState();
|
||||
}
|
||||
else if (SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)) {
|
||||
LoadState();
|
||||
}
|
||||
}
|
||||
#ifndef __ANDROID__
|
||||
else if (event.type == SDL_WINDOWEVENT) {
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
if (!IsFullscreen()) {
|
||||
SDL_SetWindowSize(sdlScreen,
|
||||
(event.window.data1 + SV_W / 2) / SV_W * SV_W,
|
||||
(event.window.data2 + SV_H / 2) / SV_H * SV_H);
|
||||
}
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
if (GetMenuState() == MENUSTATE_SET_KEY) PopMenuState();
|
||||
PushMenuState(MENUSTATE_PAUSE);
|
||||
SDL_PauseAudio(1);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
if (GetMenuState() == MENUSTATE_PAUSE) PopMenuState();
|
||||
SDL_PauseAudio(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (event.type == SDL_DROPFILE) {
|
||||
if (LoadROM(event.drop.file) == 0) {
|
||||
LoadBuffer();
|
||||
}
|
||||
else {
|
||||
ReturnToDropROM();
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
// External SD Card isn't writable
|
||||
strncpy(romPath, SDL_AndroidGetExternalStoragePath(), sizeof(romPath));
|
||||
strncat(romPath, "/", sizeof(romPath) - strlen(romPath) - 1);
|
||||
strncat(romPath, romName, sizeof(romPath) - strlen(romPath) - 1);
|
||||
supervision_load_state(romPath, 9);
|
||||
#endif
|
||||
SDL_free(event.drop.file);
|
||||
}
|
||||
else if (event.type == SDL_JOYDEVICEADDED) {
|
||||
if (SDL_IsGameController(event.jdevice.which)) {
|
||||
controller = SDL_GameControllerOpen(event.jdevice.which);
|
||||
if (!controller) {
|
||||
fprintf(stderr, "Could not open gamecontroller %i: %s\n", event.jdevice.which, SDL_GetError());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Loop(void)
|
||||
{
|
||||
PollEvents();
|
||||
|
||||
while (NeedUpdate()) {
|
||||
switch (GetMenuState()) {
|
||||
case MENUSTATE_EMULATION:
|
||||
HandleInput();
|
||||
supervision_exec(screenBuffer, FALSE);
|
||||
break;
|
||||
case MENUSTATE_DROP_ROM:
|
||||
DrawDropROM();
|
||||
break;
|
||||
case MENUSTATE_PAUSE:
|
||||
SDL_Delay(16); // Reduce CPU usage
|
||||
break;
|
||||
case MENUSTATE_SET_KEY:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw
|
||||
SDL_UpdateTexture(sdlTexture, NULL, screenBuffer, SV_W * sizeof(uint16_t));
|
||||
|
||||
SDL_RenderClear(sdlRenderer);
|
||||
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
|
||||
SDL_RenderPresent(sdlRenderer);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
if (done) {
|
||||
emscripten_cancel_main_loop();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
OR_DIE(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0);
|
||||
|
||||
char title[64] = { 0 };
|
||||
snprintf(title, sizeof(title), "Potator (SDL2) %s (core: %u.%u.%u)",
|
||||
VERSION, SV_CORE_VERSION_MAJOR, SV_CORE_VERSION_MINOR, SV_CORE_VERSION_PATCH);
|
||||
sdlScreen = SDL_CreateWindow(title,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SV_W * windowScale, SV_H * windowScale,
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
OR_DIE(sdlScreen == NULL);
|
||||
|
||||
sdlRenderer = SDL_CreateRenderer(sdlScreen, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
OR_DIE(sdlRenderer == NULL);
|
||||
|
||||
SDL_RenderSetLogicalSize(sdlRenderer, SV_W, SV_H);
|
||||
|
||||
sdlTexture = SDL_CreateTexture(sdlRenderer,
|
||||
SDL_PIXELFORMAT_BGR555,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
SV_W, SV_H);
|
||||
OR_DIE(sdlTexture == NULL);
|
||||
|
||||
SDL_AudioSpec audio_spec;
|
||||
SDL_zero(audio_spec);
|
||||
audio_spec.freq = SV_SAMPLE_RATE;
|
||||
audio_spec.channels = 2;
|
||||
audio_spec.samples = 512;
|
||||
audio_spec.format = AUDIO_F32;
|
||||
audio_spec.callback = AudioCallback;
|
||||
audio_spec.userdata = &audio_spec;
|
||||
OR_DIE(SDL_OpenAudio(&audio_spec, NULL) < 0);
|
||||
//SDL_AudioDeviceID devid = SDL_OpenAudioDevice(NULL, 0, &audio_spec, NULL, 0);
|
||||
//OR_DIE(devid == 0);
|
||||
|
||||
printf("# Controls\n");
|
||||
for (int i = 0; i < COUNT_OF(keysNames); i++) {
|
||||
printf("%20s: %s\n", keysNames[i], SDL_GetScancodeName(keysMapping[i]));
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
supervision_init();
|
||||
|
||||
PushMenuState(MENUSTATE_DROP_ROM);
|
||||
if (LoadROM(argc <= 1 ? "rom.sv" : argv[1]) == 0) {
|
||||
LoadBuffer();
|
||||
}
|
||||
|
||||
//SDL_PauseAudio(0);
|
||||
//SDL_PauseAudioDevice(devid, 0);
|
||||
|
||||
InitCounter();
|
||||
#ifdef __EMSCRIPTEN__
|
||||
emscripten_set_main_loop(Loop, 0, 1);
|
||||
#else
|
||||
while (!done) {
|
||||
Loop();
|
||||
}
|
||||
#endif
|
||||
|
||||
supervision_done();
|
||||
|
||||
SDL_CloseAudio();
|
||||
//SDL_CloseAudioDevice(devid);
|
||||
|
||||
SDL_DestroyTexture(sdlTexture);
|
||||
SDL_DestroyRenderer(sdlRenderer);
|
||||
SDL_DestroyWindow(sdlScreen);
|
||||
|
||||
SDL_Quit();
|
||||
#ifdef __ANDROID__
|
||||
// Unload library hack https://stackoverflow.com/a/6509866
|
||||
exit(0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FULLSCREEN_FLAG SDL_WINDOW_FULLSCREEN_DESKTOP
|
||||
|
||||
SDL_bool IsFullscreen(void)
|
||||
{
|
||||
return 0 != (SDL_GetWindowFlags(sdlScreen) & FULLSCREEN_FLAG);
|
||||
}
|
||||
|
||||
void ToggleFullscreen(void)
|
||||
{
|
||||
static int mouseX;
|
||||
static int mouseY;
|
||||
static SDL_bool cursorInWindow = SDL_FALSE;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
return;
|
||||
#endif
|
||||
if (!IsFullscreen()) {
|
||||
SDL_SetWindowFullscreen(sdlScreen, FULLSCREEN_FLAG);
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
int x, y;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
SDL_GetGlobalMouseState(&mouseX, &mouseY);
|
||||
if (x == mouseX && y == mouseY) {
|
||||
cursorInWindow = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SDL_SetWindowFullscreen(sdlScreen, 0);
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
|
||||
// Don't move cursor. Bug?
|
||||
if (cursorInWindow) {
|
||||
SDL_WarpMouseInWindow(sdlScreen, mouseX, mouseY);
|
||||
}
|
||||
else {
|
||||
SDL_WarpMouseGlobal(mouseX, mouseY);
|
||||
}
|
||||
cursorInWindow = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void InitCounter(void)
|
||||
{
|
||||
SDL_DisplayMode current;
|
||||
SDL_GetCurrentDisplayMode(0, ¤t);
|
||||
isRefreshRate60 = (current.refresh_rate == 60);
|
||||
startCounter = SDL_GetPerformanceCounter();
|
||||
}
|
||||
|
||||
SDL_bool NeedUpdate(void)
|
||||
{
|
||||
static double elapsedCounter = 0.0;
|
||||
static SDL_bool result = SDL_FALSE;
|
||||
|
||||
if (isRefreshRate60) {
|
||||
result = !result;
|
||||
}
|
||||
else {
|
||||
// New frame
|
||||
if (!result) {
|
||||
uint64_t now = SDL_GetPerformanceCounter();
|
||||
elapsedCounter += (double)((now - startCounter) * 1000) / SDL_GetPerformanceFrequency();
|
||||
startCounter = now;
|
||||
if (elapsedCounter > 100.0) {
|
||||
elapsedCounter = 0.0;
|
||||
}
|
||||
}
|
||||
result = elapsedCounter >= 1000.0 / UPDATE_RATE;
|
||||
if (result) {
|
||||
elapsedCounter -= 1000.0 / UPDATE_RATE;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void DrawDropROM(void)
|
||||
{
|
||||
static uint8_t fade = 0;
|
||||
char dropRom[] = {
|
||||
"## ### ## ### ### ## ###"
|
||||
"# # # # # # # # # # # # ###"
|
||||
"# # ## # # ### ## # # # #"
|
||||
"### # # ## # # # ## # #"
|
||||
};
|
||||
uint8_t f = (fade < 32) ? fade : 63 - fade;
|
||||
uint16_t color = (f << 0) | (f << 5) | (f << 10);
|
||||
fade = (fade + 1) % 64;
|
||||
|
||||
int width = 28, height = 4;
|
||||
int scale = 4, start = (SV_W - width * scale) / 2 + SV_W * (SV_H - height * scale) / 2;
|
||||
for (int j = 0; j < height * scale; j++) {
|
||||
for (int i = 0; i < width * scale; i++) {
|
||||
if (dropRom[i / scale + width * (j / scale)] == '#')
|
||||
screenBuffer[start + i + SV_W * j] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PushMenuState(MenuState state)
|
||||
{
|
||||
if (nextMenuState >= MENUSTATE_STACK_SIZE) {
|
||||
// Error
|
||||
return;
|
||||
}
|
||||
if (nextMenuState == 0 || (nextMenuState > 0 && menuStates[nextMenuState - 1] != state)) {
|
||||
menuStates[nextMenuState] = state;
|
||||
nextMenuState++;
|
||||
}
|
||||
}
|
||||
|
||||
void PopMenuState(void)
|
||||
{
|
||||
if (nextMenuState > 0)
|
||||
nextMenuState--;
|
||||
}
|
||||
|
||||
MenuState GetMenuState(void)
|
||||
{
|
||||
if (nextMenuState > 0)
|
||||
return menuStates[nextMenuState - 1];
|
||||
return MENUSTATE_NONE;
|
||||
}
|
||||
|
||||
// Emscripten
|
||||
void UploadROM(void *newBuffer, int newBufferSize, const char *fileName)
|
||||
{
|
||||
romBufferSize = newBufferSize;
|
||||
if (romBuffer != NULL) {
|
||||
free(romBuffer);
|
||||
romBuffer = NULL;
|
||||
}
|
||||
romBuffer = (uint8_t *)malloc(romBufferSize);
|
||||
if (romBuffer == NULL) {
|
||||
return;
|
||||
}
|
||||
memcpy(romBuffer, newBuffer, romBufferSize);
|
||||
|
||||
SetRomName(fileName);
|
||||
LoadBuffer();
|
||||
}
|
||||
|
||||
void Reset(void)
|
||||
{
|
||||
if (GetMenuState() == MENUSTATE_EMULATION)
|
||||
LoadBuffer();
|
||||
}
|
||||
|
||||
void NextPalette(void)
|
||||
{
|
||||
currentPalette = (currentPalette + 1) % SV_COLOR_SCHEME_COUNT;
|
||||
supervision_set_color_scheme(currentPalette);
|
||||
}
|
||||
|
||||
void IncreaseWindowSize(void)
|
||||
{
|
||||
if (IsFullscreen())
|
||||
return;
|
||||
|
||||
SDL_DisplayMode dm;
|
||||
SDL_GetDesktopDisplayMode(0, &dm);
|
||||
if (SV_W * (windowScale + 1) <= dm.w && SV_H * (windowScale + 1) <= dm.h) {
|
||||
windowScale++;
|
||||
SDL_SetWindowSize(sdlScreen, SV_W * windowScale, SV_H * windowScale);
|
||||
}
|
||||
}
|
||||
|
||||
void DecreaseWindowSize(void)
|
||||
{
|
||||
if (IsFullscreen())
|
||||
return;
|
||||
|
||||
if (windowScale > 1) {
|
||||
windowScale--;
|
||||
SDL_SetWindowSize(sdlScreen, SV_W * windowScale, SV_H * windowScale);
|
||||
}
|
||||
}
|
||||
|
||||
void SaveState(void)
|
||||
{
|
||||
if (GetMenuState() == MENUSTATE_EMULATION)
|
||||
supervision_save_state(romName, 0);
|
||||
}
|
||||
|
||||
void LoadState(void)
|
||||
{
|
||||
if (GetMenuState() == MENUSTATE_EMULATION)
|
||||
supervision_load_state(romName, 0);
|
||||
}
|
||||
|
||||
void SetVolume(int volume)
|
||||
{
|
||||
if (volume < 0)
|
||||
audioVolume = 0;
|
||||
else if (volume > SDL_MIX_MAXVOLUME)
|
||||
audioVolume = SDL_MIX_MAXVOLUME; // 128
|
||||
else
|
||||
audioVolume = volume;
|
||||
if (lastVolume != -1) { // Mute
|
||||
lastVolume = audioVolume;
|
||||
audioVolume = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MuteAudio(void)
|
||||
{
|
||||
if (lastVolume == -1) {
|
||||
lastVolume = audioVolume;
|
||||
audioVolume = 0;
|
||||
}
|
||||
else {
|
||||
audioVolume = lastVolume;
|
||||
lastVolume = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void IncreaseGhosting(void)
|
||||
{
|
||||
SetGhosting(currentGhosting + 1);
|
||||
}
|
||||
|
||||
void DecreaseGhosting(void)
|
||||
{
|
||||
SetGhosting(currentGhosting - 1);
|
||||
}
|
||||
|
||||
void SetGhosting(int frameCount)
|
||||
{
|
||||
currentGhosting = frameCount;
|
||||
if (frameCount < 0)
|
||||
currentGhosting = 0;
|
||||
else if (frameCount > SV_GHOSTING_MAX)
|
||||
currentGhosting = SV_GHOSTING_MAX;
|
||||
if (frameCount == currentGhosting) {
|
||||
supervision_set_ghosting(currentGhosting);
|
||||
}
|
||||
}
|
||||
|
||||
void SetKey(int button)
|
||||
{
|
||||
setButton = button;
|
||||
PushMenuState(MENUSTATE_SET_KEY);
|
||||
SDL_PauseAudio(1);
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
set(SDL2_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/include")
|
||||
|
||||
# Support both 32 and 64 bit builds
|
||||
if (${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
||||
set(SDL2_LIBRARY "${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2main.lib")
|
||||
else ()
|
||||
set(SDL2_LIBRARY "${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2main.lib")
|
||||
endif ()
|
||||
|
||||
string(STRIP "${SDL2_LIBRARY}" SDL2_LIBRARY)
|
@ -1,712 +0,0 @@
|
||||
#pragma comment(linker,"\"/manifestdependency:type='win32' \
|
||||
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
|
||||
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
|
||||
#include <windows.h>
|
||||
//#include <commctrl.h>
|
||||
//#pragma comment(lib, "Comctl32.lib")
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
|
||||
// PathFindFileName()
|
||||
#include <shlwapi.h>
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
#define TERRIBLE_AUDIO_IMPLEMENTATION
|
||||
|
||||
#ifdef TERRIBLE_AUDIO_IMPLEMENTATION
|
||||
#include <mmsystem.h>
|
||||
#pragma comment(lib, "Winmm.lib")
|
||||
#endif
|
||||
|
||||
#include "resource.h"
|
||||
#include "../../common/supervision.h"
|
||||
|
||||
#ifdef TERRIBLE_AUDIO_IMPLEMENTATION
|
||||
WAVEHDR whdr;
|
||||
HWAVEOUT hWaveOut;
|
||||
// 44100 / FPS * 2 (channels) * 2 (16-bit)
|
||||
#define BUFFER_SIZE 2940
|
||||
INT8 audioBuffer[BUFFER_SIZE];
|
||||
#endif
|
||||
|
||||
volatile BOOL finished = FALSE;
|
||||
volatile BOOL execute = FALSE;
|
||||
|
||||
LPCTSTR szClassName = _T("Potator (WinAPI)");
|
||||
LPCTSTR VERSION = _T("1.0.1");
|
||||
#define WINDOW_STYLE (WS_SYSMENU | WS_MINIMIZEBOX | WS_CAPTION | WS_VISIBLE)
|
||||
#define WINDOW_EX_STYLE (WS_EX_CLIENTEDGE)
|
||||
|
||||
HWND hWindow;
|
||||
HMENU hMenu;
|
||||
HDC hDC;
|
||||
|
||||
DWORD threadID;
|
||||
HANDLE runthread = INVALID_HANDLE_VALUE;
|
||||
|
||||
char romName[MAX_PATH];
|
||||
UINT8 *buffer;
|
||||
UINT32 bufferSize = 0;
|
||||
UINT8 windowScale = 2;
|
||||
UINT16 screenBuffer[SV_W * SV_H];
|
||||
|
||||
int keysMapping[] = {
|
||||
VK_RIGHT
|
||||
, VK_LEFT
|
||||
, VK_DOWN
|
||||
, VK_UP
|
||||
, 'X'
|
||||
, 'C'
|
||||
, 'Z'
|
||||
, VK_SPACE
|
||||
};
|
||||
LPCTSTR keysNames[] = {
|
||||
_T("Right")
|
||||
, _T("Left")
|
||||
, _T("Down")
|
||||
, _T("Up")
|
||||
, _T("B")
|
||||
, _T("A")
|
||||
, _T("Select")
|
||||
, _T("Start")
|
||||
};
|
||||
|
||||
#define UPDATE_RATE 60
|
||||
UINT64 startCounter;
|
||||
UINT64 freq;
|
||||
|
||||
void InitCounter(void)
|
||||
{
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&startCounter);
|
||||
}
|
||||
|
||||
BOOL NeedUpdate(void)
|
||||
{
|
||||
static double elapsedCounter = 0.0;
|
||||
static BOOL result = FALSE;
|
||||
|
||||
// New frame
|
||||
if (!result) {
|
||||
UINT64 now;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&now);
|
||||
elapsedCounter += (double)((now - startCounter) * 1000) / freq;
|
||||
startCounter = now;
|
||||
}
|
||||
result = elapsedCounter >= 1000.0 / UPDATE_RATE;
|
||||
if (result) {
|
||||
elapsedCounter -= 1000.0 / UPDATE_RATE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// FIXME: IPC (lock Load ROM before exit 'while (execute)')
|
||||
DWORD WINAPI run(LPVOID lpParameter)
|
||||
{
|
||||
BITMAPV4HEADER bmi = { 0 };
|
||||
TCHAR txt[64];
|
||||
UINT64 curticks = 0;
|
||||
UINT64 fpsticks = 0;
|
||||
UINT16 fpsframecount = 0;
|
||||
|
||||
HANDLE hTimer;
|
||||
LARGE_INTEGER dueTime = { 0 };
|
||||
// Reduce CPU usage
|
||||
hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
|
||||
SetWaitableTimer(hTimer, &dueTime, 1000 / UPDATE_RATE, NULL, NULL, TRUE);
|
||||
|
||||
bmi.bV4Size = sizeof(bmi);
|
||||
bmi.bV4Planes = 1;
|
||||
bmi.bV4BitCount = 16;
|
||||
bmi.bV4V4Compression = BI_RGB | BI_BITFIELDS;
|
||||
bmi.bV4RedMask = 0x001F;
|
||||
bmi.bV4GreenMask = 0x03E0;
|
||||
bmi.bV4BlueMask = 0x7C00;
|
||||
bmi.bV4Width = SV_W;
|
||||
bmi.bV4Height = -SV_H;
|
||||
|
||||
while (!finished) {
|
||||
InitCounter();
|
||||
while (execute) {
|
||||
UINT8 controls_state = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (GetAsyncKeyState(keysMapping[i]) & 0x8000)
|
||||
controls_state |= 1 << i;
|
||||
}
|
||||
|
||||
supervision_set_input(controls_state);
|
||||
|
||||
while (NeedUpdate()) {
|
||||
supervision_exec(screenBuffer, FALSE);
|
||||
|
||||
#ifdef TERRIBLE_AUDIO_IMPLEMENTATION
|
||||
supervision_update_sound(audioBuffer, BUFFER_SIZE / 2);
|
||||
INT16* dst = (INT16*)audioBuffer;
|
||||
UINT8* src = (UINT8*)audioBuffer;
|
||||
for (int i = BUFFER_SIZE / 2 - 1; i >= 0; i--) {
|
||||
dst[i] = src[i] << (8 + 1);
|
||||
}
|
||||
waveOutPrepareHeader(hWaveOut, &whdr, sizeof(whdr));
|
||||
waveOutWrite(hWaveOut, &whdr, sizeof(whdr));
|
||||
whdr.dwFlags = 0;
|
||||
#endif
|
||||
|
||||
fpsframecount++;
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&curticks);
|
||||
|
||||
if (fpsticks + freq < curticks)
|
||||
fpsticks = curticks; // Initial value
|
||||
if (curticks >= fpsticks) {
|
||||
_sntprintf_s(txt, _countof(txt), _TRUNCATE , _T("%s [FPS: %d]"), szClassName, fpsframecount);
|
||||
SetWindowText(hWindow, txt);
|
||||
fpsframecount = 0;
|
||||
fpsticks += freq;
|
||||
}
|
||||
|
||||
RECT r;
|
||||
GetClientRect(hWindow, &r);
|
||||
LONG x = 0, w = r.right - r.left;
|
||||
LONG y = 0, h = r.bottom - r.top;
|
||||
if (w != h) {
|
||||
// Center
|
||||
LONG size = h / SV_H * SV_H;
|
||||
x = (w - size) / 2; w = size;
|
||||
y = (h - size) / 2; h = size;
|
||||
}
|
||||
StretchDIBits(hDC, x, y, w, h, 0, 0, SV_W, SV_H, screenBuffer, (BITMAPINFO*)&bmi, DIB_RGB_COLORS, SRCCOPY);
|
||||
}
|
||||
|
||||
WaitForSingleObject(hTimer, INFINITE);
|
||||
}
|
||||
execute = FALSE;
|
||||
WaitForSingleObject(hTimer, INFINITE);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SetRomName(LPCTSTR path)
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WideCharToMultiByte(CP_UTF8, 0, PathFindFileName(path), -1, romName, MAX_PATH, NULL, NULL);
|
||||
#else
|
||||
strcpy_s(romName, sizeof(romName), PathFindFileName(path));
|
||||
#endif
|
||||
}
|
||||
|
||||
int LoadROM(LPCTSTR fileName)
|
||||
{
|
||||
if (buffer != NULL) {
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
DWORD dwTemp;
|
||||
HANDLE hFile = CreateFile(fileName, GENERIC_READ, 0, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (INVALID_HANDLE_VALUE == hFile) {
|
||||
return 1;
|
||||
}
|
||||
bufferSize = GetFileSize(hFile, NULL);
|
||||
buffer = (UINT8 *)malloc(bufferSize);
|
||||
ReadFile(hFile, buffer, bufferSize, &dwTemp, NULL);
|
||||
if (bufferSize != dwTemp) {
|
||||
CloseHandle(hFile);
|
||||
return 1;
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
SetRomName(fileName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UpdateGhosting(void);
|
||||
void UpdatePalette(void);
|
||||
|
||||
void LoadBuffer(void)
|
||||
{
|
||||
supervision_load(buffer, bufferSize);
|
||||
UpdateGhosting();
|
||||
UpdatePalette();
|
||||
}
|
||||
|
||||
void StopEmulation(void)
|
||||
{
|
||||
execute = FALSE;
|
||||
Sleep(1000 / UPDATE_RATE * 4); // Wait for the end of execution
|
||||
}
|
||||
|
||||
void ResumeEmulation(void)
|
||||
{
|
||||
execute = TRUE;
|
||||
}
|
||||
|
||||
void UpdateWindowSize(void)
|
||||
{
|
||||
CheckMenuRadioItem(hMenu, IDM_SIZE1, IDM_SIZE6, IDM_SIZE1 + windowScale - 1, MF_BYCOMMAND);
|
||||
RECT r;
|
||||
SetRect(&r, 0, 0, SV_W * windowScale, SV_H * windowScale);
|
||||
AdjustWindowRectEx(&r, WINDOW_STYLE, TRUE, WINDOW_EX_STYLE);
|
||||
SetWindowPos(hWindow, NULL, 0, 0, r.right - r.left, r.bottom - r.top, SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
|
||||
}
|
||||
|
||||
int currGhosting = 0;
|
||||
|
||||
void UpdateGhosting(void)
|
||||
{
|
||||
CheckMenuRadioItem(hMenu, IDM_GHOSTING, IDM_GHOSTING + SV_GHOSTING_MAX, IDM_GHOSTING + currGhosting, MF_BYCOMMAND);
|
||||
supervision_set_ghosting(currGhosting);
|
||||
}
|
||||
|
||||
int currPalette = 0;
|
||||
|
||||
void UpdatePalette(void)
|
||||
{
|
||||
CheckMenuRadioItem(hMenu, IDM_PALETTE, IDM_PALETTE + SV_COLOR_SCHEME_COUNT - 1, IDM_PALETTE + currPalette, MF_BYCOMMAND);
|
||||
supervision_set_color_scheme(currPalette);
|
||||
}
|
||||
|
||||
void InitMenu(void)
|
||||
{
|
||||
HMENU hMenuGhosting = CreateMenu();
|
||||
for (int i = 0; i < SV_GHOSTING_MAX + 1; i++) {
|
||||
TCHAR buf[16];
|
||||
if (i == 0) {
|
||||
_sntprintf_s(buf, _countof(buf), _TRUNCATE, _T("Off"));
|
||||
}
|
||||
else {
|
||||
_sntprintf_s(buf, _countof(buf), _TRUNCATE, _T("%d frame%s"), i, (i > 1 ? _T("s") : _T("")));
|
||||
}
|
||||
AppendMenu(hMenuGhosting, MF_STRING, IDM_GHOSTING + i, buf);
|
||||
}
|
||||
HMENU hMenuOptions = GetSubMenu(hMenu, 1);
|
||||
InsertMenu(hMenuOptions, 2, MF_POPUP | MF_BYPOSITION, (UINT_PTR)hMenuGhosting, _T("Ghosting"));
|
||||
UpdateGhosting();
|
||||
|
||||
HMENU hMenuPalette = CreateMenu();
|
||||
for (int i = 0; i < SV_COLOR_SCHEME_COUNT; i++) {
|
||||
TCHAR buf[2];
|
||||
_sntprintf_s(buf, _countof(buf), _TRUNCATE, _T("%d"), i);
|
||||
AppendMenu(hMenuPalette, MF_STRING, IDM_PALETTE + i, buf);
|
||||
}
|
||||
InsertMenu(hMenuOptions, 3, MF_POPUP | MF_BYPOSITION, (UINT_PTR)hMenuPalette, _T("Palette"));
|
||||
UpdatePalette();
|
||||
}
|
||||
|
||||
BOOL showCursorFullscreen = FALSE;
|
||||
|
||||
BOOL IsFullscreen(void)
|
||||
{
|
||||
return GetWindowLongPtr(hWindow, GWL_STYLE) & WS_POPUP;
|
||||
}
|
||||
|
||||
void ToggleFullscreen(void)
|
||||
{
|
||||
static WINDOWPLACEMENT wp;
|
||||
if (IsFullscreen()) {
|
||||
SetWindowLongPtr(hWindow, GWL_STYLE, WINDOW_STYLE);
|
||||
SetWindowLongPtr(hWindow, GWL_EXSTYLE, WINDOW_EX_STYLE);
|
||||
SetWindowPlacement(hWindow, &wp);
|
||||
SetWindowPos(hWindow, NULL, 0, 0, 0, 0,
|
||||
SWP_FRAMECHANGED | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
|
||||
SetMenu(hWindow, hMenu);
|
||||
if (!showCursorFullscreen)
|
||||
ShowCursor(TRUE);
|
||||
}
|
||||
else {
|
||||
showCursorFullscreen = FALSE;
|
||||
wp.length = sizeof(wp);
|
||||
GetWindowPlacement(hWindow, &wp);
|
||||
SetWindowLongPtr(hWindow, GWL_STYLE, WS_VISIBLE | WS_POPUP);
|
||||
SetWindowLongPtr(hWindow, GWL_EXSTYLE, 0);
|
||||
int w = GetSystemMetrics(SM_CXSCREEN);
|
||||
int h = GetSystemMetrics(SM_CYSCREEN);
|
||||
// SWP_NOOWNERZORDER - prevents showing child windows on top
|
||||
SetWindowPos(hWindow, HWND_TOP, 0, 0, w, h, SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
|
||||
SetMenu(hWindow, NULL);
|
||||
ShowCursor(FALSE);
|
||||
RECT r = { 0, 0, w, h };
|
||||
FillRect(hDC, &r, (HBRUSH)GetStockObject(BLACK_BRUSH));
|
||||
}
|
||||
InvalidateRect(hWindow, NULL, TRUE);
|
||||
}
|
||||
|
||||
void RegisterControlConfigClass(HWND);
|
||||
void CreateControlConfigWindow(HWND);
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static HFONT hFont;
|
||||
switch (msg) {
|
||||
case WM_CREATE:
|
||||
hFont = CreateFont(0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
|
||||
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("Arial"));
|
||||
RegisterControlConfigClass(hWnd);
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
int wmId = LOWORD(wParam);
|
||||
if (wmId >= IDM_GHOSTING && wmId <= IDM_GHOSTING + SV_GHOSTING_MAX) {
|
||||
currGhosting = wmId - IDM_GHOSTING;
|
||||
UpdateGhosting();
|
||||
break;
|
||||
}
|
||||
else if (wmId >= IDM_PALETTE && wmId <= IDM_PALETTE + SV_COLOR_SCHEME_COUNT - 1) {
|
||||
currPalette = wmId - IDM_PALETTE;
|
||||
UpdatePalette();
|
||||
break;
|
||||
}
|
||||
switch (wmId) {
|
||||
case IDM_OPEN:
|
||||
{
|
||||
execute = FALSE; // Stop emulation while opening new rom
|
||||
TCHAR szFileName[MAX_PATH] = _T("");
|
||||
OPENFILENAME ofn;
|
||||
ZeroMemory(&ofn, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = hWnd;
|
||||
ofn.lpstrFilter = _T("Supervision files (.sv, .ws, .bin)\0*.sv;*.ws;*.bin\0\0");
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFile = szFileName;
|
||||
ofn.nMaxFile = MAX_PATH;
|
||||
ofn.lpstrDefExt = _T("sv");
|
||||
ofn.Flags = OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
|
||||
|
||||
if (!GetOpenFileName(&ofn)) {
|
||||
if (buffer)
|
||||
execute = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (LoadROM(szFileName) == 0) {
|
||||
LoadBuffer();
|
||||
execute = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IDM_RESET:
|
||||
LoadBuffer();
|
||||
break;
|
||||
case IDM_SAVE:
|
||||
if (buffer) {
|
||||
StopEmulation();
|
||||
supervision_save_state(romName, 0);
|
||||
ResumeEmulation();
|
||||
}
|
||||
break;
|
||||
case IDM_LOAD:
|
||||
if (buffer) {
|
||||
StopEmulation();
|
||||
supervision_load_state(romName, 0);
|
||||
ResumeEmulation();
|
||||
}
|
||||
break;
|
||||
case IDM_WEBSITE:
|
||||
ShellExecute(NULL, _T("open"), _T("https://github.com/infval/potator"), NULL, NULL, SW_SHOWNORMAL);
|
||||
break;
|
||||
case IDM_ABOUT:
|
||||
{
|
||||
TCHAR text[64] = { 0 };
|
||||
_sntprintf_s(text, _countof(text), _TRUNCATE, _T("%s %s (core: %u.%u.%u)"),
|
||||
szClassName, VERSION, SV_CORE_VERSION_MAJOR, SV_CORE_VERSION_MINOR, SV_CORE_VERSION_PATCH);
|
||||
MessageBox(NULL, text, _T("About"), MB_ICONEXCLAMATION | MB_OK);
|
||||
}
|
||||
break;
|
||||
case IDM_FULLSCREEN:
|
||||
ToggleFullscreen();
|
||||
break;
|
||||
case IDM_SIZE1:
|
||||
case IDM_SIZE2:
|
||||
case IDM_SIZE3:
|
||||
case IDM_SIZE4:
|
||||
case IDM_SIZE5:
|
||||
case IDM_SIZE6:
|
||||
windowScale = wmId - IDM_SIZE1 + 1;
|
||||
UpdateWindowSize();
|
||||
break;
|
||||
case IDM_CONTROL_CONFIG:
|
||||
CreateControlConfigWindow(hWnd);
|
||||
break;
|
||||
case IDM_EXIT:
|
||||
DestroyWindow(hWnd);
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_DROPFILES:
|
||||
{
|
||||
StopEmulation();
|
||||
HDROP hDrop = (HDROP)wParam;
|
||||
TCHAR szFileName[MAX_PATH] = _T("");
|
||||
DragQueryFile(hDrop, 0, szFileName, MAX_PATH);
|
||||
DragFinish(hDrop);
|
||||
|
||||
if (LoadROM(szFileName) == 0) {
|
||||
LoadBuffer();
|
||||
ResumeEmulation();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_LBUTTONDBLCLK:
|
||||
ToggleFullscreen();
|
||||
break;
|
||||
case WM_SYSCOMMAND:
|
||||
// Alt or F10 show menu
|
||||
if (wParam == SC_KEYMENU && IsFullscreen()) {
|
||||
showCursorFullscreen = !showCursorFullscreen;
|
||||
ShowCursor(showCursorFullscreen);
|
||||
SetMenu(hWindow, showCursorFullscreen ? hMenu : NULL);
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam); // If break;, menu doesn't get focus
|
||||
}
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
case WM_PAINT:
|
||||
{
|
||||
if (!buffer && !IsFullscreen()) {
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hWnd, &ps);
|
||||
SelectObject(hdc, hFont);
|
||||
TEXTMETRIC tm;
|
||||
GetTextMetrics(hdc, &tm);
|
||||
SetTextColor(hdc, RGB(255, 255, 255));
|
||||
SetBkColor(hdc, RGB(0, 0, 0));
|
||||
#define X(s) _T(s), _countof(s)
|
||||
TextOut(hdc, 8, 8 , X("Open ROM:"));
|
||||
TextOut(hdc, 8, 8 + tm.tmHeight * 1, X("Drag & Drop"));
|
||||
TextOut(hdc, 8, 8 + tm.tmHeight * 3, X("Toggle Fullscreen:"));
|
||||
TextOut(hdc, 8, 8 + tm.tmHeight * 4, X("Double-Click or Alt+Enter"));
|
||||
TextOut(hdc, 8, 8 + tm.tmHeight * 6, X("Toggle Menu in Fullscreen:"));
|
||||
TextOut(hdc, 8, 8 + tm.tmHeight * 7, X("Press Alt or F10"));
|
||||
#undef X
|
||||
EndPaint(hWnd, &ps);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
DeleteObject(hFont);
|
||||
DestroyWindow(hWnd);
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
//INITCOMMONCONTROLSEX ccs = { 0 };
|
||||
//ccs.dwSize = sizeof(ccs);
|
||||
//ccs.dwICC = ICC_STANDARD_CLASSES;
|
||||
//InitCommonControlsEx(&ccs);
|
||||
|
||||
supervision_init();
|
||||
|
||||
WNDCLASSEX wcex;
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.hInstance = hInstance;
|
||||
wcex.lpszClassName = szClassName;
|
||||
wcex.lpfnWndProc = WndProc;
|
||||
wcex.style = CS_DBLCLKS;
|
||||
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
||||
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wcex.lpszMenuName = _T("MENU_PRINCIPAL");
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = 0;
|
||||
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // (HBRUSH)COLOR_BACKGROUND;
|
||||
|
||||
if (!RegisterClassEx(&wcex)) {
|
||||
MessageBox(NULL, _T("Window registration failed!"), szClassName, MB_ICONEXCLAMATION | MB_OK);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hWindow = CreateWindowEx(WINDOW_EX_STYLE, szClassName, szClassName, WINDOW_STYLE,
|
||||
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
|
||||
if (!hWindow) {
|
||||
MessageBox(NULL, _T("Window creation failed!"), szClassName, MB_ICONEXCLAMATION | MB_OK);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DragAcceptFiles(hWindow, TRUE);
|
||||
|
||||
hDC = GetDC(hWindow);
|
||||
hMenu = GetMenu(hWindow);
|
||||
UpdateWindowSize();
|
||||
|
||||
InitMenu();
|
||||
|
||||
ShowWindow(hWindow, nCmdShow);
|
||||
UpdateWindow(hWindow);
|
||||
|
||||
#ifdef TERRIBLE_AUDIO_IMPLEMENTATION
|
||||
whdr.lpData = (LPSTR)audioBuffer;
|
||||
whdr.dwBufferLength = BUFFER_SIZE;
|
||||
whdr.dwFlags = 0;
|
||||
whdr.dwLoops = 0;
|
||||
WAVEFORMATEX wfx;
|
||||
wfx.nSamplesPerSec = SV_SAMPLE_RATE;
|
||||
wfx.wBitsPerSample = 16;
|
||||
wfx.nChannels = 2;
|
||||
wfx.cbSize = 0;
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfx.nBlockAlign = (wfx.wBitsPerSample * wfx.nChannels) / 8;
|
||||
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
|
||||
if (waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
runthread = CreateThread(NULL, 0, run, NULL, 0, &threadID);
|
||||
|
||||
HACCEL hAccelTable = LoadAccelerators(hInstance, _T("IDR_MAIN_ACCEL"));
|
||||
|
||||
MSG msg;
|
||||
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseDC(hWindow, hDC);
|
||||
|
||||
UnregisterClass(wcex.lpszClassName, hInstance);
|
||||
|
||||
return (int)msg.wParam;
|
||||
}
|
||||
|
||||
// Control Config
|
||||
|
||||
WPARAM MapLeftRightKeys(WPARAM vk, LPARAM lParam);
|
||||
void VirtualKeyCodeToString(UINT virtualKey, LPTSTR szName, int size);
|
||||
|
||||
HWND hButton;
|
||||
int buttonId;
|
||||
|
||||
LRESULT CALLBACK GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (code < 0) {
|
||||
return CallNextHookEx(NULL, code, wParam, lParam);
|
||||
}
|
||||
MSG msg = *((MSG*)lParam);
|
||||
if (msg.message == WM_KEYDOWN) {
|
||||
if (hButton) {
|
||||
TCHAR buf[32] = { 0 };
|
||||
GetKeyNameText(msg.lParam, buf, _countof(buf));
|
||||
SetWindowText(hButton, buf);
|
||||
EnableWindow(hButton, TRUE);
|
||||
hButton = NULL;
|
||||
keysMapping[buttonId - 1] = (int)MapLeftRightKeys(msg.wParam, msg.lParam);
|
||||
}
|
||||
}
|
||||
return CallNextHookEx(NULL, code, wParam, lParam);
|
||||
}
|
||||
|
||||
HWND hControlConfigWindow;
|
||||
|
||||
LRESULT CALLBACK ControlConfigProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static HHOOK hHook;
|
||||
static HFONT hFont;
|
||||
switch (msg) {
|
||||
case WM_CREATE:
|
||||
hButton = NULL;
|
||||
buttonId = 0;
|
||||
hFont = CreateFont(0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
|
||||
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("Arial"));
|
||||
for (int i = 0; i < 8; i++) {
|
||||
HWND h = CreateWindow(_T("static"), keysNames[i], WS_VISIBLE | WS_CHILD,
|
||||
11, 11 + i * 30, 80, 25, hwnd, (HMENU)((UINT_PTR)i + 1 + 8), NULL, NULL);
|
||||
SendMessage(h, WM_SETFONT, (WPARAM)hFont, TRUE);
|
||||
TCHAR name[32];
|
||||
VirtualKeyCodeToString(keysMapping[i], name, _countof(name));
|
||||
h = CreateWindow(_T("button"), name, WS_VISIBLE | WS_CHILD,
|
||||
80, 8 + i * 30, 120, 25, hwnd, (HMENU)((UINT_PTR)i + 1), NULL, NULL);
|
||||
SendMessage(h, WM_SETFONT, (WPARAM)hFont, TRUE);
|
||||
}
|
||||
hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, GetModuleHandle(NULL), GetCurrentThreadId());
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
int wmId = LOWORD(wParam);
|
||||
if (wmId >= 1 && wmId <= 8) {
|
||||
if (hButton) break;
|
||||
hButton = (HWND)lParam;
|
||||
buttonId = wmId;
|
||||
EnableWindow(hButton, FALSE);
|
||||
SetWindowText(hButton, _T("Press Key"));
|
||||
SetFocus(hwnd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
hControlConfigWindow = NULL;
|
||||
DeleteObject(hFont);
|
||||
UnhookWindowsHookEx(hHook);
|
||||
DestroyWindow(hwnd);
|
||||
break;
|
||||
}
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
void RegisterControlConfigClass(HWND hwnd)
|
||||
{
|
||||
WNDCLASSEX wc = { 0 };
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.lpszClassName = _T("ControlConfigClass");
|
||||
wc.lpfnWndProc = ControlConfigProc;
|
||||
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
||||
RegisterClassEx(&wc);
|
||||
}
|
||||
|
||||
void CreateControlConfigWindow(HWND hwnd)
|
||||
{
|
||||
if (hControlConfigWindow)
|
||||
return;
|
||||
RECT r;
|
||||
GetWindowRect(hWindow, &r);
|
||||
hControlConfigWindow = CreateWindowEx(WS_EX_DLGMODALFRAME, _T("ControlConfigClass"), _T("Control Config"),
|
||||
WS_VISIBLE | WS_SYSMENU | WS_CAPTION, r.left + 64, r.top + 64, 228, 290,
|
||||
hwnd, NULL, GetModuleHandle(NULL), NULL);
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/15977613
|
||||
WPARAM MapLeftRightKeys(WPARAM virtualKey, LPARAM lParam)
|
||||
{
|
||||
UINT scancode = (lParam & 0x00ff0000) >> 16;
|
||||
int extended = (lParam & 0x01000000) != 0;
|
||||
switch (virtualKey) {
|
||||
case VK_SHIFT:
|
||||
return MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
|
||||
case VK_CONTROL:
|
||||
return extended ? VK_RCONTROL : VK_LCONTROL;
|
||||
case VK_MENU:
|
||||
return extended ? VK_RMENU : VK_LMENU;
|
||||
}
|
||||
return virtualKey;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/38107083
|
||||
void VirtualKeyCodeToString(UINT virtualKey, LPTSTR szName, int size)
|
||||
{
|
||||
UINT scanCode = MapVirtualKey(virtualKey, MAPVK_VK_TO_VSC);
|
||||
switch (virtualKey) {
|
||||
case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN:
|
||||
case VK_RCONTROL: case VK_RMENU:
|
||||
case VK_LWIN: case VK_RWIN: case VK_APPS:
|
||||
case VK_INSERT: case VK_DELETE:
|
||||
case VK_HOME: case VK_END:
|
||||
case VK_PRIOR: case VK_NEXT:
|
||||
case VK_NUMLOCK: case VK_DIVIDE:
|
||||
scanCode |= KF_EXTENDED;
|
||||
}
|
||||
GetKeyNameText(scanCode << 16, szName, size);
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#ifndef RESOURCE_H
|
||||
#define RESOURCE_H
|
||||
|
||||
#define IDC_STATIC -1
|
||||
#define IDM_OPEN 101
|
||||
#define IDM_RESET 102
|
||||
#define IDM_LOAD 103
|
||||
#define IDM_SAVE 104
|
||||
#define IDM_EXIT 105
|
||||
#define IDM_WEBSITE 106
|
||||
#define IDM_ABOUT 107
|
||||
|
||||
#define IDM_SIZE1 108
|
||||
#define IDM_SIZE2 109
|
||||
#define IDM_SIZE3 110
|
||||
#define IDM_SIZE4 111
|
||||
#define IDM_SIZE5 112
|
||||
#define IDM_SIZE6 113
|
||||
|
||||
#define IDM_FULLSCREEN 114
|
||||
#define IDM_CONTROL_CONFIG 115
|
||||
|
||||
#define IDM_GHOSTING 116
|
||||
#define IDM_PALETTE (IDM_GHOSTING + SV_GHOSTING_MAX + 1)
|
||||
|
||||
#endif
|
@ -1,48 +0,0 @@
|
||||
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
|
||||
MENU_PRINCIPAL MENU
|
||||
BEGIN
|
||||
POPUP "&File"
|
||||
BEGIN
|
||||
MENUITEM "&Open ROM...\tCtrl+O",IDM_OPEN
|
||||
MENUITEM "&Reset\tCtrl+R", IDM_RESET
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Load State\t2", IDM_LOAD
|
||||
MENUITEM "&Save State\t1", IDM_SAVE
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "E&xit\tAlt+F4",IDM_EXIT
|
||||
END
|
||||
POPUP "&Options"
|
||||
BEGIN
|
||||
MENUITEM "&Fullscreen\tF11",IDM_FULLSCREEN
|
||||
POPUP "Screen Size"
|
||||
BEGIN
|
||||
MENUITEM "&1x",IDM_SIZE1
|
||||
MENUITEM "&2x",IDM_SIZE2
|
||||
MENUITEM "&3x",IDM_SIZE3
|
||||
MENUITEM "&4x",IDM_SIZE4
|
||||
MENUITEM "&5x",IDM_SIZE5
|
||||
MENUITEM "&6x",IDM_SIZE6
|
||||
END
|
||||
MENUITEM "&Control Config...\tCtrl+I",IDM_CONTROL_CONFIG
|
||||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&Website",IDM_WEBSITE
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&About...",IDM_ABOUT
|
||||
END
|
||||
END
|
||||
|
||||
IDR_MAIN_ACCEL ACCELERATORS DISCARDABLE
|
||||
BEGIN
|
||||
"O", IDM_OPEN, VIRTKEY, CONTROL
|
||||
"R", IDM_RESET, VIRTKEY, CONTROL
|
||||
"2", IDM_LOAD, VIRTKEY
|
||||
"1", IDM_SAVE, VIRTKEY
|
||||
VK_F11, IDM_FULLSCREEN, VIRTKEY
|
||||
VK_RETURN, IDM_FULLSCREEN, VIRTKEY, ALT
|
||||
"I", IDM_CONTROL_CONFIG, VIRTKEY, CONTROL
|
||||
END
|
@ -1,49 +0,0 @@
|
||||
# Emscripten makefile
|
||||
# Based on https://github.com/aardappel/lobster/blob/master/dev/emscripten/Makefile
|
||||
|
||||
CC = emcc
|
||||
|
||||
# use -g4 for maximum debug info.
|
||||
OPTLEVEL = -g4 -O0
|
||||
CFLAGS = $(OPTLEVEL)
|
||||
CFLAGS += -Wall -s USE_SDL=2
|
||||
|
||||
CSRCS = \
|
||||
../SDL2/main.c \
|
||||
../../common/m6502/m6502.c \
|
||||
$(wildcard ../../common/*.c)
|
||||
|
||||
COBJS := $(patsubst %.c,%.o,$(CSRCS))
|
||||
|
||||
EXPORTED_FUNCTIONS = \
|
||||
'_main', \
|
||||
'_UploadROM', \
|
||||
'_SaveState', \
|
||||
'_LoadState', \
|
||||
'_NextPalette', \
|
||||
'_IncreaseWindowSize', \
|
||||
'_DecreaseWindowSize', \
|
||||
'_SetVolume', \
|
||||
'_SetKey', \
|
||||
'_MuteAudio', \
|
||||
'_SetGhosting'
|
||||
|
||||
.PHONY: potator clean clean2 release all default
|
||||
|
||||
# add -s ASSERTIONS=2 when troubleshooting.
|
||||
#EMCC_WASM_BACKEND=1
|
||||
potator: $(COBJS)
|
||||
$(CC) $(CFLAGS) $(COBJS) \
|
||||
-s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']" \
|
||||
-s "EXPORTED_FUNCTIONS=[$(EXPORTED_FUNCTIONS)]" \
|
||||
-o index.html --shell-file potator_shell.html
|
||||
|
||||
clean clean2:
|
||||
-$(RM) $(COBJS)
|
||||
|
||||
release: OPTLEVEL = -O2
|
||||
release: clean potator clean2
|
||||
|
||||
all: potator
|
||||
|
||||
default: all
|
@ -1,912 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Potator</title>
|
||||
<style>
|
||||
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
|
||||
textarea.emscripten { font-family: monospace; width: 80%; }
|
||||
div.emscripten { text-align: center; }
|
||||
div.emscripten_border { /*border: 1px solid black;*/ }
|
||||
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
|
||||
canvas.emscripten { border: 0px none; background-color: black; }
|
||||
|
||||
.spinner {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
margin: 0px auto;
|
||||
-webkit-animation: rotation .8s linear infinite;
|
||||
-moz-animation: rotation .8s linear infinite;
|
||||
-o-animation: rotation .8s linear infinite;
|
||||
animation: rotation 0.8s linear infinite;
|
||||
border-left: 10px solid rgb(0,150,240);
|
||||
border-right: 10px solid rgb(0,150,240);
|
||||
border-bottom: 10px solid rgb(0,150,240);
|
||||
border-top: 10px solid rgb(100,0,200);
|
||||
border-radius: 100%;
|
||||
background-color: rgb(200,100,250);
|
||||
}
|
||||
@-webkit-keyframes rotation {
|
||||
from {-webkit-transform: rotate(0deg);}
|
||||
to {-webkit-transform: rotate(360deg);}
|
||||
}
|
||||
@-moz-keyframes rotation {
|
||||
from {-moz-transform: rotate(0deg);}
|
||||
to {-moz-transform: rotate(360deg);}
|
||||
}
|
||||
@-o-keyframes rotation {
|
||||
from {-o-transform: rotate(0deg);}
|
||||
to {-o-transform: rotate(360deg);}
|
||||
}
|
||||
@keyframes rotation {
|
||||
from {transform: rotate(0deg);}
|
||||
to {transform: rotate(360deg);}
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.main-button, canvas {
|
||||
image-rendering: pixelated;
|
||||
image-rendering: crisp-edges;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -webkit-crisp-edges;
|
||||
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.main-button {
|
||||
width: 48px;
|
||||
height: 36px;
|
||||
box-sizing: content-box;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-origin: content-box;
|
||||
border: 2px solid #aaa;
|
||||
margin: 1px;
|
||||
padding: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.main-button:hover {
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
#fileb {
|
||||
display: block;
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAMAAABcOc2zAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAB5QTFRFvALakJCQ2gIFAjraHtoC+MBI8IgAgq7I+Kgw////JqDhkgAAAAp0Uk5T////////////ALLMLM8AAABJSURBVHjaXI5BDoAwDMPC2s3t/z+MADFafLSiJJrRmFqzsbSCQlxijOHuhkl6BDhuZnoT7MQnuEXpoHb8VujHUHaRSo4CeQowALRTBDws+boxAAAAAElFTkSuQmCC');
|
||||
}
|
||||
|
||||
#savestateb {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAMAAABcOc2zAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRFZmZmmZmZAAAA////ugmYcAAAAAR0Uk5T////AEAqqfQAAAA4SURBVHjajIvRCgAgCAO38///OVCLCB+ag9PhFCXoRZ8Bqfvj3EPFUdOweCT0GLOdULMCD5UlwADBvAGarVk1DAAAAABJRU5ErkJggg==');
|
||||
}
|
||||
|
||||
#loadstateb {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAMAAABcOc2zAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRFZmZmmZmZAAAA////ugmYcAAAAAR0Uk5T////AEAqqfQAAAA5SURBVHjafIvRCgAwCAIv+/9/HizbQ2wzwTyQLEl+6N6E0014TH4gss4RaAgxrFB7B84CcZksAQYAwRIBmu1bY5MAAAAASUVORK5CYII=');
|
||||
}
|
||||
|
||||
#muteb {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAMAAABcOc2zAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAlQTFRFZmZmAAAA////UkbnHwAAAEJJREFUeNp0zgEKACAIA8DN/z86l8swaFDBsUrEE/jk2Q2kl4FkFQSsqDAhvoCMADDsz+tRNKSEKrowBsSdtLMEGAB8ZgExwXIzcQAAAABJRU5ErkJggg==');
|
||||
}
|
||||
#muteab {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAMAAABcOc2zAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAlQTFRFZmZmAAAA////UkbnHwAAADBJREFUeNpiYEIDDFCaEU2AEU2AEVmAEQJIEWAAAkZ0QxnQBYAi6A5jQBeAA4AAAwCHogFSzpCvUAAAAABJRU5ErkJggg==')
|
||||
}
|
||||
|
||||
#decreaseb {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAMAAABcOc2zAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFAAAAAAAApWe5zwAAAAJ0Uk5T/wDltzBKAAAAJElEQVR42mJgwACMMABmUUkA1XhkFYwYAiAOfhUYhoIBQIABADFuAHvO4HrHAAAAAElFTkSuQmCC');
|
||||
}
|
||||
|
||||
#increaseb {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAMAAABcOc2zAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFAAAAAAAApWe5zwAAAAJ0Uk5T/wDltzBKAAAAJUlEQVR42mJgwACMMABmUUkA1XhkFWA1KAIgDn4VGIaCAUCAAQAxAAB51Z56IgAAAABJRU5ErkJggg==');
|
||||
}
|
||||
|
||||
#nextpaletteb {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAMAAABcOc2zAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABhQTFRFJEc7uc2rb6Bag71qMWJSABAY3vbNAAAAjQpJGgAAACdJREFUeNpiYIQCJihgYGSDAGYIoI4AAwsEsEIAO3UEoIAdCgACDAAfcgL57TF56gAAAABJRU5ErkJggg==');
|
||||
}
|
||||
|
||||
#fullscreenb {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAMAAABcOc2zAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFAAAAAAAApWe5zwAAAAJ0Uk5T/wDltzBKAAAAIUlEQVR42mJggABGRgYGOBMZkCXAiAYwBahhC7rTAQIMADvEAJWS8qCXAAAAAElFTkSuQmCC');
|
||||
}
|
||||
|
||||
.page-header {
|
||||
display: inline-block;
|
||||
padding-bottom: 9px;
|
||||
margin: 40px 0 20px;
|
||||
border-bottom: 2px solid #eee;
|
||||
}
|
||||
|
||||
/* https://www.w3schools.com/cSS/css_tooltip.asp */
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tooltip .tooltiptext {
|
||||
visibility: hidden;
|
||||
width: 120px;
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding: 5px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 110%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.tooltip .tooltiptext::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px;
|
||||
border-style: solid;
|
||||
border-color: #444 transparent transparent transparent;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltiptext {
|
||||
visibility: visible;
|
||||
transition: visibility 0s linear 0.5s; /* https://stackoverflow.com/q/36242258 */
|
||||
}
|
||||
|
||||
.tooltip .tooltipaudio {
|
||||
visibility: hidden;
|
||||
width: 120px;
|
||||
background-color: rgba(68, 68, 68, 0.6);
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding: 6px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: rotate(-90deg) translateX(-21px);
|
||||
transform-origin: 0px 20px;
|
||||
height: 40px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltipaudio {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.tooltipinfo {
|
||||
border: 1px solid black;
|
||||
border-radius: 100%;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
text-align: center;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* https://www.w3schools.com/howto/howto_js_rangeslider.asp */
|
||||
.slider {
|
||||
-webkit-appearance: none;
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
background: #d3d3d3;
|
||||
outline: none;
|
||||
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
/*box-sizing: content-box;*/
|
||||
|
||||
background-color: white;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 0px solid #888;
|
||||
border-radius: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb {
|
||||
background-color: white;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 0px solid #888;
|
||||
border-radius: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
.slider::-moz-range-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#ghostslider::-webkit-slider-thumb {
|
||||
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRF////AAAAnJyc////cfZmagAAAAR0Uk5T////AEAqqfQAAABzSURBVHjanJFREgARDEOTuv+dt2ip4sPmo0PeKBWUizBWbNqAeqKaCO6LyQmSPwiyrySA1lys9iMGSNCrDFAtAF4DkD/gfIcsr+rPwjaGTeJzvAJeQDrCK1i+nSGSGJTuOmUCtW+lxYOfmRstMcGTPgEGAKVGBNcv/z1ZAAAAAElFTkSuQmCC');
|
||||
}
|
||||
|
||||
#ghostslider::-moz-range-thumb {
|
||||
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRF////AAAAnJyc////cfZmagAAAAR0Uk5T////AEAqqfQAAABzSURBVHjanJFREgARDEOTuv+dt2ip4sPmo0PeKBWUizBWbNqAeqKaCO6LyQmSPwiyrySA1lys9iMGSNCrDFAtAF4DkD/gfIcsr+rPwjaGTeJzvAJeQDrCK1i+nSGSGJTuOmUCtW+lxYOfmRstMcGTPgEGAKVGBNcv/z1ZAAAAAElFTkSuQmCC');
|
||||
}
|
||||
|
||||
#ghost {
|
||||
box-sizing: border-box;
|
||||
width: 158px;
|
||||
height: 46px;
|
||||
padding: 8px 4px;
|
||||
margin: 1px;
|
||||
border: 2px solid #aaa;
|
||||
}
|
||||
#ghost:hover {
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
/* autohotkey.com */
|
||||
kbd {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 1px 0 rgba(0,0,0,.2),0 0 0 2px #fff inset;
|
||||
color: #333;
|
||||
display: inline-block;
|
||||
font-family: Consolas,Courier New,monospace;
|
||||
line-height: 1.4em;
|
||||
margin: 0 .1em;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
padding: 0 .5em;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
white-space: nowrap;
|
||||
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border: 1px solid #dddddd;
|
||||
text-align: left;
|
||||
padding: 2px 8px;
|
||||
}
|
||||
|
||||
.ps-bg {
|
||||
display: inline-block;
|
||||
background-color: #484848;
|
||||
border-radius: 100%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.ps-square {
|
||||
display: inline-block;
|
||||
border: solid 2px #e398c9;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.ps-cross {
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%) rotate(45deg);
|
||||
/* https://stackoverflow.com/a/17359874 */
|
||||
background: linear-gradient(to bottom, transparent 44%,
|
||||
#a2abd6 44%,
|
||||
#a2abd6 56%,
|
||||
transparent 56%),
|
||||
linear-gradient(to right, transparent 44%,
|
||||
#a2abd6 44%,
|
||||
#a2abd6 56%,
|
||||
transparent 56%);
|
||||
}
|
||||
.ps-select {
|
||||
display: inline-block;
|
||||
background-color: #484848;
|
||||
border-radius: 2px;
|
||||
width: 20px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.ps-start {
|
||||
display: inline-block;
|
||||
border-radius: 2px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 6px solid transparent;
|
||||
border-left: 20px solid #484848;
|
||||
border-bottom: 6px solid transparent;
|
||||
}
|
||||
|
||||
.ps-up, .ps-right, .ps-down, .ps-left {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background-color: #484848;
|
||||
position: relative;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.ps-right {
|
||||
transform: rotate(90deg) translateY(-2px);
|
||||
margin: 0 1px 0 2px;
|
||||
}
|
||||
.ps-down {
|
||||
transform: rotate(180deg) translateY(-2px);
|
||||
}
|
||||
.ps-left {
|
||||
transform: rotate(-90deg) translateY(-2px);
|
||||
margin: 0 2px 0 1px;
|
||||
}
|
||||
.ps-up::after, .ps-right::after, .ps-down::after, .ps-left::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin-left: -50%;
|
||||
border-width: 6px;
|
||||
border-style: solid;
|
||||
border-color: #484848 transparent transparent transparent;
|
||||
}
|
||||
|
||||
#dropzone {
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
z-index: 666;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgb(0, 128, 192);
|
||||
opacity: 0.5;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.preview-td {
|
||||
background-color: #111;
|
||||
padding: 0px;
|
||||
width: 1px;
|
||||
text-align: center;
|
||||
}
|
||||
.preview-img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.preview-img:hover {
|
||||
transform: scale(2) translateX(-20px);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="text-align: center;">
|
||||
<h1 class="page-header">Potator - Watara Supervision Emulator</h1>
|
||||
</div>
|
||||
<div class="emscripten_border" style="position: relative; background: #111;" ondblclick="toggleFullscreen()">
|
||||
<figure style="position: absolute; top: 50%; left: 50%; margin: 0; transform: translate(-50%, -50%);" id="spinner"><div class="spinner"></div></figure>
|
||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" width="640" height="640"></canvas>
|
||||
</div>
|
||||
<div class="emscripten" style="text-align: left; width: 640px; margin: 3px auto;">
|
||||
<div class="tooltip" style="vertical-align: top;">
|
||||
<label>
|
||||
<span id="fileb" class="main-button"></span>
|
||||
<input type="file" onchange="onChange(event)" accept=".bin, .sv, .ws" style="display: none;">
|
||||
</label>
|
||||
<span class="tooltiptext">Load ROM</span>
|
||||
</div><!-- delete space
|
||||
--><div class="tooltip" style="vertical-align: top;">
|
||||
<button id="savestateb" class="main-button" onclick="Module.ccall('SaveState', 'void', ['void'])"></button>
|
||||
<span class="tooltiptext">Save state <kbd>1</kbd></span>
|
||||
</div><!-- delete space
|
||||
--><div class="tooltip" style="vertical-align: top;">
|
||||
<button id="loadstateb" class="main-button" onclick="Module.ccall('LoadState', 'void', ['void'])"></button>
|
||||
<span class="tooltiptext">Load state <kbd>2</kbd></span>
|
||||
</div><!-- delete space
|
||||
--><div class="tooltip" id="ghost">
|
||||
<input id="ghostslider" class="slider" type="range" min="0" max="8" value="0" step="1" autocomplete="off">
|
||||
<span class="tooltiptext" style="width: 200px;">Ghosting (reduce flickering)</span>
|
||||
</div>
|
||||
<div style="float: right;">
|
||||
<div class="tooltip">
|
||||
<button id="muteb" class="main-button" onclick="this.id = (this.id=='muteb'?'muteab':'muteb'); Module.ccall('MuteAudio', 'void', ['void'])"></button>
|
||||
<span class="tooltipaudio">
|
||||
<input id="volumeslider" class="slider" type="range" min="0" max="128" value="128" step="1" autocomplete="off">
|
||||
</span>
|
||||
</div><!-- delete space
|
||||
--><div class="tooltip">
|
||||
<button id="nextpaletteb" class="main-button" onclick="Module.ccall('NextPalette', 'void', ['void'])"></button>
|
||||
<span class="tooltiptext">Next palette <kbd>P</kbd></span>
|
||||
</div><!-- delete space
|
||||
--><div class="tooltip">
|
||||
<button id="decreaseb" class="main-button" onclick="Module.ccall('DecreaseWindowSize', 'void', ['void'])"></button>
|
||||
<span class="tooltiptext">Decrease window size <kbd>-_</kbd></span>
|
||||
</div><!-- delete space
|
||||
--><div class="tooltip">
|
||||
<button id="increaseb" class="main-button" onclick="Module.ccall('IncreaseWindowSize', 'void', ['void'])"></button>
|
||||
<span class="tooltiptext">Increase window size <kbd>=+</kbd></span>
|
||||
</div><!-- delete space
|
||||
--><div class="tooltip">
|
||||
<button id="fullscreenb" class="main-button" onclick="Module.requestFullscreen(true, false)"></button>
|
||||
<span class="tooltiptext">Fullscreen</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Controls</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Action</th>
|
||||
<th>Keyboard</th>
|
||||
<th>Gamepad <span class="tooltip tooltipinfo">!<span class="tooltiptext" style="width: 360px; font-weight: normal;">Some gamepads have the wrong button mapping in Firefox.</span></span></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Right</td>
|
||||
<td><span class="keyName">Arrow Right</span><button style="float: right;" onclick="setKey(this, 0)">Change</button></td>
|
||||
<td><span class="ps-right"></span>, Axis LeftX+</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Left</td>
|
||||
<td><span class="keyName">Arrow Left</span><button style="float: right;" onclick="setKey(this, 1)">Change</button></td>
|
||||
<td><span class="ps-left"></span>, Axis LeftX-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Down</td>
|
||||
<td><span class="keyName">Arrow Down</span><button style="float: right;" onclick="setKey(this, 2)">Change</button></td>
|
||||
<td><span class="ps-down"></span>, Axis LeftY+</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Up</td>
|
||||
<td><span class="keyName">Arrow Up</span><button style="float: right;" onclick="setKey(this, 3)">Change</button></td>
|
||||
<td><span class="ps-up"></span>, Axis LeftY-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>B</td>
|
||||
<td><span class="keyName">Key X</span><button style="float: right;" onclick="setKey(this, 4)">Change</button></td>
|
||||
<td><span class="ps-bg" style="text-align: center;"><span style="color: #91c85c; vertical-align: middle;">A</span></span> / <span class="ps-bg"><span class="ps-cross"></span></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>A</td>
|
||||
<td><span class="keyName">Key C</span><button style="float: right;" onclick="setKey(this, 5)">Change</button></td>
|
||||
<td><span class="ps-bg" style="text-align: center;"><span style="color: #0098d9; vertical-align: middle;">X</span></span> / <span class="ps-bg"><span class="ps-square"></span></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Select</td>
|
||||
<td><span class="keyName">Key Z</span><button style="float: right;" onclick="setKey(this, 6)">Change</button></td>
|
||||
<td>Back / <span class="ps-select"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Start</td>
|
||||
<td><span class="keyName">Space</span><button style="float: right;" onclick="setKey(this, 7)">Change</button></td>
|
||||
<td>Start / <span class="ps-start"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fullscreen</td>
|
||||
<td>Mouse Double-Click<span class="keyName"></span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Reset</td>
|
||||
<td><span class="keyName">Tab</span><button style="float: right;" onclick="setKey(this, 9)">Change</button></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Save state</td>
|
||||
<td><span class="keyName">Digit 1</span><button style="float: right;" onclick="setKey(this, 10)">Change</button></td>
|
||||
<td>Left bumper / L1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Load state</td>
|
||||
<td><span class="keyName">Digit 2</span><button style="float: right;" onclick="setKey(this, 11)">Change</button></td>
|
||||
<td>Right bumper/ R1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Next palette</td>
|
||||
<td><span class="keyName">Key P</span><button style="float: right;" onclick="setKey(this, 12)">Change</button></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Window size -</td>
|
||||
<td><span class="keyName">Minus</span><button style="float: right;" onclick="setKey(this, 13)">Change</button></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Window size +</td>
|
||||
<td><span class="keyName">Equal</span><button style="float: right;" onclick="setKey(this, 14)">Change</button></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ghosting -</td>
|
||||
<td><span class="keyName">Bracket Left</span><button style="float: right;" onclick="setKey(this, 15)">Change</button></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ghosting +</td>
|
||||
<td><span class="keyName">Bracket Right</span><button style="float: right;" onclick="setKey(this, 16)">Change</button></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mute</td>
|
||||
<td><span class="keyName">Key M</span><button style="float: right;" onclick="setKey(this, 17)">Change</button></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Savestates <span class="tooltip tooltipinfo" style="font-size: 0.7em;"><span style="font-weight: bolder;">!</span><span class="tooltiptext" style="width: 360px">The savestates exist in-memory. They are lost when the page is reloaded.</span></span></h2>
|
||||
<div style="margin: 10px auto;">
|
||||
<button onclick="refreshSavestates()">Refresh</button>
|
||||
<div style="display: inline;">
|
||||
<button onclick="this.nextElementSibling.click()">Upload</button>
|
||||
<label>
|
||||
<input type="file" onchange="uploadSavestate(event)" style="display: none;">
|
||||
</label>
|
||||
</div>
|
||||
<!-- Lost preview-img's hover -->
|
||||
<div style="position: absolute; height: 10px; width: 80px; z-index: 1;"></div>
|
||||
</div>
|
||||
<table><tbody id="savestates"></tbody></table>
|
||||
|
||||
<h2>Information</h2>
|
||||
<p>Chrome <a href="https://blog.google/products/chrome/improving-autoplay-chrome/">blocks audio autoplay</a>. Click on game view (canvas) or press any key.</p>
|
||||
<p>Source code: <a href="https://github.com/infval/potator">GitHub</a>.</p>
|
||||
</div>
|
||||
<div class="emscripten" id="status" style="position: fixed; top: 0px; background-color: #eee; padding: 8px;">Downloading...</div>
|
||||
<div class="emscripten"><progress value="0" max="100" id="progress" style="display: none;"></progress></div>
|
||||
<textarea class="emscripten" id="output" rows="8" style="display: none;"></textarea>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
var statusElement = document.getElementById('status');
|
||||
var progressElement = document.getElementById('progress');
|
||||
var spinnerElement = document.getElementById('spinner');
|
||||
|
||||
var Module = {
|
||||
preRun: [],
|
||||
postRun: [],
|
||||
print: (function() {
|
||||
var element = document.getElementById('output');
|
||||
if (element) element.value = ''; // clear browser cache
|
||||
return function(text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
// These replacements are necessary if you render to raw HTML
|
||||
//text = text.replace(/&/g, "&");
|
||||
//text = text.replace(/</g, "<");
|
||||
//text = text.replace(/>/g, ">");
|
||||
//text = text.replace('\n', '<br>', 'g');
|
||||
console.log(text);
|
||||
if (element) {
|
||||
element.value += text + "\n";
|
||||
element.scrollTop = element.scrollHeight; // focus on bottom
|
||||
}
|
||||
};
|
||||
})(),
|
||||
printErr: function(text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
if (0) { // XXX disabled for safety typeof dump == 'function') {
|
||||
dump(text + '\n'); // fast, straight to the real console
|
||||
} else {
|
||||
console.error(text);
|
||||
}
|
||||
},
|
||||
canvas: (function() {
|
||||
var canvas = document.getElementById('canvas');
|
||||
|
||||
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
|
||||
// application robust, you may want to override this behavior before shipping!
|
||||
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
|
||||
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
|
||||
|
||||
return canvas;
|
||||
})(),
|
||||
setStatus: function(text) {
|
||||
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
|
||||
if (text === Module.setStatus.last.text) return;
|
||||
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
|
||||
var now = Date.now();
|
||||
if (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon
|
||||
Module.setStatus.last.time = now;
|
||||
Module.setStatus.last.text = text;
|
||||
if (m) {
|
||||
text = m[1];
|
||||
progressElement.value = parseInt(m[2])*100;
|
||||
progressElement.max = parseInt(m[4])*100;
|
||||
progressElement.hidden = false;
|
||||
spinnerElement.hidden = false;
|
||||
} else {
|
||||
progressElement.value = null;
|
||||
progressElement.max = null;
|
||||
progressElement.hidden = true;
|
||||
if (!text) {
|
||||
spinnerElement.style.display = 'none';
|
||||
statusElement.style.display = 'none';
|
||||
}
|
||||
}
|
||||
statusElement.innerHTML = text;
|
||||
},
|
||||
totalDependencies: 0,
|
||||
monitorRunDependencies: function(left) {
|
||||
this.totalDependencies = Math.max(this.totalDependencies, left);
|
||||
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
|
||||
}
|
||||
};
|
||||
Module.setStatus('Downloading...');
|
||||
window.onerror = function() {
|
||||
Module.setStatus('Exception thrown, see JavaScript console');
|
||||
spinnerElement.style.display = 'none';
|
||||
Module.setStatus = function(text) {
|
||||
if (text) Module.printErr('[post-exception status] ' + text);
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<div id="dropzone"></div>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function onChange(event) {
|
||||
handleFiles(event.target.files);
|
||||
}
|
||||
function handleFiles(files) {
|
||||
var file = files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
//var buffer = Module._malloc(event.target.result.byteLength);
|
||||
//Module.writeArrayToMemory(new Uint8Array(event.target.result), buffer);
|
||||
//Module.ccall('UploadROM', 'void', ['number', 'number'], [buffer, event.target.result.byteLength]);
|
||||
//Module._free(buffer);
|
||||
var arr = new Uint8Array(event.target.result);
|
||||
Module.ccall('UploadROM', 'void', ['array', 'number', 'string'], [arr, arr.length, file.name]);
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
var dropzone = document.getElementById("dropzone");
|
||||
window.addEventListener("dragover", dragover, false);
|
||||
dropzone.addEventListener("dragleave", dragleave, false);
|
||||
dropzone.addEventListener("drop", drop, false);
|
||||
function dragover(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (e.target.id != "dropzone") {
|
||||
dropzone.style.display = "block";
|
||||
}
|
||||
}
|
||||
function dragleave(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (e.target.id == "dropzone") {
|
||||
dropzone.style.display = "none";
|
||||
}
|
||||
}
|
||||
function drop(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
dropzone.style.display = "none";
|
||||
handleFiles(e.dataTransfer.files);
|
||||
}
|
||||
|
||||
function createSlider(slider, oninput) {
|
||||
slider.addEventListener("input", oninput, false);
|
||||
slider.addEventListener("mouseup", (e) => {
|
||||
e.target.blur(); // FIX (Firefox), https://github.com/emscripten-ports/SDL2/issues/41
|
||||
}, false);
|
||||
}
|
||||
createSlider(document.getElementById("volumeslider"),
|
||||
(e) => { Module.ccall('SetVolume', 'void', ['number'], [e.target.value]); });
|
||||
createSlider(document.getElementById("ghostslider"),
|
||||
(e) => { Module.ccall('SetGhosting', 'void', ['number'], [e.target.value]); });
|
||||
|
||||
var newButtonId = -1;
|
||||
var ghostSlider = document.getElementById("ghostslider");
|
||||
var muteButton = document.getElementById("muteb");
|
||||
var keyCodes = [].map.call(document.getElementsByClassName("keyName"), (e) => e.textContent.replace(/ /g, ''));
|
||||
document.addEventListener("keydown", (e) => {
|
||||
switch (e.code) {
|
||||
case keyCodes[15]:
|
||||
ghostSlider.value -= 1;
|
||||
break;
|
||||
case keyCodes[16]:
|
||||
ghostSlider.value -= -1;
|
||||
break;
|
||||
case keyCodes[17]:
|
||||
muteButton.id = (muteButton.id == 'muteb' ? 'muteab' : 'muteb');
|
||||
break;
|
||||
}
|
||||
|
||||
endSetKey(e);
|
||||
});
|
||||
function setKey(element, buttonId) {
|
||||
if (newButtonId == -1) {
|
||||
element.textContent = "Press key";
|
||||
newButtonId = buttonId;
|
||||
Module.ccall('SetKey', 'void', ['int'], [newButtonId]);
|
||||
|
||||
pauseAudio(1);
|
||||
}
|
||||
}
|
||||
function endSetKey(keyboardEvent) {
|
||||
if (newButtonId != -1) {
|
||||
let keyNames = document.getElementsByClassName("keyName");
|
||||
if (keyboardEvent && keyboardEvent.code != "Escape") {
|
||||
keyCodes[newButtonId] = keyboardEvent.code;
|
||||
let newKeyName = keyboardEvent.code.replace(/([a-z])([\dA-Z])/g, '$1 $2');
|
||||
keyNames[newButtonId].textContent = newKeyName;
|
||||
}
|
||||
keyNames[newButtonId].nextElementSibling.textContent = "Change";
|
||||
newButtonId = -1;
|
||||
|
||||
if (keyboardEvent) pauseAudio(0);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("blur", function() {
|
||||
pauseAudio(1);
|
||||
endSetKey();
|
||||
}, false);
|
||||
window.addEventListener("focus", function() {
|
||||
pauseAudio(0);
|
||||
}, false);
|
||||
|
||||
// FIX (Chrome, ...?), project.js -> ASM_CONSTS,
|
||||
// https://github.com/emscripten-ports/SDL2/blob/master/src/audio/emscripten/SDL_emscriptenaudio.c
|
||||
function pauseAudio(on) {
|
||||
if (typeof Module === 'undefined') return;
|
||||
let moduleSDL2 = Module.SDL2;
|
||||
if (typeof moduleSDL2 === 'undefined' && typeof SDL2 !== 'undefined')
|
||||
moduleSDL2 = SDL2; // Old emscripten
|
||||
else
|
||||
return;
|
||||
//if (typeof Module === 'undefined'
|
||||
// || typeof Module.SDL2 === 'undefined'
|
||||
// || typeof Module.SDL2.audio === 'undefined'
|
||||
// || typeof Module.SDL2.audioContext === 'undefined')
|
||||
// return;
|
||||
if (on) {
|
||||
moduleSDL2.audio.scriptProcessorNode.disconnect();
|
||||
}
|
||||
else {
|
||||
moduleSDL2.audio.scriptProcessorNode['connect'](moduleSDL2.audioContext['destination']);
|
||||
}
|
||||
}
|
||||
|
||||
// Work-around chromium autoplay policy
|
||||
// https://github.com/emscripten-core/emscripten/issues/6511
|
||||
function resumeAudio(e) {
|
||||
if (typeof Module === 'undefined') return;
|
||||
let moduleSDL2 = Module.SDL2;
|
||||
if (typeof moduleSDL2 === 'undefined' && typeof SDL2 !== 'undefined')
|
||||
moduleSDL2 = SDL2; // Old emscripten
|
||||
else
|
||||
return;
|
||||
//if (typeof Module === 'undefined'
|
||||
// || typeof Module.SDL2 === 'undefined'
|
||||
// || typeof Module.SDL2.audioContext === 'undefined')
|
||||
// return;
|
||||
if (moduleSDL2.audioContext.state == 'suspended') {
|
||||
moduleSDL2.audioContext.resume();
|
||||
}
|
||||
if (moduleSDL2.audioContext.state == 'running') {
|
||||
document.getElementById('canvas').removeEventListener('click', resumeAudio);
|
||||
document.removeEventListener('keydown', resumeAudio);
|
||||
}
|
||||
}
|
||||
document.getElementById('canvas').addEventListener('click', resumeAudio);
|
||||
document.addEventListener('keydown', resumeAudio);
|
||||
|
||||
function refreshSavestates() {
|
||||
var fileNames = FS.readdir(".").filter((e) => e.search(/\.svst$/) != -1);
|
||||
var ss = document.getElementById("savestates");
|
||||
ss.innerHTML = fileNames.map((e) =>
|
||||
'<tr>\
|
||||
<td>\
|
||||
' + e + '<button onclick="saveFile(\'' + e.replace(/'/g, "\\'") + '\')" style="float: right;">Download</button>\
|
||||
</td>\
|
||||
</tr>'
|
||||
).join('');
|
||||
|
||||
for (let i = 0; i < ss.children.length; i++) {
|
||||
let telem = document.createElement('td');
|
||||
let image = document.createElement('img');
|
||||
telem.setAttribute("class", "preview-td");
|
||||
image.setAttribute("class", "preview-img");
|
||||
drawPreview(fileNames[i], image);
|
||||
telem.appendChild(image);
|
||||
ss.children[i].insertBefore(telem, ss.children[i].firstChild);
|
||||
}
|
||||
}
|
||||
function saveFile(fileName) {
|
||||
saveAs(new Blob([FS.readFile(fileName)], {type: 'application/octet-stream'}), fileName);
|
||||
}
|
||||
// https://stackoverflow.com/q/23451726
|
||||
function saveAs(blob, fileName) {
|
||||
var url = window.URL.createObjectURL(blob);
|
||||
|
||||
var anchorElem = document.createElement("a");
|
||||
anchorElem.style = "display: none";
|
||||
anchorElem.href = url;
|
||||
anchorElem.download = fileName;
|
||||
|
||||
document.body.appendChild(anchorElem);
|
||||
anchorElem.click();
|
||||
|
||||
document.body.removeChild(anchorElem);
|
||||
|
||||
// On Edge, revokeObjectURL should be called only after
|
||||
// a.click() has completed, atleast on EdgeHTML 15.15048
|
||||
setTimeout(function() {
|
||||
window.URL.revokeObjectURL(url);
|
||||
}, 1000);
|
||||
}
|
||||
function uploadSavestate(event) {
|
||||
var file = event.target.files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
FS.writeFile(file.name, new Uint8Array(event.target.result));
|
||||
refreshSavestates();
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
function drawPreview(fileName, dstImage) {
|
||||
const WIDTH = 160, HEIGHT = 160;
|
||||
function setPixel(imageData, x, y, r, g, b) {
|
||||
var i = (x + y * d.width) * 4;
|
||||
imageData.data[i+0] = r;
|
||||
imageData.data[i+1] = g;
|
||||
imageData.data[i+2] = b;
|
||||
imageData.data[i+3] = 255;
|
||||
}
|
||||
function setPixelPalette(imageData, x, y, index) {
|
||||
const c = [240, 160, 80, 0];
|
||||
setPixel(imageData, x, y, c[index], c[index], c[index]);
|
||||
}
|
||||
var canvas = document.getElementById('canvas-preview');
|
||||
var ctx = canvas.getContext('2d');
|
||||
var d = ctx.createImageData(WIDTH, HEIGHT);
|
||||
var f = FS.readFile(fileName);
|
||||
var startRegs = 0;
|
||||
var startUpperRam = startRegs + 0x2000 * 2;
|
||||
var startVRAM = startUpperRam + f[startRegs + 2] / 4 + f[startRegs + 3] * 0x30;
|
||||
for (let y = 0; y < HEIGHT; y++) {
|
||||
for (let x = 0; x < WIDTH / 4; x++) {
|
||||
let b = f[startVRAM + y*0x30 + x];
|
||||
setPixelPalette(d, x*4 + 0, y, (b >> 0)&3);
|
||||
setPixelPalette(d, x*4 + 1, y, (b >> 2)&3);
|
||||
setPixelPalette(d, x*4 + 2, y, (b >> 4)&3);
|
||||
setPixelPalette(d, x*4 + 3, y, (b >> 6)&3);
|
||||
}
|
||||
}
|
||||
ctx.putImageData(d, 0, 0);
|
||||
|
||||
dstImage.src = canvas.toDataURL();
|
||||
}
|
||||
|
||||
function toggleFullscreen() {
|
||||
if (Browser.isFullscreen)
|
||||
Module.canvas.exitFullscreen();
|
||||
else
|
||||
Module.requestFullscreen(true, false);
|
||||
}
|
||||
</script>
|
||||
<canvas id="canvas-preview" width="160" height="160" style="border: 1px solid black; position: fixed; right: 0px; top: 0px; display: none;"></canvas>
|
||||
|
||||
<div style="height: 64px; margin-top: 32px; background-color: #fcfcfc; border-top: 2px solid #eee;">
|
||||
</div>
|
||||
{{{ SCRIPT }}}
|
||||
</body>
|
||||
</html>
|
@ -270,7 +270,7 @@ static void update_audio(void)
|
||||
int16_t *out_ptr = audio_out_buffer;
|
||||
size_t i;
|
||||
|
||||
supervision_update_sound(audio_samples_buffer, AUDIO_BUFFER_SIZE);
|
||||
sound_stream_update(audio_samples_buffer, AUDIO_BUFFER_SIZE);
|
||||
|
||||
/* Convert from U8 (0 - 45) to S16 */
|
||||
for (i = 0; i < AUDIO_BUFFER_SIZE; i++)
|
||||
@ -604,7 +604,6 @@ void retro_run(void)
|
||||
skip_frame = (retro_audio_buff_occupancy < frameskip_threshold) ? TRUE : FALSE;
|
||||
break;
|
||||
default:
|
||||
skip_frame = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -627,7 +626,7 @@ void retro_run(void)
|
||||
}
|
||||
|
||||
/* Run emulator */
|
||||
supervision_exec(video_buffer, skip_frame);
|
||||
supervision_exec_ex(video_buffer, SV_W, skip_frame);
|
||||
|
||||
/* Output video */
|
||||
video_cb((bool)skip_frame ? NULL : video_buffer,
|
||||
|
Binary file not shown.
@ -1,7 +0,0 @@
|
||||
del *.h
|
||||
|
||||
bin2txt -cc potator_background.bmp
|
||||
bin2txt -cc potator_load.bmp
|
||||
bin2txt -cc potator_skin.bmp
|
||||
|
||||
pause
|
Binary file not shown.
Before Width: | Height: | Size: 76 KiB |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 76 KiB |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 76 KiB |
File diff suppressed because it is too large
Load Diff
@ -1,2 +0,0 @@
|
||||
rm potator.opk
|
||||
mksquashfs potator potator.opk
|
Binary file not shown.
@ -1,8 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Potator
|
||||
Comment=Watara Supervision Emulator
|
||||
Exec=potator-gcw0.dge
|
||||
Icon=icon
|
||||
Categories=emulators;
|
||||
X-OD-Manual=readme.txt
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
@ -1,64 +0,0 @@
|
||||
Potator for GCW-ZERO V1.1
|
||||
--------------------------------------------------------------------------------
|
||||
This is a Watara SuperVision for GCW-ZERO.
|
||||
To use this emulator, you must have compatibles ROMS with .SV & .BIN extension.
|
||||
Do not ask me about ROMS, I don't have them. A search with Google will certainly help
|
||||
you.
|
||||
|
||||
Features :
|
||||
----------
|
||||
Most things you should expect from an emulator.
|
||||
|
||||
Missing :
|
||||
---------
|
||||
Just tell me :).
|
||||
|
||||
Check updates on my web site :
|
||||
http://www.portabledev.com
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
List of emulated games
|
||||
--------------------------------------------------------------------------------
|
||||
All of the Potator games ;)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
History :
|
||||
--------------------------------------------------------------------------------
|
||||
V1.1 : 17/09/2013
|
||||
Fixed : last register for fm voice not write
|
||||
Fixed : some typo in readme file
|
||||
Fixed : game crc was not good (always 0)
|
||||
Update : sound driver rewrite to be more accurate with MESS version driver
|
||||
|
||||
V1.0 : 03/11/2012
|
||||
Initiale release
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
How to use Potator :
|
||||
--------------------------------------------------------------------------------
|
||||
Put potator.opk in your apps directory. Put your games where you want.
|
||||
The Potator icon will appear in Emulators section.
|
||||
|
||||
Controls :
|
||||
* Direction pad and A / B : Watara Supervision pad and button A / B
|
||||
* START is the same that the START button
|
||||
* SELECT is the same that the SELECT button
|
||||
|
||||
Use START + SELECT to enter menu.
|
||||
During menu browsing, LEFT and RIGHT can go through pages of available games.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Credits
|
||||
--------------------------------------------------------------------------------
|
||||
Special thanks to :
|
||||
Cal2 & Normmatt for potator source code (http://potator.sourceforge.net/).
|
||||
Mess Team for supervision driver (http://www.mess.org/)
|
||||
d_smargin for handy_a320 gui, which i used some part of code for potator gui.
|
||||
qbertaddict for test.
|
||||
hi-ban for skin.
|
||||
Without the help of the infos from these people, this emulator can't be here.
|
||||
--------------------------------------------------------------------------------
|
||||
Alekmaul
|
||||
alekmaul@portabledev.com
|
||||
http://www.portabledev.com
|
||||
--------------------------------------------------------------------------------
|
@ -1,364 +0,0 @@
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
unsigned int m_Flag;
|
||||
unsigned int interval;
|
||||
|
||||
char current_conf_app[MAX__PATH];
|
||||
|
||||
unsigned long nextTick, lastTick = 0, newTick, currentTick, wait;
|
||||
int FPS = 60;
|
||||
int pastFPS = 0;
|
||||
|
||||
SDL_Surface *layer,*layerback,*layerbackgrey;
|
||||
SDL_Surface *actualScreen;
|
||||
SDL_Event event;
|
||||
SDL_Joystick *stick = NULL;
|
||||
#define JOYSTICK_AXIS 8192
|
||||
|
||||
SDL_mutex *sndlock;
|
||||
|
||||
unsigned short XBuf[(SYSVID_WIDTH+1)*(SYSVID_HEIGHT+1)];
|
||||
char gameName[MAX__PATH];
|
||||
unsigned int gameCRC=0;
|
||||
|
||||
unsigned char *rom_buffer;
|
||||
unsigned int rom_size;
|
||||
|
||||
unsigned short keyCoresp[8] = {
|
||||
0x08 ,0x04, 0x02, 0x01,
|
||||
0x10, 0x20, 0x80, 0x40,
|
||||
};
|
||||
|
||||
gamecfg GameConf;
|
||||
|
||||
unsigned long SDL_UXTimerRead(void) {
|
||||
struct timeval tval; // timing
|
||||
|
||||
gettimeofday(&tval, 0);
|
||||
return (((tval.tv_sec*1000000) + (tval.tv_usec )));
|
||||
}
|
||||
|
||||
void graphics_paint(void) {
|
||||
unsigned short *buffer_scr = (unsigned short *) actualScreen->pixels;
|
||||
unsigned short *buffer_flip = (unsigned short *) XBuf;
|
||||
unsigned int W,H,ix,iy,x,y, xfp,yfp;
|
||||
static char buffer[32];
|
||||
|
||||
if(SDL_MUSTLOCK(actualScreen)) SDL_LockSurface(actualScreen);
|
||||
|
||||
if (GameConf.m_ScreenRatio) { // Full screen
|
||||
x=0;
|
||||
y=0;
|
||||
W=320;
|
||||
H=240;
|
||||
ix=(SYSVID_WIDTH<<16)/W;
|
||||
iy=(SYSVID_HEIGHT<<16)/H;
|
||||
xfp = 300;yfp = 1;
|
||||
|
||||
do
|
||||
{
|
||||
unsigned short *buffer_mem=(buffer_flip+((y>>16)*SYSVID_WIDTH));
|
||||
W=320; x=0;
|
||||
do {
|
||||
*buffer_scr++=buffer_mem[x>>16];
|
||||
x+=ix;
|
||||
} while (--W);
|
||||
y+=iy;
|
||||
} while (--H);
|
||||
}
|
||||
else { // Original show
|
||||
x=((actualScreen->w - SYSVID_WIDTH)/2);
|
||||
y=((actualScreen->h - SYSVID_HEIGHT)/2);
|
||||
W=SYSVID_WIDTH;
|
||||
H=SYSVID_HEIGHT;
|
||||
ix=(SYSVID_WIDTH<<16)/W;
|
||||
iy=(SYSVID_HEIGHT<<16)/H;
|
||||
xfp = (x+SYSVID_WIDTH)-20;yfp = y+1;
|
||||
|
||||
buffer_scr += (y)*320;
|
||||
buffer_scr += (x);
|
||||
do
|
||||
{
|
||||
unsigned short *buffer_mem=(buffer_flip+((y>>16)*SYSVID_WIDTH));
|
||||
W=SYSVID_WIDTH; x=((actualScreen->w - SYSVID_WIDTH)/2);
|
||||
do {
|
||||
*buffer_scr++=buffer_mem[x>>16];
|
||||
x+=ix;
|
||||
} while (--W);
|
||||
y+=iy;
|
||||
buffer_scr += actualScreen->pitch - 320 - SYSVID_WIDTH;
|
||||
} while (--H);
|
||||
}
|
||||
|
||||
pastFPS++;
|
||||
newTick = SDL_UXTimerRead();
|
||||
if ((newTick-lastTick)>1000000) {
|
||||
FPS = pastFPS;
|
||||
pastFPS = 0;
|
||||
lastTick = newTick;
|
||||
}
|
||||
|
||||
if (GameConf.m_DisplayFPS) {
|
||||
sprintf(buffer,"%02d",FPS);
|
||||
print_string_video(xfp,yfp,buffer);
|
||||
}
|
||||
|
||||
if (SDL_MUSTLOCK(actualScreen)) SDL_UnlockSurface(actualScreen);
|
||||
SDL_Flip(actualScreen);
|
||||
}
|
||||
|
||||
|
||||
void initSDL(void) {
|
||||
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0) {
|
||||
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
atexit(SDL_Quit);
|
||||
|
||||
actualScreen = SDL_SetVideoMode(320, 240, 16, SDL_DOUBLEBUF | SDL_HWSURFACE );
|
||||
if(actualScreen == NULL) {
|
||||
fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
// Init new layer to add background and text
|
||||
layer = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 240, 16, 0,0,0,0);
|
||||
if(layer == NULL) {
|
||||
fprintf(stderr, "Couldn't create surface: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
layerback = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 240, 16, 0,0,0,0);
|
||||
if(layerback == NULL) {
|
||||
fprintf(stderr, "Couldn't create surface: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
layerbackgrey = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 240, 16, 0,0,0,0);
|
||||
if(layerbackgrey == NULL) {
|
||||
fprintf(stderr, "Couldn't create surface: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Init joystick
|
||||
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
stick = SDL_JoystickOpen(0);
|
||||
}
|
||||
|
||||
uint16 mapRGB(uint8 r, uint8 g, uint8 b) {
|
||||
return PIX_TO_RGB(actualScreen->format, r, g, b);
|
||||
}
|
||||
|
||||
unsigned char potatorLoadROM(char* filename) {
|
||||
if (rom_buffer != NULL)
|
||||
free(rom_buffer);
|
||||
|
||||
FILE *romfile = fopen(filename, "rb");
|
||||
if (romfile != NULL) {
|
||||
fseek(romfile, 0, SEEK_END);
|
||||
rom_size = ftell(romfile);
|
||||
fseek(romfile, 0, SEEK_SET);
|
||||
rom_buffer = (unsigned char *)malloc(rom_size);
|
||||
fread(rom_buffer, 1, rom_size, romfile);
|
||||
fclose(romfile);
|
||||
|
||||
supervision_load(rom_buffer, rom_size);
|
||||
supervision_set_map_func(mapRGB);
|
||||
switch (GameConf.m_Color) {
|
||||
case 0: supervision_set_color_scheme(SV_COLOR_SCHEME_DEFAULT); break;
|
||||
case 1: supervision_set_color_scheme(SV_COLOR_SCHEME_AMBER); break;
|
||||
case 2: supervision_set_color_scheme(SV_COLOR_SCHEME_GREEN); break;
|
||||
case 3: supervision_set_color_scheme(SV_COLOR_SCHEME_BLUE); break;
|
||||
}
|
||||
|
||||
// Compute game CRC
|
||||
gameCRC = crc32(0, rom_buffer, rom_size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
double period;
|
||||
|
||||
// Get init file directory & name
|
||||
gethomedir(current_conf_app, "potator");
|
||||
strncat(current_conf_app, "//potator.cfg", sizeof(current_conf_app) - strlen(current_conf_app) - 1);
|
||||
|
||||
// Init graphics & sound
|
||||
initSDL();
|
||||
|
||||
SDL_WM_SetCaption("potator", NULL);
|
||||
|
||||
//load rom file via args if a rom path is supplied
|
||||
if(argc > 1) {
|
||||
strncpy(gameName, argv[1], sizeof(gameName) - 1);
|
||||
m_Flag = GF_GAMEINIT;
|
||||
}
|
||||
|
||||
// Initialize the virtual console emulation
|
||||
supervision_init();
|
||||
|
||||
m_Flag = GF_MAINUI;
|
||||
system_loadcfg(current_conf_app);
|
||||
|
||||
while (m_Flag != GF_GAMEQUIT) {
|
||||
SDL_PollEvent(&event);
|
||||
unsigned char *keys = SDL_GetKeyState(NULL);
|
||||
|
||||
switch (m_Flag) {
|
||||
case GF_MAINUI:
|
||||
SDL_PauseAudio(1);
|
||||
screen_showtopmenu();
|
||||
if (cartridge_IsLoaded()) {
|
||||
SDL_PauseAudio(0);
|
||||
nextTick = SDL_UXTimerRead() + interval;
|
||||
}
|
||||
break;
|
||||
|
||||
case GF_GAMEINIT:
|
||||
// load card game if ok
|
||||
if (potatorLoadROM(gameName) != 0) {
|
||||
m_Flag = GF_GAMERUNNING;
|
||||
|
||||
// Init timing
|
||||
period = 1.0 / 60;
|
||||
period = period * 1000000;
|
||||
interval = (int) period;
|
||||
nextTick = SDL_UXTimerRead() + interval;
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"cant't load %s : %s",gameName,SDL_GetError()); fflush(stderr);
|
||||
m_Flag = GF_GAMEQUIT;
|
||||
}
|
||||
break;
|
||||
|
||||
case GF_GAMERUNNING:
|
||||
currentTick = SDL_UXTimerRead();
|
||||
wait = (nextTick - currentTick);
|
||||
if (wait > 0) {
|
||||
if (wait < 1000000)
|
||||
usleep(wait);
|
||||
}
|
||||
|
||||
// Manage keys
|
||||
unsigned char controls_state = 0;
|
||||
|
||||
if ( (keys[SDLK_UP] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[0]]; // UP
|
||||
if ( (keys[SDLK_DOWN] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[1]]; // DOWN
|
||||
if ( (keys[SDLK_LEFT] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[2]]; // LEFT
|
||||
if ( (keys[SDLK_RIGHT] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[3]]; // RIGHT
|
||||
|
||||
if ( (keys[SDLK_LCTRL] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[4]]; // BUTTON #A
|
||||
if ( (keys[SDLK_LALT] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[5]]; // BUTTON #B
|
||||
if ( (keys[SDLK_SPACE] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[6]]; // KEYPAD #A
|
||||
if ( (keys[SDLK_LSHIFT] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[7]]; // KEYPAD #B
|
||||
|
||||
if ( (keys[SDLK_BACKSPACE] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[8]]; // KEYPAD #A
|
||||
if ( (keys[SDLK_TAB] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[9]]; // KEYPAD #B
|
||||
if ( (keys[SDLK_ESCAPE] == SDL_PRESSED) && (keys[SDLK_RETURN] == SDL_PRESSED ) ) {
|
||||
m_Flag = GF_MAINUI;
|
||||
}
|
||||
else if ( (keys[SDLK_RETURN] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[10]]; // START
|
||||
else if ( (keys[SDLK_ESCAPE] == SDL_PRESSED) ) controls_state |= keyCoresp[GameConf.OD_Joy[11]]; // SELECT
|
||||
supervision_set_input(controls_state);
|
||||
|
||||
// Update emulation
|
||||
supervision_exec(XBuf, FALSE);
|
||||
graphics_paint();
|
||||
|
||||
nextTick += interval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Free memory
|
||||
SDL_FreeSurface(layerbackgrey);
|
||||
SDL_FreeSurface(layerback);
|
||||
SDL_FreeSurface(layer);
|
||||
SDL_FreeSurface(actualScreen);
|
||||
|
||||
// Free memory
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO|SDL_INIT_AUDIO);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
|
||||
#define DO2(buf) DO1(buf); DO1(buf);
|
||||
#define DO4(buf) DO2(buf); DO2(buf);
|
||||
#define DO8(buf) DO4(buf); DO4(buf);
|
||||
// Table of CRC-32's of all single-byte values (made by make_crc_table)
|
||||
unsigned int crc_table[256] = {
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
||||
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
|
||||
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
||||
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
|
||||
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
|
||||
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
|
||||
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
|
||||
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
|
||||
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
|
||||
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
||||
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
|
||||
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
|
||||
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
|
||||
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
|
||||
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
|
||||
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
|
||||
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
||||
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
|
||||
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
|
||||
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
|
||||
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
|
||||
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
|
||||
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
|
||||
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
||||
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
|
||||
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
|
||||
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
|
||||
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
|
||||
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
|
||||
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
|
||||
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
||||
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
|
||||
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
|
||||
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
|
||||
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
|
||||
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
|
||||
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
|
||||
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
||||
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
|
||||
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
|
||||
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
|
||||
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
|
||||
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
|
||||
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
|
||||
0x2d02ef8dL
|
||||
};
|
||||
|
||||
unsigned long crc32 (unsigned int crc, const unsigned char *buf, unsigned int len) {
|
||||
if (buf == 0) return 0L;
|
||||
crc = crc ^ 0xffffffffL;
|
||||
while (len >= 8) {
|
||||
DO8(buf);
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
DO1(buf);
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffffL;
|
||||
}
|
@ -1,990 +0,0 @@
|
||||
#include <dirent.h>
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
#include "./data/potator_background.h"
|
||||
#include "./data/potator_load.h"
|
||||
#include "./data/potator_skin.h"
|
||||
|
||||
extern unsigned int m_Flag;
|
||||
|
||||
bool gameMenu;
|
||||
|
||||
#define COLOR_BG PIX_TO_RGB(layer->format,05, 03, 02)
|
||||
#define COLOR_HELP_TEXT PIX_TO_RGB(layer->format,64, 240, 96)
|
||||
#define COLOR_OK PIX_TO_RGB(layer->format,0,0,255)
|
||||
#define COLOR_KO PIX_TO_RGB(layer->format,255,0,0)
|
||||
#define COLOR_INFO PIX_TO_RGB(layer->format,0,255,0)
|
||||
#define COLOR_LIGHT PIX_TO_RGB(layer->format,255,255,0)
|
||||
#define COLOR_ACTIVE_ITEM PIX_TO_RGB(layer->format,232, 253, 77)
|
||||
#define COLOR_INACTIVE_ITEM PIX_TO_RGB(layer->format,67,89,153)
|
||||
|
||||
// Font: THIN8X8.pf : Exported from PixelFontEdit 2.7.0
|
||||
static const unsigned char fontdata8x8[2048] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 000 (.)
|
||||
0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E, // Char 001 (.)
|
||||
0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, // Char 002 (.)
|
||||
0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, // Char 003 (.)
|
||||
0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, // Char 004 (.)
|
||||
0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x7C, 0x38, 0x7C, // Char 005 (.)
|
||||
0x10, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C, // Char 006 (.)
|
||||
0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, // Char 007 (.)
|
||||
0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, // Char 008 (.)
|
||||
0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, // Char 009 (.)
|
||||
0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, // Char 010 (.)
|
||||
0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78, // Char 011 (.)
|
||||
0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, // Char 012 (.)
|
||||
0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0, // Char 013 (.)
|
||||
0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0, // Char 014 (.)
|
||||
0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99, // Char 015 (.)
|
||||
0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00, // Char 016 (.)
|
||||
0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00, // Char 017 (.)
|
||||
0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, // Char 018 (.)
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, // Char 019 (.)
|
||||
0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00, // Char 020 (.)
|
||||
0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0xCC, 0x78, // Char 021 (.)
|
||||
0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00, // Char 022 (.)
|
||||
0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF, // Char 023 (.)
|
||||
0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, // Char 024 (.)
|
||||
0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, // Char 025 (.)
|
||||
0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, // Char 026 (.) right arrow
|
||||
0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, // Char 027 (.)
|
||||
0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, // Char 028 (.)
|
||||
0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, // Char 029 (.)
|
||||
0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00, // Char 030 (.)
|
||||
0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00, // Char 031 (.)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 032 ( )
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x00, // Char 033 (!)
|
||||
0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 034 (")
|
||||
0x50, 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x50, 0x00, // Char 035 (#)
|
||||
0x20, 0x78, 0xA0, 0x70, 0x28, 0xF0, 0x20, 0x00, // Char 036 ($)
|
||||
0xC8, 0xC8, 0x10, 0x20, 0x40, 0x98, 0x98, 0x00, // Char 037 (%)
|
||||
0x70, 0x88, 0x50, 0x20, 0x54, 0x88, 0x74, 0x00, // Char 038 (&)
|
||||
0x60, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 039 (')
|
||||
0x20, 0x40, 0x80, 0x80, 0x80, 0x40, 0x20, 0x00, // Char 040 (()
|
||||
0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, // Char 041 ())
|
||||
0x00, 0x20, 0xA8, 0x70, 0x70, 0xA8, 0x20, 0x00, // Char 042 (*)
|
||||
0x00, 0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, // Char 043 (+)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x20, 0x40, // Char 044 (,)
|
||||
0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, // Char 045 (-)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, // Char 046 (.)
|
||||
0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, // Char 047 (/)
|
||||
0x70, 0x88, 0x98, 0xA8, 0xC8, 0x88, 0x70, 0x00, // Char 048 (0)
|
||||
0x40, 0xC0, 0x40, 0x40, 0x40, 0x40, 0xE0, 0x00, // Char 049 (1)
|
||||
0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xF8, 0x00, // Char 050 (2)
|
||||
0x70, 0x88, 0x08, 0x10, 0x08, 0x88, 0x70, 0x00, // Char 051 (3)
|
||||
0x08, 0x18, 0x28, 0x48, 0xFC, 0x08, 0x08, 0x00, // Char 052 (4)
|
||||
0xF8, 0x80, 0x80, 0xF0, 0x08, 0x88, 0x70, 0x00, // Char 053 (5)
|
||||
0x20, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70, 0x00, // Char 054 (6)
|
||||
0xF8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x40, 0x00, // Char 055 (7)
|
||||
0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00, // Char 056 (8)
|
||||
0x70, 0x88, 0x88, 0x78, 0x08, 0x08, 0x70, 0x00, // Char 057 (9)
|
||||
0x00, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, // Char 058 (:)
|
||||
0x00, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x20, // Char 059 (;)
|
||||
0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x00, // Char 060 (<)
|
||||
0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, // Char 061 (=)
|
||||
0x80, 0x40, 0x20, 0x10, 0x20, 0x40, 0x80, 0x00, // Char 062 (>)
|
||||
0x78, 0x84, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00, // Char 063 (?)
|
||||
0x70, 0x88, 0x88, 0xA8, 0xB8, 0x80, 0x78, 0x00, // Char 064 (@)
|
||||
0x20, 0x50, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00, // Char 065 (A)
|
||||
0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0, 0x00, // Char 066 (B)
|
||||
0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00, // Char 067 (C)
|
||||
0xF0, 0x88, 0x88, 0x88, 0x88, 0x88, 0xF0, 0x00, // Char 068 (D)
|
||||
0xF8, 0x80, 0x80, 0xE0, 0x80, 0x80, 0xF8, 0x00, // Char 069 (E)
|
||||
0xF8, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x80, 0x00, // Char 070 (F)
|
||||
0x70, 0x88, 0x80, 0x80, 0x98, 0x88, 0x78, 0x00, // Char 071 (G)
|
||||
0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88, 0x00, // Char 072 (H)
|
||||
0xE0, 0x40, 0x40, 0x40, 0x40, 0x40, 0xE0, 0x00, // Char 073 (I)
|
||||
0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00, // Char 074 (J)
|
||||
0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88, 0x00, // Char 075 (K)
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8, 0x00, // Char 076 (L)
|
||||
0x82, 0xC6, 0xAA, 0x92, 0x82, 0x82, 0x82, 0x00, // Char 077 (M)
|
||||
0x84, 0xC4, 0xA4, 0x94, 0x8C, 0x84, 0x84, 0x00, // Char 078 (N)
|
||||
0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, // Char 079 (O)
|
||||
0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80, 0x00, // Char 080 (P)
|
||||
0x70, 0x88, 0x88, 0x88, 0xA8, 0x90, 0x68, 0x00, // Char 081 (Q)
|
||||
0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88, 0x00, // Char 082 (R)
|
||||
0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00, // Char 083 (S)
|
||||
0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, // Char 084 (T)
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, // Char 085 (U)
|
||||
0x88, 0x88, 0x88, 0x50, 0x50, 0x20, 0x20, 0x00, // Char 086 (V)
|
||||
0x82, 0x82, 0x82, 0x82, 0x92, 0x92, 0x6C, 0x00, // Char 087 (W)
|
||||
0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00, // Char 088 (X)
|
||||
0x88, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x00, // Char 089 (Y)
|
||||
0xF8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xF8, 0x00, // Char 090 (Z)
|
||||
0xE0, 0x80, 0x80, 0x80, 0x80, 0x80, 0xE0, 0x00, // Char 091 ([)
|
||||
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, // Char 092 (\)
|
||||
0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x00, // Char 093 (])
|
||||
0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 094 (^)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, // Char 095 (_)
|
||||
0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 096 (`)
|
||||
0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x74, 0x00, // Char 097 (a)
|
||||
0x80, 0x80, 0xB0, 0xC8, 0x88, 0xC8, 0xB0, 0x00, // Char 098 (b)
|
||||
0x00, 0x00, 0x70, 0x88, 0x80, 0x88, 0x70, 0x00, // Char 099 (c)
|
||||
0x08, 0x08, 0x68, 0x98, 0x88, 0x98, 0x68, 0x00, // Char 100 (d)
|
||||
0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, // Char 101 (e)
|
||||
0x30, 0x48, 0x40, 0xE0, 0x40, 0x40, 0x40, 0x00, // Char 102 (f)
|
||||
0x00, 0x00, 0x34, 0x48, 0x48, 0x38, 0x08, 0x30, // Char 103 (g)
|
||||
0x80, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00, // Char 104 (h)
|
||||
0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, // Char 105 (i)
|
||||
0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x90, 0x60, // Char 106 (j)
|
||||
0x80, 0x80, 0x88, 0x90, 0xA0, 0xD0, 0x88, 0x00, // Char 107 (k)
|
||||
0xC0, 0x40, 0x40, 0x40, 0x40, 0x40, 0xE0, 0x00, // Char 108 (l)
|
||||
0x00, 0x00, 0xEC, 0x92, 0x92, 0x92, 0x92, 0x00, // Char 109 (m)
|
||||
0x00, 0x00, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00, // Char 110 (n)
|
||||
0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, // Char 111 (o)
|
||||
0x00, 0x00, 0xB0, 0xC8, 0xC8, 0xB0, 0x80, 0x80, // Char 112 (p)
|
||||
0x00, 0x00, 0x68, 0x98, 0x98, 0x68, 0x08, 0x08, // Char 113 (q)
|
||||
0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80, 0x00, // Char 114 (r)
|
||||
0x00, 0x00, 0x78, 0x80, 0x70, 0x08, 0xF0, 0x00, // Char 115 (s)
|
||||
0x40, 0x40, 0xE0, 0x40, 0x40, 0x50, 0x20, 0x00, // Char 116 (t)
|
||||
0x00, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00, // Char 117 (u)
|
||||
0x00, 0x00, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00, // Char 118 (v)
|
||||
0x00, 0x00, 0x82, 0x82, 0x92, 0x92, 0x6C, 0x00, // Char 119 (w)
|
||||
0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, // Char 120 (x)
|
||||
0x00, 0x00, 0x88, 0x88, 0x98, 0x68, 0x08, 0x70, // Char 121 (y)
|
||||
0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8, 0x00, // Char 122 (z)
|
||||
0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x10, 0x00, // Char 123 ({)
|
||||
0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, // Char 124 (|)
|
||||
0x40, 0x20, 0x20, 0x10, 0x20, 0x20, 0x40, 0x00, // Char 125 (})
|
||||
0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 126 (~)
|
||||
0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00 // Char 127 (.)
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
int system_is_load_state(void);
|
||||
|
||||
void menuReset(void);
|
||||
void menuQuit(void);
|
||||
void menuContinue(void);
|
||||
void menuFileBrowse(void);
|
||||
void menuSaveBmp(void);
|
||||
void menuSaveState(void);
|
||||
void menuLoadState(void);
|
||||
void screen_showkeymenu(void);
|
||||
void menuReturn(void);
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
char itemName[16];
|
||||
int *itemPar;
|
||||
int itemParMaxValue;
|
||||
char *itemParName;
|
||||
void (*itemOnA)();
|
||||
} MENUITEM;
|
||||
|
||||
typedef struct {
|
||||
int itemNum; // number of items
|
||||
int itemCur; // current item
|
||||
MENUITEM *m; // array of items
|
||||
} MENU;
|
||||
|
||||
char mnuYesNo[2][16] = {"no", "yes"};
|
||||
char mnuRatio[2][16] = { "Original show","Full screen"};
|
||||
char mnuColor[4][16] = { "White","Amber","Green","Blue"};
|
||||
|
||||
char mnuButtons[8][16] = {
|
||||
"Up","Down","Left","Right","But A","But B", "Start", "Select",
|
||||
};
|
||||
|
||||
MENUITEM MainMenuItems[] = {
|
||||
{"Load rom", NULL, 0, NULL, &menuFileBrowse},
|
||||
{"Continue", NULL, 0, NULL, &menuContinue},
|
||||
{"Reset", NULL, 0, NULL, &menuReset},
|
||||
{"Ratio: ", (int *) &GameConf.m_ScreenRatio, 1, (char *) &mnuRatio, NULL},
|
||||
{"Color scheme: ",(int *) &GameConf.m_Color, 3, (char *) &mnuColor, NULL},
|
||||
{"Button Settings", NULL, 0, NULL, &screen_showkeymenu},
|
||||
{"Take Screenshot", NULL, 0, NULL, &menuSaveBmp},
|
||||
{"Show FPS: ", (int *) &GameConf.m_DisplayFPS, 1,(char *) &mnuYesNo, NULL},
|
||||
{"Exit", NULL, 0, NULL, &menuQuit}
|
||||
};
|
||||
MENU mnuMainMenu = { 9, 0, (MENUITEM *) &MainMenuItems };
|
||||
|
||||
MENUITEM ConfigMenuItems[] = {
|
||||
{"Button A: ", (int *) &GameConf.OD_Joy[4], 6, (char *) &mnuButtons, NULL},
|
||||
{"Button B: ", (int *) &GameConf.OD_Joy[5], 6, (char *) &mnuButtons, NULL},
|
||||
{"Button X: ", (int *) &GameConf.OD_Joy[6], 6, (char *) &mnuButtons, NULL},
|
||||
{"Button Y: ", (int *) &GameConf.OD_Joy[7], 6, (char *) &mnuButtons, NULL},
|
||||
{"Button R: ", (int *) &GameConf.OD_Joy[8], 6, (char *) &mnuButtons, NULL},
|
||||
{"Button L: ", (int *) &GameConf.OD_Joy[9], 6, (char *) &mnuButtons, NULL},
|
||||
{"START : ", (int *) &GameConf.OD_Joy[10], 6, (char *) &mnuButtons, NULL},
|
||||
{"SELECT : ", (int *) &GameConf.OD_Joy[11], 6, (char *) &mnuButtons, NULL},
|
||||
{"Return to menu", NULL, 0, NULL, &menuReturn},
|
||||
};
|
||||
MENU mnuConfigMenu = { 9, 0, (MENUITEM *) &ConfigMenuItems };
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
#if 0
|
||||
void screen_drawpixel(SDL_Surface *s, unsigned int x, unsigned int y, unsigned int color) {
|
||||
unsigned int bpp, ofs;
|
||||
|
||||
bpp = s->format->BytesPerPixel;
|
||||
ofs = s->pitch*y + x*bpp;
|
||||
|
||||
memcpy(s->pixels + ofs, &color, bpp);
|
||||
}
|
||||
|
||||
// Basic Bresenham line algorithm
|
||||
static void SDL_DrawLine(SDL_Surface *s, unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int color) {
|
||||
#define SGN(x) ((x)>0 ? 1 : ((x)==0 ? 0:(-1)))
|
||||
#define ABS(x) ((x)>0 ? (x) : (-x))
|
||||
|
||||
int lg_delta, sh_delta, cycle, lg_step, sh_step;
|
||||
|
||||
lg_delta = x2 - x1;
|
||||
sh_delta = y2 - y1;
|
||||
lg_step = SGN(lg_delta);
|
||||
lg_delta = ABS(lg_delta);
|
||||
sh_step = SGN(sh_delta);
|
||||
sh_delta = ABS(sh_delta);
|
||||
if (sh_delta < lg_delta) {
|
||||
cycle = lg_delta >> 1;
|
||||
while (x1 != x2) {
|
||||
screen_drawpixel(s, x1, y1, color);
|
||||
cycle += sh_delta;
|
||||
if (cycle > lg_delta) {
|
||||
cycle -= lg_delta;
|
||||
y1 += sh_step;
|
||||
}
|
||||
x1 += lg_step;
|
||||
}
|
||||
screen_drawpixel(s, x1, y1, color);
|
||||
}
|
||||
cycle = sh_delta >> 1;
|
||||
while (y1 != y2) {
|
||||
screen_drawpixel(s, x1, y1, color);
|
||||
cycle += lg_delta;
|
||||
if (cycle > sh_delta) {
|
||||
cycle -= sh_delta;
|
||||
x1 += lg_step;
|
||||
}
|
||||
y1 += sh_step;
|
||||
}
|
||||
screen_drawpixel(s, x1, y1, color);
|
||||
}
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Prints char on a given surface
|
||||
void screen_showchar(SDL_Surface *s, int x, int y, unsigned char a, int fg_color, int bg_color) {
|
||||
unsigned short *dst;
|
||||
int w, h;
|
||||
|
||||
//if(SDL_MUSTLOCK(s)) SDL_LockSurface(s);
|
||||
for(h = 8; h; h--) {
|
||||
dst = (unsigned short *)s->pixels + (y+8-h)*s->w + x;
|
||||
for(w = 8; w; w--) {
|
||||
unsigned short color = *dst; // background
|
||||
if((fontdata8x8[a*8 + (8-h)] >> w) & 1) color = fg_color;
|
||||
*dst++ = color;
|
||||
}
|
||||
}
|
||||
//if(SDL_MUSTLOCK(s)) SDL_UnlockSurface(s);
|
||||
}
|
||||
|
||||
// copy-pasted mostly from gpsp emulator by Exophaze. thanks for it
|
||||
void print_string(const char *s, unsigned short fg_color, unsigned short bg_color, int x, int y) {
|
||||
int i, j = strlen(s);
|
||||
for(i = 0; i < j; i++, x += 6) screen_showchar(layer, x, y, s[i], fg_color, bg_color);
|
||||
}
|
||||
|
||||
void print_string_video(int x, int y, const char *s) {
|
||||
int i, j = strlen(s);
|
||||
for(i = 0; i < j; i++, x += 8) screen_showchar(actualScreen, x, y, s[i], PIX_TO_RGB(actualScreen->format,255, 0, 0), 0);
|
||||
}
|
||||
|
||||
void screen_showitem(int x, int y, MENUITEM *m, int fg_color) {
|
||||
static char i_str[24];
|
||||
|
||||
// if no parameters, show simple menu item
|
||||
if(m->itemPar == NULL) print_string(m->itemName, fg_color, COLOR_BG, x, y);
|
||||
else {
|
||||
if(m->itemParName == NULL) {
|
||||
// if parameter is a digit
|
||||
sprintf(i_str, "%s%i", m->itemName, *m->itemPar);
|
||||
} else {
|
||||
// if parameter is a name in array
|
||||
sprintf(i_str, "%s%s", m->itemName, m->itemParName+(*m->itemPar)*16);
|
||||
}
|
||||
print_string(i_str, fg_color, COLOR_BG, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
// Shows menu items and pointing arrow
|
||||
#define SPRX (16)
|
||||
void screen_showmenu(MENU *menu) {
|
||||
int i;
|
||||
MENUITEM *mi = menu->m;
|
||||
|
||||
// clear buffer
|
||||
SDL_BlitSurface(layerbackgrey, 0, layer, 0);
|
||||
|
||||
// show menu lines
|
||||
for(i = 0; i < menu->itemNum; i++, mi++) {
|
||||
int fg_color;
|
||||
|
||||
if(menu->itemCur == i) fg_color = COLOR_ACTIVE_ITEM; else fg_color = COLOR_INACTIVE_ITEM;
|
||||
screen_showitem(SPRX+10, 59+i*15, mi, fg_color);
|
||||
if(menu->itemCur == i) print_string("-", fg_color, COLOR_BG, SPRX+10-12, 59+i*15);
|
||||
}
|
||||
}
|
||||
|
||||
// draw default emulator design
|
||||
void screen_prepback(SDL_Surface *s, unsigned char *bmpBuf, unsigned int bmpSize) {
|
||||
// load logo, Convert the image to optimal display format and Free the temporary surface
|
||||
SDL_RWops *rw = SDL_RWFromMem(bmpBuf, bmpSize);
|
||||
SDL_Surface *temp = SDL_LoadBMP_RW(rw, 1);
|
||||
SDL_Surface *image;
|
||||
image = SDL_DisplayFormat(temp);
|
||||
SDL_FreeSurface(temp);
|
||||
|
||||
// Display image
|
||||
SDL_BlitSurface(image, 0, s, 0);
|
||||
SDL_FreeSurface(image);
|
||||
}
|
||||
|
||||
// draw main emulator design
|
||||
void screen_prepbackground(void) {
|
||||
// draw default background
|
||||
screen_prepback(layerbackgrey, POTATOR_BACKGROUND, POTATOR_BACKGROUND_SIZE);
|
||||
}
|
||||
|
||||
// wait for a key
|
||||
void screen_waitkey(void) {
|
||||
bool akey=false;
|
||||
|
||||
while (!akey) {
|
||||
while(SDL_PollEvent(&event)) {
|
||||
if(event.type == SDL_KEYDOWN)
|
||||
akey = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void screen_waitkeyarelease(void) {
|
||||
unsigned char *keys;
|
||||
|
||||
// wait key release and go in menu
|
||||
while (1) {
|
||||
SDL_PollEvent(&event);
|
||||
keys = SDL_GetKeyState(NULL);
|
||||
if (keys[SDLK_LCTRL] != SDL_PRESSED) break;
|
||||
}
|
||||
}
|
||||
|
||||
// flip the layer to screen
|
||||
void screen_flip(void) {
|
||||
SDL_BlitSurface(layer, 0, actualScreen, 0);
|
||||
SDL_Flip(actualScreen);
|
||||
}
|
||||
|
||||
// Main function that runs all the stuff
|
||||
void screen_showmainmenu(MENU *menu) {
|
||||
unsigned char *keys;
|
||||
MENUITEM *mi;
|
||||
char szVal[100];
|
||||
int isSta = 0;
|
||||
unsigned int keya=0, keyb=0, keyup=0, keydown=0, keyleft=0, keyright=0;
|
||||
|
||||
gameMenu=true;
|
||||
|
||||
// Test if load state available
|
||||
if (menu == &mnuMainMenu) {
|
||||
if (cartridge_IsLoaded()) {
|
||||
//isSta = system_is_load_state();
|
||||
}
|
||||
}
|
||||
|
||||
while(gameMenu) {
|
||||
SDL_PollEvent(&event);
|
||||
keys = SDL_GetKeyState(NULL);
|
||||
|
||||
mi = menu->m + menu->itemCur; // pointer to highlit menu option
|
||||
|
||||
// A - apply parameter or enter submenu
|
||||
if (keys[SDLK_LCTRL] == SDL_PRESSED) {
|
||||
if (!keya) {
|
||||
keya = 1;
|
||||
screen_waitkeyarelease();
|
||||
if (mi->itemOnA != NULL) (*mi->itemOnA)();
|
||||
}
|
||||
}
|
||||
else keya=0;
|
||||
|
||||
// B - exit or back to previous menu
|
||||
if (keys[SDLK_LALT] == SDL_PRESSED) {
|
||||
if (!keyb) {
|
||||
keyb = 1; if (menu != &mnuMainMenu) gameMenu = false;
|
||||
}
|
||||
}
|
||||
else keyb=0;
|
||||
|
||||
// UP - arrow up
|
||||
if (keys[SDLK_UP] == SDL_PRESSED) {
|
||||
if (!keyup) {
|
||||
keyup = 1; if(--menu->itemCur < 0) menu->itemCur = menu->itemNum - 1;
|
||||
}
|
||||
else {
|
||||
keyup++; if (keyup>12) keyup=0;
|
||||
}
|
||||
}
|
||||
else keyup=0;
|
||||
|
||||
//DOWN - arrow down
|
||||
if (keys[SDLK_DOWN] == SDL_PRESSED) {
|
||||
if (!keydown) {
|
||||
keydown = 1; if(++menu->itemCur == menu->itemNum) menu->itemCur = 0;
|
||||
}
|
||||
else {
|
||||
keydown++; if (keydown>12) keydown=0;
|
||||
}
|
||||
}
|
||||
else keydown=0;
|
||||
|
||||
// LEFT - decrease parameter value
|
||||
if (keys[SDLK_LEFT] == SDL_PRESSED) {
|
||||
if (!keyleft) {
|
||||
keyleft = 1; if(mi->itemPar != NULL && *mi->itemPar > 0) *mi->itemPar -= 1;
|
||||
// big hack for key conf
|
||||
if (menu == &mnuConfigMenu) {
|
||||
if (*mi->itemPar < 4) *mi->itemPar = 4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
keyleft++; if (keyleft>12) keyleft=0;
|
||||
}
|
||||
}
|
||||
else keyleft=0;
|
||||
|
||||
// RIGHT - increase parameter value
|
||||
if (keys[SDLK_RIGHT] == SDL_PRESSED) {
|
||||
if (!keyright) {
|
||||
keyright = 1; if(mi->itemPar != NULL && *mi->itemPar < mi->itemParMaxValue) *mi->itemPar += 1;
|
||||
}
|
||||
else {
|
||||
keyright++; if (keyright>12) keyright=0;
|
||||
}
|
||||
}
|
||||
else keyright=0;
|
||||
|
||||
if (gameMenu) {
|
||||
screen_showmenu(menu); // show menu items
|
||||
if (menu == &mnuMainMenu) {
|
||||
int len = snprintf(szVal, sizeof(szVal), "V1.1 (core: %u.%u.%u)",
|
||||
SV_CORE_VERSION_MAJOR, SV_CORE_VERSION_MINOR, SV_CORE_VERSION_PATCH);
|
||||
print_string(szVal, COLOR_LIGHT,COLOR_BG, 320-len*6,29);
|
||||
if (cartridge_IsLoaded()) {
|
||||
#ifdef _OPENDINGUX_
|
||||
sprintf(szVal,"Game:%s",strrchr(gameName,'/')+1);szVal[(320/6)-2] = '\0';
|
||||
#else
|
||||
sprintf(szVal,"Game:%s",strrchr(gameName,'\\')+1);szVal[(320/6)-2] = '\0';
|
||||
#endif
|
||||
print_string(szVal, COLOR_LIGHT,COLOR_BG, 8,240-2-10-10);
|
||||
sprintf(szVal,"CRC:%08X",gameCRC);
|
||||
print_string(szVal, COLOR_LIGHT, COLOR_BG,8,240-2-10);
|
||||
if (isSta) print_string("Load state available",COLOR_INFO, COLOR_BG,8+104,240-2-10);
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_Delay(16);
|
||||
screen_flip();
|
||||
}
|
||||
}
|
||||
|
||||
// Menu function that runs keys configuration
|
||||
void screen_showkeymenu(void) {
|
||||
screen_showmainmenu(&mnuConfigMenu);
|
||||
}
|
||||
|
||||
// Menu function that runs main top menu
|
||||
void screen_showtopmenu(void) {
|
||||
// Save screen in layer
|
||||
SDL_BlitSurface(actualScreen, 0, layerback, 0);
|
||||
screen_prepbackground();
|
||||
|
||||
// Display and manage main menu
|
||||
screen_showmainmenu(&mnuMainMenu);
|
||||
|
||||
// save actual config
|
||||
system_savecfg(current_conf_app);
|
||||
|
||||
// if no ratio, put skin
|
||||
if (!GameConf.m_ScreenRatio) {
|
||||
screen_prepback(actualScreen, POTATOR_SKIN, POTATOR_SKIN_SIZE);
|
||||
SDL_Flip(actualScreen);
|
||||
screen_prepback(actualScreen, POTATOR_SKIN, POTATOR_SKIN_SIZE);
|
||||
SDL_Flip(actualScreen);
|
||||
}
|
||||
|
||||
// in case of different color scheme
|
||||
switch (GameConf.m_Color) {
|
||||
case 0: supervision_set_color_scheme(SV_COLOR_SCHEME_DEFAULT); break;
|
||||
case 1: supervision_set_color_scheme(SV_COLOR_SCHEME_AMBER); break;
|
||||
case 2: supervision_set_color_scheme(SV_COLOR_SCHEME_GREEN); break;
|
||||
case 3: supervision_set_color_scheme(SV_COLOR_SCHEME_BLUE); break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int system_is_load_state(void) {
|
||||
char name[512];
|
||||
int fd;
|
||||
int n=0;
|
||||
|
||||
strcpy(name, gameName);
|
||||
strcpy(strrchr(name, '.'), ".sta");
|
||||
|
||||
fd = open(name, O_RDONLY | O_BINARY);
|
||||
if (fd >= 0) {
|
||||
n = 1;
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return (n ? 1 : 0);
|
||||
}
|
||||
|
||||
// find a filename for bmp or state saving
|
||||
void findNextFilename(char *szFileFormat, char *szFilename) {
|
||||
uint32_t uBcl;
|
||||
int fp;
|
||||
|
||||
for (uBcl = 0; uBcl<1000; uBcl++) {
|
||||
sprintf(szFilename,szFileFormat,uBcl);
|
||||
fp = open(szFilename,O_RDONLY | O_BINARY);
|
||||
if (fp <0) break;
|
||||
close(fp);
|
||||
}
|
||||
if (uBcl == 1000)
|
||||
strcpy(szFilename,"NOSLOT");
|
||||
if (fp>=0) close(fp);
|
||||
}
|
||||
|
||||
// Reset current game
|
||||
void menuReset(void) {
|
||||
if (cartridge_IsLoaded()) {
|
||||
supervision_reset();
|
||||
supervision_set_map_func(mapRGB);
|
||||
switch (GameConf.m_Color) {
|
||||
case 0: supervision_set_color_scheme(SV_COLOR_SCHEME_DEFAULT); break;
|
||||
case 1: supervision_set_color_scheme(SV_COLOR_SCHEME_AMBER); break;
|
||||
case 2: supervision_set_color_scheme(SV_COLOR_SCHEME_GREEN); break;
|
||||
case 3: supervision_set_color_scheme(SV_COLOR_SCHEME_BLUE); break;
|
||||
}
|
||||
gameMenu=false;
|
||||
m_Flag = GF_GAMERUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
// Quit oswan emulator (oh noooo :P)
|
||||
void menuQuit(void) {
|
||||
if (cartridge_IsLoaded()) {
|
||||
supervision_done();
|
||||
}
|
||||
gameMenu=false;
|
||||
m_Flag = GF_GAMEQUIT;
|
||||
}
|
||||
|
||||
// Return to game if loaded
|
||||
void menuContinue(void) {
|
||||
if (cartridge_IsLoaded()) {
|
||||
gameMenu=false;
|
||||
m_Flag = GF_GAMERUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
// Rom file browser which is called from menu
|
||||
#define MAX_FILES 512
|
||||
typedef struct {
|
||||
char name[255];
|
||||
unsigned int type;
|
||||
} filedirtype;
|
||||
filedirtype filedir_list[MAX_FILES];
|
||||
|
||||
int sort_function(const void *src_str_ptr, const void *dest_str_ptr) {
|
||||
filedirtype *p1 = (filedirtype *) src_str_ptr;
|
||||
filedirtype *p2 = (filedirtype *) dest_str_ptr;
|
||||
|
||||
return strcmp (p1->name, p2->name);
|
||||
}
|
||||
|
||||
int strcmp_function(char *s1, char *s2) {
|
||||
unsigned i;
|
||||
|
||||
if (strlen(s1) != strlen(s2)) return 1;
|
||||
|
||||
for(i=0; i<strlen(s1); i++) {
|
||||
if (toupper(s1[i]) != toupper(s2[i]))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
signed int load_file(char **wildcards, char *result) {
|
||||
unsigned char *keys;
|
||||
unsigned int keya=0, keyb=0, keyup=0, kepufl=8, keydown=0, kepdfl=8, keyr=0, keyl=0;
|
||||
|
||||
char current_dir_name[MAX__PATH];
|
||||
DIR *current_dir;
|
||||
struct dirent *current_file;
|
||||
struct stat file_info;
|
||||
char current_dir_short[81];
|
||||
unsigned int current_dir_length;
|
||||
unsigned int num_filedir;
|
||||
|
||||
char *file_name;
|
||||
unsigned int file_name_length;
|
||||
unsigned int ext_pos = -1;
|
||||
signed int return_value = 1;
|
||||
unsigned int repeat;
|
||||
unsigned int i;
|
||||
|
||||
unsigned int current_filedir_scroll_value;
|
||||
unsigned int current_filedir_selection;
|
||||
unsigned int current_filedir_in_scroll;
|
||||
unsigned int current_filedir_number;
|
||||
|
||||
// Init dir with saved one
|
||||
strcpy(current_dir_name,GameConf.current_dir_rom);
|
||||
chdir(GameConf.current_dir_rom);
|
||||
|
||||
while (return_value == 1) {
|
||||
current_filedir_in_scroll = 0;
|
||||
current_filedir_scroll_value = 0;
|
||||
current_filedir_number = 0;
|
||||
current_filedir_selection = 0;
|
||||
num_filedir = 0;
|
||||
|
||||
getcwd(current_dir_name, MAX__PATH);
|
||||
current_dir = opendir(current_dir_name);
|
||||
|
||||
do {
|
||||
if(current_dir) current_file = readdir(current_dir); else current_file = NULL;
|
||||
|
||||
if(current_file) {
|
||||
file_name = current_file->d_name;
|
||||
file_name_length = strlen(file_name);
|
||||
|
||||
if((stat(file_name, &file_info) >= 0) && ((file_name[0] != '.') || (file_name[1] == '.'))) {
|
||||
if(S_ISDIR(file_info.st_mode)) {
|
||||
filedir_list[num_filedir].type = 1; // 1 -> directory
|
||||
strcpy(filedir_list[num_filedir].name, file_name);
|
||||
num_filedir++;
|
||||
|
||||
} else {
|
||||
// Must match one of the wildcards, also ignore the .
|
||||
if(file_name_length >= 4) {
|
||||
if(file_name[file_name_length - 4] == '.') ext_pos = file_name_length - 4;
|
||||
else if(file_name[file_name_length - 3] == '.') ext_pos = file_name_length - 3;
|
||||
else ext_pos = 0;
|
||||
|
||||
for(i = 0; wildcards[i] != NULL; i++) {
|
||||
if(!strcmp_function((file_name + ext_pos), wildcards[i])) {
|
||||
filedir_list[num_filedir].type = 0; // 0 -> file
|
||||
strcpy(filedir_list[num_filedir].name, file_name);
|
||||
num_filedir++;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(current_file);
|
||||
|
||||
if (num_filedir)
|
||||
qsort((void *)filedir_list, num_filedir, sizeof(filedirtype), sort_function);
|
||||
|
||||
closedir(current_dir);
|
||||
|
||||
current_dir_length = strlen(current_dir_name);
|
||||
if(current_dir_length > 39) {
|
||||
memcpy(current_dir_short, "...", 3);
|
||||
memcpy(current_dir_short + 3, current_dir_name + current_dir_length - (39-3), (39-3));
|
||||
current_dir_short[39] = 0;
|
||||
} else {
|
||||
memcpy(current_dir_short, current_dir_name, current_dir_length + 1);
|
||||
}
|
||||
|
||||
repeat = 1;
|
||||
|
||||
char print_buffer[81];
|
||||
|
||||
while(repeat) {
|
||||
//SDL_FillRect(layer, NULL, COLOR_BG);
|
||||
screen_prepback(layer, POTATOR_LOAD, POTATOR_LOAD_SIZE);
|
||||
print_string(current_dir_short, COLOR_ACTIVE_ITEM, COLOR_BG, 4, 10*3);
|
||||
print_string("Press B to return to the main menu", COLOR_HELP_TEXT, COLOR_BG, 160-(34*8/2), 240-5 -10*3);
|
||||
for(i = 0, current_filedir_number = i + current_filedir_scroll_value; i < FILE_LIST_ROWS; i++, current_filedir_number++) {
|
||||
#define CHARLEN ((320/6)-2)
|
||||
if(current_filedir_number < num_filedir) {
|
||||
if (filedir_list[current_filedir_number].type == 0) { // file (0) or dir (1) ?
|
||||
strncpy(print_buffer,filedir_list[current_filedir_number].name, CHARLEN);
|
||||
}
|
||||
else {
|
||||
strncpy(print_buffer+1,filedir_list[current_filedir_number].name, CHARLEN-1);
|
||||
print_buffer[0] = '[';
|
||||
if (strlen(filedir_list[current_filedir_number].name)<(CHARLEN-1))
|
||||
print_buffer[strlen(filedir_list[current_filedir_number].name)+1] = ']';
|
||||
else
|
||||
print_buffer[CHARLEN-1] = ']';
|
||||
}
|
||||
print_buffer[CHARLEN] = 0;
|
||||
if((current_filedir_number == current_filedir_selection)) {
|
||||
print_string(print_buffer, COLOR_ACTIVE_ITEM, COLOR_BG, 4, 10*3+((i + 2) * 8));
|
||||
} else {
|
||||
print_string(print_buffer, COLOR_INACTIVE_ITEM, COLOR_BG, 4,10*3+ ((i + 2) * 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Catch input
|
||||
SDL_PollEvent(&event);
|
||||
keys = SDL_GetKeyState(NULL);
|
||||
|
||||
// A - choose file or enter directory
|
||||
if (keys[SDLK_LCTRL] == SDL_PRESSED) {
|
||||
if (!keya) {
|
||||
keya = 1;
|
||||
screen_waitkeyarelease();
|
||||
if (filedir_list[current_filedir_selection].type == 1) { // so it's a directory
|
||||
repeat = 0;
|
||||
chdir(filedir_list[current_filedir_selection].name);
|
||||
}
|
||||
else {
|
||||
repeat = 0;
|
||||
return_value = 0;
|
||||
#ifdef _OPENDINGUX_
|
||||
sprintf(result, "%s/%s", current_dir_name, filedir_list[current_filedir_selection].name);
|
||||
#else
|
||||
sprintf(result, "%s\\%s", current_dir_name, filedir_list[current_filedir_selection].name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else keya=0;
|
||||
|
||||
// B - exit or back to previous menu
|
||||
if (keys[SDLK_LALT] == SDL_PRESSED) {
|
||||
if (!keyb) {
|
||||
keyb = 1;
|
||||
return_value = -1;
|
||||
repeat = 0;
|
||||
}
|
||||
}
|
||||
else keyb=0;
|
||||
|
||||
// UP - arrow up
|
||||
if (keys[SDLK_UP] == SDL_PRESSED) {
|
||||
if (!keyup) {
|
||||
keyup = 1;
|
||||
if(current_filedir_selection) {
|
||||
current_filedir_selection--;
|
||||
if(current_filedir_in_scroll == 0) {
|
||||
current_filedir_scroll_value--;
|
||||
} else {
|
||||
current_filedir_in_scroll--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
current_filedir_selection = (num_filedir - 1);
|
||||
current_filedir_in_scroll = num_filedir> FILE_LIST_ROWS ? (FILE_LIST_ROWS - 1) : num_filedir-1;
|
||||
current_filedir_scroll_value = num_filedir> FILE_LIST_ROWS ? (num_filedir - 1)-FILE_LIST_ROWS+1 : 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
keyup++; if (keyup>kepufl) keyup=0;
|
||||
if (kepufl>2) kepufl--;
|
||||
}
|
||||
}
|
||||
else { keyup=0; kepufl = 8; }
|
||||
|
||||
//DOWN - arrow down
|
||||
if (keys[SDLK_DOWN] == SDL_PRESSED) {
|
||||
if (!keydown) {
|
||||
keydown = 1;
|
||||
if(current_filedir_selection < (num_filedir - 1)) {
|
||||
current_filedir_selection++;
|
||||
if(current_filedir_in_scroll == (FILE_LIST_ROWS - 1)) {
|
||||
current_filedir_scroll_value++;
|
||||
} else {
|
||||
current_filedir_in_scroll++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
current_filedir_selection = 0;
|
||||
current_filedir_in_scroll =0;
|
||||
current_filedir_scroll_value = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
keydown++; if (keydown>kepdfl) keydown=0;
|
||||
if (kepdfl>2) kepdfl--;
|
||||
}
|
||||
}
|
||||
else { keydown=0; kepdfl = 8; }
|
||||
|
||||
// R - arrow down from current screen
|
||||
if (keys[SDLK_RIGHT] == SDL_PRESSED) {
|
||||
if (!keyr) {
|
||||
keyr = 1;
|
||||
if ( (current_filedir_selection+FILE_LIST_ROWS) < (num_filedir-1)) {
|
||||
current_filedir_selection+=FILE_LIST_ROWS;
|
||||
//current_filedir_in_scroll=0;
|
||||
current_filedir_scroll_value+=FILE_LIST_ROWS;
|
||||
}
|
||||
}
|
||||
}
|
||||
else keyr = 0;
|
||||
|
||||
// L - arrow up from current screen
|
||||
if (keys[SDLK_LEFT] == SDL_PRESSED) {
|
||||
if (!keyl) {
|
||||
keyl = 1;
|
||||
if (current_filedir_selection> FILE_LIST_ROWS-1) {
|
||||
//current_filedir_in_scroll=0;
|
||||
current_filedir_selection-=FILE_LIST_ROWS-1;
|
||||
current_filedir_scroll_value-=FILE_LIST_ROWS-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else keyl = 0;
|
||||
|
||||
SDL_Delay(16);
|
||||
screen_flip();
|
||||
}
|
||||
}
|
||||
|
||||
// Save current rom directory
|
||||
if (return_value != -1) {
|
||||
strcpy(GameConf.current_dir_rom,current_dir_name);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
char *file_ext[] = { (char *) ".sv", (char *) ".ws", (char *) ".bin", NULL };
|
||||
|
||||
void menuFileBrowse(void) {
|
||||
if (load_file(file_ext, gameName) != -1) { // exit if file is chosen
|
||||
gameMenu=false;
|
||||
m_Flag = GF_GAMEINIT;
|
||||
}
|
||||
}
|
||||
|
||||
// Take a screenshot of current game
|
||||
void menuSaveBmp(void) {
|
||||
char szFile[512], szFile1[512];
|
||||
|
||||
if (cartridge_IsLoaded()) {
|
||||
#ifdef _OPENDINGUX_
|
||||
sprintf(szFile,"./%s",strrchr(gameName,'/')+1);
|
||||
#else
|
||||
sprintf(szFile,".\\%s",strrchr(gameName,'\\')+1);
|
||||
#endif
|
||||
strcat(szFile, "%03d.bmp");
|
||||
|
||||
print_string("Saving...", COLOR_OK, COLOR_BG, 8,240-5 -10*3);
|
||||
screen_flip();
|
||||
findNextFilename(szFile,szFile1);
|
||||
SDL_SaveBMP(layerback, szFile1);
|
||||
print_string("Screen saved !", COLOR_OK, COLOR_BG, 8+10*8,240-5 -10*3);
|
||||
screen_flip();
|
||||
screen_waitkey();
|
||||
}
|
||||
}
|
||||
|
||||
// Save current state of game emulated
|
||||
void menuSaveState(void) {
|
||||
char szFile[512];
|
||||
|
||||
if (cartridge_IsLoaded()) {
|
||||
strcpy(szFile, gameName);
|
||||
strcpy(strrchr(szFile, '.'), ".sta");
|
||||
print_string("Saving...", COLOR_OK, COLOR_BG, 8,240-5 -10*3);
|
||||
supervision_save_state(szFile,1);
|
||||
print_string("Save OK",COLOR_OK,COLOR_BG, 8+10*8,240-5 -10*3);
|
||||
screen_flip();
|
||||
screen_waitkey();
|
||||
}
|
||||
}
|
||||
|
||||
// Load current state of game emulated
|
||||
void menuLoadState(void) {
|
||||
char szFile[512];
|
||||
|
||||
if (cartridge_IsLoaded()) {
|
||||
strcpy(szFile, gameName);
|
||||
strcpy(strrchr(szFile, '.'), ".sta");
|
||||
print_string("Loading...", COLOR_OK, COLOR_BG, 8,240-5 -10*3);
|
||||
supervision_load_state(szFile,1);
|
||||
print_string("Load OK",COLOR_OK,COLOR_BG, 8+10*8,240-5 -10*3);
|
||||
screen_flip();
|
||||
screen_waitkey();
|
||||
gameMenu=false;
|
||||
m_Flag = GF_GAMERUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
// Go back to menu
|
||||
void menuReturn(void) {
|
||||
gameMenu=false;
|
||||
}
|
||||
|
||||
|
||||
void system_loadcfg(char *cfg_name) {
|
||||
int fd;
|
||||
|
||||
fd = open(cfg_name, O_RDONLY | O_BINARY);
|
||||
if (fd >= 0) {
|
||||
read(fd, &GameConf, sizeof(GameConf));
|
||||
close(fd);
|
||||
if (!GameConf.m_ScreenRatio) {
|
||||
screen_prepback(actualScreen, POTATOR_SKIN, POTATOR_SKIN_SIZE);
|
||||
SDL_Flip(actualScreen);
|
||||
screen_prepback(actualScreen, POTATOR_SKIN, POTATOR_SKIN_SIZE);
|
||||
SDL_Flip(actualScreen);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// UP DOWN LEFT RIGHT A B X Y R L START SELECT
|
||||
// 0, 1, 2, 3, 4, 5, 4, 5, 4, 5, 6, 7
|
||||
GameConf.OD_Joy[ 0] = 0; GameConf.OD_Joy[ 1] = 1;
|
||||
GameConf.OD_Joy[ 2] = 2; GameConf.OD_Joy[ 3] = 3;
|
||||
GameConf.OD_Joy[ 4] = 4; GameConf.OD_Joy[ 5] = 5;
|
||||
GameConf.OD_Joy[ 6] = 4; GameConf.OD_Joy[ 7] = 5;
|
||||
GameConf.OD_Joy[ 8] = 4; GameConf.OD_Joy[ 9] = 5;
|
||||
GameConf.OD_Joy[10] = 6; GameConf.OD_Joy[11] = 7;
|
||||
|
||||
GameConf.sndLevel=40;
|
||||
GameConf.m_ScreenRatio=1; // 0 = original show, 1 = full screen
|
||||
GameConf.m_DisplayFPS=1; // 0 = no
|
||||
GameConf.m_Color = 0; // default color scheme
|
||||
supervision_set_color_scheme(SV_COLOR_SCHEME_DEFAULT);
|
||||
getcwd(GameConf.current_dir_rom, MAX__PATH);
|
||||
}
|
||||
}
|
||||
|
||||
void system_savecfg(char *cfg_name) {
|
||||
int fd;
|
||||
|
||||
fd = open(cfg_name, O_CREAT | O_RDWR | O_BINARY | O_TRUNC, S_IREAD | S_IWRITE);
|
||||
if (fd >= 0) {
|
||||
write(fd, &GameConf, sizeof(GameConf));
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
void gethomedir(char *dir, char* name) {
|
||||
#ifdef _OPENDINGUX_
|
||||
strcpy(dir, getenv("HOME"));
|
||||
if (strlen(dir) == 0) {
|
||||
getcwd(dir, 256);
|
||||
}
|
||||
sprintf(dir + strlen(dir), "//.%s//", name);
|
||||
mkdir(dir,S_IRWXU | S_IRWXG | S_IRWXO); // create $HOME/.config/program if it doesn't exist
|
||||
#else
|
||||
getcwd(dir, 256);
|
||||
#endif
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
Potator for GCW-ZERO V1.1
|
||||
--------------------------------------------------------------------------------
|
||||
This is a Watara SuperVision for GCW-ZERO.
|
||||
To use this emulator, you must have compatibles ROMS with .SV & .BIN extension.
|
||||
Do not ask me about ROMS, I don't have them. A search with Google will certainly help
|
||||
you.
|
||||
|
||||
Features :
|
||||
----------
|
||||
Most things you should expect from an emulator.
|
||||
|
||||
Missing :
|
||||
---------
|
||||
Just tell me :).
|
||||
|
||||
Check updates on my web site :
|
||||
http://www.portabledev.com
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
List of emulated games
|
||||
--------------------------------------------------------------------------------
|
||||
All of the Potator games ;)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
History :
|
||||
--------------------------------------------------------------------------------
|
||||
V1.1 : 17/09/2013
|
||||
Fixed : last register for fm voice not write
|
||||
Fixed : some typo in readme file
|
||||
Fixed : game crc was not good (always 0)
|
||||
Update : sound driver rewrite to be more accurate with MESS version driver
|
||||
|
||||
V1.0 : 03/11/2012
|
||||
Initiale release
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
How to use Potator :
|
||||
--------------------------------------------------------------------------------
|
||||
Put potator.opk in your apps directory. Put your games where you want.
|
||||
The Potator icon will appear in Emulators section.
|
||||
|
||||
Controls :
|
||||
* Direction pad and A / B : Watara Supervision pad and button A / B
|
||||
* START is the same that the START button
|
||||
* SELECT is the same that the SELECT button
|
||||
|
||||
Use START + SELECT to enter menu.
|
||||
During menu browsing, LEFT and RIGHT can go through pages of available games.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Credits
|
||||
--------------------------------------------------------------------------------
|
||||
Special thanks to :
|
||||
Cal2 & Normmatt for potator source code (http://potator.sourceforge.net/).
|
||||
Mess Team for supervision driver (http://www.mess.org/)
|
||||
d_smargin for handy_a320 gui, which i used some part of code for potator gui.
|
||||
qbertaddict for test.
|
||||
hi-ban for skin.
|
||||
Without the help of the infos from these people, this emulator can't be here.
|
||||
--------------------------------------------------------------------------------
|
||||
Alekmaul
|
||||
alekmaul@portabledev.com
|
||||
http://www.portabledev.com
|
||||
--------------------------------------------------------------------------------
|
@ -1,82 +0,0 @@
|
||||
#ifndef SHARED_H
|
||||
#define SHARED_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
// potator dependencies
|
||||
#include "../../common/supervision.h"
|
||||
|
||||
// defines and macros
|
||||
#define MAX__PATH 1024
|
||||
#define FILE_LIST_ROWS 19
|
||||
|
||||
#define SYSVID_WIDTH 160
|
||||
#define SYSVID_HEIGHT 160
|
||||
|
||||
#define GF_GAMEINIT 1
|
||||
#define GF_MAINUI 2
|
||||
#define GF_GAMEQUIT 3
|
||||
#define GF_GAMERUNNING 4
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
typedef int bool;
|
||||
|
||||
#define PIX_TO_RGB(fmt, r, g, b) (((r>>fmt->Rloss)<<fmt->Rshift)| ((g>>fmt->Gloss)<<fmt->Gshift)|((b>>fmt->Bloss)<<fmt->Bshift))
|
||||
extern uint16 mapRGB(uint8 r, uint8 g, uint8 b);
|
||||
|
||||
#define cartridge_IsLoaded() (strlen(gameName) != 0)
|
||||
|
||||
typedef struct {
|
||||
unsigned int sndLevel;
|
||||
unsigned int m_ScreenRatio; // 0 = original show, 1 = full screen
|
||||
unsigned int OD_Joy[12]; // each key mapping
|
||||
unsigned int m_DisplayFPS;
|
||||
char current_dir_rom[MAX__PATH];
|
||||
unsigned int m_Color;
|
||||
} gamecfg;
|
||||
|
||||
extern char gameName[MAX__PATH];
|
||||
extern unsigned int gameCRC;
|
||||
|
||||
//typedef unsigned char byte;
|
||||
//typedef unsigned short word;
|
||||
typedef unsigned int uint;
|
||||
|
||||
extern SDL_Surface* screen; // Main program screen
|
||||
extern SDL_Surface* actualScreen; // Main program screen
|
||||
|
||||
extern SDL_Surface *layer,*layerback,*layerbackgrey;
|
||||
|
||||
extern SDL_Event event;
|
||||
|
||||
extern gamecfg GameConf;
|
||||
extern unsigned int m_Flag;
|
||||
|
||||
extern char current_conf_app[MAX__PATH];
|
||||
|
||||
extern void system_loadcfg(char *cfg_name);
|
||||
extern void system_savecfg(char *cfg_name);
|
||||
|
||||
extern unsigned long crc32 (unsigned int crc, const unsigned char *buf, unsigned int len);
|
||||
|
||||
extern void mainemuinit();
|
||||
|
||||
// menu
|
||||
extern void screen_showtopmenu(void);
|
||||
extern void print_string_video(int x, int y, const char *s);
|
||||
extern void gethomedir(char *dir, char* name);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user