Compare commits

...
55 Commits
Author SHA1 Message Date
kichikuou 065e16a082 Version 2.11.4 2024-05-22 13:38:33 +09:00
kichikuou 3699aa5c2d Windows: Hide menu bar in fullscreen mode
The menu bar is displayed when the mouse is moved to the top of the
screen, like System39.exe's full-screen mode.

This fixes https://github.com/kichikuou/xsystem35-sdl2/issues/53.
2024-05-22 13:37:12 +09:00
kichikuou 20914970c9 Fix text rendering issue in Rance 3 OP
This fixes https://github.com/kichikuou/xsystem35-sdl2/issues/54.
2024-05-22 09:13:09 +09:00
kichikuou 3f2f555aa6 Add a link to SDL issue 2024-05-16 20:55:35 +09:00
kichikuou 095da0bb86 Version 2.11.3 2024-04-11 09:12:55 +09:00
kichikuou 7b8acd6e05 Use lowercase s[a-z].asd in Android and Emscripten
To make sure that save files created in older versions can be loaded.
2024-04-11 09:10:39 +09:00
kichikuou 1b13e331e4 emscripten: Enable msgskip in initGameResourceFromDir()
This is in preparation to stop using xsystem35.gr in Kichikuou on Web,
without changing the current behavior.
2024-04-11 09:00:42 +09:00
kichikuou 5621ab4d86 Version 2.11.2 2024-04-10 17:21:55 +09:00
kichikuou 79805d9ea2 Android: Update SDL, SDL_ttf and SDL_mixer 2024-04-10 15:32:40 +09:00
kichikuou f427d50fa3 Android: Remove playlist migration code
And stop using -playlist option, so that it can be overridden by
.xsys35rc.
2024-04-10 15:07:07 +09:00
kichikuou 7c7768fba4 Android: Improve installation when game is in non-root directory of ZIP
Launcher.kt extracts given ZIP file to the internal storage, preserving
its directory structure.

Before this change, if the game files were in a subdirectory, an
xsystem35.gr file was generated containing the path to the game files.
However, with this method, .xsys35rc and some data files (such as map
files of Kaeru Nyo) could not be loaded.

After this change, Launcher.kt will no longer generate the xsystem35.gr
file. Instead, it records the directory where the game is located in
game_directory.txt, and specify that directory in -gamedir to launch
xsystem35.

Fixes #51.
2024-04-10 15:06:51 +09:00
kichikuou 2b6267aeb9 Create save directory if it doesn't exist 2024-04-10 14:37:21 +09:00
kichikuou 16e7d3baf1 Add -savedir option
It allows specifying a save directory without writing a game resource
file.
2024-04-10 14:37:21 +09:00
kichikuou 2d8d95ac6f emscripten: Simplify link options 2024-03-12 17:03:57 +09:00
kichikuou d5899ff55a emscripten: Add return in wait_vsync
To make it work with ASYNCIFY=2.
2024-03-12 13:04:30 +09:00
kichikuou 04037682ee Version 2.11.1 2024-02-18 10:36:16 +09:00
kichikuou cdb16f73a3 Read link table only from first ALD volume
This fixes https://github.com/kichikuou/xsystem35-sdl2/issues/45.

The behavior when the contents of link table differ between ALD volumes
is different between System 3.8 and System 3.9, and System 3.9 uses the
link table of the first volume. The MangaGamer version of Rance 5D
depends on this behavior.

As far as I know, the only game that depends on the System 3.8 behavior
is Child Assassin (in Alice CD 2.50). Considering the additional
complexity, we do not implement switching to the old behavior.
2024-02-18 10:28:13 +09:00
kichikuou 2895e338c0 Fix a crash in command-line debugger 2024-02-18 08:36:15 +09:00
kichikuou 1a2268e94b Update emscripten to 3.1.54 2024-02-16 12:44:00 +09:00
kichikuou 07643c82a4 emscripten: Don't let SDL change document.title 2024-02-16 12:44:00 +09:00
kichikuou a16156f8e4 CMake: Generate compile_commands.json 2024-01-28 11:26:05 +09:00
kichikuou ea5cef91fd Rename cdrom_device profile to playlist
Also renames `-devcd` command line flag to `-playlist`.

The old names can still be used for backwards compatibility.
2024-01-28 10:28:15 +09:00
kichikuou 48a41b9f82 Require SDL2_mixer on non-Emscripten platforms 2024-01-28 10:20:42 +09:00
kichikuou c11c80d95d Remove CD-ROM device support
This removes (old, unmaintained) real CD-ROM support for Linux and
FreeBSD. It may be possible to implement cross-platform CD support using
libcdio (https://www.gnu.org/software/libcdio/), but it would not be
worth the effort given the low avilability of hardware that can play
CD-DA these days.
2024-01-28 10:20:32 +09:00
kichikuou d7082a9d80 CI: Update GitHub actions 2024-01-27 10:40:17 +09:00
kichikuou 083cf885de CI: Enable COMPILE_WARNING_AS_ERROR on Windows and Emscripten 2024-01-27 10:25:15 +09:00
kichikuou 7b1fef4ad7 Fix a deprecated-non-prototype warning 2024-01-27 09:08:31 +09:00
kichikuou f039baf061 Refactor CMakeLists.txt 2024-01-21 08:49:30 +09:00
kichikuou 22c6b8e963 Version 2.11.0 2024-01-20 13:57:18 +09:00
kichikuou 576afecbfc Update xsys35rc.sample and include it in the package 2024-01-20 13:13:02 +09:00
kichikuou 4e28d92a2d Windows: Load %USERPROFILE%/.xys35rc if %HOME% is not set 2024-01-20 12:42:17 +09:00
kichikuou 22192c245f Windows: Remove game selection dialog 2024-01-20 11:55:29 +09:00
kichikuou 409fa83406 Windows CI: Add packaging step 2024-01-20 11:35:04 +09:00
kichikuou 894b0592f4 Windows: Remove installer 2024-01-20 11:04:43 +09:00
kichikuou 370100a6f2 Windows: Fix static library options 2024-01-20 09:59:10 +09:00
kichikuou 18cfbc90f2 Windows: Do not read profile from registry
This was only used for the default font path, so it should be safe to
remove it.
2024-01-20 09:38:44 +09:00
kichikuou cd51dc7f02 Windows: Embed fonts as PE resources 2024-01-20 09:30:10 +09:00
kichikuou e2638ed840 Refactor CMakeLists.txt using alias targets 2024-01-19 14:56:50 +09:00
kichikuou 6607815df3 MSYS build: Use static linking 2024-01-19 14:55:53 +09:00
kichikuou 77ed85aff7 Display error when debugger is requested but not available 2024-01-18 10:49:31 +09:00
kichikuou 3b1a311f32 CI: Disable debugger on MinGW32 build
The 32-bit cJSON package was removed from MSYS2.
2024-01-18 10:16:54 +09:00
kichikuou 1b3c2190b8 profile: get_profile() returns const char* 2024-01-18 10:16:54 +09:00
kichikuou 52e2d6095a profile: Allow various boolean expressions
In .xsys35rc, now "yes", "true", "on", "1" (case insensitive) mean true
and "no", "false", "off", "0" mean false.
2024-01-18 10:16:48 +09:00
kichikuou 47e2fcaec0 Add enable_zb option for enabling ZB command
By default it is disabled and normal weight is always used.

Issue: https://github.com/kichikuou/xsystem35-sdl2/issues/44
2024-01-18 08:27:46 +09:00
kichikuou 183ceb614a Implement ZB command
Although undocumented, it also affects the font weight of selection
window.

Issue: https://github.com/kichikuou/xsystem35-sdl2/issues/44
2024-01-17 14:32:32 +09:00
kichikuou 185e62010b Fix argument range check in commands2F60() 2024-01-14 11:35:35 +09:00
kichikuou 6f647701dd Android CMake: Use FetchContent_MakeAvailable 2024-01-13 16:18:38 +09:00
kichikuou a9c79b2e31 sysGetOSName: Use SDL_GetPlatform() 2024-01-11 14:08:31 +09:00
kichikuou ba52fbf5e9 Version 2.10.1 2024-01-01 13:17:44 +09:00
kichikuou 85d40701c4 Palette 246-249 should be preserved when loading PMS8 2024-01-01 12:46:13 +09:00
kichikuou 7b535b371a Fix initial palette values
These match the System3.9 default colors that came from the default
system colors in Windows 256-color mode [1].

[1] https://en.wikipedia.org/wiki/List_of_software_palettes#Microsoft_Windows_default_20-color_palette
2024-01-01 12:25:43 +09:00
kichikuou c0dbae8202 Refactor palette data structure 2024-01-01 11:47:11 +09:00
kichikuou ca03450b87 Windows: Add menu command for integer scaling 2023-12-15 10:46:06 +09:00
kichikuou f795a500cf Update emscripten to 3.1.50 2023-12-10 13:24:49 +09:00
kichikuou 3314f00bf8 Fix cdGetMaxTrack for download edition of Daiakuji
It should return the maximum index of the BGM archive.

Fixes #43.
2023-12-09 14:57:01 +09:00
88 changed files with 934 additions and 1628 deletions
+2 -2
View File
@@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Deps
run: sudo apt install ninja-build
@@ -22,7 +22,7 @@ jobs:
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: xsystem35-apk
path: android/app/build/outputs/apk/release/app-release.apk
+7 -7
View File
@@ -2,7 +2,7 @@ name: Emscripten Build
on: [push, pull_request]
env:
EM_VERSION: 3.1.34
EM_VERSION: 3.1.54
EM_CACHE_FOLDER: 'emsdk-cache'
jobs:
@@ -10,17 +10,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup cache
id: cache-system-libraries
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{env.EM_CACHE_FOLDER}}
key: ${{env.EM_VERSION}}-${{ runner.os }}
- name: Setup Emscripten toolchain
uses: mymindstorm/setup-emsdk@v12
uses: mymindstorm/setup-emsdk@v14
with:
version: ${{ env.EM_VERSION }}
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
@@ -29,13 +29,13 @@ jobs:
run: |
mkdir -p out/wasm
cd out/wasm
emcmake cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../../
make
emcmake cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_COMPILE_WARNING_AS_ERROR=YES ../../
make -j4
mkdir xsystem35
mv src/xsystem35.* xsystem35/
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: xsystem35-wasm
path: out/wasm/xsystem35
+2 -2
View File
@@ -10,7 +10,7 @@ jobs:
name: Linux ${{ matrix.build-type }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Deps
run: |
@@ -22,7 +22,7 @@ jobs:
mkdir -p out/${{ matrix.build-type }}
cd out/${{ matrix.build-type }}
cmake -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} ../../
make
make -j4
- name: Test
run: ctest --output-on-failure
+28 -15
View File
@@ -5,10 +5,17 @@ jobs:
build:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- { sys: MINGW32, installer: "xsystem35-32bit" }
- { sys: UCRT64, installer: "xsystem35-64bit" }
- sys: mingw32
package: "xsystem35-32bit"
cmake_args: "-DENABLE_DEBUGGER=no"
deps: ""
- sys: ucrt64
package: "xsystem35-64bit"
cmake_args: ""
deps: "cjson:p"
defaults:
run:
shell: msys2 {0}
@@ -20,25 +27,30 @@ jobs:
with:
msystem: ${{ matrix.sys }}
pacboy: >-
gcc:p
cmake:p
ninja:p
SDL2:p
SDL2_ttf:p
SDL2_mixer:p
libwebp:p
cjson:p
nsis:p
ntldd:p
${{ matrix.deps }}
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Copy licenses
run: |
ls /${{ matrix.sys }}/share/licenses
mkdir dist
cp -r /${{ matrix.sys }}/share/licenses dist/
cp fonts/*.license dist/licenses/
- name: Install dev dependencies
run: pacboy --noconfirm -S --needed gcc:p cmake:p ninja:p
- name: Build
run: |
mkdir -p out/release
cd out/release
cmake -G"Ninja" -DCMAKE_BUILD_TYPE=Release ../../
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_COMPILE_WARNING_AS_ERROR=YES ${{ matrix.cmake_args }} ../../
ninja
- name: Test
@@ -46,11 +58,12 @@ jobs:
working-directory: out/release
- name: Package
working-directory: tools/installer
run: ./make-installer.sh ../../out/release ${{ matrix.installer }}.nsi
run: |
cp out/release/src/xsystem35.exe *.md COPYING xsys35rc.sample dist/
- name: Upload
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.installer }}
path: tools/installer/${{ matrix.installer }}.exe
name: ${{ matrix.package }}
path: dist
compression-level: 9 # because we use it for releases
+72 -65
View File
@@ -3,17 +3,10 @@ cmake_minimum_required(VERSION 3.13)
project(xsystem35 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
enable_testing()
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
include(CheckIncludeFile)
include(CheckLibraryExists)
include(CheckSymbolExists)
# In msys, `pkg-config --libs` returns `-lmingw32` but find_library() cannot
# find it in default search paths.
if (MSYS)
list(APPEND CMAKE_LIBRARY_PATH $ENV{MINGW_PREFIX}/$ENV{MINGW_CHOST}/lib)
endif ()
# A wrapper around pkg_check_modules() that skips the check if ENABLE_<prefix> is false
macro (optional_pkg_check_modules prefix)
option(ENABLE_${prefix} "Use ${prefix} if available" ON)
@@ -22,19 +15,48 @@ macro (optional_pkg_check_modules prefix)
endif()
endmacro()
# Generates a static library from pkg_check_modules() result
function(add_static_library name pkg)
add_library(${name} INTERFACE)
set_target_properties(${name}
PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${${pkg}_STATIC_INCLUDE_DIRS}"
INTERFACE_COMPILE_OPTIONS "${${pkg}_STATIC_CFLAGS_OTHER}"
INTERFACE_LINK_LIBRARIES "${${pkg}_STATIC_LIBRARIES}"
INTERFACE_LINK_OPTIONS "${${pkg}_STATIC_LDFLAGS_OTHER}")
endfunction()
check_symbol_exists(getlogin "unistd.h" HAVE_GETLOGIN)
check_symbol_exists(mmap "sys/mman.h" HAVE_MMAP)
check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
check_symbol_exists(uname "sys/utsname.h" HAVE_UNAME)
if (EMSCRIPTEN)
function(add_emscripten_library name option)
add_library(${name} INTERFACE)
set_target_properties(${name} PROPERTIES
INTERFACE_COMPILE_OPTIONS ${option}
INTERFACE_LINK_OPTIONS ${option})
endfunction()
add_emscripten_library(zlib -sUSE_ZLIB=1)
add_emscripten_library(sdl2 -sUSE_SDL=2)
add_emscripten_library(sdl2_ttf -sUSE_SDL_TTF=2)
set(DEFAULT_FONT_PATH /fonts/)
elseif (ANDROID)
set(SDL2MIXER_FOUND 1)
find_library(ndk_zlib z)
add_library(sdl2 ALIAS SDL2)
add_library(sdl2_ttf ALIAS SDL2_ttf)
add_library(sdl2_mixer ALIAS SDL2_mixer)
find_library(ndk_log log)
else()
find_library(ndk_zlib z)
add_library(zlib INTERFACE)
set_target_properties(zlib PROPERTIES INTERFACE_LINK_LIBRARIES ${ndk_zlib})
else() # non-emscripten, non-android
if (WIN32)
set(ZLIB_USE_STATIC_LIBS ON)
endif()
find_package(ZLIB REQUIRED)
add_library(zlib ALIAS ZLIB::ZLIB)
include(FindPkgConfig)
optional_pkg_check_modules(GTK3 IMPORTED_TARGET gtk+-3.0)
@@ -42,45 +64,61 @@ else()
set(ENABLE_GTK 1)
endif()
pkg_check_modules(SDL2 IMPORTED_TARGET sdl2)
pkg_check_modules(SDL2TTF IMPORTED_TARGET SDL2_ttf)
optional_pkg_check_modules(SDL2MIXER IMPORTED_TARGET SDL2_mixer)
pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2)
pkg_check_modules(SDL2TTF REQUIRED IMPORTED_TARGET SDL2_ttf)
pkg_check_modules(SDL2MIXER REQUIRED IMPORTED_TARGET SDL2_mixer)
if (WIN32)
add_static_library(sdl2 SDL2)
add_static_library(sdl2_ttf SDL2TTF)
# Workaround for linking error
set_property(TARGET sdl2_ttf PROPERTY INTERFACE_LINK_LIBRARIES
$<LINK_GROUP:RESCAN,${SDL2TTF_STATIC_LIBRARIES} -lstdc++>)
add_static_library(sdl2_mixer SDL2MIXER)
else()
add_library(sdl2 ALIAS PkgConfig::SDL2)
add_library(sdl2_ttf ALIAS PkgConfig::SDL2TTF)
add_library(sdl2_mixer ALIAS PkgConfig::SDL2MIXER)
set(DEFAULT_FONT_PATH ${CMAKE_INSTALL_PREFIX}/share/xsystem35/fonts/)
endif()
option(ENABLE_DEBUGGER "Enable built-in debugger" ON)
if (ENABLE_DEBUGGER)
pkg_check_modules(cJSON IMPORTED_TARGET libcjson)
if (NOT cJSON_FOUND)
if (cJSON_FOUND)
if (WIN32)
add_static_library(cJSON cJSON)
else ()
add_library(cJSON ALIAS PkgConfig::cJSON)
endif()
else ()
# libcjson-dev of Debian buster / Ubuntu 20.04 does not install pkgconfig files.
find_library(cJSON cjson)
if (NOT cJSON)
message(FATAL_ERROR "libcjson is required but not found.")
endif()
add_library(cJSON ALIAS ${cJSON})
endif()
endif()
optional_pkg_check_modules(WEBP IMPORTED_TARGET libwebp)
if (WEBP_FOUND)
set(HAVE_WEBP 1)
if (WIN32)
add_static_library(WebP WEBP)
else()
add_library(WebP ALIAS PkgConfig::WEBP)
endif()
endif()
find_library(PORTMIDI portmidi)
if (PORTMIDI)
set(HAVE_PORTMIDI 1)
set(ENABLE_MIDI_PORTMIDI 1)
endif()
set(DEFAULT_FONT_PATH ${CMAKE_INSTALL_PREFIX}/share/xsystem35/fonts/)
endif()
# Menu
if (EMSCRIPTEN)
set(SRC_MENU menu_emscripten.c)
elseif (ANDROID)
set(SRC_MENU menu_android.c)
elseif (ENABLE_GTK)
set(SRC_MENU menu.c menu_callback.c menu_gui.c s39init.c)
if (ENABLE_GTK)
# i18n support (currently only menus are translated)
include(FindIntl)
include(FindGettext)
@@ -90,60 +128,36 @@ elseif (ENABLE_GTK)
include_directories(${Intl_INCLUDE_DIRS})
link_libraries(${Intl_LIBRARIES})
endif()
else ()
set(SRC_MENU menu_sdl.c sdl_input.c)
endif()
# PCM audio
if (EMSCRIPTEN)
list(APPEND SRC_AUDIO)
list(APPEND SRC_AUDIO pcm.emscripten.c bgm.emscripten.c bgi.c)
list(APPEND SUMMARY_AUDIO "Emscripten")
elseif (SDL2MIXER_FOUND)
list(APPEND SRC_AUDIO pcm.sdlmixer.c bgm.sdlmixer.c bgi.c)
list(APPEND SUMMARY_AUDIO "SDL_mixer")
set(ENABLE_SDLMIXER 1)
else()
list(APPEND SRC_AUDIO pcm.dummy.c bgm.dummy.c)
list(APPEND SUMMARY_AUDIO "SDL_mixer")
endif()
# CDROM
list(APPEND SRC_CDROM cdrom.bgm.c)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
list(APPEND SRC_CDROM cdrom.Linux.c)
list(APPEND SUMMARY_CDROM "Linux ioctl")
set(ENABLE_CDROM_LINUX 1)
elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
list(APPEND SRC_CDROM cdrom.FreeBSD.c)
list(APPEND SUMMARY_CDROM "*BSD ioctl")
set(ENABLE_CDROM_BSD 1)
elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
list(APPEND SRC_CDROM cdrom.emscripten.c)
if (EMSCRIPTEN)
list(APPEND SUMMARY_CDROM "Emscripten")
set(ENABLE_CDROM_EMSCRIPTEN 1)
else()
list(APPEND SRC_CDROM cdrom.empty.c)
endif()
if (SDL2MIXER_FOUND)
list(APPEND SRC_CDROM cdrom.mp3.c)
list(APPEND SUMMARY_CDROM "SDL_mixer (wav|mp3|ogg...)")
set(ENABLE_CDROM_MP3 1)
endif()
set(CDROM_DEVICE "playlist.txt" CACHE STRING "CDROM Device Name")
set(DEFAULT_PLAYLIST_PATH "playlist.txt" CACHE STRING "Default playlist path")
# MIDI
if (EMSCRIPTEN)
list(APPEND SRC_MIDI midi.emscripten.c)
list(APPEND SUMMARY_MIDI "Emscripten")
elseif (ANDROID)
list(APPEND SRC_MIDI midi.android.c)
list(APPEND SUMMARY_MIDI "Android")
else()
list(APPEND SUMMARY_MIDI "SDL_mixer")
set(ENABLE_MIDI_SDLMIXER 1)
if (HAVE_SIGACTION)
list(APPEND SRC_MIDI midi.rawmidi.c midifile.c)
list(APPEND SUMMARY_MIDI "raw")
set(MIDI_DEVICE "/dev/midi" CACHE STRING "midi device")
set(ENABLE_MIDI_RAWMIDI 1)
@@ -162,15 +176,9 @@ else()
set(SEQ_DEVICE "/dev/sequencer" CACHE STRING "sequencer device")
endif()
if (SDL2MIXER_FOUND)
list(APPEND SRC_MIDI midi.sdlmixer.c)
list(APPEND SUMMARY_MIDI "SDL_mixer")
set(ENABLE_MIDI_SDLMIXER 1)
endif()
if (HAVE_PORTMIDI AND ENABLE_MIDI_PORTMIDI)
list(APPEND SRC_MIDI midi.portmidi.c)
if (HAVE_PORTMIDI)
list(APPEND SUMMARY_MIDI "PortMidi")
set(ENABLE_MIDI_PORTMIDI 1)
endif()
endif()
@@ -193,7 +201,6 @@ message("------------------")
set(PACKAGE ${PROJECT_NAME})
configure_file(config.h.in config.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_compile_definitions(HAVE_CONFIG_H)
add_compile_definitions($<$<CONFIG:Debug>:DEBUG>)
add_subdirectory(src)
+1 -2
View File
@@ -69,8 +69,7 @@ other platforms, refer to the [Building](#building) section.
## Running
### Windows
Execute `xsystem35`, and a dialog will appear for you to select a folder.
Choose the game folder (where the ALD files are located).
Copy `xsystem35.exe` to the game folder and run it.
### Android
+2 -2
View File
@@ -16,8 +16,8 @@ android {
defaultConfig {
minSdkVersion 19
targetSdkVersion 34
versionCode 16
versionName "2.10.0" + gitRevision()
versionCode 22
versionName "2.11.4" + gitRevision()
externalNativeBuild {
cmake {
arguments "-DANDROID_APP_PLATFORM=android-19", "-DANDROID_STL=c++_static"
+23 -32
View File
@@ -1,50 +1,41 @@
cmake_minimum_required(VERSION 3.13)
cmake_minimum_required(VERSION 3.14)
project(GAME)
set(PROJECT_ROOT_DIR ../../..)
# Compilation of SDL and companion libraries
include(FetchContent)
FetchContent_Declare(
SDL
URL https://github.com/libsdl-org/SDL/releases/download/release-2.28.5/SDL2-2.28.5.tar.gz
URL_HASH SHA1=50af6b564890d702e57e2a72d6429b43778ed29a
URL https://github.com/libsdl-org/SDL/releases/download/release-2.30.2/SDL2-2.30.2.tar.gz
URL_HASH SHA1=37a0557fc39460dc2a4fbbf162d95f115d2c9be2
)
FetchContent_Declare(
SDL_ttf
URL https://github.com/libsdl-org/SDL_ttf/releases/download/release-2.20.1/SDL2_ttf-2.20.1.tar.gz
URL_HASH SHA1=f774ff407915ae4afa3d03e5a9395283d9090f28
URL https://github.com/libsdl-org/SDL_ttf/releases/download/release-2.22.0/SDL2_ttf-2.22.0.tar.gz
URL_HASH SHA1=da5e86b601ad299a697878fab1af6f3be47b529d
)
FetchContent_Declare(
SDL_mixer
URL https://github.com/libsdl-org/SDL_mixer/releases/download/release-2.6.2/SDL2_mixer-2.6.2.tar.gz
URL_HASH SHA1=036fc7839a6b8dc1af3dbfed4e2531224bbacdd7
URL https://github.com/libsdl-org/SDL_mixer/releases/download/release-2.8.0/SDL2_mixer-2.8.0.tar.gz
URL_HASH SHA1=a58c69f9d00e44833b9e00e1adb58d85759ca499
)
# Compilation of SDL and companion libraries
FetchContent_GetProperties(SDL)
if(NOT sdl_POPULATED)
FetchContent_Populate(SDL)
add_subdirectory(${sdl_SOURCE_DIR} ${sdl_BINARY_DIR})
endif()
FetchContent_GetProperties(SDL_ttf)
if(NOT sdl_ttf_POPULATED)
FetchContent_Populate(SDL_ttf)
set(SDL2TTF_SAMPLES OFF CACHE BOOL "Build the SDL2_ttf sample program(s)" FORCE)
set(SDL2TTF_INSTALL OFF CACHE BOOL "Enable SDL2_ttf install target" FORCE)
set(SDL2TTF_VENDORED ON CACHE BOOL "Use vendored third-party libraries" FORCE)
add_subdirectory(${sdl_ttf_SOURCE_DIR} ${sdl_ttf_BINARY_DIR})
endif()
FetchContent_GetProperties(SDL_mixer)
if(NOT sdl_mixer_POPULATED)
FetchContent_Populate(SDL_mixer)
set(SDL2MIXER_OPUS OFF CACHE BOOL "Enable Opus music" FORCE)
set(SDL2MIXER_FLAC OFF CACHE BOOL "Enable FLAC music" FORCE)
set(SDL2MIXER_MOD OFF CACHE BOOL "Support loading MOD music" FORCE)
set(SDL2MIXER_MIDI OFF CACHE BOOL "Enable MIDI music" FORCE)
set(SDL2MIXER_SAMPLES OFF CACHE BOOL "Build the SDL2_mixer sample program(s)" FORCE)
set(SDL2MIXER_INSTALL OFF CACHE BOOL "Enable SDL2_mixer install target" FORCE)
add_subdirectory(${sdl_mixer_SOURCE_DIR} ${sdl_mixer_BINARY_DIR})
endif()
set(SDL2TTF_SAMPLES OFF CACHE BOOL "Build the SDL2_ttf sample program(s)" FORCE)
set(SDL2TTF_INSTALL OFF CACHE BOOL "Enable SDL2_ttf install target" FORCE)
set(SDL2TTF_VENDORED ON CACHE BOOL "Use vendored third-party libraries" FORCE)
set(SDL2MIXER_OPUS OFF CACHE BOOL "Enable Opus music" FORCE)
set(SDL2MIXER_FLAC OFF CACHE BOOL "Enable FLAC music" FORCE)
set(SDL2MIXER_MOD OFF CACHE BOOL "Support loading MOD music" FORCE)
set(SDL2MIXER_MIDI OFF CACHE BOOL "Enable MIDI music" FORCE)
set(SDL2MIXER_WAVPACK OFF CACHE BOOL "Enable WavPack music" FORCE)
set(SDL2MIXER_SAMPLES OFF CACHE BOOL "Build the SDL2_mixer sample program(s)" FORCE)
set(SDL2MIXER_INSTALL OFF CACHE BOOL "Enable SDL2_mixer install target" FORCE)
FetchContent_MakeAvailable(SDL)
FetchContent_MakeAvailable(SDL_ttf)
FetchContent_MakeAvailable(SDL_mixer)
# The main CMakeLists.txt of xsystem35
add_subdirectory(${PROJECT_ROOT_DIR} xsystem35)
@@ -30,9 +30,11 @@ import java.io.IOException
// Intent for this activity must have the following extra:
// - EXTRA_GAME_ROOT (string): A path to the game installation.
// - EXTRA_SAVE_DIRECTORY (string): A path to the save data directory.
class GameActivity : SDLActivity() {
companion object {
const val EXTRA_GAME_ROOT = "GAME_ROOT"
const val EXTRA_SAVE_DIRECTORY = "SAVE_DIRECTORY"
const val EXTRA_ARCHIVE_NAME = "ARCHIVE_NAME"
}
@@ -61,7 +63,7 @@ class GameActivity : SDLActivity() {
override fun getArguments(): Array<String> {
return arrayOf(
"-gamedir", intent.getStringExtra(EXTRA_GAME_ROOT)!!,
"-devcd", Launcher.PLAYLIST_FILE)
"-savedir", intent.getStringExtra(EXTRA_SAVE_DIRECTORY)!!)
}
override fun setTitle(title: CharSequence?) {
@@ -25,9 +25,7 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.*
import java.lang.StringBuilder
import java.nio.charset.Charset
import java.util.*
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
@@ -41,13 +39,13 @@ interface LauncherObserver {
fun onInstallFailure(msgId: Int)
}
private const val SAVE_DIR = "save"
class Launcher private constructor(private val rootDir: File) {
companion object {
const val SAVE_DIR = "save"
const val TITLE_FILE = "title.txt"
const val PLAYLIST_FILE = "playlist2.txt"
const val OLD_PLAYLIST_FILE = "playlist.txt"
const val GAMEDIR_FILE = "game_directory.txt"
const val PLAYLIST_FILE = "playlist.txt"
const val OLD_PLAYLIST_FILE = "playlist2.txt"
fun getInstance(rootDir: File): Launcher {
if (gLauncher == null) {
@@ -79,14 +77,14 @@ class Launcher private constructor(private val rootDir: File) {
isInstalling = true
GlobalScope.launch(Dispatchers.Main) {
try {
withContext(Dispatchers.IO) {
val gameDir = withContext(Dispatchers.IO) {
extractFiles(input, dir) { msg ->
GlobalScope.launch(Dispatchers.Main) {
observer?.onInstallProgress(msg)
}
}
}
observer?.onInstallSuccess(dir, archiveName)
observer?.onInstallSuccess(gameDir, archiveName)
} catch (e: InstallFailureException) {
observer?.onInstallFailure(e.msgId)
} catch (e: Exception) {
@@ -114,9 +112,11 @@ class Launcher private constructor(private val rootDir: File) {
continue
}
try {
val titleFile = File(path, TITLE_FILE)
val gameDirFile = File(path, GAMEDIR_FILE)
val gamePath = if (gameDirFile.exists()) File(path, gameDirFile.readText()) else path
val titleFile = File(gamePath, TITLE_FILE)
val title = titleFile.readText()
games.add(Entry(path, title, titleFile.lastModified()))
games.add(Entry(gamePath, title, titleFile.lastModified()))
migratePlaylist(path)
} catch (e: IOException) {
// Incomplete game installation. Delete it.
@@ -179,7 +179,7 @@ class Launcher private constructor(private val rootDir: File) {
}
}
private fun extractFiles(input: InputStream, outDir: File, progressCallback: (String) -> Unit) {
private fun extractFiles(input: InputStream, outDir: File, progressCallback: (String) -> Unit): File {
val configWriter = GameConfigWriter()
val hadDecodeError = forEachZipEntry(input) { zipEntry, zip ->
Log.i("extractFiles", zipEntry.name)
@@ -193,90 +193,62 @@ class Launcher private constructor(private val rootDir: File) {
}
configWriter.maybeAdd(zipEntry.name)
}
if (!configWriter.readyToWrite()) {
if (!configWriter.ready) {
if (hadDecodeError)
throw InstallFailureException(R.string.unsupported_zip)
throw InstallFailureException(R.string.cannot_find_ald)
}
configWriter.write(outDir)
return configWriter.gameDir?.let { File(outDir, it) } ?: outDir
}
// Xsystem35-sdl2 <=2.2.0 had a bug where playlist had an extra empty line at
// the beginning of the file. This migrates playlist.txt created by an old
// version of xsystem35-sdl2 to playlist2.txt.
// Xsystem35-sdl2 2.3.0 - 2.11.1 used playlist2.txt. Rename it to playlist.txt.
private fun migratePlaylist(dir: File) {
val oldPlaylist = File(dir, OLD_PLAYLIST_FILE)
if (!oldPlaylist.exists())
return
var tracks = oldPlaylist.readLines()
if (tracks.isNotEmpty())
tracks = tracks.subList(1, tracks.size)
File(dir, PLAYLIST_FILE).writeText(tracks.joinToString("\n"))
oldPlaylist.delete()
if (oldPlaylist.exists()) {
oldPlaylist.renameTo(File(dir, PLAYLIST_FILE))
}
}
class InstallFailureException(val msgId: Int) : Exception()
// A helper class which generates xsystem35.gr and playlist.txt in the game root directory.
// A helper class which generates GAMEDIR_FILE and PLAYLIST_FILE.
private class GameConfigWriter {
private val grb = StringBuilder()
private var basename: String? = null
private val aldRegex = """(.*?)([a-z])([a-z])\.(ald|wai|bgi)""".toRegex(RegexOption.IGNORE_CASE)
private val aldType = mapOf(
"b" to "BGM",
"d" to "Data",
"g" to "Graphics",
"m" to "Midi",
"r" to "Resource",
"s" to "Scenario",
"w" to "Wave")
private val specialResources = mapOf(
"system39.ain" to "Ain",
"system39.ini" to "Init",
"sactefam.kld" to "SACT01"
)
var ready = false
private set
var gameDir: String? = null
private set
private val aldRegex = """.*?s[a-z]\.ald""".toRegex(RegexOption.IGNORE_CASE)
private val audioRegex = """.*?(\d+)\.(wav|mp3|ogg)""".toRegex(RegexOption.IGNORE_CASE)
private val audioFiles: Array<String?> = arrayOfNulls(100)
fun maybeAdd(path: String) {
val name = File(path).name
specialResources[name.lowercase(Locale.US)]?.let {
grb.appendLine("$it $path")
return
aldRegex.matchEntire(path)?.let {
gameDir = File(path).parent
ready = true
}
aldRegex.matchEntire(name)?.let {
val ext = it.groupValues[4].uppercase(Locale.US)
val type = if (ext == "ALD") {
aldType[it.groupValues[2].lowercase(Locale.US)]
} else {
ext
}
val id = it.groupValues[3].uppercase(Locale.US)
if (type != null) {
grb.appendLine("$type$id $path")
basename = it.groupValues[1]
}
}
audioRegex.matchEntire(name)?.let {
audioRegex.matchEntire(path)?.let {
val track = it.groupValues[1].toInt()
if (0 < track && track <= audioFiles.size)
audioFiles[track - 1] = path
}
}
fun readyToWrite() = basename != null
fun write(outDir: File) {
for (id in 'A' .. 'Z') {
grb.appendLine("Save$id ../save/${basename}s${id.lowercase(Locale.US)}.asd")
// Generate GAMEDIR_FILE
gameDir?.let {
File(outDir, GAMEDIR_FILE).writeText(it)
}
// Generate PLAYLIST_FILE
val absGameDir = gameDir?.let { File(outDir, it) } ?: outDir
val playlistFile = File(absGameDir, PLAYLIST_FILE)
if (!playlistFile.exists()) {
val prefixToRemove = gameDir?.let { "$it/" } ?: ""
val playlist = audioFiles.joinToString("\n") {
it?.removePrefix(prefixToRemove) ?: ""
}.trimEnd('\n')
playlistFile.writeText(playlist)
}
val gr = grb.toString()
Log.i("xsystem35.gr", gr)
File(outDir, "xsystem35.gr").writeText(gr)
val playlist = audioFiles.joinToString("\n") { it ?: "" }.trimEnd('\n')
File(outDir, PLAYLIST_FILE).writeText(playlist)
}
}
}
@@ -180,6 +180,7 @@ class LauncherActivity : Activity(), LauncherObserver {
val i = Intent()
i.setClass(applicationContext, GameActivity::class.java)
i.putExtra(GameActivity.EXTRA_GAME_ROOT, path.path)
i.putExtra(GameActivity.EXTRA_SAVE_DIRECTORY, File(filesDir, Launcher.SAVE_DIR).path)
i.putExtra(GameActivity.EXTRA_ARCHIVE_NAME, archiveName)
startActivity(i)
}
@@ -285,6 +285,7 @@ public class HIDDeviceManager {
0x24c6, // PowerA
0x2dc8, // 8BitDo
0x2e24, // Hyperkin
0x3537, // GameSir
};
if (usbInterface.getId() == 0 &&
@@ -358,6 +359,12 @@ public class HIDDeviceManager {
private void initializeBluetooth() {
Log.d(TAG, "Initializing Bluetooth");
if (Build.VERSION.SDK_INT >= 31 /* Android 12 */ &&
mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH_CONNECT, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH_CONNECT");
return;
}
if (Build.VERSION.SDK_INT <= 30 /* Android 11.0 (R) */ &&
mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH");
@@ -60,8 +60,8 @@ import java.util.Locale;
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 2;
private static final int SDL_MINOR_VERSION = 28;
private static final int SDL_MICRO_VERSION = 5;
private static final int SDL_MINOR_VERSION = 30;
private static final int SDL_MICRO_VERSION = 2;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
@@ -546,13 +546,15 @@ class SDLHapticHandler {
if (haptic == null) {
InputDevice device = InputDevice.getDevice(deviceIds[i]);
Vibrator vib = device.getVibrator();
if (vib.hasVibrator()) {
haptic = new SDLHaptic();
haptic.device_id = deviceIds[i];
haptic.name = device.getName();
haptic.vib = vib;
mHaptics.add(haptic);
SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
if (vib != null) {
if (vib.hasVibrator()) {
haptic = new SDLHaptic();
haptic.device_id = deviceIds[i];
haptic.name = device.getName();
haptic.vib = vib;
mHaptics.add(haptic);
SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
}
}
}
}
+2 -11
View File
@@ -1,15 +1,8 @@
#cmakedefine PACKAGE "@PACKAGE@"
#define VERSION "2.10.0"
#cmakedefine CMAKE_SYSTEM_NAME "@CMAKE_SYSTEM_NAME@"
#define VERSION "2.11.4"
#cmakedefine CACHE_TOTALSIZE @CACHE_TOTALSIZE@
#cmakedefine ENABLE_CDROM_ANDROID @ENABLE_CDROM_ANDROID@
#cmakedefine ENABLE_CDROM_BSD @ENABLE_CDROM_BSD@
#cmakedefine ENABLE_CDROM_EMSCRIPTEN @ENABLE_CDROM_EMSCRIPTEN@
#cmakedefine ENABLE_CDROM_LINUX @ENABLE_CDROM_LINUX@
#cmakedefine ENABLE_CDROM_MP3 @ENABLE_CDROM_MP3@
#cmakedefine ENABLE_DEBUGGER @ENABLE_DEBUGGER@
#cmakedefine ENABLE_GTK @ENABLE_GTK@
#cmakedefine ENABLE_MIDI_RAWMIDI @ENABLE_MIDI_RAWMIDI@
@@ -17,9 +10,8 @@
#cmakedefine ENABLE_MIDI_SEQMIDI @ENABLE_MIDI_SEQMIDI@
#cmakedefine ENABLE_MIDI_PORTMIDI @ENABLE_MIDI_PORTMIDI@
#cmakedefine ENABLE_NLS @ENABLE_NLS@
#cmakedefine ENABLE_SDLMIXER @ENABLE_SDLMIXER@
#cmakedefine CDROM_DEVICE "@CDROM_DEVICE@"
#cmakedefine DEFAULT_PLAYLIST_PATH "@DEFAULT_PLAYLIST_PATH@"
#cmakedefine JOY_DEVICE "@JOY_DEVICE@"
#cmakedefine MIDI_DEVICE "@MIDI_DEVICE@"
#cmakedefine SEQ_DEVICE "@SEQ_DEVICE@"
@@ -27,7 +19,6 @@
#cmakedefine HAVE_GETLOGIN @HAVE_GETLOGIN@
#cmakedefine HAVE_MMAP @HAVE_MMAP@
#cmakedefine HAVE_SIGACTION @HAVE_SIGACTION@
#cmakedefine HAVE_UNAME @HAVE_UNAME@
#cmakedefine HAVE_WEBP @HAVE_WEBP@
#define DEFAULT_GOTHIC_TTF "@DEFAULT_FONT_PATH@MTLc3m.ttf"
+1 -1
View File
@@ -76,7 +76,7 @@ Game Compatibility
| マスカレイド | Supported | From アリスCD |
| キャロル ~聖なる鐘が響く夜~ | Supported | From アリスCD, Online match is not supported |
| できるかなー? | Supported | From アリスCD |
| Child Assassin | Supported | From アリスCD |
| Child Assassin | Unsupported | From アリスCD |
| Klavier | Supported | From アリスCD |
| 弱肉狂食 | Supported | From アリスCD |
| 眼鏡大戦2 | Supported | From アリスCD |
+3 -16
View File
@@ -98,20 +98,7 @@ endif()
target_compile_options(modules PRIVATE -Wno-pointer-sign)
if (EMSCRIPTEN)
set(LIBS
"SHELL:-s USE_ZLIB=1"
"SHELL:-s USE_SDL=2")
target_compile_options(modules PRIVATE ${LIBS})
target_link_options(modules PRIVATE ${LIBS})
elseif (ANDROID)
target_link_libraries(modules PRIVATE ${ndk_zlib})
if (SDL2MIXER_FOUND)
target_link_libraries(modules PRIVATE SDL2 SDL2_mixer)
endif()
else()
target_link_libraries(modules PRIVATE ZLIB::ZLIB)
if (SDL2MIXER_FOUND)
target_link_libraries(modules PRIVATE PkgConfig::SDL2MIXER)
endif()
target_link_libraries(modules PRIVATE sdl2 zlib)
if (TARGET sdl2_mixer)
target_link_libraries(modules PRIVATE sdl2_mixer)
endif()
+130 -77
View File
@@ -11,6 +11,9 @@ if (ANDROID)
add_library(xsystem35 SHARED)
else()
add_executable(xsystem35)
if (WIN32)
target_link_options(xsystem35 PRIVATE -static)
endif()
endif()
target_compile_options(xsystem35 PRIVATE -Wno-pointer-sign $<$<CONFIG:Debug>:-Wall>)
@@ -18,114 +21,164 @@ target_include_directories(xsystem35 PRIVATE .)
target_link_libraries(xsystem35 PRIVATE src_lib)
target_sources(xsystem35 PRIVATE
xsystem35.c
dri.c
ags.c
ald_manager.c
alpha_plane.c
bgi.c
bmp.c
cache.c
${SRC_AUDIO}
${SRC_CDROM}
${SRC_MIDI}
${SRC_MENU})
cali.c
cdrom.bgm.c
cg.c
cmd2F.c
cmd2F60.c
cmd_check.c
cmdb.c
cmdc.c
cmdd.c
cmde.c
cmdf.c
cmdg.c
cmdh.c
cmdi.c
cmdj.c
cmdk.c
cmdl.c
cmdm.c
cmdn.c
cmdo.c
cmdp.c
cmdq.c
cmds.c
cmdt.c
cmdu.c
cmdv.c
cmdw.c
cmdy.c
cmdz.c
cursor.c
dri.c
ecopy.c
filecheck.c
font.c
hacks.c
image.c
input.c
jpeg.c
message.c
midi.c
mmap.c
msgskip.c
mt19937-1.c
music.c
music_cdrom.c
music_midi.c
nact.c
network.c
pms.c
profile.c
qnt.c
s39ain.c
savedata.c
scenario.c
sdl_cursor.c
sdl_draw.c
sdl_effect.c
sdl_event.c
sdl_image.c
sdl_video.c
selection.c
texthook.c
variable.c
vsp.c
xsystem35.c
)
# System3.x commands
target_sources(xsystem35 PRIVATE
cmdb.c cmdc.c cmdd.c cmde.c cmdf.c cmdg.c cmdh.c cmdi.c cmdj.c
cmdk.c cmdl.c cmdm.c cmdn.c cmdo.c cmdp.c cmdq.c cmds.c cmdt.c
cmdu.c cmdv.c cmdw.c cmdy.c cmdz.c cmd2F.c cmd2F60.c)
# Graphics
target_sources(xsystem35 PRIVATE
sdl_video.c sdl_draw.c sdl_event.c sdl_image.c sdl_cursor.c sdl_effect.c
image.c font.c)
# CG
target_sources(xsystem35 PRIVATE
pms.c vsp.c bmp.c qnt.c jpeg.c)
if (HAVE_WEBP)
target_sources(xsystem35 PRIVATE webp.c)
target_link_libraries(xsystem35 PRIVATE PkgConfig::WEBP)
if (EMSCRIPTEN)
target_sources(xsystem35 PRIVATE pcm.emscripten.c bgm.emscripten.c)
else()
target_sources(xsystem35 PRIVATE pcm.sdlmixer.c bgm.sdlmixer.c)
endif()
# Music
target_sources(xsystem35 PRIVATE
music.c music_cdrom.c music_midi.c midi.c cdrom.c)
if (EMSCRIPTEN)
target_sources(xsystem35 PRIVATE cdrom.emscripten.c)
else()
target_sources(xsystem35 PRIVATE cdrom.mp3.c)
endif()
# Misc
target_sources(xsystem35 PRIVATE
input.c profile.c mt19937-1.c filecheck.c mmap.c hacks.c)
if (EMSCRIPTEN)
target_sources(xsystem35 PRIVATE midi.emscripten.c)
elseif (ANDROID)
target_sources(xsystem35 PRIVATE midi.android.c)
else()
target_sources(xsystem35 PRIVATE midi.sdlmixer.c)
if (ENABLE_MIDI_RAWMIDI)
target_sources(xsystem35 PRIVATE midi.rawmidi.c midifile.c)
endif()
if (ENABLE_MIDI_PORTMIDI)
target_sources(xsystem35 PRIVATE midi.portmidi.c)
endif()
endif()
# Scenario
target_sources(xsystem35 PRIVATE
cali.c scenario.c variable.c cmd_check.c nact.c
selection.c message.c savedata.c s39ain.c texthook.c msgskip.c)
if (EMSCRIPTEN)
target_sources(xsystem35 PRIVATE menu_emscripten.c)
elseif (ANDROID)
target_sources(xsystem35 PRIVATE menu_android.c)
elseif (ENABLE_GTK)
target_sources(xsystem35 PRIVATE menu.c menu_callback.c menu_gui.c s39init.c)
else ()
target_sources(xsystem35 PRIVATE menu_sdl.c sdl_input.c)
endif()
# Graphics
target_sources(xsystem35 PRIVATE
ags.c cg.c ecopy.c alpha_plane.c cursor.c)
if (HAVE_WEBP)
target_sources(xsystem35 PRIVATE webp.c)
target_link_libraries(xsystem35 PRIVATE WebP)
endif()
# Network
target_sources(xsystem35 PRIVATE
network.c)
# Debugger
if (ENABLE_DEBUGGER)
target_sources(xsystem35 PRIVATE
debug_symbol.c debugger.c debugger_cui.c debugger_dap.c)
endif()
if (WIN32)
target_sources(xsystem35 PRIVATE win/dialog.c win/resources.rc win/menubar.c win/console.c)
target_sources(xsystem35 PRIVATE
win/dialog.c win/resources.rc win/resources.c win/menubar.c win/console.c)
endif()
target_link_libraries(src_lib PRIVATE sdl2 zlib)
target_link_libraries(xsystem35 PRIVATE m zlib sdl2 sdl2_ttf)
if (TARGET sdl2_mixer)
target_link_libraries(xsystem35 PRIVATE sdl2_mixer)
endif()
if (EMSCRIPTEN)
set(LIBS
"SHELL:-s USE_ZLIB=1"
"SHELL:-s USE_SDL=2"
"SHELL:-s USE_SDL_TTF=2")
target_compile_options(src_lib PRIVATE ${LIBS})
target_compile_options(xsystem35 PRIVATE ${LIBS})
target_link_options(xsystem35 PRIVATE ${LIBS})
target_link_libraries(xsystem35 PRIVATE idbfs.js)
# Without optimizations, Asyncify generates very large code.
list(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG "-O1")
target_link_options(xsystem35 PRIVATE
"SHELL:-s ENVIRONMENT=web"
"SHELL:-s ASYNCIFY=1 -s ASYNCIFY_IGNORE_INDIRECT=1"
"SHELL:-s ASYNCIFY_REMOVE=SDL_Delay"
"SHELL:-s ASYNCIFY_IMPORTS=muspcm_load_no,muspcm_load_data,muspcm_load_mixlr,muspcm_waitend,wait_vsync,load_mincho_font"
"SHELL:-s ASYNCIFY_ADD=commands2F60,nact_main,send_agsevent,cb_waitkey_sprite"
"SHELL:-s ALLOW_MEMORY_GROWTH=1"
"SHELL:-s NO_EXIT_RUNTIME=1"
"SHELL:-s EXPORTED_FUNCTIONS=_main,_malloc"
"SHELL:-s EXPORTED_RUNTIME_METHODS=getValue,addRunDependency,removeRunDependency")
-sENVIRONMENT=web
-sASYNCIFY=1
-sASYNCIFY_IGNORE_INDIRECT=1
-sASYNCIFY_REMOVE=SDL_Delay
-sASYNCIFY_IMPORTS=muspcm_load_no,muspcm_load_data,muspcm_load_mixlr,muspcm_waitend,wait_vsync,load_mincho_font
-sASYNCIFY_ADD=commands2F60,nact_main,send_agsevent,cb_waitkey_sprite
-sALLOW_MEMORY_GROWTH=1
-sNO_EXIT_RUNTIME=1
-sEXPORTED_FUNCTIONS=_main,_malloc
-sEXPORTED_RUNTIME_METHODS=getValue,addRunDependency,removeRunDependency)
elseif (ANDROID)
target_link_libraries(src_lib PRIVATE SDL2)
target_link_libraries(xsystem35 PRIVATE SDL2 SDL2_ttf SDL2_mixer ${ndk_zlib} ${ndk_log})
target_link_libraries(xsystem35 PRIVATE ${ndk_log})
else() # non-emscripten, non-android
target_link_libraries(src_lib PRIVATE PkgConfig::SDL2)
target_link_libraries(xsystem35 PRIVATE m ZLIB::ZLIB)
target_link_libraries(xsystem35 PRIVATE PkgConfig::SDL2)
target_link_libraries(xsystem35 PRIVATE PkgConfig::SDL2TTF)
if (TARGET cJSON)
target_link_libraries(xsystem35 PRIVATE cJSON)
endif()
if (GTK3_FOUND)
target_link_libraries(xsystem35 PRIVATE PkgConfig::GTK3)
endif()
if (SDL2MIXER_FOUND)
target_link_libraries(xsystem35 PRIVATE PkgConfig::SDL2MIXER)
endif()
if (ENABLE_DEBUGGER)
if (cJSON_FOUND)
target_link_libraries(xsystem35 PRIVATE PkgConfig::cJSON)
else()
target_link_libraries(xsystem35 PRIVATE ${cJSON})
endif()
endif()
if (ENABLE_MIDI_PORTMIDI)
target_link_libraries(xsystem35 PRIVATE ${PORTMIDI})
endif()
+47 -29
View File
@@ -44,7 +44,6 @@
#include "image.h"
#include "debugger.h"
static Palette256 pal_256;
static boolean need_update = TRUE;
static boolean fade_outed = FALSE;
static int cursor_move_time = 50; /* カーソル移動にかかる時間(ms) */
@@ -54,16 +53,32 @@ static void palette_changed(void) {
dbg_on_palette_change();
}
static void initPal(Palette256 *pal) {
int i;
for (i = 0; i < 256; i++) {
pal->red[i] = 0; pal->green[i] = 0; pal->blue[i] = 0;
}
pal->red[0] = 0; pal->green[0] = 0; pal->blue[0] = 0;
pal->red[7] = 255; pal->green[7] = 255; pal->blue[7] = 255;
pal->red[15] = 255; pal->green[15] = 255; pal->blue[15] = 255;
pal->red[255] = 255; pal->green[255] = 255; pal->blue[255] = 255;
sdl_setPalette(pal, 0, 256);
static void initPal(void) {
static const Color initial_palette[256] = {
[ 0] = { 0, 0, 0},
[ 1] = {128, 0, 0},
[ 2] = { 0, 128, 0},
[ 3] = {128, 128, 0},
[ 4] = { 0, 0, 128},
[ 5] = {128, 0, 128},
[ 6] = { 0, 128, 128},
[ 7] = {192, 192, 192},
[ 8] = {192, 220, 192},
[ 9] = {166, 202, 240},
[ 15] = {255, 255, 255},
[246] = {255, 251, 240},
[247] = {160, 160, 164},
[248] = {128, 128, 128},
[249] = {255, 0, 0},
[250] = { 0, 255, 0},
[251] = {255, 255, 0},
[252] = { 0, 0, 255},
[253] = {255, 0, 255},
[254] = { 0, 255, 255},
[255] = {255, 255, 255},
};
memcpy(nact->ags.pal, initial_palette, sizeof(initial_palette));
sdl_setPalette(nact->ags.pal, 0, 256);
palette_changed();
}
@@ -105,9 +120,8 @@ boolean ags_check_param_xy(int *x, int *y) {
return TRUE;
}
void ags_init(const char *render_driver) {
void ags_init(const char *render_driver, bool enable_zb) {
nact->ags.mouse_warp_enabled = true;
nact->ags.pal = &pal_256;
nact->ags.world_size.width = SYS35_DEFAULT_WIDTH;
nact->ags.world_size.height = SYS35_DEFAULT_HEIGHT;
nact->ags.world_depth = SYS35_DEFAULT_DEPTH;
@@ -115,11 +129,14 @@ void ags_init(const char *render_driver) {
nact->ags.view_area.y = 0;
nact->ags.view_area.w = SYS35_DEFAULT_WIDTH;
nact->ags.view_area.h = SYS35_DEFAULT_HEIGHT;
nact->ags.enable_zb = enable_zb;
nact->ags.font_weight = enable_zb ? FONT_WEIGHT_BOLD : FONT_WEIGHT_NORMAL;
sdl_Initialize(render_driver);
font_init();
initPal(&pal_256);
initPal();
cg_init();
}
@@ -131,7 +148,7 @@ void ags_remove(void) {
void ags_reset(void) {
nact->ags.mouse_warp_enabled = true;
nact->ags.eventcb = NULL;
initPal(&pal_256);
initPal();
cg_reset();
}
@@ -222,20 +239,17 @@ void ags_updateFull() {
sdl_updateArea(&r, &p);
}
void ags_setPalettes(Palette256 *src_pal, int src, int dst, int cnt) {
int i;
for (i = 0; i < cnt; i++) {
nact->ags.pal->red [dst + i] = src_pal->red [src + i];
nact->ags.pal->green[dst + i] = src_pal->green[src + i];
nact->ags.pal->blue [dst + i] = src_pal->blue [src + i];
void ags_setPalettes(Color *src, int dst, int cnt) {
for (int i = 0; i < cnt; i++) {
nact->ags.pal[dst + i] = src[i];
}
palette_changed();
}
void ags_setPalette(int no, int red, int green, int blue) {
nact->ags.pal->red[no] = red;
nact->ags.pal->green[no] = green;
nact->ags.pal->blue[no] = blue;
nact->ags.pal[no].r = red;
nact->ags.pal[no].g = green;
nact->ags.pal[no].b = blue;
palette_changed();
}
@@ -583,9 +597,9 @@ void ags_fadeOut(int rate, boolean flag) {
fade(duration, flag, nact->ags.world_depth == 8 ? EFFECT_FADEOUT : EFFECT_DITHERING_FADEOUT);
if (nact->ags.world_depth == 8) {
Palette256 pal;
Color pal[256];
memset(&pal, 0, sizeof(pal));
sdl_setPalette(&pal, 0, 256);
sdl_setPalette(pal, 0, 256);
}
}
@@ -612,14 +626,18 @@ void ags_whiteOut(int rate, boolean flag) {
fade(duration, flag, nact->ags.world_depth == 8 ? EFFECT_WHITEIN : EFFECT_DITHERING_WHITEOUT);
if (nact->ags.world_depth == 8) {
Palette256 pal;
Color pal[256];
memset(&pal, 255, sizeof(pal));
sdl_setPalette(&pal, 0, 256);
sdl_setPalette(pal, 0, 256);
}
}
void ags_setFont(int type, int size) {
font_select(type, size);
font_select(type, size, FONT_WEIGHT_NORMAL);
}
void ags_setFontWithWeight(int type, int size, int weight) {
font_select(type, size, weight);
}
void ags_setCursorType(int type) {
+7 -3
View File
@@ -101,7 +101,7 @@ enum agsevent_button {
};
struct _ags {
Palette256 *pal; /* system palette */
Color pal[256]; /* system palette */
boolean pal_changed; /* system palette has changed */
MyDimension world_size; /* size of off-screen */
@@ -113,7 +113,10 @@ struct _ags {
agsurface_t *dib; /* main surface */
void (*eventcb)(agsevent_t *e); /* deliver event */
int font_weight;
bool mouse_warp_enabled;
bool enable_zb;
boolean noantialias; /* antialias を使用しない */
boolean noimagecursor; /* リソースファイルのカーソルを読みこまない */
};
@@ -122,7 +125,7 @@ typedef struct _ags ags_t;
/* 初期化関係 */
void ags_init(const char *render_driver);
void ags_init(const char *render_driver, bool enable_zb);
void ags_remove(void);
void ags_reset(void);
@@ -143,7 +146,7 @@ extern void ags_updateFull(void);
extern void ags_updateArea(int x, int y, int width, int height);
/* パレット関係 */
extern void ags_setPalettes(Palette256 *src_pal, int src, int dst, int cnt);
extern void ags_setPalettes(Color *src, int dst, int cnt);
extern void ags_setPalette(int no, int red, int green, int blue);
extern void ags_setPaletteToSystem(int src, int cnt);
@@ -199,6 +202,7 @@ enum FontType {
FONT_MINCHO,
};
extern void ags_setFont(int type, int size);
extern void ags_setFontWithWeight(int type, int size, int weight);
extern agsurface_t *ags_drawStringToSurface(const char *str);
/* カーソル関係 */
+1 -1
View File
@@ -108,5 +108,5 @@ void ald_init(int type, const char **file, int cnt, boolean use_mmap) {
int ald_get_maxno(DRIFILETYPE type) {
if (type >= DRIFILETYPEMAX || !dri[type])
return 0;
return dri[type]->nr_files;
return dri[type]->maxno;
}
-75
View File
@@ -1,75 +0,0 @@
/*
* bgm.dummy.c BGM (*BA.ALD) dummy implementation
*
* Copyright (C) 2019 <KichikuouChrome@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdio.h>
#include "portab.h"
#include "bgm.h"
int musbgm_init(DRIFILETYPE type, int base_no) {
return NG;
}
int musbgm_exit(void) {
return NG;
}
int musbgm_reset(void) {
return NG;
}
int musbgm_play(int no, int time, int vol) {
WARNING("not implemented");
return NG;
}
int musbgm_stop(int no, int time) {
WARNING("not implemented");
return NG;
}
int musbgm_fade(int no, int time, int vol) {
WARNING("not implemented");
return NG;
}
int musbgm_getpos(int no) {
WARNING("not implemented");
return 0;
}
int musbgm_getlen(int no) {
WARNING("not implemented");
return 0;
}
int musbgm_isplaying(int no) {
WARNING("not implemented");
return 0;
}
int musbgm_stopall(int time) {
WARNING("not implemented");
return NG;
}
int musbgm_wait(int no, int timeout) {
WARNING("not implemented");
return NG;
}
+8 -11
View File
@@ -36,7 +36,6 @@
* static methods
*/
static bmp_header *extract_header(uint8_t *b);
static void getpal(Palette256 *pal, uint8_t *b);
static void extract_8bit(bmp_header *bmp, uint8_t *pic, uint8_t *b);
static void extract_24bit(bmp_header *bmp, uint16_t *pic, uint8_t *b);
@@ -65,17 +64,16 @@ static bmp_header *extract_header(uint8_t *b) {
/*
* Get palette from raw data
* pal: palette to be stored
* b : raw data (pointer to palette)
*/
static void getpal(Palette256 *pal, uint8_t *b) {
int i;
for (i = 0; i < 256; i++) {
pal->blue[i] = *b++;
pal->red[i] = *b++;
pal->green[i] = *b++;
static Color *getpal(uint8_t *b) {
Color *pal = malloc(sizeof(Color) * 256);
for (int i = 0; i < 256; i++) {
pal[i].b = *b++;
pal[i].r = *b++;
pal[i].g = *b++;
}
return pal;
}
/*
@@ -168,8 +166,7 @@ cgdata *bmp256_extract(uint8_t *data) {
bmp_header *bmp = extract_header(data);
cgdata *cg = calloc(1, sizeof(cgdata));
cg->pal = malloc(sizeof(Palette256));
getpal(cg->pal, data + bmp->bmpPp);
cg->pal = getpal(data + bmp->bmpPp);
/* +10: margin for broken cg */
cg->pic = malloc(sizeof(uint8_t) * ((bmp->bmpXW + 10) * (bmp->bmpYW + 10)));
-238
View File
@@ -1,238 +0,0 @@
/*
* cdrom.FreeBSD.c CD-ROMアクセス
*
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* $Id: cdrom.FreeBSD.c,v 1.17 2002/08/18 09:35:29 chikama Exp $ */
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/cdio.h>
#include "portab.h"
#include "cdrom.h"
#include "music_private.h"
#include "system.h"
static int cdrom_init(char *);
static int cdrom_exit(void);
static int cdrom_reset(void);
static int cdrom_start(int, int);
static int cdrom_stop();
static int cdrom_getPlayingInfo(cd_time *);
#define cdrom cdrom_bsd
cdromdevice_t cdrom = {
cdrom_init,
cdrom_exit,
cdrom_reset,
cdrom_start,
cdrom_stop,
cdrom_getPlayingInfo,
NULL,
NULL
};
static int cd_fd;
static boolean enabled = FALSE;
static struct cd_toc_entry toc_buffer[100];
static boolean msfmode = TRUE; /* default は MSFPLAY mode */
static int lastindex; /* 最終トラック */
/* ioctlがエラーで帰って来る場合 IOCTL_RETRY_TIME 回リトライする */
static int do_ioctl(int cmd, void *data) {
int i;
for (i = 0; i < CDROM_IOCTL_RETRY_TIME; i++) {
if (0 <= ioctl(cd_fd, cmd, data)) {
return 0;
}
usleep(CDROM_IOCTL_RETRY_INTERVAL * 100 * 1000);
}
return -1;
}
/* CD-ROM の目次を読み出しておく */
static int get_cd_entry() {
int endtrk, i;
struct ioc_toc_header tochdr;
struct ioc_read_toc_entry toc;
struct ioc_play_msf msf;
/* 最終トラック番号を得る */
if (do_ioctl(CDIOREADTOCHEADER, &tochdr) < 0) {
WARNING("CDIOREADTOCHEADER: %s", strerror(errno));
return NG;
}
lastindex = endtrk = tochdr.ending_track;
i = tochdr.ending_track - tochdr.starting_track + 1;
if (endtrk <= 1) { /* 2トラック以上ないとダメ */
WARNING("No CD-AUDIO in CD-ROM");
return NG;
}
prv.cd_maxtrk = lastindex;
/* すべてのトラックの目次を読みだしてキャッシュしておく */
toc.address_format = CD_MSF_FORMAT;
toc.starting_track = 0;
toc.data_len = (i + 1) * sizeof(struct cd_toc_entry);
toc.data = toc_buffer;
if (do_ioctl(CDIOREADTOCENTRYS, &toc) < 0) {
WARNING("CDIOREADTOCENTRYS: %s", strerror(errno));
return NG;
}
#ifdef CDROM_USE_TRKIND_ONLY
msfmode = FALSE;
return OK;
#endif
/* CDROMPLAYMSF が有効かチェック */
msf.start_m = toc_buffer[1].addr.msf.minute;
msf.start_s = toc_buffer[1].addr.msf.second;
msf.start_f = toc_buffer[1].addr.msf.frame;
msf.end_m = toc_buffer[2].addr.msf.minute;
msf.end_s = toc_buffer[2].addr.msf.second;
msf.end_f = toc_buffer[2].addr.msf.frame;
if (do_ioctl(CDIOCPLAYMSF, &msf) < 0) {
WARNING("CDIOPLAYMSF: %s", strerror(errno));
WARNING("CD-ROM: change TRKMODE");
msfmode = FALSE;
}
/* stop */
if (do_ioctl(CDIOCSTOP, NULL) < 0) {
WARNING("CDIOCSTOP: %s", strerror(errno));
return NG;
}
return OK;
}
/* デバイスの初期化 */
int cdrom_init(char *dev_cd) {
if (dev_cd == NULL) return NG;
if ((cd_fd = open(dev_cd, O_RDONLY, 0)) < 0) {
WARNING("CDROM_DEVICE OPEN: %s", strerror(errno));
enabled = FALSE;
return NG;
}
if (OK == get_cd_entry()) {
enabled = TRUE;
return OK;
}
enabled = FALSE;
return NG;
}
/* デバイスの後始末 */
int cdrom_exit(void) {
if (enabled) {
cdrom_stop();
close(cd_fd);
}
return OK;
}
int cdrom_reset(void) {
return cdrom_stop();
}
/* トラック番号 trk の演奏 trk = 1~ */
int cdrom_start(int trk, int loop) {
struct ioc_play_msf msf;
struct ioc_play_track track;
if (!enabled) return NG;
/* 曲数よりも多い指定は不可*/
if (trk > lastindex) {
return NG;
}
/* drive spin up */
if (do_ioctl(CDIOCSTART, NULL) < 0) {
WARNING("CDIOCSTART: %s", strerror(errno));
return NG;
}
if (msfmode) {
msf.start_m = toc_buffer[trk - 1].addr.msf.minute;
msf.start_s = toc_buffer[trk - 1].addr.msf.second;
msf.start_f = toc_buffer[trk - 1].addr.msf.frame;
msf.end_m = toc_buffer[trk].addr.msf.minute;
msf.end_s = toc_buffer[trk].addr.msf.second;
msf.end_f = toc_buffer[trk].addr.msf.frame;
if (do_ioctl(CDIOCPLAYMSF, &msf) < 0) {
WARNING("CDIOPLAYMSF: %s", strerror(errno));
return NG;
}
} else {
track.start_track = track.end_track = trk;
track.start_index = track.end_index = 0;
if (do_ioctl(CDIOCPLAYTRACKS, &track) < 0) {
WARNING("CDIOCPLAYTRACKS: %s", strerror(errno));
return NG;
}
}
return OK;
}
/* 演奏停止 */
int cdrom_stop() {
if (enabled) {
/* if (do_ioctl(CDIOCSTOP, NULL) < 0) { */
if (do_ioctl(CDIOCPAUSE, NULL) < 0) {
/* WARNING("CDIOCSTOP: %s", strerror(errno)); */
WARNING("CDIOCPAUSE: %s", strerror(errno));
}
return OK;
}
return NG;
}
/* 現在演奏中のトラック情報の取得 */
int cdrom_getPlayingInfo (cd_time *info) {
struct ioc_read_subchannel s;
struct cd_sub_channel_info data;
if (!enabled)
return NG;
memset(&s, 0, sizeof(s));
s.data = &data;
s.data_len = sizeof (data);
s.address_format = CD_MSF_FORMAT;
s.data_format = CD_CURRENT_POSITION;
if (do_ioctl(CDIOCREADSUBCHANNEL, &s) < 0) {
WARNING("CDIOCREADSUBCHANNEL: %s", strerror(errno));
return NG;
}
if (s.data->header.audio_status != CD_AS_PLAY_IN_PROGRESS) {
return NG;
}
info->t = s.data->what.position.track_number;
info->m = s.data->what.position.reladdr.msf.minute;
info->s = s.data->what.position.reladdr.msf.second;
info->f = s.data->what.position.reladdr.msf.frame;
return OK;
}
-268
View File
@@ -1,268 +0,0 @@
/*
* cdrom.Linux.c CD-ROMアクセス
*
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* $Id: cdrom.Linux.c,v 1.18 2002/08/18 09:35:29 chikama Exp $ */
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#if defined(sun)
#include <sys/cdio.h>
struct cdrom_msf0 {
unsigned char minute; /* minute */
unsigned char second; /* second */
unsigned char frame; /* frame */
};
#else
#include <linux/cdrom.h>
#endif /* sun */
#include "portab.h"
#include "cdrom.h"
#include "music_private.h"
#include "system.h"
static int cdrom_init(char *);
static int cdrom_exit(void);
static int cdrom_reset(void);
static int cdrom_start(int, int);
static int cdrom_stop();
static int cdrom_getPlayingInfo(cd_time *);
#define cdrom cdrom_linux
cdromdevice_t cdrom = {
cdrom_init,
cdrom_exit,
cdrom_reset,
cdrom_start,
cdrom_stop,
cdrom_getPlayingInfo,
NULL,
NULL
};
static int cd_fd;
static boolean enabled = FALSE;
static struct cdrom_msf0 tocmsf[100];
static boolean msfmode = TRUE; /* default は MSFPLAY mode */
static int lastindex; /* 最終トラック */
/* ioctlがエラーで帰って来る場合 IOCTL_RETRY_TIME 回リトライする */
static int do_ioctl(int cmd, void *data) {
int i;
for (i = 0; i < CDROM_IOCTL_RETRY_TIME; i++) {
if (0 <= ioctl(cd_fd, cmd, data)) {
return 0;
}
usleep(CDROM_IOCTL_RETRY_INTERVAL * 100 * 1000);
}
return -1;
}
/* CD-ROM の目次を読み出しておく */
static int get_cd_entry() {
int endtrk, i;
struct cdrom_tochdr tochdr;
struct cdrom_tocentry toc;
struct cdrom_msf msf;
/* 最終トラック番号を得る */
if (do_ioctl(CDROMREADTOCHDR, &tochdr) < 0) {
WARNING("CDROMREADTOCHDR: %s", strerror(errno));
return NG;
}
lastindex = endtrk = tochdr.cdth_trk1;
if (endtrk <= 1) { /* 2トラック以上ないとダメ */
WARNING("No CD-AUDIO in CD-ROM");
return NG;
}
prv.cd_maxtrk = lastindex;
/* すべてのトラックの目次を読みだしてキャッシュしておく */
toc.cdte_format = CDROM_MSF;
for (i = 1; i <= endtrk; i++) {
toc.cdte_track = i;
if (do_ioctl(CDROMREADTOCENTRY, &toc) < 0) {
WARNING("CDROMREADTOCENTRY: %s", strerror(errno));
return NG;
}
tocmsf[i - 1].minute = toc.cdte_addr.msf.minute;
tocmsf[i - 1].second = toc.cdte_addr.msf.second;
tocmsf[i - 1].frame = toc.cdte_addr.msf.frame;
}
/* リードアウトを読み出す */
toc.cdte_track = CDROM_LEADOUT;
if (do_ioctl(CDROMREADTOCENTRY, &toc) < 0) {
WARNING("CDROMREADTOCENTRY: %s", strerror(errno));
return NG;
}
#ifdef PPC
/* Linux PPC 対策 ;last track -1 frame */
FRAMES_TO_MSF(MSF_TO_FRAMES(toc.cdte_addr.msf.minute,
toc.cdte_addr.msf.second,
toc.cdte_addr.msf.frame) - 1,
&tocmsf[endtrk].minute,
&tocmsf[endtrk].second,
&tocmsf[endtrk].frame);
#else
tocmsf[endtrk].minute = toc.cdte_addr.msf.minute;
tocmsf[endtrk].second = toc.cdte_addr.msf.second;
tocmsf[endtrk].frame = toc.cdte_addr.msf.frame;
#endif
#ifdef CDROM_USE_TRKIND_ONLY
msfmode = FALSE;
return OK;
#endif
/* CDROMPLAYMSF が有効かチェック */
msf.cdmsf_min0 = tocmsf[1].minute;
msf.cdmsf_sec0 = tocmsf[1].second;
msf.cdmsf_frame0 = tocmsf[1].frame;
msf.cdmsf_min1 = tocmsf[2].minute;
msf.cdmsf_sec1 = tocmsf[2].second;
msf.cdmsf_frame1 = tocmsf[2].frame;
if (do_ioctl(CDROMPLAYMSF, &msf) < 0) {
WARNING("CDROMPLAYMSF: %s", strerror(errno));
WARNING("CD-ROM: change TRKIND mode");
msfmode = FALSE;
}
/* stop */
if (do_ioctl(CDROMSTOP, NULL) < 0) {
WARNING("CDROMSTOP: %s", strerror(errno));
return NG;
}
return OK;
}
/* デバイスの初期化 */
static int cdrom_init(char *dev_cd) {
if (dev_cd == NULL) return NG;
if ((cd_fd = open(dev_cd, O_RDONLY, 0)) < 0) {
WARNING("CDROM_DEVICE OPEN: %s", strerror(errno));
enabled = FALSE;
return NG;
}
if (OK == get_cd_entry()) {
enabled = TRUE;
return OK;
}
enabled = FALSE;
return NG;
}
/* デバイスの後始末 */
static int cdrom_exit(void) {
if (enabled) {
cdrom_stop();
close(cd_fd);
}
return OK;
}
static int cdrom_reset(void) {
return cdrom_stop();
}
/* トラック番号 trk の演奏 trk = 1~ */
static int cdrom_start(int trk, int loop) {
struct cdrom_msf msf;
struct cdrom_ti ti;
if (!enabled) return NG;
/* 曲数よりも多い指定は不可*/
if (trk > lastindex) {
return NG;
}
/* drive spin up */
if (do_ioctl(CDROMSTART, NULL) < 0) {
WARNING("CDROMSTART: %s", strerror(errno));
return NG;
}
if (msfmode) {
msf.cdmsf_min0 = tocmsf[trk - 1].minute;
msf.cdmsf_sec0 = tocmsf[trk - 1].second;
msf.cdmsf_frame0 = tocmsf[trk - 1].frame;
msf.cdmsf_min1 = tocmsf[trk].minute;
msf.cdmsf_sec1 = tocmsf[trk].second;
msf.cdmsf_frame1 = tocmsf[trk].frame;
if (do_ioctl(CDROMPLAYMSF, &msf) < 0) {
WARNING("CDROMPLAYMSF: %s", strerror(errno));
return NG;
}
return OK;
} else {
ti.cdti_trk0 = ti.cdti_trk1 = trk;
ti.cdti_ind0 = ti.cdti_ind1 = 0;
if (do_ioctl(CDROMPLAYTRKIND, &ti) < 0) {
WARNING("CDROMPLAYTRKIND: %s", strerror(errno));
return NG;
}
return OK;
}
}
/* 演奏停止 */
static int cdrom_stop() {
if (enabled) {
/* if (do_ioctl(CDROMSTOP, NULL) < 0) { */
if (do_ioctl(CDROMPAUSE, NULL) < 0) {
/* WARNING("CDROMSTOP: %s", strerror(errno)); */
WARNING("CDROMPAUSE: %s", strerror(errno));
return NG;
}
return OK;
}
return NG;
}
/* 現在演奏中のトラック情報の取得 */
static int cdrom_getPlayingInfo (cd_time *info) {
struct cdrom_subchnl sc;
if (!enabled)
return NG;
sc.cdsc_format = CDROM_MSF;
if (do_ioctl(CDROMSUBCHNL, &sc) < 0) {
WARNING("CDROMSUBCHNL: %s", strerror(errno));
return NG;
}
if (sc.cdsc_audiostatus != CDROM_AUDIO_PLAY) {
return NG;
}
info->t = sc.cdsc_trk;
info->m = sc.cdsc_reladdr.msf.minute;
info->s = sc.cdsc_reladdr.msf.second;
info->f = sc.cdsc_reladdr.msf.frame;
return OK;
}
+4 -1
View File
@@ -22,11 +22,14 @@
#include <stdio.h>
#include "cdrom.h"
#include "ald_manager.h"
#include "music.h"
#include "music_private.h"
static int current_track;
static int cdrom_bgm_init(char *dev) {
static int cdrom_bgm_init(char *playlist) {
prv.cd_maxtrk = ald_get_maxno(DRIFILE_BGM) + 1;
return OK;
}
-71
View File
@@ -1,71 +0,0 @@
/*
* cdrom.c CD-ROM control wrapper
*
* Copyright (C) 2000- Masaki Chikama (Wren) <masaki-c@is.aist-nara.ac.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* $Id: cdrom.c,v 1.20 2002/08/18 09:35:29 chikama Exp $ */
#include "config.h"
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include "portab.h"
#include "cdrom.h"
#include "system.h"
#if defined(ENABLE_CDROM_LINUX)
extern cdromdevice_t cdrom_linux;
#define NATIVE_CD_DEVICE &cdrom_linux
#elif defined(ENABLE_CDROM_BSD)
extern cdromdevice_t cdrom_bsd;
#define NATIVE_CD_DEVICE &cdrom_bsd
#elif defined(ENABLE_CDROM_EMSCRIPTEN)
extern cdromdevice_t cdrom_emscripten;
#define NATIVE_CD_DEVICE &cdrom_emscripten
#else
extern cdromdevice_t cdrom_empty;
#define NATIVE_CD_DEVICE &cdrom_empty
#endif
#ifdef ENABLE_CDROM_MP3
extern cdromdevice_t cdrom_mp3;
#endif
cdromdevice_t *cd_init(const char *dev) {
#if defined(ENABLE_CDROM_EMSCRIPTEN)
return NATIVE_CD_DEVICE;
#else
struct stat st;
if (dev && stat(dev, &st) && (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)))
return NATIVE_CD_DEVICE;
#ifdef ENABLE_CDROM_MP3
return &cdrom_mp3;
#else
WARNING("no cdrom device available");
return NULL;
#endif
#endif // ENABLE_CDROM_EMSCRIPTEN
}
-69
View File
@@ -1,69 +0,0 @@
/*
* cdrom.empty.c CD-ROMアクセス
*
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* $Id: cdrom.empty.c,v 1.8 2002/08/18 09:35:29 chikama Exp $ */
#include <unistd.h>
#include "portab.h"
#include "cdrom.h"
static int cdrom_init(char *);
static int cdrom_exit(void);
static int cdrom_reset(void);
static int cdrom_start(int, int);
static int cdrom_stop();
static int cdrom_getPlayingInfo(cd_time *);
#define cdrom cdrom_empty
cdromdevice_t cdrom = {
cdrom_init,
cdrom_exit,
cdrom_reset,
cdrom_start,
cdrom_stop,
cdrom_getPlayingInfo,
NULL,
NULL
};
int cdrom_init(char *name) {
return NG;
}
int cdrom_exit(void) {
return OK;
}
int cdrom_reset(void) {
return OK;
}
int cdrom_start(int trk, int loop) {
return OK;
}
int cdrom_stop() {
return OK;
}
int cdrom_getPlayingInfo (cd_time *info) {
return NG;
}
+1 -1
View File
@@ -27,7 +27,7 @@
static int frame_of_getpos = -1;
int cdrom_init(char *name) {
int cdrom_init(char *playlist) {
return OK;
}
-2
View File
@@ -51,8 +51,6 @@ typedef struct _cdromdevice cdromdevice_t;
extern cdromdevice_t cdrom_bgm;
extern cdromdevice_t *cd_init(const char *dev);
#define CD_FPS 75
#define FRAMES_TO_MSF(f, M,S,F) { \
int value = f; \
+3
View File
@@ -64,6 +64,9 @@ static int start_time;
static int cdrom_init(char *playlist_path) {
char buf[256];
if (!playlist_path || !playlist_path[0])
return NG;
FILE *fp = fopen(playlist_path, "r");
if (fp) {
// Skip the first line
+9 -14
View File
@@ -293,13 +293,8 @@ void cg_load(int no, int flg) {
bank = cg_vspPB == -1 ? cg->vsp_bank : cg_vspPB;
set_vspbank(cg->pic, bank << 4, cg->width, cg->height);
/* copy palettes 0 -> bank */
{
int i, i_dst = bank << 4;
for (i = 0; i < 16; i++) {
cg->pal->red[i + i_dst] = cg->pal->red[i];
cg->pal->green[i + i_dst] = cg->pal->green[i];
cg->pal->blue[i + i_dst] = cg->pal->blue[i];
}
if (bank != 0) {
memcpy(cg->pal + bank * 16, cg->pal, 16 * sizeof(cg->pal[0]));
}
if (flg != -1) {
flg |= (bank << 4);
@@ -310,22 +305,22 @@ void cg_load(int no, int flg) {
if (GCMD_LOAD_PALETTE(cg_fflg)) {
switch(cg->type) {
case ALCG_VSP:
ags_setPalettes(cg->pal, 0, bank << 4, 16);
ags_setPalettes(cg->pal, bank << 4, 16);
break;
case ALCG_PMS8:
// Avoid changing the Windows' reserved palette area (0-9, 246-255)
if (cg->pms_bank & 1)
ags_setPalettes(cg->pal, 10, 10, 6);
ags_setPalettes(cg->pal + 10, 10, 6);
if (cg->pms_bank & (1 << 15))
//ags_setPalettes(cg->pal, 240, 240, 15);
ags_setPalettes(cg->pal, 240, 240, 10);
ags_setPalettes(cg->pal + 240, 240, 6);
for (i = 1; i < 15; i++) {
if (cg->pms_bank & (1 << i)) {
ags_setPalettes(cg->pal, i * 16, i * 16, 16);
ags_setPalettes(cg->pal + i * 16, i * 16, 16);
}
}
break;
case ALCG_BMP8:
ags_setPalettes(cg->pal, 10, 10, 236);
ags_setPalettes(cg->pal + 10, 10, 236);
break;
default:
break;
@@ -463,7 +458,7 @@ int cg_load_with_filename(char *fname_utf8, int x, int y) {
/* load palette if not extracted */
if (cg->depth == 8) {
if (GCMD_LOAD_PALETTE(cg_fflg))
ags_setPalettes(cg->pal, 10, 10, 236);
ags_setPalettes(cg->pal + 10, 10, 236);
if (GCMD_SET_PALETTE(cg_fflg))
ags_setPaletteToSystem(0, 256);
}
+1 -1
View File
@@ -55,7 +55,7 @@ typedef struct {
uint8_t *pic; // extracted pixel data
uint8_t *alpha; // extracted alpha data if exists
Palette256 *pal; // extracted palette data if exists
Color *pal; // 256-color palette if exists
int vsp_bank; // palette bank for vsp
int pms_bank; // palette bank for pms
+2 -16
View File
@@ -42,9 +42,6 @@
#include "ald_manager.h"
#include "LittleEndian.h"
#include "hacks.h"
#if HAVE_UNAME
#include <sys/utsname.h>
#endif
/* 選択 Window OPEN 時 callback */
static int cb_sel_init_page = 0;
@@ -829,20 +826,9 @@ void commands2F52() {
int eNum = getCaliValue();
if (eNum <= 0) return;
#if HAVE_UNAME
struct utsname un;
char s[256];
if (uname(&un) < 0) return;
NOTICE("sysname %s nodename %s release %s version %s machine %s",
un.sysname, un.nodename, un.release, un.version, un.machine);
sprintf(s,"%s %s %s",
un.sysname, un.release, un.machine);
#else
const char *s = CMAKE_SYSTEM_NAME;
#endif
const char *s = SDL_GetPlatform();
svar_set(eNum, s);
DEBUG_COMMAND("sysGetOsName %d: %s", eNum, s);
DEBUG_COMMAND("sysGetOSName %d: %s", eNum, s);
}
void commands2F53() {
+2 -2
View File
@@ -46,9 +46,9 @@ void commands2F60() {
SYSERROR("No DLL initilized");
}
if (dll + type == NULL) goto eexit;
if (type < 0 || type >= nact->ain.dllnum) goto eexit;
if (dll[type].function_num < fnum) goto eexit;
if (fnum < 0 || fnum >= dll[type].function_num) goto eexit;
if (dll[type].function[fnum].entrypoint == NULL) goto eexit;
+1 -1
View File
@@ -72,7 +72,7 @@ void commandCX() {
case 0:
// In Daiakuji, the image after the blending is used as a source image
// for sprite copy (CX 1). SDL's SIMD blending implementation has some
// error (blending #ff00ff and #ff00ff results in #fd00fd), so the
// error (https://github.com/libsdl-org/SDL/issues/3364), so the
// resulting color may not match the colorkey of CX 1. To workaround
// this, specify a small alpha mod so that SDL will use a "slow path"
// that does accurate calculation.
+2 -2
View File
@@ -33,7 +33,7 @@
#include "ags.h"
#include "message.h"
#include "hankaku.h"
#include "hacks.h"
/* MI 用パラメータ */
INPUTSTRING_PARAM mi_param;
@@ -60,7 +60,7 @@ void commandMP() {
char *str;
/* Patched English executable appends num2 spaces instead of truncating */
if (nact->game == GAME_RANCE3_ENG || nact->game == GAME_RANCE4_ENG) {
if (game_id == GAME_RANCE3_ENG || game_id == GAME_RANCE4_ENG) {
str = calloc(strlen(src) + num2 * strlen(fullwidth_blank[nact->encoding]) + 1, 1);
if (NULL == str) {
NOMEMERR();
+3 -3
View File
@@ -112,9 +112,9 @@ void commandPG() { /* T2 */
int i;
for (i = 0; i < num2; i++) {
*var = nact->ags.pal->red[num1 + i]; var++;
*var = nact->ags.pal->green[num1 + i]; var++;
*var = nact->ags.pal->blue[num1 + i]; var++;
*var++ = nact->ags.pal[num1 + i].r;
*var++ = nact->ags.pal[num1 + i].g;
*var++ = nact->ags.pal[num1 + i].b;
}
DEBUG_COMMAND("PG %p,%d,%d:", var, num1, num2);
}
+2 -1
View File
@@ -26,6 +26,7 @@
#include "xsystem35.h"
#include "scenario.h"
#include "music.h"
#include "hacks.h"
/* ぱにょ〜ん 異常シナリオ対策 */
static boolean dummy_pcm_in_play = FALSE;
@@ -272,7 +273,7 @@ void commandSU() {
}
}
/* 闘神都市II 異常シナリオ対策 */
if (nact->game == GAME_TT2) {
if (game_id == GAME_TT2) {
*var1 = *var2 = 0;
}
+2 -1
View File
@@ -33,6 +33,7 @@
#include "cmd_check.h"
#include "sdl_core.h"
#include "music_cdrom.h"
#include "hacks.h"
unsigned Y3waitFlags = KEYWAIT_CANCELABLE;
@@ -126,7 +127,7 @@ void commandY() {
default:
if (p1 == 1003) {
sys_key_releasewait(SYS35KEY_RET, FALSE);
} else if (nact->game == GAME_RANCE4_V2 && p2 == 1) {
} else if (game_id == GAME_RANCE4_V2 && p2 == 1) {
// Return immediately if any key is pressed.
sysVar[0] = sys_getInputInfo();
if (sysVar[0])
+6 -5
View File
@@ -113,11 +113,12 @@ void commandZS() {
void commandZB() {
/* メッセージ文字を太さを設定 */
int size = getCaliValue();
nact->msg.MsgFontBoldSize = size;
DEBUG_COMMAND("ZB %d:",size);
int weight = getCaliValue();
if (nact->ags.enable_zb)
nact->ags.font_weight = weight;
DEBUG_COMMAND("ZB %d:", weight);
}
void commandZH() {
+1 -1
View File
@@ -531,7 +531,7 @@ void dbg_onsleep(void) {
}
void dbg_on_palette_change(void) {
if (dbg_impl)
if (dbg_impl && dbg_impl->on_palette_change)
dbg_impl->on_palette_change();
}
+3 -3
View File
@@ -488,9 +488,9 @@ static void cmd_palette(cJSON *args, cJSON *resp) {
cJSON_AddNumberToObject(body, "version", palette_version);
cJSON_AddItemToObjectCS(body, "palette", palette = cJSON_CreateArray());
for (int i = 0; i < 256; i++) {
int val = nact->ags.pal->red[i] << 16 |
nact->ags.pal->green[i] << 8 |
nact->ags.pal->blue[i];
int val = nact->ags.pal[i].r << 16 |
nact->ags.pal[i].g << 8 |
nact->ags.pal[i].b;
cJSON_AddItemToArray(palette, cJSON_CreateNumber(val));
}
}
+34 -34
View File
@@ -30,48 +30,48 @@
#include "LittleEndian.h"
#include "dri.h"
static bool read_index(int disk, drifiles *d, FILE *fp) {
static bool read_index(int volume, drifiles *d, FILE *fp) {
fseek(fp, 0L, SEEK_END);
int filesize = ftell(fp);
// Get ptrsize and mapsize
// Get the size of offsets table and link table.
uint8_t hdr[6];
fseek(fp, 0L, SEEK_SET);
if (fread(hdr, 6, 1, fp) != 1)
return false;
int ptrsize = LittleEndian_get3B(hdr, 0) << 8;
int mapsize = (LittleEndian_get3B(hdr, 3) << 8) - ptrsize;
if (ptrsize <= 0 || mapsize <= 0 || ptrsize + mapsize > filesize)
int ofssize = LittleEndian_get3B(hdr, 0) << 8;
int linksize = (LittleEndian_get3B(hdr, 3) << 8) - ofssize;
if (ofssize <= 0 || linksize <= 0 || ofssize + linksize > filesize)
return false;
// Read the pointer table and the link table
uint8_t *ptbl = malloc(ptrsize + mapsize);
memcpy(ptbl, hdr, 6);
if (fread(ptbl + 6, ptrsize + mapsize - 6, 1, fp) != 1) {
free(ptbl);
// Read the link table. In System 3.9, only the first volume's link table is
// valid. It's different in System 3.8 and earlier, and games that depend
// on the old behavior (e.g. Child Assassin in Alice CD 2.50) won't work.
if (!d->link) {
d->nr_files = linksize / 3;
d->link = calloc(1, linksize);
d->offset = calloc(sizeof(uint32_t), d->nr_files);
fseek(fp, ofssize, SEEK_SET);
if (fread(d->link, linksize, 1, fp) != 1)
return false;
}
// Read the offsets table.
uint8_t *otbl = malloc(ofssize);
fseek(fp, 0L, SEEK_SET);
if (fread(otbl, ofssize, 1, fp) != 1) {
free(otbl);
return false;
}
uint8_t *ltbl = ptbl + ptrsize;
// (Re)allocate the index buffers
int nr_files = mapsize / 3;
if (d->nr_files < nr_files) {
d->disk = realloc(d->disk, nr_files);
d->offset = realloc(d->offset, sizeof(uint32_t) * nr_files);
memset(d->disk + d->nr_files, 0, nr_files - d->nr_files);
memset(d->offset + d->nr_files, 0, sizeof(uint32_t) * (nr_files - d->nr_files));
d->nr_files = nr_files;
}
// Parse the index
for (int i = 0; i < nr_files; i++) {
if (disk != ltbl[i * 3] - 1)
for (int i = 0; i < d->nr_files; i++) {
if (d->link[i * 3] != volume)
continue;
d->disk[i] = ltbl[i * 3];
int ptr = LittleEndian_getW(ltbl, i * 3 + 1);
d->offset[i] = LittleEndian_get3B(ptbl, ptr * 3) << 8;
if (d->maxno < i)
d->maxno = i;
int offset_index = LittleEndian_getW(d->link, i * 3 + 1);
d->offset[i] = LittleEndian_get3B(otbl, offset_index * 3) << 8;
}
free(ptbl);
free(otbl);
return true;
}
@@ -88,7 +88,7 @@ drifiles *dri_init(const char **file, int cnt, boolean use_mmap) {
FILE *fp = fopen(file[i], "rb");
if (!fp)
SYSERROR("%s: %s", file[i], strerror(errno));
if (!read_index(i, d, fp)) {
if (!read_index(i + 1, d, fp)) {
// Only errors in *A.ALD are fatal, because some games have
// dummy (invalid) *[B-Z].ALD files.
if (i == 0)
@@ -115,18 +115,18 @@ drifiles *dri_init(const char **file, int cnt, boolean use_mmap) {
}
dridata *dri_getdata(drifiles *d, int no) {
if (no < 0 || no >= d->nr_files || !d->disk[no] || !d->offset[no])
if (no < 0 || no >= d->nr_files || !d->link[no * 3] || !d->offset[no])
return NULL;
int disk = d->disk[no] - 1;
int volume = d->link[no * 3];
uint8_t *data;
int ptr, size;
if (d->mmapped) {
data = d->mmap[disk]->addr + d->offset[no];
data = d->mmap[volume - 1]->addr + d->offset[no];
ptr = LittleEndian_getDW(data, 0);
size = LittleEndian_getDW(data, 4);
} else {
FILE *fp = fopen(d->fnames[disk], "rb");
FILE *fp = fopen(d->fnames[volume - 1], "rb");
if (!fp)
return NULL;
uint8_t entry_header[8];
+2 -1
View File
@@ -34,7 +34,8 @@ struct _drifiles {
mmap_t *mmap[DRIFILEMAX];
char *fnames[DRIFILEMAX];
int nr_files; // upper limit on how many files could be referenced by this archive
uint8_t *disk; // file numbers
int maxno;
uint8_t *link; // link table
uint32_t *offset; // offsets in file
};
typedef struct _drifiles drifiles;
+60
View File
@@ -21,12 +21,16 @@
*/
/* $Id: filecheck.c,v 1.5 2006/04/21 16:40:48 chikama Exp $ */
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#ifdef _WIN32
#include <direct.h>
#include <windows.h>
#undef min
#undef max
@@ -47,9 +51,65 @@ static char *get_fullpath(const char* dir, const char *filename) {
return fn;
}
#ifdef _WIN32
static int make_dir(const char *path)
{
wchar_t wpath[PATH_MAX + 1];
if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path, -1, wpath, PATH_MAX + 1)) {
errno = EILSEQ;
return -1;
}
return _wmkdir(wpath);
}
#else
#define make_dir(path) mkdir(path, S_IRWXU)
#endif
// Adapted from http://stackoverflow.com/a/2336245/119527
static int mkdir_p(const char *path)
{
const size_t len = strlen(path);
char _path[PATH_MAX];
char *p;
errno = 0;
// Copy string so its mutable
if (len > sizeof(_path)-1) {
errno = ENAMETOOLONG;
return -1;
}
strcpy(_path, path);
// Iterate the string
for (p = _path + 1; *p; p++) {
if (*p == '/') {
// Temporarily truncate
*p = '\0';
if (make_dir(_path) != 0) {
if (errno != EEXIST)
return -1;
}
*p = '/';
}
}
if (make_dir(_path) != 0) {
if (errno != EEXIST)
return -1;
}
return 0;
}
/* list up file in current directory */
/* name : save/load directory */
void fc_init(const char *name) {
mkdir_p(name);
saveDataPath = strdup(name);
}
+23 -3
View File
@@ -23,6 +23,11 @@
#include <math.h>
#include <SDL.h>
#include <SDL_ttf.h>
#ifdef _WIN32
#include "win/resources.h"
#endif
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
@@ -31,6 +36,7 @@
#include "system.h"
#include "font.h"
#include "sdl_private.h"
#include "hacks.h"
typedef struct {
int size;
@@ -73,7 +79,7 @@ static FontTable *font_lookup(int size, int type) {
return NULL;
}
void font_select(int type, int size) {
void font_select(int type, int size, int weight) {
FontTable *tbl;
if (NULL == (tbl = font_lookup(size, type))) {
@@ -89,6 +95,11 @@ void font_select(int type, int size) {
if (fp)
fs = TTF_OpenFontIndexRW(SDL_RWFromFP(fp, true), true, size, this.face[type]);
}
#endif
#ifdef _WIN32
SDL_RWops *r = open_resource(this.name[type], "fonts");
if (r)
fs = TTF_OpenFontIndexRW(r, true, size, this.face[type]);
#endif
if (!fs)
SYSERROR("Cannot open font %s", this.name[type]);
@@ -98,6 +109,7 @@ void font_select(int type, int size) {
} else {
fontset = tbl;
}
TTF_SetFontStyle(fontset->id, weight > 5 ? TTF_STYLE_BOLD : TTF_STYLE_NORMAL);
}
SDL_Surface *font_get_glyph(const char *str_utf8) {
@@ -164,7 +176,15 @@ SDL_Rect font_draw_glyph(int x, int y, const char *str_utf8, uint8_t cl) {
if (!fontset)
return r_dst;
if (this.antialiase_on) {
bool antialias = this.antialiase_on;
// The post-effect in Rance 3 opening does not work properly if colors other
// than the specified text color (32) are used.
// https://github.com/kichikuou/xsystem35-sdl2/issues/54
// In Rance 3, text color 32 is only used in the opening.
if ((game_id == GAME_RANCE3 || game_id == GAME_RANCE3_ENG) && cl == 32)
antialias = false;
if (antialias) {
fs = TTF_RenderUTF8_Blended(fontset->id, str_utf8, sdl_col[cl]);
} else {
fs = TTF_RenderUTF8_Solid(fontset->id, str_utf8, sdl_col[cl]);
@@ -179,7 +199,7 @@ SDL_Rect font_draw_glyph(int x, int y, const char *str_utf8, uint8_t cl) {
y -= (TTF_FontHeight(fontset->id) - fontset->size) / 2;
r_dst = (SDL_Rect){x, y, w, h};
if (sdl_dib->format->BitsPerPixel == 8 && this.antialiase_on) {
if (sdl_dib->format->BitsPerPixel == 8 && antialias) {
sdl_drawAntiAlias_8bpp(x, y, fs, cl);
} else {
r_src = (SDL_Rect){0, 0, w, h};
+4 -1
View File
@@ -31,11 +31,14 @@
/* font の種類 */
#define FONTTYPEMAX 2
#define FONT_WEIGHT_NORMAL 4
#define FONT_WEIGHT_BOLD 7
extern void font_init(void);
extern void font_set_name_and_index(int type, const char *name, int index);
extern void font_set_antialias(boolean enable);
extern boolean font_get_antialias(void);
extern void font_select(int type, int size);
extern void font_select(int type, int size, int weight);
extern struct SDL_Surface *font_get_glyph(const char *str_utf8);
extern SDL_Rect font_draw_glyph(int x, int y, const char *str_utf8, uint8_t col);
+20 -6
View File
@@ -63,7 +63,7 @@ static void storeSaveName(GameResource *gr, int no, char *src) {
if (path) free(path);
}
boolean initGameResourceFromDir(GameResource *gr, DIR *dir, struct dirent *(*p_readdir)(DIR *)) {
boolean initGameResourceFromDir(GameResource *gr, DIR *dir, const char *savedir, struct dirent *(*p_readdir)(DIR *)) {
memset(gr, 0, sizeof(GameResource));
char *basename = NULL;
@@ -121,14 +121,28 @@ boolean initGameResourceFromDir(GameResource *gr, DIR *dir, struct dirent *(*p_r
found_xsleep = true;
}
}
if (basename && !found_xsleep) {
char *buf = malloc(strlen(basename) + 6);
if (basename && (savedir || !found_xsleep)) {
const char *dir = savedir ? savedir : "";
const char *sep = savedir ? "/" : "";
char *buf = malloc(strlen(dir) + strlen(sep) + strlen(basename) + 9);
#if defined(__ANDROID__) || defined(__EMSCRIPTEN__)
// Use lowercase 's[a-z].asd' in Android and Emscripten, for compatibility.
basename[strlen(basename) - 1] = 's';
int a = 'a';
#else
int a = basename[strlen(basename) - 1] == 'S' ? 'A' : 'a';
#endif
for (int i = 0; i < SAVE_MAXNUMBER; i++) {
sprintf(buf, "%s%c.asd", basename, a + i);
sprintf(buf, "%s%s%s%c.asd", dir, sep, basename, a + i);
storeSaveName(gr, i, buf);
}
#ifdef __EMSCRIPTEN__
basename[strlen(basename) - 1] = '\0';
sprintf(buf, "%s%s%s.msgskip", dir, sep, basename);
gr->msgskip = buf;
#else
free(buf);
#endif
} else {
for (int i = 0; i < SAVE_MAXNUMBER; i++) {
char buf[] = "asleep.asd";
@@ -220,7 +234,7 @@ static boolean initGameResourceFromFile(GameResource *gr, FILE *fp, const char *
return FALSE;
}
boolean initGameResource(GameResource *gr, const char *gr_fname) {
boolean initGameResource(GameResource *gr, const char *gr_fname, const char *savedir) {
FILE *fp = fopen(gr_fname, "r");
if (fp) {
boolean result = initGameResourceFromFile(gr, fp, gr_fname);
@@ -229,7 +243,7 @@ boolean initGameResource(GameResource *gr, const char *gr_fname) {
}
DIR *dir = opendir(".");
if (dir) {
boolean result = initGameResourceFromDir(gr, dir, readdir);
boolean result = initGameResourceFromDir(gr, dir, savedir, readdir);
closedir(dir);
return result;
}
+2 -2
View File
@@ -43,7 +43,7 @@ typedef struct {
const char *msgskip;
} GameResource;
boolean initGameResource(GameResource *gr, const char *gr_fname);
boolean initGameResourceFromDir(GameResource *gr, DIR *dir, struct dirent *(*p_readdir)(DIR *));
boolean initGameResource(GameResource *gr, const char *gr_fname, const char *savedir);
boolean initGameResourceFromDir(GameResource *gr, DIR *dir, const char *savedir, struct dirent *(*p_readdir)(DIR *));
#endif /* !__GAMERESOURCE_H__ */
+20 -3
View File
@@ -25,7 +25,7 @@
static void initGameResource_test(void) {
GameResource gr;
ASSERT_TRUE(initGameResource(&gr, "testdata/test.gr"));
ASSERT_TRUE(initGameResource(&gr, "testdata/test.gr", NULL));
ASSERT_EQUAL(gr.cnt[DRIFILE_SCO], 1);
ASSERT_STRCMP(gr.game_fname[DRIFILE_SCO][0], "fooSA.ALD");
@@ -96,7 +96,7 @@ static void initGameResourceFromDir_test(void) {
};
const char **dir = files;
GameResource gr;
ASSERT_TRUE(initGameResourceFromDir(&gr, (DIR *)&dir, mockReaddir));
ASSERT_TRUE(initGameResourceFromDir(&gr, (DIR *)&dir, NULL, mockReaddir));
ASSERT_EQUAL(gr.cnt[DRIFILE_SCO], 2);
ASSERT_STRCMP(gr.game_fname[DRIFILE_SCO][0], "FOOSA.ALD");
ASSERT_STRCMP(gr.game_fname[DRIFILE_SCO][1], "FOOSB.ALD");
@@ -120,6 +120,23 @@ static void initGameResourceFromDir_test(void) {
for (int i = 2; i < 10; i++)
ASSERT_NULL(gr.alk[i]);
}
{
const char *files[] = {
"foosa.ald",
NULL
};
const char **dir = files;
GameResource gr;
ASSERT_TRUE(initGameResourceFromDir(&gr, (DIR *)&dir, "~/save", mockReaddir));
ASSERT_EQUAL(gr.cnt[DRIFILE_SCO], 1);
ASSERT_STRCMP(gr.game_fname[DRIFILE_SCO][0], "foosa.ald");
for (int i = 0; i < 26; i++) {
char buf[32];
sprintf(buf, "/home/kichikuou/save/foos%c.asd", 'a' + i);
ASSERT_STRCMP(gr.save_fname[i], buf);
}
ASSERT_STRCMP(gr.save_path, "/home/kichikuou/save");
}
{
const char *files[] = {
"ADISK.ALD",
@@ -128,7 +145,7 @@ static void initGameResourceFromDir_test(void) {
};
const char **dir = files;
GameResource gr;
ASSERT_TRUE(initGameResourceFromDir(&gr, (DIR *)&dir, mockReaddir));
ASSERT_TRUE(initGameResourceFromDir(&gr, (DIR *)&dir, NULL, mockReaddir));
ASSERT_EQUAL(gr.cnt[DRIFILE_SCO], 1);
ASSERT_STRCMP(gr.game_fname[DRIFILE_SCO][0], "ADISK.ALD");
for (int i = 0; i < 26; i++) {
+4 -4
View File
@@ -28,10 +28,10 @@
#include <SDL_rect.h>
typedef struct {
uint8_t red[256];
uint8_t green[256];
uint8_t blue[256];
} Palette256;
uint8_t r;
uint8_t g;
uint8_t b;
} Color;
typedef struct {
uint8_t r,g,b;
+15 -9
View File
@@ -27,23 +27,27 @@
#define GT_TOSHIN2 "闘神都市Ⅱ for Win95 "
#define GT_RANCE4 "Rance4 -教団の遺産- For Win95 "
#define GT_RANCE4_V2 "RanceⅣ -教団の遺産- for Windows "
#define GT_RANCE3 "Rance3"
#define GT_RANCE3_ENG "Rance3"
#define GT_RANCE4_ENG "Rance4 -Legacy of the Sect- For Win95 "
/* defined by cmdy.c */
extern boolean Y3waitFlags;
enum gameId game_id;
bool daiakuji_cx_hack;
void enable_hack_by_gameid(const char *gameid) {
if (!strcmp(gameid, "toushin2"))
nact->game = GAME_TT2;
game_id = GAME_TT2;
else if (!strcmp(gameid, "rance3"))
game_id = GAME_RANCE3;
else if (!strcmp(gameid, "rance3_eng"))
nact->game = GAME_RANCE3_ENG;
game_id = GAME_RANCE3_ENG;
else if (!strcmp(gameid, "rance4_eng"))
nact->game = GAME_RANCE4_ENG;
game_id = GAME_RANCE4_ENG;
else if (!strcmp(gameid, "rance4_v2"))
nact->game = GAME_RANCE4_V2;
game_id = GAME_RANCE4_V2;
else
sys_error("Unknown game id \"%s\"", gameid);
}
@@ -52,15 +56,17 @@ void enable_hack_by_title(const char *title_utf8) {
if (!strcmp(title_utf8, GT_RANCE4))
Y3waitFlags = KEYWAIT_NONCANCELABLE;
if (nact->game != GAME_UNKNOWN)
if (game_id != GAME_UNKNOWN)
return;
if (!strcmp(title_utf8, GT_TOSHIN2))
nact->game = GAME_TT2;
game_id = GAME_TT2;
else if (!strcmp(title_utf8, GT_RANCE4_V2))
nact->game = GAME_RANCE4_V2;
game_id = GAME_RANCE4_V2;
else if (!strcmp(title_utf8, GT_RANCE3))
game_id = GAME_RANCE3;
else if (!strcmp(title_utf8, GT_RANCE3_ENG))
nact->game = GAME_RANCE3_ENG;
game_id = GAME_RANCE3_ENG;
else if (!strcmp(title_utf8, GT_RANCE4_ENG))
nact->game = GAME_RANCE4_ENG;
game_id = GAME_RANCE4_ENG;
}
+3
View File
@@ -25,11 +25,14 @@
enum gameId {
GAME_UNKNOWN = 0,
GAME_TT2,
GAME_RANCE3,
GAME_RANCE3_ENG,
GAME_RANCE4_ENG,
GAME_RANCE4_V2,
};
extern enum gameId game_id;
void enable_hack_by_gameid(const char *gameid);
void enable_hack_by_title(const char *game_title_utf8);
+3 -2
View File
@@ -59,8 +59,9 @@ extern void menu_setSkipState(boolean enabled, boolean activated);
#ifdef _WIN32
struct SDL_SysWMmsg;
extern void win_menu_init(void);
extern void win_menu_onsyswmevent(struct SDL_SysWMmsg* msg);
void win_menu_init(void);
void win_menu_onSysWMEvent(struct SDL_SysWMmsg* msg);
void win_menu_onMouseMotion(int x, int y);
#endif
#endif /* !__MENULL */
+1 -3
View File
@@ -20,9 +20,7 @@
*/
/* $Id: menu_callback.c,v 1.11 2003/04/25 17:23:55 chikama Exp $ */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "config.h"
#include "portab.h"
#include "menu.h"
+1 -3
View File
@@ -1,6 +1,4 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
+4 -4
View File
@@ -64,9 +64,8 @@ static void msgget_at_a();
void msg_init() {
/* メッセージフォントの大きさ */
msg.MsgFontSize = 16;
msg.MsgFontBoldSize = 0;
msg.MsgFont = FONT_GOTHIC;
msg.MsgFontSize = 16;
msg.MsgFont = FONT_GOTHIC;
/* 各種色 */
msg.MsgFontColor = 255;
@@ -141,7 +140,8 @@ void msg_putMessage(const char *m) {
// fprintf(stdout, "x=%d, y = %d, msg=%s\n", msgcur.x,msgcur.y,msg);
if (!msg.mg_dspMsg) return;
ags_setFont(msg.MsgFont, msg.MsgFontSize);
ags_setFontWithWeight(msg.MsgFont, msg.MsgFontSize, nact->ags.font_weight);
switch(msgDecorateType) {
case 0:
default:
-1
View File
@@ -44,7 +44,6 @@ extern void msg_mg6_command(int cmd);
struct __message {
/* メッセージフォントの大きさ */
int MsgFontSize;
int MsgFontBoldSize;
int MsgFont;
/* 各種色 */
+1 -1
View File
@@ -90,7 +90,7 @@ int midi_init(mididevice_t *midi) {
return ret;
}
void midi_set_devicename(char *name) {
void midi_set_devicename(const char *name) {
if (dev) free(dev);
if (0 == strcmp("none", name)) dev = NULL;
else dev = strdup(name);
+1 -1
View File
@@ -52,7 +52,7 @@ struct mididevice {
};
extern int midi_init(mididevice_t *);
extern void midi_set_devicename(char *);
extern void midi_set_devicename(const char *);
extern void midi_set_output_device(int mode);
#endif /* __MIDI_H__ */
+1 -3
View File
@@ -54,9 +54,7 @@ static unsigned long mt[N]; /* the array for the state vector */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
/* initializing the array with a NONZERO seed */
void
sgenrand(seed)
unsigned long seed;
void sgenrand(unsigned long seed)
{
/* setting initial seeds to mt[N] using */
/* the generator Line 25 of Table 1 in */
+13 -9
View File
@@ -30,11 +30,18 @@
#include "music_cdrom.h"
#include "cdrom.h"
static char *dev = CDROM_DEVICE;
#ifdef __EMSCRIPTEN__
extern cdromdevice_t cdrom_emscripten;
#define NATIVE_CD_DEVICE &cdrom_emscripten
#else
extern cdromdevice_t cdrom_mp3;
#define NATIVE_CD_DEVICE &cdrom_mp3
#endif
void muscd_set_devicename(char *name) {
if (0 == strcmp("none", name)) dev = NULL;
else dev = strdup(name);
static char *playlist = DEFAULT_PLAYLIST_PATH;
void muscd_set_playlist(const char *name) {
playlist = strdup(name);
}
int muscd_init(void) {
@@ -42,12 +49,9 @@ int muscd_init(void) {
if (ald_get_maxno(DRIFILE_BGM) > 0) {
prv.cddev = &cdrom_bgm;
} else {
prv.cddev = cd_init(dev);
if (!prv.cddev) {
return NG;
}
prv.cddev = NATIVE_CD_DEVICE;
}
prv.cddev->init(dev);
prv.cddev->init(playlist);
prv.cd_current_track = 0;
return OK;
}
+1 -1
View File
@@ -27,7 +27,7 @@
#include "portab.h"
#include "ald_manager.h"
void muscd_set_devicename(char *);
void muscd_set_playlist(const char *);
int muscd_init(void);
int muscd_init_bgm(DRIFILETYPE type, int base_no);
int muscd_exit(void);
-3
View File
@@ -110,9 +110,6 @@ typedef struct {
int patch_emen; /* see patch_emen command */
int patch_g0; /* see patch g0 command */
// For game-specific hacks.
enum gameId game;
/* ain 関連 */
S39AIN ain;
-40
View File
@@ -1,40 +0,0 @@
/*
* pcm.dummy.c Dummy PCM implementation
*
* Copyright (C) 2019 <KichikuouChrome@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "portab.h"
#include "music_pcm.h"
int muspcm_init(int audio_buffer_size) { return NG; }
int muspcm_exit(void) { return NG; }
int muspcm_reset(void) { return NG; }
int muspcm_load_no(int slot, int no) { return NG; }
int muspcm_load_mixlr(int slot, int noL, int noR) { return NG; }
int muspcm_load_data(int slot, uint8_t *buf, uint32_t len) { return NG; }
int muspcm_unload(int slot) { return NG; }
int muspcm_start(int slot, int loop) { return NG; }
int muspcm_stop(int slot) { return NG; }
int muspcm_fadeout(int slot, int msec) { return NG; }
int muspcm_pause(int slot) { return NG; }
int muspcm_unpause(int slot) { return NG; }
int muspcm_getpos(int slot) { return NG; }
int muspcm_setvol(int dev, int slot, int lv) { return NG; }
int muspcm_getwavelen(int slot) { return NG; }
boolean muspcm_isplaying(int slot) { return FALSE; }
int muspcm_waitend(int slot) { return NG; }
+8 -11
View File
@@ -44,7 +44,6 @@
* static methods
*/
static pms_header *extract_header(uint8_t *b);
static void getpal(Palette256 *pal, uint8_t *b);
static void extract_8bit(pms_header *pms, uint8_t *pic, uint8_t *b);
static void extract_16bit(pms_header *pms, uint16_t *pic, uint8_t *b);
@@ -75,17 +74,16 @@ static pms_header *extract_header(uint8_t *b) {
/*
* Get palette from raw data
* pal: palette to be stored
* b : raw data (pointer to palette)
*/
static void getpal(Palette256 *pal, uint8_t *b) {
int i;
for (i = 0; i < 256; i++) {
pal->red[i] = *b++;
pal->green[i] = *b++;
pal->blue[i] = *b++;
static Color *getpal(uint8_t *b) {
Color *pal = malloc(sizeof(Color) * 256);
for (int i = 0; i < 256; i++) {
pal[i].r = *b++;
pal[i].g = *b++;
pal[i].b = *b++;
}
return pal;
}
/*
@@ -227,8 +225,7 @@ cgdata *pms256_extract(uint8_t *data) {
cgdata *cg = calloc(1, sizeof(cgdata));
pms_header *pms = extract_header(data);
cg->pal = malloc(sizeof(Palette256));
getpal(cg->pal, data + pms->pmsPp);
cg->pal = getpal(data + pms->pmsPp);
/* +10: margin for broken cg */
cg->pic = malloc(sizeof(uint8_t) * ((pms->pmsXW + 10) * (pms->pmsYW + 10)));
+28 -39
View File
@@ -28,12 +28,6 @@
#include <string.h>
#include <ctype.h>
#include <limits.h>
#ifdef _WIN32
#include <windows.h>
#include "win/resources.h"
#undef min
#undef max
#endif
#include "portab.h"
#include "profile.h"
@@ -41,7 +35,6 @@
#define RC_NAME ".xsys35rc"
#define RC_LINE_CHARS_MAX 256
#define REGKEY_PROFILE XSYSTEM35_REGKEY "\\profile"
struct profile_kv {
char *name;
@@ -138,39 +131,14 @@ static int load_rc_file(const char *profile_path)
return 0;
}
#ifdef _WIN32
static void load_profile_from_registry(HKEY rootKey)
{
HKEY hKey;
LSTATUS err = RegOpenKeyEx(rootKey, REGKEY_PROFILE, 0, KEY_QUERY_VALUE, &hKey);
if (err != ERROR_SUCCESS)
return;
for (DWORD index = 0;; index++) {
char name[64];
BYTE value[RC_LINE_CHARS_MAX];
DWORD name_size = sizeof(name);
DWORD value_size = sizeof(value);
DWORD type;
err = RegEnumValue(hKey, index, name, &name_size, NULL, &type, value, &value_size);
if (err != ERROR_SUCCESS)
break;
if (type != REG_SZ)
continue;
insert_profile(name, value);
}
}
#endif // _WIN32
int load_profile(void)
{
char *home_dir = getenv("HOME");
#ifdef _WIN32
load_profile_from_registry(HKEY_LOCAL_MACHINE);
load_profile_from_registry(HKEY_CURRENT_USER);
#endif // _WIN32
char *home_dir;
if ((home_dir = getenv("HOME"))) {
if (!home_dir)
home_dir = getenv("USERPROFILE");
#endif
if (home_dir) {
char profile_path[PATH_MAX];
sprintf(profile_path, "%s/%s", home_dir, RC_NAME);
load_rc_file(profile_path);
@@ -178,11 +146,32 @@ int load_profile(void)
return load_rc_file(RC_NAME);
}
char *get_profile(const char *name)
{
const char *get_profile(const char *name) {
struct profile_kv *kv;
if (!(kv = check_profile(name)))
return NULL;
return kv->value;
}
bool get_boolean_profile(const char *name, bool *out) {
const char *value = get_profile(name);
if (!value)
return false;
const char *yes_values[] = {"yes", "true", "on", "1", NULL};
const char *no_values[] = {"no", "false", "off", "0", NULL};
for (int i = 0; yes_values[i]; i++) {
if (!strcasecmp(value, yes_values[i])) {
*out = true;
return true;
}
}
for (int i = 0; no_values[i]; i++) {
if (!strcasecmp(value, no_values[i])) {
*out = false;
return true;
}
}
WARNING("invalid profile value for %s: \"%s\"\n", name, value);
return false;
}
+4 -1
View File
@@ -25,7 +25,10 @@
#ifndef __PROFILE_H__
#define __PROFILE_H__
#include <stdbool.h>
int load_profile(void);
char *get_profile(const char *name);
const char *get_profile(const char *name);
bool get_boolean_profile(const char *name, bool *out);
#endif /* __PROFILE_H__ */
+1 -1
View File
@@ -55,7 +55,7 @@ extern void sdl_updateAll(MyRectangle *view_rect);
extern void sdl_updateScreen(void);
/* パレット関係 */
extern void sdl_setPalette(Palette256 *pal, int first, int count);
extern void sdl_setPalette(Color *pal, int first, int count);
/* 描画関係 */
extern void sdl_drawRectangle(int x, int y, int w, int h, uint8_t c);
+9 -11
View File
@@ -81,7 +81,8 @@ void sdl_sleep(int msec) {
#ifdef __EMSCRIPTEN__
EM_JS(void, wait_vsync, (void), {
Asyncify.handleSleep(function(wakeUp) {
// We need a `return` here for JSPI support (ASYNCIFY=2).
return Asyncify.handleSleep(function(wakeUp) {
window.requestAnimationFrame(function() {
wakeUp();
});
@@ -118,11 +119,11 @@ void sdl_updateAll(MyRectangle *view_rect) {
}
/* Color の複数個指定 */
void sdl_setPalette(Palette256 *pal, int first, int count) {
void sdl_setPalette(Color *pal, int first, int count) {
for (int i = 0; i < count; i++) {
sdl_col[first + i].r = pal->red [first + i];
sdl_col[first + i].g = pal->green[first + i];
sdl_col[first + i].b = pal->blue [first + i];
sdl_col[first + i].r = pal[first + i].r;
sdl_col[first + i].g = pal[first + i].g;
sdl_col[first + i].b = pal[first + i].b;
}
if (sdl_dib->format->BitsPerPixel == 8)
SDL_SetPaletteColors(sdl_dib->format->palette, &sdl_col[first], first, count);
@@ -227,13 +228,10 @@ void sdl_drawImage8_fromData(cgdata *cg, int dx, int dy, int sprite_color) {
if (sdl_dib->format->BitsPerPixel > 8 && cg->pal) {
SDL_Color *c = s->format->palette->colors;
uint8_t *r = cg->pal->red;
uint8_t *g = cg->pal->green;
uint8_t *b = cg->pal->blue;
for (int i = 0; i < 256; i++) {
c->r = *(r++);
c->g = *(g++);
c->b = *(b++);
c->r = cg->pal[i].r;
c->g = cg->pal[i].g;
c->b = cg->pal[i].b;
c++;
}
} else {
+6 -2
View File
@@ -40,6 +40,7 @@
#include "menu.h"
#include "input.h"
#include "msgskip.h"
#include "hacks.h"
static void sdl_getEvent(void);
static void keyEventProsess(SDL_KeyboardEvent *e, boolean pressed);
@@ -259,7 +260,7 @@ void sdl_handle_event(SDL_Event *e) {
break;
#ifdef _WIN32
case SDL_SYSWMEVENT:
win_menu_onsyswmevent(e->syswm.msg);
win_menu_onSysWMEvent(e->syswm.msg);
break;
#endif
case SDL_APP_DIDENTERFOREGROUND:
@@ -281,6 +282,9 @@ void sdl_handle_event(SDL_Event *e) {
break;
case SDL_MOUSEMOTION:
sdl_setCursorInternalLocation(e->motion.x, e->motion.y);
#ifdef _WIN32
win_menu_onMouseMotion(e->motion.x, e->motion.y);
#endif
break;
case SDL_MOUSEWHEEL:
@@ -445,7 +449,7 @@ static void sdl_getEvent(void) {
cmd_count_of_prev_input = nact->cmd_count;
} else if (nact->cmd_count != cmd_count_of_prev_input) {
nact->wait_vsync = TRUE;
if (nact->game == GAME_RANCE4_V2)
if (game_id == GAME_RANCE4_V2)
rance4v2_hack();
}
}
+8 -7
View File
@@ -41,7 +41,6 @@ static void makeDIB(int width, int height, int depth);
struct sdl_private_data *sdl_videodev;
static int joy_device_index = -1;
static boolean integer_scaling = FALSE;
static SDL_Joystick *js;
@@ -137,6 +136,10 @@ static void window_init(const char *render_driver) {
// indirectly, which does not work with ASYNCIFY_IGNORE_INDIRECT=1. For
// details, see https://github.com/emscripten-core/emscripten/issues/10746.
SDL_SetHint(SDL_HINT_EMSCRIPTEN_ASYNCIFY, "0");
const char *title = NULL; // Don't let SDL change document.title.
#else
const char title[] = "XSystem35 Version " VERSION;
#endif
#ifdef __ANDROID__
@@ -146,13 +149,11 @@ static void window_init(const char *render_driver) {
#else
Uint32 flags = SDL_WINDOW_RESIZABLE;
#endif
sdl_window = SDL_CreateWindow("XSystem35 Version "VERSION,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SYS35_DEFAULT_WIDTH, SYS35_DEFAULT_HEIGHT,
flags);
sdl_window = SDL_CreateWindow(
title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SYS35_DEFAULT_WIDTH, SYS35_DEFAULT_HEIGHT, flags);
sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
SDL_RenderSetIntegerScale(sdl_renderer, integer_scaling);
}
static void makeDIB(int width, int height, int depth) {
@@ -274,7 +275,7 @@ void sdl_setJoyDeviceIndex(int index) {
}
void sdl_setIntegerScaling(boolean enable) {
integer_scaling = enable;
SDL_RenderSetIntegerScale(sdl_renderer, enable);
}
#ifdef __EMSCRIPTEN__
+1 -1
View File
@@ -301,7 +301,7 @@ static void init_selwindow() {
NOTICE("frameType is Default");
break;
}
ags_setFont(FONT_GOTHIC, sel.MsgFontSize);
ags_setFontWithWeight(FONT_GOTHIC, sel.MsgFontSize, nact->ags.font_weight);
for (i = 0; i < regnum; i++) {
DEBUG_MESSAGE("%d:%s\n", i +1, elm[i]);
ags_drawString(r.x +2, r.y + i * (sel.MsgFontSize +2) +1, elm[i], sel.MsgFontColor);
+1 -1
View File
@@ -53,7 +53,7 @@ struct _selection {
int FrameCgNoBot;
int Framedot;
/* メッセージフォントの大きさ */
/* メッセージフォントの大きさ */
int MsgFontSize;
/* 各種色 */
+7 -8
View File
@@ -42,7 +42,6 @@
* static methods
*/
static vsp_header *extract_header(uint8_t *b);
static void getpal(Palette256 *pal, uint8_t *b);
static void extract(vsp_header *vsp, uint8_t *pic, uint8_t *b);
/*
@@ -66,15 +65,16 @@ static vsp_header *extract_header(uint8_t *b) {
/*
* Get palette from raw data
* pal: palette to be stored
* b : raw data (pointer to palette)
*/
static void getpal(Palette256 *pal, uint8_t *b) {
static Color *getpal(uint8_t *b) {
Color *pal = malloc(sizeof(Color) * 256);
for (int i = 0; i < 16; i++) {
pal->blue[i] = b[i * 3 + 0] * 17;
pal->red[i] = b[i * 3 + 1] * 17;
pal->green[i] = b[i * 3 + 2] * 17;
pal[i].b = b[i * 3 + 0] * 17;
pal[i].r = b[i * 3 + 1] * 17;
pal[i].g = b[i * 3 + 2] * 17;
}
return pal;
}
/*
@@ -196,8 +196,7 @@ cgdata *vsp_extract(uint8_t *data) {
cgdata *cg = calloc(1, sizeof(cgdata));
vsp_header *vsp = extract_header(data);
cg->pal = malloc(sizeof(Palette256));
getpal(cg->pal, data + vsp->vspPp);
cg->pal = getpal(data + vsp->vspPp);
/* +10: margin for broken cg */
cg->pic = malloc(sizeof(uint8_t) * ((vsp->vspXW * 8 + 10) * (vsp->vspYW + 10)));
-46
View File
@@ -17,7 +17,6 @@
*
*/
#include <windows.h>
#include <shlobj.h>
#undef min
#undef max
#include <SDL_syswm.h>
@@ -25,8 +24,6 @@
#include "sdl_private.h"
#include "resources.h"
#define REGVAL_RECENT_FOLDER "RecentFolder"
static HWND get_hwnd(SDL_Window *window) {
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
@@ -34,49 +31,6 @@ static HWND get_hwnd(SDL_Window *window) {
return info.info.win.window;
}
static int CALLBACK select_game_callback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) {
if (uMsg == BFFM_INITIALIZED)
SendMessage(hwnd, BFFM_SETSELECTION, (WPARAM)TRUE, lpData);
return 0;
}
boolean current_folder_has_ald(void) {
WIN32_FIND_DATA find_data;
HANDLE hFind = FindFirstFile("*.ALD", &find_data);
if (hFind == INVALID_HANDLE_VALUE)
return FALSE;
FindClose(hFind);
return TRUE;
}
boolean select_game_folder(void) {
char title[256];
LoadString(GetModuleHandle(NULL), IDS_CHOOSE_GAME_FOLDER, title, sizeof(title));
char path[MAX_PATH] = "";
DWORD value_size = sizeof(path);
RegGetValue(HKEY_CURRENT_USER, XSYSTEM35_REGKEY, REGVAL_RECENT_FOLDER,
RRF_RT_REG_SZ, NULL, path, &value_size);
BROWSEINFO bi = {
.lpszTitle = title,
.ulFlags = BIF_RETURNONLYFSDIRS,
.lpfn = &select_game_callback,
.lParam = (LPARAM)path,
};
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
if (!pidl)
return FALSE;
SHGetPathFromIDList(pidl, path);
CoTaskMemFree(pidl);
if (!SetCurrentDirectory(path))
return FALSE;
RegSetKeyValue(HKEY_CURRENT_USER, XSYSTEM35_REGKEY, REGVAL_RECENT_FOLDER,
REG_SZ, path, strlen(path) + 1);
return TRUE;
}
static INT_PTR CALLBACK text_dialog_proc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
static INPUTSTRING_PARAM *p;
-2
View File
@@ -24,8 +24,6 @@
struct inputstring_param;
struct inputnum_param;
boolean current_folder_has_ald(void);
boolean select_game_folder(void);
boolean input_string(struct inputstring_param *p);
boolean input_number(struct inputnum_param *p);
+27 -14
View File
@@ -29,6 +29,8 @@
#include "resources.h"
#include "msgskip.h"
static HMENU hmenu;
static HWND get_hwnd(SDL_Window *window) {
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
@@ -59,29 +61,27 @@ static void saveScreenshot(void) {
}
}
static void toggle_mouse_warp_mode(void) {
HWND hwnd = get_hwnd(sdl_window);
HMENU hmenu = GetMenu(hwnd);
static bool toggle_menu_item(UINT id, bool *checked_out) {
MENUITEMINFO menuitem = {
.cbSize = sizeof(MENUITEMINFO),
.fMask = MIIM_STATE,
};
if (!GetMenuItemInfo(hmenu, ID_OPTION_MOUSE_MOVE, false, &menuitem))
return;
if (!GetMenuItemInfo(hmenu, id, false, &menuitem))
return false;
if (menuitem.fState & MFS_CHECKED) {
nact->ags.mouse_warp_enabled = false;
CheckMenuItem(hmenu, ID_OPTION_MOUSE_MOVE, MF_BYCOMMAND | MFS_UNCHECKED);
CheckMenuItem(hmenu, id, MF_BYCOMMAND | MFS_UNCHECKED);
*checked_out = false;
} else {
nact->ags.mouse_warp_enabled = true;
CheckMenuItem(hmenu, ID_OPTION_MOUSE_MOVE, MF_BYCOMMAND | MFS_CHECKED);
CheckMenuItem(hmenu, id, MF_BYCOMMAND | MFS_CHECKED);
*checked_out = true;
}
return true;
}
void win_menu_init(void) {
HINSTANCE hinst = (HINSTANCE)GetModuleHandle(NULL);
HMENU hmenu = LoadMenu(hinst, MAKEINTRESOURCE(IDR_MENU1));
hmenu = LoadMenu(hinst, MAKEINTRESOURCE(IDR_MENU1));
SetMenu(get_hwnd(sdl_window), hmenu);
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
// Let SDL recalc the window size, taking menu height into account.
@@ -89,7 +89,8 @@ void win_menu_init(void) {
CheckMenuItem(hmenu, ID_OPTION_MOUSE_MOVE, MF_BYCOMMAND | MFS_CHECKED);
}
void win_menu_onsyswmevent(SDL_SysWMmsg* msg) {
void win_menu_onSysWMEvent(SDL_SysWMmsg* msg) {
bool checked;
switch (msg->msg.win.msg) {
case WM_COMMAND:
switch (msg->msg.win.wParam) {
@@ -104,12 +105,19 @@ void win_menu_onsyswmevent(SDL_SysWMmsg* msg) {
break;
case ID_SCREEN_WINDOW:
sdl_setFullscreen(FALSE);
SetMenu(get_hwnd(sdl_window), hmenu);
break;
case ID_SCREEN_FULL:
sdl_setFullscreen(TRUE);
SetMenu(get_hwnd(sdl_window), NULL);
break;
case ID_SCREEN_INTEGER_SCALING:
if (toggle_menu_item(ID_SCREEN_INTEGER_SCALING, &checked))
sdl_setIntegerScaling(checked);
break;
case ID_OPTION_MOUSE_MOVE:
toggle_mouse_warp_mode();
if (toggle_menu_item(ID_OPTION_MOUSE_MOVE, &checked))
nact->ags.mouse_warp_enabled = checked;
break;
case ID_MSGSKIP:
msgskip_activate(!msgskip_isActivated());
@@ -119,9 +127,14 @@ void win_menu_onsyswmevent(SDL_SysWMmsg* msg) {
}
}
void win_menu_onMouseMotion(int x, int y) {
if (!sdl_isFullscreen())
return;
SetMenu(get_hwnd(sdl_window), y > 0 ? NULL : hmenu);
}
void menu_setSkipState(boolean enabled, boolean activated) {
HWND hwnd = get_hwnd(sdl_window);
HMENU hmenu = GetMenu(hwnd);
EnableMenuItem(hmenu, ID_MSGSKIP, enabled ? MF_ENABLED : MF_GRAYED);
+30
View File
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2024 <KichikuouChrome@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <windows.h>
#include <SDL_rwops.h>
#include "resources.h"
SDL_RWops *open_resource(const char* name, const char* type) {
HINSTANCE hInst = GetModuleHandle(NULL);
HRSRC hRes = FindResource(hInst, name, type);
if (!hRes) return NULL;
HGLOBAL hGlobal = LoadResource(hInst, hRes);
if (!hGlobal) return NULL;
return SDL_RWFromConstMem(LockResource(hGlobal), SizeofResource(hInst, hRes));
}
+11 -9
View File
@@ -19,8 +19,6 @@
#ifndef __RESOURCES_H__
#define __RESOURCES_H__
#define XSYSTEM35_REGKEY "Software\\Kichikuou\\xsystem35"
#define IDR_MENU1 101
#define IDD_DIALOG1 103
#define IDC_TEXT 104
@@ -28,12 +26,16 @@
#define IDS_CHOOSE_GAME_FOLDER 1001
#define ID_SCREENSHOT 40001
#define ID_RESTART 40002
#define ID_EXIT 40003
#define ID_SCREEN_WINDOW 40011
#define ID_SCREEN_FULL 40012
#define ID_OPTION_MOUSE_MOVE 40021
#define ID_MSGSKIP 40030
#define ID_SCREENSHOT 40001
#define ID_RESTART 40002
#define ID_EXIT 40003
#define ID_SCREEN_WINDOW 40011
#define ID_SCREEN_FULL 40012
#define ID_SCREEN_INTEGER_SCALING 40013
#define ID_OPTION_MOUSE_MOVE 40021
#define ID_MSGSKIP 40030
struct SDL_RWops;
struct SDL_RWops *open_resource(const char* name, const char* type);
#endif /* __RESOURCES_H__ */
+10
View File
@@ -4,6 +4,14 @@
100 ICON DISCARDABLE "xsystem35.ico"
// Note for game translators:
// Rather than replacing these, use the "ttfont_gothic" and "ttfont_mincho"
// options in .xsys35rc. That will allow your translated game run on other
// other platforms, such as Android and Web.
MTLc3m.ttf FONTS DISCARDABLE "../../fonts/MTLc3m.ttf"
mincho.otf FONTS DISCARDABLE "../../fonts/mincho.otf"
////////////////////////////////////////////////////////////////////////
LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
@@ -19,6 +27,7 @@ IDR_MENU1 MENU DISCARDABLE
{
MENUITEM "Window", ID_SCREEN_WINDOW
MENUITEM "Fullscreen", ID_SCREEN_FULL
MENUITEM "Integer Scaling", ID_SCREEN_INTEGER_SCALING
}
POPUP "Option"
{
@@ -57,6 +66,7 @@ IDR_MENU1 MENU DISCARDABLE
{
MENUITEM "ウィンドウ", ID_SCREEN_WINDOW
MENUITEM "フルスクリーン", ID_SCREEN_FULL
MENUITEM "整数倍スケーリング", ID_SCREEN_INTEGER_SCALING
}
POPUP "オプション"
{
+54 -38
View File
@@ -80,7 +80,7 @@ static void sys35_remove();
static void sys35_ParseOption(int *argc, char **argv);
static void check_profile();
static char *render_driver = NULL;
static const char *render_driver = NULL;
/* for debugging */
static int debuglv = DEBUGLEVEL;
@@ -93,11 +93,13 @@ enum {
static int audio_buffer_size = 0;
/* font name from rcfile */
static char *fontname_tt[FONTTYPEMAX] = {DEFAULT_GOTHIC_TTF, DEFAULT_MINCHO_TTF};
static const char *fontname_tt[FONTTYPEMAX] = {DEFAULT_GOTHIC_TTF, DEFAULT_MINCHO_TTF};
static char fontface[FONTTYPEMAX];
static const char *savedir;
static boolean font_noantialias;
static bool enable_zb = false;
static bool integer_scaling = false;
/* fullscreen on from command line */
static boolean fs_on;
@@ -111,9 +113,10 @@ static void sys35_usage(boolean verbose) {
puts("OPTIONS");
puts(" -gamefile file : set game resource file to 'file'");
puts(" -game game : enable game-specific hacks");
puts(" -savedir dir : directory to save game state files");
puts(" -saveformat fmt : save file format. 'xsystem35', 'system36' or 'system39' (default)");
puts(" -renderer name : set rendering driver name to 'name'");
puts(" -devcd device : set cdrom device name to 'device'");
puts(" -playlist file : load CD playlist from 'file'");
puts(" -devmidi device : set midi device name to 'device'");
puts(" -M? : select output midi methos");
@@ -137,12 +140,15 @@ static void sys35_usage(boolean verbose) {
puts(" -ttfont_gothic : set TrueType font for mincho");
#ifdef DEBUG
puts(" -debuglv # : debug level");
puts(" -debuglv # : logging level");
puts(" : 1: warings");
puts(" : 2: unimplemented commands");
puts(" : 5: command trace");
puts(" : 6: message trace");
#endif
#endif
#ifdef ENABLE_DEBUGGER
puts(" -debug : start with debugger");
#endif
puts(" -noantialias : never use antialiased string");
puts(" -fullscreen : start with fullscreen");
puts(" -integerscale : use integer scaling when resizing");
@@ -210,7 +216,7 @@ static void sys35_init() {
v_init();
ags_init(render_driver);
ags_init(render_driver, enable_zb);
for (i = 0; i < FONTTYPEMAX; i++)
font_set_name_and_index(i, fontname_tt[i], fontface[i]);
@@ -254,6 +260,13 @@ static void sys35_ParseOption(int *argc, char **argv) {
}
}
for (i = 1; i < *argc; i++) {
if (0 == strcmp(argv[i], "-savedir")) {
if (i == *argc - 1) {
fprintf(stderr, "xsystem35: The -savedir option requires directory name\n\n");
sys35_usage(FALSE);
}
savedir = argv[++i];
}
if (0 == strcmp(argv[i], "-gamefile")) {
if (i == *argc - 1) {
fprintf(stderr, "xsystem35: The -gamefile option requires file value\n\n");
@@ -271,9 +284,9 @@ static void sys35_ParseOption(int *argc, char **argv) {
debugger_mode = DEBUGGER_DAP;
} else if (0 == strcmp(argv[i], "-renderer")) {
render_driver = argv[i + 1];
} else if (0 == strcmp(argv[i], "-devcd")) {
} else if (0 == strcmp(argv[i], "-playlist") || 0 == strcmp(argv[i], "-devcd")) {
if (argv[i + 1] != NULL) {
muscd_set_devicename(argv[i + 1]);
muscd_set_playlist(argv[i + 1]);
}
} else if (0 == strcmp(argv[i], "-devmidi")) {
if (argv[i + 1] != NULL) {
@@ -293,6 +306,8 @@ static void sys35_ParseOption(int *argc, char **argv) {
fs_on = TRUE;
} else if (0 == strcmp(argv[i], "-noantialias")) {
font_noantialias = TRUE;
} else if (0 == strcmp(argv[i], "-enable_zb")) {
enable_zb = TRUE;
} else if (0 == strcmp(argv[i], "-ttfont_gothic")) {
if (argv[i + 1] != NULL) {
fontname_tt[FONT_GOTHIC] = argv[i + 1];
@@ -311,7 +326,7 @@ static void sys35_ParseOption(int *argc, char **argv) {
puts(VERSION);
exit(0);
} else if (0 == strcmp(argv[i], "-integerscale")) {
sdl_setIntegerScaling(TRUE);
integer_scaling = true;
} else if (0 == strcmp(argv[i], "-game")) {
if (argv[i + 1] != NULL) {
enable_hack_by_gameid(argv[i + 1]);
@@ -325,8 +340,12 @@ static void sys35_ParseOption(int *argc, char **argv) {
}
static void check_profile() {
char *param;
const char *param;
param = get_profile("savedir");
if (param) {
savedir = param;
}
/* ゴシックフォント(TT)の設定 */
param = get_profile("ttfont_gothic");
if (param) {
@@ -348,12 +367,14 @@ static void check_profile() {
fontface[FONT_MINCHO] = *param - '0';
}
/* Font antialiasing */
param = get_profile("antialias");
if (param) {
if (0 == strcmp(param, "No")) {
font_noantialias = TRUE;
}
bool antialias;
if (get_boolean_profile("antialias", &antialias)) {
font_noantialias = !antialias;
}
/* Enable ZB command (font weight) */
get_boolean_profile("enable_zb", &enable_zb);
/* Audio buffer size */
param = get_profile("audio_buffer_size");
if (param) {
@@ -366,11 +387,14 @@ static void check_profile() {
render_driver = param;
}
/* CD-ROM device name の設定 */
param = get_profile("cdrom_device");
/* CD-ROM playlist */
param = get_profile("playlist");
if (!param)
param = get_profile("cdrom_device"); // For backwards compatibility
if (param) {
muscd_set_devicename(param);
muscd_set_playlist(param);
}
/* joystick device name の設定 */
param = get_profile("joy_device");
if (param) {
@@ -391,19 +415,11 @@ static void check_profile() {
midi_set_output_device(*param | subdev);
}
/* disable image cursor */
param = get_profile("no_imagecursor");
if (param) {
if (0 == strcmp(param, "Yes")) {
nact->ags.noimagecursor = TRUE;
}
}
get_boolean_profile("no_imagecursor", &nact->ags.noimagecursor);
/* enable integer scaling */
param = get_profile("integerscale");
if (param) {
if (0 == strcmp(param, "Yes")) {
sdl_setIntegerScaling(TRUE);
}
}
get_boolean_profile("integerscale", &integer_scaling);
/* enable game-specific hacks */
param = get_profile("game");
if (param) {
@@ -476,18 +492,12 @@ int main(int argc, char **argv) {
if (strcmp(argv[1], "-gamedir") == 0)
chdir(argv[2]);
#endif
#ifdef _WIN32
if (argc == 1 && !current_folder_has_ald()) {
if (!select_game_folder())
return 0;
}
#endif
load_profile();
check_profile();
sys35_ParseOption(&argc, argv);
if (!initGameResource(&nact->files, gameResourceFile)) {
if (!initGameResource(&nact->files, gameResourceFile, savedir)) {
#ifdef _WIN32
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "xsystem35", "Cannot find scenario file (*SA.ALD)", NULL);
exit(1);
@@ -509,6 +519,8 @@ int main(int argc, char **argv) {
#endif
sys35_init();
if (integer_scaling)
sdl_setIntegerScaling(true);
#ifdef ENABLE_GTK
gtk_init(&argc, &argv);
@@ -517,9 +529,13 @@ int main(int argc, char **argv) {
menu_init();
if (debugger_mode != DEBUGGER_DISABLED) {
#ifdef ENABLE_DEBUGGER
char symbols_path[500];
snprintf(symbols_path, sizeof(symbols_path), "%s.symbols", nact->files.game_fname[DRIFILE_SCO][0]);
dbg_init(symbols_path, debugger_mode == DEBUGGER_DAP);
#else
sys_error("Debugging is not supported in this build.");
#endif
}
for (;;) {
-21
View File
@@ -1,21 +0,0 @@
#!/bin/sh
# To use this script in MSYS2 shell, install mingw-w64-ucrt-x86_64-nsis and
# mingw-w64-ucrt-x86_64-ntldd packages.
if [ $# -ne 2 ]; then
echo 'Usage: make-installer.sh <build-dir> <nsi>'
exit 1
fi
builddir=$1
nsi=$2
echo 'dlls.nsi:'
ntldd -R $builddir/src/xsystem35.exe |perl -ne 'print "File \"$1\"\n" if /=> (.*) \(/' |grep 'mingw32\|ucrt64' |tee $builddir/dlls.nsi
echo
echo 'dlls-uninstall.nsi:'
sed 's/^File ".*\\/Delete "$INSTDIR\\/' $builddir/dlls.nsi |tee $builddir/dlls-uninstall.nsi
echo
makensis -INPUTCHARSET UTF8 -DBUILDDIR="$builddir" "$nsi"
-5
View File
@@ -1,5 +0,0 @@
Unicode true
Name xsystem35
OutFile xsystem35-32bit.exe
InstallDir $PROGRAMFILES32\xsystem35
!include xsystem35.nsi
-5
View File
@@ -1,5 +0,0 @@
Unicode true
Name xsystem35
OutFile xsystem35-64bit.exe
InstallDir $PROGRAMFILES64\xsystem35
!include xsystem35.nsi
-78
View File
@@ -1,78 +0,0 @@
ManifestDPIAware true
SetCompressor /SOLID lzma
LoadLanguageFile "${NSISDIR}\Contrib\Language files\English.nlf"
LoadLanguageFile "${NSISDIR}\Contrib\Language files\Japanese.nlf"
Page license
Page directory
Page components
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles
LicenseData ..\..\COPYING
!define SHCNE_ASSOCCHANGED 0x08000000
!define SHCNF_IDLIST 0
Function RefreshShellIcons
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v \
(${SHCNE_ASSOCCHANGED}, ${SHCNF_IDLIST}, 0, 0)'
FunctionEnd
Section
SetOutPath $INSTDIR
FILE ${BUILDDIR}\src\xsystem35.exe
!include ${BUILDDIR}\dlls.nsi
SetOutPath $INSTDIR\fonts
FILE /x CMakeLists.txt ..\..\fonts\*.*
WriteUninstaller $INSTDIR\uninstall.exe
WriteRegStr HKLM "Software\Kichikuou\xsystem35" "InstallDir" "$INSTDIR"
WriteRegStr HKLM "Software\Kichikuou\xsystem35\profile" "ttfont_gothic" "$INSTDIR\fonts\MTLc3m.ttf"
WriteRegStr HKLM "Software\Kichikuou\xsystem35\profile" "ttfont_mincho" "$INSTDIR\fonts\mincho.otf"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\xsystem35" "DisplayName" "xsystem35 (remove only)"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\xsystem35" "UninstallString" '"$INSTDIR\uninstall.exe"'
SectionEnd
LangString FileAssociation ${LANG_ENGLISH} "Associate with .ALD file type"
LangString FileAssociation ${LANG_JAPANESE} ".ALD ファイルに関連付け"
Section "$(FileAssociation)"
WriteRegStr HKCR ".ald" "" "System35Archive"
WriteRegStr HKCR "System35Archive" "" "AliceSoft System 3.x archive"
WriteRegStr HKCR "System35Archive\DefaultIcon" "" "$INSTDIR\xsystem35.exe,0"
WriteRegStr HKCR "System35Archive\shell\open\command" "" '"$INSTDIR\xsystem35.exe" "%1"'
Call RefreshShellIcons
SectionEnd
LangString DesktopIcon ${LANG_ENGLISH} "Create Desktop icon"
LangString DesktopIcon ${LANG_JAPANESE} "デスクトップショートカットを作成"
Section "$(DesktopIcon)"
CreateShortcut $DESKTOP\xsystem35.lnk $INSTDIR\xsystem35.exe
SectionEnd
LangString StartMenu ${LANG_ENGLISH} "Create Start menu entry"
LangString StartMenu ${LANG_JAPANESE} "スタートメニューに登録"
Section "$(StartMenu)"
CreateDirectory $SMPROGRAMS\xsystem35
CreateShortcut $SMPROGRAMS\xsystem35\xsystem35.lnk $INSTDIR\xsystem35.exe
CreateShortcut $SMPROGRAMS\xsystem35\uninstall.lnk $INSTDIR\uninstall.exe
SectionEnd
Section "Uninstall"
Delete $DESKTOP\xsystem35.lnk
RMDir /r $SMPROGRAMS\xsystem35
DeleteRegKey HKCR ".ald"
DeleteRegKey HKCR "System35Archive"
DeleteRegKey HKLM "Software\Kichikuou\xsystem35"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\xsystem35"
RMDir /r $INSTDIR\fonts
Delete $INSTDIR\uninstall.exe
Delete $INSTDIR\xsystem35.exe
!include ${BUILDDIR}\dlls-uninstall.nsi
RMDir $INSTDIR
SectionEnd
+76 -65
View File
@@ -1,36 +1,90 @@
#----------------------------------------------------------
# XSyetem35 設定ファイル
# XSyetem35 Configuration File
#
# 行頭が '#' で始まる行はコメント行です
# XSystem35 reads configuration from ~/.xsys35rc and .xsys35rc in the current
# directory. The latter takes precedence over the former, so you should put
# general settings in ~/.xsys35rc and game-specific settings in .xsys35rc
# in the game directory.
#
# Lines starting with '#' are comments.
# ------------------------------------------------------------
# 使用するフォントの指定
# Fonts
#
# Gothic (sans-serif) and Mincho (serif) fonts. .ttf and .otf files are
# supported.
#ttfont_gothic: /usr/local/share/xsystem35/fonts/MTLc3m.ttf
#ttfont_mincho: /usr/local/share/xsystem35/fonts/mincho.otf
#ttfont_gothic: /usr/local/share/xsystem35/fonts/MTLc3m.ttf
# Some fonts have multiple "faces" included. This specifies which face to use
# from the font file.
# True Type フォントのフェイス指定
#ttfont_mincho_face: 0
#ttfont_gothic_face: 0
# ------------------------------------------------------------
# フォントのアンチエイリアスを無効にする
# Disable font antialiasing.
#antialias: No
# ------------------------------------------------------------
# ------------------------------------------------------------
# Enables game-specific hacks. Usually auto-detected, but must be
# specified for games with modified / translated titles.
# Display
#
# Possible values are: toushin2, rance3_eng, rance4_eng, rance4_v2.
#game: rance4_v2
# Enforce integer scaling.
#integerscale: Yes
# Disable custom mouse cursor defined in resource files.
#no_imagecursor: Yes
# ------------------------------------------------------------
# Audio
#
# Path to the CD playlist. The playlist is a text file with one filename per
# line, in the order of CD tracks.
#playlist: playlist.txt
# device name of the raw midi device or sequencer device.
#midi_device: /dev/midi
#midi_device: /dev/sequencer
# Audio buffer size in bytes.
# Too small value causes sound glitches, too large value causes sound delay.
#audio_buffer_size: 2048
# MIDI Output method
# 'e' : SDL_mixer (default)
# 'pX' : via PortMidi (X is the device number, usually 0)
# 'r' : raw midi device
# 'sX' : sequencer device (X is the port number, usually 0)
# '0' : disable MIDI
#midi_output_device: e
# ------------------------------------------------------------
# Input
#
# joystick device number (0-)
#joy_device: 0
# -----------------------------------------------------------
# Miscellaneous
#
# Directory to save game state files.
# If it begins with '~', it is expanded to the user's home directory ($HOME).
#savedir: ~/.xsystem35-saves
# The format when writing save files.
# xsystem35 : default
# system36 : compatible with System3.5 v2 - System3.6
@@ -38,59 +92,16 @@
#saveformat: xsystem35
# ------------------------------------------------------------
# ------------------------------------------------------------
# CD-ROM のデバイス名
# Enables game-specific hacks. Usually auto-detected, but must be
# specified for games with modified / translated titles.
#
# Possible values are: toushin2, rance3_eng, rance4_eng, rance4_v2.
#cdrom_device: /dev/cdrom
#game: rance4_v2
# ------------------------------------------------------------
# Enables the ZB command (change the font weight). It is disabled by default
# because it makes the text too bold with our default fonts.
# This option is experimental and may be removed in the future. See
# https://github.com/kichikuou/xsystem35-sdl2/issues/44 for details.
# ------------------------------------------------------------
# raw midi device または sequencer device のデバイス名
#
#midi_device: /dev/midi
##midi_device: /dev/sequencer
# ------------------------------------------------------------
# ------------------------------------------------------------
# オーディオバッファのバイト数
# 小さすぎると音が途切れ、大きくすると効果音が遅れるようになります。
#audio_buffer_size: 2048
# ------------------------------------------------------------
# ------------------------------------------------------------
# MIDI Output method
# 'e' : SDL_mixer (default)
# 'pX' : via PortMidi (X is the device number, usually 0)
# 'r' : raw midi device
# 'sX' : sequencer device (X is the port number, usually 0)
# '0' : disable MIDI
#
#midi_output_device: e
# ------------------------------------------------------------
# ------------------------------------------------------------
# joystick device のデバイス番号 (0-)
#
#joy_device: 0
# ------------------------------------------------------------
# -----------------------------------------------------------
# リソースファイルによるマウスカーソルの形状変更を無効にする
# にする場合、以下を Yes にする (なにも指定しない場合は有効)
#
#no_imagecursor: Yes
# -----------------------------------------------------------
#enable_zb: Yes