Compare commits

...
49 Commits
Author SHA1 Message Date
kichikuou 9c73a34c35 Version 2.11.7 2024-11-12 08:57:54 +09:00
kichikuou 36e1dc152b Fix crash when canceling menu with two-finger touch
Fixes #58.

It was a regression by commit eeeab6e.
2024-11-12 08:55:36 +09:00
kichikuou f786db5a50 Android: Upgrade SDL to 2.30.9 2024-11-12 08:51:36 +09:00
kichikuou c515b21afb Refactor ags_eSpriteCopyArea() 2024-09-01 21:44:11 +09:00
kichikuou d3db3fa83e sdl_effect: Implement EFFECT_PAN_IN_* and EFFECT_SKIP_LINE_*
This also fixes incorrect behavior of `CD 1` and `CD 2`.
2024-09-01 14:57:59 +09:00
kichikuou 86068b0ab9 Prefer single precision float 2024-09-01 08:25:34 +09:00
kichikuou de4f3ebb0d sdl_effect: Implement EFFECT_RASTER_BLEND (CD 5)
Used in Mugen Houyou's title logo.
2024-08-31 22:00:07 +09:00
kichikuou 187a3ced35 Separate ags_eSpriteCopyArea() from ags_eCopyArea() 2024-08-31 16:10:42 +09:00
kichikuou b7703b6270 CMake: Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP 2024-08-31 12:36:22 +09:00
kichikuou b7d0efbe55 README.md: Add note for Windows 2024-08-31 10:52:29 +09:00
kichikuou 02fe55eb93 Remove console message on quit 2024-08-31 10:39:00 +09:00
kichikuou 058789b435 Fix fade-in when screen refresh is disabled
Fade-in by `PF` or `PW` command was updating sdl_display even if screen
update was disabled by the `WZ 0` command.

In Rance 3, this caused a screen artifact immediately after selecting
"Game Start".

This was a regression introduced by commit 605de28.
2024-08-31 10:27:09 +09:00
kichikuou c5dcb20ac3 Simplify midifile.c 2024-08-21 12:20:01 +09:00
kichikuou cb08f7ca76 Windows CI: Build with portmidi
Also update README.md.
2024-08-19 12:58:46 +09:00
kichikuou 7a7d94e60f Remove raw and OSS sequencer MIDI mackends
In favor of PortMidi.
2024-08-19 12:46:56 +09:00
kichikuou b7681982a6 Rework midi.portmidi.c
Copied midi.rawmidi.c and adapted it to use PortMidi. Now the main
thread and the MIDI thread communicate via a message queue.
2024-08-19 11:07:00 +09:00
kichikuou fefaf6c343 Remove RPM spec files 2024-08-02 15:17:49 +09:00
kichikuou 42e994dfba emscripten: Use EM_ASYNC_JS 2024-07-31 08:59:33 +09:00
kichikuou a6aa50b5cf emscripten: Use MODULARIZE=1 2024-07-30 12:30:50 +09:00
kichikuou c4e8205d6c Version 2.11.6 2024-07-22 12:32:33 +09:00
kichikuou dd09f54329 mouse: Use system cursor if possible 2024-07-22 09:28:07 +09:00
kichikuou 435ceb31d3 Fix build with portmidi enabled but raw-midi disabled 2024-07-22 09:28:07 +09:00
kichikuou e40de66821 Remove obsolete docs 2024-07-12 11:25:15 +09:00
kichikuou 73c79b7a2e Add xsystem35 version string to mansource 2024-07-12 08:07:42 +09:00
kichikuou a825ee80b3 Add AsciiDoc manuals for xsystem35 command and .gr file format
They replace the outdated README and GRFMT.TXT files.
2024-07-12 07:40:32 +09:00
kichikuou eeeab6e054 Right-click exits selection without waiting for button up
This fixes https://github.com/kichikuou/xsystem35-sdl2/issues/56.
2024-06-18 13:17:53 +09:00
kichikuou 875b233f32 CI: Build with latest emscripten 2024-06-11 07:49:43 +09:00
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
101 changed files with 1705 additions and 3590 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ name: Emscripten Build
on: [push, pull_request]
env:
EM_VERSION: 3.1.54
EM_VERSION: latest
EM_CACHE_FOLDER: 'emsdk-cache'
jobs:
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
- name: Install Deps
run: |
sudo apt update
sudo apt install libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libportmidi-dev libcjson-dev
sudo apt install libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libportmidi-dev libcjson-dev asciidoctor
- name: Build
run: |
+3 -2
View File
@@ -31,6 +31,7 @@ jobs:
SDL2_ttf:p
SDL2_mixer:p
libwebp:p
portmidi:p
${{ matrix.deps }}
- name: Checkout
@@ -44,7 +45,7 @@ jobs:
cp fonts/*.license dist/licenses/
- name: Install dev dependencies
run: pacboy --noconfirm -S --needed gcc:p cmake:p ninja:p
run: pacboy --noconfirm -S --needed gcc:p cmake:p ninja:p asciidoctor:p
- name: Build
run: |
@@ -59,7 +60,7 @@ jobs:
- name: Package
run: |
cp out/release/src/xsystem35.exe *.md COPYING xsys35rc.sample dist/
cp out/release/src/xsystem35.exe out/release/doc/*.html *.md COPYING xsys35rc.sample dist/
- name: Upload
uses: actions/upload-artifact@v4
+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
+116
View File
@@ -0,0 +1,116 @@
# Changelog
## 2.11.7 - 2024-11-12
- Fixed crash when canceling menu with two-finger touch (#58)
- Fixed screen artifact in Rance 3 immediately after selecting "Game Start"
## 2.11.6 - 2024-07-22
- Fixed strange behavior when canceling the battle selection menu in Kichikuou Rance. (#56)
- Use system mouse cursors whenever possible. They look better on high dpi displays.
- Added manual page for the xsystem35 command.
## 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.
+39 -22
View File
@@ -1,11 +1,19 @@
cmake_minimum_required(VERSION 3.13)
# Rebuild external projects when download URL changes
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif()
project(xsystem35 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
enable_testing()
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
set(XSYSTEM35_VERSION "2.11.7")
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)
@@ -26,6 +34,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)
@@ -37,10 +66,12 @@ 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)
@@ -50,6 +81,8 @@ elseif (ANDROID)
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)
@@ -157,25 +190,6 @@ else()
list(APPEND SUMMARY_MIDI "SDL_mixer")
set(ENABLE_MIDI_SDLMIXER 1)
if (HAVE_SIGACTION)
list(APPEND SUMMARY_MIDI "raw")
set(MIDI_DEVICE "/dev/midi" CACHE STRING "midi device")
set(ENABLE_MIDI_RAWMIDI 1)
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
check_symbol_exists(SNDCTL_SEQ_NRSYNTHS "machine/soundcard.h" ENABLE_MIDI_SEQMIDI)
elseif (CMAKE_SYSTEM_NAME MATCHES "(NetBSD|OpenBSD)")
check_symbol_exists(SNDCTL_SEQ_NRSYNTHS "soundcard.h" ENABLE_MIDI_SEQMIDI)
else ()
check_symbol_exists(SNDCTL_SEQ_NRSYNTHS "sys/soundcard.h" ENABLE_MIDI_SEQMIDI)
endif()
if (ENABLE_MIDI_SEQMIDI)
list(APPEND SUMMARY_MIDI "OSS sequencer")
set(SEQ_DEVICE "/dev/sequencer" CACHE STRING "sequencer device")
endif()
if (HAVE_PORTMIDI)
list(APPEND SUMMARY_MIDI "PortMidi")
set(ENABLE_MIDI_PORTMIDI 1)
@@ -206,6 +220,9 @@ add_compile_definitions($<$<CONFIG:Debug>:DEBUG>)
add_subdirectory(src)
add_subdirectory(tools)
add_subdirectory(fonts)
if (NOT ANDROID AND NOT EMSCRIPTEN)
add_subdirectory(doc)
endif()
if (ENABLE_NLS)
add_subdirectory(po)
endif()
+14 -6
View File
@@ -63,8 +63,14 @@ and examine or modify game variables. There are two ways to use the debugger:
## Installation
Prebuilt packages for Windows and Android can be downloaded from the
[Releases](https://github.com/kichikuou/xsystem35-sdl2/releases) page. For
other platforms, refer to the [Building](#building) section.
[Releases](https://github.com/kichikuou/xsystem35-sdl2/releases) page.
Note for Windows:
- The 64-bit version supports Windows 10 or later. For older versions of
Windows, please use the 32-bit version.
- Debugging is supported only in the 64-bit version.
For other platforms, refer to the [Building](#building) section.
## Running
### Windows
@@ -73,7 +79,7 @@ Copy `xsystem35.exe` to the game folder and run it.
### Android
See [android/README.md](android/README.md#use).
See [android/README.md](android/README.md#usage).
### Other Platforms
@@ -84,11 +90,13 @@ $ cd /path/to/game_directory
$ xsystem35
```
See [xsystem35 command manual](doc/xsystem35.6.adoc) for detailed usage.
## Building
### Linux (Debian / Ubuntu)
```bash
$ sudo apt install build-essential cmake libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libcjson-dev
$ sudo apt install build-essential cmake libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libportmidi-dev libcjson-dev asciidoctor
$ mkdir -p out/debug
$ cd out/debug
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
@@ -100,7 +108,7 @@ $ make && make install
[Homebrew](https://brew.sh/) is required.
```bash
$ brew install cmake pkg-config sdl2 sdl2_mixer sdl2_ttf webp cjson
$ brew install cmake pkg-config sdl2 sdl2_mixer sdl2_ttf webp portmidi cjson asciidoctor
$ mkdir -p out/debug
$ cd out/debug
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
@@ -112,7 +120,7 @@ $ make && make install
[MSYS2](https://www.msys2.org) is required.
```bash
$ pacman -S cmake mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-SDL2 mingw-w64-ucrt-x86_64-SDL2_ttf mingw-w64-ucrt-x86_64-SDL2_mixer mingw-w64-ucrt-x86_64-libwebp mingw-w64-ucrt-x86_64-cjson
$ pacman -S cmake mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-SDL2 mingw-w64-ucrt-x86_64-SDL2_ttf mingw-w64-ucrt-x86_64-SDL2_mixer mingw-w64-ucrt-x86_64-libwebp mingw-w64-ucrt-x86_64-portmidi mingw-w64-ucrt-x86_64-cjson
$ mkdir -p out/debug
$ cd out/debug
$ cmake -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug ../../
+2 -2
View File
@@ -16,8 +16,8 @@ android {
defaultConfig {
minSdkVersion 19
targetSdkVersion 34
versionCode 19
versionName "2.11.1" + gitRevision()
versionCode 25
versionName "2.11.7" + 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.9/SDL2-2.30.9.tar.gz
URL_HASH SHA1=9403df0573d47f62f2de074b582b87576bb4abbc
)
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)
+1 -1
View File
@@ -80,7 +80,7 @@
android:label="@string/app_name"
android:alwaysRetainTaskState="true"
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:theme="@style/AppTheme"
android:hardwareAccelerated="true"
>
@@ -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)!!,
"-playlist", 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)
}
@@ -277,6 +277,7 @@ public class HIDDeviceManager {
0x044f, // Thrustmaster
0x045e, // Microsoft
0x0738, // Mad Catz
0x0b05, // ASUS
0x0e6f, // PDP
0x0f0d, // Hori
0x10f5, // Turtle Beach
@@ -285,6 +286,7 @@ public class HIDDeviceManager {
0x24c6, // PowerA
0x2dc8, // 8BitDo
0x2e24, // Hyperkin
0x3537, // GameSir
};
if (usbInterface.getId() == 0 &&
@@ -358,6 +360,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");
@@ -583,7 +591,13 @@ public class HIDDeviceManager {
} else {
flags = 0;
}
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), flags));
if (Build.VERSION.SDK_INT >= 33 /* Android 14.0 (U) */) {
Intent intent = new Intent(HIDDeviceManager.ACTION_USB_PERMISSION);
intent.setPackage(mContext.getPackageName());
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, intent, flags));
} else {
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), flags));
}
} catch (Exception e) {
Log.v(TAG, "Couldn't request permission for USB device " + usbDevice);
HIDDeviceOpenResult(deviceID, false);
@@ -38,6 +38,10 @@ public class SDL {
}
public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
loadLibrary(libraryName, mContext);
}
public static void loadLibrary(String libraryName, Context context) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
if (libraryName == null) {
throw new NullPointerException("No library name provided.");
@@ -53,10 +57,10 @@ public class SDL {
// To use ReLinker, just add it as a dependency. For more information, see
// https://github.com/KeepSafe/ReLinker for ReLinker's repository.
//
Class<?> relinkClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker");
Class<?> relinkListenerClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener");
Class<?> contextClass = mContext.getClassLoader().loadClass("android.content.Context");
Class<?> stringClass = mContext.getClassLoader().loadClass("java.lang.String");
Class<?> relinkClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker");
Class<?> relinkListenerClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener");
Class<?> contextClass = context.getClassLoader().loadClass("android.content.Context");
Class<?> stringClass = context.getClassLoader().loadClass("java.lang.String");
// Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if
// they've changed during updates.
@@ -66,7 +70,7 @@ public class SDL {
// Actually load the library!
Method loadMethod = relinkInstanceClass.getDeclaredMethod("loadLibrary", contextClass, stringClass, stringClass, relinkListenerClass);
loadMethod.invoke(relinkInstance, mContext, libraryName, null, null);
loadMethod.invoke(relinkInstance, context, libraryName, null, null);
}
catch (final Throwable e) {
// Fall back
@@ -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 = 9;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
@@ -89,7 +89,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
| InputDevice.SOURCE_CLASS_POSITION
| InputDevice.SOURCE_CLASS_TRACKBALL);
if (s2 != 0) cls += "Some_Unkown";
if (s2 != 0) cls += "Some_Unknown";
s2 = s_copy & InputDevice.SOURCE_ANY; // keep source only, no class;
@@ -163,7 +163,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (s == FLAG_TAINTED) src += " FLAG_TAINTED";
s2 &= ~FLAG_TAINTED;
if (s2 != 0) src += " Some_Unkown";
if (s2 != 0) src += " Some_Unknown";
Log.v(TAG, prefix + "int=" + s_copy + " CLASS={" + cls + " } source(s):" + src);
}
@@ -281,7 +281,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
// Load the .so
public void loadLibraries() {
for (String lib : getLibraries()) {
SDL.loadLibrary(lib);
SDL.loadLibrary(lib, this);
}
}
@@ -995,8 +995,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
/* No valid hint, nothing is explicitly allowed */
if (!is_portrait_allowed && !is_landscape_allowed) {
if (resizable) {
/* All orientations are allowed */
req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR;
/* All orientations are allowed, respecting user orientation lock setting */
req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER;
} else {
/* Fixed window and nothing specified. Get orientation from w/h of created window */
req = (w > h ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
@@ -1005,8 +1005,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
/* At least one orientation is allowed */
if (resizable) {
if (is_portrait_allowed && is_landscape_allowed) {
/* hint allows both landscape and portrait, promote to full sensor */
req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR;
/* hint allows both landscape and portrait, promote to full user */
req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER;
} else {
/* Use the only one allowed "orientation" */
req = (is_landscape_allowed ? orientation_landscape : orientation_portrait);
@@ -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 -3
View File
@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<style name="AppTheme" parent="android:Theme.NoTitleBar.Fullscreen">
<!-- Customize your theme here. -->
</style>
</resources>
+1 -5
View File
@@ -1,20 +1,16 @@
#cmakedefine PACKAGE "@PACKAGE@"
#define VERSION "2.11.1"
#define VERSION "@XSYSTEM35_VERSION@"
#cmakedefine CACHE_TOTALSIZE @CACHE_TOTALSIZE@
#cmakedefine ENABLE_DEBUGGER @ENABLE_DEBUGGER@
#cmakedefine ENABLE_GTK @ENABLE_GTK@
#cmakedefine ENABLE_MIDI_RAWMIDI @ENABLE_MIDI_RAWMIDI@
#cmakedefine ENABLE_MIDI_SDLMIXER @ENABLE_MIDI_SDLMIXER@
#cmakedefine ENABLE_MIDI_SEQMIDI @ENABLE_MIDI_SEQMIDI@
#cmakedefine ENABLE_MIDI_PORTMIDI @ENABLE_MIDI_PORTMIDI@
#cmakedefine ENABLE_NLS @ENABLE_NLS@
#cmakedefine DEFAULT_PLAYLIST_PATH "@DEFAULT_PLAYLIST_PATH@"
#cmakedefine JOY_DEVICE "@JOY_DEVICE@"
#cmakedefine MIDI_DEVICE "@MIDI_DEVICE@"
#cmakedefine SEQ_DEVICE "@SEQ_DEVICE@"
#cmakedefine HAVE_GETLOGIN @HAVE_GETLOGIN@
#cmakedefine HAVE_MMAP @HAVE_MMAP@
+42
View File
@@ -0,0 +1,42 @@
set(SOURCES
xsystem35.6.adoc
xsystem35.gr.5.adoc
)
find_program(ASCIIDOCTOR asciidoctor)
if (NOT ASCIIDOCTOR)
message(WARNING "asciidoctor not found, manpages will not be generated")
else()
if (WIN32)
set(BACKEND html)
else()
set(BACKEND manpage)
include(GNUInstallDirs)
endif()
set(MANUALS "")
foreach(SRC ${SOURCES})
string(REGEX MATCH "^(.*)\\.([0-9])\\.adoc$" _ ${SRC})
set(NAME ${CMAKE_MATCH_1})
set(SECTION ${CMAKE_MATCH_2})
if (WIN32)
set(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.html)
else()
set(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.${SECTION})
install(FILES ${OUTPUT} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${SECTION})
endif()
add_custom_command(
OUTPUT ${OUTPUT}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${SRC}
COMMAND ${ASCIIDOCTOR}
--attribute xsystem35-version=${XSYSTEM35_VERSION}
--backend ${BACKEND}
--out-file ${OUTPUT}
${CMAKE_CURRENT_SOURCE_DIR}/${SRC}
)
list(APPEND MANUALS ${OUTPUT})
endforeach()
add_custom_target(manual ALL DEPENDS ${MANUALS})
endif()
View File
-80
View File
@@ -1,80 +0,0 @@
ゲームリソースファイル(*.gr)の書き方
xsystem35ではゲームデータの置き場所をテキストファイルに保存しておき、
それをxsystem35に指定してやる事でデータの置き場所を知らせます。
# このファイルのファイル名はxsystem35を起動する時に指定できますので、hoge.gr
# である必要は無く、自由につける事が出来ます。
ここでは、このテキストファイル(ゲームリソースファイル)の書式を説明します。
1つのデータにつき1行で記述します。例を見て下さい。
ScenarioA /home/chikama/game/rance4/rance4_sa.ald
キーワード データのフルパス
の順に書きます。キーワードは行の先頭から書き、データのフルパスとの間は半角
スペースです。(セーブデータのみ、ホームディレクトリを表す ~ を評価します。)
キーワードには次の7つがあります。
Scenario : シナリオ
Graphics : グラフィック
Wave : PCMデータ
Midi : MIDIデータ
Data : その他データ
Save : セーブデータ
Resource : リソースファイル(マウスカーソル形状)
Ain : DLL とその関数の情報のかかれた System39.ain
BGM : BGMデータ(エスカレイヤー以降のBGMデータファイル)
WAI : PCMデータの追加情報 (mixer channel 情報等)
BGI : BGMデータの追加情報 (ループ位置等)
SACT01 : SACT.DLL用データ (SACTEFAM.KLD)
ALK : デモ用アーカイブファイル
Init : System39.ini
同じ種類のデータが複数ある場合はキーワードの次にA,B,C...をつけます。
(Ain を除く)
CD-ROM上のどれがどの種類のファイルかは、ファイル名で判別します。
*SA.ALD ならシナリオの1番目、*GA.ALDはグラフィック、*WA.ALDはPCM、
*MA.ALD はMIDI、*DA.ALDはその他データです。
Ain は System39.ain へのパスを書きます。例えば
Ain /home/chikama/game/20cKaeru/System39.ain
のように書きます。
Init は System39.ini へのパスを書きます。例えば
Init /home/chikama/game/esuka/System39.ini
のように書きます。
WAI/BGI は通常1ファイルだけですので
WAIA /home/chikama/game/esuka/DOKI_WA.WAI
BGIA /home/chikama/game/esuka/DOKI_BA.BGI
のように書きます。
SACT01 は SACTシステム固有のデータファイル(SACTEFAM.KLD)へのパスを
指定します。
SACT01 /home/chikama/game/rance5d/SACTEFAM.KLD
ALK はデモ用のデータが入ったアーカイブファイルです。
ALK01 /home/chikama/game/nd/NightDemonDemo1.alk
ALK02 /home/chikama/game/nd/NightDemonDemo2.alk
ALK03 /home/chikama/game/nd/NightDemonDemo3.alk
のように書きます。
また、これらの範疇にはいらないデータ、たとえば、かえるにょぱにょんの
floor_1.mapなどはリソースファイルを介しませんので、ゲームリソース
ファイルには書かず、「セーブデータを置いたディレクトリと同じ場所」に
コピーして下さい。
また、Save? のみ、'~' (ホームディレクトリ)を評価しますので、
SaveA ~/savedata/kichiku/kichiku_sa.ald
のように書く事が出来ます。
コメントを書く場合は行頭に # をつけます。また空白行は無視されます。
-314
View File
@@ -1,314 +0,0 @@
System 3.5 for X Window System Version 1.7 (開発版)
0. 目次
1. はじめに
2. 開発環境と動作確認環境
2.a. 開発環境
2.b. 動作確認環境
2.c. 多分動くと思われる環境
3. xystem35の設定ファイル
4. ゲームの実行と終了
4.a. ゲームの実行
4.b. ゲームの終了
4.c. xsystem35メニュー
4.d. キーボード操作
5. コマンドラインオプション
6. その他情報
6.a. SYSV IPC
6.b. SharedMemoryの大きさについて
6.c. locale と X
7. 著作権とライセンス
8. サポート
1. はじめに
このソフトは AliceSoft の Syetem3.5/3.6/3.8/3.9 上で動くゲームを
X Window System 上で動かすためのプログラムです。
* 動作確認ゲーム
鬼畜王ランス
ランス4 (for Win95)
闘神都市II (for Win95)
夢幻泡影 (for Win95)
かえるにょぱにょ〜ん (初版、廉価版)
いけないかつみ先生
戦巫女 (初版、廉価版)
零式 (館456版、廉価版)
ATLACH=NACHA (館456版、廉価版)
人間狩り
王道勇者
ディアボリカ (初版、廉価版)
AmbivalenZ(for Win95)
ぱすてるチャイム
ぷろすちゅーでんとGood
守り神様
ママトト
アリスの館456
DALK
闘神都市
DrStop!
ランス1
ランス2
ランス3
アリスCD Ver 1.02
メイドのすすめ
ぶろぶろ
学園漂流戦記
Hushaby Baby
Darcrows
PERSIOM
隠れ月
SeeIn青
20世紀アリス
これDPS
かえるにょ国にょアリス
アリスCD Ver 2.02
妖精
OnlyYou リ・クルス
王子さま Lv1.5
* 動かないゲーム
夜が来る!
王子さま Lv1
DALK外伝 (System4)
ままにょにょ (System4)
* 一部動作可能
大悪司 (オープニング不可)
妻みぐい (オープニング不可)
エスカレイヤー (オープニング不可)
Rance5D
妻みぐい2 (オープニング不可)
シェル・クレイル
NightDemon (オープニング不可)
各ゲームについての補足事項は doc/GAMES.TXT を御覧ください。
また、ネット上で公開されているSYSTEM3.5用のゲームのうち、いくつかは
動作が確認されています。くわしくは MISCGAME.TXT を御覧下さい。
2. 開発環境と動作確認環境
2.a. 開発環境
Kondara-1.2 (Linux/i386)
2.b. 動作確認環境
DigitalUnix 4.0F (alpha)
SunOS 5.8 (sparc)
2.c. 多分動くと思われる環境
Linux(!i386)
FreeBSD/NetBSD/OpenBSD (i386 etc)
Irix 6.X
Solaris 2.X 以降 (sparc/i386)
3. xystem35の設定ファイル
xsystem35ではフォントの設定などを、カレントディレクトリとホームディレクトリに
ある .xsys35rcというファイルから読み込みます。カレントディレクトリの .xsys35rc
に書かれた設定のほうが優先されるため、一般的な設定はホームディレクトリの
.xsys35rcに書き、特定のゲームで書き換えたい項目はゲームを置いたディレクトリの
.xsys35rcに書くといいでしょう。
サンプルとなるファイルを xsys35rc.sample として用意しました。
また、gtk widgetのリソースは ~/.gtk/gtkrc または ~/.gtkrc から読み込みます。
読み込み先は .xsys35rc で指定できます。
ゲームで使用するフォントは X のフォントの仕組を使う方法と、TrueTypeFontを
外部ライブラリを使って直接表示する方法の2種類が選べます。
~/.xsys35rc の ttfont_mincho: と ttfont_gothic: の場所にフォントファイルを
指定し、font_device: ttf と指定してください。詳しくはサンプルファイル
(xsys35rc.sample)を見て下さい。
4. ゲームの実行と終了
4.a. ゲームの実行
instgameを使ってゲームデータをインストールすると、インストールした
ディレクトリにの一つ上に ???????.gr というファイル(ゲームリソースファイル)
が自動的に作成されますので
% xsystem35 -gamefile ~/game/???????.gr
のように実行します。-gamefile オプションをつけない場合は、カレントディレク
トリの xsystem35.gr を参照します。
またいずれも見つからない場合は、カレントディレクトリにあるファイルをゲーム
データとして設定します。例えば testSA.ALD というファイルがカレントディレク
トリにあると、それをシナリオデータとして使います。またセーブデータは適当な
名前で 10個確保されます。
ゲームリソースファイルの書き方については、doc/GRFMT.TXT を御覧下さい。
4.b. ゲームの終了
* 起動した端末で Ctrl+C を押すと、すぐに終了します。
* ゲーム中にマウスの真中のボタンを押すと、メニューが出て来ますので、
そこから 'Exit' を選んで終了させて下さい。Window Manager のCloseボタンでも
同じように動作します。
* ESC + SPACE + RET キーを同時に押すと、すぐに終了します。
4.c. xsystem35メニュー
ゲーム中にマウスの真中ボタンを押すとメニューが出て来ます。
メッセージスキップ(MessageSkip):
次の選択肢までメッセージを飛ばします。マウスの右クリックで
止まります。シナリオによっては停止しない場合もあります。
マウスカーソル移動(MouseAutoMove):
選択ウィンドなどでマウスが自動的に移動するのを制御します。
ボリュームバランス(VolumeValance):
SACTシステムで音声の人物毎に音量を変えることができます。
(ゲームがそう出来るように対応している場合のみ)
情報(About):
このゲームについて。
終了(Exit):
ゲームを終了します。
4.d. キーボード操作
アリスソフトのゲームは有史来、基本的に上下左右キーに SPACE, RET, ESC, TAB
キーしか使いません(一部のゲームはそれ以外のキーを使うこともあります)。
XSystem35 では次のキー割当を特別に使っています。
F1: メッセージスキップ
F4: フルスクリーン <-> Window表示の切替え
また、旧き良き時代の DOS への復帰キー (ESC + SPACE + RET) でゲームを確認なし
で終了出来ます。
5. コマンドラインオプション
-h : ヘルプを表示します。
-gamefile file : ゲームリソースファイルを file から読み込みます。
-no-shm : ネットワーク越しに起動する場合に指定します。
-devcd name : CD-ROM device名を name にします。
-devmidi name : MIDI device名を name にします。
-M? : MIDI の出力の種類を選択します。
-Me : External midi player (default)
-Mr : Raw Midi device
-Ms? : Sequencer device (?:device number)
-M0 : disable midi
-devjoy n : n 番目の joystick のデバイスを使用します。
-version : バージョン情報を表示します。
-fullscreen : フルスクリーンでゲームを実行します。
SDL 有効時には Widget にフォーカスが当たらないため Popup
menu 等が使用できません。
-antialias : 常に文字にアンチエリアスをかけます。
-noantialias : 常に文字にアンチエリアスをかけません。シナリオ上でアンチ
エリアスの指定があっても無視します。
-devfont : フォントデバイスを指定します。x11/ft2/sdl のいずれかが
使えます。
-noimagecursor : リソースファイルによるカーソル形状の変更(Darcrows等)を無効
にしたい場合に指定します。
6. その他情報
6.a. SYSV IPC
カーネルに SYSV IPC (SharedMemory/MessageQueue/Semaphore)の機能が
組み込まれている必要があります。
6.b. SharedMemoryの大きさについて
カーネルのSharedMemoryの大きさが十分大きい場合、MIT-SHMを利用して画面を
高速に描画する事が出来ます。起動時にエラーが出る場合、カーネルパラメータを
変更してみて下さい。(BSD 系はデフォルトの SharedMemory の大きさが小さい
ようです)
6.b.1. FreeBSDの場合 /usr/src/sys/i386/conf/LINT 中の
options SHMALL=1025
options "SHMMAX=(SHMMAXPGS*PAGE_SIZE+1)"
options SHMMAXPGS=1025
options SHMMIN=2
options SHMMNI=33
options SHMSEG=9
「SHMMAXPGS」が関連項目です。
24bppで起動する場合は SHMMAXPGS=4096 くらいにするとよいようです。
もちろん設定後はカーネルの再構築が必要です。
6.c. locale と X
libc に locale 機構が組み込まれていない環境の場合、libxpg4 などの
ライブラリ(FreeBSD) や X の locale を使うことになります。
linux の libc5 な環境では configure 時に --with-locale=ja_JP.ujis として
コンパイルしてください。
それ以外のほとんどの環境では考慮する必要はないでしょう。
7. 著作権とライセンス
プログラムの著作権は作者(chikama)に属しますが、ソースコードはGPLに基づいて
再配付できます。
(一部のソースコードは私以外に著作権があります。詳しくは、ソースコードを御覧
下さい)
ゲーム内で使われてるカーソルフォントの一部をqvwm(Windows95そっくりのWindow
Manager)からいただきました。
8. サポート
動作報告・バグ報告などは以下のメールアドレスまでお願いします。
E-Mail: chikama@nabal.aist-nara.ac.jp (private)
masaki-c@is.aist-nara.ac.jp (official)
また最新版は以下のURLからダウンロードできます。
http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/index.html
バグレポートの際は、お使いの環境を出来るだけくわしく書いて下さい。
また特定のゲームで動かない場合は、出来るだけセーブデータも添付して下さい。
プログラムやシナリオデータのバグで 'sigsegv caught @xxx,xxxxx' といって
終了する場合は、そのメッセージの部分(xxx,xxxx)も送って下さい。
可能ならば、./configure で --enable-debug を付けてコンパイルしておき、
デバッガ上で実行して segmentation fault で止まった時に、bt と打って出てくる
メッセージを添付していただけるととても助かります。
-307
View File
@@ -1,307 +0,0 @@
xsystem35 における音楽環境について
0. もくじ
1. MIDIについて
a) 外部プレーヤーを使う方法
1) xsystem35 側の準備
2) プレイヤーの準備
3) xsystem35へのリダイレクト
4) 制限事項
b) 外部 MIDI 音源を /dev/midi 経由で制御する方法
1) xsystem35 側の準備
2) 外部 MIDI 音源の準備
c) Synthesizer 音源を /dev/sequencer 経由で制御する方法
1) xsystem35 側の準備
2) Synthesizer 音源の準備
d) オプション一覧
2. 効果音(WAV)について
a) OSS 出力
b) ALSA 出力
c) ESD 出力
3. CDオーディオについて
a) CD-ROM コントロールによる演奏
b) 外部プレイヤ(mp3など)による演奏
4. PCM & MIDI(timidity) & CD-ROM(MP3) を1枚のサウンドカードで同時に使う方法
1. MIDIについて
xsystem35 では MIDI の演奏に外部プレーヤーを使う方法と、サウンドカードの
MIDI port を介して接続した外部 MIDI 機器を /dev/midi 経由で制御する方法、
さらに、synthesizer device を OSS sequencer (/dev/sequencer) 経由で制御する
方法の3種類が選択できます。
a) 外部プレーヤーを使う方法
1) xsystem35 側の準備
xsystem35 の configure 実行時に --enable-midi=extp を付けてコンパイル
しておきます。
2) プレイヤーの準備
TiMidity や playmidi など、お好みのプレーヤーをお使いください。
プレイヤーへはあらかじめパスを通しておき、~/.xsys35rc にプレイヤーと
プレイヤーへの引数を記述します。
(例) TiMidity を esd 経由で出力する場合
midi_player: timidity -A 100 -s 44100 -Oe
2a) xsystem35へのリダイレクト (オプション)
TiMidity を使っている場合、TiMidity の PCM 出力を xsystem35 へとリダ
イレクトして xsystem35 側で管理しているPCM デバイスに流す事が出来ます。
~/.xsys35rc の MIDI プレーヤーの設定の際に先頭に '-' をつけて下さい。
(例)
midi_player: -timidity -A 100 -s 44100 -Or -o-
この場合 timidity の出力は 44.1kHz, Stereo, 16bit 固定です。
3) 制限事項
外部プレイヤーを 使用する場合、MIDIファイルに埋め込まれた system35 用の
制御コマンドを実行することができず、リピート再生、ジャンプ再生などが出来
ません。このため、ゲームの進行に支障が出ることがあります。
b) 外部 MIDI 音源を /dev/midi 経由で制御する方法
1) xsystem35 側の準備
xsystem35 の configure 実行時に --enable-midi=raw を付けてコンパイル
しておきます。
2) 外部 MIDI 音源の準備
外部 MIDI 音源(SC-88など)をサウンドカード の MIDI port を介して接続
します。このポートは /dev/midi デバイスを介して制御できる必要があります。
ALSA OSS Emulation 上で SB-Live の MIDI 端子に接続した SC-88 での動作を
確認しています。
c) Synthesizer 音源を /dev/sequencer 経由で制御する方法
1) xsystem35 側の準備
xsystem35 の configure 実行時に --enable-midi=seq を付けてコンパイル
しておきます。
2) Synthesizer 音源の準備
外部 MIDI 機器を接続するか、サウンドカード上に soundfont を load するか
TiMidity を ALSA sequencer server として常駐させておいてください。
TiMidity を ALSA sequencer server にするには、コンパイル時にその機能を
有効にしておき、timidity -iA で常駐させます。
d) オプション一覧
MIDI 出力に関する、 .xsys35rc の設定項目(A)とコマンドラインオプション(B)
をまとめます。
1) MIDI プレイヤーの設定
(A) ----> midi_player:
(B) ----> -midiplayer
2) MIDI デバイスファイルの設定 (default: /dev/midi or /dev/sequencer)
(A) ----> midi_device:
(B) ----> -devmidi
3) MIDI 出力方法の選択 (default: e)
(A) ----> midi_output_device: ?
(B) ----> -M?
? .... e : 外部プレーヤ
r : midi device 経由
sX: sequencer device 経由 (X番目のポート)
0 : (ゼロ) 無効化
コンパイル時に --enable-midi=extp,raw,seq とすることで、複数の方式を有効
にし、実行時にいずれかを選択できます。その他のコンパイルオプションは
INSTALL ドキュメントを御覧ください。
sequencer device の X 番目のポートは通常、0 ですが、複数のポートがある
場合はそのポート番号を指定してください。ALSA の OSS emu では、
$ cat /proc/asound/seq/oss
と実行して出て来る
midi ?: [xxxx] ALSA port aa:bb
の ? の番号を指定します。
コマンドラインから外部MIDIプレイヤーを指定する場合は
-midiplayer "timidity -A 100 -s 44100 -Oe" のようにします。
2. 効果音(WAV)について
xsystem35ではオーディオインターフェイスとして、Linux/*BSD などで良く使われて
いる OSS およびその互換インターフェイスに加えて、ALSA(Advanced Linux Sound
Architecture) と ESD(Enligtened Sound Daemon)に対応しています。
a) OSS 出力
1) コンパイル
configure 時に --enable-audio=oss オプションを付けてコンパイルします。
2) 実行時オプション
コマンドライン: -Oo
.xsys35rc : audio_output_device: o
3) dsp デバイス (default: /dev/dsp)
コマンドライン: -devdsp
.xsys35rc : dsp_device:
4) mixer デバイス (default: /dev/mixer)
コマンドライン: -devmix
.xsys35rc : mixer_device:
b) ALSA 出力
1) コンパイル
configure 時に --enable-audio=alsa オプションを付けてコンパイルします。
2) 実行時オプション
コマンドライン: -Os
.xsys35rc : audio_output_device: s
3) dsp デバイス (default: 0:0)
コマンドライン: -devdsp
.xsys35rc : dsp_device:
c) ESD 出力
1) コンパイル
configure 時に --enable-audio=esd オプションを付けてコンパイルします。
2) 実行時オプション
コマンドライン: -Oe
.xsys35rc : audio_output_device: e
OSS/ALSA/ESD をすべて有効にしてコンパイルし、実行時にどの出力を使用するか
選択できます。configure 時に --enable-audio=oss,alsa,esd としてコンパイル
してください。
3. CDオーディオについて
CD-ROM の制御には Linux/FreeBSD/Irix のインターフェイスに対応しています。
また、CD-ROM デバイスを直接制御する他に、外部プレイヤを使って mp3 file など
を鳴らすことも出来ます。
a) CD-ROM コントロールによる演奏
環境によって自動的に適切なドライブが選択されコンパイルされます。
b) 外部プレイヤ(mp3など)による演奏
あらかじめ CD を MP3/WAV 化して起きます。また mpg123 などのプレイヤ
を用意し、パスを通しておきます。
1) コンパイル
configure 時に --enable-cdrom=mp3 オプションを追加します。CD-ROM
コントロールを実行時に使い分けたい時は --enable-cdrom=linux,mp3 などと
します。
3) プレイヤー名とファイルリストを書いた次のようなファイルを用意します。
% cat /game/kichiku.playlist
mpg123-esd -quite
/game/kichiku/mp3/trk02.mp3
/game/kichiku/mp3/trk03.mp3
/game/kichiku/mp3/trk04.mp3
/game/kichiku/mp3/trk05.mp3
/game/kichiku/mp3/trk06.mp3
というようなファイルを用意します。
1行目はプレーヤーとそのオプション
2行目以降はトラック2から順にファイルをならべます。(フルパスで指定します)
*) 適切に外部プレイヤーと演奏ファイルを用意すれば、データ形式は問いません。
3a) xsystem35 へのリダイレクト(オプション)
mpg123 などのプレイヤーのPCM 出力を xsystem35 へとリダイレクトして
xsystem35 側で管理しているPCM デバイスに流す事が出来ます。
上の kichiku.playlist ファイルのプレイヤの設定で先頭に '-' をつけて
ください。
(例)
-mpg123 -q -s
この場合 mpg123 の出力は 44.1kHz, Stereo, 16bit 固定です。
4) 実行時オプションに -devcd /game/kichiku.playlist と上で作成したファイル
を指定します。
CD-ROM に関する .xsys35rc の設定項目(A) と コマンドラインオプション(B) を
まとめます。
1) CD 出力方法の選択
(A) ----> cdrom_device: ???
(B) ----> -devcd ????
MP3 出力 => ???? にプレイリストを指定
CD-ROM => ???? にデバイスファイルを指定
2) CD-ROM デバイスファイルの設定 (defult /dev/cdrom)
(A) ----> cdrom_device: ???
(B) ----> -devcd: ????
4. PCM & MIDI(timidity) & CD-ROM(MP3) を1枚のサウンドカードで同時に使う方法
(special thanks to Fumihiko Murata)
サウンドカードを選ばない方法としては esd を使うことです。esd は対応した複数
のプログラムの音の出力を合成してサウンドカードに出力するプログラムです。
xsystem35/timidity/mp3 player を esd 対応にコンパイルすることで合成が可能
です。
また、Trident 4DWave DX/NX、SoundBlaster Live/ YAMAHA YMF724以降 などのサウ
ンドカードは PCM チャンネルを複数持っていて、対応のサウンドドライバーがあれば
PCMとMIDI(SoftwareMIDI)とMP3 を同時に鳴らすことが出来ます。たとえば
SoundBlaster Live + ALSA では
$ cat /proc/asound/pcm
00-00: emu10k1 : EMU10K1 : playback 32 : capture 1
00-01: emu10k1 mic : EMU10K1 MIC : capture 1
00-02: emu10k1 efx : EMU10K1 EFX : capture 1
のように PCM を 32 チャンネル持っていることが分かります。これは OSS でいうと
ころの /dev/dspN に最大 32 の PCM がぶら下がっているように見え、同時に 32 回
/dev/dspN を開くことが出来ます。
また Trident 4DWave DX/NX + ALSA では全部で64chあり、最大で32chを PCM playback
に割り当てる事ができます。最大チャンネルはモジュールロード時に 設定され、設定
数を使いきるまで同時に /dev/dspN を開く事ができます。
残りの 32ch は MIDI 用に設けられていて、PCM と MIDI の2つのバンクに分ける事
ができます。個々のチャンネルには PCM front volume がありますが、2つのバンク
をそれぞれ統括する Wave/Music Volume があり さらにそれらを合わせる PCM volume
があります。(最後に Master Volume)
図にすると次のようになります。
PCM Volume + - Wave Volume + - front volume- PCM Playback 0
| + - .. - PCM Playback 1
| :
| + - .. - PCM Playback 31
|
+ - Music Volume + - .. - PCM Playback 32
:
+ - .. - PCM Playback 63
ES1370/1371 でも PCM 用 と MIDI 用に 2 チャンネルの PCM 出力があります。
ALSA では
$ cat /proc/asound/pcm
00-00: ES1371/1 : ES1371 DAC2/ADC : playback 1 : capture 1
00-01: ES1371/2 : ES1371 DAC1 : playback 1
のように 0:0 と 0:1 のデバイスが再生用として使う事が出来ます。timidity 用に
0:1 のデバイスを使うと良いでしょう。OSS では /dev/dsp0 と /dev/dsp1 に割り当
てられ、 /dev/dsp1 を timidity で使います。
またその他のカードでも多チャンネル出力を持っているものもありますので、
ドライバーのドキュメントを御覧下さい。
(2003.1.23 追記)
追記を書いている時点で手に入りやすい多チャンネルPCM出力をもつ音源カード
としては SoundBlaster Live と YMF7xx くらいでしょうか。
-57
View File
@@ -1,57 +0,0 @@
TODO (順番は特に無し)
* メンテナンス
-- obsolete
* TODOを増やさない
* SYSTEM3の3.5への移植ものや、ネット上にあるSYSTEM3.5のデータへの対応
* system 3.9への対応
* Xのイベントハンドリングの改良
* oringinal の savedata(v1/v2/v3?) を convert する tool
* savedata を lt/bg でどっちでも読めるようにする
* XIM 対応?
* 関数/変数名の統一
* 技術情報のドキュメント化
* GUI付 installer (っていうか、CD-ROMの中の setup.infを直接使う)
* 異常終了時に出来るだけプロセスが残らないようにする
* global変数を減らす
* 意図的な異常シナリオデータでもsegv.らないよう努力する
* Tab/Spaceの混在などソースの見直し(随時)
* CEの残りのコマンドをさっさと実装する
* SDL を理解して cleanup
* キー入力まわりの cleanup
* UNIX+X 以外の環境へ移植しやすくする
* 王子様1/16
+ スケジュールを組む時に「もどる」「クリア」「OK!」の選択がうまくで
きない。
* ランス4
+ プチハニーの爆風に巻き込まれると、キャラの上に「防」マークがつきっぱ
なしになる。
+ 戦闘シーンでたまに左上にモンスターのかけらが表示されることがある。
DONE
* configure 化
* gtk_setup.c rewrite
* keyboard操作対応
* cd/mp3の切替えをオプションで切替えられるようにする
* packed 24bpp対応 (rewrite xcore.c)
* music server cleanup
* dri mmap化
* 汎用 data cache 処理を作る。TTF フォントと展開済み CG で使おうか。
* alphabelnd asm化
* imgae.c をもうちょっとすっきりと。(depthで関数のテーブル化
* ecopy のタイミングの最適化
* wav が鳴らない事がしばしばある(open err)のを調査&修正
* *.h の依存関係 cleanup, 特に xsystem35.h
* xcore/imageの統合とcleanup
* MIDIの自前のハンドリング(/dev/sequener ?)
* FullScreen対応(with DGA)
* 古いドキュメントをなんとかする。(FAQ/BUGS etc)
* 大悪司
+ SDLの時、MAP選択が正常に動かない。
+141
View File
@@ -0,0 +1,141 @@
= xsystem35(6)
:doctype: manpage
:manmanual: xsystem35 manual
:mansource: xsystem35 {xsystem35-version}
== Name
xsystem35 - play System 3.x games
== SYNOPSIS
*xsystem35* [_OPTION_]...
== DESCRIPTION
This man page describes *xsystem35-sdl2*, a multi-platform port of the
AliceSoft's System3.5/3.6/3.8/3.9 game engine derived from the original
*xsystem35*.
`xsystem35` reads the game resource file from the path specified by the
`-gamefile` option, or from `xsystem35.gr` in the current directory if the
option is not specified. If the game resource file is not found, `xsystem35`
finds System 3.x game files (*.ALD) from the current directory.
== OPTIONS
*-gamefile* _file_::
Load game resouce file from _file_. See <<FILES>> section for details.
*-game* _game_::
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`.
*-savedir* _dir_::
Directory to save game state files. If _dir_ begins with '~', it is expanded
to the user's home directory (`$HOME`).
*-saveformat* _fmt_::
The format when writing save files. Possible values are: `xsystem35`,
`system36`, `system39` (default).
*-renderer* _name_::
Use the SDL rendering driver named _name_.
*-playlist* _file_::
Load the CD playlist from _file_. The playlist is a text file with one
filename per line, in the order of CD tracks. See <<FILES>> section for details.
*-Me*::
Use SDL_mixer for MIDI playback.
**-Mp**_device_number_::
Use ALSA (via PortMidi) for MIDI playback.
*-M0*::
Disable MIDI playback.
*-devjoy* _device_index_::
Use the joystick device with the given index.
*-ttfont_mincho* _file_::
Use the given TrueType or OpenType font file for mincho (serif) text.
*-ttfont_gothic* _file_::
Use the given TrueType or OpenType font file for gothic (sans-serif) text.
*-debuglv* _level_::
Set the debug level to _level_. The higher the level, the more verbose
the debug output.
*-debug*::
Start with the debugger enabled.
*-noantialias*::
Disable text antialiasing.
*-fullscreen*::
Start in fullscreen mode.
*-integerscale*::
Use integer scaling for the window.
*-noimagecursor*::
Disable custom mouse cursor images.
*-version*::
Print the version number and exit.
*-h, --help*::
Print a help message and exit.
== FILES
*.xsys35rc*::
`xsystem35` reads its configuration from `${HOME}/.xsys35rc` and `.xsys35rc`
in the game directory. The latter takes precedence over the former, so you
can put general settings in `${HOME}/.xsys35rc` and game-specific settings in
`.xsys35rc` in the game directory. Options specified on the command line
override both. See xsys35rc.sample for the format of the configuration file.
*playlist.txt*::
`xsystem35` does not support playing BGM directly from a CD. Instead, it
supports playing BGM from audio files on your filesystem. `xsystem35` reads
the playlist from a file specified by the `-playlist` option, or from
`playlist.txt` in the game directory. The first line is the path to the audio
file for track 1, the second line is the path to the audio file for track 2,
and so on. The first line is usually empty, because track 1 is not an audio
track but a data track.
*xsystem35.gr*::
Game resource file which lists the locations of various files needed to run
a game. This is optional; `xsystem35` can automatically find the files it
needs when run inside a game directory. See
xref:xsystem35.gr.adoc[*xsystem35.gr(5)*] for the format of the game resource
file.
== KEYBOARD SHORTCUTS
System 3.x games basically only use the UP, DOWN, LEFT, RIGHT, SPACE, RET, ESC,
and TAB keys (some games use other keys). `xsystem35` uses the following
special key assignments:
*F1*::
Toggle message skip mode.
*F4*::
Toggle fullscreen mode.
Also, in some platforms, the middle mouse button opens the menu.
== HISTORY
*xsystem35* was originally developed by Masaki Chikama (Wren)
<masaki-c@is.aist-nara.ac.jp> between 1998 and 2006. The project was later
forked by Kichikuou <KichikuouChrome@gmail.com> as *xsystem35-sdl2* and ported
to SDL2.
== SEE ALSO
xsystem35-sdl2 project page: https://github.com/kichikuou/xsystem35-sdl2
+103
View File
@@ -0,0 +1,103 @@
= xsystem35.gr(5)
:doctype: manpage
:manmanual: xsystem35 manual
:mansource: xsystem35 {xsystem35-version}
== Name
xsystem35.gr - game resource file for xsystem35
== DESCRIPTION
Game resource file is a plain text file that defines the locations of the
various game data files for xsystem35. This file is only needed if you want to
place game data files in a location other than the current directory.
The path to the game resource file is specified with the `-gamefile` option of
xref:xsystem35.adoc[*xsystem35(6)*]. If it is not specified, xsystem35 reads
`xsystem35.gr` in the current directory.
Each line of the file specifies a single data file and follows the format:
_keyword_ _path-to-data_
If multiple files of the same type exist, suffixes `A`, `B`, `C`... are
appended to the _keyword_.
Comments can be added by starting the line with `#`. Blank lines are ignored.
== KEYWORDS
*Scenario*::
Scenario files (`*S?.ALD`).
*Graphics*::
Graphic files (`*G?.ALD`).
*Wave*::
PCM data files (`*W?.ALD`).
*Midi*::
MIDI data files (`*M?.ALD`).
*Data*::
Miscellaneous data files (`*D?.ALD`).
*Resource*::
Resource files (`*R?.ALD`).
*BGM*::
BGM files (`*B?.ALD`).
*Save*::
Save files (`*S?.ASD`). If the path begins with '`~`', it is expanded to the
user's home directory (`$HOME`).
*Ain*::
The `System39.ain` file.
*WAI*::
Additional information for PCM data (`*WA.WAI`)
*BGI*::
Additional information for BGM data (`*BA.BGI`)
*SACT01*::
Data for SACT.DLL (`SACTEFAM.KLD`)
*ALK01* - *ALK09*::
Archive files for demo data (`*1.ALK` - `*9.ALK`)
*Init*::
The `System39.ini` file.
== NOTES
Data files not categorized under the above keywords (e.g., map files for
Kaeru nyo Panyon) should not be listed in the game resource file, and should be
placed in the same directory as the save files.
== EXAMPLES
The following is a game resource file for the English translation of Kichikuou
Rance.
ScenarioA KICHIKUSA.ALD
GraphicsA KICHIKUGA.ALD
GraphicsB KICHIKUGB.ALD
WaveA KICHIKUWA.ALD
Ain System39.ain
SaveA ~/.xsys35/saves/kichikuou/KICHIKUSA.ASD
SaveB ~/.xsys35/saves/kichikuou/KICHIKUSB.ASD
SaveC ~/.xsys35/saves/kichikuou/KICHIKUSC.ASD
SaveD ~/.xsys35/saves/kichikuou/KICHIKUSD.ASD
SaveE ~/.xsys35/saves/kichikuou/KICHIKUSE.ASD
SaveF ~/.xsys35/saves/kichikuou/KICHIKUSF.ASD
SaveG ~/.xsys35/saves/kichikuou/KICHIKUSG.ASD
SaveH ~/.xsys35/saves/kichikuou/KICHIKUSH.ASD
SaveI ~/.xsys35/saves/kichikuou/KICHIKUSI.ASD
SaveJ ~/.xsys35/saves/kichikuou/KICHIKUSJ.ASD
== SEE ALSO
xref:xsystem35.adoc[*xsystem35(6)*]
+3 -3
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 |
+1 -1
View File
@@ -58,7 +58,7 @@ int nt_sp_eupdate(int no, int time, int cancel) {
int edtime = curtime + time;
while ((curtime = sdl_getTicks()) < edtime) {
sdl_effect_step(eff, (double)(curtime - sttime) / (edtime - sttime));
sdl_effect_step(eff, (float)(curtime - sttime) / (edtime - sttime));
int rest = 16 - (sdl_getTicks() - curtime);
int key = sys_keywait(rest, cancel ? KEYWAIT_CANCELABLE : KEYWAIT_NONCANCELABLE);
if (cancel && key)
+10 -8
View File
@@ -39,10 +39,12 @@
#include "sdl_core.h"
#include "randMT.h"
typedef void entrypoint (double step, int p1, int p2, int *retx, int *rety);
#define M_PIf ((float)M_PI)
typedef void entrypoint (float step, int p1, int p2, int *retx, int *rety);
// 上下左右方向の揺らし
static void quake0(double step, int ampx, int ampy, int *adjx, int *adjy) {
static void quake0(float step, int ampx, int ampy, int *adjx, int *adjy) {
static int i = 0;
*adjx = (int)(genrand() * ampx/2);
@@ -53,12 +55,12 @@ static void quake0(double step, int ampx, int ampy, int *adjx, int *adjy) {
}
// 回転の揺らし
static void quake1(double curstep, int diam, int round, int *adjx, int *adjy) {
double R = (1 - curstep) * diam / 2;
double th = curstep * 2 * M_PI * round;
static void quake1(float curstep, int diam, int round, int *adjx, int *adjy) {
float R = (1 - curstep) * diam / 2;
float th = curstep * 2 * M_PIf * round;
*adjx = (int)(R * cos(th));
*adjy = (int)(R * sin(th));
*adjx = (int)(R * cosf(th));
*adjy = (int)(R * sinf(th));
}
/*
@@ -83,7 +85,7 @@ int sp_quake_screen(int type, int p1, int p2, int time, int cancel) {
while ((curtime = sdl_getTicks()) < edtime) {
int adjx, adjy;
cb[type]((double)(curtime - sttime)/(edtime - sttime), p1, p2, &adjx, &adjy);
cb[type]((float)(curtime - sttime)/(edtime - sttime), p1, p2, &adjx, &adjy);
ags_setViewArea(adjx, adjy, sf0->width, sf0->height);
ags_updateFull();
+1 -1
View File
@@ -59,7 +59,7 @@ int sp_eupdate(int type, int time, int cancel) {
int edtime = curtime + time * 10;
while ((curtime = sdl_getTicks()) < edtime) {
sdl_effect_step(eff, (double)(curtime - sttime) / (edtime - sttime));
sdl_effect_step(eff, (float)(curtime - sttime) / (edtime - sttime));
int rest = 16 - (sdl_getTicks() - curtime);
int key = sys_keywait(rest, cancel ? KEYWAIT_CANCELABLE : KEYWAIT_NONCANCELABLE);
if (cancel && key)
+1 -1
View File
@@ -129,7 +129,7 @@ void spev_move_setup(void* data, void* userdata) {
// speed から timeへ
int dx = sp->move.to.x - sp->loc.x;
int dy = sp->move.to.y - sp->loc.y;
int d = (int)sqrt(dx*dx+dy*dy);
int d = (int)sqrtf(dx*dx+dy*dy);
sp->move.time = d * 100 / sp->move.speed;
}
+15 -13
View File
@@ -112,11 +112,8 @@ 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)
target_sources(xsystem35 PRIVATE midi.portmidi.c midifile.c)
endif()
endif()
@@ -158,15 +155,20 @@ 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
-sMODULARIZE=1
-sEXPORT_ES6=1
-sASYNCIFY=1
-sASYNCIFY_IGNORE_INDIRECT=1
-sASYNCIFY_REMOVE=SDL_Delay
-sASYNCIFY_IMPORTS=wait_vsync
-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=FS,IDBFS,getValue,addRunDependency,removeRunDependency
--emit-tsd=xsystem35.d.ts
)
elseif (ANDROID)
target_link_libraries(xsystem35 PRIVATE ${ndk_log})
+17 -28
View File
@@ -370,15 +370,6 @@ void ags_putRegion(void *region, int x, int y) {
sdl_putRegion(region, x, y);
}
void ags_copyRegion(void *region, int sx, int sy , int w, int h, int dx, int dy) {
if (region == NULL) return;
if (!ags_check_param_xy(&dx, &dy)) return;
if (!ags_check_param(&dx, &dy, &w, &h)) return;
sdl_CopyRegion(region, sx, sy, w, h, dx, dy);
}
void ags_delRegion(void *region) {
if (region == NULL) return;
@@ -552,7 +543,7 @@ void ags_runEffect(int duration_ms, boolean cancelable, ags_EffectStepFunc step,
unsigned wflags = cancelable ? KEYWAIT_CANCELABLE : KEYWAIT_NONCANCELABLE;
int start = sdl_getTicks();
for (int t = 0; t < duration_ms; t = sdl_getTicks() - start) {
step(arg, (double)t / duration_ms);
step(arg, (float)t / duration_ms);
int key = sys_keywait(start + t + 16 - sdl_getTicks(), wflags);
if (cancelable && key) {
nact->waitcancel_key = key;
@@ -575,27 +566,26 @@ static void fade(int duration, boolean cancelable, enum sdl_effect_type type) {
}
void ags_fadeIn(int rate, boolean flag) {
int duration = rate * 16 * 1000 / 60;
if (!need_update)
duration = 0;
fade_outed = FALSE;
if (nact->ags.world_depth == 8)
sdl_setPalette(nact->ags.pal, 0, 256);
if (!need_update)
return;
int duration = rate * 16 * 1000 / 60;
fade(duration, flag, nact->ags.world_depth == 8 ? EFFECT_FADEIN : EFFECT_DITHERING_FADEIN);
sdl_updateAll(&nact->ags.view_area);
}
void ags_fadeOut(int rate, boolean flag) {
int duration = rate * 16 * 1000 / 60;
if (!need_update || fade_outed)
duration = 0;
if (need_update && !fade_outed) {
int duration = rate * 16 * 1000 / 60;
fade(duration, flag, nact->ags.world_depth == 8 ? EFFECT_FADEOUT : EFFECT_DITHERING_FADEOUT);
}
fade_outed = TRUE;
fade(duration, flag, nact->ags.world_depth == 8 ? EFFECT_FADEOUT : EFFECT_DITHERING_FADEOUT);
if (nact->ags.world_depth == 8) {
Color pal[256];
memset(&pal, 0, sizeof(pal));
@@ -604,27 +594,26 @@ void ags_fadeOut(int rate, boolean flag) {
}
void ags_whiteIn(int rate, boolean flag) {
int duration = rate * 16 * 1000 / 60;
if (!need_update)
duration = 0;
fade_outed = FALSE;
if (nact->ags.world_depth == 8)
sdl_setPalette(nact->ags.pal, 0, 256);
if (!need_update)
return;
int duration = rate * 16 * 1000 / 60;
fade(duration, flag, nact->ags.world_depth == 8 ? EFFECT_WHITEIN : EFFECT_DITHERING_WHITEIN);
sdl_updateAll(&nact->ags.view_area);
}
void ags_whiteOut(int rate, boolean flag) {
int duration = rate * 16 * 1000 / 60;
if (!need_update || fade_outed)
duration = 0;
if (need_update && !fade_outed) {
int duration = rate * 16 * 1000 / 60;
fade(duration, flag, nact->ags.world_depth == 8 ? EFFECT_WHITEIN : EFFECT_DITHERING_WHITEOUT);
}
fade_outed = TRUE;
fade(duration, flag, nact->ags.world_depth == 8 ? EFFECT_WHITEIN : EFFECT_DITHERING_WHITEOUT);
if (nact->ags.world_depth == 8) {
Color pal[256];
memset(&pal, 255, sizeof(pal));
+3 -3
View File
@@ -167,7 +167,6 @@ extern void ags_changeColorArea(int x, int y, int w, int h, int dst, int src, in
extern void* ags_saveRegion(int x, int y, int w, int h);
extern void ags_restoreRegion(void *region, int x, int y);
extern void ags_putRegion(void *region, int x, int y);
extern void ags_copyRegion(void *region, int sx, int sy, int w,int h,int dx,int dy);
extern void ags_delRegion(void *region);
extern MyRectangle ags_drawString(int x, int y, const char *src, int col);
@@ -178,7 +177,8 @@ extern void ags_copyArea_transparent(int sx, int sy, int w, int h, int dx, int d
extern void ags_copyArea_alphaLevel(int sx, int sy, int w, int h, int dx, int dy, int lv);
extern void ags_copyArea_alphaBlend(int sx, int sy, int w, int h, int dx, int dy, int lv);
extern MyRectangle ags_floodFill(int x, int y, int col);
extern void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int type, int opt, boolean flg, int spCol);
extern void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt, bool cancel);
extern void ags_eSpriteCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt, bool cancel, int spCol);
/* alpha channel 操作 */
extern void ags_copyFromAlpha(int sx, int sy, int w, int h, int dx, int dy, ALPHA_DIB_COPY_TYPE flg);
@@ -217,7 +217,7 @@ extern void ags_setAntialiasedStringMode(boolean mode);
extern boolean ags_getAntialiasedStringMode();
extern void ags_autorepeat(boolean enable);
typedef void (*ags_EffectStepFunc)(void *, double);
typedef void (*ags_EffectStepFunc)(void *, float);
void ags_runEffect(int duration_ms, boolean cancelable, ags_EffectStepFunc step, void *arg);
#define RMASK16 0xf800
-12
View File
@@ -1,12 +0,0 @@
#define curbm0_width 32
#define curbm0_height 32
static char curbm0_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x48,0x00,0x00,0x00,
0x88,0x00,0x00,0x00,0x08,0x01,0x00,0x00,0x08,0x02,0x00,0x00,0x08,0x04,0x00,
0x00,0x08,0x08,0x00,0x00,0x08,0x10,0x00,0x00,0x08,0x3e,0x00,0x00,0x48,0x02,
0x00,0x00,0xa8,0x04,0x00,0x00,0x98,0x04,0x00,0x00,0x08,0x09,0x00,0x00,0x00,
0x09,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x0c,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-12
View File
@@ -1,12 +0,0 @@
#define curbm1_width 32
#define curbm1_height 32
static char curbm1_bits[] = {
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xf3,0x9f,0xff,0xff,0xf5,0x5f,0xff,0xff,0xf6,0xdf,0xfe,
0x7f,0x07,0xc0,0xfd,0xbf,0xff,0xff,0xfb,0x7f,0x07,0xc0,0xfd,0xff,0xf6,0xdf,
0xfe,0xff,0xf5,0x5f,0xff,0xff,0xf3,0x9f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
-12
View File
@@ -1,12 +0,0 @@
#define curbm2_width 32
#define curbm2_height 32
static char curbm2_bits[] = {
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xbf,0xfe,0xff,0xff,0xdf,0xfd,0xff,0xff,0xef,0xfb,0xff,0xff,
0xf7,0xf7,0xff,0xff,0x87,0xf0,0xff,0xff,0xbf,0xfe,0xff,0xff,0xbf,0xfe,0xff,
0xff,0xbf,0xfe,0xff,0xff,0xbf,0xfe,0xff,0xff,0xbf,0xfe,0xff,0xff,0xbf,0xfe,
0xff,0xff,0xbf,0xfe,0xff,0xff,0xbf,0xfe,0xff,0xff,0x87,0xf0,0xff,0xff,0xf7,
0xf7,0xff,0xff,0xef,0xfb,0xff,0xff,0xdf,0xfd,0xff,0xff,0xbf,0xfe,0xff,0xff,
0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
-12
View File
@@ -1,12 +0,0 @@
#define curbm3_width 32
#define curbm3_height 32
static char curbm3_bits[] = {
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0xff,0xff,0xff,0x7d,0xff,0xff,0xff,
0xbd,0xff,0xff,0xff,0xdd,0xff,0xff,0xff,0xad,0xff,0xff,0xff,0x55,0xff,0xff,
0xff,0xb9,0xfe,0xff,0xff,0x7f,0xfd,0xff,0xff,0xff,0x3a,0xff,0xff,0xff,0x55,
0xff,0xff,0xff,0x6b,0xff,0xff,0xff,0x77,0xff,0xff,0xff,0x7b,0xff,0xff,0xff,
0x7d,0xff,0xff,0xff,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
-12
View File
@@ -1,12 +0,0 @@
#define curbm4_width 32
#define curbm4_height 32
static char curbm4_bits[] = {
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0xff,0xff,0xff,0xbe,0xff,0xff,
0xff,0xbd,0xff,0xff,0xff,0xbb,0xff,0xff,0xff,0xb5,0xff,0xff,0xff,0xaa,0xff,
0xff,0x7f,0x9d,0xff,0xff,0xbf,0xfe,0xff,0xff,0x5c,0xff,0xff,0xff,0xaa,0xff,
0xff,0xff,0xd6,0xff,0xff,0xff,0xee,0xff,0xff,0xff,0xde,0xff,0xff,0xff,0xbe,
0xff,0xff,0xff,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
-12
View File
@@ -1,12 +0,0 @@
#define curbm5_width 32
#define curbm5_height 32
static char curbm5_bits[] = {
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0x00,0x80,0xff,0xff,0xfe,0xbf,0xff,0xff,0x06,0xb0,0xff,0xff,0xfe,
0xbf,0xff,0xff,0x05,0xd0,0xff,0xff,0x05,0xd0,0xff,0xff,0xa5,0xd2,0xff,0xff,
0x45,0xd1,0xff,0xff,0x8d,0xd8,0xff,0xff,0x1b,0xec,0xff,0xff,0xb7,0xf6,0xff,
0xff,0x6f,0xfb,0xff,0xff,0x6f,0xfb,0xff,0xff,0x37,0xf6,0xff,0xff,0x9b,0xec,
0xff,0xff,0x0d,0xd8,0xff,0xff,0x85,0xd0,0xff,0xff,0x45,0xd1,0xff,0xff,0xa5,
0xd2,0xff,0xff,0x55,0xd5,0xff,0xff,0xfe,0xbf,0xff,0xff,0x06,0xb0,0xff,0xff,
0xfe,0xbf,0xff,0xff,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
-12
View File
@@ -1,12 +0,0 @@
#define curbm6_width 32
#define curbm6_height 32
static char curbm6_bits[] = {
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xfe,0xff,0xff,0x7f,0xfd,0xff,0xff,0xbf,0xfb,0xff,0xff,0xdf,
0xf7,0xff,0xff,0xef,0xef,0xff,0xff,0x0f,0xe0,0xff,0xff,0x7f,0xfd,0xff,0xff,
0x7f,0xfd,0xff,0xff,0x7c,0x7d,0xfe,0x7f,0x7d,0x7d,0xfd,0xbf,0x7d,0x7d,0xfb,
0xdf,0x01,0x01,0xf7,0xef,0xfd,0x7f,0xef,0xdf,0x01,0x01,0xf7,0xbf,0x7d,0x7d,
0xfb,0x7f,0x7d,0x7d,0xfd,0xff,0x7c,0x7d,0xfe,0xff,0x7f,0xfd,0xff,0xff,0x7f,
0xfd,0xff,0xff,0x0f,0xe0,0xff,0xff,0xef,0xef,0xff,0xff,0xdf,0xf7,0xff,0xff,
0xbf,0xfb,0xff,0xff,0x7f,0xfd,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
-43
View File
@@ -1,43 +0,0 @@
/* XPM */
static const char *cursor_arrow[] = {
/* width height num_colors chars_per_pixel */
" 32 32 3 1",
/* colors */
"X c #000000",
". c #ffffff",
" c None",
/* pixels */
"X ",
"XX ",
"X.X ",
"X..X ",
"X...X ",
"X....X ",
"X.....X ",
"X......X ",
"X.......X ",
"X........X ",
"X.....XXXXX ",
"X..X..X ",
"X.X X..X ",
"XX X..X ",
"X X..X ",
" X..X ",
" X..X ",
" X..X ",
" XX ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"0,0"
};
-42
View File
@@ -1,42 +0,0 @@
/* XPM */
static const char *cursor_busy[] = {
/* columns rows colors chars-per-pixel */
"32 32 3 1",
"X c #ffffff",
". c #000000",
" c None",
/* pixels */
" ",
" ",
" ",
" XXXXXXXXXXXXXXXXX ",
" X...............X ",
" X.XXXXXXXXXXXXX.X ",
" X.XX.........XX.X ",
" X.XXXXXXXXXXXXX.X ",
" X.X.........X.X ",
" X.X.........X.X ",
" X.X..X.X.X..X.X ",
" X.X...X.X...X.X ",
" X.XX...X...XX.X ",
" X.XX.....XX.X ",
" X.XX.X.XX.X ",
" X.XX.XX.X ",
" X.XX.XX.X ",
" X.XX...XX.X ",
" X.XX..X..XX.X ",
" X.XX.......XX.X ",
" X.X....X....X.X ",
" X.X...X.X...X.X ",
" X.X..X.X.X..X.X ",
" X.X.X.X.X.X.X.X ",
" X.XXXXXXXXXXXXX.X ",
" X.XX.........XX.X ",
" X.XXXXXXXXXXXXX.X ",
" X...............X ",
" XXXXXXXXXXXXXXXXX ",
" ",
" ",
" ",
"15,15"
};
-43
View File
@@ -1,43 +0,0 @@
/* XPM */
static const char *cursor_cross[] = {
/* width height num_colors chars_per_pixel */
" 32 32 3 1",
/* colors */
"X c #000000",
". c #ffffff",
" c None",
/* pixels */
" ",
" ",
" ",
" ",
" ",
" XXXX ",
" X..X ",
" X..X ",
" X..X ",
" X..X ",
" X..X ",
" X..X ",
" X..X ",
" XXXXXXXXX..XXXXXXXXX ",
" X..................X ",
" X..................X ",
" XXXXXXXXX..XXXXXXXXX ",
" X..X ",
" X..X ",
" X..X ",
" X..X ",
" X..X ",
" X..X ",
" X..X ",
" XXXX ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"15,15"
};
-43
View File
@@ -1,43 +0,0 @@
/* XPM */
static const char *cursor_ibeam[] = {
/* width height num_colors chars_per_pixel */
" 32 32 3 1",
/* colors */
". c #000000",
"X c #ffffff",
" c None",
/* pixels */
" XXX XXX ",
" XXX ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" XXX ",
" XXX XXX ",
" ",
"15,15"
};
-42
View File
@@ -1,42 +0,0 @@
/* XPM */
static const char *cursor_move[] = {
/* columns rows colors chars-per-pixel */
"32 32 3 1",
"X c #ffffff",
". c #000000",
" c None",
/* pixels */
" ",
" ",
" ",
" ",
" X ",
" X.X ",
" X...X ",
" X.....X ",
" X.......X ",
" XXXXXXXXX ",
" X.X ",
" X.X ",
" XX X.X XX ",
" X.X X.X X.X ",
" X..X X.X X..X ",
" X...XXXXXXX.XXXXXXX...X ",
" X....X.............X....X ",
" X...XXXXXXX.XXXXXXX...X ",
" X..X X.X X..X ",
" X.X X.X X.X ",
" XX X.X XX ",
" X.X ",
" X.X ",
" XXXXXXXXX ",
" X.......X ",
" X.....X ",
" X...X ",
" X.X ",
" X ",
" ",
" ",
" ",
"15,15"
};
-42
View File
@@ -1,42 +0,0 @@
/* XPM */
static const char *cursor_no[] = {
/* columns rows colors chars-per-pixel */
"32 32 3 1",
"X c #ffffff",
". c #000000",
" c None",
/* pixels */
" ",
" ",
" ",
" ",
" ",
" ",
" ...... ",
" ..XXXXXX.. ",
" .XXXXXXXXX . ",
" .XXXX....XXX . ",
" .XXX.. ..XXX. ",
" .XXXXX. .XXX. ",
" .XX.XXX. .XX. ",
" .XXX..XXX. .XXX. ",
" .XX. .XXX. .XX. ",
" .XX. .XXX. .XX. ",
" .XX. .XXX. .XX. ",
" .XX. .XXX. .XX. ",
" .XXX. .XXX..XXX. ",
" .XX . .XX.XX. ",
" .XXX. .XXXXX. ",
" .XXX.. ..XXX. ",
" .XXXX....XXXX. ",
" .XXXXXXXXXX. ",
" ..XXXXXX.. ",
" ...... ",
" ",
" ",
" ",
" ",
" ",
" ",
"16,16"
};
-42
View File
@@ -1,42 +0,0 @@
/* XPM */
static const char *cursor_size_h[] = {
/* columns rows colors chars-per-pixel */
"32 32 3 1",
". c #000000",
"X c #ffffff",
" c None",
/* pixels */
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" XX XX ",
" X.X X.X ",
" X..X X..X ",
" X...XXXXXXXXXXX...X ",
" X...................X ",
" X...XXXXXXXXXXX...X ",
" X..X X..X ",
" X.X X.X ",
" XX XX ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"15,15"
};
-42
View File
@@ -1,42 +0,0 @@
/* XPM */
static const char *cursor_size_l[] = {
/* columns rows colors chars-per-pixel */
"32 32 3 1",
". c #000000",
"X c #ffffff",
" c None",
/* pixels */
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" XXXXXXX ",
" X.....X ",
" X....X ",
" X...X ",
" X..X.X ",
" X.X X.X ",
" XX X.X ",
" X.X ",
" X.X XX ",
" X.X X.X ",
" X.X..X ",
" X...X ",
" X....X ",
" X.... X ",
" XXXXXXX ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"15,15"
};
-42
View File
@@ -1,42 +0,0 @@
/* XPM */
static const char *cursor_size_r[] = {
/* columns rows colors chars-per-pixel */
"32 32 3 1",
". c #000000",
"X c #ffffff",
" c None",
/* pixels */
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" XXXXXXX ",
" X.....X ",
" X....X ",
" X...X ",
" X.X..X ",
" X.X X.X ",
" X.X XX ",
" X.X ",
" XX X.X ",
" X.X X.X ",
" X..X.X ",
" X...X ",
" X....X ",
" X.....X ",
" XXXXXXX ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"15,15"
};
-42
View File
@@ -1,42 +0,0 @@
/* XPM */
static const char *cursor_size_v[] = {
/* columns rows colors chars-per-pixel */
"32 32 3 1",
". c #000000",
"X c #ffffff",
" c None",
/* pixels */
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" X ",
" X.X ",
" X...X ",
" X.....X ",
" X.......X ",
" XXXX.XXXX ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" X.X ",
" XXXX XXXX ",
" X.......X ",
" X.....X ",
" X...X ",
" X/X ",
" X ",
" ",
" ",
" ",
" ",
" ",
"15,15"
};
-12
View File
@@ -1,12 +0,0 @@
#define maskbm0_width 32
#define maskbm0_height 32
static char maskbm0_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x78,0x00,0x00,0x00,
0xf8,0x00,0x00,0x00,0xf8,0x01,0x00,0x00,0xf8,0x03,0x00,0x00,0xf8,0x07,0x00,
0x00,0xf8,0x0f,0x00,0x00,0xf8,0x1f,0x00,0x00,0xf8,0x3f,0x00,0x00,0xf8,0x03,
0x00,0x00,0xb8,0x07,0x00,0x00,0x98,0x07,0x00,0x00,0x08,0x0f,0x00,0x00,0x00,
0x0f,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x0c,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-12
View File
@@ -1,12 +0,0 @@
#define maskbm1_width 32
#define maskbm1_height 32
static char maskbm1_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x0c,0x60,0x00,0x00,0x0e,0xe0,0x00,0x00,0x0f,0xe0,0x01,
0x80,0xff,0xff,0x03,0xc0,0xff,0xff,0x07,0x80,0xff,0xff,0x03,0x00,0x0f,0xe0,
0x01,0x00,0x0e,0xe0,0x00,0x00,0x0c,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-12
View File
@@ -1,12 +0,0 @@
#define maskbm2_width 32
#define maskbm2_height 32
static char maskbm2_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0xe0,0x03,0x00,0x00,0xf0,0x07,0x00,0x00,
0xf8,0x0f,0x00,0x00,0xf8,0x0f,0x00,0x00,0xc0,0x01,0x00,0x00,0xc0,0x01,0x00,
0x00,0xc0,0x01,0x00,0x00,0xc0,0x01,0x00,0x00,0xc0,0x01,0x00,0x00,0xc0,0x01,
0x00,0x00,0xc0,0x01,0x00,0x00,0xc0,0x01,0x00,0x00,0xf8,0x0f,0x00,0x00,0xf8,
0x0f,0x00,0x00,0xf0,0x07,0x00,0x00,0xe0,0x03,0x00,0x00,0xc0,0x01,0x00,0x00,
0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-12
View File
@@ -1,12 +0,0 @@
#define maskbm3_width 32
#define maskbm3_height 32
static char maskbm3_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,
0x7e,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0xee,0x00,0x00,
0x00,0xc6,0x01,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0xc7,0x00,0x00,0x00,0xee,
0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,
0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-12
View File
@@ -1,12 +0,0 @@
#define maskbm4_width 32
#define maskbm4_height 32
static char maskbm4_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x7f,0x00,0x00,
0x00,0x7e,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x77,0x00,
0x00,0x80,0x63,0x00,0x00,0xc0,0x01,0x00,0x00,0xe3,0x00,0x00,0x00,0x77,0x00,
0x00,0x00,0x3f,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x7f,
0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-12
View File
@@ -1,12 +0,0 @@
#define maskbm5_width 32
#define maskbm5_height 32
static char maskbm5_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0xff,0x7f,0x00,0x00,0xff,0x7f,0x00,0x00,0xff,0x7f,0x00,0x00,0xff,
0x7f,0x00,0x00,0xfe,0x3f,0x00,0x00,0xfe,0x3f,0x00,0x00,0xfe,0x3f,0x00,0x00,
0xfe,0x3f,0x00,0x00,0xfe,0x3f,0x00,0x00,0xfc,0x1f,0x00,0x00,0xf8,0x0f,0x00,
0x00,0xf0,0x07,0x00,0x00,0xf0,0x07,0x00,0x00,0xf8,0x0f,0x00,0x00,0xfc,0x1f,
0x00,0x00,0xfe,0x3f,0x00,0x00,0xfe,0x3f,0x00,0x00,0xfe,0x3f,0x00,0x00,0xfe,
0x3f,0x00,0x00,0xfe,0x3f,0x00,0x00,0xff,0x7f,0x00,0x00,0xff,0x7f,0x00,0x00,
0xff,0x7f,0x00,0x00,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-12
View File
@@ -1,12 +0,0 @@
#define maskbm6_width 32
#define maskbm6_height 32
static char maskbm6_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x00,0x00,0x80,0x03,0x00,0x00,0xc0,0x07,0x00,0x00,0xe0,
0x0f,0x00,0x00,0xf0,0x1f,0x00,0x00,0xf0,0x1f,0x00,0x00,0x80,0x03,0x00,0x00,
0x80,0x03,0x00,0x00,0x83,0x83,0x01,0x80,0x83,0x83,0x03,0xc0,0x83,0x83,0x07,
0xe0,0xff,0xff,0x0f,0xf0,0xff,0xff,0x1f,0xe0,0xff,0xff,0x0f,0xc0,0x83,0x83,
0x07,0x80,0x83,0x83,0x03,0x00,0x83,0x83,0x01,0x00,0x80,0x03,0x00,0x00,0x80,
0x03,0x00,0x00,0xf0,0x1f,0x00,0x00,0xf0,0x1f,0x00,0x00,0xe0,0x0f,0x00,0x00,
0xc0,0x07,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+19 -4
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();
@@ -966,7 +969,7 @@ struct grEffectMoveView_data {
int target_y;
};
static void grEffectMoveView_step(void *data, double progress) {
static void grEffectMoveView_step(void *data, float progress) {
struct grEffectMoveView_data *d = data;
int x = d->origin_x + (d->target_x - d->origin_x) * progress;
int y = d->origin_y + (d->target_y - d->origin_y) * progress;
@@ -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);
}
+3 -3
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.
@@ -137,7 +137,7 @@ void commandCE() {
int option = getCaliValue();
int wait_flag = getCaliValue();
ags_eCopyArea(src_x, src_y, width, height, dst_x, dst_y, effect_sw, option, wait_flag, -1);
ags_eCopyArea(src_x, src_y, width, height, dst_x, dst_y, effect_sw, option, wait_flag);
if (wait_flag == 1) {
sysVar[0] = nact->waitcancel_key;
@@ -167,7 +167,7 @@ void commandCD() {
int wait_flag = getCaliValue();
int color = getCaliValue();
ags_eCopyArea(src_x, src_y, width, height, dst_x, dst_y, effect_sw, option, wait_flag, color);
ags_eSpriteCopyArea(src_x, src_y, width, height, dst_x, dst_y, effect_sw, option, wait_flag, color);
if (wait_flag == 1) {
sysVar[0] = nact->waitcancel_key;
+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();
+1 -1
View File
@@ -75,7 +75,7 @@ void commandNR() {
int var1 = getCaliValue();
int *var2 = getCaliVariable();
*var2 = (int)sqrt(var1);
*var2 = (int)sqrtf(var1);
DEBUG_COMMAND("NR %d,%d:", var1, *var2);
}
+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])
+54 -149
View File
@@ -54,84 +54,6 @@ static void eCopyUpdateArea(int sx, int sy, int w, int h, int dx, int dy) {
sdl_updateArea(&src, &dst);
}
static int eCopyArea1(int dx, int dy, int w, int h, int opt) {
int y, key = 0, cnt;
int waitcnt = opt == 0 ? 20 : opt;
cnt = sdl_getTicks();
for (y = 0; y < h - 24; y += 24) {
cnt += waitcnt;
eCopyUpdateArea(dx, dy + h - y, w, y, dx, dy);
EC_WAIT;
}
eCopyUpdateArea(dx, dy, w, h, dx, dy);
return key;
}
static int eCopyArea2(int dx, int dy, int w, int h, int opt) {
int y, key = 0, cnt;
int waitcnt = opt == 0 ? 20 : opt;
cnt = sdl_getTicks();
for (y = 0; y < h - 24; y += 24) {
cnt += waitcnt;
eCopyUpdateArea(dx, dy , w, y, dx, dy + h - y);
EC_WAIT;
}
eCopyUpdateArea(dx, dy, w, h, dx, dy);
return key;
}
static int eCopyArea3(int dx, int dy, int w, int h, int opt) {
int y1, y2, key = 0, cnt;
int waitcnt = opt == 0 ? 3 : opt;
if (h % 2) {
h--;
eCopyUpdateArea(dx , dy + h, w, 1, dx, dy + h);
}
y1 = dy;
y2 = dy + h - 1;
cnt = sdl_getTicks();
while (h > 0) {
cnt += waitcnt;
eCopyUpdateArea(dx, y1, w, 1, dx, y1);
eCopyUpdateArea(dx, y2, w, 1, dx, y2);
y1 += 2;
y2 -= 2;
h -= 2;
EC_WAIT;
}
eCopyUpdateArea(dx, dy, w, h, dx, dy);
return key;
}
static int eCopyArea4(int dx, int dy, int w, int h, int opt) {
int x1,x2, key = 0, cnt;
int waitcnt = opt == 0 ? 3 : opt;
if (w % 2) {
w--;
eCopyUpdateArea(dx + w , dy, 1, h, dx + w, dy);
}
x1 = dx;
x2 = dx + w - 1;
cnt = sdl_getTicks();
while (w > 0) {
cnt += waitcnt;
eCopyUpdateArea(x1, dy, 1, h, x1, dy);
eCopyUpdateArea(x2, dy, 1, h, x2, dy);
x1 += 2;
x2 -= 2;
w -= 2;
EC_WAIT;
}
eCopyUpdateArea(dx, dy, w, h, dx, dy);
return key;
}
static int eCopyArea5(int sx, int sy, int w, int h, int dx, int dy, int opt) {
int i, x, y, key = 0, cnt;
int waitcnt = opt == 0 ? 20 : opt;
@@ -279,7 +201,7 @@ static int eCopyArea23(int sx, int sy, int w, int h, int dx, int dy, int opt) {
return key;
}
static int eCopyArea1000(int sx, int sy, int w, int h, int dx, int dy, int opt, int spCol) {
static int eCopyArea1000(int sx, int sy, int w, int h, int dx, int dy, int opt) {
/* XOR */
return sys_getInputInfo();
}
@@ -297,40 +219,17 @@ static int eCopyArea2001(int sx, int sy, int w, int h, int dx, int dy, int opt)
return sys_getInputInfo();
}
static int eCopyArea5sp(int sx, int sy, int w, int h, int dx, int dy, int opt) {
int i, j, k, key = 0, cnt;
int st_i, ed_i;
int waitcnt = opt == 0 ? 50 : opt * 10;
int step[200];
void *save = ags_saveRegion(dx - 50, dy, w + 100, h);
for (i = 0; i < 200; i++) {
step[i] = 50 * sin((2 * M_PI * i) / 50);
}
cnt = sdl_getTicks();
for (i = 150; i < h + 200; i++) {
cnt += waitcnt;
st_i = max(0, i - 200);
ed_i = h;
ags_copyRegion(save, 0, st_i, w + 100, ed_i - st_i, dx - 50, dy + st_i);
for (j = st_i, k = 0; j < ed_i; j++, k++) {
ags_copyArea_shadow(sx , sy + j, w, 1,
dx + step[(k + max(0, 200 - i)) % 200],
dy + j);
}
ags_updateArea(dx - 50, dy + st_i, w + 100, ed_i - st_i);
EC_WAIT;
}
ags_delRegion(save);
return key;
}
static int duration(enum nact_effect effect, int opt, SDL_Rect *rect) {
switch (effect) {
case NACT_EFFECT_PAN_IN_DOWN:
case NACT_EFFECT_PAN_IN_UP:
return (opt ? opt : 20) * (rect->h / 24);
case NACT_EFFECT_SKIP_LINE_UP_DOWN:
return (opt ? opt : 3) * (rect->h / 2);
case NACT_EFFECT_SKIP_LINE_LR_RL:
return (opt ? opt : 3) * (rect->w / 2);
case NACT_SP_EFFECT_RASTER_BLEND:
return (opt ? opt : 25) * rect->h;
case NACT_EFFECT_ZOOM_IN:
return opt ? opt * 64 : 500;
case NACT_EFFECT_BLIND_DOWN:
@@ -360,7 +259,7 @@ static int duration(enum nact_effect effect, int opt, SDL_Rect *rect) {
return (opt ? opt : 100) * 8;
case NACT_EFFECT_CIRCLE_WIPE_OUT:
case NACT_EFFECT_CIRCLE_WIPE_IN:
return (opt ? opt : 20) * sqrt(rect->w * rect->w + rect->h * rect->h) / 40;
return (opt ? opt : 20) * sqrtf(rect->w * rect->w + rect->h * rect->h) / 40;
case NACT_EFFECT_FADEIN:
case NACT_EFFECT_WHITEIN:
case NACT_EFFECT_FADEOUT:
@@ -402,12 +301,12 @@ static int duration(enum nact_effect effect, int opt, SDL_Rect *rect) {
return 1000;
}
void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt, boolean cancel, int spCol) {
void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt, bool cancel) {
int ret = 0;
#if 0
NOTICE("ec_area sx %d sy %d w %d h %d dx %d dy %d sw %d opt %d spc %d cancel %s",
sx, sy, w, h, dx, dy, sw, opt, spCol, cancel ? "True" : "False");
NOTICE("ags_eCopyArea sx %d sy %d w %d h %d dx %d dy %d sw %d opt %d cancel %s",
sx, sy, w, h, dx, dy, sw, opt, cancel ? "True" : "False");
#endif
if (!ags_check_param(&sx, &sy, &w, &h)) return;
if (!ags_check_param(&dx, &dy, &w, &h)) return;
@@ -430,7 +329,7 @@ void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt
enum sdl_effect_type sdl_effect = from_nact_effect(sw);
if (sdl_effect != EFFECT_INVALID) {
SDL_Rect rect = { dx - nact->ags.view_area.x, dy - nact->ags.view_area.y, w, h };
struct sdl_effect *eff = sdl_effect_init(&rect, sdl_getDIB(), dx, dy, sdl_getDIB(), sx, sy, from_nact_effect(sw));
struct sdl_effect *eff = sdl_effect_init(&rect, sdl_getDIB(), dx, dy, sdl_getDIB(), sx, sy, sdl_effect);
ags_runEffect(duration(sw, opt, &rect), cancel, (ags_EffectStepFunc)sdl_effect_step, eff);
sdl_effect_finish(eff);
@@ -455,19 +354,11 @@ void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt
ecp_cancel = cancel;
switch(sw) {
case 1:
case 2:
case 3:
case 4:
case 6:
case 16:
case 17:
case 54:
if (spCol == -1) {
ags_copyArea(sx, sy, w, h, dx, dy);
} else {
ags_copyAreaSP(sx, sy, w, h, dx, dy, spCol);
}
ags_copyArea(sx, sy, w, h, dx, dy);
{
MyRectangle r = {dx, dy, w, h}, update;
SDL_IntersectRect(&nact->ags.view_area, &r, &update);
@@ -477,24 +368,8 @@ void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt
}
switch(sw) {
case 1:
ret = eCopyArea1(dx, dy, w, h, opt);
break;
case 2:
ret = eCopyArea2(dx, dy, w, h, opt);
break;
case 3:
ret = eCopyArea3(dx, dy, w, h, opt);
break;
case 4:
ret = eCopyArea4(dx, dy, w, h, opt);
break;
case 5:
if (spCol == -1) {
ret = eCopyArea5(sx, sy, w, h, dx, dy, opt);
} else {
ret = eCopyArea5sp(sx, sy, w, h, dx, dy, opt);
}
ret = eCopyArea5(sx, sy, w, h, dx, dy, opt);
break;
case 6:
ret = eCopyArea6(dx, dy, w, h, opt);
@@ -517,13 +392,7 @@ void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt
case 1000:
if (nact->ags.world_depth != 8) return;
ret = eCopyArea1000(sx, sy, w, h, dx, dy, opt, spCol);
break;
case NACT_EFFECT_PALETTE_SHIFT:
if (nact->ags.world_depth != 8 || spCol == -1) return;
ags_copyPaletteShift(sx, sy, w, h, dx, dy, spCol);
ags_updateArea(dx, dy, w, h);
ret = sys_getInputInfo();
ret = eCopyArea1000(sx, sy, w, h, dx, dy, opt);
break;
case 2000:
if (nact->ags.world_depth == 8) return;
@@ -540,3 +409,39 @@ void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt
}
nact->waitcancel_key = ret;
}
void ags_eSpriteCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt, bool cancel, int spCol) {
#if 0
NOTICE("ags_eSpriteCopyArea sx %d sy %d w %d h %d dx %d dy %d sw %d opt %d spc %d cancel %s",
sx, sy, w, h, dx, dy, sw, opt, spCol, cancel ? "True" : "False");
#endif
if (!ags_check_param(&sx, &sy, &w, &h)) return;
if (!ags_check_param(&dx, &dy, &w, &h)) return;
nact->waitcancel_key = 0;
if (sw == NACT_EFFECT_PALETTE_SHIFT) {
if (nact->ags.world_depth != 8) return;
ags_copyPaletteShift(sx, sy, w, h, dx, dy, spCol);
ags_updateArea(dx, dy, w, h);
nact->waitcancel_key = sys_getInputInfo();
return;
}
enum sdl_effect_type type = from_nact_sprite_effect(sw);
if (type == EFFECT_INVALID) {
WARNING("Invalid effect: %d", sw);
return;
}
SDL_Rect rect = { dx - nact->ags.view_area.x, dy - nact->ags.view_area.y, w, h };
struct sdl_effect *eff = sdl_sprite_effect_init(&rect, dx, dy, sx, sy, spCol, type);
ags_runEffect(duration(sw, opt, &rect), cancel, (ags_EffectStepFunc)sdl_effect_step, eff);
sdl_effect_finish(eff);
// Actual copy.
if (sw == 5) {
ags_copyArea_shadow(sx, sy, w, h, dx, dy);
} else {
ags_copyAreaSP(sx, sy, w, h, dx, dy, spCol);
}
ags_updateArea(dx, dy, w, h);
}
+11
View File
@@ -22,6 +22,11 @@
// Effect types of the CE/CD command.
enum nact_effect {
NACT_EFFECT_PAN_IN_DOWN = 1,
NACT_EFFECT_PAN_IN_UP = 2,
NACT_EFFECT_SKIP_LINE_UP_DOWN = 3,
NACT_EFFECT_SKIP_LINE_LR_RL = 4,
NACT_SP_EFFECT_RASTER_BLEND = 5, // CD 5
NACT_EFFECT_WIPE_IN = 7,
NACT_EFFECT_WIPE_OUT = 8,
NACT_EFFECT_ZOOM_IN = 10,
@@ -124,6 +129,10 @@ enum sdl_effect_type {
EFFECT_DITHERING_FADEIN,
EFFECT_DITHERING_WHITEOUT,
EFFECT_DITHERING_WHITEIN,
EFFECT_PAN_IN_DOWN,
EFFECT_PAN_IN_UP,
EFFECT_SKIP_LINE_UP_DOWN,
EFFECT_SKIP_LINE_LR_RL,
EFFECT_WIPE_IN,
EFFECT_WIPE_OUT,
EFFECT_WIPE_LR,
@@ -173,9 +182,11 @@ enum sdl_effect_type {
EFFECT_POLYGON_ROTATE_X_CW,
EFFECT_ZIGZAG_CROSSFADE,
EFFECT_MAGNIFY,
EFFECT_RASTER_BLEND,
};
enum sdl_effect_type from_nact_effect(enum nact_effect effect);
enum sdl_effect_type from_nact_sprite_effect(enum nact_effect effect);
enum sdl_effect_type from_sact_effect(enum sact_effect effect);
#endif /* __EFFECT_H__ */
+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__ */
+13 -6
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};
@@ -226,9 +235,7 @@ boolean font_get_antialias(void) {
}
#ifdef __EMSCRIPTEN__
EM_JS(int, load_mincho_font, (void), {
return Asyncify.handleSleep(function(wakeUp) {
xsystem35.load_mincho_font().then(wakeUp);
});
EM_ASYNC_JS(int, load_mincho_font, (void), {
await xsystem35.load_mincho_font();
});
#endif
+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 */
+3 -3
View File
@@ -23,7 +23,7 @@
#include "portab.h"
#include "midi.h"
static int midi_initilize(char *pname, int subdev);
static int midi_initialize(int subdev);
static int midi_exit(void);
static int midi_reset(void);
static int midi_start(int no, int loop, char *data, int datalen);
@@ -40,7 +40,7 @@ static boolean midi_fading();
#define midi midi_android
mididevice_t midi = {
midi_initilize,
midi_initialize,
midi_exit,
midi_reset,
midi_start,
@@ -56,7 +56,7 @@ mididevice_t midi = {
midi_fading
};
static int midi_initilize(char *pname, int subdev) {
static int midi_initialize(int subdev) {
return OK;
}
+4 -32
View File
@@ -23,13 +23,11 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "portab.h"
#include "midi.h"
static char *dev;
static char default_mode = 'e';
static int subdev = -1;
@@ -45,10 +43,6 @@ extern mididevice_t midi_android;
extern mididevice_t midi_sdlmixer;
#endif
#if defined(ENABLE_MIDI_RAWMIDI) || defined(ENABLE_MIDI_SEQMIDI)
extern mididevice_t midi_rawmidi;
#endif
#ifdef ENABLE_MIDI_PORTMIDI
extern mididevice_t midi_portmidi;
#endif
@@ -57,30 +51,23 @@ int midi_init(mididevice_t *midi) {
int ret = NG;
switch(default_mode) {
case 'r':
case 's':
#if defined(ENABLE_MIDI_RAWMIDI) || defined(ENABLE_MIDI_SEQMIDI)
memcpy(midi, &midi_rawmidi, sizeof(mididevice_t));
ret = midi->init(dev, subdev);
#endif
break;
case 'e':
#ifdef __EMSCRIPTEN__
ret = midi_emscripten.init(NULL, 0);
ret = midi_emscripten.init(0);
memcpy(midi, &midi_emscripten, sizeof(mididevice_t));
#endif
#ifdef __ANDROID__
ret = midi_android.init(NULL, 0);
ret = midi_android.init(0);
memcpy(midi, &midi_android, sizeof(mididevice_t));
#endif
#ifdef ENABLE_MIDI_SDLMIXER
ret = midi_sdlmixer.init(NULL, 0);
ret = midi_sdlmixer.init(0);
memcpy(midi, &midi_sdlmixer, sizeof(mididevice_t));
#endif
break;
case 'p':
#ifdef ENABLE_MIDI_PORTMIDI
ret = midi_portmidi.init(NULL, subdev);
ret = midi_portmidi.init(subdev);
memcpy(midi, &midi_portmidi, sizeof(mididevice_t));
#endif
case '0':
@@ -90,27 +77,12 @@ int midi_init(mididevice_t *midi) {
return ret;
}
void midi_set_devicename(const char *name) {
if (dev) free(dev);
if (0 == strcmp("none", name)) dev = NULL;
else dev = strdup(name);
}
void midi_set_output_device(int mode) {
switch(mode & 0x7f) {
case 'e':
/* external player */
default_mode = 'e';
break;
case 'r':
/* raw midi mode */
default_mode = 'r';
break;
case 's':
/* sequencer midi mode */
default_mode = 's';
subdev = mode >> 8;
break;
case 'p':
/* portmidi midi mode */
default_mode = 'p';
+2 -2
View File
@@ -24,7 +24,7 @@
#include "portab.h"
#include "midi.h"
static int midi_initilize(char *pname, int subdev) {
static int midi_initialize(int subdev) {
return OK;
}
@@ -96,7 +96,7 @@ EM_JS(boolean, midi_fading, (), {
});
mididevice_t midi_emscripten = {
midi_initilize,
midi_initialize,
midi_exit,
midi_reset,
midi_start,
+1 -2
View File
@@ -34,7 +34,7 @@ typedef struct {
typedef struct mididevice mididevice_t;
struct mididevice {
int (* init)(char *, int);
int (* init)(int);
int (* exit)(void);
int (* reset)(void);
// Play through the music loop times. If loop == 0, loops forever.
@@ -52,7 +52,6 @@ struct mididevice {
};
extern int midi_init(mididevice_t *);
extern void midi_set_devicename(const char *);
extern void midi_set_output_device(int mode);
#endif /* __MIDI_H__ */
+217 -289
View File
@@ -1,5 +1,10 @@
/*
* Copyright (C) 2021 bsdf <EMAILBEN145@gmail.com>
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
* 2021 bsdf <EMAILBEN145@gmail.com>
* 2024 kichikuou <KichikuouChrome@gmail.com>
*
* Based on midiplay+ by Daisuke NAGANO <breeze.nagano@nifty.ne.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
@@ -17,43 +22,36 @@
*
*/
#include <stdio.h>
#include <unistd.h>
#include "config.h"
#include <time.h>
#include <sys/time.h>
#include <assert.h>
#include <portmidi.h>
#include <SDL_thread.h>
#include <SDL_timer.h>
#include <portmidi.h>
#include "portab.h"
#include "system.h"
#include "midi.h"
#include "midifile.h"
#include "msgqueue.h"
#define MIDI_LATENCY 20
static struct {
char midi_variable[128];
char midi_flag[128];
} flags;
typedef struct midievent midievent_t;
static int midi_thread(void *);
static int midi_initialize(char *devnm, int subdev);
static int midi_initialize(int subdev);
static int midi_exit(void);
static int midi_reset(void);
static int midi_start(int no, int loop, char *data, int datalen);
static int midi_stop();
static int midi_pause();
static int midi_unpause();
static int midi_stop(void);
static int midi_pause(void);
static int midi_unpause(void);
static int midi_getpos(midiplaystate *st);
static int midi_getflag(int mode, int idx);
static int midi_setflag(int mode, int idx, int val);
static void midi_allnotesoff();
static void midi_send_reset();
static void midi_settempo(midievent_t event);
static void midi_sync(midievent_t event);
static int midi_getflag(int mode, int index);
static int midi_setflag(int mode, int index, int val);
mididevice_t midi_portmidi = {
midi_initialize,
@@ -72,115 +70,252 @@ mididevice_t midi_portmidi = {
NULL
};
static boolean enabled = FALSE;
static PortMidiStream *stream;
static struct midiinfo *midi;
static PmDeviceID device_id;
static SDL_Thread *thread;
static struct msgq *queue;
static int start_time;
static SDL_Thread *thread;
static boolean thread_running = FALSE;
static boolean should_stop = FALSE;
static boolean should_pause = FALSE;
static boolean should_unpause = FALSE;
static boolean should_loop = FALSE;
static char cmd_pause[] = "pause";
static char cmd_unpause[] = "unpause";
static char cmd_stop[] = "stop";
static int midi_initialize(char *devnm, int subdev) {
NOTICE("midi_initialize: devnm = [%s] subdev = [%i]", devnm, subdev);
PmError err;
static void allnotesoff() {
for (int i = 0; i < 16; i++) {
Pm_WriteShort(stream, 0, Pm_Message(0xb0 + i, 0x7b, 0x00));
}
}
if ((err = Pm_Initialize()) != pmNoError) {
static void send_reset() {
for (int i = 0; i < 16; i++) {
Pm_WriteShort(stream, 0, Pm_Message(0xb0 + i, 0x78, 0x00));
Pm_WriteShort(stream, 0, Pm_Message(0xb0 + i, 0x79, 0x00));
}
return;
}
static void midi_write(struct midievent *event, uint32_t timestamp) {
Pm_WriteShort(stream, timestamp, event->data);
}
static PmTimestamp midi_time_proc(void *time_info) {
return SDL_GetTicks();
}
static uint32_t ticks2ms(int ticks, int division, unsigned int tempo) {
return ticks * tempo / (division * 1000);
}
static void *midi_mainloop(struct midiinfo *midi) {
int i = 0;
int ctick = 0;
int tempo = 500000;
uint32_t last_time = SDL_GetTicks();
void *cmd;
while (i < midi->nr_events) {
if (ctick < midi->event[i].ctime) {
int delta = midi->event[i].ctime - ctick;
uint32_t target_time = last_time + ticks2ms(delta, midi->division, tempo);
uint32_t current_time = SDL_GetTicks();
while (current_time < target_time) {
cmd = msgq_dequeue_timeout(queue, target_time - current_time);
if (cmd == cmd_stop)
return cmd;
if (cmd == cmd_pause) {
while (TRUE) {
cmd = msgq_dequeue(queue);
if (cmd == cmd_stop)
return cmd;
if (cmd == cmd_unpause)
break;
}
target_time += SDL_GetTicks() - current_time;
}
current_time = SDL_GetTicks();
}
last_time = target_time;
ctick = midi->event[i].ctime;
}
if (midi->event[i].type == MIDI_EVENT_NORMAL) {
midi_write(&midi->event[i], last_time);
i++;
} else if (midi->event[i].type == MIDI_EVENT_TEMPO) {
tempo = midi->event[i].data;
i++;
} else if (midi->event[i].type == MIDI_EVENT_SYS35) {
int vn1 = Pm_MessageData2(midi->event[i+1].data);
int vn2 = Pm_MessageData2(midi->event[i+2].data);
int vn3 = Pm_MessageData2(midi->event[i+3].data);
switch (vn1) {
case MIDI_SYS35_LABEL_DEFINITION:
i += MIDI_SYS35_EVENT_SIZE;
break;
case MIDI_SYS35_LABEL_JUMP:
allnotesoff();
i = midi->sys35_label[vn2];
ctick = midi->event[i].ctime;
break;
case MIDI_SYS35_FLAG_SET:
flags.midi_flag[vn2] = vn3;
i += MIDI_SYS35_EVENT_SIZE;
break;
case MIDI_SYS35_FLAG_JUMP:
if (flags.midi_flag[vn2] == 1) {
i = midi->sys35_label[vn3];
ctick = midi->event[i].ctime;
allnotesoff();
} else {
i += MIDI_SYS35_EVENT_SIZE;
}
break;
case MIDI_SYS35_VARIABLE_SET:
flags.midi_variable[vn2] = vn3;
i += MIDI_SYS35_EVENT_SIZE;
break;
case MIDI_SYS35_VARIABLE_JUMP:
if (--(flags.midi_variable[vn2]) == 0) {
i = midi->sys35_label[vn3];
ctick = midi->event[i].ctime;
allnotesoff();
} else {
i += MIDI_SYS35_EVENT_SIZE;
}
break;
}
} else {
WARNING("Unknown type of event %x (NEVER!).", midi->event[i].type);
}
}
return NULL;
}
static int midi_initialize(int subdev) {
enabled = FALSE;
PmError err = Pm_Initialize();
if (err != pmNoError) {
WARNING("%s", Pm_GetErrorText(err));
return NG;
}
int ndevices = Pm_CountDevices();
if (ndevices == 0 || subdev >= ndevices) {
for (int i = 0; i < ndevices; i++) {
const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
NOTICE("MIDI #%d: interf=\"%s\", name=\"%s\", input=%d, output=%d",
i, info->interf, info->name, info->input, info->output);
}
if (subdev < 0 || subdev >= ndevices) {
WARNING("invalid midi device number");
return NG;
}
if ((err = Pm_OpenOutput(&stream, subdev, NULL, 0, NULL, NULL, 10)) != pmNoError) {
WARNING("%s", Pm_GetErrorText(err));
return NG;
}
device_id = subdev;
enabled = TRUE;
return OK;
}
static int midi_exit(void) {
NOTICE("midi_exit");
if (thread_running) {
if (enabled) {
midi_stop();
}
NOTICE("midi stopped");
Pm_Close(stream);
stream = NULL;
Pm_Terminate();
return OK;
}
static int midi_reset(void) {
if (thread_running) {
if (enabled) {
midi_stop();
}
return OK;
}
static int midi_thread(void *data) {
send_reset();
void *cmd = midi_mainloop(data);
send_reset();
SDL_Delay(MIDI_LATENCY);
mf_remove_midifile(data);
Pm_Close(stream);
stream = NULL;
while (cmd != cmd_stop)
cmd = msgq_dequeue(queue);
return 0;
}
/* no = 0~ */
static int midi_start(int no, int loop, char *data, int datalen) {
NOTICE("midi_start: no = %i loop = %i datalen = %i", no, loop, datalen);
should_stop = FALSE;
should_pause = FALSE;
should_unpause = FALSE;
should_loop = loop;
if (queue)
midi_stop();
if (thread_running) {
if (midi_stop() == NG) {
WARNING("error stopping midi thread");
return NG;
}
}
midi = mf_read_midifile(data, datalen);
if (midi == NULL) {
struct midiinfo *midi = mf_read_midifile(data, datalen);
if (!midi) {
WARNING("error reading midi file");
return NG;
}
thread = SDL_CreateThread(midi_thread, "PortMIDI", NULL);
if (!thread) {
WARNING("could not create midi thread");
PmError err = Pm_OpenOutput(&stream, device_id, NULL, 0, midi_time_proc, NULL, MIDI_LATENCY);
if (err != pmNoError) {
WARNING("Pm_OpenOutput failed: %s", Pm_GetErrorText(err));
mf_remove_midifile(midi);
return NG;
}
queue = msgq_new();
thread = SDL_CreateThread(midi_thread, "MIDI", midi);
start_time = SDL_GetTicks();
return OK;
}
static int midi_stop() {
NOTICE("midi_stop");
should_stop = TRUE;
static int midi_stop(void) {
if (!enabled || !queue) {
return OK;
}
msgq_enqueue(queue, cmd_stop);
SDL_WaitThread(thread, NULL);
thread = NULL;
msgq_free(queue);
queue = NULL;
return OK;
}
static int midi_pause() {
NOTICE("midi_pause");
should_pause = TRUE;
static int midi_pause(void) {
if (!enabled || !queue) return OK;
msgq_enqueue(queue, cmd_pause);
return OK;
}
static int midi_unpause() {
NOTICE("midi_unpause");
should_unpause = TRUE;
static int midi_unpause(void) {
if (!enabled || !queue) return OK;
msgq_enqueue(queue, cmd_unpause);
return OK;
}
static int midi_getpos(midiplaystate *st) {
NOTICE("midi_getpos");
if (!thread_running) {
if (!enabled || !queue) {
st->in_play = FALSE;
st->loc_ms = 0;
st->loc_ms = 0;
return OK;
}
if (!stream) {
midi_stop();
st->in_play = FALSE;
st->loc_ms = 0;
return OK;
}
@@ -190,230 +325,23 @@ static int midi_getpos(midiplaystate *st) {
return OK;
}
static int midi_getflag(int mode, int idx) {
NOTICE("midi_getflag: %i = %i", mode, idx);
static int midi_getflag(int mode, int index) {
if (mode == 0) {
/* flag */
return flags.midi_flag[idx];
}
else {
return flags.midi_flag[index];
} else {
/* variable */
return flags.midi_variable[idx];
return flags.midi_variable[index];
}
}
static int midi_setflag(int mode, int idx, int val) {
NOTICE("midi_setflag: %i %i = %i", mode, idx, val);
static int midi_setflag(int mode, int index, int val) {
if (mode == 0) {
/* flag */
return flags.midi_flag[idx] = val;
}
else {
flags.midi_flag[index] = val;
} else {
/* variable */
flags.midi_variable[idx] = val;
flags.midi_variable[index] = val;
}
return OK;
}
static uint64_t pc, tick, ctick, tempo, ppqn;
static void midi_write(midievent_t event) {
uint64_t ts = (event.ctime * ppqn) / 1000;
Pm_WriteShort(stream, ts, Pm_Message(event.data[0], event.data[1], event.data[2]));
pc++;
}
static void midi_allnotesoff() {
NOTICE("midi_allnotesoff");
for (int i = 0; i < 16; i++) {
Pm_WriteShort(stream, 0, Pm_Message(0xb0 + i, 0x7b, 0x00));
}
}
static void midi_send_reset() {
NOTICE("midi_send_reset");
for (int i = 0; i < 16; i++) {
Pm_WriteShort(stream, 0, Pm_Message(0xb0 + i, 0x78, 0x00));
Pm_WriteShort(stream, 0, Pm_Message(0xb0 + i, 0x79, 0x00));
}
}
static void midi_settempo(midievent_t event) {
int *p;
p = (int*)event.data;
tempo = (unsigned int)*p;
NOTICE("midi_settempo(%i)", tempo);
ppqn = tempo / midi->division;
pc++;
}
// the timing here feels a little ...off. it could just be that i've
// been listening way too hard and overanalyzing but there are a few
// things that don't feel right. i've tweaked this every way i can think of
// so any new ideas welcome.
static void midi_sync(midievent_t event) {
int delta = event.ctime - ctick;
// (delta * ppqn) SHOULD return the clock time in microseconds.
// the 1000 is subtracted to give portmidi some time to queue the events
uint64_t stime = (uint64_t) (delta * ppqn) - 1000;
if (stime > 0) {
struct timespec req;
// since stime should be in microseconds, we should be dividing by 10^6
// but here we are dividing by 10^7 instead. i can't figure out why
// the numbers are off.
req.tv_sec = (time_t) stime / 10000000;
req.tv_nsec = (uint64_t)(stime % 10000000) * 1000;
nanosleep(&req, NULL);
}
ctick = event.ctime;
}
static void midi_handlesys35(midievent_t event) {
NOTICE("midi_handlesys35: ");
int vn1 = midi->event[pc+1].data[2];
int vn2 = midi->event[pc+2].data[2];
int vn3 = midi->event[pc+3].data[2];
switch (vn1) {
case 0:
/* set label */
NOTICE("set label");
pc += 6;
break;
case 1:
/* jump */
midi_allnotesoff();
pc = midi->sys35_label[vn2];
NOTICE("jump to tick [%i]", pc);
break;
case 2:
/* set flag */
NOTICE("set flag %i = %i", vn2, vn3);
flags.midi_flag[vn2] = vn3;
pc += 6;
break;
case 3:
/* flag jump */
if (flags.midi_flag[vn2] == 1) {
pc = midi->sys35_label[vn3];
tick = ctick = event.ctime;
midi_allnotesoff();
NOTICE("jump to tick [%i] ctime = [%i]", pc, tick);
} else {
NOTICE("flag [%i] not set, not jumping", vn2);
pc += 6;
}
break;
case 4:
/* set variable */
NOTICE("set var %i = %i", vn2, vn3);
flags.midi_variable[vn2] = vn3;
pc += 6;
break;
case 5:
/* variable jump */
if (--(flags.midi_variable[vn2]) == 0) {
pc = midi->sys35_label[vn3];
tick = ctick = event.ctime;
midi_allnotesoff();
NOTICE("jump to tick [%i] ctime = [%i]", pc, tick);
} else {
NOTICE("var [%i] not set, not jumping", vn2);
pc += 6;
}
break;
default:
NOTICE("unknown [%i]", vn2);
break;
}
}
static int midi_thread(void *args) {
thread_running = TRUE;
NOTICE("midi_thread started");
start:
midi_allnotesoff();
midi_send_reset();
boolean pausing = FALSE;
int nevents = midi->eventsize;
pc = tick = ctick = 0;
tempo = 500000;
ppqn = tempo / midi->division;
while (TRUE) {
if (pc >= nevents) {
NOTICE("midi_thread finished midi file");
break;
}
if (should_stop) {
NOTICE("midi_thread received stop command");
break;
}
if (should_pause) {
NOTICE("midi_thread pausing");
midi_allnotesoff();
should_pause = FALSE;
pausing = TRUE;
}
if (should_unpause) {
NOTICE("midi_thread unpausing");
should_unpause = FALSE;
pausing = FALSE;
}
if (pausing) {
usleep(50*1000);
continue;
}
while (tick == midi->event[pc].ctime) {
midievent_t event = midi->event[pc];
midi_sync(event);
switch (midi->event[pc].type) {
case MIDI_EVENT_NORMAL:
midi_write(event);
break;
case MIDI_EVENT_TEMPO:
midi_settempo(event);
break;
case MIDI_EVENT_SYS35:
midi_handlesys35(event);
break;
default:
NOTICE("unknown type of event [%x]", event.type);
break;
}
}
tick++;
}
if (should_loop && !should_stop)
goto start;
if (midi != NULL) {
NOTICE("freeing midi file");
mf_remove_midifile(midi);
midi = NULL;
}
midi_allnotesoff();
usleep(10000);
midi_send_reset();
usleep(10000);
should_stop = FALSE;
thread_running = FALSE;
NOTICE("midi_thread done.");
return 0;
}
-493
View File
@@ -1,493 +0,0 @@
/*
* midi.rawmidi.c midi play with rawmidi device
*
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
*
* Based on midiplay+ by Daisuke NAGANO <breeze.nagano@nifty.ne.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: midi.rawmidi.c,v 1.7 2003/01/31 12:58:28 chikama Exp $ */
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#ifdef ENABLE_MIDI_SEQMIDI
#if defined(__FreeBSD__)
#include <machine/soundcard.h>
#elif defined(__OpenBSD__) || defined(__NetBSD__)
#include <soundcard.h>
#else
#include <sys/soundcard.h>
#endif
#include <sys/ioctl.h>
#endif
#include <SDL_thread.h>
#include <SDL_timer.h>
#include "portab.h"
#include "system.h"
#include "midi.h"
#include "music_private.h"
#include "midifile.h"
#include "msgqueue.h"
static struct {
char midi_variable[128];
char midi_flag[128];
} flags;
static void send_reset();
static int midi_initilize(char *devnm, int subdev);
static int midi_exit(void);
static int midi_reset(void);
static int midi_start(int no, int loop, char *data, int datalen);
static int midi_stop();
static int midi_pause(void);
static int midi_unpause(void);
static int midi_get_playing_info(midiplaystate *st);
static int midi_getflag(int mode, int index);
static int midi_setflag(int mode, int index, int val);
static void (*myflush)(void);
static void (*mywrite)(unsigned char *d, int n, int p);
#ifdef ENABLE_MIDI_RAWMIDI
static void raw_myflush();
static void raw_mywrite(unsigned char *d, int n, int p);
#endif
#ifdef ENABLE_MIDI_SEQMIDI
static void seq_myflush();
static void seq_mywrite(unsigned char *d, int n, int p);
#endif
mididevice_t midi_rawmidi = {
midi_initilize,
midi_exit,
midi_reset,
midi_start,
midi_stop,
midi_pause,
midi_unpause,
midi_get_playing_info,
midi_getflag,
midi_setflag,
NULL,
NULL,
NULL,
NULL
};
#ifndef MIDI_DEVICE
#define MIDI_DEVICE "/dev/midi"
#endif
#ifndef SEQ_DEVICE
#define SEQ_DEVICE "/dev/sequencer"
#endif
static boolean enabled = FALSE;
static int midifd = -1;
static char *mididevname;
static SDL_Thread *thread;
static struct msgq *queue;
static int start_time;
static char cmd_pause[] = "pause";
static char cmd_unpause[] = "unpause";
static char cmd_stop[] = "stop";
#define ALL_NOTEOFF_SZ 48
static char all_noteoff[] = { 0xb0, 0x7b, 0x00,
0xb1, 0x7b, 0x00,
0xb2, 0x7b, 0x00,
0xb3, 0x7b, 0x00,
0xb4, 0x7b, 0x00,
0xb5, 0x7b, 0x00,
0xb6, 0x7b, 0x00,
0xb7, 0x7b, 0x00,
0xb8, 0x7b, 0x00,
0xb9, 0x7b, 0x00,
0xba, 0x7b, 0x00,
0xbb, 0x7b, 0x00,
0xbc, 0x7b, 0x00,
0xbd, 0x7b, 0x00,
0xbe, 0x7b, 0x00,
0xbf, 0x7b, 0x00 };
#define ALL_RESET_SZ 96
static char all_reset[] = { 0xb0, 0x78, 0x00, 0xb0, 0x79, 0x00,
0xb1, 0x78, 0x00, 0xb1, 0x79, 0x00,
0xb2, 0x78, 0x00, 0xb2, 0x79, 0x00,
0xb3, 0x78, 0x00, 0xb3, 0x79, 0x00,
0xb4, 0x78, 0x00, 0xb4, 0x79, 0x00,
0xb5, 0x78, 0x00, 0xb5, 0x79, 0x00,
0xb6, 0x78, 0x00, 0xb6, 0x79, 0x00,
0xb7, 0x78, 0x00, 0xb7, 0x79, 0x00,
0xb8, 0x78, 0x00, 0xb8, 0x79, 0x00,
0xb9, 0x78, 0x00, 0xb9, 0x79, 0x00,
0xba, 0x78, 0x00, 0xba, 0x79, 0x00,
0xbb, 0x78, 0x00, 0xbb, 0x79, 0x00,
0xbc, 0x78, 0x00, 0xbc, 0x79, 0x00,
0xbd, 0x78, 0x00, 0xbd, 0x79, 0x00,
0xbe, 0x78, 0x00, 0xbe, 0x79, 0x00,
0xbf, 0x78, 0x00, 0xbf, 0x79, 0x00 };
static void send_reset() {
mywrite(all_reset, ALL_RESET_SZ, 0);
usleep(60000);
myflush();
usleep(70000);
return;
}
#ifdef ENABLE_MIDI_RAWMIDI
#define WRBFSIZE 16384
static unsigned char wrbuff[WRBFSIZE];
static int nwr = 0; /* wrbuff の index */
static void raw_myflush() {
for (int i = 0; i < nwr; i++) {
while (write(midifd, wrbuff+i, 1) != 1);
}
nwr = 0;
}
/*
* write the code to the buffer
*/
static void raw_mywrite(unsigned char *d, int n, int p) {
if ((nwr + n + 2) >= WRBFSIZE) {
myflush();
}
while (n--) {
wrbuff[nwr++] = *(d++);
}
return;
}
#endif
#ifdef ENABLE_MIDI_SEQMIDI
SEQ_DEFINEBUF(2048);
SEQ_USE_EXTBUF();
static int midi_subdev;
void seqbuf_dump(void) {
if (_seqbufptr) {
if (write(midifd, _seqbuf, _seqbufptr) == -1)
WARNING("write: %s", strerror(errno));
}
_seqbufptr = 0;
}
static void seq_myflush() {
seqbuf_dump();
}
/*
* write the code to the buffer
*/
static void seq_mywrite(unsigned char *d, int n, int p) {
while(n--) {
SEQ_MIDIOUT(midi_subdev, *(d++));
}
return;
}
#endif
static uint32_t ticks2ms(int ticks, int division, unsigned int tempo) {
return ticks * tempo / (division * 1000);
}
static void *midi_mainloop(struct midiinfo *midi) {
int i = 0;
int ctick = 0;
int tempo = 500000;
uint32_t last_time = SDL_GetTicks();
void *cmd;
while (i < midi->eventsize) {
if (ctick < midi->event[i].ctime) {
myflush();
int delta = midi->event[i].ctime - ctick;
uint32_t target_time = last_time + ticks2ms(delta, midi->division, tempo);
uint32_t current_time = SDL_GetTicks();
while (current_time < target_time) {
cmd = msgq_dequeue_timeout(queue, target_time - current_time);
if (cmd == cmd_stop)
return cmd;
if (cmd == cmd_pause) {
while (TRUE) {
cmd = msgq_dequeue(queue);
if (cmd == cmd_stop)
return cmd;
if (cmd == cmd_unpause)
break;
}
target_time += SDL_GetTicks() - current_time;
}
current_time = SDL_GetTicks();
}
last_time = target_time;
ctick = midi->event[i].ctime;
}
if (midi->event[i].type == 0) {
/* ordinary data */
mywrite(midi->event[i].data, midi->event[i].n, midi->event[i].port);
i++;
} else if (midi->event[i].type == 2) {
/* tempo change */
int *p = (int*)midi->event[i].data;
tempo = (unsigned int)*p;
i++;
} else if (midi->event[i].type == 3) {
/* system35 maker */
int vn1 = midi->event[i+1].data[2];
int vn2 = midi->event[i+2].data[2];
int vn3 = midi->event[i+3].data[2];
switch (vn1) {
case 0:
/* set label */
i += 6;
break;
case 1:
/* jump */
mywrite(all_noteoff, ALL_NOTEOFF_SZ, 0);
i = midi->sys35_label[vn2];
ctick = midi->event[i].ctime;
break;
case 2:
/* set flag */
flags.midi_flag[vn2] = vn3;
i += 6;
break;
case 3:
/* flag jump */
if (flags.midi_flag[vn2] == 1) {
i = midi->sys35_label[vn3];
ctick = midi->event[i].ctime;
mywrite(all_noteoff, ALL_NOTEOFF_SZ, 0);
} else {
i += 6;
}
break;
case 4:
/* set variable */
flags.midi_variable[vn2] = vn3;
i += 6;
break;
case 5:
/* variable jump */
if (--(flags.midi_variable[vn2]) == 0) {
i = midi->sys35_label[vn3];
ctick = midi->event[i].ctime;
mywrite(all_noteoff, ALL_NOTEOFF_SZ, 0);
} else {
i += 6;
}
break;
}
} else {
WARNING("Unknown type of event %x (NEVER!).", midi->event[i].type);
}
}
return NULL;
}
static int midi_initilize(char *devnm, int subdev) {
enabled = FALSE;
if (devnm == NULL) {
if (subdev == -1) {
mididevname = MIDI_DEVICE;
} else {
mididevname = SEQ_DEVICE;
}
} else {
mididevname = devnm;
}
if (subdev == -1) {
#ifdef ENABLE_MIDI_RAWMIDI
myflush = raw_myflush;
mywrite = raw_mywrite;
NOTICE("RAWMIDI Initilize OK");
#endif
} else {
#ifdef ENABLE_MIDI_SEQMIDI
myflush = seq_myflush;
mywrite = seq_mywrite;
midi_subdev = subdev;
NOTICE("SEQMIDI Initilize OK");
#endif
}
enabled = TRUE;
return OK;
}
static int midi_exit(void) {
if (enabled) {
midi_stop();
}
return OK;
}
static int midi_reset(void) {
if (enabled) {
midi_stop();
}
return OK;
}
static int midi_thread(void *data) {
send_reset();
void *cmd = midi_mainloop(data);
send_reset();
mf_remove_midifile(data);
close(midifd);
midifd = -1;
while (cmd != cmd_stop)
cmd = msgq_dequeue(queue);
return 0;
}
/* no = 0~ */
static int midi_start(int no, int loop, char *data, int datalen) {
if (queue)
midi_stop();
struct midiinfo *midi = mf_read_midifile(data, datalen);
if (!midi) {
WARNING("error reading midi file");
return NG;
}
if (0 > (midifd = open(mididevname, O_RDWR))) {
WARNING("error opening %s: %s", mididevname, strerror(errno));
mf_remove_midifile(midi);
return NG;
}
#ifdef ENABLE_SEQMIDI
{
int nrsynths;
if (-1 == ioctl(mididev, SNDCTL_SEQ_NRSYNTHS, &nrsynths)) {
WARNING("SNDCTL_SEQ_NRSYNTHS: %s", strerror(errno));
mf_remove_midifile(midi);
close(midifd);
midifid = -1;
return NG;
}
}
#endif
queue = msgq_new();
thread = SDL_CreateThread(midi_thread, "MIDI", midi);
start_time = SDL_GetTicks();
return OK;
}
static int midi_stop() {
if (!enabled || !queue) {
return OK;
}
msgq_enqueue(queue, cmd_stop);
SDL_WaitThread(thread, NULL);
thread = NULL;
msgq_free(queue);
queue = NULL;
return OK;
}
static int midi_pause(void) {
if (!enabled || !queue) return OK;
msgq_enqueue(queue, cmd_pause);
return OK;
}
static int midi_unpause(void) {
if (!enabled || !queue) return OK;
msgq_enqueue(queue, cmd_unpause);
return OK;
}
static int midi_get_playing_info(midiplaystate *st) {
if (!enabled || !queue) {
st->in_play = FALSE;
st->loc_ms = 0;
return OK;
}
if (midifd < 0) {
midi_stop();
st->in_play = FALSE;
st->loc_ms = 0;
return OK;
}
st->in_play = TRUE;
st->loc_ms = SDL_GetTicks() - start_time;
return OK;
}
static int midi_getflag(int mode, int index) {
if (mode == 0) {
/* flag */
return flags.midi_flag[index];
} else {
/* variable */
return flags.midi_variable[index];
}
}
static int midi_setflag(int mode, int index, int val) {
if (mode == 0) {
/* flag */
flags.midi_flag[index] = val;
} else {
/* variable */
flags.midi_variable[index] = val;
}
return OK;
}
+3 -3
View File
@@ -31,7 +31,7 @@
#define MIX_INIT_MID MIX_INIT_FLUIDSYNTH
#endif
static int midi_initilize(char *pname, int subdev);
static int midi_initialize(int subdev);
static int midi_exit(void);
static int midi_reset(void);
static int midi_start(int no, int loop, char *data, int datalen);
@@ -48,7 +48,7 @@ static boolean midi_fading();
#define midi midi_sdlmixer
mididevice_t midi = {
midi_initilize,
midi_initialize,
midi_exit,
midi_reset,
midi_start,
@@ -68,7 +68,7 @@ static Mix_Music *mix_music;
static int start_time;
static uint32_t fade_tick;
static int midi_initilize(char *pname, int subdev) {
static int midi_initialize(int subdev) {
if (Mix_Init(MIX_INIT_MID) != MIX_INIT_MID)
return NG;
return OK;
+190 -485
View File
@@ -3,6 +3,7 @@
*
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
* 2024 kichikuou <KichikuouChrome@gmail.com>
*
* Based on midiplay+ by Daisuke NAGANO <breeze.nagano@nifty.ne.jp>
*
@@ -28,557 +29,261 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <portmidi.h>
#include "portab.h"
#include "system.h"
#include "midifile.h"
static long to32bit(int c1, int c2, int c3, int c4);
static void midi_inc();
static void make_chunk(struct midievent *ev, int n);
static void midi_noteoff(int chan, int note, int vol);
static void midi_noteon(int chan, int note, int vol);
static void midi_pressure(int chan, int note, int press);
static void midi_controlparameter(int chan, int cnt, int val);
static void midi_pitchbend(int chan, int lsb, int msg);
static void midi_program(int chan, int prog);
static void midi_chanpressure(int chan, int press);
static void midi_tempo(int tempo);
static void chanmessage(int status, int c1, int c2);
static void metaevent(int type);
static void msginit();
static void msgadd(int c);
// static int msglen();
static char *msg();
static int midigetc();
static long readvarinum();
static void read_playevent();
static int read_header(uint8_t *stream, off_t len);
// magic bytes
#define RIFF 0x52494646
#define MThd 0x4d546864
#define MTrk 0x4d54726b
static struct midiinfo *midi;
// MIDI commands
#define MIDI_CONTROL 0xb0
#define Read16() \
(*stream << 8) | (*(stream + 1)), stream+=2
#define META_END_OF_TRACK 0x2f
#define META_SET_TEMPO 0x51
#define Read32() \
(*stream << 24) | (*(stream + 1) << 16) | (*(stream + 2) << 8) | (*(stream + 3)), stream+=4
struct stream {
uint8_t *p;
uint8_t *end;
};
static long to32bit(int c1, int c2, int c3, int c4) {
long value = 0L;
value = (c1 & 0xff);
value = (value << 8) + (c2 & 0xff);
value = (value << 8) + (c3 & 0xff);
value = (value << 8) + (c4 & 0xff);
static inline uint8_t read8(struct stream *input) {
return *input->p++;
}
static inline uint16_t read16_be(struct stream *s) {
uint16_t val = s->p[0] << 8 | s->p[1];
s->p += 2;
return val;
}
static inline uint32_t read32_be(struct stream *s) {
uint32_t val = s->p[0] << 24 | s->p[1] << 16 | s->p[2] << 8 | s->p[3];
s->p += 4;
return val;
}
static int read_vlq(struct stream *input) {
int c, value = 0;
do {
c = read8(input);
value = (value << 7) | (c & 0x7f);
} while (c & 0x80);
return value;
}
static void midi_inc() {
midi->ceptr++;
if (midi->ceptr > MAXMIDIEVENT) {
NOTICE("too much event");
sys_exit(0);
/*
* System 3.x defines custom (non-standard) MIDI commands using Registered
* Parameter Numbers (RPN). A custom command is represented by the following
* sequence of MIDI events:
*
* b0 65 64 ; set RPN MSB to 100
* b0 64 XX ; set RPN LSB to XX
* b0 06 YY ; set data MSB to YY
* b0 26 ZZ ; set data LSB to ZZ
* b0 65 7f ; unset RPN MSB
* b0 64 7f ; unset RPN LSB
*
* XX represents the command number, and YY and ZZ are data values. The
* following commands are defined:
*
* 00: Label definition. Defines a label #YY at the location of this event.
* 01: Label jump. Jumps to the label #YY.
* 02: Flag set. Sets the flag #YY to the value ZZ.
* 03: Flag jump. If the flag #YY is set to 1, jumps to the label #YY.
* 04: Variable set. Sets the variable #YY to the value ZZ.
* 05: Variable jump. Decrements the variable #YY by 1. If it reaches 0, jumps
* to the label #ZZ.
*
* Flags and variables can be retrieved or set from scenario scripts, using the
* SG command.
*/
#define CC_DATA_ENTRY_MSB 0x06
#define CC_DATA_ENTRY_LSB 0x26
#define CC_RPN_LSB 0x64
#define CC_RPN_MSB 0x65
#define SYS35_RPN_MSB 0x64
#define RPN_NULL 0x7f
static bool check_sys35cmd(int32_t msg, int *state) {
if ((Pm_MessageStatus(msg) & 0xf0) != MIDI_CONTROL) {
*state = 0;
return false;
}
}
static void make_chunk(struct midievent *ev, int n) {
ev->type = 0;
ev->ctime = midi->curtime;
ev->n = n;
ev->port = 0;
if (n != 0) {
ev->data = malloc(sizeof(unsigned char) * (n + 1));
}
}
int data1 = Pm_MessageData1(msg);
int data2 = Pm_MessageData2(msg);
(*state)++;
static void midi_noteoff(int chan, int note, int vol) {
make_chunk(&midi->event[midi->ceptr], 3);
midi->event[midi->ceptr].data[0] = MIDI_NOTEOFF + chan;
midi->event[midi->ceptr].data[1] = note;
midi->event[midi->ceptr].data[2] = vol;
midi_inc();
}
static void midi_noteon(int chan, int note, int vol) {
make_chunk(&midi->event[midi->ceptr], 3);
midi->event[midi->ceptr].data[0] = MIDI_NOTEON + chan;
midi->event[midi->ceptr].data[1] = note;
midi->event[midi->ceptr].data[2] = vol;
midi_inc();
}
static void midi_pressure(int chan, int note, int press) {
make_chunk(&midi->event[midi->ceptr], 3);
midi->event[midi->ceptr].data[0] = MIDI_PRESSURE + chan;
midi->event[midi->ceptr].data[1] = note;
midi->event[midi->ceptr].data[2] = press;
midi_inc();
}
static int check_sys35mark(int *fnc, int *val1, int *val2) {
midi->marker++;
switch(midi->marker) {
switch (*state) {
case 1:
if (midi->event[midi->ceptr].data[1] != 101 ||
midi->event[midi->ceptr].data[2] != 100) {
midi->marker = 0;
}
if (data1 == CC_RPN_MSB && data2 == SYS35_RPN_MSB)
return false;
break;
case 2:
if (midi->event[midi->ceptr].data[1] != 100) {
midi->marker = 0;
}
if (data1 == CC_RPN_LSB)
return false;
break;
case 3:
if (midi->event[midi->ceptr].data[1] != 6) {
midi->marker = 0;
}
if (data1 == CC_DATA_ENTRY_MSB)
return false;
break;
case 4:
if (midi->event[midi->ceptr].data[1] != 38) {
midi->marker = 0;
}
if (data1 == CC_DATA_ENTRY_LSB)
return false;
break;
case 5:
if (midi->event[midi->ceptr].data[1] != 101 ||
midi->event[midi->ceptr].data[2] != 127) {
midi->marker = 0;
}
if (data1 == CC_RPN_MSB && data2 == RPN_NULL)
return false;
break;
case 6:
if (midi->event[midi->ceptr].data[1] != 100 ||
midi->event[midi->ceptr].data[2] != 127) {
midi->marker = 0;
} else {
midi->marker = 0;
*fnc = midi->event[midi->ceptr-4].data[2];
*val1 = midi->event[midi->ceptr-3].data[2];
*val2 = midi->event[midi->ceptr-2].data[2];
return 1;
if (data1 == CC_RPN_LSB && data2 == RPN_NULL) {
*state = 0;
return true;
}
break;
}
return 0;
*state = 0;
return false;
}
static void midi_controlparameter(int chan, int cnt, int val) {
int fnc, val1, val2;
make_chunk(&midi->event[midi->ceptr], 3);
midi->event[midi->ceptr].data[0] = MIDI_CONTROL + chan;
midi->event[midi->ceptr].data[1] = cnt;
midi->event[midi->ceptr].data[2] = val;
if (check_sys35mark(&fnc, &val1, &val2) > 0) {
midi->event[midi->ceptr - 5].type = 3;
/* ラベル登録 */
if (fnc == 0) {
midi->sys35_label[val1] = midi->ceptr -5;
}
static void add_event(struct midiinfo *midi, int *event_buffer_size, enum midi_event_type type, int curtime, int32_t data) {
if (midi->nr_events >= *event_buffer_size) {
*event_buffer_size = *event_buffer_size ? *event_buffer_size * 3 / 2 : 4096;
midi->event = realloc(midi->event, *event_buffer_size * sizeof(struct midievent));
}
midi_inc();
midi->event[midi->nr_events].type = type;
midi->event[midi->nr_events].ctime = curtime;
midi->event[midi->nr_events].data = data;
midi->nr_events++;
}
static void midi_pitchbend(int chan, int lsb, int msg) {
make_chunk(&midi->event[midi->ceptr], 3);
midi->event[midi->ceptr].data[0] = MIDI_PITCHB + chan;
midi->event[midi->ceptr].data[1] = lsb;
midi->event[midi->ceptr].data[2] = msg;
midi_inc();
}
static void midi_program(int chan, int prog) {
make_chunk(&midi->event[midi->ceptr], 2);
midi->event[midi->ceptr].data[0] = MIDI_PROGRAM + chan;
midi->event[midi->ceptr].data[1] = prog;
midi_inc();
}
static void midi_chanpressure(int chan, int press) {
make_chunk(&midi->event[midi->ceptr], 2);
midi->event[midi->ceptr].data[0] = MIDI_CHANPRES + chan;
midi->event[midi->ceptr].data[1] = press;
midi_inc();
}
static void midi_tempo(int tempo) {
unsigned char x[4];
unsigned int *p;
p = (unsigned int*)x;
*p = (unsigned int)tempo;
make_chunk(&midi->event[midi->ceptr], sizeof(unsigned long));
midi->event[midi->ceptr].type = 2; /* tempo change (msec/midi-qnote) */
midi->event[midi->ceptr].data[0] = x[0];
midi->event[midi->ceptr].data[1] = x[1];
midi->event[midi->ceptr].data[2] = x[2];
midi->event[midi->ceptr].data[3] = x[3];
midi_inc();
}
static void chanmessage(int status, int c1, int c2) {
int chan = status & 0xf;
switch (status & 0xf0) {
case 0x80:
midi_noteoff(chan, c1, c2);
break;
case 0x90:
midi_noteon(chan, c1, c2);
break;
case 0xa0:
midi_pressure(chan, c1, c2);
break;
case 0xb0:
midi_controlparameter(chan, c1, c2);
break;
case 0xe0:
midi_pitchbend(chan, c1, c2);
break;
case 0xc0:
midi_program(chan, c1);
break;
case 0xd0:
midi_chanpressure(chan, c1);
break;
default:
NOTICE("Unknown Message");
}
}
static void metaevent(int type) {
// int len = msglen();
char *m = msg();
switch(type) {
case 0x00:
NOTICE("seqnum");
break;
case 0x01:
NOTICE("text event (Text Event, Ignored)");
break;
case 0x02:
NOTICE("copyright notice (Text Event, Ignored)");
break;
case 0x03:
NOTICE("sequence / track name (Text Event, Ignored)");
break;
case 0x04:
NOTICE("instrument name (Text Event, Ignored)");
break;
case 0x05:
NOTICE("lyric (Text Event, Ignored)");
break;
case 0x06:
NOTICE("marker (Text Event, Ignored)");
break;
case 0x07:
NOTICE("cue point (Text Event, Ignored)");
break;
case 0x08:
NOTICE("meta event 0x08 (Text Event, Ignored)");
break;
case 0x09:
NOTICE("meta event 0x09 (Text Event, Ignored)");
break;
case 0x0a:
NOTICE("meta event 0x0a (Text Event, Ignored)");
break;
case 0x0b:
NOTICE("meta event 0x0b (Text Event, Ignored)");
break;
case 0x0c:
NOTICE("meta event 0x0c (Text Event, Ignored)");
break;
case 0x0d:
NOTICE("meta event 0x0d (Text Event, Ignored)");
break;
case 0x0e:
NOTICE("meta event 0x0e (Text Event, Ignored)");
break;
case 0x0f:
NOTICE("meta event 0x0f (Text Event, Ignored)");
break;
case 0x2f:
/* EOF */
midi->length_left = 0;
midi->eventsize = midi->ceptr;
break;
case 0x51:
midi_tempo(to32bit(0, m[0], m[1], m[2]));
break;
case 0x54:
NOTICE("set smpte");
break;
case 0x58:
NOTICE("time sig (Ignore)");
break;
case 0x59:
NOTICE("keysig (Ignore)");
break;
case 0x7f:
NOTICE("seq specific");
break;
default:
NOTICE("meta misc");
break;
}
}
static void msginit() {
midi->msgindex = 0;
}
static void msgadd(int c) {
if (midi->msgindex >= midi->msgsize) {
midi->msgsize *= 2;
midi->msgbuffer = (unsigned char *)realloc(midi->msgbuffer, midi->msgsize);
}
midi->msgbuffer[midi->msgindex++] = (unsigned char)c;
}
#if 0
static int msglen() {
return midi->msgindex;
}
#endif
static char *msg() {
return midi->msgbuffer;
}
static int midigetc() {
midi->length_left--;
return *midi->cdata++;
}
/* readvarinum - read a varying-length number, and return the */
/* number of characters it took. */
static long readvarinum() {
long value;
int c;
value = c = midigetc();
if (c & 0x80) {
value &= 0x7f;
do {
c = midigetc();
value = (value << 7) + (c & 0x7f);
} while (c & 0x80);
}
return value;
}
static void read_playevent() {
int c, c1, type;
int running = 0; /* 1 when running status used */
int status = 0; /* status value (e.g. 0x90==note-on) */
int delta, needed, lookfor, len;
static void read_events(struct midiinfo *midi, struct stream *input) {
/* This array is indexed by the high half of a status byte. It's */
/* value is either the number of bytes needed (1 or 2) for a channel */
/* message, or 0 (meaning it's not a channel message). */
static int chantype[] = {
const int chantype[] = {
0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 through 0x70 */
2, 2, 2, 2, 1, 1, 2, 0 /* 0x80 through 0xf0 */
};
midi->cdata = midi->data;
midi->length_left = midi->length;
midi->curtime = 0;
midi->ceptr = 0;
while(midi->length_left > 0) {
midi->curtime += (delta = readvarinum()); /* delta time for midi event */
c = midigetc();
if ((c & 0x80) == 0) {
running = 1;
int curtime = 0;
int event_buffer_size = 0;
int status = 0; /* status value (e.g. 0x90==note-on) */
bool running = false;
int sys35cmd_state = 0;
while (input->p < input->end) {
int delta = read_vlq(input);
curtime += delta; /* delta time for midi event */
int c = read8(input);
if (!(c & 0x80)) {
running = true;
} else {
status = c;
running = 0;
}
needed = chantype[(status >> 4) & 0x0f];
if (needed) { /* ie. is it a channel message? */
if (running) {
c1 = c;
} else {
c1 = midigetc();
}
chanmessage(status, c1, (needed > 1) ? midigetc() : 0);
if ((status & 0xf0) != 0xb0) {
midi->marker = 0; /* maker flag clear */
}
continue;;
running = false;
}
midi->marker = 0; /* maker flag clear */
int needed = chantype[(status >> 4) & 0x0f];
if (needed) { /* ie. is it a channel message? */
int c1 = running ? c : read8(input);
int c2 = needed > 1 ? read8(input) : 0;
int32_t msg = Pm_Message(status, c1, c2);
add_event(midi, &event_buffer_size, MIDI_EVENT_NORMAL, curtime, msg);
if (check_sys35cmd(msg, &sys35cmd_state)) {
int command_top = midi->nr_events - MIDI_SYS35_EVENT_SIZE;
midi->event[command_top].type = MIDI_EVENT_SYS35;
int cmd = Pm_MessageData2(midi->event[command_top + 1].data);
int val1 = Pm_MessageData2(midi->event[command_top + 2].data);
if (cmd == MIDI_SYS35_LABEL_DEFINITION)
midi->sys35_label[val1] = command_top;
}
continue;
}
sys35cmd_state = 0;
int type, len;
switch (c) {
case 0xFF: /* meta event */
type = midigetc();
len = readvarinum();
lookfor = midi->length_left - len;
msginit();
while(midi->length_left > lookfor) {
msgadd(midigetc());
type = read8(input);
len = read_vlq(input);
switch(type) {
case META_END_OF_TRACK:
return;
case META_SET_TEMPO:
add_event(midi, &event_buffer_size, MIDI_EVENT_TEMPO, curtime, input->p[0] << 16 | input->p[1] << 8 | input->p[2]);
break;
}
metaevent(type);
input->p += len;
break;
case 0xF0: /* system exclusive */
len = readvarinum();
lookfor = midi->length_left - len;
msginit();
msgadd(0xF0);
while(midi->length_left > lookfor) {
msgadd(midigetc());
}
NOTICE("system exculsive ( not supported )");
input->p += read_vlq(input);
break;
case 0xF7: /* system exclusive continuation or arbitrary stuff */
len = readvarinum();
lookfor = midi->length_left - len;
msginit();
while(midi->length_left > lookfor) {
msgadd(c = midigetc());
}
NOTICE("system exclusive cont. ( not supporte d)");
input->p += read_vlq(input);
break;
default:
NOTICE("Unknow Event ( not supported )");
WARNING("SMF: Unknown Event 0x%x", c);
}
}
}
static int read_header(uint8_t *stream, off_t len) {
int tracklen, i = 0;
uint8_t *stream_top = stream;
while(i == 0 && stream < (stream_top + len)) {
if (0 == strncmp(stream, "MThd", 4)) {
stream += 4;
i++;
} else {
stream++;
}
static bool read_header(struct midiinfo *midi, struct stream *input) {
int magic = read32_be(input);
if (magic == RIFF) {
input->p += 16;
magic = read32_be(input);
}
if (stream != stream_top) {
stream -= 4;
}
i = Read32();
if (i == RIFF) {
stream += 16;
i = Read32();
}
if (i == MThd) {
tracklen = Read32();
midi->format = Read16();
midi->ntrks = Read16();
midi->division = Read16();
} else {
boolean found = FALSE;
while (!found && stream < (stream_top + len - 8)) {
if (0 == strncmp(stream, "MThd", 4)) {
found = TRUE;
} else {
stream++;
}
}
if (found) {
stream += 4;
tracklen = Read32();
midi->format = Read16();
midi->ntrks = Read16();
midi->division = Read16();
} else {
WARNING("unknow format");
return NG;
}
}
if (midi->ntrks != 1) {
WARNING("multiple track (format 1) is not supported");
return NG;
}
NOTICE("tracklen = %d, format = %d, ntrks = %d, division = %d",
tracklen, midi->format, midi->ntrks, midi->division);
i = Read32();
if (i != MTrk) {
WARNING("Unknow format");
}
tracklen = Read32();
if (stream + tracklen > stream_top + len) {
tracklen = stream + len - stream_top;
}
midi->length = tracklen;
midi->data = stream;
return OK;
if (magic != MThd)
return false;
if (read32_be(input) != 6) // header size
return false;
if (read16_be(input) != 0) // format
return false;
if (read16_be(input) != 1) // number of tracks
return false;
midi->division = read16_be(input);
magic = read32_be(input);
if (magic != MTrk)
return false;
int tracklen = read32_be(input);
if (input->p + tracklen < input->end)
input->end = input->p + tracklen;
return true;
}
struct midiinfo *mf_read_midifile(uint8_t *stream, off_t len) {
midi = malloc(sizeof(struct midiinfo));
midi->msgsize = 128; /* Initial msg buffer size */
midi->msgbuffer = calloc(midi->msgsize, sizeof(unsigned char));
if (0 > read_header(stream, len)) {
struct midiinfo *mf_read_midifile(uint8_t *data, size_t len) {
struct stream input = { .p = data, .end = data + len };
struct midiinfo *midi = calloc(1, sizeof(struct midiinfo));
if (!read_header(midi, &input)) {
free(midi);
return NULL;
}
read_playevent();
read_events(midi, &input);
return midi;
}
void mf_remove_midifile(struct midiinfo *m) {
int i;
free(m->msgbuffer);
for (i = 0; i < m->eventsize; i ++) {
free(m->event[i].data);
}
free(m->event);
free(m);
}
+23 -56
View File
@@ -26,74 +26,41 @@
#ifndef __MIDIFILE_H__
#define __MIDIFILE_H__
#include <stdio.h>
#include <sys/types.h>
#include "portab.h"
/* Non-standard MIDI file formats */
#define RIFF 0x52494646
#define CTMF 0x43544d46
/* Standard MIDI file format definitions */
#define MThd 0x4d546864
#define MTrk 0x4d54726b
enum midi_event_type {
MIDI_EVENT_NORMAL,
MIDI_EVENT_TEMPO, /* tempo change (msec/midi-qnote) */
MIDI_EVENT_SYS35
};
/* MIDI COMMANDS */
#define MIDI_NOTEOFF 0x80 /* Note off */
#define MIDI_NOTEON 0x90 /* Note on */
#define MIDI_PRESSURE 0xa0 /* Polyphonic key pressure */
#define MIDI_CONTROL 0xb0 /* Control change */
#define MIDI_PROGRAM 0xc0 /* Program change */
#define MIDI_CHANPRES 0xd0 /* Channel pressure */
#define MIDI_PITCHB 0xe0 /* Pitch wheel change */
#define MIDI_SYSEX 0xf0 /* System exclusive data */
#define MIDI_SYS35_EVENT_SIZE 6
#define MIDI_EVENT_NORMAL 0
#define MIDI_EVENT_TEXT 1
#define MIDI_EVENT_TEMPO 2
#define MIDI_EVENT_SYS35 3
#define MAXMIDIEVENT 65536 /* maxium event sequence number */
enum midi_sys35_event_type {
MIDI_SYS35_LABEL_DEFINITION = 0,
MIDI_SYS35_LABEL_JUMP = 1,
MIDI_SYS35_FLAG_SET = 2,
MIDI_SYS35_FLAG_JUMP = 3,
MIDI_SYS35_VARIABLE_SET = 4,
MIDI_SYS35_VARIABLE_JUMP = 5,
};
struct midievent {
int type; /* Data type
0: normal
1: text
2: tempo change
3: system35 message
*/
unsigned long ctime; /* steptime */
int n; /* data length */
int port; /* midi port */
unsigned char *data; /* midi data */
enum midi_event_type type;
int ctime; /* steptime */
int32_t data;
};
struct midiinfo {
int format; /* MIDI format version ( only 0 is supported) */
int division; /* division for delta time*/
int ntrks; /* number of track */
uint8_t *data;
uint8_t *cdata;
int length;
int length_left;
struct midievent event[MAXMIDIEVENT]; /* event data */
int eventsize; /* total event size */
int ceptr; /* current event pointer */
/* work info */
long curtime; /* current time */
size_t msgindex; /* midi message buffer index */
size_t msgsize; /* size of current allocaed msg */
unsigned char *msgbuffer; /* message buffer */
/* system35 jump info */
int sys35_label[127];
int marker;
struct midievent *event;
int nr_events;
int sys35_label[128]; /* system35 jump info */
};
extern struct midiinfo *mf_read_midifile(uint8_t *stream, off_t len);
extern struct midiinfo *mf_read_midifile(uint8_t *stream, size_t len);
extern void mf_remove_midifile(struct midiinfo *m);
#endif /* __MIDIFILE_H__ */
-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;
+8 -8
View File
@@ -36,16 +36,16 @@ EM_JS(int, muspcm_reset, (void), {
return xsystem35.audio.pcm_reset();;
});
EM_JS(int, muspcm_load_no, (int slot, int no), { // async
return xsystem35.audio.pcm_load(slot, no);
EM_ASYNC_JS(int, muspcm_load_no, (int slot, int no), {
return await xsystem35.audio.pcm_load(slot, no);
});
EM_JS(int, muspcm_load_data, (int slot, uint8_t *buf, uint32_t len), { // async
return xsystem35.audio.pcm_load_data(slot, buf, len);
EM_ASYNC_JS(int, muspcm_load_data, (int slot, uint8_t *buf, uint32_t len), {
return await xsystem35.audio.pcm_load_data(slot, buf, len);
});
EM_JS(int, muspcm_load_mixlr, (int slot, int noL, int noR), { // async
return xsystem35.audio.pcm_load_mixlr(slot, noL, noR);
EM_ASYNC_JS(int, muspcm_load_mixlr, (int slot, int noL, int noR), {
return await xsystem35.audio.pcm_load_mixlr(slot, noL, noR);
});
EM_JS(int, muspcm_unload, (int slot), {
@@ -91,6 +91,6 @@ EM_JS(boolean, muspcm_isplaying, (int slot), {
return xsystem35.audio.pcm_isplaying(slot);
});
EM_JS(int, muspcm_waitend, (int slot), { // async
return xsystem35.audio.pcm_waitend(slot);
EM_ASYNC_JS(int, muspcm_waitend, (int slot), {
return await xsystem35.audio.pcm_waitend(slot);
});
+2 -2
View File
@@ -79,7 +79,6 @@ extern void sdl_copy_from_alpha(int sx, int sy, int w, int h, int dx, int dy, AL
extern void sdl_copy_to_alpha(int sx, int sy, int w, int h, int dx, int dy, ALPHA_DIB_COPY_TYPE flag);
extern void sdl_getPixel(int x, int y, Palette *cell);
extern void sdl_putRegion(void *src, int x, int y);
extern void sdl_CopyRegion(void *src, int sx, int sy, int w, int h, int dx, int dy);
extern void sdl_restoreRegion(void *src, int x, int y);
extern void* sdl_saveRegion(int x, int y, int w, int h);
extern void sdl_delRegion(void *src);
@@ -88,8 +87,9 @@ extern SDL_Surface *com2surface(agsurface_t *s);
/* Effects */
struct sdl_effect;
struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int oy, agsurface_t *new, int nx, int ny, enum sdl_effect_type effect);
struct sdl_effect *sdl_sprite_effect_init(SDL_Rect *rect, int dx, int dy, int sx, int sy, int col, enum sdl_effect_type type);
struct sdl_effect *sdl_effect_magnify_init(agsurface_t *surface, SDL_Rect *view_rect, SDL_Rect *target_rect);
void sdl_effect_step(struct sdl_effect *eff, double progress);
void sdl_effect_step(struct sdl_effect *eff, float progress);
void sdl_effect_finish(struct sdl_effect *eff);
/* key/pointer 関係 */
+12 -22
View File
@@ -30,17 +30,7 @@
#include "sdl_private.h"
/* マウスカーソルフォントイメージ*/
#include "bitmaps/cursor_arrow.xpm"
#include "bitmaps/cursor_busy.xpm"
#include "bitmaps/cursor_no.xpm"
#include "bitmaps/cursor_move.xpm"
#include "bitmaps/cursor_cross.xpm"
#include "bitmaps/cursor_size_h.xpm"
#include "bitmaps/cursor_size_l.xpm"
#include "bitmaps/cursor_size_r.xpm"
#include "bitmaps/cursor_size_v.xpm"
#include "bitmaps/cursor_uparrow.xpm"
#include "bitmaps/cursor_ibeam.xpm"
static SDL_Cursor *cursor[256];
@@ -80,20 +70,20 @@ static SDL_Cursor *init_system_cursor(const char *image[]) {
return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
}
/* mouse cursur の初期化 */
void sdl_cursor_init(void) {
cursor[CURSOR_ARROW] = init_system_cursor(cursor_arrow);
cursor[CURSOR_CROSS] = init_system_cursor(cursor_cross);
cursor[CURSOR_IBEAM] = init_system_cursor(cursor_ibeam);
cursor[CURSOR_NO] = init_system_cursor(cursor_no);
cursor[CURSOR_SIZE] = init_system_cursor(cursor_move);
cursor[CURSOR_SIZEALL] = init_system_cursor(cursor_move);
cursor[CURSOR_SIZENESW] = init_system_cursor(cursor_size_r);
cursor[CURSOR_SIZENS] = init_system_cursor(cursor_size_v);
cursor[CURSOR_SIZENWSE] = init_system_cursor(cursor_size_l);
cursor[CURSOR_SIZEWE] = init_system_cursor(cursor_size_h);
cursor[CURSOR_ARROW] = SDL_GetDefaultCursor();
cursor[CURSOR_CROSS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR);
cursor[CURSOR_IBEAM] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
cursor[CURSOR_ICON] = SDL_GetDefaultCursor();
cursor[CURSOR_NO] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
cursor[CURSOR_SIZE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
cursor[CURSOR_SIZEALL] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
cursor[CURSOR_SIZENESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
cursor[CURSOR_SIZENS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
cursor[CURSOR_SIZENWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
cursor[CURSOR_SIZEWE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
cursor[CURSOR_UPARROW] = init_system_cursor(cursor_uparrow);
cursor[CURSOR_WAIT] = init_system_cursor(cursor_busy);
cursor[CURSOR_WAIT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT);
}
boolean sdl_cursorNew(uint8_t* data, int no, CursorImage *cursorImage, TCursorDirEntry *cursordirentry) {
+18 -6
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();
});
@@ -201,10 +202,7 @@ void sdl_copyArea(int sx, int sy, int w, int h, int dx, int dy) {
}
}
/*
* dib sp
*/
void sdl_copyAreaSP(int sx, int sy, int w, int h, int dx, int dy, uint8_t sp) {
static void sdl_dib_sprite_copy(SDL_Surface *dst, int sx, int sy, int w, int h, int dx, int dy, uint8_t sp) {
sdl_pal_check();
Uint32 col = palette_color(sp);
@@ -213,10 +211,24 @@ void sdl_copyAreaSP(int sx, int sy, int w, int h, int dx, int dy, uint8_t sp) {
SDL_Rect r_src = {sx, sy, w, h};
SDL_Rect r_dst = {dx, dy, w, h};
SDL_BlitSurface(sdl_dib, &r_src, sdl_dib, &r_dst);
SDL_BlitSurface(sdl_dib, &r_src, dst, &r_dst);
SDL_SetColorKey(sdl_dib, SDL_FALSE, 0);
}
/*
* dib sp
*/
void sdl_copyAreaSP(int sx, int sy, int w, int h, int dx, int dy, uint8_t sp) {
sdl_dib_sprite_copy(sdl_dib, sx, sy, w, h, dx, dy, sp);
}
SDL_Surface *sdl_dib_to_surface_colorkey(int x, int y, int w, int h, int sp) {
SDL_Surface *s = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_ARGB8888);
SDL_FillRect(s, NULL, 0);
sdl_dib_sprite_copy(s, x, y, w, h, 0, 0, sp);
return s;
}
void sdl_drawImage8_fromData(cgdata *cg, int dx, int dy, int sprite_color) {
int w = cg->width;
int h = cg->height;
+292 -115
View File
@@ -27,10 +27,15 @@
#include "sdl_core.h"
#include "sdl_private.h"
#define M_PIf ((float)M_PI)
#define HAS_SDL_RenderGeometry SDL_VERSION_ATLEAST(2, 0, 18)
enum sdl_effect_type from_nact_effect(enum nact_effect effect) {
switch (effect) {
case NACT_EFFECT_PAN_IN_DOWN: return EFFECT_PAN_IN_DOWN;
case NACT_EFFECT_PAN_IN_UP: return EFFECT_PAN_IN_UP;
case NACT_EFFECT_SKIP_LINE_UP_DOWN: return EFFECT_SKIP_LINE_UP_DOWN;
case NACT_EFFECT_SKIP_LINE_LR_RL: return EFFECT_SKIP_LINE_LR_RL;
case NACT_EFFECT_WIPE_IN: return EFFECT_WIPE_IN;
case NACT_EFFECT_WIPE_OUT: return EFFECT_WIPE_OUT;
case NACT_EFFECT_ZOOM_IN: return EFFECT_ZOOM_IN;
@@ -77,6 +82,17 @@ enum sdl_effect_type from_nact_effect(enum nact_effect effect) {
}
}
enum sdl_effect_type from_nact_sprite_effect(enum nact_effect effect) {
switch (effect) {
case NACT_EFFECT_PAN_IN_DOWN: return EFFECT_PAN_IN_DOWN;
case NACT_EFFECT_PAN_IN_UP: return EFFECT_PAN_IN_UP;
case NACT_EFFECT_SKIP_LINE_UP_DOWN: return EFFECT_SKIP_LINE_UP_DOWN;
case NACT_EFFECT_SKIP_LINE_LR_RL: return EFFECT_SKIP_LINE_LR_RL;
case NACT_SP_EFFECT_RASTER_BLEND: return EFFECT_RASTER_BLEND;
default: return EFFECT_INVALID;
}
}
enum sdl_effect_type from_sact_effect(enum sact_effect effect) {
switch (effect) {
case SACT_EFFECT_CROSSFADE: return EFFECT_CROSSFADE;
@@ -111,7 +127,7 @@ enum sdl_effect_type from_sact_effect(enum sact_effect effect) {
}
struct sdl_effect {
void (*step)(struct sdl_effect *this, double progress);
void (*step)(struct sdl_effect *this, float progress);
void (*finish)(struct sdl_effect *this);
enum sdl_effect_type type;
SDL_Rect dst_rect;
@@ -175,7 +191,7 @@ static inline void move_rect(SDL_Rect *r, int off_x, int off_y) {
// EFFECT_CROSSFADE
static void crossfade_step(struct sdl_effect *eff, double progress);
static void crossfade_step(struct sdl_effect *eff, float progress);
static void crossfade_free(struct sdl_effect *eff);
static struct sdl_effect *crossfade_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new) {
@@ -188,7 +204,7 @@ static struct sdl_effect *crossfade_new(SDL_Rect *rect, SDL_Surface *old, SDL_Su
return eff;
}
static void crossfade_step(struct sdl_effect *eff, double progress) {
static void crossfade_step(struct sdl_effect *eff, float progress) {
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
SDL_SetTextureBlendMode(eff->tx_new, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(eff->tx_new, progress * 255);
@@ -209,7 +225,7 @@ static struct sdl_effect *fallback_effect_new(SDL_Rect *rect, SDL_Surface *old,
// EFFECT_CROSSFADE_{UP,DOWN,LR,RL}
static void crossfade_animation_step(struct sdl_effect *eff, double progress);
static void crossfade_animation_step(struct sdl_effect *eff, float progress);
static void crossfade_animation_free(struct sdl_effect *eff);
static struct sdl_effect *crossfade_animation_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
@@ -222,7 +238,7 @@ static struct sdl_effect *crossfade_animation_new(SDL_Rect *rect, SDL_Surface *o
return eff;
}
static void crossfade_animation_step_sub(SDL_Rect *rect, SDL_Texture *tx, int tx_x, int tx_y, double progress, int band_width, bool lr, bool flip) {
static void crossfade_animation_step_sub(SDL_Rect *rect, SDL_Texture *tx, int tx_x, int tx_y, float progress, int band_width, bool lr, bool flip) {
int maxstep = (lr ? rect->w : rect->h) + band_width;
int band_top = maxstep * progress - band_width;
if (band_top > 0) {
@@ -267,7 +283,7 @@ static void crossfade_animation_step_sub(SDL_Rect *rect, SDL_Texture *tx, int tx
SDL_SetTextureBlendMode(tx, SDL_BLENDMODE_NONE);
}
static void crossfade_animation_step(struct sdl_effect *eff, double progress) {
static void crossfade_animation_step(struct sdl_effect *eff, float progress) {
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
switch (eff->type) {
@@ -324,7 +340,7 @@ struct mosaic_effect {
SDL_Texture *tmp_old, *tmp_new, *tx_mosaic;
};
static void mosaic_step(struct sdl_effect *eff, double progress);
static void mosaic_step(struct sdl_effect *eff, float progress);
static void mosaic_free(struct sdl_effect *eff);
static struct sdl_effect *mosaic_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
@@ -343,7 +359,7 @@ static struct sdl_effect *mosaic_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surfa
return &eff->eff;
}
static void mosaic(SDL_Texture *src, SDL_Texture *tmp, SDL_Texture *dst, int w, int h, double scale) {
static void mosaic(SDL_Texture *src, SDL_Texture *tmp, SDL_Texture *dst, int w, int h, float scale) {
int cx = w / 2;
int cy = h / 2;
SDL_FRect fr = {
@@ -372,17 +388,17 @@ static void mosaic(SDL_Texture *src, SDL_Texture *tmp, SDL_Texture *dst, int w,
SDL_SetRenderTarget(sdl_renderer, NULL);
}
static void mosaic_step(struct sdl_effect *eff, double progress) {
static void mosaic_step(struct sdl_effect *eff, float progress) {
struct mosaic_effect *this = (struct mosaic_effect *)eff;
if (eff->type == EFFECT_MOSAIC) {
const int max_scale = 80;
int scale = (1.0 - progress) * (max_scale - 1) + 1;
int scale = (1.f - progress) * (max_scale - 1) + 1;
mosaic(eff->tx_new, this->tmp_new, this->tx_mosaic, eff->dst_rect.w, eff->dst_rect.h, scale);
SDL_RenderCopy(sdl_renderer, this->tx_mosaic, NULL, &eff->dst_rect);
} else if (eff->type == EFFECT_CROSSFADE_MOSAIC) {
const int max_scale = 96;
double scale = (progress < 0.5 ? progress : 1.0 - progress) * 2 * (max_scale - 1) + 1;
float scale = (progress < 0.5f ? progress : 1.f - progress) * 2 * (max_scale - 1) + 1;
mosaic(eff->tx_old, this->tmp_old, this->tx_mosaic, eff->dst_rect.w, eff->dst_rect.h, scale);
SDL_RenderCopy(sdl_renderer, this->tx_mosaic, NULL, &eff->dst_rect);
mosaic(eff->tx_new, this->tmp_new, this->tx_mosaic, eff->dst_rect.w, eff->dst_rect.h, scale);
@@ -408,7 +424,7 @@ static void mosaic_free(struct sdl_effect *eff) {
// EFFECT_{FADE,WHITE}{OUT,IN}
static void brightness_step(struct sdl_effect *eff, double progress);
static void brightness_step(struct sdl_effect *eff, float progress);
static void brightness_free(struct sdl_effect *eff);
static struct sdl_effect *brightness_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
@@ -421,7 +437,7 @@ static struct sdl_effect *brightness_new(SDL_Rect *rect, SDL_Surface *old, SDL_S
return eff;
}
static void brightness_step(struct sdl_effect *eff, double progress) {
static void brightness_step(struct sdl_effect *eff, float progress) {
SDL_Texture *texture;
int color;
int alpha;
@@ -439,7 +455,7 @@ static void brightness_step(struct sdl_effect *eff, double progress) {
case EFFECT_FADEIN:
texture = eff->tx_new;
color = 0;
alpha = (1.0 - progress) * 255;
alpha = (1.f - progress) * 255;
break;
case EFFECT_WHITEOUT:
texture = eff->tx_old;
@@ -454,7 +470,7 @@ static void brightness_step(struct sdl_effect *eff, double progress) {
case EFFECT_WHITEIN:
texture = eff->tx_new;
color = 255;
alpha = (1.0 - progress) * 255;
alpha = (1.f - progress) * 255;
break;
default:
assert(!"Cannot happen");
@@ -475,7 +491,7 @@ static void brightness_free(struct sdl_effect *eff) {
// EFFECT_DITHERING_{FADE,WHITE}{OUT,IN}
static void dithering_fade_step(struct sdl_effect *eff, double progress);
static void dithering_fade_step(struct sdl_effect *eff, float progress);
static void dithering_fade_free(struct sdl_effect *eff);
static SDL_Texture *create_dither_pattern_texture(int w, int h, int val) {
@@ -532,15 +548,15 @@ static struct sdl_effect *dithering_fade_new(SDL_Rect *rect, SDL_Surface *old, S
return eff;
}
static void dithering_fade_step(struct sdl_effect *eff, double progress) {
static void dithering_fade_step(struct sdl_effect *eff, float progress) {
static const int dither_x[16] = {0,2,2,0,1,3,3,1,1,3,3,1,0,2,2,0};
static const int dither_y[16] = {0,2,0,2,1,3,1,3,0,2,0,2,1,3,1,3};
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
if (eff->type == EFFECT_DITHERING_FADEIN || eff->type == EFFECT_DITHERING_WHITEIN)
progress = 1 - progress;
int level = round(progress * 16);
progress = 1.f - progress;
int level = roundf(progress * 16);
assert(eff->is_fullscreen);
SDL_Rect dr = eff->dst_rect;
@@ -562,9 +578,110 @@ static void dithering_fade_free(struct sdl_effect *eff) {
free(eff);
}
// EFFECT_PAN_IN_*
static void pan_in_step(struct sdl_effect *eff, float progress);
static void pan_in_free(struct sdl_effect *eff);
static struct sdl_effect *pan_in_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
effect_init(eff, rect, old, new, type);
eff->step = pan_in_step;
eff->finish = pan_in_free;
return eff;
}
static void pan_in_step(struct sdl_effect *eff, float progress) {
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
int h = eff->dst_rect.h * progress;
SDL_Rect sr = { 0, 0, eff->dst_rect.w, h };
SDL_Rect dr = eff->dst_rect;
dr.h = h;
if (eff->type == EFFECT_PAN_IN_DOWN) {
sr.y = eff->dst_rect.h - h;
} else {
dr.y += eff->dst_rect.h - h;
}
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
SDL_RenderPresent(sdl_renderer);
}
static void pan_in_free(struct sdl_effect *eff) {
effect_finish(eff, true);
free(eff);
}
// EFFECT_SKIP_LINE_*
static void skip_line_step(struct sdl_effect *eff, float progress);
static void skip_line_free(struct sdl_effect *eff);
static struct sdl_effect *skip_line_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
effect_init(eff, rect, old, new, type);
eff->step = skip_line_step;
eff->finish = skip_line_free;
return eff;
}
static void skip_line_step(struct sdl_effect *eff, float progress) {
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
if (eff->type == EFFECT_SKIP_LINE_UP_DOWN) {
int h = eff->dst_rect.h * progress;
SDL_Rect sr = { 0, 0, eff->dst_rect.w, 1 };
SDL_Rect dr = eff->dst_rect;
dr.h = 1;
int bottom = (eff->dst_rect.h - 1) | 1;
for (int y = 0; y < h; y += 2) {
sr.y = y;
dr.y = eff->dst_rect.y + y;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
if (y == 0 && eff->dst_rect.h & 1)
continue;
sr.y = bottom - y;
dr.y = eff->dst_rect.y + bottom - y;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
}
} else {
int w = eff->dst_rect.w * progress;
SDL_Rect sr = { 0, 0, 1, eff->dst_rect.h };
SDL_Rect dr = eff->dst_rect;
dr.w = 1;
int right = (eff->dst_rect.w - 1) | 1;
for (int x = 0; x < w; x += 2) {
sr.x = x;
dr.x = eff->dst_rect.x + x;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
if (x == 0 && eff->dst_rect.w & 1)
continue;
sr.x = right - x;
dr.x = eff->dst_rect.x + right - x;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
}
}
SDL_RenderPresent(sdl_renderer);
}
static void skip_line_free(struct sdl_effect *eff) {
effect_finish(eff, true);
free(eff);
}
// EFFECT_WIPE_*
static void wipe_step(struct sdl_effect *eff, double progress);
static void wipe_step(struct sdl_effect *eff, float progress);
static void wipe_free(struct sdl_effect *eff);
static struct sdl_effect *wipe_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
@@ -577,7 +694,7 @@ static struct sdl_effect *wipe_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface
return eff;
}
static void wipe_step(struct sdl_effect *eff, double progress) {
static void wipe_step(struct sdl_effect *eff, float progress) {
SDL_Texture *bg = eff->tx_old;
SDL_Texture *fg = eff->tx_new;
if (eff->type == EFFECT_WIPE_RL ||
@@ -587,7 +704,7 @@ static void wipe_step(struct sdl_effect *eff, double progress) {
eff->type == EFFECT_WIPE_IN_H) {
bg = eff->tx_new;
fg = eff->tx_old;
progress = 1 - progress;
progress = 1.f - progress;
}
SDL_RenderCopy(sdl_renderer, bg, NULL, &eff->dst_rect);
@@ -638,7 +755,7 @@ static void wipe_free(struct sdl_effect *eff) {
// EFFECT_CIRCLE_WIPE_*
static void circle_wipe_step(struct sdl_effect *eff, double progress);
static void circle_wipe_step(struct sdl_effect *eff, float progress);
static void circle_wipe_free(struct sdl_effect *eff);
static struct sdl_effect *circle_wipe_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
@@ -651,7 +768,7 @@ static struct sdl_effect *circle_wipe_new(SDL_Rect *rect, SDL_Surface *old, SDL_
return eff;
}
static void circle_wipe_step(struct sdl_effect *eff, double progress) {
static void circle_wipe_step(struct sdl_effect *eff, float progress) {
SDL_Texture *bg = eff->tx_old;
SDL_Texture *fg = eff->tx_new;
if (eff->type == EFFECT_CIRCLE_WIPE_IN) {
@@ -663,7 +780,7 @@ static void circle_wipe_step(struct sdl_effect *eff, double progress) {
int hw = eff->dst_rect.w / 2;
int hh = eff->dst_rect.h / 2;
int r = sqrt(hw*hw + hh*hh) * progress;
int r = sqrtf(hw*hw + hh*hh) * progress;
for (int y = -r; y < r; y++) {
if (y < -hh || y >= hh)
@@ -688,7 +805,7 @@ static void circle_wipe_free(struct sdl_effect *eff) {
// EFFECT_BLIND_*
static void blind_step(struct sdl_effect *eff, double progress);
static void blind_step(struct sdl_effect *eff, float progress);
static void blind_free(struct sdl_effect *eff);
static struct sdl_effect *blind_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
@@ -701,7 +818,7 @@ static struct sdl_effect *blind_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surfac
return eff;
}
static void blind_vstep(double progress, SDL_Rect *rect, SDL_Texture *tx_new, int offset_y, bool flip) {
static void blind_vstep(float progress, SDL_Rect *rect, SDL_Texture *tx_new, int offset_y, bool flip) {
const int N = 16;
int nr_bands = rect->h / N + N - 1;
@@ -733,7 +850,7 @@ static void blind_vstep(double progress, SDL_Rect *rect, SDL_Texture *tx_new, in
}
}
static void blind_step(struct sdl_effect *eff, double progress) {
static void blind_step(struct sdl_effect *eff, float progress) {
const int N = 16;
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
@@ -790,7 +907,7 @@ static void blind_free(struct sdl_effect *eff) {
// EFFECT_BLEND_*
static void blend_animation_step(struct sdl_effect *eff, double progress);
static void blend_animation_step(struct sdl_effect *eff, float progress);
static void blend_animation_free(struct sdl_effect *eff);
static struct sdl_effect *blend_animation_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
@@ -803,17 +920,17 @@ static struct sdl_effect *blend_animation_new(SDL_Rect *rect, SDL_Surface *old,
return eff;
}
static void blend_animation_step(struct sdl_effect *eff, double progress) {
static void blend_animation_step(struct sdl_effect *eff, float progress) {
const bool lr = eff->type == EFFECT_BLEND_LR_RL;
SDL_Texture *bg, *fg;
if (progress < 0.5) {
if (progress < 0.5f) {
bg = eff->tx_old;
fg = eff->tx_new;
} else {
bg = eff->tx_new;
fg = eff->tx_old;
progress = 1.0 - progress;
progress = 1.f - progress;
}
SDL_RenderCopy(sdl_renderer, bg, NULL, &eff->dst_rect);
@@ -857,7 +974,7 @@ struct zoom_blend_blur_effect {
int index;
};
static void zoom_blend_blur_step(struct sdl_effect *eff, double progress);
static void zoom_blend_blur_step(struct sdl_effect *eff, float progress);
static void zoom_blend_blur_free(struct sdl_effect *eff);
static struct sdl_effect *zoom_blend_blur_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new) {
@@ -873,14 +990,14 @@ static struct sdl_effect *zoom_blend_blur_new(SDL_Rect *rect, SDL_Surface *old,
return &eff->eff;
}
static void zoom_blend_blur_step(struct sdl_effect *eff, double progress) {
static void zoom_blend_blur_step(struct sdl_effect *eff, float progress) {
struct zoom_blend_blur_effect *this = (struct zoom_blend_blur_effect *)eff;
if (!this->tx[this->index]) {
this->tx[this->index] = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, eff->dst_rect.w, eff->dst_rect.h);
}
double scale = (progress < 0.5 ? 1 - progress * 2 : (progress - 0.5) * 2) * 0.9 + 0.1; // 0.1 - 1.0
float scale = (progress < 0.5f ? 1 - progress * 2 : (progress - 0.5f) * 2) * 0.9f + 0.1f; // 0.1 - 1.0
int w = eff->dst_rect.w * scale;
int h = eff->dst_rect.h * scale;
SDL_Rect r = {
@@ -927,7 +1044,7 @@ struct linear_blur_effect {
SDL_Texture *blurred_new[LINEAR_BLUR_STEPS];
};
static void linear_blur_step(struct sdl_effect *eff, double progress);
static void linear_blur_step(struct sdl_effect *eff, float progress);
static void linear_blur_free(struct sdl_effect *eff);
static struct sdl_effect *linear_blur_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
@@ -983,7 +1100,7 @@ static SDL_Texture *blur(struct linear_blur_effect *this, SDL_Texture *src, int
return dst;
}
static void linear_blur_step(struct sdl_effect *eff, double progress) {
static void linear_blur_step(struct sdl_effect *eff, float progress) {
struct linear_blur_effect *this = (struct linear_blur_effect *)eff;
int step = progress * LINEAR_BLUR_STEPS * 2;
@@ -1029,7 +1146,7 @@ struct polygon_mask_effect {
SDL_Texture *tx_tmp;
};
static void polygon_mask_step(struct sdl_effect *eff, double progress);
static void polygon_mask_step(struct sdl_effect *eff, float progress);
static void polygon_mask_free(struct sdl_effect *eff);
static struct sdl_effect *polygon_mask_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
@@ -1051,7 +1168,7 @@ static struct sdl_effect *polygon_mask_new(SDL_Rect *rect, SDL_Surface *old, SDL
#if HAS_SDL_RenderGeometry
static void draw_pentagram(int center_x, int center_y, double radius, double rotate) {
static void draw_pentagram(int center_x, int center_y, float radius, float rotate) {
const SDL_FPoint p[10] = {
{ 1.5, 0 },
{ 0.4635, 0.3368},
@@ -1065,8 +1182,8 @@ static void draw_pentagram(int center_x, int center_y, double radius, double rot
{ 0.4635, -0.3368},
};
SDL_Vertex v[10];
double sin_r = sin(rotate);
double cos_r = cos(rotate);
float sin_r = sinf(rotate);
float cos_r = cosf(rotate);
for (int i = 0; i < 10; i++) {
v[i].position.x = radius * (p[i].x * cos_r - p[i].y * sin_r) + center_x;
v[i].position.y = radius * (p[i].x * sin_r + p[i].y * cos_r) + center_y;
@@ -1082,7 +1199,7 @@ static void draw_pentagram(int center_x, int center_y, double radius, double rot
SDL_RenderGeometry(sdl_renderer, NULL, v, 10, indices, 15);
}
static void draw_hexagram(int center_x, int center_y, double radius, double rotate) {
static void draw_hexagram(int center_x, int center_y, float radius, float rotate) {
const SDL_FPoint p[6] = {
{ 0, -1.0},
{-0.866, 0.5},
@@ -1093,8 +1210,8 @@ static void draw_hexagram(int center_x, int center_y, double radius, double rota
{ 0.866, -0.5}
};
SDL_Vertex v[6];
double sin_r = sin(rotate);
double cos_r = cos(rotate);
float sin_r = sinf(rotate);
float cos_r = cosf(rotate);
for (int i = 0; i < 6; i++) {
v[i].position.x = radius * (p[i].x * cos_r - p[i].y * sin_r) + center_x;
v[i].position.y = radius * (p[i].x * sin_r + p[i].y * cos_r) + center_y;
@@ -1103,12 +1220,12 @@ static void draw_hexagram(int center_x, int center_y, double radius, double rota
SDL_RenderGeometry(sdl_renderer, NULL, v, 6, NULL, 0);
}
static void draw_windmill_90(int w, int h, double theta) {
double cx = w / 2.0;
double cy = h / 2.0;
double r = max(cx, cy) * sqrt(2);
double r_sin = r * sin(theta);
double r_cos = r * cos(theta);
static void draw_windmill_90(int w, int h, float theta) {
float cx = w / 2.f;
float cy = h / 2.f;
float r = max(cx, cy) * sqrtf(2);
float r_sin = r * sinf(theta);
float r_cos = r * cosf(theta);
SDL_Vertex v[13] = {
// center
@@ -1131,7 +1248,7 @@ static void draw_windmill_90(int w, int h, double theta) {
{.position = {cx - r_cos, cy - r_sin}},
};
if (theta <= M_PI / 4) {
if (theta <= M_PIf / 4) {
const int indices[12] = {
0, 1, 3,
0, 4, 6,
@@ -1154,12 +1271,12 @@ static void draw_windmill_90(int w, int h, double theta) {
}
}
static void draw_windmill_180(int w, int h, double theta) {
double cx = w / 2.0;
double cy = h / 2.0;
double r = max(cx, cy) * sqrt(2);
double r_sin = r * sin(theta);
double r_cos = r * cos(theta);
static void draw_windmill_180(int w, int h, float theta) {
float cx = w / 2.f;
float cy = h / 2.f;
float r = max(cx, cy) * sqrtf(2);
float r_sin = r * sinf(theta);
float r_cos = r * cosf(theta);
SDL_Vertex v[11] = {
{.position = {cx, cy }}, // center
@@ -1174,7 +1291,7 @@ static void draw_windmill_180(int w, int h, double theta) {
{.position = {cx, cy + r }}, // bottom
{.position = {cx - r, cy + r }}, // left-bottom
{.position = {cx - r, cy }}, // left
{.position = {cx + r_cos, cy + r_sin}}, // theta+M_PI
{.position = {cx + r_cos, cy + r_sin}}, // theta+M_PIf
};
int indices[24];
@@ -1182,7 +1299,7 @@ static void draw_windmill_180(int w, int h, double theta) {
indices[i++] = 0; // center
indices[i++] = 9; // left
for (int j = 1; theta > M_PI / 4 * j; j++) {
for (int j = 1; theta > M_PIf / 4 * j; j++) {
indices[i++] = j;
indices[i++] = 0; // center
indices[i++] = j;
@@ -1191,22 +1308,22 @@ static void draw_windmill_180(int w, int h, double theta) {
indices[i++] = 0; // center
indices[i++] = 4; // right
for (int j = 1; theta > M_PI / 4 * j; j++) {
for (int j = 1; theta > M_PIf / 4 * j; j++) {
indices[i++] = j + 5;
indices[i++] = 0; // center
indices[i++] = j + 5;
}
indices[i++] = 10; // theta+M_PI
indices[i++] = 10; // theta+M_PIf
SDL_RenderGeometry(sdl_renderer, NULL, v, 11, indices, i);
}
static void draw_windmill_360(int w, int h, double theta) {
double cx = w / 2.0;
double cy = h / 2.0;
double r = max(cx, cy) * sqrt(2);
double r_sin = r * sin(theta);
double r_cos = r * cos(theta);
static void draw_windmill_360(int w, int h, float theta) {
float cx = w / 2.f;
float cy = h / 2.f;
float r = max(cx, cy) * sqrtf(2);
float r_sin = r * sinf(theta);
float r_cos = r * cosf(theta);
SDL_Vertex v[10] = {
{.position = {cx, cy }}, // center
@@ -1226,7 +1343,7 @@ static void draw_windmill_360(int w, int h, double theta) {
indices[i++] = 0; // center
indices[i++] = 8; // left
for (int j = 1; theta > M_PI / 4 * j; j++) {
for (int j = 1; theta > M_PIf / 4 * j; j++) {
indices[i++] = j;
indices[i++] = 0; // center
indices[i++] = j;
@@ -1235,7 +1352,7 @@ static void draw_windmill_360(int w, int h, double theta) {
SDL_RenderGeometry(sdl_renderer, NULL, v, 10, indices, i);
}
static void polygon_mask_step(struct sdl_effect *eff, double progress) {
static void polygon_mask_step(struct sdl_effect *eff, float progress) {
struct polygon_mask_effect *this = (struct polygon_mask_effect *)eff;
int w = eff->dst_rect.w;
int h = eff->dst_rect.h;
@@ -1243,25 +1360,25 @@ static void polygon_mask_step(struct sdl_effect *eff, double progress) {
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, NULL);
switch (eff->type) {
case EFFECT_PENTAGRAM_IN_OUT:
draw_pentagram(w / 2, h / 2, max(w, h) * progress, M_PI * progress);
draw_pentagram(w / 2, h / 2, max(w, h) * progress, M_PIf * progress);
break;
case EFFECT_PENTAGRAM_OUT_IN:
draw_pentagram(w / 2, h / 2, max(w, h) * (1 - progress), M_PI * progress);
draw_pentagram(w / 2, h / 2, max(w, h) * (1 - progress), M_PIf * progress);
break;
case EFFECT_HEXAGRAM_IN_OUT:
draw_hexagram(w / 2, h / 2, max(w, h) * progress, M_PI * progress);
draw_hexagram(w / 2, h / 2, max(w, h) * progress, M_PIf * progress);
break;
case EFFECT_HEXAGRAM_OUT_IN:
draw_hexagram(w / 2, h / 2, max(w, h) * (1 - progress), M_PI * progress);
draw_hexagram(w / 2, h / 2, max(w, h) * (1 - progress), M_PIf * progress);
break;
case EFFECT_WINDMILL:
draw_windmill_90(w, h, M_PI / 2 * progress);
draw_windmill_90(w, h, M_PIf / 2 * progress);
break;
case EFFECT_WINDMILL_180:
draw_windmill_180(w, h, M_PI * progress);
draw_windmill_180(w, h, M_PIf * progress);
break;
case EFFECT_WINDMILL_360:
draw_windmill_360(w, h, M_PI * 2 * progress);
draw_windmill_360(w, h, M_PIf * 2 * progress);
break;
default:
assert(!"Cannot happen");
@@ -1284,7 +1401,7 @@ static void polygon_mask_free(struct sdl_effect *eff) {
// EFFECT_ROTATE_*
static void rotate_step(struct sdl_effect *eff, double progress);
static void rotate_step(struct sdl_effect *eff, float progress);
static void rotate_free(struct sdl_effect *eff);
static struct sdl_effect *rotate_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
@@ -1297,24 +1414,24 @@ static struct sdl_effect *rotate_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surfa
return eff;
}
static void rotate_step(struct sdl_effect *eff, double progress) {
static void rotate_step(struct sdl_effect *eff, float progress) {
SDL_Texture *bg_texture, *fg_texture;
double angle = progress * 360;
double scale = progress;
float angle = progress * 360;
float scale = progress;
switch (eff->type) {
case EFFECT_ROTATE_OUT:
scale = 1.0 - scale;
scale = 1.f - scale;
bg_texture = eff->tx_new;
fg_texture = eff->tx_old;
angle *= -1.0;
angle *= -1.f;
break;
case EFFECT_ROTATE_IN:
bg_texture = eff->tx_old;
fg_texture = eff->tx_new;
angle *= -1.0;
angle *= -1.f;
break;
case EFFECT_ROTATE_OUT_CW:
scale = 1.0 - scale;
scale = 1.f - scale;
bg_texture = eff->tx_new;
fg_texture = eff->tx_old;
break;
@@ -1331,8 +1448,8 @@ static void rotate_step(struct sdl_effect *eff, double progress) {
assert(!"Cannot happen");
}
SDL_Rect r = eff->dst_rect;
r.x += (1.0 - scale) * r.w / 2;
r.y += (1.0 - scale) * r.h / 2;
r.x += (1.f - scale) * r.w / 2;
r.y += (1.f - scale) * r.h / 2;
r.w *= scale;
r.h *= scale;
SDL_RenderCopy(sdl_renderer, bg_texture, NULL, &eff->dst_rect);
@@ -1347,7 +1464,7 @@ static void rotate_free(struct sdl_effect *eff) {
// EFFECT_POLYGON_ROTATE_*
static void polygon_rotate_step(struct sdl_effect *eff, double progress);
static void polygon_rotate_step(struct sdl_effect *eff, float progress);
static void polygon_rotate_free(struct sdl_effect *eff);
static struct sdl_effect *polygon_rotate_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
@@ -1360,35 +1477,35 @@ static struct sdl_effect *polygon_rotate_new(SDL_Rect *rect, SDL_Surface *old, S
return eff;
}
static void polygon_rotate_step(struct sdl_effect *eff, double progress) {
static void polygon_rotate_step(struct sdl_effect *eff, float progress) {
bool vertical = eff->type == EFFECT_POLYGON_ROTATE_Y || eff->type == EFFECT_POLYGON_ROTATE_Y_CW;
SDL_Texture *texture = progress < 0.5 ? eff->tx_old : eff->tx_new;
double angle = progress < 0.5 ? progress * M_PI : (progress - 1.0) * M_PI;
SDL_Texture *texture = progress < 0.5f ? eff->tx_old : eff->tx_new;
float angle = progress < 0.5f ? progress * M_PIf : (progress - 1.f) * M_PIf;
if (eff->type == EFFECT_POLYGON_ROTATE_Y_CW || eff->type == EFFECT_POLYGON_ROTATE_X_CW)
angle *= -1;
const double distance = 2.0;
double cos_a = cos(angle);
double sin_a = sin(angle);
double lz = -0.5 * sin_a + distance;
double rz = 0.5 * sin_a + distance;
double lx = -0.5 * cos_a / lz;
double rx = 0.5 * cos_a / rz;
const float distance = 2.f;
float cos_a = cosf(angle);
float sin_a = sinf(angle);
float lz = -0.5f * sin_a + distance;
float rz = 0.5f * sin_a + distance;
float lx = -0.5f * cos_a / lz;
float rx = 0.5f * cos_a / rz;
int w = vertical ? eff->dst_rect.w : eff->dst_rect.h;
int h = vertical ? eff->dst_rect.h : eff->dst_rect.w;
double dlx = w * (lx * distance + 0.5);
double drx = w * (rx * distance + 0.5);
float dlx = w * (lx * distance + 0.5f);
float drx = w * (rx * distance + 0.5f);
// Perspective-correct interpolation.
for (int x = dlx; x <= drx; x++) {
if (x < 0 || x >= w)
continue;
double t = (x - dlx) / (drx - dlx);
double recip_z = (1 - t) * (1 / lz) + t * (1 / rz);
double tx = t * (w / rz) / recip_z;
float t = (x - dlx) / (drx - dlx);
float recip_z = (1 - t) * (1 / lz) + t * (1 / rz);
float tx = t * (w / rz) / recip_z;
SDL_Rect sr = {tx, 0, 1, h};
double dh = h * recip_z * distance;
float dh = h * recip_z * distance;
SDL_Rect dr = {x, (h - dh) / 2, 1, dh};
if (!vertical) {
transpose_rect(&sr);
@@ -1412,7 +1529,7 @@ struct zigzag_crossfade_effect {
SDL_Texture *tmp1, *tmp2;
};
static void zigzag_crossfade_step(struct sdl_effect *eff, double progress);
static void zigzag_crossfade_step(struct sdl_effect *eff, float progress);
static void zigzag_crossfade_free(struct sdl_effect *eff);
static struct sdl_effect *zigzag_crossfade_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new) {
@@ -1430,38 +1547,38 @@ static struct sdl_effect *zigzag_crossfade_new(SDL_Rect *rect, SDL_Surface *old,
return &eff->eff;
}
static void wave_warp_h(SDL_Texture *src, SDL_Texture *dst, int w, int h, double amplitude, double length, double phase) {
static void wave_warp_h(SDL_Texture *src, SDL_Texture *dst, int w, int h, float amplitude, float length, float phase) {
SDL_SetRenderTarget(sdl_renderer, dst);
SDL_RenderClear(sdl_renderer);
SDL_Rect sr = {0, 0, w, 1};
SDL_Rect dr = {0, 0, w, 1};
for (int y = 0; y < h; y++) {
sr.y = dr.y = y;
dr.x = sin(phase + y * (2 * M_PI / 360 * length)) * amplitude;
dr.x = sinf(phase + y * (2 * M_PIf / 360 * length)) * amplitude;
SDL_RenderCopy(sdl_renderer, src, &sr, &dr);
}
SDL_SetRenderTarget(sdl_renderer, NULL);
}
static void wave_warp_v(SDL_Texture *src, SDL_Texture *dst, int w, int h, double amplitude, double length, double phase) {
static void wave_warp_v(SDL_Texture *src, SDL_Texture *dst, int w, int h, float amplitude, float length, float phase) {
SDL_SetRenderTarget(sdl_renderer, dst);
SDL_RenderClear(sdl_renderer);
SDL_Rect sr = {0, 0, 1, h};
SDL_Rect dr = {0, 0, 1, h};
for (int x = 0; x < w; x++) {
sr.x = dr.x = x;
dr.y = sin(phase + x * (2 * M_PI / 360 * length)) * amplitude;
dr.y = sinf(phase + x * (2 * M_PIf / 360 * length)) * amplitude;
SDL_RenderCopy(sdl_renderer, src, &sr, &dr);
}
SDL_SetRenderTarget(sdl_renderer, NULL);
}
static void zigzag_crossfade_step(struct sdl_effect *eff, double progress) {
static void zigzag_crossfade_step(struct sdl_effect *eff, float progress) {
struct zigzag_crossfade_effect *this = (struct zigzag_crossfade_effect *)eff;
double amp = (progress < 0.5 ? progress : 1.0 - progress) * 80;
double len = (progress < 0.5 ? progress : 1.0 - progress) * 20;
double phase = progress * 10;
float amp = (progress < 0.5f ? progress : 1.f - progress) * 80;
float len = (progress < 0.5f ? progress : 1.f - progress) * 20;
float phase = progress * 10;
wave_warp_h(eff->tx_old, this->tmp1, eff->dst_rect.w, eff->dst_rect.h, amp, len, phase);
wave_warp_v(this->tmp1, this->tmp2, eff->dst_rect.w, eff->dst_rect.h, amp, len, phase);
@@ -1492,7 +1609,7 @@ struct magnify_effect {
SDL_Rect new_rect;
};
static void magnify_step(struct sdl_effect *eff, double progress);
static void magnify_step(struct sdl_effect *eff, float progress);
static void magnify_free(struct sdl_effect *eff);
static struct sdl_effect *magnify_new(SDL_Surface *sf, SDL_Rect *old_rect, SDL_Rect *new_rect) {
@@ -1506,7 +1623,7 @@ static struct sdl_effect *magnify_new(SDL_Surface *sf, SDL_Rect *old_rect, SDL_R
return &eff->eff;
}
static void magnify_step(struct sdl_effect *eff, double progress) {
static void magnify_step(struct sdl_effect *eff, float progress) {
struct magnify_effect *this = (struct magnify_effect *)eff;
SDL_Rect *or = &eff->dst_rect;
SDL_Rect *nr = &this->new_rect;
@@ -1525,6 +1642,41 @@ static void magnify_free(struct sdl_effect *eff) {
free(eff);
}
// EFFECT_RASTER_BLEND
static void raster_blend_step(struct sdl_effect *eff, float progress);
static void raster_blend_free(struct sdl_effect *eff);
static struct sdl_effect *raster_blend_new(SDL_Rect *rect, int sx, int sy) {
SDL_Surface *sprite = sdl_dib_to_surface_with_alpha(sx, sy, rect->w, rect->h);
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
effect_init(eff, rect, NULL, sprite, EFFECT_RASTER_BLEND);
eff->step = raster_blend_step;
eff->finish = raster_blend_free;
return eff;
}
static void raster_blend_step(struct sdl_effect *eff, float progress) {
SDL_Rect s_rect = { 0, 0, eff->dst_rect.w, 1 };
SDL_Rect d_rect = eff->dst_rect;
d_rect.h = 1;
for (int y = 0; y < eff->dst_rect.h; y++) {
float t = 1.f - 4.f * progress + 3.f * y / eff->dst_rect.h;
d_rect.x = eff->dst_rect.x + (t < 0 ? 0 : sinf(2 * M_PIf * t) * 50);
SDL_RenderCopy(sdl_renderer, eff->tx_new, &s_rect, &d_rect);
s_rect.y++;
d_rect.y++;
}
SDL_RenderPresent(sdl_renderer);
}
static void raster_blend_free(struct sdl_effect *eff) {
effect_finish(eff, false);
free(eff);
}
// -----------------
static SDL_Surface *create_surface(agsurface_t *as, int x, int y, int w, int h) {
@@ -1571,6 +1723,12 @@ struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int
case EFFECT_DITHERING_WHITEOUT:
case EFFECT_DITHERING_WHITEIN:
return dithering_fade_new(rect, sf_old, sf_new, type);
case EFFECT_PAN_IN_DOWN:
case EFFECT_PAN_IN_UP:
return pan_in_new(rect, sf_old, sf_new, type);
case EFFECT_SKIP_LINE_UP_DOWN:
case EFFECT_SKIP_LINE_LR_RL:
return skip_line_new(rect, sf_old, sf_new, type);
case EFFECT_WIPE_IN:
case EFFECT_WIPE_OUT:
case EFFECT_WIPE_LR:
@@ -1627,12 +1785,31 @@ struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int
}
}
struct sdl_effect *sdl_sprite_effect_init(SDL_Rect *rect, int dx, int dy, int sx, int sy, int col, enum sdl_effect_type type) {
SDL_Surface *sf_old = create_surface(sdl_dibinfo, dx, dy, rect->w, rect->h);
SDL_Surface *sprite = sdl_dib_to_surface_colorkey(sx, sy, rect->w, rect->h, col);
switch (type) {
case EFFECT_PAN_IN_DOWN:
case EFFECT_PAN_IN_UP:
return pan_in_new(rect, sf_old, sprite, type);
case EFFECT_SKIP_LINE_UP_DOWN:
case EFFECT_SKIP_LINE_LR_RL:
return skip_line_new(rect, sf_old, sprite, type);
case EFFECT_RASTER_BLEND:
return raster_blend_new(rect, sx, sy);
default:
SYSERROR("Unknown sprite effect %d", type);
return NULL;
}
}
struct sdl_effect *sdl_effect_magnify_init(agsurface_t *surface, SDL_Rect *view_rect, SDL_Rect *target_rect) {
SDL_Surface *sf = create_surface(surface, view_rect->x, view_rect->y, view_rect->w, view_rect->h);
return magnify_new(sf, view_rect, target_rect);
}
void sdl_effect_step(struct sdl_effect *eff, double progress) {
void sdl_effect_step(struct sdl_effect *eff, float progress) {
SDL_RenderClear(sdl_renderer);
if (!eff->is_fullscreen)
SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
+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();
}
}
+12 -18
View File
@@ -204,19 +204,18 @@ void sdl_drawImage24_fromData(cgdata *cg, int x, int y, int brightness) {
SDL_FreeSurface(s);
}
void sdl_copyAreaSP16_shadow(int sx, int sy, int w, int h, int dx, int dy, int lv) {
SDL_Surface *sdl_dib_to_surface_with_alpha(int x, int y, int w, int h) {
SDL_Surface *s = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_ARGB8888);
SDL_Rect r_src = {sx, sy, w, h};
SDL_Rect r_tmp = { 0, 0, w, h};
SDL_BlitSurface(sdl_dib, &r_src, s, &r_tmp);
SDL_Rect r_src = {x, y, w, h};
SDL_BlitSurface(sdl_dib, &r_src, s, NULL);
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
uint8_t *p_ds = s->pixels + 3;
#else
uint8_t *p_ds = s->pixels;
#endif
uint8_t *adata = GETOFFSET_ALPHA(sdl_dibinfo, sx, sy);
uint8_t *adata = GETOFFSET_ALPHA(sdl_dibinfo, x, y);
for (int y = 0; y < h; y++) {
uint8_t *p_src = adata;
uint8_t *p_dst = p_ds;
@@ -227,11 +226,16 @@ void sdl_copyAreaSP16_shadow(int sx, int sy, int w, int h, int dx, int dy, int l
adata += sdl_dibinfo->width;
p_ds += s->pitch;
}
return s;
}
void sdl_copyAreaSP16_shadow(int sx, int sy, int w, int h, int dx, int dy, int lv) {
SDL_Surface *s = sdl_dib_to_surface_with_alpha(sx, sy, w, h);
if (lv < 255)
SDL_SetSurfaceAlphaMod(s, lv);
SDL_Rect r_dst = {dx, dy, w, h};
SDL_BlitSurface(s, &r_tmp, sdl_dib, &r_dst);
SDL_BlitSurface(s, NULL, sdl_dib, &r_dst);
SDL_FreeSurface(s);
}
@@ -241,6 +245,7 @@ void sdl_copyAreaSP16_alphaBlend(int sx, int sy, int w, int h, int dx, int dy, i
SDL_SetSurfaceBlendMode(sdl_dib, SDL_BLENDMODE_BLEND);
SDL_SetSurfaceAlphaMod(sdl_dib, lv);
SDL_BlitSurface(sdl_dib, &r_src, sdl_dib, &r_dst);
SDL_SetSurfaceAlphaMod(sdl_dib, 255);
SDL_SetSurfaceBlendMode(sdl_dib, SDL_BLENDMODE_NONE);
}
@@ -251,6 +256,7 @@ void sdl_copyAreaSP16_alphaLevel(int sx, int sy, int w, int h, int dx, int dy, i
SDL_SetSurfaceAlphaMod(sdl_dib, lv);
SDL_FillRect(sdl_dib, &r_dst, 0);
SDL_BlitSurface(sdl_dib, &r_src, sdl_dib, &r_dst);
SDL_SetSurfaceAlphaMod(sdl_dib, 255);
SDL_SetSurfaceBlendMode(sdl_dib, SDL_BLENDMODE_NONE);
}
@@ -330,18 +336,6 @@ void sdl_putRegion(void *psrc, int x, int y) {
SDL_BlitSurface(src, &r_src, sdl_dib, &r_dst);
}
/*
* dib
*/
void sdl_CopyRegion(void *psrc, int sx, int sy, int w,int h, int dx, int dy) {
SDL_Surface *src = (SDL_Surface *)psrc;
SDL_Rect r_src = {sx, sy, w, h};
SDL_Rect r_dst = {dx, dy, w, h};
SDL_BlitSurface(src, &r_src, sdl_dib, &r_dst);
}
/*
* dib dstを描画後
*/
+2
View File
@@ -56,6 +56,8 @@ void sdl_event_init(void);
void sdl_cursor_init(void);
int sdl_nearest_color(int r, int g, int b);
boolean sdl_joy_open(int index);
SDL_Surface *sdl_dib_to_surface_with_alpha(int x, int y, int w, int h);
SDL_Surface *sdl_dib_to_surface_colorkey(int x, int y, int w, int h, int col);
extern struct sdl_private_data *sdl_videodev;
-7
View File
@@ -98,17 +98,10 @@ void sdl_Remove(void) {
if (sdl_videodev == NULL) return;
if (sdl_display) {
NOTICE("Now SDL shutdown ... ");
SDL_FreeSurface(sdl_dib);
SDL_DestroyRenderer(sdl_renderer);
SDL_JoystickClose(js);
SDL_Quit();
NOTICE("Done!");
}
}
+7 -2
View File
@@ -460,7 +460,12 @@ void sel_select() {
while (!nact->is_quit) {
key = sys_keywait(25, KEYWAIT_CANCELABLE);
if (!key && prevkey == SYS35KEY_SPC) break;
// Right-click exits the menu without waiting for button up.
if (key == SYS35KEY_SPC) {
curElement = -1;
break;
}
if (!key && prevkey == SYS35KEY_RET && curElement != -1) break;
prevkey = key;
@@ -534,7 +539,7 @@ void sel_select() {
msg_nextPage(TRUE);
}
if (prevkey == SYS35KEY_RET) {
if (curElement != -1) {
sl_jmpNear(elmv[curElement]);
if (cb_select_page != 0) {
sl_callFar2(cb_select_page -1, cb_select_address);
+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);
+14 -16
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,6 +113,7 @@ 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(" -playlist file : load CD playlist from 'file'");
@@ -121,12 +123,6 @@ static void sys35_usage(boolean verbose) {
#ifdef ENABLE_MIDI_SDLMIXER
puts(" -Me : SDL_mixer midi player");
#endif
#ifdef ENABLE_MIDI_RAWMIDI
puts(" -Mr : Raw Midi device");
#endif
#ifdef ENABLE_MIDI_SEQMIDI
puts(" -Ms? : Sequenceer device (?:devicenumber)");
#endif
#ifdef ENABLE_MIDI_PORTMIDI
puts(" -Mp? : ALSA (via PortMidi) (?:devicenumber)");
#endif
@@ -258,6 +254,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");
@@ -279,10 +282,6 @@ static void sys35_ParseOption(int *argc, char **argv) {
if (argv[i + 1] != NULL) {
muscd_set_playlist(argv[i + 1]);
}
} else if (0 == strcmp(argv[i], "-devmidi")) {
if (argv[i + 1] != NULL) {
midi_set_devicename(argv[i + 1]);
}
} else if (0 == strncmp(argv[i], "-M", 2)) {
int subdev = 0;
if (argv[i][3] != '\0') {
@@ -333,6 +332,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) {
@@ -387,11 +390,6 @@ static void check_profile() {
if (param) {
sdl_setJoyDeviceIndex(atoi(param));
}
/* Raw MIDI device name の設定 */
param = get_profile("midi_device");
if (param) {
midi_set_devicename(param);
}
/* MIDI output device の設定 */
param = get_profile("midi_output_device");
if (param) {
@@ -484,7 +482,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);
+5 -7
View File
@@ -49,11 +49,6 @@
#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.
@@ -62,8 +57,6 @@
# 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
@@ -80,6 +73,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
-133
View File
@@ -1,133 +0,0 @@
%define ver 1.7.3
%define rel 1
Summary: system35 scenario decoder on X
Name: xsystem35
Version: %{ver}pre5
Release: %{rel}
License: GPL
Group: Amusements/Games
Source: http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/down/xsystem35-1.7.3pre5.tar.gz
# Source: http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/down/test/xsystem35-%{ver}-pre5.tar.gz
Requires: gtk+ >= 1.0.0
BuildPreReq: gtk+-devel
URL: http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/index.html
BuildRoot: %{_tmppath}/%{name}-%{version}-root
%description
system35 scenario decoder on X
Xsystem35 enables Alice Soft's games on X.
%description -l ja
アリスソフトのゲームをX上で実行するためのプログラムです。
最初に実行する前に ドキュメントディレクトリの xsys35rc.sample
をホームディレクトリに.xsys35rcとしてコピーしてお使い下さい。
%changelog
%prep
%setup -q
# %setup -q -n %{name}-%{ver}-pre5
#%patch -p1
rm -rf %{buildroot}
%build
./configure --prefix=/usr --enable-audio=oss,alsa,esd --enable-cdrom=linux,mp3 --enable-midi=extp,raw,seq --disable-debug --enable-qmidi
make
%install
%makeinstall
%clean
rm -rf %{buildroot}
%pre
%post
%preun
%postun
%files
%defattr(-, root, root)
%doc ABOUT-NLS COPYING INSTALL doc/* src/xsys35rc.sample
%doc contrib
%doc patch
%{_libdir}/xsystem35/*
%{_bindir}/xsystem35
%{_datadir}/locale/*/LC_MESSAGES/xsystem35*
%changelog
* Sun Dec 21 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
[xsystem35-1.7.2]
- version 1.7.2
* Sun Aug 31 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
[xsystem35-1.7.1]
- version 1.7.1
* Thu May 01 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
[xsystem35-1.7.0]
- version 1.7.0 preX
* Sat Feb 01 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
[xsystem35-1.6.0]
- version 1.6.0
* Sun Jan 05 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
[xsystem35-1.6.0]
- 1.6.0 preX
* Tue May 14 2002 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
[xsystem35-1.5.x]
- revised for xsystem35-1.5.x
* Sun May 1 2001 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
[xsystem35-1.4.0]
- update to xsystem35-1.4.0
* Sun Apr 1 2001 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
[xsystem35-1.3.4]
- update to xsystem35-1.3.4
* Sun Nov 26 2000 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
[xsystem35-1.3.3]
- import spec file from JRPM to tar ball. (Grate thanks to Toshiya Takagi)
* Sun Dec 4 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
[xsystem35-1.2.4-1]
- Updated to xsystem35-1.2.4
* Sun Sep 5 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
[xsystem35-1.2.3-2]
- Use TiMidity and mp3 instead of CD-DA
* Thu Aug 26 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
[xsystem35-1.2.3-1]
- Updated to xsystem35-1.2.3
* Sat Jul 24 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
[xsystem35-1.2.2-1]
- Updated to xsystem35-1.2.2
* Thu Jun 10 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
[xsystem35-1.2.1-1]
- Updated to xsystem35-1.2.1
* Mon May 24 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
[xsystem35-1.2.0-1]
- Updated to xsystem35-1.2.0
* Thu May 13 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
- Changed /usr/local/lib/xsystem35 to /usr/X11R6/lib/xsystem35
* Mon May 3 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
- First release against glibc

Some files were not shown because too many files have changed in this diff Show More