* 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:
libretroadmin 2022-06-20 06:59:00 +02:00
parent 3e3bfd7873
commit 0220ce3acb
64 changed files with 74 additions and 21808 deletions

View File

@ -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

View File

@ -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
#---------------------------------------------------------------------------------------

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 +

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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) +

View File

@ -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);

View File

@ -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
*/

View File

@ -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() +

View File

@ -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

View File

@ -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

View File

@ -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
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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(&currentConfig, 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(&currentConfig, 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(&currentConfig, 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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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()));
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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})

View File

@ -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, &current);
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);
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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, "&amp;");
//text = text.replace(/</g, "&lt;");
//text = text.replace(/>/g, "&gt;");
//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>

View File

@ -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.

View File

@ -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

View File

@ -1,2 +0,0 @@
rm potator.opk
mksquashfs potator potator.opk

View File

@ -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

View File

@ -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
--------------------------------------------------------------------------------

View File

@ -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;
}

View File

@ -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
}

View File

@ -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
--------------------------------------------------------------------------------

View File

@ -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