mirror of
https://github.com/ARMSX2/ARMSX1.git
synced 2026-08-24 16:53:35 -07:00
first
This commit is contained in:
+2
-1
@@ -24,4 +24,5 @@ snap/
|
||||
*.iso
|
||||
*.mcd
|
||||
*.rom
|
||||
*.o
|
||||
*.o
|
||||
psxe.app
|
||||
+22
-28
@@ -1,32 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>psxe</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>psxe.app.0</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>psxe</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1-alpha</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>psxe</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.1-alpha</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.games</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.6</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>psxe</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>psxe.app.0</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>psxe</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.10.4-alpha</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.10.4-alpha</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.9</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,35 +1,65 @@
|
||||
.ONESHELL:
|
||||
|
||||
CFLAGS := -g -DLOG_USE_COLOR `sdl2-config --cflags --libs`
|
||||
CFLAGS += -Ofast -Wno-overflow -Wall -pedantic -Wno-address-of-packed-member -flto
|
||||
|
||||
PLATFORM := $(shell uname -s)
|
||||
|
||||
ifeq ($(PLATFORM),Darwin)
|
||||
CFLAGS += -mmacosx-version-min=10.9 -Wno-newline-eof
|
||||
endif
|
||||
|
||||
VERSION_TAG := $(shell git describe --always --tags --abbrev=0)
|
||||
COMMIT_HASH := $(shell git rev-parse --short HEAD)
|
||||
OS_INFO := $(shell uname -rmo)
|
||||
|
||||
SOURCES := $(wildcard psx/*.c)
|
||||
CFLAGS := -g -DLOG_USE_COLOR `sdl2-config --cflags --libs`
|
||||
CFLAGS += -Ofast -Wno-overflow -Wall -pedantic -Wno-address-of-packed-member -flto
|
||||
|
||||
PLATFORM := $(shell uname -s)
|
||||
|
||||
ifeq ($(PLATFORM),Darwin)
|
||||
CFLAGS += -mmacosx-version-min=10.9 -Wno-newline-eof
|
||||
endif
|
||||
|
||||
SHARED_EXT := .so
|
||||
SHARED_LDFLAGS := -shared
|
||||
SHARED_CFLAGS := $(CFLAGS) -D__DLL_BUILD -fPIC
|
||||
|
||||
ifeq ($(PLATFORM),Darwin)
|
||||
SHARED_EXT := .dylib
|
||||
SHARED_LDFLAGS := -dynamiclib
|
||||
endif
|
||||
|
||||
VERSION_TAG := $(shell git describe --always --tags --abbrev=0)
|
||||
COMMIT_HASH := $(shell git rev-parse --short HEAD)
|
||||
OS_INFO := $(shell uname -rmo)
|
||||
|
||||
SOURCES := $(wildcard psx/*.c)
|
||||
SOURCES += $(wildcard psx/dev/*.c)
|
||||
SOURCES += $(wildcard psx/dev/cdrom/*.c)
|
||||
SOURCES += $(wildcard psx/input/*.c)
|
||||
SOURCES += $(wildcard psx/disc/*.c)
|
||||
SOURCES += $(wildcard frontend/*.c)
|
||||
|
||||
bin/psxe frontend/main.c:
|
||||
mkdir -p bin
|
||||
|
||||
gcc $(SOURCES) -o bin/psxe \
|
||||
-I"." \
|
||||
-I"psx" \
|
||||
-DOS_INFO="$(OS_INFO)" \
|
||||
-DREP_VERSION="$(VERSION_TAG)" \
|
||||
-DREP_COMMIT_HASH="$(COMMIT_HASH)" \
|
||||
$(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf "bin"
|
||||
SOURCES += $(wildcard psx/dev/cdrom/*.c)
|
||||
SOURCES += $(wildcard psx/input/*.c)
|
||||
SOURCES += $(wildcard psx/disc/*.c)
|
||||
SOURCES += $(wildcard frontend/*.c)
|
||||
SHARED_SOURCES := $(filter-out frontend/main.c,$(SOURCES))
|
||||
|
||||
BIN_DIR := bin
|
||||
BIN := $(BIN_DIR)/psxe
|
||||
SHARED_BIN := $(BIN_DIR)/libpsxe$(SHARED_EXT)
|
||||
|
||||
.PHONY: all clean shared
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
$(BIN_DIR):
|
||||
mkdir -p $(BIN_DIR)
|
||||
|
||||
$(BIN): $(SOURCES) | $(BIN_DIR)
|
||||
gcc $(SOURCES) -o $(BIN) \
|
||||
-I"." \
|
||||
-I"psx" \
|
||||
-DOS_INFO="$(OS_INFO)" \
|
||||
-DREP_VERSION="$(VERSION_TAG)" \
|
||||
-DREP_COMMIT_HASH="$(COMMIT_HASH)" \
|
||||
$(CFLAGS)
|
||||
|
||||
shared: $(SHARED_BIN)
|
||||
|
||||
$(SHARED_BIN): $(SHARED_SOURCES) | $(BIN_DIR)
|
||||
gcc $(SHARED_LDFLAGS) $(SHARED_SOURCES) -o $(SHARED_BIN) \
|
||||
-I"." \
|
||||
-I"psx" \
|
||||
-DOS_INFO="$(OS_INFO)" \
|
||||
-DREP_VERSION="$(VERSION_TAG)" \
|
||||
-DREP_COMMIT_HASH="$(COMMIT_HASH)" \
|
||||
$(SHARED_CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf "$(BIN_DIR)"
|
||||
|
||||
@@ -12,11 +12,11 @@ A simple and portable Sony PlayStation emulator and emulation library written in
|
||||

|
||||

|
||||
|
||||
## Running
|
||||
You can download the latest automated build for your platform on Releases. If your system isn't supported, you can easily build the emulator from source, instructions on "Building" below.
|
||||
|
||||
In order to run the emulator, you will need a BIOS file. You can either get one from the internet or [dump it from your own console](https://www.youtube.com/watch?v=u8eHp0COcBo).
|
||||
|
||||
## Running
|
||||
You can download the latest automated build for your platform on Releases. If your system isn't supported, you can easily build the emulator from source, instructions on "Building" below.
|
||||
|
||||
In order to run the emulator, you will need a BIOS file. You can either get one from the internet or [dump it from your own console](https://www.youtube.com/watch?v=u8eHp0COcBo).
|
||||
|
||||
Most BIOS versions are confirmed to work.
|
||||
|
||||
Use the `-b` or `--bios` setting to configure the BIOS file.
|
||||
@@ -72,12 +72,47 @@ cd psxe
|
||||
make clean && make
|
||||
```
|
||||
|
||||
### macOS
|
||||
```
|
||||
git clone https://github.com/allkern/psxe
|
||||
cd psxe
|
||||
./build.sh
|
||||
```
|
||||
### macOS
|
||||
```
|
||||
git clone https://github.com/allkern/psxe
|
||||
cd psxe
|
||||
./build.sh
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
A `settings.toml` is generated on first run next to the executable. CLI flags always override file settings for a session.
|
||||
|
||||
### Settings file keys
|
||||
- `psxe_version` (string, managed by PSXE)
|
||||
|
||||
`[bios]`
|
||||
- `search_path` (string): directory to search for BIOS files
|
||||
- `preferred_model` (string): default model (e.g. `SCPH-1001`)
|
||||
- `override_file` (string): explicit BIOS path; leave empty to use search/model
|
||||
|
||||
`[console]`
|
||||
- `region` (string): `ntsc`, `pal`, or `auto`
|
||||
|
||||
`[video]`
|
||||
- `texture_scale_mode` (bool): enable SDL texture scale mode; toggle bilinear via F4 when supported
|
||||
|
||||
### CLI flags (override settings)
|
||||
`psxe [options] path-to-cdrom`
|
||||
- `-a, --use-args` : ignore settings file
|
||||
- `-b, --bios=<str>` : BIOS file
|
||||
- `-B, --bios-folder` : BIOS search folder
|
||||
- `-c, --console-source=<str>` : auto | null | kernel | atcons
|
||||
- `-e, --exp-rom=<str>` : expansion ROM file
|
||||
- `-L, --log-level=<int>` : 0=trace .. 5=fatal
|
||||
- `-M, --model=<str>` : console model (SCPH-XXXX)
|
||||
- `-r, --region=<str>` : console region
|
||||
- `-s, --scale=<int>` : display scaling factor
|
||||
- `-S, --settings-file=<str>` : settings file path
|
||||
- `-q, --quiet` : silence logs
|
||||
- `-x, --exe=<str>` : PS-X EXE to boot
|
||||
- `--cdrom=<str>` : CDROM image
|
||||
- `-h/--help` | `--help-model` | `--help-region` | `-v/--version` : info helpers
|
||||
|
||||
## Acknowledgements
|
||||
This project uses external open source code that can be found on the following GitHub repos:
|
||||
|
||||
@@ -1,19 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Build emulator
|
||||
make clean && make
|
||||
# Build options:
|
||||
# BUILD_DLL=1 -> build shared library (libpsxe.* with __DLL_BUILD)
|
||||
# BUILD_DLL_ONLY=1 -> build only the shared library
|
||||
# BUNDLE_APP=1 -> bundle macOS .app (uses executable build)
|
||||
|
||||
# Create bundle filesystem
|
||||
mkdir -p psxe.app/Contents/MacOS/Libraries
|
||||
make clean
|
||||
|
||||
# Move executable to folder
|
||||
mv bin/psxe psxe.app/Contents/MacOS
|
||||
if [ "${BUILD_DLL_ONLY:-0}" != "0" ]; then
|
||||
make shared
|
||||
else
|
||||
make
|
||||
if [ "${BUILD_DLL:-0}" != "0" ]; then
|
||||
make shared
|
||||
fi
|
||||
|
||||
# Make executable
|
||||
chmod 777 psxe.app/Contents/MacOS/psxe
|
||||
if [ "${BUNDLE_APP:-0}" != "0" ]; then
|
||||
# Create bundle filesystem
|
||||
mkdir -p psxe.app/Contents/MacOS/Libraries
|
||||
|
||||
# Bundle required dylibs
|
||||
dylibbundler -b -x ./psxe.app/Contents/MacOS/psxe -d ./psxe.app/Contents/Libraries/ -p @executable_path/../Libraries/ -cd
|
||||
# Copy executable to bundle folder (keep bin/psxe intact)
|
||||
cp bin/psxe psxe.app/Contents/MacOS
|
||||
|
||||
# Move plist to Contents folder
|
||||
mv Info.plist psxe.app/Contents/Info.plist
|
||||
# Make executable
|
||||
chmod 777 psxe.app/Contents/MacOS/psxe
|
||||
|
||||
# Bundle required dylibs
|
||||
dylibbundler -b -x ./psxe.app/Contents/MacOS/psxe -d ./psxe.app/Contents/Libraries/ -p @executable_path/../Libraries/ -cd
|
||||
|
||||
# Copy plist to Contents folder (keep a copy in repo for subsequent builds)
|
||||
cp Info.plist psxe.app/Contents/Info.plist
|
||||
else
|
||||
echo "Skipping macOS .app bundle. Set BUNDLE_APP=1 to build the application bundle."
|
||||
fi
|
||||
fi
|
||||
|
||||
+90
-54
@@ -19,11 +19,11 @@ static const char* g_version_text =
|
||||
"This is free software; see the source for copying conditions. There is NO\n"
|
||||
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
|
||||
|
||||
static const char g_default_settings[] =
|
||||
"# Settings file generated by PSXE\n"
|
||||
"\n"
|
||||
"# Don't change please, reserved for future use\n"
|
||||
"psxe_version = \"" STR(REP_VERSION) "\"\n"
|
||||
static const char g_default_settings[] =
|
||||
"# Settings file generated by PSXE\n"
|
||||
"\n"
|
||||
"# Don't change please, reserved for future use\n"
|
||||
"psxe_version = \"" STR(REP_VERSION) "\"\n"
|
||||
"\n"
|
||||
"# BIOS-related settings:\n"
|
||||
"[bios]\n"
|
||||
@@ -31,9 +31,13 @@ static const char g_default_settings[] =
|
||||
" preferred_model = \"SCPH-1001\"\n"
|
||||
" override_file = \"\"\n"
|
||||
"\n"
|
||||
"# Console settings\n"
|
||||
"[console]\n"
|
||||
" region = \"auto\"\n";
|
||||
"# Console settings\n"
|
||||
"[console]\n"
|
||||
" region = \"auto\"\n"
|
||||
"\n"
|
||||
"# Video settings\n"
|
||||
"[video]\n"
|
||||
" texture_scale_mode = false\n";
|
||||
|
||||
static const char* g_models_text =
|
||||
"Available console models:\n"
|
||||
@@ -78,8 +82,8 @@ void psxe_cfg_destroy(psxe_config_t* cfg) {
|
||||
free(cfg);
|
||||
}
|
||||
|
||||
void psxe_cfg_load_defaults(psxe_config_t* cfg) {
|
||||
cfg->bios = "bios.bin";
|
||||
void psxe_cfg_load_defaults(psxe_config_t* cfg) {
|
||||
cfg->bios = "bios.bin";
|
||||
cfg->bios_search = "bios";
|
||||
cfg->exe = NULL;
|
||||
cfg->help_model = 0;
|
||||
@@ -91,25 +95,39 @@ void psxe_cfg_load_defaults(psxe_config_t* cfg) {
|
||||
cfg->settings_path = NULL;
|
||||
cfg->use_args = 0;
|
||||
cfg->version = 0;
|
||||
cfg->log_level = LOG_FATAL;
|
||||
cfg->quiet = 0;
|
||||
cfg->cd_path = NULL;
|
||||
cfg->exp_path = NULL;
|
||||
}
|
||||
cfg->log_level = LOG_FATAL;
|
||||
cfg->quiet = 0;
|
||||
cfg->cd_path = NULL;
|
||||
cfg->exp_path = NULL;
|
||||
cfg->texture_scale_mode = 0;
|
||||
}
|
||||
|
||||
void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) {
|
||||
log_set_level(LOG_INFO);
|
||||
void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) {
|
||||
log_set_level(LOG_INFO);
|
||||
|
||||
// macOS .app bundles can inject a "-psn_*" argument; drop it before parsing
|
||||
const char** argv_filtered = (const char**)malloc(sizeof(char*) * argc);
|
||||
int argc_filtered = 0;
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (strncmp(argv[i], "-psn_", 5) == 0)
|
||||
continue;
|
||||
|
||||
argv_filtered[argc_filtered++] = argv[i];
|
||||
}
|
||||
|
||||
int use_args = 0;
|
||||
int version = 0;
|
||||
int use_args = 0;
|
||||
int version = 0;
|
||||
int help_model = 0;
|
||||
int help_region = 0;
|
||||
int log_level = 0;
|
||||
int quiet = 0;
|
||||
int console_source = 0;
|
||||
int scale = 0;
|
||||
const char* settings_path = NULL;
|
||||
const char* bios = NULL;
|
||||
int quiet = 0;
|
||||
int console_source = 0;
|
||||
int scale = 0;
|
||||
int texture_scale_mode = 0;
|
||||
const char* settings_path = NULL;
|
||||
const char* bios = NULL;
|
||||
int bios_from_cli = 0;
|
||||
const char* bios_search = NULL;
|
||||
const char* model = NULL;
|
||||
const char* exe = NULL;
|
||||
@@ -130,7 +148,7 @@ void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) {
|
||||
OPT_BOOLEAN ('v', "version" , &version , "Display version and build information", NULL, 0, 0),
|
||||
OPT_GROUP("Basic options"),
|
||||
OPT_BOOLEAN ('a', "use-args" , &use_args , "Ignore settings file, use CLI args instead", NULL, 0, 0),
|
||||
OPT_STRING ('b', "bios" , &bios , "Specify a BIOS file (ignores -B, -M)", NULL, 0, 0),
|
||||
OPT_STRING ('b', "bios" , &bios , "Specify a BIOS file (ignores -B, -M)", NULL, 0, 0),
|
||||
OPT_BOOLEAN ('B', "bios-folder" , &bios_search , "Specify a BIOS search folder", NULL, 0, 0),
|
||||
OPT_STRING ('c', "console-source", &console_source, "Select console source (auto, null, kernel, atcons)"),
|
||||
OPT_STRING ('e', "exp-rom" , &exp_path , "Specify an expansion ROM file"),
|
||||
@@ -147,10 +165,13 @@ void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) {
|
||||
|
||||
struct argparse argparse;
|
||||
|
||||
argparse_init(&argparse, options, usages, 0);
|
||||
argparse_describe(&argparse, NULL, g_desc_text);
|
||||
|
||||
argc = argparse_parse(&argparse, argc, argv);
|
||||
argparse_init(&argparse, options, usages, 0);
|
||||
argparse_describe(&argparse, NULL, g_desc_text);
|
||||
|
||||
argc = argparse_parse(&argparse, argc_filtered, argv_filtered);
|
||||
|
||||
if (bios)
|
||||
bios_from_cli = 1;
|
||||
|
||||
if (help_model) {
|
||||
printf("%s\n", g_models_text);
|
||||
@@ -201,10 +222,10 @@ void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) {
|
||||
toml_table_t* conf = toml_parse_file(settings, error, sizeof(error));
|
||||
|
||||
if (!conf) {
|
||||
log_error("Couldn't parse settings file");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
log_error("Couldn't parse settings file");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
toml_datum_t s_version = toml_string_in(conf, "psxe_version");
|
||||
|
||||
@@ -227,27 +248,36 @@ void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) {
|
||||
if (s_bios_preferred_model.ok)
|
||||
model = s_bios_preferred_model.u.s;
|
||||
|
||||
toml_datum_t s_bios_override_file = toml_string_in(s_bios_table, "override_file");
|
||||
|
||||
if (s_bios_override_file.ok)
|
||||
bios = s_bios_override_file.u.s;
|
||||
toml_datum_t s_bios_override_file = toml_string_in(s_bios_table, "override_file");
|
||||
|
||||
if (!bios_from_cli && s_bios_override_file.ok && s_bios_override_file.u.s[0])
|
||||
bios = s_bios_override_file.u.s;
|
||||
}
|
||||
|
||||
toml_table_t* s_console_table = toml_table_in(conf, "console");
|
||||
|
||||
if (s_console_table) {
|
||||
toml_datum_t s_console_region = toml_string_in(s_console_table, "region");
|
||||
|
||||
if (s_console_region.ok)
|
||||
region = s_console_region.u.s;
|
||||
}
|
||||
|
||||
psxe_version = s_version.u.s;
|
||||
if (s_console_table) {
|
||||
toml_datum_t s_console_region = toml_string_in(s_console_table, "region");
|
||||
|
||||
if (s_console_region.ok)
|
||||
region = s_console_region.u.s;
|
||||
}
|
||||
|
||||
toml_table_t* s_video_table = toml_table_in(conf, "video");
|
||||
|
||||
if (s_video_table) {
|
||||
toml_datum_t s_texture_scale_mode = toml_bool_in(s_video_table, "texture_scale_mode");
|
||||
|
||||
if (s_texture_scale_mode.ok)
|
||||
texture_scale_mode = s_texture_scale_mode.u.b;
|
||||
}
|
||||
|
||||
psxe_version = s_version.u.s;
|
||||
|
||||
log_info("Settings file parsed. PSXE version: %s", psxe_version);
|
||||
|
||||
fclose(settings);
|
||||
}
|
||||
fclose(settings);
|
||||
}
|
||||
|
||||
if (argc) {
|
||||
if (argc > 1) {
|
||||
@@ -283,12 +313,18 @@ void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) {
|
||||
if (psxe_version)
|
||||
cfg->psxe_version = psxe_version;
|
||||
|
||||
if (exp_path)
|
||||
cfg->exp_path = exp_path;
|
||||
|
||||
if (scale)
|
||||
cfg->scale = scale;
|
||||
}
|
||||
if (exp_path)
|
||||
cfg->exp_path = exp_path;
|
||||
|
||||
if (scale)
|
||||
cfg->scale = scale;
|
||||
|
||||
cfg->texture_scale_mode = texture_scale_mode;
|
||||
|
||||
log_info("Using BIOS path: %s", cfg->bios ? cfg->bios : "(none)");
|
||||
|
||||
free(argv_filtered);
|
||||
}
|
||||
|
||||
// To-do: Implement BIOS searching
|
||||
char* psxe_cfg_get_bios_path(psxe_config_t* cfg) {
|
||||
@@ -296,4 +332,4 @@ char* psxe_cfg_get_bios_path(psxe_config_t* cfg) {
|
||||
}
|
||||
|
||||
#undef STR1
|
||||
#undef STR
|
||||
#undef STR
|
||||
|
||||
+12
-11
@@ -10,16 +10,17 @@ typedef struct {
|
||||
int use_args;
|
||||
int version;
|
||||
int help_model;
|
||||
int help_region;
|
||||
int log_level;
|
||||
int quiet;
|
||||
int console_source;
|
||||
int scale;
|
||||
const char* snap_path;
|
||||
const char* settings_path;
|
||||
const char* bios;
|
||||
const char* bios_search;
|
||||
const char* model;
|
||||
int help_region;
|
||||
int log_level;
|
||||
int quiet;
|
||||
int console_source;
|
||||
int scale;
|
||||
int texture_scale_mode;
|
||||
const char* snap_path;
|
||||
const char* settings_path;
|
||||
const char* bios;
|
||||
const char* bios_search;
|
||||
const char* model;
|
||||
const char* exe;
|
||||
const char* region;
|
||||
const char* psxe_version;
|
||||
@@ -34,4 +35,4 @@ void psxe_cfg_load(psxe_config_t*, int, const char**);
|
||||
char* psxe_cfg_get_bios_path(psxe_config_t*);
|
||||
void psxe_cfg_destroy(psxe_config_t*);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+15
-10
@@ -37,21 +37,26 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
log_set_level(cfg->log_level);
|
||||
|
||||
psx_t* psx = psx_create();
|
||||
psx_init(psx, cfg->bios, cfg->exp_path);
|
||||
psx_t* psx = psx_create();
|
||||
int init_result = psx_init(psx, cfg->bios, cfg->exp_path);
|
||||
|
||||
if (init_result) {
|
||||
log_fatal("Failed to initialize PSX (code %d). Check BIOS/expansion paths and settings.", init_result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
psx_cdrom_t* cdrom = psx_get_cdrom(psx);
|
||||
|
||||
// To-do: Set CDROM firmware version and region based
|
||||
// on CLI options
|
||||
|
||||
if (cfg->cd_path)
|
||||
psx_cdrom_open(cdrom, cfg->cd_path);
|
||||
|
||||
psxe_screen_t* screen = psxe_screen_create();
|
||||
psxe_screen_init(screen, psx);
|
||||
psxe_screen_set_scale(screen, cfg->scale);
|
||||
psxe_screen_reload(screen);
|
||||
if (cfg->cd_path)
|
||||
psx_cdrom_open(cdrom, cfg->cd_path);
|
||||
|
||||
psxe_screen_t* screen = psxe_screen_create();
|
||||
psxe_screen_init(screen, psx, cfg);
|
||||
psxe_screen_set_scale(screen, cfg->scale);
|
||||
psxe_screen_reload(screen);
|
||||
|
||||
SDL_Init(SDL_INIT_AUDIO);
|
||||
|
||||
@@ -126,4 +131,4 @@ int main(int argc, const char* argv[]) {
|
||||
psxe_screen_destroy(screen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
+92
-59
@@ -1,7 +1,8 @@
|
||||
#include "screen.h"
|
||||
|
||||
#include "input/sda.h"
|
||||
#include "input/guncon.h"
|
||||
#include "screen.h"
|
||||
|
||||
#include "input/sda.h"
|
||||
#include "input/guncon.h"
|
||||
#include "../psx/log.h"
|
||||
|
||||
uint32_t screen_get_button(SDL_Keycode k) {
|
||||
if (k == SDLK_x ) return PSXI_SW_SDA_CROSS;
|
||||
@@ -66,16 +67,30 @@ int screen_get_base_width(psxe_screen_t* screen) {
|
||||
return 320;
|
||||
}
|
||||
|
||||
psxe_screen_t* psxe_screen_create(void) {
|
||||
return (psxe_screen_t*)malloc(sizeof(psxe_screen_t));
|
||||
}
|
||||
|
||||
void psxe_screen_init(psxe_screen_t* screen, psx_t* psx) {
|
||||
memset(screen, 0, sizeof(psxe_screen_t));
|
||||
|
||||
if (screen->debug_mode) {
|
||||
screen->width = PSX_GPU_FB_WIDTH;
|
||||
screen->height = PSX_GPU_FB_HEIGHT;
|
||||
psxe_screen_t* psxe_screen_create(void) {
|
||||
return (psxe_screen_t*)malloc(sizeof(psxe_screen_t));
|
||||
}
|
||||
|
||||
static void psxe_screen_apply_texture_scale_mode(psxe_screen_t* screen) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 12)
|
||||
if (!screen->texture_scale_mode)
|
||||
return;
|
||||
|
||||
SDL_ScaleMode scale_mode = screen->bilinear ? SDL_ScaleModeLinear : SDL_ScaleModeNearest;
|
||||
|
||||
if (SDL_SetTextureScaleMode(screen->texture, scale_mode) < 0) {
|
||||
log_warn("SDL_SetTextureScaleMode failed, disabling texture_scale_mode: %s", SDL_GetError());
|
||||
screen->texture_scale_mode = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void psxe_screen_init(psxe_screen_t* screen, psx_t* psx, const psxe_config_t* cfg) {
|
||||
memset(screen, 0, sizeof(psxe_screen_t));
|
||||
|
||||
if (screen->debug_mode) {
|
||||
screen->width = PSX_GPU_FB_WIDTH;
|
||||
screen->height = PSX_GPU_FB_HEIGHT;
|
||||
} else {
|
||||
screen->width = 320;
|
||||
screen->height = 240;
|
||||
@@ -83,23 +98,29 @@ void psxe_screen_init(psxe_screen_t* screen, psx_t* psx) {
|
||||
|
||||
screen->scale = 1;
|
||||
screen->open = 1;
|
||||
screen->format = SDL_PIXELFORMAT_BGR555;
|
||||
screen->psx = psx;
|
||||
screen->pad = psx_get_pad(psx);
|
||||
|
||||
screen->texture_width = PSX_GPU_FB_WIDTH;
|
||||
screen->texture_height = PSX_GPU_FB_HEIGHT;
|
||||
screen->format = SDL_PIXELFORMAT_BGR555;
|
||||
screen->psx = psx;
|
||||
screen->pad = psx_get_pad(psx);
|
||||
screen->texture_scale_mode = cfg ? cfg->texture_scale_mode : 0;
|
||||
screen->bilinear = screen->texture_scale_mode ? SDL_ScaleModeLinear : SDL_ScaleModeNearest;
|
||||
|
||||
screen->texture_width = PSX_GPU_FB_WIDTH;
|
||||
screen->texture_height = PSX_GPU_FB_HEIGHT;
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER);
|
||||
SDL_SetRenderDrawColor(screen->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
|
||||
screen->controller = screen_find_controller();
|
||||
}
|
||||
|
||||
void psxe_screen_reload(psxe_screen_t* screen) {
|
||||
if (screen->texture) SDL_DestroyTexture(screen->texture);
|
||||
if (screen->renderer) SDL_DestroyRenderer(screen->renderer);
|
||||
if (screen->window) SDL_DestroyWindow(screen->window);
|
||||
screen->controller = screen_find_controller();
|
||||
}
|
||||
|
||||
void psxe_screen_set_window_handle(psxe_screen_t* screen, void* native_handle) {
|
||||
screen->external_window = native_handle;
|
||||
}
|
||||
|
||||
void psxe_screen_reload(psxe_screen_t* screen) {
|
||||
if (screen->texture) SDL_DestroyTexture(screen->texture);
|
||||
if (screen->renderer) SDL_DestroyRenderer(screen->renderer);
|
||||
if (screen->window) SDL_DestroyWindow(screen->window);
|
||||
|
||||
if (screen->debug_mode) {
|
||||
screen->width = PSX_GPU_FB_WIDTH;
|
||||
@@ -113,14 +134,30 @@ void psxe_screen_reload(psxe_screen_t* screen) {
|
||||
screen->height = 240;
|
||||
}
|
||||
}
|
||||
|
||||
screen->window = SDL_CreateWindow(
|
||||
"psxe " STR(REP_VERSION) "-" STR(REP_COMMIT_HASH),
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
screen->width * screen->scale,
|
||||
screen->height * screen->scale,
|
||||
0
|
||||
);
|
||||
|
||||
#ifndef __DLL_BUILD
|
||||
screen->window = SDL_CreateWindow(
|
||||
"psxe " STR(REP_VERSION) "-" STR(REP_COMMIT_HASH),
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
screen->width * screen->scale,
|
||||
screen->height * screen->scale,
|
||||
0
|
||||
);
|
||||
#else
|
||||
if (!screen->external_window) {
|
||||
log_error("DLL build requires external window handle before reload");
|
||||
screen->open = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
screen->window = SDL_CreateWindowFrom(screen->external_window);
|
||||
|
||||
if (!screen->window) {
|
||||
log_error("Failed to create SDL window from external handle: %s", SDL_GetError());
|
||||
screen->open = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
screen->renderer = SDL_CreateRenderer(
|
||||
screen->window,
|
||||
@@ -128,16 +165,14 @@ void psxe_screen_reload(psxe_screen_t* screen) {
|
||||
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
|
||||
);
|
||||
|
||||
screen->texture = SDL_CreateTexture(
|
||||
screen->renderer,
|
||||
screen->format,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
screen->texture_width, screen->texture_height
|
||||
);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 12)
|
||||
SDL_SetTextureScaleMode(screen->texture, screen->bilinear);
|
||||
#endif
|
||||
screen->texture = SDL_CreateTexture(
|
||||
screen->renderer,
|
||||
screen->format,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
screen->texture_width, screen->texture_height
|
||||
);
|
||||
|
||||
psxe_screen_apply_texture_scale_mode(screen);
|
||||
|
||||
// Check for retina displays
|
||||
int width = 0, height = 0;
|
||||
@@ -511,19 +546,17 @@ void psxe_gpu_dmode_event_cb(psx_gpu_t* gpu) {
|
||||
|
||||
SDL_DestroyTexture(screen->texture);
|
||||
|
||||
screen->texture = SDL_CreateTexture(
|
||||
screen->renderer,
|
||||
screen->format,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
screen->texture_width, screen->texture_height
|
||||
);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 12)
|
||||
SDL_SetTextureScaleMode(screen->texture, screen->bilinear);
|
||||
#endif
|
||||
|
||||
SDL_SetWindowSize(screen->window, screen->width, screen->height);
|
||||
}
|
||||
screen->texture = SDL_CreateTexture(
|
||||
screen->renderer,
|
||||
screen->format,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
screen->texture_width, screen->texture_height
|
||||
);
|
||||
|
||||
psxe_screen_apply_texture_scale_mode(screen);
|
||||
|
||||
SDL_SetWindowSize(screen->window, screen->width, screen->height);
|
||||
}
|
||||
|
||||
void psxe_gpu_vblank_event_cb(psx_gpu_t* gpu) {
|
||||
psxe_screen_t* screen = gpu->udata[0];
|
||||
@@ -531,4 +564,4 @@ void psxe_gpu_vblank_event_cb(psx_gpu_t* gpu) {
|
||||
psxe_screen_update(screen);
|
||||
|
||||
psxe_gpu_vblank_timer_event_cb(gpu);
|
||||
}
|
||||
}
|
||||
|
||||
+23
-19
@@ -1,8 +1,9 @@
|
||||
#ifndef SCREEN_H
|
||||
#define SCREEN_H
|
||||
|
||||
#include "../psx/psx.h"
|
||||
#include "common.h"
|
||||
#include "../psx/psx.h"
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -22,29 +23,32 @@ typedef struct {
|
||||
unsigned int width, height, scale;
|
||||
unsigned int image_width, image_height;
|
||||
unsigned int image_xoff, image_yoff;
|
||||
unsigned int format;
|
||||
unsigned int texture_width, texture_height;
|
||||
|
||||
int bilinear;
|
||||
int fullscreen;
|
||||
int vertical_mode;
|
||||
int debug_mode;
|
||||
int open;
|
||||
unsigned int format;
|
||||
unsigned int texture_width, texture_height;
|
||||
|
||||
void* external_window;
|
||||
int texture_scale_mode;
|
||||
int bilinear;
|
||||
int fullscreen;
|
||||
int vertical_mode;
|
||||
int debug_mode;
|
||||
int open;
|
||||
|
||||
SDL_GameController* controller;
|
||||
} psxe_screen_t;
|
||||
|
||||
psxe_screen_t* psxe_screen_create(void);
|
||||
void psxe_screen_init(psxe_screen_t*, psx_t*);
|
||||
void psxe_screen_reload(psxe_screen_t*);
|
||||
int psxe_screen_is_open(psxe_screen_t*);
|
||||
void psxe_screen_update(psxe_screen_t*);
|
||||
void psxe_screen_destroy(psxe_screen_t*);
|
||||
void psxe_screen_set_scale(psxe_screen_t*, unsigned int);
|
||||
void psxe_screen_toggle_debug_mode(psxe_screen_t*);
|
||||
psxe_screen_t* psxe_screen_create(void);
|
||||
void psxe_screen_init(psxe_screen_t*, psx_t*, const psxe_config_t*);
|
||||
void psxe_screen_reload(psxe_screen_t*);
|
||||
int psxe_screen_is_open(psxe_screen_t*);
|
||||
void psxe_screen_update(psxe_screen_t*);
|
||||
void psxe_screen_destroy(psxe_screen_t*);
|
||||
void psxe_screen_set_scale(psxe_screen_t*, unsigned int);
|
||||
void psxe_screen_set_window_handle(psxe_screen_t*, void* native_handle);
|
||||
void psxe_screen_toggle_debug_mode(psxe_screen_t*);
|
||||
|
||||
// GPU event handlers
|
||||
void psxe_gpu_dmode_event_cb(psx_gpu_t*);
|
||||
void psxe_gpu_vblank_event_cb(psx_gpu_t*);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+25
-20
@@ -1,13 +1,14 @@
|
||||
#include "bios.h"
|
||||
#include "../log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
psx_bios_t* psx_bios_create(void) {
|
||||
return (psx_bios_t*)malloc(sizeof(psx_bios_t));
|
||||
}
|
||||
#include "../log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
psx_bios_t* psx_bios_create(void) {
|
||||
return (psx_bios_t*)malloc(sizeof(psx_bios_t));
|
||||
}
|
||||
|
||||
void psx_bios_init(psx_bios_t* bios) {
|
||||
memset(bios, 0, sizeof(psx_bios_t));
|
||||
@@ -17,14 +18,16 @@ void psx_bios_init(psx_bios_t* bios) {
|
||||
bios->bus_delay = 18;
|
||||
}
|
||||
|
||||
int psx_bios_load(psx_bios_t* bios, const char* path) {
|
||||
if (!path)
|
||||
return 0;
|
||||
|
||||
FILE* file = fopen(path, "rb");
|
||||
|
||||
if (!file)
|
||||
return 1;
|
||||
int psx_bios_load(psx_bios_t* bios, const char* path) {
|
||||
if (!path)
|
||||
return 0;
|
||||
|
||||
FILE* file = fopen(path, "rb");
|
||||
|
||||
if (!file) {
|
||||
log_error("Failed to open BIOS at '%s': %s", path, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Almost all PS1 BIOS ROMs are 512 KiB in size.
|
||||
// There's (at least) one exception, and that is SCPH-5903.
|
||||
@@ -40,8 +43,10 @@ int psx_bios_load(psx_bios_t* bios, const char* path) {
|
||||
bios->buf = malloc(size);
|
||||
bios->io_size = size;
|
||||
|
||||
if (!fread(bios->buf, 1, size, file))
|
||||
return 2;
|
||||
if (!fread(bios->buf, 1, size, file)) {
|
||||
log_error("Failed to read BIOS at '%s': %s", path, strerror(errno));
|
||||
return 2;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
@@ -75,4 +80,4 @@ void psx_bios_write8(psx_bios_t* bios, uint32_t offset, uint8_t value) {
|
||||
void psx_bios_destroy(psx_bios_t* bios) {
|
||||
free(bios->buf);
|
||||
free(bios);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-1
@@ -4,6 +4,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "cdrom.h"
|
||||
#include "../../log.h"
|
||||
|
||||
typedef void (*cdrom_cmd_func)(psx_cdrom_t* cdrom);
|
||||
|
||||
@@ -194,11 +195,21 @@ int psx_cdrom_open(psx_cdrom_t* cdrom, const char* path) {
|
||||
cdrom->disc_type = psx_disc_open(cdrom->disc, path);
|
||||
|
||||
if (cdrom->disc_type == CDT_ERROR) {
|
||||
log_error("Failed to open CD image: %s", path);
|
||||
psx_cdrom_close(cdrom);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cdrom->disc_type != CDT_LICENSED) {
|
||||
log_error("CD image not recognized as a licensed PSX disc (type=%d). Use a proper BIN/CUE rip.", cdrom->disc_type);
|
||||
psx_cdrom_close(cdrom);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_info("CD image type: Licensed");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -759,4 +770,4 @@ void psx_cdrom_write32(psx_cdrom_t* cdrom, uint32_t addr, uint32_t value) {
|
||||
|
||||
void psx_cdrom_write16(psx_cdrom_t* cdrom, uint32_t addr, uint32_t value) {
|
||||
assert("16-bit CDROM writes are not supported" && 0);
|
||||
}
|
||||
}
|
||||
|
||||
+100
-2
@@ -1,8 +1,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "disc.h"
|
||||
#include "cue.h"
|
||||
#include "../../log.h"
|
||||
|
||||
#define MSF_TO_LBA(m, s, f) ((m * 4500) + (s * 75) + f)
|
||||
|
||||
@@ -13,8 +15,67 @@ const char* disc_cd_extensions[] = {
|
||||
0
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
FILE* file;
|
||||
uint32_t sector_size;
|
||||
uint32_t sector_count;
|
||||
} raw_disc_t;
|
||||
|
||||
static int raw_read(void* udata, uint32_t lba, void* buf) {
|
||||
raw_disc_t* raw = (raw_disc_t*)udata;
|
||||
|
||||
if (!raw || !raw->file)
|
||||
return 0;
|
||||
|
||||
if (lba >= raw->sector_count)
|
||||
return 0;
|
||||
|
||||
if (fseek(raw->file, (long long)lba * raw->sector_size, SEEK_SET))
|
||||
return 0;
|
||||
|
||||
size_t to_read = raw->sector_size;
|
||||
memset(buf, 0, CD_SECTOR_SIZE);
|
||||
|
||||
return fread(buf, 1, to_read, raw->file) == to_read ? TS_DATA : 0;
|
||||
}
|
||||
|
||||
static int raw_query(void* udata, uint32_t lba) {
|
||||
raw_disc_t* raw = (raw_disc_t*)udata;
|
||||
|
||||
return (raw && (lba < raw->sector_count)) ? TS_DATA : TS_FAR;
|
||||
}
|
||||
|
||||
static int raw_get_track_number(void* udata, uint32_t lba) {
|
||||
(void)udata; (void)lba;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int raw_get_track_count(void* udata) {
|
||||
(void)udata;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t raw_get_track_lba(void* udata, int track) {
|
||||
(void)udata; (void)track;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void raw_destroy(void* udata) {
|
||||
raw_disc_t* raw = (raw_disc_t*)udata;
|
||||
|
||||
if (raw && raw->file)
|
||||
fclose(raw->file);
|
||||
|
||||
free(raw);
|
||||
}
|
||||
|
||||
psx_disc_t* psx_disc_create(void) {
|
||||
return malloc(sizeof(psx_disc_t));
|
||||
psx_disc_t* disc = malloc(sizeof(psx_disc_t));
|
||||
|
||||
if (disc)
|
||||
memset(disc, 0, sizeof(psx_disc_t));
|
||||
|
||||
return disc;
|
||||
}
|
||||
|
||||
int disc_get_extension(const char* path) {
|
||||
@@ -81,12 +142,49 @@ int psx_disc_open_as(psx_disc_t* disc, const char* path, int type) {
|
||||
if (cue_load(cue, LD_FILE))
|
||||
return CDT_ERROR;
|
||||
} break;
|
||||
|
||||
case CD_EXT_BIN:
|
||||
case CD_EXT_ISO: {
|
||||
FILE* f = fopen(path, "rb");
|
||||
|
||||
if (!f)
|
||||
return CDT_ERROR;
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
long long size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
raw_disc_t* raw = (raw_disc_t*)malloc(sizeof(raw_disc_t));
|
||||
|
||||
raw->file = f;
|
||||
raw->sector_size = (type == CD_EXT_BIN) ? CD_SECTOR_SIZE : 2048;
|
||||
raw->sector_count = (uint32_t)(size / raw->sector_size);
|
||||
|
||||
disc->udata = raw;
|
||||
disc->read_sector = raw_read;
|
||||
disc->query_sector = raw_query;
|
||||
disc->get_track_number = raw_get_track_number;
|
||||
disc->get_track_count = raw_get_track_count;
|
||||
disc->get_track_lba = raw_get_track_lba;
|
||||
disc->destroy = raw_destroy;
|
||||
} break;
|
||||
|
||||
default:
|
||||
return CDT_ERROR;
|
||||
}
|
||||
|
||||
if (!disc->read_sector) {
|
||||
log_error("Unsupported or failed to open disc image: %s", path);
|
||||
return CDT_ERROR;
|
||||
}
|
||||
|
||||
return disc_get_cd_type(disc);
|
||||
}
|
||||
|
||||
int psx_disc_read(psx_disc_t* disc, uint32_t lba, void* buf) {
|
||||
if (!disc->read_sector)
|
||||
return 0;
|
||||
|
||||
return disc->read_sector(disc->udata, lba, buf);
|
||||
}
|
||||
|
||||
@@ -110,4 +208,4 @@ void psx_disc_destroy(psx_disc_t* disc) {
|
||||
disc->destroy(disc->udata);
|
||||
|
||||
free(disc);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user