mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-09-22 22:48:08 +03:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b30fd71e4b | ||
|
|
99ad91306b | ||
|
|
ed96f26cea | ||
|
|
e6f71190ed | ||
|
|
8219feee6d | ||
|
|
bc8a85e046 | ||
|
|
67f62f02e6 | ||
|
|
471c65973b | ||
|
|
5ff7149dc1 | ||
|
|
80988e52cf | ||
|
|
ade76adda6 | ||
|
|
53d0e8ffef | ||
|
|
b2e14bd19a | ||
|
|
9c73a34c35 | ||
|
|
36e1dc152b | ||
|
|
f786db5a50 | ||
|
|
c515b21afb | ||
|
|
d3db3fa83e | ||
|
|
86068b0ab9 | ||
|
|
de4f3ebb0d | ||
|
|
187a3ced35 | ||
|
|
b7703b6270 | ||
|
|
b7d0efbe55 | ||
|
|
02fe55eb93 | ||
|
|
058789b435 | ||
|
|
c5dcb20ac3 | ||
|
|
cb08f7ca76 | ||
|
|
7a7d94e60f | ||
|
|
b7681982a6 | ||
|
|
fefaf6c343 | ||
|
|
42e994dfba | ||
|
|
a6aa50b5cf | ||
|
|
c4e8205d6c | ||
|
|
dd09f54329 | ||
|
|
435ceb31d3 | ||
|
|
e40de66821 | ||
|
|
73c79b7a2e | ||
|
|
a825ee80b3 | ||
|
|
eeeab6e054 | ||
|
|
875b233f32 | ||
|
|
bcaed3a687 | ||
|
|
894e8e26a6 | ||
|
|
7206b0a4f7 | ||
|
|
343f3bb7c5 | ||
|
|
d3650ce293 | ||
|
|
386cfeb60c | ||
|
|
9cd66c83ef | ||
|
|
065e16a082 | ||
|
|
3699aa5c2d | ||
|
|
20914970c9 | ||
|
|
3f2f555aa6 | ||
|
|
095da0bb86 | ||
|
|
7b8acd6e05 | ||
|
|
1b13e331e4 |
@@ -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:
|
||||
|
||||
@@ -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: |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
# Changelog
|
||||
|
||||
## 2.13.0 - 2024-12-07
|
||||
- Windows: `Option` -> `Auto Copy Text to Clipboard` menu command has been added.
|
||||
When enabled, in-game text will be copied to the clipboard automatically. This
|
||||
can be used with text hooker tools that support clipboard monitoring.
|
||||
|
||||
## 2.12.1 - 2024-12-02
|
||||
- Windows: Fixed missing DLL error (#60)
|
||||
|
||||
## 2.12.0 - 2024-11-26
|
||||
- Implemented playback of the opening movie for 妻みぐい2.
|
||||
|
||||
## 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.
|
||||
+48
-22
@@ -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.13.0")
|
||||
|
||||
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)
|
||||
@@ -41,6 +70,8 @@ if (EMSCRIPTEN)
|
||||
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)
|
||||
@@ -110,9 +143,18 @@ else() # non-emscripten, non-android
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_library(PORTMIDI portmidi)
|
||||
if (PORTMIDI)
|
||||
set(HAVE_PORTMIDI 1)
|
||||
if (WIN32)
|
||||
optional_pkg_check_modules(PORTMIDI IMPORTED_TARGET portmidi)
|
||||
if (PORTMIDI_FOUND)
|
||||
set(HAVE_PORTMIDI 1)
|
||||
add_static_library(portmidi_static PORTMIDI)
|
||||
set(PORTMIDI portmidi_static)
|
||||
endif()
|
||||
else ()
|
||||
find_library(PORTMIDI portmidi)
|
||||
if (PORTMIDI)
|
||||
set(HAVE_PORTMIDI 1)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -157,25 +199,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 +229,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()
|
||||
|
||||
@@ -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 ../../
|
||||
|
||||
@@ -16,8 +16,8 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 34
|
||||
versionCode 20
|
||||
versionName "2.11.2" + gitRevision()
|
||||
versionCode 28
|
||||
versionName "2.13.0" + gitRevision()
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DANDROID_APP_PLATFORM=android-19", "-DANDROID_STL=c++_static"
|
||||
|
||||
@@ -7,8 +7,8 @@ set(PROJECT_ROOT_DIR ../../..)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
SDL
|
||||
URL https://github.com/libsdl-org/SDL/releases/download/release-2.30.2/SDL2-2.30.2.tar.gz
|
||||
URL_HASH SHA1=37a0557fc39460dc2a4fbbf162d95f115d2c9be2
|
||||
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
|
||||
@@ -33,9 +33,7 @@ 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)
|
||||
|
||||
@@ -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"
|
||||
>
|
||||
|
||||
|
||||
@@ -277,6 +277,7 @@ public class HIDDeviceManager {
|
||||
0x044f, // Thrustmaster
|
||||
0x045e, // Microsoft
|
||||
0x0738, // Mad Catz
|
||||
0x0b05, // ASUS
|
||||
0x0e6f, // PDP
|
||||
0x0f0d, // Hori
|
||||
0x10f5, // Turtle Beach
|
||||
@@ -590,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
|
||||
|
||||
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
private static final String TAG = "SDL";
|
||||
private static final int SDL_MAJOR_VERSION = 2;
|
||||
private static final int SDL_MINOR_VERSION = 30;
|
||||
private static final int SDL_MICRO_VERSION = 2;
|
||||
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);
|
||||
|
||||
@@ -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
@@ -1,20 +1,16 @@
|
||||
#cmakedefine PACKAGE "@PACKAGE@"
|
||||
#define VERSION "2.11.2"
|
||||
#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@
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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 と打って出てくる
|
||||
メッセージを添付していただけるととても助かります。
|
||||
@@ -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 くらいでしょうか。
|
||||
|
||||
@@ -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選択が正常に動かない。
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
= 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).
|
||||
|
||||
*-texthook* _mode_::
|
||||
Set the text hook mode. Possible values are: `none` (default), `print` (print
|
||||
text to console), `copy` (copy text to clipboard).
|
||||
|
||||
*-texthook_suppress* _list_::
|
||||
Suppress text hook on specified scenario pages. _list_ is a comma-separated
|
||||
list of page numbers. Used to suppress system messages, etc.
|
||||
|
||||
*-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
|
||||
@@ -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)*]
|
||||
@@ -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 |
|
||||
@@ -55,7 +55,7 @@ Game Compatibility
|
||||
| Rance 5D - The Lonely Girl (MangaGamer) | Supported | |
|
||||
| 俺の下であがけ | Unknown | |
|
||||
| 楽園行 | Unknown | |
|
||||
| 妻みぐい2 | Supported | Opening demo is not supported |
|
||||
| 妻みぐい2 | Supported | |
|
||||
| シェル・クレイル | Supported | |
|
||||
| ナイトデーモン | Supported | |
|
||||
| 学園KING | Supported | From アリスCD |
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -73,6 +73,7 @@ static void ndd_run(int demonum) {
|
||||
if (sys_keywait(wait_ms, KEYWAIT_CANCELABLE))
|
||||
break;
|
||||
} else {
|
||||
sdl_updateScreen();
|
||||
if (sys_getInputInfo())
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+72
-2
@@ -1,3 +1,23 @@
|
||||
/*
|
||||
* 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>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -7,6 +27,16 @@
|
||||
#include "xsystem35.h"
|
||||
#include "modules.h"
|
||||
#include "nact.h"
|
||||
#include "alk.h"
|
||||
#include "input.h"
|
||||
#include "bgm.h"
|
||||
#include "sdl_core.h"
|
||||
#include "ngraph.h"
|
||||
#include "cg.h"
|
||||
#include "jpeg.h"
|
||||
|
||||
#define TDEMO_MUSIC_NO 1
|
||||
#define FPS 30
|
||||
|
||||
static void Init() {
|
||||
int p1 = getCaliValue();
|
||||
@@ -16,7 +46,7 @@ static void Init() {
|
||||
|
||||
*var = 1;
|
||||
|
||||
DEBUG_COMMAND_YET("tDemo.Init %d,%d,%d,%p:", p1, p2, p3, var);
|
||||
DEBUG_COMMAND("tDemo.Init %d,%d,%d,%p:", p1, p2, p3, var);
|
||||
}
|
||||
|
||||
static void SetKeyCancelFlag() {
|
||||
@@ -33,7 +63,47 @@ static void SetLoopFlag() {
|
||||
}
|
||||
|
||||
static void Run() {
|
||||
DEBUG_COMMAND_YET("tDemo.Run:");
|
||||
alk_t *alk = alk_new("tDEMO.alk");
|
||||
if (!alk) {
|
||||
WARNING("Cannot open tDEMO.alk");
|
||||
return;
|
||||
}
|
||||
|
||||
while (sys_getInputInfo()); // wait for key up
|
||||
|
||||
musbgm_play(TDEMO_MUSIC_NO, 0, 100);
|
||||
|
||||
uint32_t start = sdl_getTicks();
|
||||
while (!nact->is_quit) {
|
||||
int i = (sdl_getTicks() - start) / (1000 / FPS);
|
||||
if (i >= alk->datanum)
|
||||
break;
|
||||
|
||||
cgdata *cg = jpeg_extract(alk->entries[i].data, alk->entries[i].size);
|
||||
if (cg) {
|
||||
gr_drawimage24(sf0, cg, 0, 0);
|
||||
ags_updateFull();
|
||||
cgdata_free(cg);
|
||||
} else {
|
||||
WARNING("Cannot decode CG %d", i);
|
||||
}
|
||||
|
||||
int wait_ms = (i + 1) * (1000 / FPS) - (sdl_getTicks() - start);
|
||||
if (wait_ms > 0) {
|
||||
if (sys_keywait(wait_ms, KEYWAIT_CANCELABLE))
|
||||
break;
|
||||
} else {
|
||||
sdl_updateScreen();
|
||||
if (sys_getInputInfo())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
musbgm_stop(TDEMO_MUSIC_NO, 0);
|
||||
|
||||
alk_free(alk);
|
||||
|
||||
DEBUG_COMMAND("tDemo.Run:");
|
||||
}
|
||||
|
||||
static const ModuleFunc functions[] = {
|
||||
|
||||
+10
-6
@@ -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()
|
||||
|
||||
@@ -159,15 +156,22 @@ if (EMSCRIPTEN)
|
||||
|
||||
target_link_options(xsystem35 PRIVATE
|
||||
-sENVIRONMENT=web
|
||||
-sMODULARIZE=1
|
||||
-sEXPORT_ES6=1
|
||||
-sASYNCIFY=1
|
||||
-sASYNCIFY_IGNORE_INDIRECT=1
|
||||
-sASYNCIFY_REMOVE=SDL_Delay
|
||||
-sASYNCIFY_IMPORTS=muspcm_load_no,muspcm_load_data,muspcm_load_mixlr,muspcm_waitend,wait_vsync,load_mincho_font
|
||||
-sASYNCIFY_IMPORTS=wait_vsync
|
||||
# Functions that call an asynchronous function via a function pointer must
|
||||
# be added to ASYNCIFY_ADD, even if it had a direct call to another
|
||||
# asynchronous function, so that the indirect call itself is instrumented.
|
||||
-sASYNCIFY_ADD=commands2F60,nact_main,send_agsevent,cb_waitkey_sprite
|
||||
-sALLOW_MEMORY_GROWTH=1
|
||||
-sNO_EXIT_RUNTIME=1
|
||||
-sEXPORTED_FUNCTIONS=_main,_malloc
|
||||
-sEXPORTED_RUNTIME_METHODS=getValue,addRunDependency,removeRunDependency)
|
||||
-sEXPORTED_RUNTIME_METHODS=FS,IDBFS,getValue,addRunDependency,removeRunDependency,stringToUTF8OnStack
|
||||
--emit-tsd=xsystem35.d.ts
|
||||
)
|
||||
|
||||
elseif (ANDROID)
|
||||
target_link_libraries(xsystem35 PRIVATE ${ndk_log})
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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"
|
||||
};
|
||||
@@ -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"
|
||||
};
|
||||
@@ -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"
|
||||
};
|
||||
@@ -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"
|
||||
};
|
||||
@@ -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"
|
||||
};
|
||||
@@ -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"
|
||||
};
|
||||
@@ -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"
|
||||
};
|
||||
@@ -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"
|
||||
};
|
||||
@@ -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"
|
||||
};
|
||||
@@ -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"
|
||||
};
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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])
|
||||
|
||||
@@ -77,7 +77,7 @@ static bool read_index(int volume, drifiles *d, FILE *fp) {
|
||||
|
||||
drifiles *dri_init(const char **file, int cnt, boolean use_mmap) {
|
||||
drifiles *d = calloc(1, sizeof(drifiles));
|
||||
#ifndef HAVE_MEMORY_MAPPED_FILE
|
||||
#if !defined(HAVE_MEMORY_MAPPED_FILE) || defined(__EMSCRIPTEN__)
|
||||
use_mmap = FALSE;
|
||||
#endif
|
||||
|
||||
|
||||
+54
-149
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
+21
-2
@@ -29,11 +29,10 @@
|
||||
#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"
|
||||
@@ -126,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);
|
||||
@@ -162,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
@@ -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
@@ -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
|
||||
|
||||
+13
-1
@@ -124,13 +124,25 @@ boolean initGameResourceFromDir(GameResource *gr, DIR *dir, const char *savedir,
|
||||
if (basename && (savedir || !found_xsleep)) {
|
||||
const char *dir = savedir ? savedir : "";
|
||||
const char *sep = savedir ? "/" : "";
|
||||
char *buf = malloc(strlen(dir) + strlen(sep) + strlen(basename) + 6);
|
||||
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%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";
|
||||
|
||||
+15
-9
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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';
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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__ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
+16
-5
@@ -202,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);
|
||||
@@ -214,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
@@ -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);
|
||||
|
||||
+13
-2
@@ -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);
|
||||
@@ -221,6 +222,13 @@ void send_agsevent(enum agsevent_type type, int code) {
|
||||
.mousey = mousey
|
||||
};
|
||||
nact->ags.eventcb(&agse); // Async in emscripten
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// HACK: this ensures that callers of this function are instrumented.
|
||||
// This is necessary because ASYNCIFY_PROPAGATE_ADD does not work:
|
||||
// https://github.com/emscripten-core/emscripten/issues/23015
|
||||
emscripten_sleep(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sdl_setCursorInternalLocation(int x, int y) {
|
||||
@@ -259,7 +267,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 +289,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 +456,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
@@ -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を描画後、後始末
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+1
-8
@@ -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!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +155,7 @@ static void makeDIB(int width, int height, int depth) {
|
||||
SDL_FreeSurface(sdl_dib);
|
||||
}
|
||||
|
||||
uint32_t format;
|
||||
uint32_t format = 0;
|
||||
switch (depth) {
|
||||
case 8:
|
||||
format = SDL_PIXELFORMAT_INDEX8;
|
||||
|
||||
+7
-2
@@ -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);
|
||||
|
||||
+177
-38
@@ -19,78 +19,217 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <SDL.h>
|
||||
#include "scenario.h"
|
||||
#include "texthook.h"
|
||||
#include "nact.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__ // ----------------------------------------------
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
void texthook_message(const char *m) {
|
||||
char *utf = toUTF8(m);
|
||||
EM_ASM_({ xsystem35.texthook.message(UTF8ToString($0), $1); },
|
||||
utf, sl_getPage());
|
||||
free(utf);
|
||||
}
|
||||
static struct {
|
||||
int newlines;
|
||||
} print;
|
||||
|
||||
EM_JS(void, texthook_newline, (void), {
|
||||
xsystem35.texthook.newline();
|
||||
});
|
||||
|
||||
EM_JS(void, texthook_nextpage, (void), {
|
||||
xsystem35.texthook.nextpage();
|
||||
});
|
||||
|
||||
EM_JS(void, texthook_keywait, (void), {
|
||||
xsystem35.texthook.keywait();
|
||||
});
|
||||
|
||||
|
||||
#elif defined(TEXTHOOK_PRINT) // --------------------------------------
|
||||
|
||||
static int newlines = 0;
|
||||
|
||||
void texthook_message(const char *m) {
|
||||
if (newlines)
|
||||
static void texthook_print_message(const char *m) {
|
||||
if (print.newlines)
|
||||
printf("%d:", sl_getPage());
|
||||
char *utf = toUTF8(m);
|
||||
printf("%s", utf);
|
||||
free(utf);
|
||||
newlines = 0;
|
||||
print.newlines = 0;
|
||||
}
|
||||
|
||||
void texthook_newline(void) {
|
||||
if (newlines < 2) {
|
||||
static void texthook_print_newline(void) {
|
||||
if (print.newlines < 2) {
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
newlines++;
|
||||
print.newlines++;
|
||||
}
|
||||
}
|
||||
|
||||
void texthook_nextpage(void) {
|
||||
while (newlines < 2) {
|
||||
static void texthook_print_nextpage(void) {
|
||||
while (print.newlines < 2) {
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
newlines++;
|
||||
print.newlines++;
|
||||
}
|
||||
}
|
||||
|
||||
void texthook_keywait(void) {
|
||||
texthook_newline();
|
||||
static void texthook_print_keywait(void) {
|
||||
texthook_print_newline();
|
||||
}
|
||||
|
||||
#else // --------------------------------------------------------------
|
||||
static struct {
|
||||
char *buf;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} copy;
|
||||
|
||||
static void texthook_copy_message(const char *m) {
|
||||
size_t len = strlen(m);
|
||||
if (copy.pos + len + 1 > copy.size) {
|
||||
copy.size += min(copy.pos + len + 1, 100);
|
||||
copy.buf = realloc(copy.buf, copy.size);
|
||||
}
|
||||
strcpy(copy.buf + copy.pos, m);
|
||||
copy.pos += len;
|
||||
}
|
||||
|
||||
static void texthook_copy_newline(void) {
|
||||
if (copy.pos == 0)
|
||||
return;
|
||||
texthook_message("\n");
|
||||
}
|
||||
|
||||
static void texthook_copy_to_clipboard(void) {
|
||||
char *utf = toUTF8(copy.buf);
|
||||
SDL_SetClipboardText(utf);
|
||||
free(utf);
|
||||
copy.pos = 0;
|
||||
}
|
||||
|
||||
static void texthook_copy_nextpage(void) {
|
||||
if (copy.pos > 0)
|
||||
texthook_copy_to_clipboard();
|
||||
}
|
||||
|
||||
static void texthook_copy_keywait(void) {
|
||||
if (copy.pos > 0)
|
||||
texthook_copy_to_clipboard();
|
||||
}
|
||||
|
||||
static enum texthook_mode mode = TEXTHOOK_NONE;
|
||||
static int *suppression_list = NULL;
|
||||
static enum {
|
||||
INIT,
|
||||
SUPPRESSING,
|
||||
EMITTING,
|
||||
} suppression_state = INIT;
|
||||
|
||||
void texthook_set_mode(enum texthook_mode m) {
|
||||
mode = m;
|
||||
}
|
||||
|
||||
// suppressions is a comma-separated list of page numbers to suppress.
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void texthook_set_suppression_list(const char *suppressions) {
|
||||
if (suppression_list != NULL) {
|
||||
free(suppression_list);
|
||||
}
|
||||
if (!suppressions) {
|
||||
suppression_list = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
int count = 1;
|
||||
for (const char *p = suppressions; *p; p++) {
|
||||
if (*p == ',')
|
||||
count++;
|
||||
}
|
||||
|
||||
suppression_list = (int*)malloc((count + 1) * sizeof(int));
|
||||
|
||||
int index = 0;
|
||||
char *buf = strdup(suppressions);
|
||||
char *token = strtok(buf, ",");
|
||||
while (token) {
|
||||
suppression_list[index++] = atoi(token);
|
||||
token = strtok(NULL, ",");
|
||||
}
|
||||
free(buf);
|
||||
|
||||
suppression_list[index] = -1; // sentinel
|
||||
}
|
||||
|
||||
static void set_suppression_state(void) {
|
||||
int page = sl_getPage();
|
||||
if (suppression_list != NULL) {
|
||||
for (int i = 0; suppression_list[i] != -1; i++) {
|
||||
if (page == suppression_list[i]) {
|
||||
suppression_state = SUPPRESSING;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
suppression_state = EMITTING;
|
||||
}
|
||||
|
||||
void texthook_message(const char *m) {
|
||||
if (suppression_state == INIT)
|
||||
set_suppression_state();
|
||||
if (suppression_state == SUPPRESSING)
|
||||
return;
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
char *utf = toUTF8(m);
|
||||
EM_ASM(xsystem35.texthook.message(UTF8ToString($0)), utf);
|
||||
free(utf);
|
||||
#else
|
||||
switch (mode) {
|
||||
case TEXTHOOK_NONE:
|
||||
break;
|
||||
case TEXTHOOK_PRINT:
|
||||
texthook_print_message(m);
|
||||
break;
|
||||
case TEXTHOOK_COPY:
|
||||
texthook_copy_message(m);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void texthook_newline(void) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM(xsystem35.texthook.newline());
|
||||
#else
|
||||
switch (mode) {
|
||||
case TEXTHOOK_NONE:
|
||||
break;
|
||||
case TEXTHOOK_PRINT:
|
||||
texthook_print_newline();
|
||||
break;
|
||||
case TEXTHOOK_COPY:
|
||||
texthook_copy_newline();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
suppression_state = INIT;
|
||||
}
|
||||
|
||||
void texthook_nextpage(void) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM(xsystem35.texthook.nextpage());
|
||||
#else
|
||||
switch (mode) {
|
||||
case TEXTHOOK_NONE:
|
||||
break;
|
||||
case TEXTHOOK_PRINT:
|
||||
texthook_print_nextpage();
|
||||
break;
|
||||
case TEXTHOOK_COPY:
|
||||
texthook_copy_nextpage();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
suppression_state = INIT;
|
||||
}
|
||||
|
||||
void texthook_keywait(void) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM(xsystem35.texthook.keywait());
|
||||
#else
|
||||
switch (mode) {
|
||||
case TEXTHOOK_NONE:
|
||||
break;
|
||||
case TEXTHOOK_PRINT:
|
||||
texthook_print_keywait();
|
||||
break;
|
||||
case TEXTHOOK_COPY:
|
||||
texthook_copy_keywait();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
suppression_state = INIT;
|
||||
}
|
||||
|
||||
#endif // -------------------------------------------------------------
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
#ifndef __TEXTHOOK__
|
||||
#define __TEXTHOOK__
|
||||
|
||||
enum texthook_mode {
|
||||
TEXTHOOK_NONE,
|
||||
TEXTHOOK_PRINT,
|
||||
TEXTHOOK_COPY,
|
||||
};
|
||||
|
||||
void texthook_set_mode(enum texthook_mode mode);
|
||||
void texthook_set_suppression_list(const char *suppressions);
|
||||
void texthook_message(const char *m);
|
||||
void texthook_newline(void);
|
||||
void texthook_nextpage(void);
|
||||
|
||||
@@ -36,6 +36,7 @@ static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) {
|
||||
void win_alloc_console(void) {
|
||||
AllocConsole();
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
freopen("CONOUT$", "w", stderr);
|
||||
freopen("CONIN$", "r", stdin);
|
||||
SetConsoleCP(CP_UTF8);
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
|
||||
+17
-6
@@ -28,6 +28,9 @@
|
||||
#include "sdl_private.h"
|
||||
#include "resources.h"
|
||||
#include "msgskip.h"
|
||||
#include "texthook.h"
|
||||
|
||||
static HMENU hmenu;
|
||||
|
||||
static HWND get_hwnd(SDL_Window *window) {
|
||||
SDL_SysWMinfo info;
|
||||
@@ -60,9 +63,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 +82,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 +90,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 +106,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))
|
||||
@@ -118,6 +120,10 @@ void win_menu_onsyswmevent(SDL_SysWMmsg* msg) {
|
||||
if (toggle_menu_item(ID_OPTION_MOUSE_MOVE, &checked))
|
||||
nact->ags.mouse_warp_enabled = checked;
|
||||
break;
|
||||
case ID_OPTION_AUTO_COPY:
|
||||
if (toggle_menu_item(ID_OPTION_AUTO_COPY, &checked))
|
||||
texthook_set_mode(checked ? TEXTHOOK_COPY : TEXTHOOK_NONE);
|
||||
break;
|
||||
case ID_MSGSKIP:
|
||||
msgskip_activate(!msgskip_isActivated());
|
||||
break;
|
||||
@@ -126,9 +132,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);
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#define ID_SCREEN_FULL 40012
|
||||
#define ID_SCREEN_INTEGER_SCALING 40013
|
||||
#define ID_OPTION_MOUSE_MOVE 40021
|
||||
#define ID_OPTION_AUTO_COPY 40022
|
||||
#define ID_MSGSKIP 40030
|
||||
|
||||
struct SDL_RWops;
|
||||
|
||||
@@ -32,6 +32,7 @@ IDR_MENU1 MENU DISCARDABLE
|
||||
POPUP "Option"
|
||||
{
|
||||
MENUITEM "Mouse Movement", ID_OPTION_MOUSE_MOVE
|
||||
MENUITEM "Auto Copy Text to Clipboard", ID_OPTION_AUTO_COPY
|
||||
}
|
||||
MENUITEM "MsgSkip[off]", ID_MSGSKIP
|
||||
}
|
||||
@@ -71,6 +72,7 @@ IDR_MENU1 MENU DISCARDABLE
|
||||
POPUP "オプション"
|
||||
{
|
||||
MENUITEM "マウスカーソル移動", ID_OPTION_MOUSE_MOVE
|
||||
MENUITEM "テキストを自動コピー", ID_OPTION_AUTO_COPY
|
||||
}
|
||||
MENUITEM "文字送り[off]", ID_MSGSKIP
|
||||
}
|
||||
|
||||
+63
-40
@@ -72,6 +72,7 @@
|
||||
#include "filecheck.h"
|
||||
#include "s39init.h"
|
||||
#include "msgskip.h"
|
||||
#include "texthook.h"
|
||||
|
||||
static char *gameResourceFile = "xsystem35.gr";
|
||||
static void sys35_usage(boolean verbose);
|
||||
@@ -111,51 +112,46 @@ static void sys35_usage(boolean verbose) {
|
||||
}
|
||||
puts("Usage: xsystem35 [OPTIONS]\n");
|
||||
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'");
|
||||
puts(" -devmidi device : set midi device name to 'device'");
|
||||
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'");
|
||||
puts(" -texthook mode : text hook mode. 'none' (default), 'print' or 'copy'");
|
||||
puts(" -texthook_suppress list : suppress text hook on specified pages");
|
||||
|
||||
puts(" -M? : select output midi methos");
|
||||
puts(" -M? : select output midi methos");
|
||||
#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)");
|
||||
puts(" -Me : SDL_mixer midi player");
|
||||
#endif
|
||||
#ifdef ENABLE_MIDI_PORTMIDI
|
||||
puts(" -Mp? : ALSA (via PortMidi) (?:devicenumber)");
|
||||
puts(" -Mp? : ALSA (via PortMidi) (?:devicenumber)");
|
||||
#endif
|
||||
puts(" -M0 : Disable MIDI output");
|
||||
puts(" -M0 : Disable MIDI output");
|
||||
|
||||
puts(" -devjoy device : joystick device index (0-)");
|
||||
puts(" -devjoy device : joystick device index (0-)");
|
||||
|
||||
puts(" -ttfont_mincho : set TrueType font for mincho");
|
||||
puts(" -ttfont_gothic : set TrueType font for mincho");
|
||||
puts(" -ttfont_mincho : set TrueType font for mincho");
|
||||
puts(" -ttfont_gothic : set TrueType font for mincho");
|
||||
|
||||
#ifdef DEBUG
|
||||
puts(" -debuglv # : logging level");
|
||||
puts(" : 1: warings");
|
||||
puts(" : 2: unimplemented commands");
|
||||
puts(" : 5: command trace");
|
||||
puts(" : 6: message trace");
|
||||
puts(" -debuglv # : logging level");
|
||||
puts(" : 1: warings");
|
||||
puts(" : 2: unimplemented commands");
|
||||
puts(" : 5: command trace");
|
||||
puts(" : 6: message trace");
|
||||
#endif
|
||||
#ifdef ENABLE_DEBUGGER
|
||||
puts(" -debug : start with debugger");
|
||||
puts(" -debug : start with debugger");
|
||||
#endif
|
||||
puts(" -noantialias : never use antialiased string");
|
||||
puts(" -fullscreen : start with fullscreen");
|
||||
puts(" -integerscale : use integer scaling when resizing");
|
||||
puts(" -noimagecursor : disable image cursor");
|
||||
puts(" -version : show version");
|
||||
puts(" -h : show this message");
|
||||
puts(" --help : show this message");
|
||||
puts(" -noantialias : never use antialiased string");
|
||||
puts(" -fullscreen : start with fullscreen");
|
||||
puts(" -integerscale : use integer scaling when resizing");
|
||||
puts(" -noimagecursor : disable image cursor");
|
||||
puts(" -version : show version");
|
||||
puts(" -h : show this message");
|
||||
puts(" --help : show this message");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -248,6 +244,19 @@ static void sys_reset(void) {
|
||||
s39ain_reset(&nact->ain);
|
||||
}
|
||||
|
||||
static bool set_texthook_mode(const char *mode) {
|
||||
if (!strcasecmp(mode, "none")) {
|
||||
texthook_set_mode(TEXTHOOK_NONE);
|
||||
} else if (!strcasecmp(mode, "print")) {
|
||||
texthook_set_mode(TEXTHOOK_PRINT);
|
||||
} else if (!strcasecmp(mode, "copy")) {
|
||||
texthook_set_mode(TEXTHOOK_COPY);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void sys35_ParseOption(int *argc, char **argv) {
|
||||
int i;
|
||||
FILE *fp;
|
||||
@@ -288,9 +297,16 @@ 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")) {
|
||||
} else if (0 == strcmp(argv[i], "-texthook")) {
|
||||
if (argv[i + 1] != NULL) {
|
||||
midi_set_devicename(argv[i + 1]);
|
||||
if (!set_texthook_mode(argv[i + 1])) {
|
||||
fprintf(stderr, "xsystem35: Invalid texthook mode '%s'\n\n", argv[i + 1]);
|
||||
sys35_usage(FALSE);
|
||||
}
|
||||
}
|
||||
} else if (0 == strcmp(argv[i], "-texthook_suppress")) {
|
||||
if (argv[i + 1] != NULL) {
|
||||
texthook_set_suppression_list(argv[i + 1]);
|
||||
}
|
||||
} else if (0 == strncmp(argv[i], "-M", 2)) {
|
||||
int subdev = 0;
|
||||
@@ -400,11 +416,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) {
|
||||
@@ -430,6 +441,18 @@ static void check_profile() {
|
||||
if (param) {
|
||||
save_setFormat(param);
|
||||
}
|
||||
|
||||
/* text hook */
|
||||
param = get_profile("texthook");
|
||||
if (param) {
|
||||
if (!set_texthook_mode(param)) {
|
||||
sys_error("Invalid texthook mode '%s'", param);
|
||||
}
|
||||
}
|
||||
param = get_profile("texthook_suppress");
|
||||
if (param) {
|
||||
texthook_set_suppression_list(param);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user