Compare commits

...
35 Commits
Author SHA1 Message Date
kichikuou bcaed3a687 Version 2.11.5 2024-06-10 13:56:51 +09:00
kichikuou 894e8e26a6 Add CHANGELOG.md 2024-06-10 10:24:46 +09:00
kichikuou 7206b0a4f7 emscripten: Build with libwebp 2024-06-10 09:46:41 +09:00
kichikuou 343f3bb7c5 Fix fileCheckExist
This fixes https://github.com/kichikuou/xsystem35-sdl2/issues/55.
2024-06-10 08:59:58 +09:00
kichikuou d3650ce293 Update game_compatibility.md 2024-05-24 21:32:39 +09:00
kichikuou 386cfeb60c Update .gitignore 2024-05-24 21:31:49 +09:00
kichikuou 9cd66c83ef Android: Build with libwebp
Fixes https://github.com/kichikuou/xsystem35-sdl2/issues/46.
2024-05-23 10:57:38 +09:00
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
57 changed files with 660 additions and 1105 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.50
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@v13
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
+5 -3
View File
@@ -34,13 +34,14 @@ jobs:
${{ 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
@@ -49,7 +50,7 @@ jobs:
run: |
mkdir -p out/release
cd out/release
cmake -G"Ninja" -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }} ../../
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_COMPILE_WARNING_AS_ERROR=YES ${{ matrix.cmake_args }} ../../
ninja
- name: Test
@@ -61,7 +62,8 @@ jobs:
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.package }}
path: dist
compression-level: 9 # because we use it for releases
+3
View File
@@ -1,10 +1,13 @@
out
android/.gradle
android/.idea
android/app/.cxx
android/app/.externalNativeBuild
android/app/build
android/app/src/main/assets
android/build
android/keystore.jks
android/local.properties
.ccls-cache
.dir-locals.el
compile_commands.json
+107
View File
@@ -0,0 +1,107 @@
# Changelog
## 2.11.5 - 2024-06-10
- Android: Fixed a black screen issue in the MangaGamer version of Rance 5D.
- Fixed `fileCheckExist` command. (#55)
## 2.11.4 - 2024-05-22
- Windows: In full-screen mode, the menu bar now appears only when the mouse pointer is at the top of the screen. (#53)
- Fixed text rendering issue in Rance 3 intro. (#54)
## 2.11.3 - 2024-04-11
- Android: Fixed a bug where save files from older versions could not be loaded in version 2.11.2.
## 2.11.2 - 2024-04-10
- Added `-savedir` option to specify save directory.
- Android: Fixed a bug where .xsys35rc in a subdirectory of ZIP was not loaded. (#51)
## 2.11.1 - 2024-02-18
- Windows: Fixed a black screen issue in the MangaGamer version of Rance 5D (#45).
- Fixed a crash bug in command-line debugger.
## 2.11.0 - 2024-01-20
- Windows: Now `xsystem35.exe` is a standalone executable. You can just copy it to the game folder and run it.
- Windows: The installer is no longer provided. If you have an earlier version installed, please uninstall it.
- Windows: The debugger is no longer available in the 32-bit version. Please use the 64-bit version if you need it.
- Added experimental `enable_zb` option (#44). See `xsys35rc.sample` for details.
## 2.10.1 - 2024-01-01
- Windows: Added "Integer Scaling" menu option
- Fixed initial palette colors (to match System3.9)
- Fixed a bug where palette 246 to 249 were unintentionally changed after loading 256-color CGs
## 2.10.0 - 2023-12-09
- Breaking change: A [bug](https://github.com/kichikuou/xsystem35-sdl2/issues/41) has been fixed in which save format for 大悪司 and かえるにょ国にょアリス was not compatible with System3.9. As a result, save files for these games created with older versions of xsystem35 are no longer usable. (Loading will not fail, but wrong values will be loaded.)
- Now the 64-bit executable supports Windows 10 or later. For older Windows, please use the 32-bit version.
- Fixed a problem with the download edition of Daiakuji requiring insertion of Disk 2. (#43)
- Debugger: Added debug commands for monitoring the color palette.
- Minor bug fixes.
## 2.9.1 - 2023-06-22
- Fixed a bug where the `CX 1` command (copy with transparent color) did not work in some games (e.g. Daiakuji)
- Debugger: Now breakpoints do not make the window completely unresponsive
- Debugger: Fixed a conditional breakpoint crash bug
## 2.9.0 - 2023-05-04
- Now xsystem35 uses the System3.9 save file format (unless `-saveformat` command line flag is specified). Old save files can still be loaded.
- Changed the default naming convention for save files from `[a-z]sleep.asd` to `<gamename>s[a-z].asd`.
- Fixed a bug where SACT games (e.g. Rance 5D) were not responding to touch.
- Fixed memory leaks in debugger.
## 2.8.0 - 2023-02-12
- Added support for Rance 4.1/4.2 ver1.05
- Fixed movement animation in rooms in Rance 4 v2.05 (#35)
- Added `-game` option which can be used to enable game-specific hacks in translated games
## 2.7.0 - 2023-01-28
- Added support for Rance4 ver.2.05
- Now supports BGM playback for the download edition of Daiakuji
- Bug fixes
## 2.6.0 - 2023-01-01
- Android: Introduced a new way to simulate right-click; tapping on the black bars at the left/right or top/bottom of the screen is treated as a right click. (Two-finger touch, the old way to simulate a right click, still works.)
- Windows: Added a menu command to enable/disable automatic mouse movements.
## 2.5.1 - 2022-07-31
- Implemented "palette shift" graphic effect (used in 闘神都市II).
- Implemented `grDrawFillCircle` command (used in グレイメルカ).
- Fixed color update bug in 256-color games.
- Fixed crash by out-of-bounds variable access in debugger.
## 2.5.0 - 2022-07-17
- Supported JPEG image format on Android.
## 2.4.0 - 2022-07-02
- Windows: Added "Restart" menu command.
- Fixed a bug where wrong music is played in Kichikuou Rance (System3.9 version). #32
- Supported mouse wheel input.
- Fixed a bug in `MF` command.
- Implemented `grEffectMoveView` command.
## 2.3.0 - 2022-04-08
- Code for screen transition effects have been substantially rewritten (but you probably wouldn't notice any difference).
- Fixed bugs in System3.9 games.
- Android: Enabled joystick input.
- Debugger improvements.
## 2.2.0 - 2021-12-03
From now on, the Android and Windows versions will use a common version number.
- Android: Use custom fonts specified in `.xsys35c`. (#20)
- Supported "王子さまLv1".
- Debugger improvements.
- Fixed some bugs and compatibility issues.
## 2.1.0 - 2021-11-07
- Fixed issues with MangaGamer version of Rance 5D.
- Fixed garbled text in some System3.9 games with Unicode mode.
- Display a message box on fatal errors.
- Various debugger improvements.
## 2.0.1 - 2021-10-24
- Fixed crash during shutdown.
## 2.0.0 - 2021-10-23
- Added window menubar from which you can save screenshots, change fullscreen mode, and enable message skipping.
- Added debugger support that can be used from Visual Studio Code. See [vscode-system3x](https://github.com/kichikuou/vscode-system3x) for details.
- Many bug fixes and compatibility fixes.
+42 -58
View File
@@ -3,8 +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(CheckSymbolExists)
include(FetchContent)
# A wrapper around pkg_check_modules() that skips the check if ENABLE_<prefix> is false
macro (optional_pkg_check_modules prefix)
@@ -25,6 +27,27 @@ function(add_static_library name pkg)
INTERFACE_LINK_OPTIONS "${${pkg}_STATIC_LDFLAGS_OTHER}")
endfunction()
function(fetch_webp)
FetchContent_Declare(
libwebp
URL https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.4.0.tar.gz
URL_HASH SHA1=0b1c8bea200caaa010182609dbaaa91aec69b64d
)
set(WEBP_BUILD_ANIM_UTILS OFF CACHE BOOL "Build animation utilities." FORCE)
set(WEBP_BUILD_CWEBP OFF CACHE BOOL "Build the cwebp command line tool." FORCE)
set(WEBP_BUILD_DWEBP OFF CACHE BOOL "Build the dwebp command line tool." FORCE)
set(WEBP_BUILD_GIF2WEBP OFF CACHE BOOL "Build the gif2webp conversion tool." FORCE)
set(WEBP_BUILD_IMG2WEBP OFF CACHE BOOL "Build the img2webp animation tool." FORCE)
set(WEBP_BUILD_VWEBP OFF CACHE BOOL "Build the vwebp viewer tool." FORCE)
set(WEBP_BUILD_WEBPINFO OFF CACHE BOOL "Build the webpinfo command line tool." FORCE)
set(WEBP_BUILD_LIBWEBPMUX OFF CACHE BOOL "Build the libwebpmux library." FORCE)
set(WEBP_BUILD_WEBPMUX OFF CACHE BOOL "Build the webpmux command line tool." FORCE)
set(WEBP_BUILD_EXTRAS OFF CACHE BOOL "Build extras." FORCE)
set(WEBP_BUILD_WEBP_JS OFF CACHE BOOL "Emscripten build of webp.js." FORCE)
FetchContent_MakeAvailable(libwebp)
add_library(WebP ALIAS webp)
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)
@@ -36,20 +59,23 @@ if (EMSCRIPTEN)
INTERFACE_COMPILE_OPTIONS ${option}
INTERFACE_LINK_OPTIONS ${option})
endfunction()
add_emscripten_library(zlib "SHELL:-s USE_ZLIB=1")
add_emscripten_library(sdl2 "SHELL:-s USE_SDL=2")
add_emscripten_library(sdl2_ttf "SHELL:-s USE_SDL_TTF=2")
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/)
fetch_webp()
set(HAVE_WEBP 1)
elseif (ANDROID)
add_library(sdl2 ALIAS SDL2)
add_library(sdl2_ttf ALIAS SDL2_ttf)
add_library(sdl2_mixer ALIAS SDL2_mixer)
set(SDL2MIXER_FOUND 1)
find_library(ndk_log log)
find_library(ndk_zlib z)
add_library(zlib INTERFACE)
set_target_properties(zlib PROPERTIES INTERFACE_LINK_LIBRARIES ${ndk_zlib})
fetch_webp()
set(HAVE_WEBP 1)
else() # non-emscripten, non-android
if (WIN32)
@@ -66,22 +92,18 @@ else() # non-emscripten, non-android
pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2)
pkg_check_modules(SDL2TTF REQUIRED IMPORTED_TARGET SDL2_ttf)
optional_pkg_check_modules(SDL2MIXER IMPORTED_TARGET SDL2_mixer)
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++>)
if (SDL2MIXER_FOUND)
add_static_library(sdl2_mixer SDL2MIXER)
endif()
add_static_library(sdl2_mixer SDL2MIXER)
else()
add_library(sdl2 ALIAS PkgConfig::SDL2)
add_library(sdl2_ttf ALIAS PkgConfig::SDL2TTF)
if (SDL2MIXER_FOUND)
add_library(sdl2_mixer ALIAS PkgConfig::SDL2MIXER)
endif()
add_library(sdl2_mixer ALIAS PkgConfig::SDL2MIXER)
set(DEFAULT_FONT_PATH ${CMAKE_INSTALL_PREFIX}/share/xsystem35/fonts/)
endif()
@@ -117,19 +139,12 @@ else() # non-emscripten, non-android
find_library(PORTMIDI portmidi)
if (PORTMIDI)
set(HAVE_PORTMIDI 1)
set(ENABLE_MIDI_PORTMIDI 1)
endif()
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)
@@ -139,60 +154,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)
@@ -211,15 +202,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()
@@ -242,7 +227,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)
+2 -2
View File
@@ -16,8 +16,8 @@ android {
defaultConfig {
minSdkVersion 19
targetSdkVersion 34
versionCode 18
versionName "2.11.0" + gitRevision()
versionCode 23
versionName "2.11.5" + gitRevision()
externalNativeBuild {
cmake {
arguments "-DANDROID_APP_PLATFORM=android-19", "-DANDROID_STL=c++_static"
+8 -9
View File
@@ -7,18 +7,18 @@ set(PROJECT_ROOT_DIR ../../..)
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
)
set(SDL2TTF_SAMPLES OFF CACHE BOOL "Build the SDL2_ttf sample program(s)" FORCE)
@@ -29,12 +29,11 @@ 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)
FetchContent_MakeAvailable(SDL SDL_ttf 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 -8
View File
@@ -1,13 +1,8 @@
#cmakedefine PACKAGE "@PACKAGE@"
#define VERSION "2.11.0"
#define VERSION "2.11.5"
#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@
@@ -15,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@"
+4 -4
View File
@@ -5,11 +5,11 @@ Game Compatibility
| ------------------------------------------- | ----------- | ----- |
| 鬼畜王ランス | Supported | |
| Kichikuou Rance (EN) | Supported | |
| RanceIV -教団の遺産- | Supported | Win95 edition, [Ver2.05](https://hannylaboratory.blogspot.com/2023/01/blog-post_26.html) |
| RanceIV -教団の遺産- | Supported | Win95 edition and [Ver2.05](https://hannylaboratory.blogspot.com/2023/01/blog-post_26.html) |
| Rance4 -Legacy of the Sect- (EN) | Supported | |
| 兰斯IV -教团的遗产- (CN) | Supported | |
| ランス4.1 | Supported | [Ver1.05](https://hannylaboratory.blogspot.com/2023/02/blog-post_9.html) |
| ランス4.2 | Supported | [Ver1.05](https://hannylaboratory.blogspot.com/2023/02/blog-post_9.html) |
| ランス4.1 | Supported | [Ver1.05](https://hannylaboratory.blogspot.com/2023/02/blog-post_9.html). Use system3-sdl2 for older versions |
| ランス4.2 | Supported | [Ver1.05](https://hannylaboratory.blogspot.com/2023/02/blog-post_9.html). Use system3-sdl2 for older versions |
| いけないかつみ先生 | Supported | Emojis are not supported |
| 闘神都市II | Supported | Win95 edition |
| かえるにょ・ぱにょ~ん | Supported | Normal / Low-priced edition |
@@ -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 |
+113 -49
View File
@@ -21,57 +21,120 @@ 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)
if (EMSCRIPTEN)
target_sources(xsystem35 PRIVATE pcm.emscripten.c bgm.emscripten.c)
else()
target_sources(xsystem35 PRIVATE pcm.sdlmixer.c bgm.sdlmixer.c)
endif()
# Graphics
if (EMSCRIPTEN)
target_sources(xsystem35 PRIVATE cdrom.emscripten.c)
else()
target_sources(xsystem35 PRIVATE cdrom.mp3.c)
endif()
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)
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()
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()
# 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 WebP)
endif()
# Music
target_sources(xsystem35 PRIVATE
music.c music_cdrom.c music_midi.c midi.c cdrom.c)
# Misc
target_sources(xsystem35 PRIVATE
input.c profile.c mt19937-1.c filecheck.c mmap.c hacks.c)
# 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)
# Graphics
target_sources(xsystem35 PRIVATE
ags.c cg.c ecopy.c alpha_plane.c cursor.c)
# 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)
@@ -95,15 +158,16 @@ if (EMSCRIPTEN)
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(xsystem35 PRIVATE ${ndk_log})
-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;
}
-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;
}
+1 -1
View File
@@ -28,7 +28,7 @@
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
+18 -3
View File
@@ -42,11 +42,14 @@
#include "ald_manager.h"
#include "LittleEndian.h"
#include "hacks.h"
#include "filecheck.h"
/* 選択 Window OPEN 時 callback */
static int cb_sel_init_page = 0;
static int cb_sel_init_address = 0;
static const char REGREADSTRING_RESULT[] = "*regReadString*";
extern INPUTSTRING_PARAM mi_param;
extern void commandH();
@@ -1441,7 +1444,10 @@ void commands2F87() {
int eBaneStrNum = getCaliValue();
int eResultStrNum = getCaliValue();
int *vResult = getCaliVariable();
// This command is used to check if the game is installed, so we always
// return 1 with the dummy string REGREADSTRING_RESULT.
svar_set(eResultStrNum, REGREADSTRING_RESULT);
*vResult = 1;
DEBUG_COMMAND("regReadString %d,%d,%d,%d:",
@@ -1451,8 +1457,17 @@ void commands2F87() {
void commands2F88() {
int eFileNameStrNum = getCaliValue();
int *vResult = getCaliVariable();
*vResult = 1;
const char *fname = svar_get(eFileNameStrNum);
if (strcmp(fname, REGREADSTRING_RESULT) == 0) {
// If this command is called with the result of regReadString, the game
// is checking if the game CD is inserted. We return 1 in this case.
*vResult = 1;
} else {
char *fname_utf8 = sjis2utf(fname);
*vResult = fc_exists(fname_utf8) ? 1 : 0;
free(fname_utf8);
}
DEBUG_COMMAND("fileCheckExist %d,%d:", eFileNameStrNum, *vResult);
}
+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();
+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])
+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();
}
+32 -34
View File
@@ -30,50 +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;
if (d->maxno < i)
d->maxno = i;
d->disk[i] = ltbl[i * 3];
int ptr = LittleEndian_getW(ltbl, i * 3 + 1);
d->offset[i] = LittleEndian_get3B(ptbl, ptr * 3) << 8;
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;
}
@@ -90,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)
@@ -117,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];
+1 -1
View File
@@ -35,7 +35,7 @@ struct _drifiles {
char *fnames[DRIFILEMAX];
int nr_files; // upper limit on how many files could be referenced by this archive
int maxno;
uint8_t *disk; // file numbers
uint8_t *link; // link table
uint32_t *offset; // offsets in file
};
typedef struct _drifiles drifiles;
+81 -2
View File
@@ -21,15 +21,18 @@
*/
/* $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>
#include <unistd.h>
#ifdef _WIN32
#include <direct.h>
#include <windows.h>
#undef min
#undef max
#endif
#include "filecheck.h"
@@ -47,9 +50,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);
}
@@ -66,6 +125,18 @@ char *fc_get_path(const char *fname_utf8) {
return get_fullpath(saveDataPath, fname_utf8);
}
bool fc_exists(const char *fname_utf8)
{
char *path = fc_get_path(fname_utf8);
wchar_t wpath[PATH_MAX + 1];
bool result = false;
if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path, -1, wpath, PATH_MAX + 1)) {
result = _waccess(wpath, F_OK) != -1;
}
free(path);
return result;
}
FILE *fc_open(const char *fname_utf8, char type) {
char *path = fc_get_path(fname_utf8);
FILE *fp = fopen_utf8(path, type);
@@ -102,6 +173,14 @@ char *fc_get_path(const char *fname_utf8) {
return get_fullpath(saveDataPath, fname_utf8);
}
bool fc_exists(const char *fname_utf8)
{
char *path = fc_get_path(fname_utf8);
bool result = access(path, F_OK) != -1;
free(path);
return result;
}
FILE *fc_open(const char *fname_utf8, char type) {
char *fullpath = fc_search(fname_utf8, saveDataPath);
if (!fullpath) {
+7 -4
View File
@@ -24,9 +24,12 @@
#ifndef __FILECHECK_H__
#define __FILECHECK_H__
extern void fc_init(const char *name);
extern char *fc_get_path(const char *fname_utf8);
extern FILE *fc_open(const char *fname_utf8, char type);
extern void fc_backup_oldfile(const char *filename);
#include <stdbool.h>
void fc_init(const char *name);
char *fc_get_path(const char *fname_utf8);
bool fc_exists(const char *fname_utf8);
FILE *fc_open(const char *fname_utf8, char type);
void fc_backup_oldfile(const char *filename);
#endif /* !__FILECHECK_H__ */
+11 -2
View File
@@ -36,6 +36,7 @@
#include "system.h"
#include "font.h"
#include "sdl_private.h"
#include "hacks.h"
typedef struct {
int size;
@@ -175,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]);
@@ -190,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};
+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++) {
+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>
+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(const 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(const 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; }
+2 -1
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();
});
+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();
}
}
+7 -4
View File
@@ -136,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__
@@ -145,10 +149,9 @@ 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);
}
+12 -6
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);
@@ -60,9 +62,6 @@ static void saveScreenshot(void) {
}
static bool toggle_menu_item(UINT id, bool *checked_out) {
HWND hwnd = get_hwnd(sdl_window);
HMENU hmenu = GetMenu(hwnd);
MENUITEMINFO menuitem = {
.cbSize = sizeof(MENUITEMINFO),
.fMask = MIIM_STATE,
@@ -82,7 +81,7 @@ static bool toggle_menu_item(UINT id, bool *checked_out) {
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.
@@ -90,7 +89,7 @@ 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:
@@ -106,9 +105,11 @@ 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))
@@ -126,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);
+23 -7
View File
@@ -96,6 +96,7 @@ static int audio_buffer_size = 0;
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;
@@ -112,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");
@@ -258,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");
@@ -275,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) {
@@ -333,6 +342,10 @@ static void sys35_ParseOption(int *argc, char **argv) {
static void check_profile() {
const char *param;
param = get_profile("savedir");
if (param) {
savedir = param;
}
/* ゴシックフォント(TT)の設定 */
param = get_profile("ttfont_gothic");
if (param) {
@@ -374,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) {
@@ -481,7 +497,7 @@ int main(int argc, char **argv) {
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);
+8 -2
View File
@@ -44,9 +44,10 @@
# Audio
#
# CD-ROM device name.
# Path to the CD playlist. The playlist is a text file with one filename per
# line, in the order of CD tracks.
#cdrom_device: /dev/cdrom
#playlist: playlist.txt
# device name of the raw midi device or sequencer device.
@@ -79,6 +80,11 @@
# 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