mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-09-26 16:38:06 +03:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ade76adda6 | ||
|
|
53d0e8ffef | ||
|
|
b2e14bd19a | ||
|
|
9c73a34c35 | ||
|
|
36e1dc152b | ||
|
|
f786db5a50 | ||
|
|
c515b21afb | ||
|
|
d3db3fa83e | ||
|
|
86068b0ab9 | ||
|
|
de4f3ebb0d | ||
|
|
187a3ced35 | ||
|
|
b7703b6270 | ||
|
|
b7d0efbe55 | ||
|
|
02fe55eb93 | ||
|
|
058789b435 | ||
|
|
c5dcb20ac3 | ||
|
|
cb08f7ca76 | ||
|
|
7a7d94e60f | ||
|
|
b7681982a6 | ||
|
|
fefaf6c343 | ||
|
|
42e994dfba | ||
|
|
a6aa50b5cf |
@@ -31,6 +31,7 @@ jobs:
|
||||
SDL2_ttf:p
|
||||
SDL2_mixer:p
|
||||
libwebp:p
|
||||
portmidi:p
|
||||
${{ matrix.deps }}
|
||||
|
||||
- name: Checkout
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
## 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.
|
||||
|
||||
+6
-20
@@ -1,11 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
# Rebuild external projects when download URL changes
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
endif()
|
||||
|
||||
project(xsystem35 LANGUAGES C)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
enable_testing()
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
|
||||
|
||||
set(XSYSTEM35_VERSION "2.11.6")
|
||||
set(XSYSTEM35_VERSION "2.12.0")
|
||||
|
||||
include(CheckSymbolExists)
|
||||
include(FetchContent)
|
||||
@@ -185,25 +190,6 @@ else()
|
||||
list(APPEND SUMMARY_MIDI "SDL_mixer")
|
||||
set(ENABLE_MIDI_SDLMIXER 1)
|
||||
|
||||
if (HAVE_SIGACTION)
|
||||
list(APPEND SUMMARY_MIDI "raw")
|
||||
set(MIDI_DEVICE "/dev/midi" CACHE STRING "midi device")
|
||||
set(ENABLE_MIDI_RAWMIDI 1)
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
||||
check_symbol_exists(SNDCTL_SEQ_NRSYNTHS "machine/soundcard.h" ENABLE_MIDI_SEQMIDI)
|
||||
elseif (CMAKE_SYSTEM_NAME MATCHES "(NetBSD|OpenBSD)")
|
||||
check_symbol_exists(SNDCTL_SEQ_NRSYNTHS "soundcard.h" ENABLE_MIDI_SEQMIDI)
|
||||
else ()
|
||||
check_symbol_exists(SNDCTL_SEQ_NRSYNTHS "sys/soundcard.h" ENABLE_MIDI_SEQMIDI)
|
||||
endif()
|
||||
|
||||
if (ENABLE_MIDI_SEQMIDI)
|
||||
list(APPEND SUMMARY_MIDI "OSS sequencer")
|
||||
set(SEQ_DEVICE "/dev/sequencer" CACHE STRING "sequencer device")
|
||||
endif()
|
||||
|
||||
if (HAVE_PORTMIDI)
|
||||
list(APPEND SUMMARY_MIDI "PortMidi")
|
||||
set(ENABLE_MIDI_PORTMIDI 1)
|
||||
|
||||
@@ -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
|
||||
@@ -90,7 +96,7 @@ See [xsystem35 command manual](doc/xsystem35.6.adoc) for detailed usage.
|
||||
### 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 asciidoctor
|
||||
$ 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 ../../
|
||||
@@ -102,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 asciidoctor
|
||||
$ 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 ../../
|
||||
@@ -114,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 24
|
||||
versionName "2.11.6" + gitRevision()
|
||||
versionCode 26
|
||||
versionName "2.12.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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -5,16 +5,12 @@
|
||||
|
||||
#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@
|
||||
|
||||
@@ -47,18 +47,9 @@ finds System 3.x game files (*.ALD) from the current directory.
|
||||
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.
|
||||
|
||||
*-devmidi* _device_::
|
||||
Path to the midi device.
|
||||
|
||||
*-Me*::
|
||||
Use SDL_mixer for MIDI playback.
|
||||
|
||||
*-Mr*::
|
||||
Use raw MIDI device for MIDI playback.
|
||||
|
||||
**-Ms**_device_number_::
|
||||
Use sequencer device of the given number for MIDI playback.
|
||||
|
||||
**-Mp**_device_number_::
|
||||
Use ALSA (via PortMidi) for MIDI playback.
|
||||
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
+6
-5
@@ -112,9 +112,6 @@ 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 midifile.c)
|
||||
endif()
|
||||
@@ -159,15 +156,19 @@ 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
|
||||
-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
|
||||
--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
-1
@@ -969,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;
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
|
||||
+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__ */
|
||||
|
||||
+2
-4
@@ -235,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
|
||||
|
||||
+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__ */
|
||||
|
||||
@@ -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 関係 */
|
||||
|
||||
+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);
|
||||
|
||||
+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;
|
||||
|
||||
|
||||
@@ -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!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -461,7 +461,10 @@ void sel_select() {
|
||||
key = sys_keywait(25, KEYWAIT_CANCELABLE);
|
||||
|
||||
// Right-click exits the menu without waiting for button up.
|
||||
if (key == SYS35KEY_SPC) break;
|
||||
if (key == SYS35KEY_SPC) {
|
||||
curElement = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!key && prevkey == SYS35KEY_RET && curElement != -1) break;
|
||||
prevkey = key;
|
||||
@@ -536,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);
|
||||
|
||||
@@ -123,12 +123,6 @@ static void sys35_usage(boolean verbose) {
|
||||
#ifdef ENABLE_MIDI_SDLMIXER
|
||||
puts(" -Me : SDL_mixer midi player");
|
||||
#endif
|
||||
#ifdef ENABLE_MIDI_RAWMIDI
|
||||
puts(" -Mr : Raw Midi device");
|
||||
#endif
|
||||
#ifdef ENABLE_MIDI_SEQMIDI
|
||||
puts(" -Ms? : Sequenceer device (?:devicenumber)");
|
||||
#endif
|
||||
#ifdef ENABLE_MIDI_PORTMIDI
|
||||
puts(" -Mp? : ALSA (via PortMidi) (?:devicenumber)");
|
||||
#endif
|
||||
@@ -288,10 +282,6 @@ static void sys35_ParseOption(int *argc, char **argv) {
|
||||
if (argv[i + 1] != NULL) {
|
||||
muscd_set_playlist(argv[i + 1]);
|
||||
}
|
||||
} else if (0 == strcmp(argv[i], "-devmidi")) {
|
||||
if (argv[i + 1] != NULL) {
|
||||
midi_set_devicename(argv[i + 1]);
|
||||
}
|
||||
} else if (0 == strncmp(argv[i], "-M", 2)) {
|
||||
int subdev = 0;
|
||||
if (argv[i][3] != '\0') {
|
||||
@@ -400,11 +390,6 @@ static void check_profile() {
|
||||
if (param) {
|
||||
sdl_setJoyDeviceIndex(atoi(param));
|
||||
}
|
||||
/* Raw MIDI device name の設定 */
|
||||
param = get_profile("midi_device");
|
||||
if (param) {
|
||||
midi_set_devicename(param);
|
||||
}
|
||||
/* MIDI output device の設定 */
|
||||
param = get_profile("midi_output_device");
|
||||
if (param) {
|
||||
|
||||
@@ -49,11 +49,6 @@
|
||||
|
||||
#playlist: playlist.txt
|
||||
|
||||
# device name of the raw midi device or sequencer device.
|
||||
|
||||
#midi_device: /dev/midi
|
||||
#midi_device: /dev/sequencer
|
||||
|
||||
# Audio buffer size in bytes.
|
||||
# Too small value causes sound glitches, too large value causes sound delay.
|
||||
|
||||
@@ -62,8 +57,6 @@
|
||||
# MIDI Output method
|
||||
# 'e' : SDL_mixer (default)
|
||||
# 'pX' : via PortMidi (X is the device number, usually 0)
|
||||
# 'r' : raw midi device
|
||||
# 'sX' : sequencer device (X is the port number, usually 0)
|
||||
# '0' : disable MIDI
|
||||
|
||||
#midi_output_device: e
|
||||
|
||||
-133
@@ -1,133 +0,0 @@
|
||||
%define ver 1.7.3
|
||||
%define rel 1
|
||||
|
||||
Summary: system35 scenario decoder on X
|
||||
Name: xsystem35
|
||||
Version: %{ver}pre5
|
||||
Release: %{rel}
|
||||
License: GPL
|
||||
Group: Amusements/Games
|
||||
Source: http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/down/xsystem35-1.7.3pre5.tar.gz
|
||||
# Source: http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/down/test/xsystem35-%{ver}-pre5.tar.gz
|
||||
Requires: gtk+ >= 1.0.0
|
||||
BuildPreReq: gtk+-devel
|
||||
URL: http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/index.html
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-root
|
||||
|
||||
%description
|
||||
system35 scenario decoder on X
|
||||
Xsystem35 enables Alice Soft's games on X.
|
||||
|
||||
%description -l ja
|
||||
アリスソフトのゲームをX上で実行するためのプログラムです。
|
||||
最初に実行する前に ドキュメントディレクトリの xsys35rc.sample
|
||||
をホームディレクトリに.xsys35rcとしてコピーしてお使い下さい。
|
||||
|
||||
%changelog
|
||||
|
||||
%prep
|
||||
|
||||
%setup -q
|
||||
# %setup -q -n %{name}-%{ver}-pre5
|
||||
|
||||
#%patch -p1
|
||||
|
||||
rm -rf %{buildroot}
|
||||
|
||||
|
||||
%build
|
||||
|
||||
./configure --prefix=/usr --enable-audio=oss,alsa,esd --enable-cdrom=linux,mp3 --enable-midi=extp,raw,seq --disable-debug --enable-qmidi
|
||||
make
|
||||
|
||||
%install
|
||||
|
||||
%makeinstall
|
||||
|
||||
%clean
|
||||
rm -rf %{buildroot}
|
||||
|
||||
%pre
|
||||
|
||||
%post
|
||||
|
||||
%preun
|
||||
|
||||
%postun
|
||||
|
||||
%files
|
||||
%defattr(-, root, root)
|
||||
%doc ABOUT-NLS COPYING INSTALL doc/* src/xsys35rc.sample
|
||||
%doc contrib
|
||||
%doc patch
|
||||
%{_libdir}/xsystem35/*
|
||||
%{_bindir}/xsystem35
|
||||
%{_datadir}/locale/*/LC_MESSAGES/xsystem35*
|
||||
|
||||
%changelog
|
||||
* Sun Dec 21 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.7.2]
|
||||
- version 1.7.2
|
||||
|
||||
* Sun Aug 31 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.7.1]
|
||||
- version 1.7.1
|
||||
|
||||
* Thu May 01 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.7.0]
|
||||
- version 1.7.0 preX
|
||||
|
||||
* Sat Feb 01 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.6.0]
|
||||
- version 1.6.0
|
||||
|
||||
* Sun Jan 05 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.6.0]
|
||||
- 1.6.0 preX
|
||||
|
||||
* Tue May 14 2002 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.5.x]
|
||||
- revised for xsystem35-1.5.x
|
||||
|
||||
* Sun May 1 2001 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.4.0]
|
||||
- update to xsystem35-1.4.0
|
||||
|
||||
* Sun Apr 1 2001 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.3.4]
|
||||
- update to xsystem35-1.3.4
|
||||
|
||||
* Sun Nov 26 2000 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.3.3]
|
||||
- import spec file from JRPM to tar ball. (Grate thanks to Toshiya Takagi)
|
||||
|
||||
* Sun Dec 4 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.4-1]
|
||||
- Updated to xsystem35-1.2.4
|
||||
|
||||
* Sun Sep 5 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.3-2]
|
||||
- Use TiMidity and mp3 instead of CD-DA
|
||||
|
||||
* Thu Aug 26 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.3-1]
|
||||
- Updated to xsystem35-1.2.3
|
||||
|
||||
* Sat Jul 24 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.2-1]
|
||||
- Updated to xsystem35-1.2.2
|
||||
|
||||
* Thu Jun 10 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.1-1]
|
||||
- Updated to xsystem35-1.2.1
|
||||
|
||||
* Mon May 24 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.0-1]
|
||||
- Updated to xsystem35-1.2.0
|
||||
|
||||
* Thu May 13 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
- Changed /usr/local/lib/xsystem35 to /usr/X11R6/lib/xsystem35
|
||||
|
||||
* Mon May 3 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
- First release against glibc
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
%define ver @VERSION_MA@
|
||||
%define rel 1
|
||||
|
||||
Summary: system35 scenario decoder on X
|
||||
Name: xsystem35
|
||||
Version: %{ver}@VERSION_MI@
|
||||
Release: %{rel}
|
||||
License: GPL
|
||||
Group: Amusements/Games
|
||||
Source: http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/down/xsystem35-@VERSION@.tar.gz
|
||||
# Source: http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/down/test/xsystem35-%{ver}-@VERSION_MI@.tar.gz
|
||||
Requires: gtk+ >= 1.0.0
|
||||
BuildPreReq: gtk+-devel
|
||||
URL: http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/index.html
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-root
|
||||
|
||||
%description
|
||||
system35 scenario decoder on X
|
||||
Xsystem35 enables Alice Soft's games on X.
|
||||
|
||||
%description -l ja
|
||||
アリスソフトのゲームをX上で実行するためのプログラムです。
|
||||
最初に実行する前に ドキュメントディレクトリの xsys35rc.sample
|
||||
をホームディレクトリに.xsys35rcとしてコピーしてお使い下さい。
|
||||
|
||||
%changelog
|
||||
|
||||
%prep
|
||||
|
||||
%setup -q
|
||||
# %setup -q -n %{name}-%{ver}-@VERSION_MI@
|
||||
|
||||
#%patch -p1
|
||||
|
||||
rm -rf %{buildroot}
|
||||
|
||||
|
||||
%build
|
||||
|
||||
./configure --prefix=/usr --enable-audio=oss,alsa,esd --enable-cdrom=linux,mp3 --enable-midi=extp,raw,seq --disable-debug --enable-qmidi
|
||||
make
|
||||
|
||||
%install
|
||||
|
||||
%makeinstall
|
||||
|
||||
%clean
|
||||
rm -rf %{buildroot}
|
||||
|
||||
%pre
|
||||
|
||||
%post
|
||||
|
||||
%preun
|
||||
|
||||
%postun
|
||||
|
||||
%files
|
||||
%defattr(-, root, root)
|
||||
%doc ABOUT-NLS COPYING INSTALL doc/* src/xsys35rc.sample
|
||||
%doc contrib
|
||||
%doc patch
|
||||
%{_libdir}/xsystem35/*
|
||||
%{_bindir}/xsystem35
|
||||
%{_datadir}/locale/*/LC_MESSAGES/xsystem35*
|
||||
|
||||
%changelog
|
||||
* Sun Dec 21 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.7.2]
|
||||
- version 1.7.2
|
||||
|
||||
* Sun Aug 31 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.7.1]
|
||||
- version 1.7.1
|
||||
|
||||
* Thu May 01 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.7.0]
|
||||
- version 1.7.0 preX
|
||||
|
||||
* Sat Feb 01 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.6.0]
|
||||
- version 1.6.0
|
||||
|
||||
* Sun Jan 05 2003 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.6.0]
|
||||
- 1.6.0 preX
|
||||
|
||||
* Tue May 14 2002 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.5.x]
|
||||
- revised for xsystem35-1.5.x
|
||||
|
||||
* Sun May 1 2001 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.4.0]
|
||||
- update to xsystem35-1.4.0
|
||||
|
||||
* Sun Apr 1 2001 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.3.4]
|
||||
- update to xsystem35-1.3.4
|
||||
|
||||
* Sun Nov 26 2000 CHIKAMA Masaki <masaki-c@is.aist-nara.ac.jp>
|
||||
[xsystem35-1.3.3]
|
||||
- import spec file from JRPM to tar ball. (Grate thanks to Toshiya Takagi)
|
||||
|
||||
* Sun Dec 4 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.4-1]
|
||||
- Updated to xsystem35-1.2.4
|
||||
|
||||
* Sun Sep 5 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.3-2]
|
||||
- Use TiMidity and mp3 instead of CD-DA
|
||||
|
||||
* Thu Aug 26 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.3-1]
|
||||
- Updated to xsystem35-1.2.3
|
||||
|
||||
* Sat Jul 24 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.2-1]
|
||||
- Updated to xsystem35-1.2.2
|
||||
|
||||
* Thu Jun 10 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.1-1]
|
||||
- Updated to xsystem35-1.2.1
|
||||
|
||||
* Mon May 24 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
[xsystem35-1.2.0-1]
|
||||
- Updated to xsystem35-1.2.0
|
||||
|
||||
* Thu May 13 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
- Changed /usr/local/lib/xsystem35 to /usr/X11R6/lib/xsystem35
|
||||
|
||||
* Mon May 3 1999 Toshiya Takagi <jwtoshi@mars.dti.ne.jp>
|
||||
- First release against glibc
|
||||
|
||||
Reference in New Issue
Block a user