mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-09-30 02:38:10 +03:00
Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3314f00bf8 | ||
|
|
a2d79f045c | ||
|
|
f247495578 | ||
|
|
f6583330de | ||
|
|
4b15f45897 | ||
|
|
7bc433731f | ||
|
|
4c21570eb1 | ||
|
|
a3e7feffc2 | ||
|
|
a4c1dd1acf | ||
|
|
09086ccc85 | ||
|
|
53e39b7c11 | ||
|
|
f0ccfee40f | ||
|
|
10cdec98e6 | ||
|
|
c61afb4308 | ||
|
|
f6cf881e61 | ||
|
|
a8277e71a7 | ||
|
|
3482fb6440 | ||
|
|
3c81c8fec2 | ||
|
|
e090485b37 |
@@ -15,7 +15,7 @@ jobs:
|
||||
run: |
|
||||
cd android
|
||||
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > keystore.jks
|
||||
ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk-bundle ./gradlew assembleRelease
|
||||
JAVA_HOME=$JAVA_HOME_17_X64 ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk-bundle ./gradlew assembleRelease
|
||||
env:
|
||||
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
|
||||
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
|
||||
|
||||
@@ -8,7 +8,7 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- { sys: MINGW32, installer: "xsystem35-32bit" }
|
||||
- { sys: MINGW64, installer: "xsystem35-64bit" }
|
||||
- { sys: UCRT64, installer: "xsystem35-64bit" }
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
@@ -19,7 +19,6 @@ jobs:
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.sys }}
|
||||
update: true
|
||||
pacboy: >-
|
||||
gcc:p
|
||||
cmake:p
|
||||
@@ -30,7 +29,7 @@ jobs:
|
||||
libwebp:p
|
||||
cjson:p
|
||||
nsis:p
|
||||
ntldd-git:p
|
||||
ntldd:p
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
@@ -3,22 +3,22 @@
|
||||
This is a multi-platform port of `xsystem35`, a free implementation of
|
||||
AliceSoft's System 3.x game engine.
|
||||
|
||||
## Compatiblity
|
||||
## Compatibility
|
||||
|
||||
See the [game compatibility table](game_compatibility.md) for a list of games
|
||||
that can be played on xsystem35-sdl2.
|
||||
that can be played with xsystem35-sdl2.
|
||||
|
||||
## Unique Features
|
||||
|
||||
In addition to the original System 3.x's functionalities, xsystem35-sdl2 has
|
||||
the following features.
|
||||
In addition to the original System 3.x functionalities, xsystem35-sdl2 offers
|
||||
the following features:
|
||||
|
||||
### Playing audio files as fake CD music
|
||||
### Playing Audio Files as Virtual CD Music
|
||||
|
||||
Many System 3.x games had music as audio tracks on the CD-ROM. Xsystem35 can
|
||||
play music from audio files instead, to avoid the hassle of inserting CDs. To
|
||||
use ripped audio files, create a file named `playlist.txt` in the game
|
||||
directory, and enter the paths to your tracks, one per line. For example:
|
||||
Many System 3.x games feature music as audio tracks on the CD-ROM. xsystem35
|
||||
can play music from audio files, eliminating the need to insert CDs. To use
|
||||
ripped audio files, create a file named `playlist.txt` in the game directory
|
||||
and list the paths to your tracks, one per line. For example:
|
||||
|
||||
```
|
||||
# The first line is not used
|
||||
@@ -27,89 +27,109 @@ BGM/track03.mp3
|
||||
...
|
||||
```
|
||||
|
||||
The first line is not used, because track 1 of game CD is usually a data track.
|
||||
The first line is not used because the first track on a game CD is typically a
|
||||
data track.
|
||||
|
||||
### Unicode translation support
|
||||
Some games have integrated music as MIDI. In such cases, the music won't play
|
||||
using the virtual CD feature. If you encounter a `Cannot load MIDI` error
|
||||
message, you might need to set the `SDL_SOUNDFONTS` environment variable to
|
||||
point to an `.sf2` file. For example:
|
||||
|
||||
The original System 3.x only supported Shift_JIS (a Japanese character
|
||||
encoding), but xsystem35 supports Unicode and is able to run games translated
|
||||
into languages other than Japanese and English.
|
||||
```
|
||||
SDL_SOUNDFONTS=/usr/share/soundfonts/GeneralUser.sf2 xsystem35
|
||||
```
|
||||
|
||||
See [xsys35c](https://github.com/kichikuou/xsys35c)'s document for how to
|
||||
build a game with Unicode mode.
|
||||
### Unicode Translation Support
|
||||
|
||||
While the original System 3.x only supported Shift_JIS (a Japanese character
|
||||
encoding), xsystem35 supports Unicode and can run games translated into
|
||||
languages other than Japanese and English.
|
||||
|
||||
For instructions on how to build a game with Unicode support, see the
|
||||
[xsys35c](https://github.com/kichikuou/xsys35c) documentation.
|
||||
|
||||
### Debugging
|
||||
|
||||
Xsystem35 has a built-in debugger that allows you to step through the game and
|
||||
examine / modify variables in the game. There are two ways to use the debugger:
|
||||
xsystem35 features a built-in debugger that allows you to step through the game
|
||||
and examine or modify game variables. There are two ways to use the debugger:
|
||||
|
||||
- Through [Visual Studio Code](https://code.visualstudio.com/) (recommended):
|
||||
The [vscode-system3x](https://github.com/kichikuou/vscode-system3x) extension
|
||||
provides graphical debugging interface for System 3.x.
|
||||
- Using CUI debugger: Running xsystem35 with `-debug` option will start the
|
||||
debugger with console interface. Type `help` to see a list of available
|
||||
commands.
|
||||
provides a graphical debugging interface for System 3.x.
|
||||
- Using the CLI Debugger: Running xsystem35 with the `-debug` option will
|
||||
launch the debugger with a console interface. Type `help` to see a list of
|
||||
available commands.
|
||||
|
||||
## Installing
|
||||
## Installation
|
||||
|
||||
Prebuilt packages for Windows and Android can be downloaded from the
|
||||
[Releases](https://github.com/kichikuou/xsystem35-sdl2/releases) page. For
|
||||
other platforms, see the [Building](#building) section.
|
||||
other platforms, refer to the [Building](#building) section.
|
||||
|
||||
## Running
|
||||
### Windows
|
||||
|
||||
Execute `xsytem35`, and it will show a dialog to select a folder. Select the
|
||||
game folder (where the ALD files are located).
|
||||
Execute `xsystem35`, and a dialog will appear for you to select a folder.
|
||||
Choose the game folder (where the ALD files are located).
|
||||
|
||||
### Android
|
||||
|
||||
See [android/README.md](https://github.com/kichikuou/xsystem35-sdl2/blob/master/android/README.md#use).
|
||||
See [android/README.md](android/README.md#use).
|
||||
|
||||
### Other Platforms
|
||||
|
||||
Run xsystem35 from within the game directory.
|
||||
|
||||
cd /path/to/game_directory
|
||||
xsystem35
|
||||
```bash
|
||||
$ cd /path/to/game_directory
|
||||
$ xsystem35
|
||||
```
|
||||
|
||||
## Building
|
||||
### Linux (Debian / Ubuntu)
|
||||
|
||||
$ sudo apt install build-essential cmake libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libcjson-dev
|
||||
$ mkdir -p out/debug
|
||||
$ cd out/debug
|
||||
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
|
||||
$ make && make install
|
||||
```bash
|
||||
$ sudo apt install build-essential cmake libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libcjson-dev
|
||||
$ mkdir -p out/debug
|
||||
$ cd out/debug
|
||||
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
|
||||
$ make && make install
|
||||
```
|
||||
|
||||
### MacOS
|
||||
|
||||
[Homebrew](https://brew.sh/index_ja) is needed.
|
||||
[Homebrew](https://brew.sh/) is required.
|
||||
|
||||
$ brew install cmake pkg-config sdl2 sdl2_mixer sdl2_ttf webp cjson
|
||||
$ mkdir -p out/debug
|
||||
$ cd out/debug
|
||||
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
|
||||
$ make && make install
|
||||
```bash
|
||||
$ brew install cmake pkg-config sdl2 sdl2_mixer sdl2_ttf webp cjson
|
||||
$ mkdir -p out/debug
|
||||
$ cd out/debug
|
||||
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
|
||||
$ make && make install
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
[MSYS2](https://www.msys2.org) is needed.
|
||||
[MSYS2](https://www.msys2.org) is required.
|
||||
|
||||
$ pacman -S cmake mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2_ttf mingw-w64-x86_64-SDL2_mixer mingw-w64-x86_64-libwebp mingw-w64-x86_64-cjson
|
||||
$ mkdir -p out/debug
|
||||
$ cd out/debug
|
||||
$ cmake -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug ../../
|
||||
$ make
|
||||
```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
|
||||
$ mkdir -p out/debug
|
||||
$ cd out/debug
|
||||
$ cmake -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug ../../
|
||||
$ make
|
||||
```
|
||||
|
||||
### Emscripten
|
||||
|
||||
$ mkdir -p out/wasm
|
||||
$ cd out/wasm
|
||||
$ emcmake cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../../
|
||||
$ make
|
||||
```bash
|
||||
$ mkdir -p out/wasm
|
||||
$ cd out/wasm
|
||||
$ emcmake cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../../
|
||||
$ make
|
||||
```
|
||||
|
||||
To use the generated binary, checkout
|
||||
To use the generated binary, check out
|
||||
[Kichikuou on Web](https://github.com/kichikuou/web) and copy `out/xsystem35.*`
|
||||
into its `docs` directory.
|
||||
|
||||
|
||||
+34
-20
@@ -1,7 +1,8 @@
|
||||
# xsystem35 for Android
|
||||
|
||||
## Download
|
||||
Prebuilt APKs are [here](https://github.com/kichikuou/xsystem35-sdl2/releases).
|
||||
You can download prebuilt APKs
|
||||
[here](https://github.com/kichikuou/xsystem35-sdl2/releases).
|
||||
|
||||
## Build
|
||||
Prerequisites:
|
||||
@@ -11,10 +12,10 @@ Prerequisites:
|
||||
### Using Android Studio
|
||||
Open this directory as an Android Studio project.
|
||||
|
||||
### Command line build
|
||||
Configure environment variables and run the `gradlew` script in this folder.
|
||||
### Command Line Build
|
||||
Set environment variables and run the `gradlew` script in this directory.
|
||||
|
||||
Example build instructions (for Debian bullseye):
|
||||
Example build instructions (for Debian bookworm):
|
||||
```sh
|
||||
# Install necessary packages
|
||||
sudo apt install git wget unzip default-jdk-headless ninja-build
|
||||
@@ -22,38 +23,51 @@ sudo apt install git wget unzip default-jdk-headless ninja-build
|
||||
# Install Android SDK / NDK
|
||||
export ANDROID_SDK_ROOT=$HOME/android-sdk
|
||||
mkdir -p $ANDROID_SDK_ROOT/cmdline-tools
|
||||
wget https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip
|
||||
unzip commandlinetools-linux-8512546_latest.zip -d $ANDROID_SDK_ROOT/cmdline-tools
|
||||
wget https://dl.google.com/android/repository/commandlinetools-linux-10406996_latest.zip
|
||||
unzip commandlinetools-linux-10406996_latest.zip -d $ANDROID_SDK_ROOT/cmdline-tools
|
||||
mv $ANDROID_SDK_ROOT/cmdline-tools/cmdline-tools $ANDROID_SDK_ROOT/cmdline-tools/tools
|
||||
yes |$ANDROID_SDK_ROOT/cmdline-tools/tools/bin/sdkmanager --licenses
|
||||
yes | $ANDROID_SDK_ROOT/cmdline-tools/tools/bin/sdkmanager --licenses
|
||||
$ANDROID_SDK_ROOT/cmdline-tools/tools/bin/sdkmanager ndk-bundle 'cmake;3.22.1'
|
||||
export ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk-bundle
|
||||
|
||||
# Check out and build xsystem35
|
||||
# Clone and build xsystem35
|
||||
git clone https://github.com/kichikuou/xsystem35-sdl2.git
|
||||
cd xsystem35-sdl2/android
|
||||
./gradlew build # or ./gradlew installDebug if you have a connected device
|
||||
```
|
||||
|
||||
## Use
|
||||
## Usage
|
||||
### Basic Usage
|
||||
1. Create a ZIP file containing all the game files and BGM files (see [below](#preparing-a-zip) for details), and transfer it to your device.
|
||||
2. Open the app. A list of installed games is displayed. Since nothing has been installed yet, only the "Install from ZIP" button is displayed. Tap it.
|
||||
3. Select the ZIP file you created in 1.
|
||||
4. The game starts. To simulate right-click, tap the black bars on the left/right or top/bottom of the screen.
|
||||
1. Create a ZIP file containing all the game files and BGM files (see
|
||||
[below](#preparing-a-zip) for details), and transfer it to your device.
|
||||
2. Open the app. A list of installed games will be displayed. Since no games
|
||||
have been installed yet, only the "Install from ZIP" button will be visible.
|
||||
Tap it.
|
||||
3. Select the ZIP file you created in step 1.
|
||||
4. The game will start. To simulate a right-click, tap the black bars on either
|
||||
the left or right, or top or bottom of the screen.
|
||||
|
||||
### Preparing a ZIP
|
||||
- Include all files in the `GAMEDATA` folder (`.ALD` files and others). `.EXE` and `.DLL` are not really needed, but you can include them as well.
|
||||
- Music files (`.mp3`, `.ogg` or `.wav`) whose file names end with a number are recognized as BGM files. For example:
|
||||
- Include all files from the `GAMEDATA` folder (such as `.ALD` files and
|
||||
others). `.EXE` and `.DLL` files are not necessary, but you can include them
|
||||
if you want.
|
||||
- Music files (`.mp3`, `.ogg`, or `.wav`) whose filenames end with a number
|
||||
will be recognized as BGM files. For example:
|
||||
- `Track2.mp3`
|
||||
- `15.ogg`
|
||||
- `rance4_03.wav` (This shouldn't be `rance403.wav`, because it would be treated as the 403rd track)
|
||||
- `rance4_03.wav` (Note: The filename shouldn't be `rance403.wav`, as it
|
||||
would be treated as the 403rd track.)
|
||||
|
||||
Note: This form of ZIP can be used in [Kichikuou on Web](http://kichikuou.github.io/web/) as well.
|
||||
Note: This ZIP format is also compatible with
|
||||
[Kichikuou on Web](http://kichikuou.github.io/web/).
|
||||
|
||||
### Miscellaneous
|
||||
- You can export / import saved files using the option menu of the game list.
|
||||
- To uninstall a game, long-tap the title in the game list.
|
||||
- You can export or import save files via the game list's option menu.
|
||||
- To uninstall a game, long-tap its title in the game list.
|
||||
|
||||
## Known Issues
|
||||
- Android versions older than 7.0 cannot handle ZIPs containing Shift-JIS file names. This is the case with some ZIPs distributed on [retroc.net](http://retropc.net/alice/). If you get the error "This type of ZIP is not supported.", unzip the ZIP file on your PC and re-archive it with a modern ZIP creation software.
|
||||
- Android versions older than 7.0 cannot handle ZIP files containing Shift-JIS
|
||||
filenames. This issue occurs with some ZIP files distributed on
|
||||
[retroc.net](http://retropc.net/alice/). If you encounter the error message
|
||||
"This type of ZIP is not supported," unzip the file on your PC and re-archive
|
||||
it using modern ZIP creation software.
|
||||
|
||||
+13
-11
@@ -9,18 +9,18 @@ else {
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion 31
|
||||
if (buildAsApplication) {
|
||||
namespace "io.github.kichikuou.xsystem35"
|
||||
}
|
||||
compileSdkVersion 34
|
||||
defaultConfig {
|
||||
if (buildAsApplication) {
|
||||
applicationId "io.github.kichikuou.xsystem35"
|
||||
}
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 31
|
||||
versionCode 15
|
||||
versionName "2.9.1" + gitRevision()
|
||||
targetSdkVersion 34
|
||||
versionCode 16
|
||||
versionName "2.10.0" + gitRevision()
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DANDROID_APP_PLATFORM=android-16", "-DANDROID_STL=c++_static"
|
||||
arguments "-DANDROID_APP_PLATFORM=android-19", "-DANDROID_STL=c++_static"
|
||||
// abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a'
|
||||
}
|
||||
@@ -38,7 +38,9 @@ android {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
if (rootProject.file('keystore.jks').exists()) {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
}
|
||||
applicationVariants.all { variant ->
|
||||
@@ -62,10 +64,10 @@ android {
|
||||
}
|
||||
|
||||
}
|
||||
lintOptions {
|
||||
lint {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
|
||||
if (buildAsLibrary) {
|
||||
libraryVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
|
||||
@@ -6,8 +6,8 @@ set(PROJECT_ROOT_DIR ../../..)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
SDL
|
||||
URL https://github.com/libsdl-org/SDL/releases/download/release-2.26.1/SDL2-2.26.1.tar.gz
|
||||
URL_HASH SHA1=08a8cec21ffcebf44e4633a786d594a7811100d2
|
||||
URL https://github.com/libsdl-org/SDL/releases/download/release-2.28.5/SDL2-2.28.5.tar.gz
|
||||
URL_HASH SHA1=50af6b564890d702e57e2a72d6429b43778ed29a
|
||||
)
|
||||
FetchContent_Declare(
|
||||
SDL_ttf
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="io.github.kichikuou.xsystem35"
|
||||
android:installLocation="auto">
|
||||
|
||||
<!-- OpenGL ES 2.0 -->
|
||||
|
||||
@@ -186,7 +186,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
// Because on Chromebooks we show up as a dual-mode device, it will attempt to connect TRANSPORT_AUTO, which will use TRANSPORT_BREDR instead
|
||||
// of TRANSPORT_LE. Let's force ourselves to connect low energy.
|
||||
private BluetoothGatt connectGatt(boolean managed) {
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
if (Build.VERSION.SDK_INT >= 23 /* Android 6.0 (M) */) {
|
||||
try {
|
||||
return mDevice.connectGatt(mManager.getContext(), managed, this, TRANSPORT_LE);
|
||||
} catch (Exception e) {
|
||||
@@ -429,7 +429,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (newState == 0) {
|
||||
mIsConnected = false;
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ public class HIDDeviceManager {
|
||||
Log.i(TAG," Interface protocol: " + mUsbInterface.getInterfaceProtocol());
|
||||
Log.i(TAG," Endpoint count: " + mUsbInterface.getEndpointCount());
|
||||
|
||||
// Get endpoint details
|
||||
// Get endpoint details
|
||||
for (int epi = 0; epi < mUsbInterface.getEndpointCount(); epi++)
|
||||
{
|
||||
UsbEndpoint mEndpoint = mUsbInterface.getEndpoint(epi);
|
||||
@@ -251,6 +251,8 @@ public class HIDDeviceManager {
|
||||
0x20d6, // PowerA
|
||||
0x24c6, // PowerA
|
||||
0x2c22, // Qanba
|
||||
0x2dc8, // 8BitDo
|
||||
0x9886, // ASTRO Gaming
|
||||
};
|
||||
|
||||
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&
|
||||
@@ -271,14 +273,17 @@ public class HIDDeviceManager {
|
||||
final int XB1_IFACE_SUBCLASS = 71;
|
||||
final int XB1_IFACE_PROTOCOL = 208;
|
||||
final int[] SUPPORTED_VENDORS = {
|
||||
0x03f0, // HP
|
||||
0x044f, // Thrustmaster
|
||||
0x045e, // Microsoft
|
||||
0x0738, // Mad Catz
|
||||
0x0e6f, // PDP
|
||||
0x0f0d, // Hori
|
||||
0x10f5, // Turtle Beach
|
||||
0x1532, // Razer Wildcat
|
||||
0x20d6, // PowerA
|
||||
0x24c6, // PowerA
|
||||
0x2dc8, /* 8BitDo */
|
||||
0x2dc8, // 8BitDo
|
||||
0x2e24, // Hyperkin
|
||||
};
|
||||
|
||||
@@ -353,13 +358,13 @@ public class HIDDeviceManager {
|
||||
private void initializeBluetooth() {
|
||||
Log.d(TAG, "Initializing Bluetooth");
|
||||
|
||||
if (Build.VERSION.SDK_INT <= 30 &&
|
||||
if (Build.VERSION.SDK_INT <= 30 /* Android 11.0 (R) */ &&
|
||||
mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
|
||||
Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) || (Build.VERSION.SDK_INT < 18)) {
|
||||
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) || (Build.VERSION.SDK_INT < 18 /* Android 4.3 (JELLY_BEAN_MR2) */)) {
|
||||
Log.d(TAG, "Couldn't initialize Bluetooth, this version of Android does not support Bluetooth LE");
|
||||
return;
|
||||
}
|
||||
@@ -524,7 +529,7 @@ public class HIDDeviceManager {
|
||||
for (HIDDevice device : mDevicesById.values()) {
|
||||
device.setFrozen(frozen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -573,7 +578,7 @@ public class HIDDeviceManager {
|
||||
try {
|
||||
final int FLAG_MUTABLE = 0x02000000; // PendingIntent.FLAG_MUTABLE, but don't require SDK 31
|
||||
int flags;
|
||||
if (Build.VERSION.SDK_INT >= 31) {
|
||||
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
||||
flags = FLAG_MUTABLE;
|
||||
} else {
|
||||
flags = 0;
|
||||
|
||||
@@ -52,7 +52,7 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
@Override
|
||||
public String getSerialNumber() {
|
||||
String result = null;
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
|
||||
try {
|
||||
result = mDevice.getSerialNumber();
|
||||
}
|
||||
@@ -74,7 +74,7 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
@Override
|
||||
public String getManufacturerName() {
|
||||
String result = null;
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
|
||||
result = mDevice.getManufacturerName();
|
||||
}
|
||||
if (result == null) {
|
||||
@@ -86,7 +86,7 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
@Override
|
||||
public String getProductName() {
|
||||
String result = null;
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
|
||||
result = mDevice.getProductName();
|
||||
}
|
||||
if (result == null) {
|
||||
|
||||
@@ -29,6 +29,7 @@ public class SDL {
|
||||
|
||||
// This function stores the current activity (SDL or not)
|
||||
public static void setContext(Context context) {
|
||||
SDLAudioManager.setContext(context);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ import java.util.Locale;
|
||||
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
|
||||
private static final String TAG = "SDL";
|
||||
private static final int SDL_MAJOR_VERSION = 2;
|
||||
private static final int SDL_MINOR_VERSION = 26;
|
||||
private static final int SDL_MICRO_VERSION = 1;
|
||||
private static final int SDL_MINOR_VERSION = 28;
|
||||
private static final int SDL_MICRO_VERSION = 5;
|
||||
/*
|
||||
// Display InputType.SOURCE/CLASS of events and devices
|
||||
//
|
||||
@@ -93,7 +93,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
|
||||
s2 = s_copy & InputDevice.SOURCE_ANY; // keep source only, no class;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
tst = InputDevice.SOURCE_BLUETOOTH_STYLUS;
|
||||
if ((s & tst) == tst) src += " BLUETOOTH_STYLUS";
|
||||
s2 &= ~tst;
|
||||
@@ -107,7 +107,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
if ((s & tst) == tst) src += " GAMEPAD";
|
||||
s2 &= ~tst;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
tst = InputDevice.SOURCE_HDMI;
|
||||
if ((s & tst) == tst) src += " HDMI";
|
||||
s2 &= ~tst;
|
||||
@@ -146,7 +146,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
if ((s & tst) == tst) src += " TOUCHSCREEN";
|
||||
s2 &= ~tst;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
if (Build.VERSION.SDK_INT >= 18) {
|
||||
tst = InputDevice.SOURCE_TOUCH_NAVIGATION;
|
||||
if ((s & tst) == tst) src += " TOUCH_NAVIGATION";
|
||||
s2 &= ~tst;
|
||||
@@ -170,7 +170,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
*/
|
||||
|
||||
public static boolean mIsResumedCalled, mHasFocus;
|
||||
public static final boolean mHasMultiWindow = (Build.VERSION.SDK_INT >= 24);
|
||||
public static final boolean mHasMultiWindow = (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */);
|
||||
|
||||
// Cursor types
|
||||
// private static final int SDL_SYSTEM_CURSOR_NONE = -1;
|
||||
@@ -224,9 +224,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
|
||||
protected static SDLGenericMotionListener_API12 getMotionListener() {
|
||||
if (mMotionListener == null) {
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {
|
||||
mMotionListener = new SDLGenericMotionListener_API26();
|
||||
} else if (Build.VERSION.SDK_INT >= 24) {
|
||||
} else if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
mMotionListener = new SDLGenericMotionListener_API24();
|
||||
} else {
|
||||
mMotionListener = new SDLGenericMotionListener_API12();
|
||||
@@ -393,7 +393,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
mHIDDeviceManager = HIDDeviceManager.acquire(this);
|
||||
|
||||
// Set up the surface
|
||||
mSurface = createSDLSurface(getApplication());
|
||||
mSurface = createSDLSurface(this);
|
||||
|
||||
mLayout = new RelativeLayout(this);
|
||||
mLayout.addView(mSurface);
|
||||
@@ -404,7 +404,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
SDLActivity.onNativeOrientationChanged(mCurrentOrientation);
|
||||
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT < 24) {
|
||||
if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) {
|
||||
mCurrentLocale = getContext().getResources().getConfiguration().locale;
|
||||
} else {
|
||||
mCurrentLocale = getContext().getResources().getConfiguration().getLocales().get(0);
|
||||
@@ -588,6 +588,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
mHIDDeviceManager = null;
|
||||
}
|
||||
|
||||
SDLAudioManager.release(this);
|
||||
|
||||
if (SDLActivity.mBrokenLibraries) {
|
||||
super.onDestroy();
|
||||
return;
|
||||
@@ -766,7 +768,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
}
|
||||
break;
|
||||
case COMMAND_CHANGE_WINDOW_STYLE:
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
|
||||
if (context instanceof Activity) {
|
||||
Window window = ((Activity) context).getWindow();
|
||||
if (window != null) {
|
||||
@@ -841,7 +843,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
msg.obj = data;
|
||||
boolean result = commandHandler.sendMessage(msg);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
|
||||
if (command == COMMAND_CHANGE_WINDOW_STYLE) {
|
||||
// Ensure we don't return until the resize has actually happened,
|
||||
// or 500ms have passed.
|
||||
@@ -969,15 +971,18 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
/* If set, hint "explicitly controls which UI orientations are allowed". */
|
||||
if (hint.contains("LandscapeRight") && hint.contains("LandscapeLeft")) {
|
||||
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
|
||||
} else if (hint.contains("LandscapeRight")) {
|
||||
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
|
||||
} else if (hint.contains("LandscapeLeft")) {
|
||||
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
|
||||
} else if (hint.contains("LandscapeRight")) {
|
||||
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
|
||||
}
|
||||
|
||||
if (hint.contains("Portrait") && hint.contains("PortraitUpsideDown")) {
|
||||
/* exact match to 'Portrait' to distinguish with PortraitUpsideDown */
|
||||
boolean contains_Portrait = hint.contains("Portrait ") || hint.endsWith("Portrait");
|
||||
|
||||
if (contains_Portrait && hint.contains("PortraitUpsideDown")) {
|
||||
orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
|
||||
} else if (hint.contains("Portrait")) {
|
||||
} else if (contains_Portrait) {
|
||||
orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
|
||||
} else if (hint.contains("PortraitUpsideDown")) {
|
||||
orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
|
||||
@@ -1090,7 +1095,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
// thus SDK version 27. If we are in DeX mode and not API 27 or higher, as a result,
|
||||
// we should stick to relative mode.
|
||||
//
|
||||
if ((Build.VERSION.SDK_INT < 27) && isDeXMode()) {
|
||||
if (Build.VERSION.SDK_INT < 27 /* Android 8.1 (O_MR1) */ && isDeXMode()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1180,7 +1185,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static boolean isDeXMode() {
|
||||
if (Build.VERSION.SDK_INT < 24) {
|
||||
if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
@@ -1340,23 +1345,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
}
|
||||
}
|
||||
|
||||
if ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
if (isTextInputEvent(event)) {
|
||||
if (ic != null) {
|
||||
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
|
||||
} else {
|
||||
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
|
||||
}
|
||||
}
|
||||
onNativeKeyDown(keyCode);
|
||||
return true;
|
||||
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
onNativeKeyUp(keyCode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
|
||||
// on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
|
||||
// they are ignored here because sending them as mouse input to SDL is messy
|
||||
@@ -1371,6 +1359,21 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
if (isTextInputEvent(event)) {
|
||||
if (ic != null) {
|
||||
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
|
||||
} else {
|
||||
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
|
||||
}
|
||||
}
|
||||
onNativeKeyDown(keyCode);
|
||||
return true;
|
||||
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
onNativeKeyUp(keyCode);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1617,7 +1620,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
private final Runnable rehideSystemUi = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
|
||||
int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
|
||||
@@ -1670,7 +1673,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
Bitmap bitmap = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888);
|
||||
++mLastCursorID;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
try {
|
||||
mCursors.put(mLastCursorID, PointerIcon.create(bitmap, hotSpotX, hotSpotY));
|
||||
} catch (Exception e) {
|
||||
@@ -1686,7 +1689,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void destroyCustomCursor(int cursorID) {
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
try {
|
||||
mCursors.remove(cursorID);
|
||||
} catch (Exception e) {
|
||||
@@ -1700,7 +1703,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
*/
|
||||
public static boolean setCustomCursor(int cursorID) {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
try {
|
||||
mSurface.setPointerIcon(mCursors.get(cursorID));
|
||||
} catch (Exception e) {
|
||||
@@ -1755,7 +1758,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
cursor_type = 1002; //PointerIcon.TYPE_HAND;
|
||||
break;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
try {
|
||||
mSurface.setPointerIcon(PointerIcon.getSystemIcon(SDL.getContext(), cursor_type));
|
||||
} catch (Exception e) {
|
||||
@@ -1769,7 +1772,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void requestPermission(String permission, int requestCode) {
|
||||
if (Build.VERSION.SDK_INT < 23) {
|
||||
if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
|
||||
nativePermissionResult(requestCode, true);
|
||||
return;
|
||||
}
|
||||
@@ -1798,7 +1801,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
i.setData(Uri.parse(url));
|
||||
|
||||
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
|
||||
flags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
|
||||
} else {
|
||||
flags |= Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET;
|
||||
@@ -2002,6 +2005,18 @@ class SDLInputConnection extends BaseInputConnection {
|
||||
|
||||
@Override
|
||||
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
||||
if (Build.VERSION.SDK_INT <= 29 /* Android 10.0 (Q) */) {
|
||||
// Workaround to capture backspace key. Ref: http://stackoverflow.com/questions>/14560344/android-backspace-in-webview-baseinputconnection
|
||||
// and https://bugzilla.libsdl.org/show_bug.cgi?id=2265
|
||||
if (beforeLength > 0 && afterLength == 0) {
|
||||
// backspace(s)
|
||||
while (beforeLength-- > 0) {
|
||||
nativeGenerateScancodeForUnichar('\b');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!super.deleteSurroundingText(beforeLength, afterLength)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.libsdl.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioDeviceCallback;
|
||||
import android.media.AudioDeviceInfo;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioRecord;
|
||||
@@ -8,34 +11,67 @@ import android.media.MediaRecorder;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
public class SDLAudioManager
|
||||
{
|
||||
import java.util.Arrays;
|
||||
|
||||
public class SDLAudioManager {
|
||||
protected static final String TAG = "SDLAudio";
|
||||
|
||||
protected static AudioTrack mAudioTrack;
|
||||
protected static AudioRecord mAudioRecord;
|
||||
protected static Context mContext;
|
||||
|
||||
private static final int[] NO_DEVICES = {};
|
||||
|
||||
private static AudioDeviceCallback mAudioDeviceCallback;
|
||||
|
||||
public static void initialize() {
|
||||
mAudioTrack = null;
|
||||
mAudioRecord = null;
|
||||
mAudioDeviceCallback = null;
|
||||
|
||||
if(Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */)
|
||||
{
|
||||
mAudioDeviceCallback = new AudioDeviceCallback() {
|
||||
@Override
|
||||
public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
|
||||
Arrays.stream(addedDevices).forEach(deviceInfo -> addAudioDevice(deviceInfo.isSink(), deviceInfo.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
|
||||
Arrays.stream(removedDevices).forEach(deviceInfo -> removeAudioDevice(deviceInfo.isSink(), deviceInfo.getId()));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static void setContext(Context context) {
|
||||
mContext = context;
|
||||
if (context != null) {
|
||||
registerAudioDeviceCallback();
|
||||
}
|
||||
}
|
||||
|
||||
public static void release(Context context) {
|
||||
unregisterAudioDeviceCallback(context);
|
||||
}
|
||||
|
||||
// Audio
|
||||
|
||||
protected static String getAudioFormatString(int audioFormat) {
|
||||
switch (audioFormat) {
|
||||
case AudioFormat.ENCODING_PCM_8BIT:
|
||||
return "8-bit";
|
||||
case AudioFormat.ENCODING_PCM_16BIT:
|
||||
return "16-bit";
|
||||
case AudioFormat.ENCODING_PCM_FLOAT:
|
||||
return "float";
|
||||
default:
|
||||
return Integer.toString(audioFormat);
|
||||
case AudioFormat.ENCODING_PCM_8BIT:
|
||||
return "8-bit";
|
||||
case AudioFormat.ENCODING_PCM_16BIT:
|
||||
return "16-bit";
|
||||
case AudioFormat.ENCODING_PCM_FLOAT:
|
||||
return "float";
|
||||
default:
|
||||
return Integer.toString(audioFormat);
|
||||
}
|
||||
}
|
||||
|
||||
protected static int[] open(boolean isCapture, int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
|
||||
protected static int[] open(boolean isCapture, int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {
|
||||
int channelConfig;
|
||||
int sampleSize;
|
||||
int frameSize;
|
||||
@@ -43,14 +79,14 @@ public class SDLAudioManager
|
||||
Log.v(TAG, "Opening " + (isCapture ? "capture" : "playback") + ", requested " + desiredFrames + " frames of " + desiredChannels + " channel " + getAudioFormatString(audioFormat) + " audio at " + sampleRate + " Hz");
|
||||
|
||||
/* On older devices let's use known good settings */
|
||||
if (Build.VERSION.SDK_INT < 21) {
|
||||
if (Build.VERSION.SDK_INT < 21 /* Android 5.0 (LOLLIPOP) */) {
|
||||
if (desiredChannels > 2) {
|
||||
desiredChannels = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* AudioTrack has sample rate limitation of 48000 (fixed in 5.0.2) */
|
||||
if (Build.VERSION.SDK_INT < 22) {
|
||||
if (Build.VERSION.SDK_INT < 22 /* Android 5.1 (LOLLIPOP_MR1) */) {
|
||||
if (sampleRate < 8000) {
|
||||
sampleRate = 8000;
|
||||
} else if (sampleRate > 48000) {
|
||||
@@ -59,7 +95,7 @@ public class SDLAudioManager
|
||||
}
|
||||
|
||||
if (audioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
|
||||
int minSDKVersion = (isCapture ? 23 : 21);
|
||||
int minSDKVersion = (isCapture ? 23 /* Android 6.0 (M) */ : 21 /* Android 5.0 (LOLLIPOP) */);
|
||||
if (Build.VERSION.SDK_INT < minSDKVersion) {
|
||||
audioFormat = AudioFormat.ENCODING_PCM_16BIT;
|
||||
}
|
||||
@@ -120,7 +156,7 @@ public class SDLAudioManager
|
||||
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER;
|
||||
break;
|
||||
case 8:
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
if (Build.VERSION.SDK_INT >= 23 /* Android 6.0 (M) */) {
|
||||
channelConfig = AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
|
||||
} else {
|
||||
Log.v(TAG, "Requested " + desiredChannels + " channels, getting 5.1 surround");
|
||||
@@ -201,6 +237,10 @@ public class SDLAudioManager
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */ && deviceId != 0) {
|
||||
mAudioRecord.setPreferredDevice(getOutputAudioDeviceInfo(deviceId));
|
||||
}
|
||||
|
||||
mAudioRecord.startRecording();
|
||||
}
|
||||
|
||||
@@ -224,6 +264,10 @@ public class SDLAudioManager
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */ && deviceId != 0) {
|
||||
mAudioTrack.setPreferredDevice(getInputAudioDeviceInfo(deviceId));
|
||||
}
|
||||
|
||||
mAudioTrack.play();
|
||||
}
|
||||
|
||||
@@ -238,11 +282,73 @@ public class SDLAudioManager
|
||||
return results;
|
||||
}
|
||||
|
||||
private static AudioDeviceInfo getInputAudioDeviceInfo(int deviceId) {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS))
|
||||
.filter(deviceInfo -> deviceInfo.getId() == deviceId)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static AudioDeviceInfo getOutputAudioDeviceInfo(int deviceId) {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS))
|
||||
.filter(deviceInfo -> deviceInfo.getId() == deviceId)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerAudioDeviceCallback() {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
audioManager.registerAudioDeviceCallback(mAudioDeviceCallback, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static void unregisterAudioDeviceCallback(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
audioManager.unregisterAudioDeviceCallback(mAudioDeviceCallback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static int[] audioOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
|
||||
return open(false, sampleRate, audioFormat, desiredChannels, desiredFrames);
|
||||
public static int[] getAudioOutputDevices() {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)).mapToInt(AudioDeviceInfo::getId).toArray();
|
||||
} else {
|
||||
return NO_DEVICES;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static int[] getAudioInputDevices() {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).mapToInt(AudioDeviceInfo::getId).toArray();
|
||||
} else {
|
||||
return NO_DEVICES;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static int[] audioOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {
|
||||
return open(false, sampleRate, audioFormat, desiredChannels, desiredFrames, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,6 +360,11 @@ public class SDLAudioManager
|
||||
return;
|
||||
}
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT < 21 /* Android 5.0 (LOLLIPOP) */) {
|
||||
Log.e(TAG, "Attempted to make an incompatible audio call with uninitialized audio! (floating-point output is supported since Android 5.0 Lollipop)");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < buffer.length;) {
|
||||
int result = mAudioTrack.write(buffer, i, buffer.length - i, AudioTrack.WRITE_BLOCKING);
|
||||
if (result > 0) {
|
||||
@@ -326,18 +437,22 @@ public class SDLAudioManager
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static int[] captureOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
|
||||
return open(true, sampleRate, audioFormat, desiredChannels, desiredFrames);
|
||||
public static int[] captureOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {
|
||||
return open(true, sampleRate, audioFormat, desiredChannels, desiredFrames, deviceId);
|
||||
}
|
||||
|
||||
/** This method is called by SDL using JNI. */
|
||||
public static int captureReadFloatBuffer(float[] buffer, boolean blocking) {
|
||||
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
|
||||
if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
|
||||
return 0;
|
||||
} else {
|
||||
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
|
||||
}
|
||||
}
|
||||
|
||||
/** This method is called by SDL using JNI. */
|
||||
public static int captureReadShortBuffer(short[] buffer, boolean blocking) {
|
||||
if (Build.VERSION.SDK_INT < 23) {
|
||||
if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
|
||||
return mAudioRecord.read(buffer, 0, buffer.length);
|
||||
} else {
|
||||
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
|
||||
@@ -346,7 +461,7 @@ public class SDLAudioManager
|
||||
|
||||
/** This method is called by SDL using JNI. */
|
||||
public static int captureReadByteBuffer(byte[] buffer, boolean blocking) {
|
||||
if (Build.VERSION.SDK_INT < 23) {
|
||||
if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
|
||||
return mAudioRecord.read(buffer, 0, buffer.length);
|
||||
} else {
|
||||
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
|
||||
@@ -391,4 +506,9 @@ public class SDLAudioManager
|
||||
}
|
||||
|
||||
public static native int nativeSetupJNI();
|
||||
|
||||
public static native void removeAudioDevice(boolean isCapture, int deviceId);
|
||||
|
||||
public static native void addAudioDevice(boolean isCapture, int deviceId);
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public class SDLControllerManager
|
||||
public static native int nativeAddJoystick(int device_id, String name, String desc,
|
||||
int vendor_id, int product_id,
|
||||
boolean is_accelerometer, int button_mask,
|
||||
int naxes, int nhats, int nballs);
|
||||
int naxes, int axis_mask, int nhats, int nballs);
|
||||
public static native int nativeRemoveJoystick(int device_id);
|
||||
public static native int nativeAddHaptic(int device_id, String name);
|
||||
public static native int nativeRemoveHaptic(int device_id);
|
||||
@@ -42,7 +42,7 @@ public class SDLControllerManager
|
||||
|
||||
public static void initialize() {
|
||||
if (mJoystickHandler == null) {
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
|
||||
mJoystickHandler = new SDLJoystickHandler_API19();
|
||||
} else {
|
||||
mJoystickHandler = new SDLJoystickHandler_API16();
|
||||
@@ -50,7 +50,7 @@ public class SDLControllerManager
|
||||
}
|
||||
|
||||
if (mHapticHandler == null) {
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {
|
||||
mHapticHandler = new SDLHapticHandler_API26();
|
||||
} else {
|
||||
mHapticHandler = new SDLHapticHandler();
|
||||
@@ -168,6 +168,32 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
arg1Axis = MotionEvent.AXIS_GAS;
|
||||
}
|
||||
|
||||
// Make sure the AXIS_Z is sorted between AXIS_RY and AXIS_RZ.
|
||||
// This is because the usual pairing are:
|
||||
// - AXIS_X + AXIS_Y (left stick).
|
||||
// - AXIS_RX, AXIS_RY (sometimes the right stick, sometimes triggers).
|
||||
// - AXIS_Z, AXIS_RZ (sometimes the right stick, sometimes triggers).
|
||||
// This sorts the axes in the above order, which tends to be correct
|
||||
// for Xbox-ish game pads that have the right stick on RX/RY and the
|
||||
// triggers on Z/RZ.
|
||||
//
|
||||
// Gamepads that don't have AXIS_Z/AXIS_RZ but use
|
||||
// AXIS_LTRIGGER/AXIS_RTRIGGER are unaffected by this.
|
||||
//
|
||||
// References:
|
||||
// - https://developer.android.com/develop/ui/views/touch-and-input/game-controllers/controller-input
|
||||
// - https://www.kernel.org/doc/html/latest/input/gamepad.html
|
||||
if (arg0Axis == MotionEvent.AXIS_Z) {
|
||||
arg0Axis = MotionEvent.AXIS_RZ - 1;
|
||||
} else if (arg0Axis > MotionEvent.AXIS_Z && arg0Axis < MotionEvent.AXIS_RZ) {
|
||||
--arg0Axis;
|
||||
}
|
||||
if (arg1Axis == MotionEvent.AXIS_Z) {
|
||||
arg1Axis = MotionEvent.AXIS_RZ - 1;
|
||||
} else if (arg1Axis > MotionEvent.AXIS_Z && arg1Axis < MotionEvent.AXIS_RZ) {
|
||||
--arg1Axis;
|
||||
}
|
||||
|
||||
return arg0Axis - arg1Axis;
|
||||
}
|
||||
}
|
||||
@@ -210,7 +236,7 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
mJoysticks.add(joystick);
|
||||
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
|
||||
getVendorId(joystickDevice), getProductId(joystickDevice), false,
|
||||
getButtonMask(joystickDevice), joystick.axes.size(), joystick.hats.size()/2, 0);
|
||||
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -291,6 +317,9 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
public int getVendorId(InputDevice joystickDevice) {
|
||||
return 0;
|
||||
}
|
||||
public int getAxisMask(List<InputDevice.MotionRange> ranges) {
|
||||
return -1;
|
||||
}
|
||||
public int getButtonMask(InputDevice joystickDevice) {
|
||||
return -1;
|
||||
}
|
||||
@@ -308,6 +337,43 @@ class SDLJoystickHandler_API19 extends SDLJoystickHandler_API16 {
|
||||
return joystickDevice.getVendorId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAxisMask(List<InputDevice.MotionRange> ranges) {
|
||||
// For compatibility, keep computing the axis mask like before,
|
||||
// only really distinguishing 2, 4 and 6 axes.
|
||||
int axis_mask = 0;
|
||||
if (ranges.size() >= 2) {
|
||||
// ((1 << SDL_GAMEPAD_AXIS_LEFTX) | (1 << SDL_GAMEPAD_AXIS_LEFTY))
|
||||
axis_mask |= 0x0003;
|
||||
}
|
||||
if (ranges.size() >= 4) {
|
||||
// ((1 << SDL_GAMEPAD_AXIS_RIGHTX) | (1 << SDL_GAMEPAD_AXIS_RIGHTY))
|
||||
axis_mask |= 0x000c;
|
||||
}
|
||||
if (ranges.size() >= 6) {
|
||||
// ((1 << SDL_GAMEPAD_AXIS_LEFT_TRIGGER) | (1 << SDL_GAMEPAD_AXIS_RIGHT_TRIGGER))
|
||||
axis_mask |= 0x0030;
|
||||
}
|
||||
// Also add an indicator bit for whether the sorting order has changed.
|
||||
// This serves to disable outdated gamecontrollerdb.txt mappings.
|
||||
boolean have_z = false;
|
||||
boolean have_past_z_before_rz = false;
|
||||
for (InputDevice.MotionRange range : ranges) {
|
||||
int axis = range.getAxis();
|
||||
if (axis == MotionEvent.AXIS_Z) {
|
||||
have_z = true;
|
||||
} else if (axis > MotionEvent.AXIS_Z && axis < MotionEvent.AXIS_RZ) {
|
||||
have_past_z_before_rz = true;
|
||||
}
|
||||
}
|
||||
if (have_z && have_past_z_before_rz) {
|
||||
// If both these exist, the compare() function changed sorting order.
|
||||
// Set a bit to indicate this fact.
|
||||
axis_mask |= 0x8000;
|
||||
}
|
||||
return axis_mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getButtonMask(InputDevice joystickDevice) {
|
||||
int button_mask = 0;
|
||||
@@ -743,7 +809,7 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
|
||||
|
||||
@Override
|
||||
public boolean supportsRelativeMouse() {
|
||||
return (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27));
|
||||
return (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -753,7 +819,7 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
|
||||
|
||||
@Override
|
||||
public boolean setRelativeMouseEnabled(boolean enabled) {
|
||||
if (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27)) {
|
||||
if (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */) {
|
||||
if (enabled) {
|
||||
SDLActivity.getContentView().requestPointerCapture();
|
||||
} else {
|
||||
|
||||
@@ -116,7 +116,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
int nDeviceHeight = height;
|
||||
try
|
||||
{
|
||||
if (Build.VERSION.SDK_INT >= 17) {
|
||||
if (Build.VERSION.SDK_INT >= 17 /* Android 4.2 (JELLY_BEAN_MR1) */) {
|
||||
DisplayMetrics realMetrics = new DisplayMetrics();
|
||||
mDisplay.getRealMetrics( realMetrics );
|
||||
nDeviceWidth = realMetrics.widthPixels;
|
||||
@@ -163,7 +163,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
|
||||
// Don't skip in MultiWindow.
|
||||
if (skip) {
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
if (SDLActivity.mSingleton.isInMultiWindowMode()) {
|
||||
Log.v("SDL", "Don't skip in Multi-Window");
|
||||
skip = false;
|
||||
|
||||
@@ -7,7 +7,7 @@ buildscript {
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.3.1'
|
||||
classpath 'com.android.tools.build:gradle:8.1.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#Thu Nov 11 18:20:34 PST 2021
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
Vendored
+2
-2
@@ -126,8 +126,8 @@ if $cygwin ; then
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
CHECK=`echo "$arg"|grep -E -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|grep -E -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#cmakedefine PACKAGE "@PACKAGE@"
|
||||
#define VERSION "2.9.1"
|
||||
#define VERSION "2.10.0"
|
||||
|
||||
#cmakedefine CMAKE_SYSTEM_NAME "@CMAKE_SYSTEM_NAME@"
|
||||
|
||||
|
||||
@@ -197,8 +197,10 @@ static void setup_selwindow() {
|
||||
|
||||
// デフォルトで選択される選択肢がある場合、そこへカーソルを移動
|
||||
if (sact.sel.movecursor) {
|
||||
ags_setCursorLocation(sp->cur.x + sact.sel.frame_dot + 2,
|
||||
sp->cur.y + sact.sel.frame_dot + 2 + (sact.sel.font_size + sact.sel.linespace)*(sact.sel.movecursor -1), TRUE);
|
||||
int x = sp->cur.x + sact.sel.frame_dot + 2;
|
||||
int y = sp->cur.y + sact.sel.frame_dot + 2 +
|
||||
(sact.sel.font_size + sact.sel.linespace) * (sact.sel.movecursor - 1);
|
||||
ags_setCursorLocation(x, y, true, true);
|
||||
selected_item = (sact.sel.movecursor -1);
|
||||
oldstate = TRUE;
|
||||
oldindex = selected_item -1;
|
||||
|
||||
@@ -1306,7 +1306,7 @@ static void ChangeSecretArray(void) { /* 53 */
|
||||
(*vAry) ^= ax; ax = (key[i&3] ^ *vAry);
|
||||
j ^= ax;
|
||||
if (i & 2) {
|
||||
ax = !ax ^ (i*3);
|
||||
ax = ~ax ^ (i*3);
|
||||
}
|
||||
if (i & 4) {
|
||||
ax = (ax >> 4) | (ax << 12);
|
||||
@@ -1328,13 +1328,12 @@ static void ChangeSecretArray(void) { /* 53 */
|
||||
*vAry ^= ax; ax = (key[i&3] ^ k);
|
||||
j ^= ax;
|
||||
if (i & 2) {
|
||||
ax = !ax ^ (i*3);
|
||||
ax = ~ax ^ (i*3);
|
||||
}
|
||||
if (i & 4) {
|
||||
ax = (ax >> 4) | (ax << 12);
|
||||
}
|
||||
vAry++;
|
||||
|
||||
}
|
||||
*vResult = j;
|
||||
}
|
||||
|
||||
@@ -42,12 +42,18 @@
|
||||
#include "font.h"
|
||||
#include "cursor.h"
|
||||
#include "image.h"
|
||||
#include "debugger.h"
|
||||
|
||||
static Palette256 pal_256;
|
||||
static boolean need_update = TRUE;
|
||||
static boolean fade_outed = FALSE;
|
||||
static int cursor_move_time = 50; /* カーソル移動にかかる時間(ms) */
|
||||
|
||||
static void palette_changed(void) {
|
||||
nact->ags.pal_changed = TRUE;
|
||||
dbg_on_palette_change();
|
||||
}
|
||||
|
||||
static void initPal(Palette256 *pal) {
|
||||
int i;
|
||||
for (i = 0; i < 256; i++) {
|
||||
@@ -58,7 +64,7 @@ static void initPal(Palette256 *pal) {
|
||||
pal->red[15] = 255; pal->green[15] = 255; pal->blue[15] = 255;
|
||||
pal->red[255] = 255; pal->green[255] = 255; pal->blue[255] = 255;
|
||||
sdl_setPalette(pal, 0, 256);
|
||||
nact->ags.pal_changed = TRUE;
|
||||
palette_changed();
|
||||
}
|
||||
|
||||
boolean ags_check_param(int *x, int *y, int *w, int *h) {
|
||||
@@ -100,7 +106,7 @@ boolean ags_check_param_xy(int *x, int *y) {
|
||||
}
|
||||
|
||||
void ags_init(const char *render_driver) {
|
||||
nact->ags.mouse_movesw = MOUSE_WARP_SMOOTH;
|
||||
nact->ags.mouse_warp_enabled = true;
|
||||
nact->ags.pal = &pal_256;
|
||||
nact->ags.world_size.width = SYS35_DEFAULT_WIDTH;
|
||||
nact->ags.world_size.height = SYS35_DEFAULT_HEIGHT;
|
||||
@@ -123,7 +129,7 @@ void ags_remove(void) {
|
||||
}
|
||||
|
||||
void ags_reset(void) {
|
||||
nact->ags.mouse_movesw = MOUSE_WARP_SMOOTH;
|
||||
nact->ags.mouse_warp_enabled = true;
|
||||
nact->ags.eventcb = NULL;
|
||||
initPal(&pal_256);
|
||||
cg_reset();
|
||||
@@ -151,7 +157,7 @@ void ags_setWorldSize(int width, int height, int depth) {
|
||||
|
||||
fade_outed = FALSE; /* thanx tajiri@wizard */
|
||||
|
||||
nact->ags.pal_changed = TRUE;
|
||||
palette_changed();
|
||||
}
|
||||
|
||||
void ags_setViewArea(int x, int y, int width, int height) {
|
||||
@@ -223,14 +229,14 @@ void ags_setPalettes(Palette256 *src_pal, int src, int dst, int cnt) {
|
||||
nact->ags.pal->green[dst + i] = src_pal->green[src + i];
|
||||
nact->ags.pal->blue [dst + i] = src_pal->blue [src + i];
|
||||
}
|
||||
nact->ags.pal_changed = TRUE;
|
||||
palette_changed();
|
||||
}
|
||||
|
||||
void ags_setPalette(int no, int red, int green, int blue) {
|
||||
nact->ags.pal->red[no] = red;
|
||||
nact->ags.pal->green[no] = green;
|
||||
nact->ags.pal->blue[no] = blue;
|
||||
nact->ags.pal_changed = TRUE;
|
||||
palette_changed();
|
||||
}
|
||||
|
||||
void ags_setPaletteToSystem(int src, int cnt) {
|
||||
@@ -627,42 +633,42 @@ void ags_loadCursor(int p1,int p2) {
|
||||
}
|
||||
}
|
||||
|
||||
void ags_setCursorLocation(int x, int y, boolean is_dibgeo) {
|
||||
int dx[8], dy[8];
|
||||
int i, delx, dely;
|
||||
MyPoint p;
|
||||
void ags_setCursorLocation(int x, int y, bool is_dibgeo, bool for_selection) {
|
||||
if (!ags_check_param_xy(&x, &y)) return;
|
||||
|
||||
/* DIB 座表系か Window 座表系か */
|
||||
if (is_dibgeo) {
|
||||
// DIB coordinates -> Window coordinates
|
||||
x -= nact->ags.view_area.x;
|
||||
y -= nact->ags.view_area.y;
|
||||
}
|
||||
|
||||
switch(nact->ags.mouse_movesw) {
|
||||
case MOUSE_WARP_DISABLED:
|
||||
return;
|
||||
case MOUSE_WARP_DIRECT:
|
||||
sdl_setCursorLocation(x, y); break;
|
||||
case MOUSE_WARP_SMOOTH:
|
||||
sys_getMouseInfo(&p, is_dibgeo);
|
||||
delx = x - p.x;
|
||||
dely = y - p.y;
|
||||
|
||||
for (i = 1; i < 8; i++) {
|
||||
dx[i-1] = ((delx*i*i*i) >> 9) - ((3*delx*i*i)>> 6) + ((3*delx*i) >> 3) + p.x;
|
||||
dy[i-1] = ((dely*i*i*i) >> 9) - ((3*dely*i*i)>> 6) + ((3*dely*i) >> 3) + p.y;
|
||||
}
|
||||
dx[7] = x; dy[7] = y;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
sdl_setCursorLocation(dx[i], dy[i]);
|
||||
usleep(cursor_move_time * 1000 / 8);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
if (!for_selection) {
|
||||
// We can't move the actual cursor in the browser, but can change the
|
||||
// internal mouse coordinates. This can help with keyboard/gamepad
|
||||
// navigation.
|
||||
sdl_setCursorInternalLocation(x, y);
|
||||
EM_ASM({ xsystem35.shell.showMouseMoveEffect($0, $1); }, x, y);
|
||||
sdl_sleep(cursor_move_time);
|
||||
}
|
||||
#else
|
||||
if (nact->ags.mouse_warp_enabled) {
|
||||
MyPoint p;
|
||||
sys_getMouseInfo(&p, is_dibgeo);
|
||||
int dx = x - p.x;
|
||||
int dy = y - p.y;
|
||||
for (int i = 1; i < 8; i++) {
|
||||
int xi = ((dx*i*i*i) >> 9) - ((3*dx*i*i)>> 6) + ((3*dx*i) >> 3) + p.x;
|
||||
int yi = ((dy*i*i*i) >> 9) - ((3*dy*i*i)>> 6) + ((3*dy*i) >> 3) + p.y;
|
||||
sdl_setCursorLocation(xi, yi);
|
||||
sdl_sleep(cursor_move_time / 7);
|
||||
}
|
||||
sdl_setCursorLocation(x, y);
|
||||
} else if (!for_selection) {
|
||||
sdl_setCursorInternalLocation(x, y);
|
||||
sdl_sleep(cursor_move_time);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
|
||||
@@ -100,12 +100,6 @@ enum agsevent_button {
|
||||
AGSEVENT_BUTTON_RIGHT,
|
||||
};
|
||||
|
||||
enum mouse_warp_mode {
|
||||
MOUSE_WARP_DISABLED,
|
||||
MOUSE_WARP_DIRECT,
|
||||
MOUSE_WARP_SMOOTH,
|
||||
};
|
||||
|
||||
struct _ags {
|
||||
Palette256 *pal; /* system palette */
|
||||
boolean pal_changed; /* system palette has changed */
|
||||
@@ -116,11 +110,10 @@ struct _ags {
|
||||
|
||||
int world_depth; /* depth of off-screen (bits per pixel) */
|
||||
|
||||
enum mouse_warp_mode mouse_movesw;
|
||||
|
||||
agsurface_t *dib; /* main surface */
|
||||
void (*eventcb)(agsevent_t *e); /* deliver event */
|
||||
|
||||
bool mouse_warp_enabled;
|
||||
boolean noantialias; /* antialias を使用しない */
|
||||
boolean noimagecursor; /* リソースファイルのカーソルを読みこまない */
|
||||
};
|
||||
@@ -211,7 +204,7 @@ extern agsurface_t *ags_drawStringToSurface(const char *str);
|
||||
/* カーソル関係 */
|
||||
extern void ags_setCursorType(int type);
|
||||
extern void ags_loadCursor(int ,int);
|
||||
extern void ags_setCursorLocation(int x, int y, boolean dibgeo);
|
||||
extern void ags_setCursorLocation(int x, int y, bool is_dibgeo, bool for_selection);
|
||||
extern void ags_setCursorMoveTime(int msec);
|
||||
extern int ags_getCursorMoveTime();
|
||||
|
||||
|
||||
+1
-1
@@ -108,5 +108,5 @@ void ald_init(int type, const char **file, int cnt, boolean use_mmap) {
|
||||
int ald_get_maxno(DRIFILETYPE type) {
|
||||
if (type >= DRIFILETYPEMAX || !dri[type])
|
||||
return 0;
|
||||
return dri[type]->nr_files;
|
||||
return dri[type]->maxno;
|
||||
}
|
||||
|
||||
@@ -22,11 +22,14 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "cdrom.h"
|
||||
#include "ald_manager.h"
|
||||
#include "music.h"
|
||||
#include "music_private.h"
|
||||
|
||||
static int current_track;
|
||||
|
||||
static int cdrom_bgm_init(char *dev) {
|
||||
prv.cd_maxtrk = ald_get_maxno(DRIFILE_BGM) + 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -72,7 +72,9 @@ static int cdrom_init(char *playlist_path) {
|
||||
fp = fopen("_inmm.ini", "r");
|
||||
}
|
||||
if (!fp) {
|
||||
NOTICE("cdrom: Cannot open playlist %s", playlist_path);
|
||||
// If the game has MIDI music, lack of the playlist is not a problem.
|
||||
if (ald_get_maxno(DRIFILE_MIDI) == 0)
|
||||
NOTICE("cdrom: Cannot open playlist %s", playlist_path);
|
||||
return NG;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ void commandIZ() {
|
||||
int x = getCaliValue();
|
||||
int y = getCaliValue();
|
||||
|
||||
ags_setCursorLocation(x, y, TRUE);
|
||||
ags_setCursorLocation(x, y, true, false);
|
||||
DEBUG_COMMAND("IZ %d,%d:", x, y);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -326,7 +326,7 @@ void commandMJ() {
|
||||
mj_param.h = h;
|
||||
mj_param.oldstring = t1;
|
||||
|
||||
ags_setCursorLocation(x, y, FALSE); /* XXX */
|
||||
ags_setCursorLocation(x, y, false, false);
|
||||
menu_inputstring2(&mj_param);
|
||||
if (mj_param.newstring == NULL) return;
|
||||
|
||||
|
||||
@@ -530,6 +530,11 @@ void dbg_onsleep(void) {
|
||||
dbg_impl->onsleep();
|
||||
}
|
||||
|
||||
void dbg_on_palette_change(void) {
|
||||
if (dbg_impl)
|
||||
dbg_impl->on_palette_change();
|
||||
}
|
||||
|
||||
boolean dbg_console_vprintf(int lv, const char *format, va_list ap) {
|
||||
if (!dbg_impl || !dbg_impl->console_output)
|
||||
return false;
|
||||
|
||||
@@ -45,6 +45,7 @@ void dbg_init(const char *symbols_path, boolean use_dap);
|
||||
void dbg_quit(void);
|
||||
void dbg_main(int bp_no);
|
||||
void dbg_onsleep(void);
|
||||
void dbg_on_palette_change(void);
|
||||
uint8_t dbg_handle_breakpoint(int page, int addr);
|
||||
boolean dbg_console_vprintf(int lv, const char *format, va_list ap);
|
||||
void dbg_post_command(void *data);
|
||||
@@ -56,6 +57,7 @@ void dbg_post_command(void *data);
|
||||
#define dbg_quit()
|
||||
#define dbg_main(bp_no)
|
||||
#define dbg_onsleep()
|
||||
#define dbg_on_palette_change()
|
||||
#define dbg_handle_breakpoint(page, addr) BREAKPOINT
|
||||
#define dbg_console_vprintf(lv, format, ap) false
|
||||
#define dbg_post_command(data)
|
||||
|
||||
+34
-2
@@ -51,6 +51,7 @@ static char *symbols_path;
|
||||
static char *src_dir;
|
||||
static struct msgq *queue;
|
||||
static bool break_on_warnings;
|
||||
static uint32_t palette_version;
|
||||
|
||||
cJSON *create_source(const char *name) {
|
||||
cJSON *source = cJSON_CreateObject();
|
||||
@@ -67,7 +68,7 @@ cJSON *create_source(const char *name) {
|
||||
static void send_json(cJSON *json) {
|
||||
static int seq = 0;
|
||||
|
||||
cJSON_AddNumberToObject(json, "seq", seq);
|
||||
cJSON_AddNumberToObject(json, "seq", ++seq);
|
||||
char *str = cJSON_PrintUnformatted(json);
|
||||
printf("Content-Length: %zu\r\n\r\n%s", strlen(str), str);
|
||||
fflush(stdout);
|
||||
@@ -480,6 +481,20 @@ static void cmd_disconnect(cJSON *args, cJSON *resp) {
|
||||
sys_exit(0);
|
||||
}
|
||||
|
||||
static void cmd_palette(cJSON *args, cJSON *resp) {
|
||||
cJSON *body, *palette;
|
||||
cJSON_AddBoolToObject(resp, "success", true);
|
||||
cJSON_AddItemToObjectCS(resp, "body", body = cJSON_CreateObject());
|
||||
cJSON_AddNumberToObject(body, "version", palette_version);
|
||||
cJSON_AddItemToObjectCS(body, "palette", palette = cJSON_CreateArray());
|
||||
for (int i = 0; i < 256; i++) {
|
||||
int val = nact->ags.pal->red[i] << 16 |
|
||||
nact->ags.pal->green[i] << 8 |
|
||||
nact->ags.pal->blue[i];
|
||||
cJSON_AddItemToArray(palette, cJSON_CreateNumber(val));
|
||||
}
|
||||
}
|
||||
|
||||
static boolean handle_request(cJSON *request) {
|
||||
boolean continue_repl = true;
|
||||
|
||||
@@ -536,8 +551,15 @@ static boolean handle_request(cJSON *request) {
|
||||
cmd_setVariable(args, resp);
|
||||
} else if (!strcmp(command->valuestring, "disconnect")) {
|
||||
cmd_disconnect(args, resp);
|
||||
} else if (!strcmp(command->valuestring, "xsystem35.palette")) {
|
||||
cmd_palette(args, resp);
|
||||
} else {
|
||||
fprintf(stderr, "unknown command \"%s\"\n", command->valuestring);
|
||||
cJSON_AddBoolToObject(resp, "success", false);
|
||||
char *buf = malloc(strlen(command->valuestring) + 30);
|
||||
sprintf(buf, "unknown request \"%s\"", command->valuestring);
|
||||
cJSON_AddStringToObject(resp, "message", buf);
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
free(buf);
|
||||
}
|
||||
send_json(resp);
|
||||
return continue_repl;
|
||||
@@ -634,6 +656,15 @@ static void dbg_dap_onsleep(void) {
|
||||
dbg_main(0);
|
||||
}
|
||||
|
||||
static void dbg_dap_on_palette_change(void) {
|
||||
cJSON *event = cJSON_CreateObject(), *body;
|
||||
cJSON_AddStringToObject(event, "type", "event");
|
||||
cJSON_AddStringToObject(event, "event", "xsystem35.paletteChanged");
|
||||
cJSON_AddItemToObjectCS(event, "body", body = cJSON_CreateObject());
|
||||
cJSON_AddNumberToObject(body, "version", ++palette_version);
|
||||
send_json(event);
|
||||
}
|
||||
|
||||
void dbg_post_command(void *data) {
|
||||
msgq_enqueue(queue, data);
|
||||
}
|
||||
@@ -643,5 +674,6 @@ DebuggerImpl dbg_dap_impl = {
|
||||
.quit = dbg_dap_quit,
|
||||
.repl = dbg_dap_repl,
|
||||
.onsleep = dbg_dap_onsleep,
|
||||
.on_palette_change = dbg_dap_on_palette_change,
|
||||
.console_output = emit_output_event,
|
||||
};
|
||||
|
||||
@@ -58,6 +58,7 @@ typedef struct {
|
||||
void (*quit)(void);
|
||||
void (*repl)(int bp_no);
|
||||
void (*onsleep)(void);
|
||||
void (*on_palette_change)(void);
|
||||
void (*console_output)(int lv, const char *output);
|
||||
} DebuggerImpl;
|
||||
|
||||
|
||||
@@ -67,6 +67,8 @@ static bool read_index(int disk, drifiles *d, FILE *fp) {
|
||||
for (int i = 0; i < nr_files; i++) {
|
||||
if (disk != ltbl[i * 3] - 1)
|
||||
continue;
|
||||
if (d->maxno < i)
|
||||
d->maxno = i;
|
||||
d->disk[i] = ltbl[i * 3];
|
||||
int ptr = LittleEndian_getW(ltbl, i * 3 + 1);
|
||||
d->offset[i] = LittleEndian_get3B(ptbl, ptr * 3) << 8;
|
||||
|
||||
@@ -34,6 +34,7 @@ struct _drifiles {
|
||||
mmap_t *mmap[DRIFILEMAX];
|
||||
char *fnames[DRIFILEMAX];
|
||||
int nr_files; // upper limit on how many files could be referenced by this archive
|
||||
int maxno;
|
||||
uint8_t *disk; // file numbers
|
||||
uint32_t *offset; // offsets in file
|
||||
};
|
||||
|
||||
+2
-2
@@ -87,7 +87,7 @@ void
|
||||
on_item5_activate (GtkMenuItem *menuitem,
|
||||
gpointer user_data)
|
||||
{
|
||||
nact->ags.mouse_movesw = MOUSE_WARP_SMOOTH;
|
||||
nact->ags.mouse_warp_enabled = true;
|
||||
gtk_menu_popdown(GTK_MENU(menu_window_popup));
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ void
|
||||
on_item6_activate (GtkMenuItem *menuitem,
|
||||
gpointer user_data)
|
||||
{
|
||||
nact->ags.mouse_movesw = MOUSE_WARP_DISABLED;
|
||||
nact->ags.mouse_warp_enabled = false;
|
||||
gtk_menu_popdown(GTK_MENU(menu_window_popup));
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -89,10 +89,13 @@ static int midi_start(int no, int loop, char *data, int datalen) {
|
||||
|
||||
SDL_RWops *rwops = SDL_RWFromConstMem(data, datalen);
|
||||
mix_music = Mix_LoadMUSType_RW(rwops, MUS_MID, SDL_TRUE /* freesrc */);
|
||||
if (!mix_music)
|
||||
if (!mix_music) {
|
||||
WARNING("Cannot load MIDI: %s", SDL_GetError());
|
||||
return NG;
|
||||
}
|
||||
|
||||
if (Mix_PlayMusic(mix_music, loop ? loop : -1) != 0) {
|
||||
WARNING("Cannot play MIDI: %s", SDL_GetError());
|
||||
Mix_FreeMusic(mix_music);
|
||||
mix_music = NULL;
|
||||
return NG;
|
||||
|
||||
@@ -95,6 +95,7 @@ void sdl_effect_finish(struct sdl_effect *eff);
|
||||
/* key/pointer 関係 */
|
||||
extern void sdl_setJoyDeviceIndex(int index);
|
||||
extern void sdl_setCursorLocation(int x, int y);
|
||||
extern void sdl_setCursorInternalLocation(int x, int y);
|
||||
extern void sdl_setCursorType(int type);
|
||||
extern boolean sdl_cursorNew(uint8_t* data, int no, CursorImage *cursorImage, TCursorDirEntry *cursordirentry);
|
||||
extern int sdl_getKeyInfo();
|
||||
|
||||
+27
-11
@@ -223,6 +223,12 @@ void send_agsevent(enum agsevent_type type, int code) {
|
||||
nact->ags.eventcb(&agse); // Async in emscripten
|
||||
}
|
||||
|
||||
void sdl_setCursorInternalLocation(int x, int y) {
|
||||
mousex = x;
|
||||
mousey = y;
|
||||
send_agsevent(AGSEVENT_MOUSE_MOTION, 0);
|
||||
}
|
||||
|
||||
// Improves map navigation of Rance4 v2. See also the function comment of
|
||||
// rance4_Y3_IM_hack() in cmdy.c.
|
||||
static void rance4v2_hack(void) {
|
||||
@@ -274,9 +280,7 @@ void sdl_handle_event(SDL_Event *e) {
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
mousex = e->motion.x;
|
||||
mousey = e->motion.y;
|
||||
send_agsevent(AGSEVENT_MOUSE_MOTION, 0);
|
||||
sdl_setCursorInternalLocation(e->motion.x, e->motion.y);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEWHEEL:
|
||||
@@ -381,14 +385,26 @@ void sdl_handle_event(SDL_Event *e) {
|
||||
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_JOYBUTTONUP:
|
||||
if (e->jbutton.button < 4) {
|
||||
int i = 1 << (e->jbutton.button+4);
|
||||
if (e->jbutton.state == SDL_PRESSED)
|
||||
joyinfo |= i;
|
||||
else
|
||||
joyinfo &= ~i;
|
||||
} else {
|
||||
if (e->jbutton.state == SDL_RELEASED) {
|
||||
{
|
||||
int mask = 0;
|
||||
switch (e->jbutton.button) {
|
||||
case 0: case 1: case 2: case 3:
|
||||
mask = 1 << (e->jbutton.button + 4);
|
||||
break;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// Gamepads known to browsers get a "standard" mapping where D-pad
|
||||
// keys are mapped to buttons 12-15.
|
||||
case 12: mask = SYS35KEY_UP; break;
|
||||
case 13: mask = SYS35KEY_DOWN; break;
|
||||
case 14: mask = SYS35KEY_LEFT; break;
|
||||
case 15: mask = SYS35KEY_RIGHT; break;
|
||||
#endif
|
||||
}
|
||||
if (mask) {
|
||||
if (e->jbutton.state == SDL_PRESSED)
|
||||
joyinfo |= mask;
|
||||
else
|
||||
joyinfo &= ~mask;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
+11
-13
@@ -309,28 +309,26 @@ static void init_selwindow() {
|
||||
ags_updateArea(saveArea.x, saveArea.y, saveArea.w, saveArea.h);
|
||||
|
||||
/* マウスカーソルの自動移動 */
|
||||
int x = r.x + r.w * MOUSE_INIT_X_RATIO/100;
|
||||
if (default_element == 0) {
|
||||
MyPoint p;
|
||||
sys_getMouseInfo(&p, TRUE);
|
||||
if (p.y < r.y) {
|
||||
ags_setCursorLocation(r.x + r.w * MOUSE_INIT_X_RATIO/100,
|
||||
r.y + (sel.MsgFontSize +2) * MOUSE_INIT_Y_RATIO/100,
|
||||
TRUE);
|
||||
int y = r.y + (sel.MsgFontSize +2) * MOUSE_INIT_Y_RATIO/100;
|
||||
ags_setCursorLocation(x, y, true, true);
|
||||
} else if (p.y > (r.y + r.h)) {
|
||||
ags_setCursorLocation(r.x + r.w * MOUSE_INIT_X_RATIO/100,
|
||||
r.y + (sel.MsgFontSize +2) * regnum * MOUSE_INIT_Y_RATIO/100,
|
||||
TRUE);
|
||||
int y = r.y + (sel.MsgFontSize +2) * regnum * MOUSE_INIT_Y_RATIO/100;
|
||||
ags_setCursorLocation(x, y, true, true);
|
||||
} else {
|
||||
ags_setCursorLocation(r.x + r.w * MOUSE_INIT_X_RATIO/100,
|
||||
p.y * MOUSE_INIT_Y_RATIO/100,
|
||||
TRUE);
|
||||
int y = p.y * MOUSE_INIT_Y_RATIO/100;
|
||||
ags_setCursorLocation(x, y, true, true);
|
||||
}
|
||||
} else if (default_element < regnum) {
|
||||
ags_setCursorLocation(r.x + r.w * MOUSE_INIT_X_RATIO/100,
|
||||
r.y + (sel.MsgFontSize +2) * default_element * MOUSE_INIT_Y_RATIO/100, TRUE);
|
||||
int y = r.y + (sel.MsgFontSize +2) * default_element * MOUSE_INIT_Y_RATIO/100;
|
||||
ags_setCursorLocation(x, y, true, true);
|
||||
} else if (default_element < 1000) {
|
||||
ags_setCursorLocation(r.x + r.w * MOUSE_INIT_X_RATIO/100,
|
||||
r.y + (sel.MsgFontSize +2) * regnum * MOUSE_INIT_Y_RATIO/100, TRUE);
|
||||
int y = r.y + (sel.MsgFontSize +2) * regnum * MOUSE_INIT_Y_RATIO/100;
|
||||
ags_setCursorLocation(x, y, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -71,10 +71,10 @@ static void toggle_mouse_warp_mode(void) {
|
||||
return;
|
||||
|
||||
if (menuitem.fState & MFS_CHECKED) {
|
||||
nact->ags.mouse_movesw = MOUSE_WARP_DISABLED;
|
||||
nact->ags.mouse_warp_enabled = false;
|
||||
CheckMenuItem(hmenu, ID_OPTION_MOUSE_MOVE, MF_BYCOMMAND | MFS_UNCHECKED);
|
||||
} else {
|
||||
nact->ags.mouse_movesw = MOUSE_WARP_SMOOTH;
|
||||
nact->ags.mouse_warp_enabled = true;
|
||||
CheckMenuItem(hmenu, ID_OPTION_MOUSE_MOVE, MF_BYCOMMAND | MFS_CHECKED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
# To use this script in MSYS2 shell, install mingw-w64-x86_64-nsis and
|
||||
# mingw-w64-x86_64-ntldd-git packages.
|
||||
# To use this script in MSYS2 shell, install mingw-w64-ucrt-x86_64-nsis and
|
||||
# mingw-w64-ucrt-x86_64-ntldd packages.
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
echo 'Usage: make-installer.sh <build-dir> <nsi>'
|
||||
@@ -11,7 +11,7 @@ builddir=$1
|
||||
nsi=$2
|
||||
|
||||
echo 'dlls.nsi:'
|
||||
ntldd -R $builddir/src/xsystem35.exe |perl -ne 'print "File \"$1\"\n" if /=> (.*) \(/' |grep mingw |tee $builddir/dlls.nsi
|
||||
ntldd -R $builddir/src/xsystem35.exe |perl -ne 'print "File \"$1\"\n" if /=> (.*) \(/' |grep 'mingw32\|ucrt64' |tee $builddir/dlls.nsi
|
||||
echo
|
||||
|
||||
echo 'dlls-uninstall.nsi:'
|
||||
|
||||
Reference in New Issue
Block a user