Compare commits

..
249 Commits
Author SHA1 Message Date
kichikuou 8806bc9545 Version 2.17.0 2025-11-09 22:27:45 +09:00
kichikuou 5e62405f17 Move patch/ to misc/patch/ 2025-11-09 22:26:15 +09:00
kichikuou 714c7d44b5 Android: Update SDL to 2.32.10 2025-11-09 22:08:54 +09:00
kichikuou 0f6d4e2343 Add Streamer Mode with -censor option
This introduces "Streamer Mode" to mosaic specified NSFW images, making
the game suitable for streaming or public viewing. This feature is
enabled via the '-censor <file>' command-line option, which takes a file
containing a list of image numbers to be filtered.
2025-11-09 11:47:13 +09:00
kichikuou f1536a801a QE/LE: Handle backslashes in filenames
Rance 5D uses filename `Save\\Rance5dSystem.asd`. This caused issues:

- On Windows, saving would fail if the `Save` directory did not exist.
- On other platforms, files were created with literal backslashes in
  their names.

This change addresses these problems by:

- In commandQE, normalizing backslashes to forward slashes in the path
  and ensuring that the target directory exists by calling mkdir_p().
- In commandLE, first attempting to load files with normalized forward
  slashes. If that fails, it retries with the original path (containing
  backslashes) for compatibility with older saves.
2025-11-06 11:05:23 +09:00
kichikuou ab372b7873 Unify old and new command implementations
Consolidate logic for parsing string arguments by introducing a
parameter to handle different terminators.
2025-11-06 09:39:51 +09:00
kichikuou 2c02f40dc4 Move uppercase commands from cmd2F.c to cmd<first_letter>.c 2025-11-06 09:39:46 +09:00
kichikuou a395366cf8 Version 2.16.1 2025-08-28 13:00:30 +09:00
kichikuou e416fc20d3 CI: Disable portmidi on mingw32
mingw-w64-i686-portmidi is no longer provided.
2025-08-28 12:47:02 +09:00
kichikuou 7d03fc6757 sactlog: Hold log text in UTF-8 2025-08-28 12:24:49 +09:00
kichikuou e3b8c90611 sactlog: Draw text using gfx_drawString()
This fixes #71. It was a regression by commit ec071d4.
2025-08-28 11:41:51 +09:00
kichikuou 361ca89016 Windows: #undef min / max in portab.h 2025-06-20 08:11:35 +09:00
kichikuou 5bd4622031 Version 2.16.0 2025-06-13 17:20:47 +09:00
kichikuou c7c0f69ec4 Split sdl_core.h to event.h and editor.h
And rename sdl_event.c to event.c, sdl_input.c to editor.c.
2025-06-11 10:12:25 +09:00
kichikuou f38a3eda5c Merge sdl_cursor.c to cursor.c 2025-06-11 10:12:22 +09:00
kichikuou dc17b78365 Move miscellaneous low-level functions to system.[ch] 2025-06-11 09:23:44 +09:00
kichikuou b9f68eedd3 Move joystick initialization code to sdl_event.c 2025-06-11 09:23:44 +09:00
kichikuou adf362ea57 Rename sdl_effect_* to effect_* 2025-06-11 09:23:44 +09:00
kichikuou b5bf439b8e Remove graphics.h 2025-06-11 09:23:42 +09:00
kichikuou 9a01d28075 Move gfx_* functions from sdl_core.h to gfx.h 2025-06-11 09:22:36 +09:00
kichikuou 945dbd7722 Rename graphics functions from sdl_* to gfx_*
And rename sdl_{video,draw,image}.c to gfx_{video,draw,image}.c.
2025-06-10 15:00:27 +09:00
kichikuou 1c54487041 cmake: Use new policies up to CMake 4.0 2025-06-10 13:58:40 +09:00
kichikuou 92389289da Android: Add "clear save files" launcher menu command 2025-06-10 13:17:27 +09:00
kichikuou 4de03cc77f Move font license files to license/ 2025-05-30 20:54:28 +09:00
kichikuou 5a81ac6fc8 Windows: Add cancel button to text/number input dialog 2025-05-30 16:06:29 +09:00
kichikuou d7bac22059 Windows: Implement number input dialog (NI command)
Fixes #68.
2025-05-30 16:06:26 +09:00
kichikuou 8d4424061d Switch JPEG decoder to NanoJPEG and disable fancy upsampling
Graymerca uses JPEG images for map tiles, which suffers from color
bleeding due to chroma upsampling in the JPEG decoder.

Since stb_image cannot disable the bilinear upsampling filter, this
switches the JPEG decoder to NanoJPEG.

Fixes #67.
2025-05-29 08:39:59 +09:00
kichikuou 6c692e44e5 Version 2.15.1 2025-05-14 15:06:20 +09:00
kichikuou ec071d4e8a dt_drawtext_col: Fix blend mode
This fixes #66. It was a regression by commit 6b646b3.
2025-05-14 12:46:30 +09:00
kichikuou 904e10daa7 Version 2.15.0 2025-04-21 11:20:31 +09:00
kichikuou 65b6da3f2a emscripten: Export HEAPU8 and HEAP16
Used in Kichikou on Web shell.
2025-04-21 10:12:43 +09:00
kichikuou 3f495b72c1 Fix message waiting in Rance 2 intro
By recreating a bug of the ZW command in system35.exe.
2025-04-21 09:43:01 +09:00
kichikuou 90670477c6 Fix uncancellable message wait mode (ZW 256-511) 2025-04-21 09:42:58 +09:00
kichikuou 566ebb503f Fix PS and PP commands
This was a regression introduced by commit c1018d9.

Fixes #65.
2025-04-21 08:22:39 +09:00
kichikuou 6feab51a5d Update android/README.md 2025-04-10 10:45:14 +09:00
kichikuou 15d0b44ab9 Android: Move "Install from ZIP" to options menu and add help message
For consistency with xsystem4-android.
2025-04-10 10:12:56 +09:00
kichikuou a0f20caa77 Android: Support audio file names prefixed with track numbers 2025-04-10 10:12:56 +09:00
kichikuou 39712ee46e Version 2.14.3 2025-04-01 09:33:24 +09:00
kichikuou dcdbe7bb76 Android, Emscripten: Upgrade libwebp to 1.5.0 2025-04-01 09:28:33 +09:00
kichikuou 01a4255b83 Android: Upgrade SDL to 2.32.4 2025-04-01 08:49:30 +09:00
kichikuou d978a24a5e Fix build for big endian architectures 2025-04-01 08:24:42 +09:00
kichikuou ed196f72b9 Update game_compatibility.md
AliceNoir games are not supported.
2025-03-30 10:02:31 +09:00
kichikuou c9fd1dcfd0 Version 2.14.2 2025-03-09 13:44:58 +09:00
kichikuou c1018d9e0f Replace Color struct with SDL_Color 2025-03-09 13:16:02 +09:00
kichikuou cb8a48cdec Introduce sdl_palette
It replaces the sdl_col array and is set as the palette of main_surface.
2025-03-09 10:42:32 +09:00
kichikuou 6bf6a5c86a Delay mouse button state changes caused by touch events
This fixes #64 where a touch operation is recognized as a click in the
wrong position in Mamatoto.

This is the same problem that occured in xsystem4 and was addressed in
https://github.com/nunuhara/xsystem4/commit/5e80c9658787b118920f850ae4cbc883e6fceb1e,
and the fix is also the same.
2025-03-08 08:33:24 +09:00
kichikuou 790aa07130 Android: Upgrade AGP to 8.7.3 and bump minSdkVersion to 21
So that it builds with latest Android Studio.
2025-03-07 14:49:17 +09:00
kichikuou fa74a4744c Fix ags_scaledCopyArea() for 8-bit DIB
This fixes special move animation in Mamatoto.
2025-03-07 11:21:14 +09:00
kichikuou fb68b03a4f debugger: Update screen before entering REPL 2025-03-07 09:47:46 +09:00
kichikuou 75228cc4c8 Android: Back button to exit the game
Fixes #50.
2025-03-06 08:00:50 +09:00
kichikuou 8c13361164 emscripten: Use System3.9 compatible save format by default 2025-02-25 21:45:11 +09:00
kichikuou d05dc83e67 emscripten: Fix unused-function warning 2025-02-22 14:37:15 +09:00
kichikuou c9f21c4547 sactamask: Use sdl_effect framework 2025-02-21 09:14:05 +09:00
kichikuou f053f25397 Make webp_extract() return SDL_Surface instead of cgdata
This eliminates unnecessary RGBA -> RGB + alpha plane -> RGBA
conversion.
2025-02-21 09:14:02 +09:00
kichikuou f673708a3f Remove depth field from surface_t 2025-02-21 09:12:07 +09:00
kichikuou aab63adac2 Refactor image drawing functions 2025-02-21 09:10:55 +09:00
kichikuou 6f09a999d2 Gpx, ShGraph: Remove unused 16bpp surface support 2025-02-19 15:59:39 +09:00
kichikuou 2ed44dab6d Move surface and graphic functions from modules/lib to modules/Gpx
Except for gr_blend_alpha_map(), which is used by oujimisc.
2025-02-19 14:57:40 +09:00
kichikuou a8f46453d8 Remove redundant fields from surface_t 2025-02-19 14:03:01 +09:00
kichikuou baa4a3158f ags: Add ALPHA_AT macro 2025-02-19 13:39:20 +09:00
kichikuou 8328b93227 Rename agsurface_t to surface_t 2025-02-19 13:24:56 +09:00
kichikuou 6665416683 Refactor NightDemonDemo and tDemo to use SDL_Surface 2025-02-19 13:21:17 +09:00
kichikuou cf5e899632 Remove unused includes from NIGHTDLL/ and SACT/ 2025-02-19 12:38:47 +09:00
kichikuou 51954c6bd4 Move load_cg_to_sdlsurface() to src/cg.c
And rename it to cg_load_as_sdlsurface().
2025-02-19 12:30:13 +09:00
kichikuou f282c02376 Replace sf0 with main_surface 2025-02-19 12:15:10 +09:00
kichikuou e2c75fbd9d Rename sdl_dib to main_surface and move it to ags.h 2025-02-19 12:15:06 +09:00
kichikuou b28e3ef2fd Do not use gr_* functions from SACT/ and NIGHTDLL/ 2025-02-19 12:14:58 +09:00
kichikuou 215de5511e Simplify gre_BlendUseAMap() 2025-02-19 10:20:38 +09:00
kichikuou f669804573 Refactor sactamask.c to use SDL_Surface 2025-02-19 09:59:31 +09:00
kichikuou 9c6423bf99 drawtext: Remove 8-bit text rendering function 2025-02-19 09:59:22 +09:00
kichikuou 4f3b73c1ac Refactor sactlog.c 2025-02-19 08:21:50 +09:00
kichikuou 8ee53accf9 SACT: Change depth map from surface_t to SDL_Surface 2025-02-18 22:01:20 +09:00
kichikuou 6b646b3857 SACT: Change text canvas from surface_t to SDL_Surface 2025-02-18 22:01:18 +09:00
kichikuou dec1649882 SACT: Make sprites have SDL_Surface instead of surface_t 2025-02-18 21:58:06 +09:00
kichikuou 6b9c3475a0 Simplify sdl_scaledCopyArea() 2025-02-17 08:16:09 +09:00
kichikuou 1335a12065 Remove sp_draw2 2025-02-16 22:52:20 +09:00
kichikuou 93bd8ca737 sprite_sel.c: Remove unnecessary variable 2025-02-16 22:39:09 +09:00
kichikuou 5bae0c16c5 Simplify gr_ functions using SDL surface operations 2025-02-16 21:03:59 +09:00
kichikuou d551cdbb70 Refactor text rendering functions in modules/ 2025-02-16 13:13:16 +09:00
kichikuou e711d5786e Make agsurface_t backed by SDL_Surface
This adds `sdl_surface` field to agsurface_t. `agsurface->pixel` is now
set to `agsurfae->sdl_surface->pixels`.

Note that the `sdl_surface` field does not have alpha; transparent
surfaces have a separate alpha plane in `agsurface->alpha`.
2025-02-16 13:13:13 +09:00
kichikuou 64abb3c582 screenshot: Save only view area, not entire sdl_dib 2025-02-11 13:46:20 +09:00
kichikuou bf26f1b0c0 Refactor clipping functions 2025-02-11 12:36:21 +09:00
kichikuou f4f1a99372 Fix mathClip command 2025-02-11 12:36:18 +09:00
kichikuou 53f0a5ce2a sdl_effect: Fix palette issue when texture is created from sdl_dib 2025-02-11 10:30:25 +09:00
kichikuou c621a5dddb Remove intermediate screen buffer
Pixels are now copied directly from sdl_dib to sdl_texture.
2025-02-11 08:37:47 +09:00
kichikuou 42faf38a47 emscripten: Replace sdl_getDisplaySurface with save_screenshot function 2025-02-10 07:47:48 +09:00
kichikuou c50a563e80 Version 2.14.1 2025-02-07 12:39:05 +09:00
kichikuou 996f63f55f Android: Upgrade SDL to 2.30.12 2025-02-07 12:34:43 +09:00
kichikuou fb77b229ea Apply text decoration to selection menus too 2025-02-07 10:52:58 +09:00
kichikuou 886d55057a ZZ13 command should also affect menu font
This fixes the problem of menus always being displayed in Gothic font.
The font type at the time the `]` command is executed should be used.
2025-02-07 09:29:30 +09:00
kichikuou 7f645d6bd1 Refactor function return types in modules/ 2025-02-03 09:24:45 +09:00
kichikuou f8d59e5fc0 Refactor savedata, s39ain, s39ini interfaces 2025-02-02 22:33:56 +09:00
kichikuou 78ebbf40f4 Refactor mus_* interfaces 2025-02-02 22:19:43 +09:00
kichikuou dccd75113b emscripten: Make load_mincho_font() return bool 2025-02-02 14:25:36 +09:00
kichikuou d063655b25 Refactor muspcm_* interface 2025-02-02 13:52:54 +09:00
kichikuou 5e0844e9ea Refactor musbgm_* interface 2025-02-02 13:08:04 +09:00
kichikuou 386c3c0fcd Refactor cdromdevice_t interface 2025-02-02 12:50:15 +09:00
kichikuou 2857c13e15 Refactor mididevice_t interface 2025-02-02 12:49:39 +09:00
kichikuou d14b42c146 Replace boolean/TRUE/FALSE with bool/true/false 2025-02-02 10:02:08 +09:00
kichikuou 29988d0d6c Simplify boolean expressions 2025-02-02 09:36:20 +09:00
kichikuou bc5d72b6fe Refactor cali.c 2025-02-02 09:00:24 +09:00
kichikuou 03f9b36ff0 Fix palette issue in DALK intro
The intro screen of DALK works as follows:

1. load CG 304 to (0,0)-(639, 399) using palette 16-31
2. load CG 305 to (0,400)-(639,799) using palette 16-31
3. CE (copy with effect) from (0,400)-(639,799) to (0,0)-(639, 399)

Step 2 destroys the palette range of CG 304, so before the copy the
pixels in (0,0)-(639,399) have incorrect colors when displayed with the
latest palette.

To avoid this problem, we need create the "old texture" of sdl_effect
from sdl_display instead of sdl_dib.
2025-01-23 14:35:00 +09:00
kichikuou afb9f96a1a Improve midi.portmidi.c
One MIDI thread now handles multiple playbacks.
2025-01-15 11:10:09 +09:00
kichikuou 28e685818c Remove gre_Blend() and gre_BlendScreen() 2025-01-10 09:23:08 +09:00
kichikuou 51eca5c8c0 Version 2.14.0 2025-01-09 10:31:50 +09:00
kichikuou 1699fbda6c Update game_compatibility.md
Ore no Shita de Agake and Rakuen Yuki are now supported.

Fixes #63.
2025-01-09 10:21:42 +09:00
kichikuou abbe8b9be1 Add warning for missing .ALD files
This warns when the link table has an entry but the contents cannot be
read.

For example, Atlach-Nacha installs only GA.ALD on the hard drive and
read GB.ALD directly from the CD-ROM. This warning message prompts the
user to copy GB.ALD to the game directory.
2025-01-09 09:24:50 +09:00
kichikuou 10735b8be6 Windows: Add application manifest to set ActiveCodePage to UTF-8
This will set the process code page to UTF-8 on Windows 10 version 1903
or above, allowing Japanese file names to be handled correctly even if
the system locale is not Japanese.
2025-01-09 08:58:14 +09:00
kichikuou e9d8a9d1a6 Refactor: Remove sdl_videodev and its accessor macros 2025-01-09 08:26:53 +09:00
kichikuou 780d30c01f Fix lnkIsLink
If the link table indicates the existence of an entry, but the volume
containing that entry is missing, this command returns 1.
2025-01-08 16:15:37 +09:00
kichikuou d6adb3241c Add sdl_showMessageBox and replace menu_msgbox_open 2025-01-08 11:24:49 +09:00
kichikuou 3594fc19dc Fix slot game speed in Persiom 2025-01-08 10:54:56 +09:00
kichikuou 883f538709 Fix SACT.QueryTextPos
It should return screen coordinates, not sprite-local coordinates.
2025-01-08 10:04:31 +09:00
kichikuou c280fc719b Implement SACT.PeekKey and SACT.MessagePeek
Used in Rakuen Yuki.
2025-01-08 10:04:28 +09:00
kichikuou 7da9e64ab6 Fix speed of slot game in Ore no Shita de Agake 2025-01-07 16:16:01 +09:00
kichikuou bba602ab04 Scheduler: Yield based on scenario address
Now it yields execution when the device state is checked multiple times
from the same scenario address.
2025-01-07 16:15:59 +09:00
kichikuou 78dc226d13 Add scheduler.c
It consolidates VM throttling logic that was scattered in various
places.
2025-01-07 15:52:48 +09:00
kichikuou a2792d502e Implement mathSetClipWindow and mathClip
Used in Ore no Shita de Agake.
2025-01-07 15:52:47 +09:00
kichikuou e800a23e1d Implement Gpx functions for Ore no Shita de Agake 2025-01-07 15:52:44 +09:00
kichikuou e731b4ec95 Implement ShCalc functions for Ore no Shita de Agake 2025-01-07 15:41:53 +09:00
kichikuou dde697d3b4 Implement S3xMusic HLL
Used in Ore no Shita de Agake.

Since the musbgm_* interface does not allow multiple channels, this
implementation uses musbgm_* for channel 0 and muspcm_* for channel 1.
2025-01-07 15:41:43 +09:00
kichikuou c4d4f85ae4 Use consistent message format in sys_message() 2025-01-06 14:26:47 +09:00
kichikuou 84e3666a66 Rename DEBUG_COMMAND{,_YET} to TRACE{,_UNIMPLEMENTED}
And now TRACE_UNIMPLEMENTED is not ignored in release build.
2025-01-06 14:14:10 +09:00
kichikuou c2f11ecfbe Fix Gpx.IsSurface()
Used in Ore no Shita de Agake.
2025-01-05 12:59:07 +09:00
kichikuou 85d69aa5f0 Output debug messages by ZD command at log level 2 2025-01-05 12:46:37 +09:00
kichikuou 7beb558140 Fix compiler warnings about unused results 2024-12-30 15:47:31 +09:00
kichikuou 49126c506d debug_symbol: Fix warning message format 2024-12-26 08:37:14 +09:00
kichikuou 4c57c98e67 Update bug report template 2024-12-26 08:36:08 +09:00
kichikuou e464d92164 Fix buffer overrun in stretch functions
Fixes #61.
2024-12-09 20:31:23 +09:00
kichikuou b30fd71e4b Version 2.13.0 2024-12-07 08:23:49 +09:00
kichikuou 99ad91306b Emscripten: Use texthook suppression list 2024-12-06 13:11:09 +09:00
kichikuou ed96f26cea Add texthook_suppress option
For suppressing text hook on specified scenario pages.
2024-12-06 09:24:08 +09:00
kichikuou e6f71190ed Add texthook option
`-texthook print` prints text to console, and `-texthook copy`
automatically copies text to clipboard (for use with text hooker tools).

On Windows, copy mode can be toggled from the menu bar.
2024-12-04 16:34:12 +09:00
kichikuou 8219feee6d Windows: Redirect stderr to console
So that WARNING messages are printed on the console.
2024-12-04 11:43:59 +09:00
kichikuou bc8a85e046 Version 2.12.1 2024-12-02 10:42:58 +09:00
kichikuou 67f62f02e6 MSYS build: Static link portmidi
Fixes #60.
2024-12-02 10:12:20 +09:00
kichikuou 471c65973b emscripten: Do not use mmap for ALDs
To save memory, as ALD files are now stored as regular files in memfs.
2024-11-28 10:23:21 +09:00
kichikuou 5ff7149dc1 Fix a compiler warning 2024-11-28 10:21:18 +09:00
kichikuou 80988e52cf emscripten: Restore a hack to asyncify send_agsevent() callers
It was inadvertently removed in commit 61ad428.
2024-11-27 09:12:39 +09:00
kichikuou ade76adda6 Version 2.12.0 2024-11-26 20:49:17 +09:00
kichikuou 53d0e8ffef NightDemonDemo, tDemo: refresh screen when frame rate < 30 2024-11-25 17:30:15 +09:00
kichikuou b2e14bd19a Implement tDemo module
Fixes #59.
2024-11-25 16:35:05 +09:00
kichikuou 9c73a34c35 Version 2.11.7 2024-11-12 08:57:54 +09:00
kichikuou 36e1dc152b Fix crash when canceling menu with two-finger touch
Fixes #58.

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

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

This was a regression introduced by commit 605de28.
2024-08-31 10:27:09 +09:00
kichikuou c5dcb20ac3 Simplify midifile.c 2024-08-21 12:20:01 +09:00
kichikuou cb08f7ca76 Windows CI: Build with portmidi
Also update README.md.
2024-08-19 12:58:46 +09:00
kichikuou 7a7d94e60f Remove raw and OSS sequencer MIDI mackends
In favor of PortMidi.
2024-08-19 12:46:56 +09:00
kichikuou b7681982a6 Rework midi.portmidi.c
Copied midi.rawmidi.c and adapted it to use PortMidi. Now the main
thread and the MIDI thread communicate via a message queue.
2024-08-19 11:07:00 +09:00
kichikuou fefaf6c343 Remove RPM spec files 2024-08-02 15:17:49 +09:00
kichikuou 42e994dfba emscripten: Use EM_ASYNC_JS 2024-07-31 08:59:33 +09:00
kichikuou a6aa50b5cf emscripten: Use MODULARIZE=1 2024-07-30 12:30:50 +09:00
kichikuou c4e8205d6c Version 2.11.6 2024-07-22 12:32:33 +09:00
kichikuou dd09f54329 mouse: Use system cursor if possible 2024-07-22 09:28:07 +09:00
kichikuou 435ceb31d3 Fix build with portmidi enabled but raw-midi disabled 2024-07-22 09:28:07 +09:00
kichikuou e40de66821 Remove obsolete docs 2024-07-12 11:25:15 +09:00
kichikuou 73c79b7a2e Add xsystem35 version string to mansource 2024-07-12 08:07:42 +09:00
kichikuou a825ee80b3 Add AsciiDoc manuals for xsystem35 command and .gr file format
They replace the outdated README and GRFMT.TXT files.
2024-07-12 07:40:32 +09:00
kichikuou eeeab6e054 Right-click exits selection without waiting for button up
This fixes https://github.com/kichikuou/xsystem35-sdl2/issues/56.
2024-06-18 13:17:53 +09:00
kichikuou 875b233f32 CI: Build with latest emscripten 2024-06-11 07:49:43 +09:00
kichikuou bcaed3a687 Version 2.11.5 2024-06-10 13:56:51 +09:00
kichikuou 894e8e26a6 Add CHANGELOG.md 2024-06-10 10:24:46 +09:00
kichikuou 7206b0a4f7 emscripten: Build with libwebp 2024-06-10 09:46:41 +09:00
kichikuou 343f3bb7c5 Fix fileCheckExist
This fixes https://github.com/kichikuou/xsystem35-sdl2/issues/55.
2024-06-10 08:59:58 +09:00
kichikuou d3650ce293 Update game_compatibility.md 2024-05-24 21:32:39 +09:00
kichikuou 386cfeb60c Update .gitignore 2024-05-24 21:31:49 +09:00
kichikuou 9cd66c83ef Android: Build with libwebp
Fixes https://github.com/kichikuou/xsystem35-sdl2/issues/46.
2024-05-23 10:57:38 +09:00
kichikuou 065e16a082 Version 2.11.4 2024-05-22 13:38:33 +09:00
kichikuou 3699aa5c2d Windows: Hide menu bar in fullscreen mode
The menu bar is displayed when the mouse is moved to the top of the
screen, like System39.exe's full-screen mode.

This fixes https://github.com/kichikuou/xsystem35-sdl2/issues/53.
2024-05-22 13:37:12 +09:00
kichikuou 20914970c9 Fix text rendering issue in Rance 3 OP
This fixes https://github.com/kichikuou/xsystem35-sdl2/issues/54.
2024-05-22 09:13:09 +09:00
kichikuou 3f2f555aa6 Add a link to SDL issue 2024-05-16 20:55:35 +09:00
kichikuou 095da0bb86 Version 2.11.3 2024-04-11 09:12:55 +09:00
kichikuou 7b8acd6e05 Use lowercase s[a-z].asd in Android and Emscripten
To make sure that save files created in older versions can be loaded.
2024-04-11 09:10:39 +09:00
kichikuou 1b13e331e4 emscripten: Enable msgskip in initGameResourceFromDir()
This is in preparation to stop using xsystem35.gr in Kichikuou on Web,
without changing the current behavior.
2024-04-11 09:00:42 +09:00
kichikuou 5621ab4d86 Version 2.11.2 2024-04-10 17:21:55 +09:00
kichikuou 79805d9ea2 Android: Update SDL, SDL_ttf and SDL_mixer 2024-04-10 15:32:40 +09:00
kichikuou f427d50fa3 Android: Remove playlist migration code
And stop using -playlist option, so that it can be overridden by
.xsys35rc.
2024-04-10 15:07:07 +09:00
kichikuou 7c7768fba4 Android: Improve installation when game is in non-root directory of ZIP
Launcher.kt extracts given ZIP file to the internal storage, preserving
its directory structure.

Before this change, if the game files were in a subdirectory, an
xsystem35.gr file was generated containing the path to the game files.
However, with this method, .xsys35rc and some data files (such as map
files of Kaeru Nyo) could not be loaded.

After this change, Launcher.kt will no longer generate the xsystem35.gr
file. Instead, it records the directory where the game is located in
game_directory.txt, and specify that directory in -gamedir to launch
xsystem35.

Fixes #51.
2024-04-10 15:06:51 +09:00
kichikuou 2b6267aeb9 Create save directory if it doesn't exist 2024-04-10 14:37:21 +09:00
kichikuou 16e7d3baf1 Add -savedir option
It allows specifying a save directory without writing a game resource
file.
2024-04-10 14:37:21 +09:00
kichikuou 2d8d95ac6f emscripten: Simplify link options 2024-03-12 17:03:57 +09:00
kichikuou d5899ff55a emscripten: Add return in wait_vsync
To make it work with ASYNCIFY=2.
2024-03-12 13:04:30 +09:00
kichikuou 04037682ee Version 2.11.1 2024-02-18 10:36:16 +09:00
kichikuou cdb16f73a3 Read link table only from first ALD volume
This fixes https://github.com/kichikuou/xsystem35-sdl2/issues/45.

The behavior when the contents of link table differ between ALD volumes
is different between System 3.8 and System 3.9, and System 3.9 uses the
link table of the first volume. The MangaGamer version of Rance 5D
depends on this behavior.

As far as I know, the only game that depends on the System 3.8 behavior
is Child Assassin (in Alice CD 2.50). Considering the additional
complexity, we do not implement switching to the old behavior.
2024-02-18 10:28:13 +09:00
kichikuou 2895e338c0 Fix a crash in command-line debugger 2024-02-18 08:36:15 +09:00
kichikuou 1a2268e94b Update emscripten to 3.1.54 2024-02-16 12:44:00 +09:00
kichikuou 07643c82a4 emscripten: Don't let SDL change document.title 2024-02-16 12:44:00 +09:00
kichikuou a16156f8e4 CMake: Generate compile_commands.json 2024-01-28 11:26:05 +09:00
kichikuou ea5cef91fd Rename cdrom_device profile to playlist
Also renames `-devcd` command line flag to `-playlist`.

The old names can still be used for backwards compatibility.
2024-01-28 10:28:15 +09:00
kichikuou 48a41b9f82 Require SDL2_mixer on non-Emscripten platforms 2024-01-28 10:20:42 +09:00
kichikuou c11c80d95d Remove CD-ROM device support
This removes (old, unmaintained) real CD-ROM support for Linux and
FreeBSD. It may be possible to implement cross-platform CD support using
libcdio (https://www.gnu.org/software/libcdio/), but it would not be
worth the effort given the low avilability of hardware that can play
CD-DA these days.
2024-01-28 10:20:32 +09:00
kichikuou d7082a9d80 CI: Update GitHub actions 2024-01-27 10:40:17 +09:00
kichikuou 083cf885de CI: Enable COMPILE_WARNING_AS_ERROR on Windows and Emscripten 2024-01-27 10:25:15 +09:00
kichikuou 7b1fef4ad7 Fix a deprecated-non-prototype warning 2024-01-27 09:08:31 +09:00
kichikuou f039baf061 Refactor CMakeLists.txt 2024-01-21 08:49:30 +09:00
kichikuou 22c6b8e963 Version 2.11.0 2024-01-20 13:57:18 +09:00
kichikuou 576afecbfc Update xsys35rc.sample and include it in the package 2024-01-20 13:13:02 +09:00
kichikuou 4e28d92a2d Windows: Load %USERPROFILE%/.xys35rc if %HOME% is not set 2024-01-20 12:42:17 +09:00
kichikuou 22192c245f Windows: Remove game selection dialog 2024-01-20 11:55:29 +09:00
kichikuou 409fa83406 Windows CI: Add packaging step 2024-01-20 11:35:04 +09:00
kichikuou 894b0592f4 Windows: Remove installer 2024-01-20 11:04:43 +09:00
kichikuou 370100a6f2 Windows: Fix static library options 2024-01-20 09:59:10 +09:00
kichikuou 18cfbc90f2 Windows: Do not read profile from registry
This was only used for the default font path, so it should be safe to
remove it.
2024-01-20 09:38:44 +09:00
kichikuou cd51dc7f02 Windows: Embed fonts as PE resources 2024-01-20 09:30:10 +09:00
kichikuou e2638ed840 Refactor CMakeLists.txt using alias targets 2024-01-19 14:56:50 +09:00
kichikuou 6607815df3 MSYS build: Use static linking 2024-01-19 14:55:53 +09:00
kichikuou 77ed85aff7 Display error when debugger is requested but not available 2024-01-18 10:49:31 +09:00
kichikuou 3b1a311f32 CI: Disable debugger on MinGW32 build
The 32-bit cJSON package was removed from MSYS2.
2024-01-18 10:16:54 +09:00
kichikuou 1b3c2190b8 profile: get_profile() returns const char* 2024-01-18 10:16:54 +09:00
kichikuou 52e2d6095a profile: Allow various boolean expressions
In .xsys35rc, now "yes", "true", "on", "1" (case insensitive) mean true
and "no", "false", "off", "0" mean false.
2024-01-18 10:16:48 +09:00
kichikuou 47e2fcaec0 Add enable_zb option for enabling ZB command
By default it is disabled and normal weight is always used.

Issue: https://github.com/kichikuou/xsystem35-sdl2/issues/44
2024-01-18 08:27:46 +09:00
kichikuou 183ceb614a Implement ZB command
Although undocumented, it also affects the font weight of selection
window.

Issue: https://github.com/kichikuou/xsystem35-sdl2/issues/44
2024-01-17 14:32:32 +09:00
kichikuou 185e62010b Fix argument range check in commands2F60() 2024-01-14 11:35:35 +09:00
kichikuou 6f647701dd Android CMake: Use FetchContent_MakeAvailable 2024-01-13 16:18:38 +09:00
kichikuou a9c79b2e31 sysGetOSName: Use SDL_GetPlatform() 2024-01-11 14:08:31 +09:00
kichikuou ba52fbf5e9 Version 2.10.1 2024-01-01 13:17:44 +09:00
kichikuou 85d40701c4 Palette 246-249 should be preserved when loading PMS8 2024-01-01 12:46:13 +09:00
kichikuou 7b535b371a Fix initial palette values
These match the System3.9 default colors that came from the default
system colors in Windows 256-color mode [1].

[1] https://en.wikipedia.org/wiki/List_of_software_palettes#Microsoft_Windows_default_20-color_palette
2024-01-01 12:25:43 +09:00
kichikuou c0dbae8202 Refactor palette data structure 2024-01-01 11:47:11 +09:00
kichikuou ca03450b87 Windows: Add menu command for integer scaling 2023-12-15 10:46:06 +09:00
kichikuou f795a500cf Update emscripten to 3.1.50 2023-12-10 13:24:49 +09:00
kichikuou 3314f00bf8 Fix cdGetMaxTrack for download edition of Daiakuji
It should return the maximum index of the BGM archive.

Fixes #43.
2023-12-09 14:57:01 +09:00
kichikuou a2d79f045c Version 2.10.0 2023-12-09 13:08:30 +09:00
kichikuou f247495578 Breaking change: Fix ShArray.ChangeSecretArray
This breaks save file compatibility for Daiakuji and Kaeru nyo Kuni nyo
Alice.

Due to an incorrect encryption code in ShArray.ChangeSecretArray, save
files were not interoperable with system3.9. (Even worse, this bug did
not affect the checksum calculation and did not cause a "corrupt save
file" error when a file saved with system3.9 was loaded with xsystem35
or vice versa.)

Fixes #41.
2023-12-09 11:35:40 +09:00
kichikuou f6583330de debugger_dap: Fix a bug that seq of outgoing messages was not increasing 2023-12-08 08:57:56 +09:00
kichikuou 4b15f45897 debugger: Add custom DAP messages for communicating palette changes
This implements "xsystem35.palette" custom request and
"xsystem35.paletteChanged" custom event.

The "xsystem35.palette" request retrieves the color values of the AGS
palette.

  interface PaletteRequest extends Request {
    command: 'xsystem35.palette';
  }

  interface PaletteResponse extends Response {
    body: {
      /**
       * A number that increases each time the palette changes.
       */
      version: number;

      /**
       * 256 element array containing color values in 0xRRGGBB format.
       */
      palette: number[];
    };
  }

The "xsystem35.paletteChanged" event indicates that the AGS palette has
changed.

  interface PaletteChangedEvent extends Event {
    event: 'xsystem35.paletteChanged';

    body: {
      /**
       * A number that increases each time the palette changes.
       */
      version: number;
    };
  }

DAP clients can know if the received value is up to date by comparing
the `version` values of paletteChanged and PaletteResponse.
2023-12-08 08:35:45 +09:00
kichikuou 7bc433731f CI: Fix Android build
AGP 8.0 requires JDK 17.
2023-11-17 13:00:56 +09:00
kichikuou 4c21570eb1 Android: Upgrade SDL to 2.28.5 2023-11-17 12:15:17 +09:00
kichikuou a3e7feffc2 Switch Windows 64-bit build from mingw64 to ucrt64 2023-11-17 09:08:24 +09:00
kichikuou a4c1dd1acf Remove unused MOUSE_WARP_DIRECT mode 2023-09-04 17:14:17 +09:00
kichikuou 09086ccc85 IZ command: add delay even if mouse movement is disabled
Without it, it's hard to exit camp mode in TT2.
2023-09-04 17:03:06 +09:00
kichikuou 53e39b7c11 emscripten: Call xsystem35.shell.showMouseMoveEffect()
See kichikuou/web@07a6118 for details.
2023-09-04 13:32:04 +09:00
kichikuou f0ccfee40f Update internal mouse coordinates even if cursor movement is disabled
In TT2, keyboard/gamepad navigation is implemented by moving the mouse
cursor using IZ command. It did not work in browsers where mouse cursor
could not be moved or when mouse movement was disabled from the menu.

Now IZ command updates the internal mouse coordinates even when the
cursor cannot be moved.
2023-09-04 13:32:00 +09:00
kichikuou 10cdec98e6 emscripten: Improve gamepads support
In the W3C gamepad API, many gamepads are mapped to the "standard
layout", where D-pad keys are mapped to buttons 12-15.
2023-09-03 22:41:12 +09:00
kichikuou c61afb4308 Improve README.md
With the help of ChatGPT.
2023-08-29 12:09:30 +09:00
kichikuou f6cf881e61 Android: Sign apk only when keystore file exists 2023-08-28 11:01:33 +09:00
kichikuou a8277e71a7 Android: Update command line build instructions 2023-08-28 10:26:17 +09:00
kichikuou 3482fb6440 Android: Upgrade SDL to 2.28.2 2023-08-13 12:42:54 +09:00
kichikuou 3c81c8fec2 Improve error messages for when MIDI cannot be played
* Show warnings on failure of Mix_LoadMUS / Mix_PlayMusic
* Display "Cannot open playlist" warning only when the game does not
  have MIDI
2023-07-29 07:50:55 +09:00
fcolecumberri e090485b37 Update README.md
https://github.com/kichikuou/xsystem35-sdl2/issues/39
2023-07-28 21:42:59 +09:00
384 changed files with 12112 additions and 22471 deletions
+2
View File
@@ -10,6 +10,7 @@ assignees: ''
### Environment
- xsystem35 version:
- OS:
- Game title:
### Steps to reproduce the behavior
1.
@@ -22,3 +23,4 @@ assignees: ''
<!-- If applicable, add screenshots to help explain your problem. -->
### Additional context
<!-- Note: Please do not post copyrighted game files. -->
+3 -3
View File
@@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Deps
run: sudo apt install ninja-build
@@ -15,14 +15,14 @@ jobs:
run: |
cd android
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > keystore.jks
ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk-bundle ./gradlew assembleRelease
JAVA_HOME=$JAVA_HOME_17_X64 ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk-bundle ./gradlew assembleRelease
env:
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: xsystem35-apk
path: android/app/build/outputs/apk/release/app-release.apk
+7 -7
View File
@@ -2,7 +2,7 @@ name: Emscripten Build
on: [push, pull_request]
env:
EM_VERSION: 3.1.34
EM_VERSION: latest
EM_CACHE_FOLDER: 'emsdk-cache'
jobs:
@@ -10,17 +10,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup cache
id: cache-system-libraries
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{env.EM_CACHE_FOLDER}}
key: ${{env.EM_VERSION}}-${{ runner.os }}
- name: Setup Emscripten toolchain
uses: mymindstorm/setup-emsdk@v12
uses: mymindstorm/setup-emsdk@v14
with:
version: ${{ env.EM_VERSION }}
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
@@ -29,13 +29,13 @@ jobs:
run: |
mkdir -p out/wasm
cd out/wasm
emcmake cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../../
make
emcmake cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_COMPILE_WARNING_AS_ERROR=YES ../../
make -j4
mkdir xsystem35
mv src/xsystem35.* xsystem35/
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: xsystem35-wasm
path: out/wasm/xsystem35
+3 -3
View File
@@ -10,19 +10,19 @@ jobs:
name: Linux ${{ matrix.build-type }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Deps
run: |
sudo apt update
sudo apt install libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libportmidi-dev libcjson-dev
sudo apt install libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libportmidi-dev libcjson-dev asciidoctor
- name: Build
run: |
mkdir -p out/${{ matrix.build-type }}
cd out/${{ matrix.build-type }}
cmake -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} ../../
make
make -j4
- name: Test
run: ctest --output-on-failure
+30 -16
View File
@@ -5,10 +5,19 @@ jobs:
build:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- { sys: MINGW32, installer: "xsystem35-32bit" }
- { sys: MINGW64, installer: "xsystem35-64bit" }
- sys: mingw32
package: "xsystem35-32bit"
cmake_args: "-DENABLE_DEBUGGER=no"
deps: ""
- sys: ucrt64
package: "xsystem35-64bit"
cmake_args: ""
deps: >-
cjson:p
portmidi:p
defaults:
run:
shell: msys2 {0}
@@ -19,27 +28,31 @@ jobs:
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.sys }}
update: true
pacboy: >-
gcc:p
cmake:p
ninja:p
SDL2:p
SDL2_ttf:p
SDL2_mixer:p
libwebp:p
cjson:p
nsis:p
ntldd-git:p
${{ matrix.deps }}
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Copy licenses
run: |
ls /${{ matrix.sys }}/share/licenses
mkdir dist
cp -r /${{ matrix.sys }}/share/licenses dist/
cp licenses/* dist/licenses/
- name: Install dev dependencies
run: pacboy --noconfirm -S --needed gcc:p cmake:p ninja:p asciidoctor:p
- name: Build
run: |
mkdir -p out/release
cd out/release
cmake -G"Ninja" -DCMAKE_BUILD_TYPE=Release ../../
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_COMPILE_WARNING_AS_ERROR=YES ${{ matrix.cmake_args }} ../../
ninja
- name: Test
@@ -47,11 +60,12 @@ jobs:
working-directory: out/release
- name: Package
working-directory: tools/installer
run: ./make-installer.sh ../../out/release ${{ matrix.installer }}.nsi
run: |
cp out/release/src/xsystem35.exe out/release/doc/*.html *.md COPYING xsys35rc.sample dist/
- name: Upload
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.installer }}
path: tools/installer/${{ matrix.installer }}.exe
name: ${{ matrix.package }}
path: dist
compression-level: 9 # because we use it for releases
+3
View File
@@ -1,10 +1,13 @@
out
android/.gradle
android/.idea
android/app/.cxx
android/app/.externalNativeBuild
android/app/build
android/app/src/main/assets
android/build
android/keystore.jks
android/local.properties
.ccls-cache
.dir-locals.el
compile_commands.json
+165
View File
@@ -0,0 +1,165 @@
# Changelog
## 2.17.0 - 2025-11-09
- Added "Streamer Mode" to mosaic specified (NSFW) images. This is enabled via the `-censor <file>` command-line option.
- Windows: Fixed an issue where Rance 5D could not save files if the `Save` directory did not exist.
## 2.16.1 - 2025-08-28
- Fixed text rendering issue in SACT log (#71)
- Windows: The 32-bit version no longer supports the portmidi MIDI backend
## 2.16.0 - 2025-06-13
- Fixed map tile color issue in Graymerca (#67)
- Windows: Implemented number input dialog for the `NI` command (#68)
- Android: Added "Clear Save Files" launcher menu command
## 2.15.1 - 2025-05-14
- Fixed a text rendering issue in Rance 5D (#66)
## 2.15.0 - 2025-04-21
- Fixed color palette bug introduced in v2.14.2.
- Fixed uncancellable message waiting mode.
- Android: "Install from ZIP" button is moved to the top-right option menu.
- Android: Improved extraction logic of track numbers from audio file names.
## 2.14.3 - 2025-04-01
- Fixed build for big endian architectures.
## 2.14.2 - 2025-03-09
- Android: Back button to exit the game (#50)
- Improved touch input usability in ママトト (#64)
## 2.14.1 - 2025-02-07
- Fixed font selection and text decoration not working in selection menus.
- Fixed a graphic issue in DALK intro.
## 2.14.0 - 2025-01-09
- New supported games: 俺の下であがけ and 楽園行.
- Windows: On Windows 10 version 1903 or above, now xsystem35 can handle
Japanese filenames correctly even if the system locale is not Japanese.
## 2.13.0 - 2024-12-07
- Windows: `Option` -> `Auto Copy Text to Clipboard` menu command has been added.
When enabled, in-game text will be copied to the clipboard automatically. This
can be used with text hooker tools that support clipboard monitoring.
## 2.12.1 - 2024-12-02
- Windows: Fixed missing DLL error (#60)
## 2.12.0 - 2024-11-26
- Implemented playback of the opening movie for 妻みぐい2.
## 2.11.7 - 2024-11-12
- Fixed crash when canceling menu with two-finger touch (#58)
- Fixed screen artifact in Rance 3 immediately after selecting "Game Start"
## 2.11.6 - 2024-07-22
- Fixed strange behavior when canceling the battle selection menu in Kichikuou Rance. (#56)
- Use system mouse cursors whenever possible. They look better on high dpi displays.
- Added manual page for the xsystem35 command.
## 2.11.5 - 2024-06-10
- Android: Fixed a black screen issue in the MangaGamer version of Rance 5D.
- Fixed `fileCheckExist` command. (#55)
## 2.11.4 - 2024-05-22
- Windows: In full-screen mode, the menu bar now appears only when the mouse pointer is at the top of the screen. (#53)
- Fixed text rendering issue in Rance 3 intro. (#54)
## 2.11.3 - 2024-04-11
- Android: Fixed a bug where save files from older versions could not be loaded in version 2.11.2.
## 2.11.2 - 2024-04-10
- Added `-savedir` option to specify save directory.
- Android: Fixed a bug where .xsys35rc in a subdirectory of ZIP was not loaded. (#51)
## 2.11.1 - 2024-02-18
- Windows: Fixed a black screen issue in the MangaGamer version of Rance 5D (#45).
- Fixed a crash bug in command-line debugger.
## 2.11.0 - 2024-01-20
- Windows: Now `xsystem35.exe` is a standalone executable. You can just copy it to the game folder and run it.
- Windows: The installer is no longer provided. If you have an earlier version installed, please uninstall it.
- Windows: The debugger is no longer available in the 32-bit version. Please use the 64-bit version if you need it.
- Added experimental `enable_zb` option (#44). See `xsys35rc.sample` for details.
## 2.10.1 - 2024-01-01
- Windows: Added "Integer Scaling" menu option
- Fixed initial palette colors (to match System3.9)
- Fixed a bug where palette 246 to 249 were unintentionally changed after loading 256-color CGs
## 2.10.0 - 2023-12-09
- Breaking change: A [bug](https://github.com/kichikuou/xsystem35-sdl2/issues/41) has been fixed in which save format for 大悪司 and かえるにょ国にょアリス was not compatible with System3.9. As a result, save files for these games created with older versions of xsystem35 are no longer usable. (Loading will not fail, but wrong values will be loaded.)
- Now the 64-bit executable supports Windows 10 or later. For older Windows, please use the 32-bit version.
- Fixed a problem with the download edition of Daiakuji requiring insertion of Disk 2. (#43)
- Debugger: Added debug commands for monitoring the color palette.
- Minor bug fixes.
## 2.9.1 - 2023-06-22
- Fixed a bug where the `CX 1` command (copy with transparent color) did not work in some games (e.g. Daiakuji)
- Debugger: Now breakpoints do not make the window completely unresponsive
- Debugger: Fixed a conditional breakpoint crash bug
## 2.9.0 - 2023-05-04
- Now xsystem35 uses the System3.9 save file format (unless `-saveformat` command line flag is specified). Old save files can still be loaded.
- Changed the default naming convention for save files from `[a-z]sleep.asd` to `<gamename>s[a-z].asd`.
- Fixed a bug where SACT games (e.g. Rance 5D) were not responding to touch.
- Fixed memory leaks in debugger.
## 2.8.0 - 2023-02-12
- Added support for Rance 4.1/4.2 ver1.05
- Fixed movement animation in rooms in Rance 4 v2.05 (#35)
- Added `-game` option which can be used to enable game-specific hacks in translated games
## 2.7.0 - 2023-01-28
- Added support for Rance4 ver.2.05
- Now supports BGM playback for the download edition of Daiakuji
- Bug fixes
## 2.6.0 - 2023-01-01
- Android: Introduced a new way to simulate right-click; tapping on the black bars at the left/right or top/bottom of the screen is treated as a right click. (Two-finger touch, the old way to simulate a right click, still works.)
- Windows: Added a menu command to enable/disable automatic mouse movements.
## 2.5.1 - 2022-07-31
- Implemented "palette shift" graphic effect (used in 闘神都市II).
- Implemented `grDrawFillCircle` command (used in グレイメルカ).
- Fixed color update bug in 256-color games.
- Fixed crash by out-of-bounds variable access in debugger.
## 2.5.0 - 2022-07-17
- Supported JPEG image format on Android.
## 2.4.0 - 2022-07-02
- Windows: Added "Restart" menu command.
- Fixed a bug where wrong music is played in Kichikuou Rance (System3.9 version). #32
- Supported mouse wheel input.
- Fixed a bug in `MF` command.
- Implemented `grEffectMoveView` command.
## 2.3.0 - 2022-04-08
- Code for screen transition effects have been substantially rewritten (but you probably wouldn't notice any difference).
- Fixed bugs in System3.9 games.
- Android: Enabled joystick input.
- Debugger improvements.
## 2.2.0 - 2021-12-03
From now on, the Android and Windows versions will use a common version number.
- Android: Use custom fonts specified in `.xsys35c`. (#20)
- Supported "王子さまLv1".
- Debugger improvements.
- Fixed some bugs and compatibility issues.
## 2.1.0 - 2021-11-07
- Fixed issues with MangaGamer version of Rance 5D.
- Fixed garbled text in some System3.9 games with Unicode mode.
- Display a message box on fatal errors.
- Various debugger improvements.
## 2.0.1 - 2021-10-24
- Fixed crash during shutdown.
## 2.0.0 - 2021-10-23
- Added window menubar from which you can save screenshots, change fullscreen mode, and enable message skipping.
- Added debugger support that can be used from Visual Studio Code. See [vscode-system3x](https://github.com/kichikuou/vscode-system3x) for details.
- Many bug fixes and compatibility fixes.
+115 -87
View File
@@ -1,18 +1,14 @@
cmake_minimum_required(VERSION 3.13)
cmake_minimum_required(VERSION 3.13...4.0)
project(xsystem35 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
enable_testing()
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
set(XSYSTEM35_VERSION "2.17.0")
include(CheckIncludeFile)
include(CheckLibraryExists)
include(CheckSymbolExists)
# In msys, `pkg-config --libs` returns `-lmingw32` but find_library() cannot
# find it in default search paths.
if (MSYS)
list(APPEND CMAKE_LIBRARY_PATH $ENV{MINGW_PREFIX}/$ENV{MINGW_CHOST}/lib)
endif ()
include(FetchContent)
# A wrapper around pkg_check_modules() that skips the check if ENABLE_<prefix> is false
macro (optional_pkg_check_modules prefix)
@@ -22,19 +18,73 @@ macro (optional_pkg_check_modules prefix)
endif()
endmacro()
# Generates a static library from pkg_check_modules() result
function(add_static_library name pkg)
add_library(${name} INTERFACE)
set_target_properties(${name}
PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${${pkg}_STATIC_INCLUDE_DIRS}"
INTERFACE_COMPILE_OPTIONS "${${pkg}_STATIC_CFLAGS_OTHER}"
INTERFACE_LINK_LIBRARIES "${${pkg}_STATIC_LIBRARIES}"
INTERFACE_LINK_OPTIONS "${${pkg}_STATIC_LDFLAGS_OTHER}")
endfunction()
function(fetch_webp)
FetchContent_Declare(
libwebp
URL https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.5.0.tar.gz
URL_HASH SHA1=b21aa842136dc59a72a38776a5aa73f4d0b00ac5
)
set(WEBP_BUILD_ANIM_UTILS OFF CACHE BOOL "Build animation utilities." FORCE)
set(WEBP_BUILD_CWEBP OFF CACHE BOOL "Build the cwebp command line tool." FORCE)
set(WEBP_BUILD_DWEBP OFF CACHE BOOL "Build the dwebp command line tool." FORCE)
set(WEBP_BUILD_GIF2WEBP OFF CACHE BOOL "Build the gif2webp conversion tool." FORCE)
set(WEBP_BUILD_IMG2WEBP OFF CACHE BOOL "Build the img2webp animation tool." FORCE)
set(WEBP_BUILD_VWEBP OFF CACHE BOOL "Build the vwebp viewer tool." FORCE)
set(WEBP_BUILD_WEBPINFO OFF CACHE BOOL "Build the webpinfo command line tool." FORCE)
set(WEBP_BUILD_LIBWEBPMUX OFF CACHE BOOL "Build the libwebpmux library." FORCE)
set(WEBP_BUILD_WEBPMUX OFF CACHE BOOL "Build the webpmux command line tool." FORCE)
set(WEBP_BUILD_EXTRAS OFF CACHE BOOL "Build extras." FORCE)
set(WEBP_BUILD_WEBP_JS OFF CACHE BOOL "Emscripten build of webp.js." FORCE)
FetchContent_MakeAvailable(libwebp)
add_library(WebP ALIAS webp)
endfunction()
check_symbol_exists(getlogin "unistd.h" HAVE_GETLOGIN)
check_symbol_exists(mmap "sys/mman.h" HAVE_MMAP)
check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
check_symbol_exists(uname "sys/utsname.h" HAVE_UNAME)
if (EMSCRIPTEN)
function(add_emscripten_library name option)
add_library(${name} INTERFACE)
set_target_properties(${name} PROPERTIES
INTERFACE_COMPILE_OPTIONS ${option}
INTERFACE_LINK_OPTIONS ${option})
endfunction()
add_emscripten_library(zlib -sUSE_ZLIB=1)
add_emscripten_library(sdl2 -sUSE_SDL=2)
add_emscripten_library(sdl2_ttf -sUSE_SDL_TTF=2)
set(DEFAULT_FONT_PATH /fonts/)
fetch_webp()
set(HAVE_WEBP 1)
elseif (ANDROID)
set(SDL2MIXER_FOUND 1)
find_library(ndk_zlib z)
add_library(sdl2 ALIAS SDL2)
add_library(sdl2_ttf ALIAS SDL2_ttf)
add_library(sdl2_mixer ALIAS SDL2_mixer)
find_library(ndk_log log)
else()
find_library(ndk_zlib z)
add_library(zlib INTERFACE)
set_target_properties(zlib PROPERTIES INTERFACE_LINK_LIBRARIES ${ndk_zlib})
fetch_webp()
set(HAVE_WEBP 1)
else() # non-emscripten, non-android
if (WIN32)
set(ZLIB_USE_STATIC_LIBS ON)
endif()
find_package(ZLIB REQUIRED)
add_library(zlib ALIAS ZLIB::ZLIB)
include(FindPkgConfig)
optional_pkg_check_modules(GTK3 IMPORTED_TARGET gtk+-3.0)
@@ -42,45 +92,70 @@ else()
set(ENABLE_GTK 1)
endif()
pkg_check_modules(SDL2 IMPORTED_TARGET sdl2)
pkg_check_modules(SDL2TTF IMPORTED_TARGET SDL2_ttf)
optional_pkg_check_modules(SDL2MIXER IMPORTED_TARGET SDL2_mixer)
pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2)
pkg_check_modules(SDL2TTF REQUIRED IMPORTED_TARGET SDL2_ttf)
pkg_check_modules(SDL2MIXER REQUIRED IMPORTED_TARGET SDL2_mixer)
if (WIN32)
add_static_library(sdl2 SDL2)
add_static_library(sdl2_ttf SDL2TTF)
# Workaround for linking error
set_property(TARGET sdl2_ttf PROPERTY INTERFACE_LINK_LIBRARIES
$<LINK_GROUP:RESCAN,${SDL2TTF_STATIC_LIBRARIES} -lstdc++>)
add_static_library(sdl2_mixer SDL2MIXER)
else()
add_library(sdl2 ALIAS PkgConfig::SDL2)
add_library(sdl2_ttf ALIAS PkgConfig::SDL2TTF)
add_library(sdl2_mixer ALIAS PkgConfig::SDL2MIXER)
set(DEFAULT_FONT_PATH ${CMAKE_INSTALL_PREFIX}/share/xsystem35/fonts/)
endif()
option(ENABLE_DEBUGGER "Enable built-in debugger" ON)
if (ENABLE_DEBUGGER)
pkg_check_modules(cJSON IMPORTED_TARGET libcjson)
if (NOT cJSON_FOUND)
if (cJSON_FOUND)
if (WIN32)
add_static_library(cJSON cJSON)
else ()
add_library(cJSON ALIAS PkgConfig::cJSON)
endif()
else ()
# libcjson-dev of Debian buster / Ubuntu 20.04 does not install pkgconfig files.
find_library(cJSON cjson)
if (NOT cJSON)
message(FATAL_ERROR "libcjson is required but not found.")
endif()
add_library(cJSON ALIAS ${cJSON})
endif()
endif()
optional_pkg_check_modules(WEBP IMPORTED_TARGET libwebp)
if (WEBP_FOUND)
set(HAVE_WEBP 1)
if (WIN32)
add_static_library(WebP WEBP)
else()
add_library(WebP ALIAS PkgConfig::WEBP)
endif()
endif()
find_library(PORTMIDI portmidi)
if (PORTMIDI)
set(HAVE_PORTMIDI 1)
set(ENABLE_MIDI_PORTMIDI 1)
if (WIN32)
optional_pkg_check_modules(PORTMIDI IMPORTED_TARGET portmidi)
if (PORTMIDI_FOUND)
set(HAVE_PORTMIDI 1)
add_static_library(portmidi_static PORTMIDI)
set(PORTMIDI portmidi_static)
endif()
else ()
find_library(PORTMIDI portmidi)
if (PORTMIDI)
set(HAVE_PORTMIDI 1)
endif()
endif()
set(DEFAULT_FONT_PATH ${CMAKE_INSTALL_PREFIX}/share/xsystem35/fonts/)
endif()
# Menu
if (EMSCRIPTEN)
set(SRC_MENU menu_emscripten.c)
elseif (ANDROID)
set(SRC_MENU menu_android.c)
elseif (ENABLE_GTK)
set(SRC_MENU menu.c menu_callback.c menu_gui.c s39init.c)
if (ENABLE_GTK)
# i18n support (currently only menus are translated)
include(FindIntl)
include(FindGettext)
@@ -90,87 +165,38 @@ elseif (ENABLE_GTK)
include_directories(${Intl_INCLUDE_DIRS})
link_libraries(${Intl_LIBRARIES})
endif()
else ()
set(SRC_MENU menu_sdl.c sdl_input.c)
endif()
# PCM audio
if (EMSCRIPTEN)
list(APPEND SRC_AUDIO)
list(APPEND SRC_AUDIO pcm.emscripten.c bgm.emscripten.c bgi.c)
list(APPEND SUMMARY_AUDIO "Emscripten")
elseif (SDL2MIXER_FOUND)
list(APPEND SRC_AUDIO pcm.sdlmixer.c bgm.sdlmixer.c bgi.c)
list(APPEND SUMMARY_AUDIO "SDL_mixer")
set(ENABLE_SDLMIXER 1)
else()
list(APPEND SRC_AUDIO pcm.dummy.c bgm.dummy.c)
list(APPEND SUMMARY_AUDIO "SDL_mixer")
endif()
# CDROM
list(APPEND SRC_CDROM cdrom.bgm.c)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
list(APPEND SRC_CDROM cdrom.Linux.c)
list(APPEND SUMMARY_CDROM "Linux ioctl")
set(ENABLE_CDROM_LINUX 1)
elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
list(APPEND SRC_CDROM cdrom.FreeBSD.c)
list(APPEND SUMMARY_CDROM "*BSD ioctl")
set(ENABLE_CDROM_BSD 1)
elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
list(APPEND SRC_CDROM cdrom.emscripten.c)
if (EMSCRIPTEN)
list(APPEND SUMMARY_CDROM "Emscripten")
set(ENABLE_CDROM_EMSCRIPTEN 1)
else()
list(APPEND SRC_CDROM cdrom.empty.c)
endif()
if (SDL2MIXER_FOUND)
list(APPEND SRC_CDROM cdrom.mp3.c)
list(APPEND SUMMARY_CDROM "SDL_mixer (wav|mp3|ogg...)")
set(ENABLE_CDROM_MP3 1)
endif()
set(CDROM_DEVICE "playlist.txt" CACHE STRING "CDROM Device Name")
set(DEFAULT_PLAYLIST_PATH "playlist.txt" CACHE STRING "Default playlist path")
# MIDI
if (EMSCRIPTEN)
list(APPEND SRC_MIDI midi.emscripten.c)
list(APPEND SUMMARY_MIDI "Emscripten")
elseif (ANDROID)
list(APPEND SRC_MIDI midi.android.c)
list(APPEND SUMMARY_MIDI "Android")
else()
if (HAVE_SIGACTION)
list(APPEND SRC_MIDI midi.rawmidi.c midifile.c)
list(APPEND SUMMARY_MIDI "raw")
set(MIDI_DEVICE "/dev/midi" CACHE STRING "midi device")
set(ENABLE_MIDI_RAWMIDI 1)
endif()
list(APPEND SUMMARY_MIDI "SDL_mixer")
set(ENABLE_MIDI_SDLMIXER 1)
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 (SDL2MIXER_FOUND)
list(APPEND SRC_MIDI midi.sdlmixer.c)
list(APPEND SUMMARY_MIDI "SDL_mixer")
set(ENABLE_MIDI_SDLMIXER 1)
endif()
if (HAVE_PORTMIDI AND ENABLE_MIDI_PORTMIDI)
list(APPEND SRC_MIDI midi.portmidi.c)
if (HAVE_PORTMIDI)
list(APPEND SUMMARY_MIDI "PortMidi")
set(ENABLE_MIDI_PORTMIDI 1)
endif()
endif()
@@ -193,12 +219,14 @@ message("------------------")
set(PACKAGE ${PROJECT_NAME})
configure_file(config.h.in config.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_compile_definitions(HAVE_CONFIG_H)
add_compile_definitions($<$<CONFIG:Debug>:DEBUG>)
add_subdirectory(src)
add_subdirectory(tools)
add_subdirectory(fonts)
if (NOT ANDROID AND NOT EMSCRIPTEN)
add_subdirectory(doc)
endif()
if (ENABLE_NLS)
add_subdirectory(po)
endif()
+87 -52
View File
@@ -3,22 +3,22 @@
This is a multi-platform port of `xsystem35`, a free implementation of
AliceSoft's System 3.x game engine.
## Compatiblity
## Compatibility
See the [game compatibility table](game_compatibility.md) for a list of games
that can be played on xsystem35-sdl2.
that can be played with xsystem35-sdl2.
## Unique Features
In addition to the original System 3.x's functionalities, xsystem35-sdl2 has
the following features.
In addition to the original System 3.x functionalities, xsystem35-sdl2 offers
the following features:
### Playing audio files as fake CD music
### Playing Audio Files as Virtual CD Music
Many System 3.x games had music as audio tracks on the CD-ROM. Xsystem35 can
play music from audio files instead, to avoid the hassle of inserting CDs. To
use ripped audio files, create a file named `playlist.txt` in the game
directory, and enter the paths to your tracks, one per line. For example:
Many System 3.x games feature music as audio tracks on the CD-ROM. xsystem35
can play music from audio files, eliminating the need to insert CDs. To use
ripped audio files, create a file named `playlist.txt` in the game directory
and list the paths to your tracks, one per line. For example:
```
# The first line is not used
@@ -27,89 +27,124 @@ BGM/track03.mp3
...
```
The first line is not used, because track 1 of game CD is usually a data track.
The first line is not used because the first track on a game CD is typically a
data track.
### Unicode translation support
Some games have integrated music as MIDI. In such cases, the music won't play
using the virtual CD feature. If you encounter a `Cannot load MIDI` error
message, you might need to set the `SDL_SOUNDFONTS` environment variable to
point to an `.sf2` file. For example:
The original System 3.x only supported Shift_JIS (a Japanese character
encoding), but xsystem35 supports Unicode and is able to run games translated
into languages other than Japanese and English.
```
SDL_SOUNDFONTS=/usr/share/soundfonts/GeneralUser.sf2 xsystem35
```
See [xsys35c](https://github.com/kichikuou/xsys35c)'s document for how to
build a game with Unicode mode.
### Unicode Translation Support
While the original System 3.x only supported Shift_JIS (a Japanese character
encoding), xsystem35 supports Unicode and can run games translated into
languages other than Japanese and English.
For instructions on how to build a game with Unicode support, see the
[xsys35c](https://github.com/kichikuou/xsys35c) documentation.
### Debugging
Xsystem35 has a built-in debugger that allows you to step through the game and
examine / modify variables in the game. There are two ways to use the debugger:
xsystem35 features a built-in debugger that allows you to step through the game
and examine or modify game variables. There are two ways to use the debugger:
- Through [Visual Studio Code](https://code.visualstudio.com/) (recommended):
The [vscode-system3x](https://github.com/kichikuou/vscode-system3x) extension
provides graphical debugging interface for System 3.x.
- Using CUI debugger: Running xsystem35 with `-debug` option will start the
debugger with console interface. Type `help` to see a list of available
commands.
provides a graphical debugging interface for System 3.x.
- Using the CLI Debugger: Running xsystem35 with the `-debug` option will
launch the debugger with a console interface. Type `help` to see a list of
available commands.
## Installing
### Streamer Mode
xsystem35 introduces a "Streamer Mode" to make playing games with NSFW content
safer for streaming or public viewing. When enabled with the `-censor <file>`
option, images specified in the provided file will be automatically mosaiced.
The `misc/censor/` directory contains example censor list files for some games.
## Installation
Prebuilt packages for Windows and Android can be downloaded from the
[Releases](https://github.com/kichikuou/xsystem35-sdl2/releases) page. For
other platforms, see the [Building](#building) section.
[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
Execute `xsytem35`, and it will show a dialog to select a folder. Select the
game folder (where the ALD files are located).
Copy `xsystem35.exe` to the game folder and run it.
### Android
See [android/README.md](https://github.com/kichikuou/xsystem35-sdl2/blob/master/android/README.md#use).
See [android/README.md](android/README.md#usage).
### Other Platforms
Run xsystem35 from within the game directory.
cd /path/to/game_directory
xsystem35
```bash
$ cd /path/to/game_directory
$ xsystem35
```
See [xsystem35 command manual](doc/xsystem35.6.adoc) for detailed usage.
## Building
### Linux (Debian / Ubuntu)
$ sudo apt install build-essential cmake libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libcjson-dev
$ mkdir -p out/debug
$ cd out/debug
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
$ make && make install
```bash
$ sudo apt install build-essential cmake libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libportmidi-dev libcjson-dev asciidoctor
$ mkdir -p out/debug
$ cd out/debug
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
$ make && make install
```
### MacOS
[Homebrew](https://brew.sh/index_ja) is needed.
[Homebrew](https://brew.sh/) is required.
$ brew install cmake pkg-config sdl2 sdl2_mixer sdl2_ttf webp cjson
$ mkdir -p out/debug
$ cd out/debug
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
$ make && make install
```bash
$ brew install cmake pkg-config sdl2 sdl2_mixer sdl2_ttf webp portmidi cjson asciidoctor
$ mkdir -p out/debug
$ cd out/debug
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
$ make && make install
```
### Windows
[MSYS2](https://www.msys2.org) is needed.
[MSYS2](https://www.msys2.org) is required.
$ pacman -S cmake mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2_ttf mingw-w64-x86_64-SDL2_mixer mingw-w64-x86_64-libwebp mingw-w64-x86_64-cjson
$ mkdir -p out/debug
$ cd out/debug
$ cmake -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug ../../
$ make
```bash
$ pacman -S cmake mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-SDL2 mingw-w64-ucrt-x86_64-SDL2_ttf mingw-w64-ucrt-x86_64-SDL2_mixer mingw-w64-ucrt-x86_64-libwebp mingw-w64-ucrt-x86_64-portmidi mingw-w64-ucrt-x86_64-cjson
$ mkdir -p out/debug
$ cd out/debug
$ cmake -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug ../../
$ make
```
### Emscripten
$ mkdir -p out/wasm
$ cd out/wasm
$ emcmake cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../../
$ make
```bash
$ mkdir -p out/wasm
$ cd out/wasm
$ emcmake cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../../
$ make
```
To use the generated binary, checkout
To use the generated binary, check out
[Kichikuou on Web](https://github.com/kichikuou/web) and copy `out/xsystem35.*`
into its `docs` directory.
+50 -36
View File
@@ -1,20 +1,57 @@
# xsystem35 for Android
## Download
Prebuilt APKs are [here](https://github.com/kichikuou/xsystem35-sdl2/releases).
Minimum supported Android version: 5.0
## Build
Prerequisites:
- Android SDK >=28
- Android NDK >=r15c
## Download
You can download prebuilt APKs
[here](https://github.com/kichikuou/xsystem35-sdl2/releases).
## Usage
### Basic Usage
1. Create a ZIP file containing all the game files and BGM files (see
[below](#preparing-a-zip) for details), and transfer it to your device.
2. Open the app. Tap the option menu (three dots in the top right corner) and
select "Install from ZIP".
3. Select the ZIP file you created in step 1.
4. The game will start. To simulate a right-click, tap the black bars on either
the left or right, or top or bottom of the screen.
### Preparing a ZIP
- Include all files from the `GAMEDATA` folder (such as `.ALD` files and
others). `.EXE` and `.DLL` files are not necessary, but you can include them
if you want.
- Music files (`.mp3`, `.ogg`, or `.wav`) whose filenames have a number either
at the beginning or just before the extension are recognized as BGM files.
For example:
- `Track2.mp3`
- `15.ogg`
- `02 - Title.mp3`
- `rance4_03.wav` (Note: The filename shouldn't be `rance403.wav`, as it
would be treated as the 403rd track.)
Note: This ZIP format is also compatible with
[Kichikuou on Web](http://kichikuou.github.io/web/).
### Miscellaneous
- You can export or import save files via the game list's option menu.
- To uninstall a game, long-tap its title in the game list.
## Known Issues
- Android versions older than 7.0 cannot handle ZIP files containing Shift-JIS
filenames. This issue occurs with some ZIP files distributed on
[retroc.net](http://retropc.net/alice/). If you encounter the error message
"This type of ZIP is not supported," unzip the file on your PC and re-archive
it using modern ZIP creation software.
## Building from Source
### Using Android Studio
Open this directory as an Android Studio project.
### Command line build
Configure environment variables and run the `gradlew` script in this folder.
### Command Line Build
Set environment variables and run the `gradlew` script in this directory.
Example build instructions (for Debian bullseye):
Example build instructions (for Debian bookworm):
```sh
# Install necessary packages
sudo apt install git wget unzip default-jdk-headless ninja-build
@@ -22,38 +59,15 @@ sudo apt install git wget unzip default-jdk-headless ninja-build
# Install Android SDK / NDK
export ANDROID_SDK_ROOT=$HOME/android-sdk
mkdir -p $ANDROID_SDK_ROOT/cmdline-tools
wget https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip
unzip commandlinetools-linux-8512546_latest.zip -d $ANDROID_SDK_ROOT/cmdline-tools
wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
unzip commandlinetools-linux-11076708_latest.zip -d $ANDROID_SDK_ROOT/cmdline-tools
mv $ANDROID_SDK_ROOT/cmdline-tools/cmdline-tools $ANDROID_SDK_ROOT/cmdline-tools/tools
yes |$ANDROID_SDK_ROOT/cmdline-tools/tools/bin/sdkmanager --licenses
yes | $ANDROID_SDK_ROOT/cmdline-tools/tools/bin/sdkmanager --licenses
$ANDROID_SDK_ROOT/cmdline-tools/tools/bin/sdkmanager ndk-bundle 'cmake;3.22.1'
export ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk-bundle
# Check out and build xsystem35
# Clone and build xsystem35
git clone https://github.com/kichikuou/xsystem35-sdl2.git
cd xsystem35-sdl2/android
./gradlew build # or ./gradlew installDebug if you have a connected device
```
## Use
### Basic Usage
1. Create a ZIP file containing all the game files and BGM files (see [below](#preparing-a-zip) for details), and transfer it to your device.
2. Open the app. A list of installed games is displayed. Since nothing has been installed yet, only the "Install from ZIP" button is displayed. Tap it.
3. Select the ZIP file you created in 1.
4. The game starts. To simulate right-click, tap the black bars on the left/right or top/bottom of the screen.
### Preparing a ZIP
- Include all files in the `GAMEDATA` folder (`.ALD` files and others). `.EXE` and `.DLL` are not really needed, but you can include them as well.
- Music files (`.mp3`, `.ogg` or `.wav`) whose file names end with a number are recognized as BGM files. For example:
- `Track2.mp3`
- `15.ogg`
- `rance4_03.wav` (This shouldn't be `rance403.wav`, because it would be treated as the 403rd track)
Note: This form of ZIP can be used in [Kichikuou on Web](http://kichikuou.github.io/web/) as well.
### Miscellaneous
- You can export / import saved files using the option menu of the game list.
- To uninstall a game, long-tap the title in the game list.
## Known Issues
- Android versions older than 7.0 cannot handle ZIPs containing Shift-JIS file names. This is the case with some ZIPs distributed on [retroc.net](http://retropc.net/alice/). If you get the error "This type of ZIP is not supported.", unzip the ZIP file on your PC and re-archive it with a modern ZIP creation software.
+14 -12
View File
@@ -9,18 +9,18 @@ else {
apply plugin: 'kotlin-android'
android {
compileSdkVersion 31
if (buildAsApplication) {
namespace "io.github.kichikuou.xsystem35"
}
compileSdkVersion 34
defaultConfig {
if (buildAsApplication) {
applicationId "io.github.kichikuou.xsystem35"
}
minSdkVersion 19
targetSdkVersion 31
versionCode 15
versionName "2.9.1" + gitRevision()
minSdkVersion 21
targetSdkVersion 34
versionCode 36
versionName "2.17.0" + gitRevision()
externalNativeBuild {
cmake {
arguments "-DANDROID_APP_PLATFORM=android-16", "-DANDROID_STL=c++_static"
arguments "-DANDROID_APP_PLATFORM=android-19", "-DANDROID_STL=c++_static"
// abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
@@ -38,7 +38,9 @@ android {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
if (rootProject.file('keystore.jks').exists()) {
signingConfig signingConfigs.release
}
}
}
applicationVariants.all { variant ->
@@ -62,10 +64,10 @@ android {
}
}
lintOptions {
lint {
abortOnError false
}
if (buildAsLibrary) {
libraryVariants.all { variant ->
variant.outputs.each { output ->
+24 -34
View File
@@ -1,50 +1,39 @@
cmake_minimum_required(VERSION 3.13)
cmake_minimum_required(VERSION 3.14)
project(GAME)
set(PROJECT_ROOT_DIR ../../..)
# Compilation of SDL and companion libraries
include(FetchContent)
FetchContent_Declare(
SDL
URL https://github.com/libsdl-org/SDL/releases/download/release-2.26.1/SDL2-2.26.1.tar.gz
URL_HASH SHA1=08a8cec21ffcebf44e4633a786d594a7811100d2
URL https://github.com/libsdl-org/SDL/releases/download/release-2.32.10/SDL2-2.32.10.tar.gz
URL_HASH SHA1=ce98fa93e31836a751feca374ab28a0770b63c16
)
FetchContent_Declare(
SDL_ttf
URL https://github.com/libsdl-org/SDL_ttf/releases/download/release-2.20.1/SDL2_ttf-2.20.1.tar.gz
URL_HASH SHA1=f774ff407915ae4afa3d03e5a9395283d9090f28
URL https://github.com/libsdl-org/SDL_ttf/releases/download/release-2.22.0/SDL2_ttf-2.22.0.tar.gz
URL_HASH SHA1=da5e86b601ad299a697878fab1af6f3be47b529d
)
FetchContent_Declare(
SDL_mixer
URL https://github.com/libsdl-org/SDL_mixer/releases/download/release-2.6.2/SDL2_mixer-2.6.2.tar.gz
URL_HASH SHA1=036fc7839a6b8dc1af3dbfed4e2531224bbacdd7
URL https://github.com/libsdl-org/SDL_mixer/releases/download/release-2.8.0/SDL2_mixer-2.8.0.tar.gz
URL_HASH SHA1=a58c69f9d00e44833b9e00e1adb58d85759ca499
)
# Compilation of SDL and companion libraries
FetchContent_GetProperties(SDL)
if(NOT sdl_POPULATED)
FetchContent_Populate(SDL)
add_subdirectory(${sdl_SOURCE_DIR} ${sdl_BINARY_DIR})
endif()
FetchContent_GetProperties(SDL_ttf)
if(NOT sdl_ttf_POPULATED)
FetchContent_Populate(SDL_ttf)
set(SDL2TTF_SAMPLES OFF CACHE BOOL "Build the SDL2_ttf sample program(s)" FORCE)
set(SDL2TTF_INSTALL OFF CACHE BOOL "Enable SDL2_ttf install target" FORCE)
set(SDL2TTF_VENDORED ON CACHE BOOL "Use vendored third-party libraries" FORCE)
add_subdirectory(${sdl_ttf_SOURCE_DIR} ${sdl_ttf_BINARY_DIR})
endif()
FetchContent_GetProperties(SDL_mixer)
if(NOT sdl_mixer_POPULATED)
FetchContent_Populate(SDL_mixer)
set(SDL2MIXER_OPUS OFF CACHE BOOL "Enable Opus music" FORCE)
set(SDL2MIXER_FLAC OFF CACHE BOOL "Enable FLAC music" FORCE)
set(SDL2MIXER_MOD OFF CACHE BOOL "Support loading MOD music" FORCE)
set(SDL2MIXER_MIDI OFF CACHE BOOL "Enable MIDI music" FORCE)
set(SDL2MIXER_SAMPLES OFF CACHE BOOL "Build the SDL2_mixer sample program(s)" FORCE)
set(SDL2MIXER_INSTALL OFF CACHE BOOL "Enable SDL2_mixer install target" FORCE)
add_subdirectory(${sdl_mixer_SOURCE_DIR} ${sdl_mixer_BINARY_DIR})
endif()
set(SDL2TTF_SAMPLES OFF CACHE BOOL "Build the SDL2_ttf sample program(s)" FORCE)
set(SDL2TTF_INSTALL OFF CACHE BOOL "Enable SDL2_ttf install target" FORCE)
set(SDL2TTF_VENDORED ON CACHE BOOL "Use vendored third-party libraries" FORCE)
set(SDL2MIXER_OPUS OFF CACHE BOOL "Enable Opus music" FORCE)
set(SDL2MIXER_FLAC OFF CACHE BOOL "Enable FLAC music" FORCE)
set(SDL2MIXER_MOD OFF CACHE BOOL "Support loading MOD music" FORCE)
set(SDL2MIXER_MIDI OFF CACHE BOOL "Enable MIDI music" FORCE)
set(SDL2MIXER_WAVPACK OFF CACHE BOOL "Enable WavPack music" FORCE)
set(SDL2MIXER_SAMPLES OFF CACHE BOOL "Build the SDL2_mixer sample program(s)" FORCE)
set(SDL2MIXER_INSTALL OFF CACHE BOOL "Enable SDL2_mixer install target" FORCE)
FetchContent_MakeAvailable(SDL SDL_ttf SDL_mixer)
# The main CMakeLists.txt of xsystem35
add_subdirectory(${PROJECT_ROOT_DIR} xsystem35)
@@ -55,8 +44,9 @@ file(MAKE_DIRECTORY ${ASSETS_DIR}/licenses)
file(COPY_FILE ${PROJECT_ROOT_DIR}/fonts/MTLc3m.ttf ${ASSETS_DIR}/MTLc3m.ttf)
file(COPY_FILE ${PROJECT_ROOT_DIR}/fonts/mincho.otf ${ASSETS_DIR}/mincho.otf)
file(COPY_FILE ${PROJECT_ROOT_DIR}/COPYING ${ASSETS_DIR}/licenses/xsystem35)
file(COPY_FILE ${PROJECT_ROOT_DIR}/fonts/MTLc3m.ttf.license ${ASSETS_DIR}/licenses/MTLc3m)
file(COPY_FILE ${PROJECT_ROOT_DIR}/fonts/mincho.otf.license ${ASSETS_DIR}/licenses/mincho)
file(COPY_FILE ${PROJECT_ROOT_DIR}/licenses/MTLc3m.txt ${ASSETS_DIR}/licenses/MTLc3m)
file(COPY_FILE ${PROJECT_ROOT_DIR}/licenses/mincho.txt ${ASSETS_DIR}/licenses/mincho)
file(COPY_FILE ${PROJECT_ROOT_DIR}/licenses/nanojpeg.txt ${ASSETS_DIR}/licenses/nanojpeg)
file(COPY_FILE ${sdl_SOURCE_DIR}/LICENSE.txt ${ASSETS_DIR}/licenses/SDL)
file(COPY_FILE ${sdl_ttf_SOURCE_DIR}/LICENSE.txt ${ASSETS_DIR}/licenses/SDL_ttf)
file(COPY_FILE ${sdl_ttf_SOURCE_DIR}/external/freetype/docs/GPLv2.TXT ${ASSETS_DIR}/licenses/freetype)
+81
View File
@@ -15,3 +15,84 @@
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLInputConnection {
void nativeCommitText(java.lang.String, int);
void nativeGenerateScancodeForUnichar(char);
}
-keep,includedescriptorclasses class org.libsdl.app.SDLActivity {
# for some reason these aren't compatible with allowoptimization modifier
boolean supportsRelativeMouse();
void setWindowStyle(boolean);
}
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLActivity {
java.lang.String nativeGetHint(java.lang.String); # Java-side doesn't use this, so it gets minified, but C-side still tries to register it
boolean onNativeSoftReturnKey();
void onNativeKeyboardFocusLost();
boolean isScreenKeyboardShown();
android.util.DisplayMetrics getDisplayDPI();
java.lang.String clipboardGetText();
boolean clipboardHasText();
void clipboardSetText(java.lang.String);
int createCustomCursor(int[], int, int, int, int);
void destroyCustomCursor(int);
android.content.Context getContext();
boolean getManifestEnvironmentVariables();
android.view.Surface getNativeSurface();
void initTouch();
boolean isAndroidTV();
boolean isChromebook();
boolean isDeXMode();
boolean isTablet();
void manualBackButton();
int messageboxShowMessageBox(int, java.lang.String, java.lang.String, int[], int[], java.lang.String[], int[]);
void minimizeWindow();
int openURL(java.lang.String);
void requestPermission(java.lang.String, int);
int showToast(java.lang.String, int, int, int, int);
boolean sendMessage(int, int);
boolean setActivityTitle(java.lang.String);
boolean setCustomCursor(int);
void setOrientation(int, int, boolean, java.lang.String);
boolean setRelativeMouseEnabled(boolean);
boolean setSystemCursor(int);
boolean shouldMinimizeOnFocusLoss();
boolean showTextInput(int, int, int, int);
}
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.HIDDeviceManager {
boolean initialize(boolean, boolean);
boolean openDevice(int);
int sendOutputReport(int, byte[]);
int sendFeatureReport(int, byte[]);
boolean getFeatureReport(int, byte[]);
void closeDevice(int);
}
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLAudioManager {
int[] getAudioOutputDevices();
int[] getAudioInputDevices();
int[] audioOpen(int, int, int, int, int);
void audioWriteFloatBuffer(float[]);
void audioWriteShortBuffer(short[]);
void audioWriteByteBuffer(byte[]);
void audioClose();
int[] captureOpen(int, int, int, int, int);
int captureReadFloatBuffer(float[], boolean);
int captureReadShortBuffer(short[], boolean);
int captureReadByteBuffer(byte[], boolean);
void captureClose();
void audioSetThreadPriority(boolean, int);
native int nativeSetupJNI();
native void removeAudioDevice(boolean, int);
native void addAudioDevice(boolean, int);
}
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLControllerManager {
void pollInputDevices();
void pollHapticDevices();
void hapticRun(int, float, int);
void hapticStop(int);
}
+1 -2
View File
@@ -4,7 +4,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="io.github.kichikuou.xsystem35"
android:installLocation="auto">
<!-- OpenGL ES 2.0 -->
@@ -81,7 +80,7 @@
android:label="@string/app_name"
android:alwaysRetainTaskState="true"
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:theme="@style/AppTheme"
android:hardwareAccelerated="true"
>
@@ -30,9 +30,11 @@ import java.io.IOException
// Intent for this activity must have the following extra:
// - EXTRA_GAME_ROOT (string): A path to the game installation.
// - EXTRA_SAVE_DIRECTORY (string): A path to the save data directory.
class GameActivity : SDLActivity() {
companion object {
const val EXTRA_GAME_ROOT = "GAME_ROOT"
const val EXTRA_SAVE_DIRECTORY = "SAVE_DIRECTORY"
const val EXTRA_ARCHIVE_NAME = "ARCHIVE_NAME"
}
@@ -61,7 +63,7 @@ class GameActivity : SDLActivity() {
override fun getArguments(): Array<String> {
return arrayOf(
"-gamedir", intent.getStringExtra(EXTRA_GAME_ROOT)!!,
"-devcd", Launcher.PLAYLIST_FILE)
"-savedir", intent.getStringExtra(EXTRA_SAVE_DIRECTORY)!!)
}
override fun setTitle(title: CharSequence?) {
@@ -25,9 +25,7 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.*
import java.lang.StringBuilder
import java.nio.charset.Charset
import java.util.*
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
@@ -41,13 +39,13 @@ interface LauncherObserver {
fun onInstallFailure(msgId: Int)
}
private const val SAVE_DIR = "save"
class Launcher private constructor(private val rootDir: File) {
companion object {
const val SAVE_DIR = "save"
const val TITLE_FILE = "title.txt"
const val PLAYLIST_FILE = "playlist2.txt"
const val OLD_PLAYLIST_FILE = "playlist.txt"
const val GAMEDIR_FILE = "game_directory.txt"
const val PLAYLIST_FILE = "playlist.txt"
const val OLD_PLAYLIST_FILE = "playlist2.txt"
fun getInstance(rootDir: File): Launcher {
if (gLauncher == null) {
@@ -79,14 +77,14 @@ class Launcher private constructor(private val rootDir: File) {
isInstalling = true
GlobalScope.launch(Dispatchers.Main) {
try {
withContext(Dispatchers.IO) {
val gameDir = withContext(Dispatchers.IO) {
extractFiles(input, dir) { msg ->
GlobalScope.launch(Dispatchers.Main) {
observer?.onInstallProgress(msg)
}
}
}
observer?.onInstallSuccess(dir, archiveName)
observer?.onInstallSuccess(gameDir, archiveName)
} catch (e: InstallFailureException) {
observer?.onInstallFailure(e.msgId)
} catch (e: Exception) {
@@ -114,9 +112,11 @@ class Launcher private constructor(private val rootDir: File) {
continue
}
try {
val titleFile = File(path, TITLE_FILE)
val gameDirFile = File(path, GAMEDIR_FILE)
val gamePath = if (gameDirFile.exists()) File(path, gameDirFile.readText()) else path
val titleFile = File(gamePath, TITLE_FILE)
val title = titleFile.readText()
games.add(Entry(path, title, titleFile.lastModified()))
games.add(Entry(gamePath, title, titleFile.lastModified()))
migratePlaylist(path)
} catch (e: IOException) {
// Incomplete game installation. Delete it.
@@ -127,6 +127,7 @@ class Launcher private constructor(private val rootDir: File) {
if (!saveDirFound) {
File(rootDir, SAVE_DIR).mkdir()
}
observer?.onGameListChange()
}
private fun createDirForGame(): File {
@@ -179,7 +180,7 @@ class Launcher private constructor(private val rootDir: File) {
}
}
private fun extractFiles(input: InputStream, outDir: File, progressCallback: (String) -> Unit) {
private fun extractFiles(input: InputStream, outDir: File, progressCallback: (String) -> Unit): File {
val configWriter = GameConfigWriter()
val hadDecodeError = forEachZipEntry(input) { zipEntry, zip ->
Log.i("extractFiles", zipEntry.name)
@@ -193,92 +194,73 @@ class Launcher private constructor(private val rootDir: File) {
}
configWriter.maybeAdd(zipEntry.name)
}
if (!configWriter.readyToWrite()) {
if (!configWriter.ready) {
if (hadDecodeError)
throw InstallFailureException(R.string.unsupported_zip)
throw InstallFailureException(R.string.cannot_find_ald)
}
configWriter.write(outDir)
return configWriter.gameDir?.let { File(outDir, it) } ?: outDir
}
// Xsystem35-sdl2 <=2.2.0 had a bug where playlist had an extra empty line at
// the beginning of the file. This migrates playlist.txt created by an old
// version of xsystem35-sdl2 to playlist2.txt.
// Xsystem35-sdl2 2.3.0 - 2.11.1 used playlist2.txt. Rename it to playlist.txt.
private fun migratePlaylist(dir: File) {
val oldPlaylist = File(dir, OLD_PLAYLIST_FILE)
if (!oldPlaylist.exists())
return
var tracks = oldPlaylist.readLines()
if (tracks.isNotEmpty())
tracks = tracks.subList(1, tracks.size)
File(dir, PLAYLIST_FILE).writeText(tracks.joinToString("\n"))
oldPlaylist.delete()
if (oldPlaylist.exists()) {
oldPlaylist.renameTo(File(dir, PLAYLIST_FILE))
}
}
class InstallFailureException(val msgId: Int) : Exception()
// A helper class which generates xsystem35.gr and playlist.txt in the game root directory.
// A helper class which generates GAMEDIR_FILE and PLAYLIST_FILE.
private class GameConfigWriter {
private val grb = StringBuilder()
private var basename: String? = null
private val aldRegex = """(.*?)([a-z])([a-z])\.(ald|wai|bgi)""".toRegex(RegexOption.IGNORE_CASE)
private val aldType = mapOf(
"b" to "BGM",
"d" to "Data",
"g" to "Graphics",
"m" to "Midi",
"r" to "Resource",
"s" to "Scenario",
"w" to "Wave")
private val specialResources = mapOf(
"system39.ain" to "Ain",
"system39.ini" to "Init",
"sactefam.kld" to "SACT01"
)
private val audioRegex = """.*?(\d+)\.(wav|mp3|ogg)""".toRegex(RegexOption.IGNORE_CASE)
var ready = false
private set
var gameDir: String? = null
private set
private val aldRegex = """.*?s[a-z]\.ald""".toRegex(RegexOption.IGNORE_CASE)
private val audioRegex = """((\d+).*|.*?(\d+))\.(wav|mp3|ogg)""".toRegex(RegexOption.IGNORE_CASE)
private val audioFiles: Array<String?> = arrayOfNulls(100)
fun maybeAdd(path: String) {
val name = File(path).name
specialResources[name.lowercase(Locale.US)]?.let {
grb.appendLine("$it $path")
return
}
aldRegex.matchEntire(name)?.let {
val ext = it.groupValues[4].uppercase(Locale.US)
val type = if (ext == "ALD") {
aldType[it.groupValues[2].lowercase(Locale.US)]
} else {
ext
}
val id = it.groupValues[3].uppercase(Locale.US)
if (type != null) {
grb.appendLine("$type$id $path")
basename = it.groupValues[1]
}
gameDir = File(path).parent
ready = true
}
audioRegex.matchEntire(name)?.let {
val track = it.groupValues[1].toInt()
val track = it.groupValues[2].toIntOrNull() ?: it.groupValues[3].toInt()
if (0 < track && track <= audioFiles.size)
audioFiles[track - 1] = path
}
}
fun readyToWrite() = basename != null
fun write(outDir: File) {
for (id in 'A' .. 'Z') {
grb.appendLine("Save$id ../save/${basename}s${id.lowercase(Locale.US)}.asd")
// Generate GAMEDIR_FILE
gameDir?.let {
File(outDir, GAMEDIR_FILE).writeText(it)
}
// Generate PLAYLIST_FILE
val absGameDir = gameDir?.let { File(outDir, it) } ?: outDir
val playlistFile = File(absGameDir, PLAYLIST_FILE)
if (!playlistFile.exists()) {
val prefixToRemove = gameDir?.let { "$it/" } ?: ""
val playlist = audioFiles.joinToString("\n") {
it?.removePrefix(prefixToRemove) ?: ""
}.trimEnd('\n')
playlistFile.writeText(playlist)
}
val gr = grb.toString()
Log.i("xsystem35.gr", gr)
File(outDir, "xsystem35.gr").writeText(gr)
val playlist = audioFiles.joinToString("\n") { it ?: "" }.trimEnd('\n')
File(outDir, PLAYLIST_FILE).writeText(playlist)
}
}
fun clearSaveData(): Boolean {
var success = true
File(rootDir, SAVE_DIR).listFiles()?.forEach { file ->
if (!file.deleteRecursively()) success = false
}
return success
}
}
private fun forEachZipEntry(input: InputStream, action: (ZipEntry, ZipInputStream) -> Unit): Boolean {
@@ -22,6 +22,7 @@ import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.OpenableColumns
import android.text.Html
import android.util.Log
import android.view.Menu
import android.view.MenuItem
@@ -53,6 +54,8 @@ class LauncherActivity : Activity(), LauncherObserver {
onGameListChange()
val listView = findViewById<ListView>(R.id.list)
listView.emptyView = findViewById(R.id.empty)
findViewById<TextView>(R.id.usage).text = Html.fromHtml(getString(R.string.usage))
listView.setOnItemClickListener { _, _, position, _ ->
onListItemClick(position)
}
@@ -75,23 +78,15 @@ class LauncherActivity : Activity(), LauncherObserver {
}
private fun onListItemClick(position: Int) {
if (position < launcher.games.size) {
startGame(launcher.games[position].path, null)
} else {
val i = Intent(Intent.ACTION_GET_CONTENT)
i.type = CONTENT_TYPE_ZIP
startActivityForResult(Intent.createChooser(i, getString(R.string.choose_a_file)), INSTALL_REQUEST)
}
startGame(launcher.games[position].path, null)
}
private fun onItemLongClick(position: Int): Boolean {
if (position < launcher.games.size) {
AlertDialog.Builder(this).setTitle(R.string.uninstall_dialog_title)
.setMessage(getString(R.string.uninstall_dialog_message, launcher.games[position].title))
.setPositiveButton(R.string.ok) {_, _ -> uninstall(position)}
.setNegativeButton(R.string.cancel) {_, _ -> }
.show()
}
AlertDialog.Builder(this).setTitle(R.string.confirm)
.setMessage(getString(R.string.uninstall_dialog_message, launcher.games[position].title))
.setPositiveButton(R.string.ok) {_, _ -> uninstall(position)}
.setNegativeButton(R.string.cancel) {_, _ -> }
.show()
return true
}
@@ -102,6 +97,12 @@ class LauncherActivity : Activity(), LauncherObserver {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.install_from_zip -> {
val i = Intent(Intent.ACTION_GET_CONTENT)
i.type = CONTENT_TYPE_ZIP
startActivityForResult(Intent.createChooser(i, getString(R.string.choose_a_file)), INSTALL_REQUEST)
true
}
R.id.export_savedata -> {
val i = Intent(Intent.ACTION_CREATE_DOCUMENT)
i.type = CONTENT_TYPE_ZIP
@@ -116,6 +117,27 @@ class LauncherActivity : Activity(), LauncherObserver {
SAVEDATA_IMPORT_REQUEST)
true
}
R.id.clear_savedata -> {
AlertDialog.Builder(this)
.setTitle(R.string.confirm)
.setMessage(R.string.clear_save_data_confirm)
.setPositiveButton(R.string.ok) { _, _ ->
if (launcher.clearSaveData()) {
Toast.makeText(this, R.string.save_data_clear_success, Toast.LENGTH_SHORT).show()
} else {
errorDialog(R.string.save_data_clear_error)
}
}
.setNegativeButton(R.string.cancel, null)
.show()
true
}
R.id.help -> {
AlertDialog.Builder(this)
.setMessage(Html.fromHtml(getString(R.string.usage)))
.show()
true
}
R.id.licenses -> {
val intent = Intent(this, LicensesMenuActivity::class.java)
startActivity(intent)
@@ -157,7 +179,6 @@ class LauncherActivity : Activity(), LauncherObserver {
override fun onGameListChange() {
val items = launcher.titles.toMutableList()
items.add(getString(R.string.install_from_zip))
val listView = findViewById<ListView>(R.id.list)
listView.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, items)
}
@@ -180,6 +201,7 @@ class LauncherActivity : Activity(), LauncherObserver {
val i = Intent()
i.setClass(applicationContext, GameActivity::class.java)
i.putExtra(GameActivity.EXTRA_GAME_ROOT, path.path)
i.putExtra(GameActivity.EXTRA_SAVE_DIRECTORY, File(filesDir, Launcher.SAVE_DIR).path)
i.putExtra(GameActivity.EXTRA_ARCHIVE_NAME, archiveName)
startActivity(i)
}
@@ -13,6 +13,7 @@ class LicensesMenuActivity : Activity() {
Entry("SDL", "SDL", "https://www.libsdl.org/"),
Entry("SDL_mixer", "SDL_mixer", "https://github.com/libsdl-org/SDL_mixer"),
Entry("SDL_ttf", "SDL_ttf", "https://github.com/libsdl-org/SDL_ttf"),
Entry("NanoJPEG", "nanojpeg", "https://keyj.emphy.de/nanojpeg/"),
Entry("FreeType", "freetype", "https://freetype.org/"),
Entry("HarfBuzz", "harfbuzz", "https://harfbuzz.github.io/"),
Entry("MotoyaLCedar W3 mono", "MTLc3m", "https://github.com/aosp-mirror/platform_frameworks_base/tree/lollipop-release/data/fonts"),
@@ -186,7 +186,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
// Because on Chromebooks we show up as a dual-mode device, it will attempt to connect TRANSPORT_AUTO, which will use TRANSPORT_BREDR instead
// of TRANSPORT_LE. Let's force ourselves to connect low energy.
private BluetoothGatt connectGatt(boolean managed) {
if (Build.VERSION.SDK_INT >= 23) {
if (Build.VERSION.SDK_INT >= 23 /* Android 6.0 (M) */) {
try {
return mDevice.connectGatt(mManager.getContext(), managed, this, TRANSPORT_LE);
} catch (Exception e) {
@@ -429,7 +429,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
}
});
}
}
}
else if (newState == 0) {
mIsConnected = false;
}
@@ -170,7 +170,7 @@ public class HIDDeviceManager {
Log.i(TAG," Interface protocol: " + mUsbInterface.getInterfaceProtocol());
Log.i(TAG," Endpoint count: " + mUsbInterface.getEndpointCount());
// Get endpoint details
// Get endpoint details
for (int epi = 0; epi < mUsbInterface.getEndpointCount(); epi++)
{
UsbEndpoint mEndpoint = mUsbInterface.getEndpoint(epi);
@@ -251,6 +251,8 @@ public class HIDDeviceManager {
0x20d6, // PowerA
0x24c6, // PowerA
0x2c22, // Qanba
0x2dc8, // 8BitDo
0x9886, // ASTRO Gaming
};
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&
@@ -271,15 +273,20 @@ public class HIDDeviceManager {
final int XB1_IFACE_SUBCLASS = 71;
final int XB1_IFACE_PROTOCOL = 208;
final int[] SUPPORTED_VENDORS = {
0x03f0, // HP
0x044f, // Thrustmaster
0x045e, // Microsoft
0x0738, // Mad Catz
0x0b05, // ASUS
0x0e6f, // PDP
0x0f0d, // Hori
0x10f5, // Turtle Beach
0x1532, // Razer Wildcat
0x20d6, // PowerA
0x24c6, // PowerA
0x2dc8, /* 8BitDo */
0x2dc8, // 8BitDo
0x2e24, // Hyperkin
0x3537, // GameSir
};
if (usbInterface.getId() == 0 &&
@@ -353,13 +360,19 @@ public class HIDDeviceManager {
private void initializeBluetooth() {
Log.d(TAG, "Initializing Bluetooth");
if (Build.VERSION.SDK_INT <= 30 &&
if (Build.VERSION.SDK_INT >= 31 /* Android 12 */ &&
mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH_CONNECT, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH_CONNECT");
return;
}
if (Build.VERSION.SDK_INT <= 30 /* Android 11.0 (R) */ &&
mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH");
return;
}
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) || (Build.VERSION.SDK_INT < 18)) {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) || (Build.VERSION.SDK_INT < 18 /* Android 4.3 (JELLY_BEAN_MR2) */)) {
Log.d(TAG, "Couldn't initialize Bluetooth, this version of Android does not support Bluetooth LE");
return;
}
@@ -524,7 +537,7 @@ public class HIDDeviceManager {
for (HIDDevice device : mDevicesById.values()) {
device.setFrozen(frozen);
}
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -573,12 +586,18 @@ public class HIDDeviceManager {
try {
final int FLAG_MUTABLE = 0x02000000; // PendingIntent.FLAG_MUTABLE, but don't require SDK 31
int flags;
if (Build.VERSION.SDK_INT >= 31) {
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
flags = FLAG_MUTABLE;
} else {
flags = 0;
}
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);
@@ -52,7 +52,7 @@ class HIDDeviceUSB implements HIDDevice {
@Override
public String getSerialNumber() {
String result = null;
if (Build.VERSION.SDK_INT >= 21) {
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
try {
result = mDevice.getSerialNumber();
}
@@ -74,7 +74,7 @@ class HIDDeviceUSB implements HIDDevice {
@Override
public String getManufacturerName() {
String result = null;
if (Build.VERSION.SDK_INT >= 21) {
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
result = mDevice.getManufacturerName();
}
if (result == null) {
@@ -86,7 +86,7 @@ class HIDDeviceUSB implements HIDDevice {
@Override
public String getProductName() {
String result = null;
if (Build.VERSION.SDK_INT >= 21) {
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
result = mDevice.getProductName();
}
if (result == null) {
@@ -29,6 +29,7 @@ public class SDL {
// This function stores the current activity (SDL or not)
public static void setContext(Context context) {
SDLAudioManager.setContext(context);
mContext = context;
}
@@ -37,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.");
@@ -52,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.
@@ -65,7 +70,7 @@ public class SDL {
// Actually load the library!
Method loadMethod = relinkInstanceClass.getDeclaredMethod("loadLibrary", contextClass, stringClass, stringClass, relinkListenerClass);
loadMethod.invoke(relinkInstance, mContext, libraryName, null, null);
loadMethod.invoke(relinkInstance, context, libraryName, null, null);
}
catch (final Throwable e) {
// Fall back
@@ -60,8 +60,8 @@ import java.util.Locale;
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 2;
private static final int SDL_MINOR_VERSION = 26;
private static final int SDL_MICRO_VERSION = 1;
private static final int SDL_MINOR_VERSION = 32;
private static final int SDL_MICRO_VERSION = 10;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
@@ -89,11 +89,11 @@ 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;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= 23) {
tst = InputDevice.SOURCE_BLUETOOTH_STYLUS;
if ((s & tst) == tst) src += " BLUETOOTH_STYLUS";
s2 &= ~tst;
@@ -107,7 +107,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if ((s & tst) == tst) src += " GAMEPAD";
s2 &= ~tst;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (Build.VERSION.SDK_INT >= 21) {
tst = InputDevice.SOURCE_HDMI;
if ((s & tst) == tst) src += " HDMI";
s2 &= ~tst;
@@ -146,7 +146,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if ((s & tst) == tst) src += " TOUCHSCREEN";
s2 &= ~tst;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (Build.VERSION.SDK_INT >= 18) {
tst = InputDevice.SOURCE_TOUCH_NAVIGATION;
if ((s & tst) == tst) src += " TOUCH_NAVIGATION";
s2 &= ~tst;
@@ -163,14 +163,14 @@ 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);
}
*/
public static boolean mIsResumedCalled, mHasFocus;
public static final boolean mHasMultiWindow = (Build.VERSION.SDK_INT >= 24);
public static final boolean mHasMultiWindow = (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */);
// Cursor types
// private static final int SDL_SYSTEM_CURSOR_NONE = -1;
@@ -224,9 +224,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
protected static SDLGenericMotionListener_API12 getMotionListener() {
if (mMotionListener == null) {
if (Build.VERSION.SDK_INT >= 26) {
if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {
mMotionListener = new SDLGenericMotionListener_API26();
} else if (Build.VERSION.SDK_INT >= 24) {
} else if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
mMotionListener = new SDLGenericMotionListener_API24();
} else {
mMotionListener = new SDLGenericMotionListener_API12();
@@ -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);
}
}
@@ -393,7 +393,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
mHIDDeviceManager = HIDDeviceManager.acquire(this);
// Set up the surface
mSurface = createSDLSurface(getApplication());
mSurface = createSDLSurface(this);
mLayout = new RelativeLayout(this);
mLayout.addView(mSurface);
@@ -404,7 +404,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
SDLActivity.onNativeOrientationChanged(mCurrentOrientation);
try {
if (Build.VERSION.SDK_INT < 24) {
if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) {
mCurrentLocale = getContext().getResources().getConfiguration().locale;
} else {
mCurrentLocale = getContext().getResources().getConfiguration().getLocales().get(0);
@@ -588,6 +588,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
mHIDDeviceManager = null;
}
SDLAudioManager.release(this);
if (SDLActivity.mBrokenLibraries) {
super.onDestroy();
return;
@@ -766,7 +768,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
}
break;
case COMMAND_CHANGE_WINDOW_STYLE:
if (Build.VERSION.SDK_INT >= 19) {
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
if (context instanceof Activity) {
Window window = ((Activity) context).getWindow();
if (window != null) {
@@ -788,6 +790,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
SDLActivity.mFullscreenModeActive = false;
}
if (Build.VERSION.SDK_INT >= 28 /* Android 9 (Pie) */) {
window.getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
}
}
} else {
Log.e(TAG, "error handling message, getContext() returned no Activity");
@@ -841,7 +846,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
msg.obj = data;
boolean result = commandHandler.sendMessage(msg);
if (Build.VERSION.SDK_INT >= 19) {
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
if (command == COMMAND_CHANGE_WINDOW_STYLE) {
// Ensure we don't return until the resize has actually happened,
// or 500ms have passed.
@@ -969,15 +974,18 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
/* If set, hint "explicitly controls which UI orientations are allowed". */
if (hint.contains("LandscapeRight") && hint.contains("LandscapeLeft")) {
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
} else if (hint.contains("LandscapeRight")) {
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
} else if (hint.contains("LandscapeLeft")) {
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
} else if (hint.contains("LandscapeRight")) {
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
}
if (hint.contains("Portrait") && hint.contains("PortraitUpsideDown")) {
/* exact match to 'Portrait' to distinguish with PortraitUpsideDown */
boolean contains_Portrait = hint.contains("Portrait ") || hint.endsWith("Portrait");
if (contains_Portrait && hint.contains("PortraitUpsideDown")) {
orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
} else if (hint.contains("Portrait")) {
} else if (contains_Portrait) {
orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
} else if (hint.contains("PortraitUpsideDown")) {
orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
@@ -990,8 +998,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);
@@ -1000,8 +1008,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);
@@ -1090,7 +1098,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
// thus SDK version 27. If we are in DeX mode and not API 27 or higher, as a result,
// we should stick to relative mode.
//
if ((Build.VERSION.SDK_INT < 27) && isDeXMode()) {
if (Build.VERSION.SDK_INT < 27 /* Android 8.1 (O_MR1) */ && isDeXMode()) {
return false;
}
@@ -1180,7 +1188,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
* This method is called by SDL using JNI.
*/
public static boolean isDeXMode() {
if (Build.VERSION.SDK_INT < 24) {
if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) {
return false;
}
try {
@@ -1340,23 +1348,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
}
}
if ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (isTextInputEvent(event)) {
if (ic != null) {
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
} else {
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
}
}
onNativeKeyDown(keyCode);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
onNativeKeyUp(keyCode);
return true;
}
}
if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
// on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
// they are ignored here because sending them as mouse input to SDL is messy
@@ -1371,6 +1362,21 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
}
}
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (isTextInputEvent(event)) {
if (ic != null) {
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
} else {
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
}
}
onNativeKeyDown(keyCode);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
onNativeKeyUp(keyCode);
return true;
}
return false;
}
@@ -1617,7 +1623,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
private final Runnable rehideSystemUi = new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT >= 19) {
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
@@ -1670,7 +1676,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
Bitmap bitmap = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888);
++mLastCursorID;
if (Build.VERSION.SDK_INT >= 24) {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
try {
mCursors.put(mLastCursorID, PointerIcon.create(bitmap, hotSpotX, hotSpotY));
} catch (Exception e) {
@@ -1686,7 +1692,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
* This method is called by SDL using JNI.
*/
public static void destroyCustomCursor(int cursorID) {
if (Build.VERSION.SDK_INT >= 24) {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
try {
mCursors.remove(cursorID);
} catch (Exception e) {
@@ -1700,7 +1706,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
*/
public static boolean setCustomCursor(int cursorID) {
if (Build.VERSION.SDK_INT >= 24) {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
try {
mSurface.setPointerIcon(mCursors.get(cursorID));
} catch (Exception e) {
@@ -1755,7 +1761,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
cursor_type = 1002; //PointerIcon.TYPE_HAND;
break;
}
if (Build.VERSION.SDK_INT >= 24) {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
try {
mSurface.setPointerIcon(PointerIcon.getSystemIcon(SDL.getContext(), cursor_type));
} catch (Exception e) {
@@ -1769,7 +1775,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
* This method is called by SDL using JNI.
*/
public static void requestPermission(String permission, int requestCode) {
if (Build.VERSION.SDK_INT < 23) {
if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
nativePermissionResult(requestCode, true);
return;
}
@@ -1798,7 +1804,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
i.setData(Uri.parse(url));
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
if (Build.VERSION.SDK_INT >= 21) {
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
flags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
} else {
flags |= Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET;
@@ -2002,6 +2008,18 @@ class SDLInputConnection extends BaseInputConnection {
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
if (Build.VERSION.SDK_INT <= 29 /* Android 10.0 (Q) */) {
// Workaround to capture backspace key. Ref: http://stackoverflow.com/questions>/14560344/android-backspace-in-webview-baseinputconnection
// and https://bugzilla.libsdl.org/show_bug.cgi?id=2265
if (beforeLength > 0 && afterLength == 0) {
// backspace(s)
while (beforeLength-- > 0) {
nativeGenerateScancodeForUnichar('\b');
}
return true;
}
}
if (!super.deleteSurroundingText(beforeLength, afterLength)) {
return false;
}
@@ -1,5 +1,8 @@
package org.libsdl.app;
import android.content.Context;
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
@@ -8,34 +11,67 @@ import android.media.MediaRecorder;
import android.os.Build;
import android.util.Log;
public class SDLAudioManager
{
import java.util.Arrays;
public class SDLAudioManager {
protected static final String TAG = "SDLAudio";
protected static AudioTrack mAudioTrack;
protected static AudioRecord mAudioRecord;
protected static Context mContext;
private static final int[] NO_DEVICES = {};
private static AudioDeviceCallback mAudioDeviceCallback;
public static void initialize() {
mAudioTrack = null;
mAudioRecord = null;
mAudioDeviceCallback = null;
if(Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */)
{
mAudioDeviceCallback = new AudioDeviceCallback() {
@Override
public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
Arrays.stream(addedDevices).forEach(deviceInfo -> addAudioDevice(deviceInfo.isSink(), deviceInfo.getId()));
}
@Override
public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
Arrays.stream(removedDevices).forEach(deviceInfo -> removeAudioDevice(deviceInfo.isSink(), deviceInfo.getId()));
}
};
}
}
public static void setContext(Context context) {
mContext = context;
if (context != null) {
registerAudioDeviceCallback();
}
}
public static void release(Context context) {
unregisterAudioDeviceCallback(context);
}
// Audio
protected static String getAudioFormatString(int audioFormat) {
switch (audioFormat) {
case AudioFormat.ENCODING_PCM_8BIT:
return "8-bit";
case AudioFormat.ENCODING_PCM_16BIT:
return "16-bit";
case AudioFormat.ENCODING_PCM_FLOAT:
return "float";
default:
return Integer.toString(audioFormat);
case AudioFormat.ENCODING_PCM_8BIT:
return "8-bit";
case AudioFormat.ENCODING_PCM_16BIT:
return "16-bit";
case AudioFormat.ENCODING_PCM_FLOAT:
return "float";
default:
return Integer.toString(audioFormat);
}
}
protected static int[] open(boolean isCapture, int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
protected static int[] open(boolean isCapture, int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {
int channelConfig;
int sampleSize;
int frameSize;
@@ -43,14 +79,14 @@ public class SDLAudioManager
Log.v(TAG, "Opening " + (isCapture ? "capture" : "playback") + ", requested " + desiredFrames + " frames of " + desiredChannels + " channel " + getAudioFormatString(audioFormat) + " audio at " + sampleRate + " Hz");
/* On older devices let's use known good settings */
if (Build.VERSION.SDK_INT < 21) {
if (Build.VERSION.SDK_INT < 21 /* Android 5.0 (LOLLIPOP) */) {
if (desiredChannels > 2) {
desiredChannels = 2;
}
}
/* AudioTrack has sample rate limitation of 48000 (fixed in 5.0.2) */
if (Build.VERSION.SDK_INT < 22) {
if (Build.VERSION.SDK_INT < 22 /* Android 5.1 (LOLLIPOP_MR1) */) {
if (sampleRate < 8000) {
sampleRate = 8000;
} else if (sampleRate > 48000) {
@@ -59,7 +95,7 @@ public class SDLAudioManager
}
if (audioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
int minSDKVersion = (isCapture ? 23 : 21);
int minSDKVersion = (isCapture ? 23 /* Android 6.0 (M) */ : 21 /* Android 5.0 (LOLLIPOP) */);
if (Build.VERSION.SDK_INT < minSDKVersion) {
audioFormat = AudioFormat.ENCODING_PCM_16BIT;
}
@@ -120,7 +156,7 @@ public class SDLAudioManager
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER;
break;
case 8:
if (Build.VERSION.SDK_INT >= 23) {
if (Build.VERSION.SDK_INT >= 23 /* Android 6.0 (M) */) {
channelConfig = AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
} else {
Log.v(TAG, "Requested " + desiredChannels + " channels, getting 5.1 surround");
@@ -201,6 +237,10 @@ public class SDLAudioManager
return null;
}
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */ && deviceId != 0) {
mAudioRecord.setPreferredDevice(getOutputAudioDeviceInfo(deviceId));
}
mAudioRecord.startRecording();
}
@@ -224,6 +264,10 @@ public class SDLAudioManager
return null;
}
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */ && deviceId != 0) {
mAudioTrack.setPreferredDevice(getInputAudioDeviceInfo(deviceId));
}
mAudioTrack.play();
}
@@ -238,11 +282,73 @@ public class SDLAudioManager
return results;
}
private static AudioDeviceInfo getInputAudioDeviceInfo(int deviceId) {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS))
.filter(deviceInfo -> deviceInfo.getId() == deviceId)
.findFirst()
.orElse(null);
} else {
return null;
}
}
private static AudioDeviceInfo getOutputAudioDeviceInfo(int deviceId) {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS))
.filter(deviceInfo -> deviceInfo.getId() == deviceId)
.findFirst()
.orElse(null);
} else {
return null;
}
}
private static void registerAudioDeviceCallback() {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
audioManager.registerAudioDeviceCallback(mAudioDeviceCallback, null);
}
}
private static void unregisterAudioDeviceCallback(Context context) {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.unregisterAudioDeviceCallback(mAudioDeviceCallback);
}
}
/**
* This method is called by SDL using JNI.
*/
public static int[] audioOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
return open(false, sampleRate, audioFormat, desiredChannels, desiredFrames);
public static int[] getAudioOutputDevices() {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)).mapToInt(AudioDeviceInfo::getId).toArray();
} else {
return NO_DEVICES;
}
}
/**
* This method is called by SDL using JNI.
*/
public static int[] getAudioInputDevices() {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
return Arrays.stream(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).mapToInt(AudioDeviceInfo::getId).toArray();
} else {
return NO_DEVICES;
}
}
/**
* This method is called by SDL using JNI.
*/
public static int[] audioOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {
return open(false, sampleRate, audioFormat, desiredChannels, desiredFrames, deviceId);
}
/**
@@ -254,6 +360,11 @@ public class SDLAudioManager
return;
}
if (android.os.Build.VERSION.SDK_INT < 21 /* Android 5.0 (LOLLIPOP) */) {
Log.e(TAG, "Attempted to make an incompatible audio call with uninitialized audio! (floating-point output is supported since Android 5.0 Lollipop)");
return;
}
for (int i = 0; i < buffer.length;) {
int result = mAudioTrack.write(buffer, i, buffer.length - i, AudioTrack.WRITE_BLOCKING);
if (result > 0) {
@@ -326,18 +437,22 @@ public class SDLAudioManager
/**
* This method is called by SDL using JNI.
*/
public static int[] captureOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
return open(true, sampleRate, audioFormat, desiredChannels, desiredFrames);
public static int[] captureOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {
return open(true, sampleRate, audioFormat, desiredChannels, desiredFrames, deviceId);
}
/** This method is called by SDL using JNI. */
public static int captureReadFloatBuffer(float[] buffer, boolean blocking) {
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
return 0;
} else {
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
}
}
/** This method is called by SDL using JNI. */
public static int captureReadShortBuffer(short[] buffer, boolean blocking) {
if (Build.VERSION.SDK_INT < 23) {
if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
return mAudioRecord.read(buffer, 0, buffer.length);
} else {
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
@@ -346,7 +461,7 @@ public class SDLAudioManager
/** This method is called by SDL using JNI. */
public static int captureReadByteBuffer(byte[] buffer, boolean blocking) {
if (Build.VERSION.SDK_INT < 23) {
if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
return mAudioRecord.read(buffer, 0, buffer.length);
} else {
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
@@ -391,4 +506,9 @@ public class SDLAudioManager
}
public static native int nativeSetupJNI();
public static native void removeAudioDevice(boolean isCapture, int deviceId);
public static native void addAudioDevice(boolean isCapture, int deviceId);
}
@@ -24,7 +24,7 @@ public class SDLControllerManager
public static native int nativeAddJoystick(int device_id, String name, String desc,
int vendor_id, int product_id,
boolean is_accelerometer, int button_mask,
int naxes, int nhats, int nballs);
int naxes, int axis_mask, int nhats, int nballs);
public static native int nativeRemoveJoystick(int device_id);
public static native int nativeAddHaptic(int device_id, String name);
public static native int nativeRemoveHaptic(int device_id);
@@ -42,7 +42,7 @@ public class SDLControllerManager
public static void initialize() {
if (mJoystickHandler == null) {
if (Build.VERSION.SDK_INT >= 19) {
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
mJoystickHandler = new SDLJoystickHandler_API19();
} else {
mJoystickHandler = new SDLJoystickHandler_API16();
@@ -50,7 +50,7 @@ public class SDLControllerManager
}
if (mHapticHandler == null) {
if (Build.VERSION.SDK_INT >= 26) {
if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {
mHapticHandler = new SDLHapticHandler_API26();
} else {
mHapticHandler = new SDLHapticHandler();
@@ -168,6 +168,32 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
arg1Axis = MotionEvent.AXIS_GAS;
}
// Make sure the AXIS_Z is sorted between AXIS_RY and AXIS_RZ.
// This is because the usual pairing are:
// - AXIS_X + AXIS_Y (left stick).
// - AXIS_RX, AXIS_RY (sometimes the right stick, sometimes triggers).
// - AXIS_Z, AXIS_RZ (sometimes the right stick, sometimes triggers).
// This sorts the axes in the above order, which tends to be correct
// for Xbox-ish game pads that have the right stick on RX/RY and the
// triggers on Z/RZ.
//
// Gamepads that don't have AXIS_Z/AXIS_RZ but use
// AXIS_LTRIGGER/AXIS_RTRIGGER are unaffected by this.
//
// References:
// - https://developer.android.com/develop/ui/views/touch-and-input/game-controllers/controller-input
// - https://www.kernel.org/doc/html/latest/input/gamepad.html
if (arg0Axis == MotionEvent.AXIS_Z) {
arg0Axis = MotionEvent.AXIS_RZ - 1;
} else if (arg0Axis > MotionEvent.AXIS_Z && arg0Axis < MotionEvent.AXIS_RZ) {
--arg0Axis;
}
if (arg1Axis == MotionEvent.AXIS_Z) {
arg1Axis = MotionEvent.AXIS_RZ - 1;
} else if (arg1Axis > MotionEvent.AXIS_Z && arg1Axis < MotionEvent.AXIS_RZ) {
--arg1Axis;
}
return arg0Axis - arg1Axis;
}
}
@@ -210,7 +236,7 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
mJoysticks.add(joystick);
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
getVendorId(joystickDevice), getProductId(joystickDevice), false,
getButtonMask(joystickDevice), joystick.axes.size(), joystick.hats.size()/2, 0);
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, 0);
}
}
}
@@ -291,6 +317,9 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
public int getVendorId(InputDevice joystickDevice) {
return 0;
}
public int getAxisMask(List<InputDevice.MotionRange> ranges) {
return -1;
}
public int getButtonMask(InputDevice joystickDevice) {
return -1;
}
@@ -308,6 +337,43 @@ class SDLJoystickHandler_API19 extends SDLJoystickHandler_API16 {
return joystickDevice.getVendorId();
}
@Override
public int getAxisMask(List<InputDevice.MotionRange> ranges) {
// For compatibility, keep computing the axis mask like before,
// only really distinguishing 2, 4 and 6 axes.
int axis_mask = 0;
if (ranges.size() >= 2) {
// ((1 << SDL_GAMEPAD_AXIS_LEFTX) | (1 << SDL_GAMEPAD_AXIS_LEFTY))
axis_mask |= 0x0003;
}
if (ranges.size() >= 4) {
// ((1 << SDL_GAMEPAD_AXIS_RIGHTX) | (1 << SDL_GAMEPAD_AXIS_RIGHTY))
axis_mask |= 0x000c;
}
if (ranges.size() >= 6) {
// ((1 << SDL_GAMEPAD_AXIS_LEFT_TRIGGER) | (1 << SDL_GAMEPAD_AXIS_RIGHT_TRIGGER))
axis_mask |= 0x0030;
}
// Also add an indicator bit for whether the sorting order has changed.
// This serves to disable outdated gamecontrollerdb.txt mappings.
boolean have_z = false;
boolean have_past_z_before_rz = false;
for (InputDevice.MotionRange range : ranges) {
int axis = range.getAxis();
if (axis == MotionEvent.AXIS_Z) {
have_z = true;
} else if (axis > MotionEvent.AXIS_Z && axis < MotionEvent.AXIS_RZ) {
have_past_z_before_rz = true;
}
}
if (have_z && have_past_z_before_rz) {
// If both these exist, the compare() function changed sorting order.
// Set a bit to indicate this fact.
axis_mask |= 0x8000;
}
return axis_mask;
}
@Override
public int getButtonMask(InputDevice joystickDevice) {
int button_mask = 0;
@@ -480,13 +546,15 @@ class SDLHapticHandler {
if (haptic == null) {
InputDevice device = InputDevice.getDevice(deviceIds[i]);
Vibrator vib = device.getVibrator();
if (vib.hasVibrator()) {
haptic = new SDLHaptic();
haptic.device_id = deviceIds[i];
haptic.name = device.getName();
haptic.vib = vib;
mHaptics.add(haptic);
SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
if (vib != null) {
if (vib.hasVibrator()) {
haptic = new SDLHaptic();
haptic.device_id = deviceIds[i];
haptic.name = device.getName();
haptic.vib = vib;
mHaptics.add(haptic);
SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
}
}
}
}
@@ -743,7 +811,7 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
@Override
public boolean supportsRelativeMouse() {
return (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27));
return (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */);
}
@Override
@@ -753,7 +821,7 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
@Override
public boolean setRelativeMouseEnabled(boolean enabled) {
if (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27)) {
if (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */) {
if (enabled) {
SDLActivity.getContentView().requestPointerCapture();
} else {
@@ -116,7 +116,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
int nDeviceHeight = height;
try
{
if (Build.VERSION.SDK_INT >= 17) {
if (Build.VERSION.SDK_INT >= 17 /* Android 4.2 (JELLY_BEAN_MR1) */) {
DisplayMetrics realMetrics = new DisplayMetrics();
mDisplay.getRealMetrics( realMetrics );
nDeviceWidth = realMetrics.widthPixels;
@@ -163,7 +163,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// Don't skip in MultiWindow.
if (skip) {
if (Build.VERSION.SDK_INT >= 24) {
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
if (SDLActivity.mSingleton.isInMultiWindowMode()) {
Log.v("SDL", "Don't skip in Multi-Window");
skip = false;
@@ -6,4 +6,12 @@
<ListView android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ScrollView android:id="@+id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView android:id="@+id/usage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp" />
</ScrollView>
</LinearLayout>
@@ -1,11 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/install_from_zip"
android:title="@string/action_install_from_zip" />
<item
android:id="@+id/export_savedata"
android:title="@string/action_export_save_data" />
<item
android:id="@+id/import_savedata"
android:title="@string/action_import_save_data" />
<item
android:id="@+id/clear_savedata"
android:title="@string/action_clear_save_data" />
<item
android:id="@+id/help"
android:title="@string/action_help" />
<item
android:id="@+id/licenses"
android:title="@string/action_licenses" />
+24 -2
View File
@@ -2,21 +2,43 @@
<resources>
<string name="app_name">xsystem35</string>
<string name="action_export_save_data">セーブデータをエクスポート</string>
<string name="action_help">使い方</string>
<string name="action_import_save_data">セーブデータをインポート</string>
<string name="action_install_from_zip">ZIPからインストール</string>
<string name="action_licenses">オープンソースライセンス</string>
<string name="action_clear_save_data">セーブデータをクリア</string>
<string name="cancel">キャンセル</string>
<string name="cannot_find_ald">System 3.x のファイル (*.ald) が見つかりません。</string>
<string name="choose_a_file">ファイルを選択</string>
<string name="clear_save_data_confirm">セーブデータをすべて削除します。元には戻せません。本当によろしいですか?</string>
<string name="confirm">確認</string>
<string name="error_dialog_title">エラー</string>
<string name="install_dialog_title">インストール中…</string>
<string name="install_from_zip">ZIP からインストール</string>
<string name="install_progress">%s を展開中</string>
<string name="no_data_to_import">ZIP アーカイブ中に save/ フォルダが見つかりません。</string>
<string name="save_data_export_error">セーブデータのエクスポートに失敗しました。</string>
<string name="save_data_export_success">エクスポートに成功しました。</string>
<string name="save_data_import_success">インポートに成功しました。</string>
<string name="save_data_clear_success">セーブデータをクリアしました。</string>
<string name="save_data_clear_error">セーブデータのクリアに失敗しました。</string>
<string name="uninstall_dialog_message">「%s」をアンインストールしますか?</string>
<string name="uninstall_dialog_title">確認</string>
<string name="unsupported_zip">この形式の ZIP はサポートしていません。</string>
<string name="zip_extraction_error">ZIP の展開に失敗しました。</string>
<string name="usage">
<![CDATA[
<h1>ゲームのインストール方法</h1>
<p>1. PC上で、ゲームのファイルが入ったZIPを用意します。例えば以下のようなファイルを含めます:</p>
<div>
・鬼畜王SA.ALD<br>
・鬼畜王GA.ALD<br>
・鬼畜王GB.ALD<br>
・鬼畜王WA.ALD<br>
・02.mp3<br>
・03.mp3<br>
・…<br>
</div>
<p>2. ZIPファイルを (例えばUSB経由で) PCからデバイスに転送します。</p>
<p>3. この画面の右上のメニューボタンをタップして「ZIPからインストール」を選択し、転送したZIPを選びます。</p>
]]>
</string>
</resources>
+25 -2
View File
@@ -1,22 +1,45 @@
<resources>
<string name="app_name">xsystem35</string>
<string name="action_clear_save_data">Clear Save Files</string>
<string name="action_export_save_data">Export Save Files</string>
<string name="action_help">Help</string>
<string name="action_import_save_data">Import Save Files</string>
<string name="action_install_from_zip">Install from ZIP</string>
<string name="action_licenses">Open source licenses</string>
<string name="cancel">Cancel</string>
<string name="cannot_find_ald">Cannot find System 3.x game files (*.ald).</string>
<string name="choose_a_file">Choose a file</string>
<string name="clear_save_data_confirm">Are you sure you want to clear all save files? This cannot be undone.</string>
<string name="confirm">Confirm</string>
<string name="error_dialog_title">Error</string>
<string name="install_dialog_title">Installing…</string>
<string name="install_from_zip">Install from ZIP</string>
<string name="install_progress">Extracting %s</string>
<string name="no_data_to_import">No save/ folder in the ZIP archive.</string>
<string name="ok">OK</string>
<string name="save_data_clear_error">Failed to clear save files.</string>
<string name="save_data_clear_success">Save files cleared.</string>
<string name="save_data_export_error">Failed to export save files.</string>
<string name="save_data_import_success">Imported successfully.</string>
<string name="save_data_export_success">Exported successfully.</string>
<string name="uninstall_dialog_message">Uninstall \"%s\"?</string>
<string name="uninstall_dialog_title">Confirm</string>
<string name="unsupported_zip">This type of ZIP is not supported.</string>
<string name="zip_extraction_error">Failed to extract ZIP.</string>
<string name="usage">
<![CDATA[
<h1>How to install a game</h1>
<p>1. On your PC, prepare a ZIP containing the game files. For example, it should contain the following files:</p>
<div>
* KICHIKUSA.ALD<br>
* KICHIKUGA.ALD<br>
* KICHIKUGB.ALD<br>
* KICHIKUWA.ALD<br>
* System39.ain<br>
* 02.mp3<br>
* 03.mp3<br>
* …<br>
</div>
<p>2. Transfer the ZIP file from your PC to the device (e.g. via USB).</p>
<p>3. Tap the menu button at the upper-right of this screen, select &quot;Install from ZIP,&quot; and choose the ZIP you transferred.</p>
]]>
</string>
</resources>
+2 -3
View File
@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<style name="AppTheme" parent="android:Theme.NoTitleBar.Fullscreen">
<!-- Customize your theme here. -->
</style>
</resources>
+1 -1
View File
@@ -7,7 +7,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath 'com.android.tools.build:gradle:8.7.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
+1 -1
View File
@@ -1,6 +1,6 @@
#Thu Nov 11 18:20:34 PST 2021
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
+2 -2
View File
@@ -126,8 +126,8 @@ if $cygwin ; then
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
CHECK=`echo "$arg"|grep -E -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|grep -E -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+2 -15
View File
@@ -1,33 +1,20 @@
#cmakedefine PACKAGE "@PACKAGE@"
#define VERSION "2.9.1"
#cmakedefine CMAKE_SYSTEM_NAME "@CMAKE_SYSTEM_NAME@"
#define VERSION "@XSYSTEM35_VERSION@"
#cmakedefine CACHE_TOTALSIZE @CACHE_TOTALSIZE@
#cmakedefine ENABLE_CDROM_ANDROID @ENABLE_CDROM_ANDROID@
#cmakedefine ENABLE_CDROM_BSD @ENABLE_CDROM_BSD@
#cmakedefine ENABLE_CDROM_EMSCRIPTEN @ENABLE_CDROM_EMSCRIPTEN@
#cmakedefine ENABLE_CDROM_LINUX @ENABLE_CDROM_LINUX@
#cmakedefine ENABLE_CDROM_MP3 @ENABLE_CDROM_MP3@
#cmakedefine ENABLE_DEBUGGER @ENABLE_DEBUGGER@
#cmakedefine ENABLE_GTK @ENABLE_GTK@
#cmakedefine ENABLE_MIDI_RAWMIDI @ENABLE_MIDI_RAWMIDI@
#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 ENABLE_SDLMIXER @ENABLE_SDLMIXER@
#cmakedefine CDROM_DEVICE "@CDROM_DEVICE@"
#cmakedefine DEFAULT_PLAYLIST_PATH "@DEFAULT_PLAYLIST_PATH@"
#cmakedefine JOY_DEVICE "@JOY_DEVICE@"
#cmakedefine MIDI_DEVICE "@MIDI_DEVICE@"
#cmakedefine SEQ_DEVICE "@SEQ_DEVICE@"
#cmakedefine HAVE_GETLOGIN @HAVE_GETLOGIN@
#cmakedefine HAVE_MMAP @HAVE_MMAP@
#cmakedefine HAVE_SIGACTION @HAVE_SIGACTION@
#cmakedefine HAVE_UNAME @HAVE_UNAME@
#cmakedefine HAVE_WEBP @HAVE_WEBP@
#define DEFAULT_GOTHIC_TTF "@DEFAULT_FONT_PATH@MTLc3m.ttf"
+42
View File
@@ -0,0 +1,42 @@
set(SOURCES
xsystem35.6.adoc
xsystem35.gr.5.adoc
)
find_program(ASCIIDOCTOR asciidoctor)
if (NOT ASCIIDOCTOR)
message(WARNING "asciidoctor not found, manpages will not be generated")
else()
if (WIN32)
set(BACKEND html)
else()
set(BACKEND manpage)
include(GNUInstallDirs)
endif()
set(MANUALS "")
foreach(SRC ${SOURCES})
string(REGEX MATCH "^(.*)\\.([0-9])\\.adoc$" _ ${SRC})
set(NAME ${CMAKE_MATCH_1})
set(SECTION ${CMAKE_MATCH_2})
if (WIN32)
set(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.html)
else()
set(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.${SECTION})
install(FILES ${OUTPUT} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${SECTION})
endif()
add_custom_command(
OUTPUT ${OUTPUT}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${SRC}
COMMAND ${ASCIIDOCTOR}
--attribute xsystem35-version=${XSYSTEM35_VERSION}
--backend ${BACKEND}
--out-file ${OUTPUT}
${CMAKE_CURRENT_SOURCE_DIR}/${SRC}
)
list(APPEND MANUALS ${OUTPUT})
endforeach()
add_custom_target(manual ALL DEPENDS ${MANUALS})
endif()
View File
-80
View File
@@ -1,80 +0,0 @@
ゲームリソースファイル(*.gr)の書き方
xsystem35ではゲームデータの置き場所をテキストファイルに保存しておき、
それをxsystem35に指定してやる事でデータの置き場所を知らせます。
# このファイルのファイル名はxsystem35を起動する時に指定できますので、hoge.gr
# である必要は無く、自由につける事が出来ます。
ここでは、このテキストファイル(ゲームリソースファイル)の書式を説明します。
1つのデータにつき1行で記述します。例を見て下さい。
ScenarioA /home/chikama/game/rance4/rance4_sa.ald
キーワード データのフルパス
の順に書きます。キーワードは行の先頭から書き、データのフルパスとの間は半角
スペースです。(セーブデータのみ、ホームディレクトリを表す ~ を評価します。)
キーワードには次の7つがあります。
Scenario : シナリオ
Graphics : グラフィック
Wave : PCMデータ
Midi : MIDIデータ
Data : その他データ
Save : セーブデータ
Resource : リソースファイル(マウスカーソル形状)
Ain : DLL とその関数の情報のかかれた System39.ain
BGM : BGMデータ(エスカレイヤー以降のBGMデータファイル)
WAI : PCMデータの追加情報 (mixer channel 情報等)
BGI : BGMデータの追加情報 (ループ位置等)
SACT01 : SACT.DLL用データ (SACTEFAM.KLD)
ALK : デモ用アーカイブファイル
Init : System39.ini
同じ種類のデータが複数ある場合はキーワードの次にA,B,C...をつけます。
(Ain を除く)
CD-ROM上のどれがどの種類のファイルかは、ファイル名で判別します。
*SA.ALD ならシナリオの1番目、*GA.ALDはグラフィック、*WA.ALDはPCM、
*MA.ALD はMIDI、*DA.ALDはその他データです。
Ain は System39.ain へのパスを書きます。例えば
Ain /home/chikama/game/20cKaeru/System39.ain
のように書きます。
Init は System39.ini へのパスを書きます。例えば
Init /home/chikama/game/esuka/System39.ini
のように書きます。
WAI/BGI は通常1ファイルだけですので
WAIA /home/chikama/game/esuka/DOKI_WA.WAI
BGIA /home/chikama/game/esuka/DOKI_BA.BGI
のように書きます。
SACT01 は SACTシステム固有のデータファイル(SACTEFAM.KLD)へのパスを
指定します。
SACT01 /home/chikama/game/rance5d/SACTEFAM.KLD
ALK はデモ用のデータが入ったアーカイブファイルです。
ALK01 /home/chikama/game/nd/NightDemonDemo1.alk
ALK02 /home/chikama/game/nd/NightDemonDemo2.alk
ALK03 /home/chikama/game/nd/NightDemonDemo3.alk
のように書きます。
また、これらの範疇にはいらないデータ、たとえば、かえるにょぱにょんの
floor_1.mapなどはリソースファイルを介しませんので、ゲームリソース
ファイルには書かず、「セーブデータを置いたディレクトリと同じ場所」に
コピーして下さい。
また、Save? のみ、'~' (ホームディレクトリ)を評価しますので、
SaveA ~/savedata/kichiku/kichiku_sa.ald
のように書く事が出来ます。
コメントを書く場合は行頭に # をつけます。また空白行は無視されます。
-314
View File
@@ -1,314 +0,0 @@
System 3.5 for X Window System Version 1.7 (開発版)
0. 目次
1. はじめに
2. 開発環境と動作確認環境
2.a. 開発環境
2.b. 動作確認環境
2.c. 多分動くと思われる環境
3. xystem35の設定ファイル
4. ゲームの実行と終了
4.a. ゲームの実行
4.b. ゲームの終了
4.c. xsystem35メニュー
4.d. キーボード操作
5. コマンドラインオプション
6. その他情報
6.a. SYSV IPC
6.b. SharedMemoryの大きさについて
6.c. locale と X
7. 著作権とライセンス
8. サポート
1. はじめに
このソフトは AliceSoft の Syetem3.5/3.6/3.8/3.9 上で動くゲームを
X Window System 上で動かすためのプログラムです。
* 動作確認ゲーム
鬼畜王ランス
ランス4 (for Win95)
闘神都市II (for Win95)
夢幻泡影 (for Win95)
かえるにょぱにょ〜ん (初版、廉価版)
いけないかつみ先生
戦巫女 (初版、廉価版)
零式 (館456版、廉価版)
ATLACH=NACHA (館456版、廉価版)
人間狩り
王道勇者
ディアボリカ (初版、廉価版)
AmbivalenZ(for Win95)
ぱすてるチャイム
ぷろすちゅーでんとGood
守り神様
ママトト
アリスの館456
DALK
闘神都市
DrStop!
ランス1
ランス2
ランス3
アリスCD Ver 1.02
メイドのすすめ
ぶろぶろ
学園漂流戦記
Hushaby Baby
Darcrows
PERSIOM
隠れ月
SeeIn青
20世紀アリス
これDPS
かえるにょ国にょアリス
アリスCD Ver 2.02
妖精
OnlyYou リ・クルス
王子さま Lv1.5
* 動かないゲーム
夜が来る!
王子さま Lv1
DALK外伝 (System4)
ままにょにょ (System4)
* 一部動作可能
大悪司 (オープニング不可)
妻みぐい (オープニング不可)
エスカレイヤー (オープニング不可)
Rance5D
妻みぐい2 (オープニング不可)
シェル・クレイル
NightDemon (オープニング不可)
各ゲームについての補足事項は doc/GAMES.TXT を御覧ください。
また、ネット上で公開されているSYSTEM3.5用のゲームのうち、いくつかは
動作が確認されています。くわしくは MISCGAME.TXT を御覧下さい。
2. 開発環境と動作確認環境
2.a. 開発環境
Kondara-1.2 (Linux/i386)
2.b. 動作確認環境
DigitalUnix 4.0F (alpha)
SunOS 5.8 (sparc)
2.c. 多分動くと思われる環境
Linux(!i386)
FreeBSD/NetBSD/OpenBSD (i386 etc)
Irix 6.X
Solaris 2.X 以降 (sparc/i386)
3. xystem35の設定ファイル
xsystem35ではフォントの設定などを、カレントディレクトリとホームディレクトリに
ある .xsys35rcというファイルから読み込みます。カレントディレクトリの .xsys35rc
に書かれた設定のほうが優先されるため、一般的な設定はホームディレクトリの
.xsys35rcに書き、特定のゲームで書き換えたい項目はゲームを置いたディレクトリの
.xsys35rcに書くといいでしょう。
サンプルとなるファイルを xsys35rc.sample として用意しました。
また、gtk widgetのリソースは ~/.gtk/gtkrc または ~/.gtkrc から読み込みます。
読み込み先は .xsys35rc で指定できます。
ゲームで使用するフォントは X のフォントの仕組を使う方法と、TrueTypeFontを
外部ライブラリを使って直接表示する方法の2種類が選べます。
~/.xsys35rc の ttfont_mincho: と ttfont_gothic: の場所にフォントファイルを
指定し、font_device: ttf と指定してください。詳しくはサンプルファイル
(xsys35rc.sample)を見て下さい。
4. ゲームの実行と終了
4.a. ゲームの実行
instgameを使ってゲームデータをインストールすると、インストールした
ディレクトリにの一つ上に ???????.gr というファイル(ゲームリソースファイル)
が自動的に作成されますので
% xsystem35 -gamefile ~/game/???????.gr
のように実行します。-gamefile オプションをつけない場合は、カレントディレク
トリの xsystem35.gr を参照します。
またいずれも見つからない場合は、カレントディレクトリにあるファイルをゲーム
データとして設定します。例えば testSA.ALD というファイルがカレントディレク
トリにあると、それをシナリオデータとして使います。またセーブデータは適当な
名前で 10個確保されます。
ゲームリソースファイルの書き方については、doc/GRFMT.TXT を御覧下さい。
4.b. ゲームの終了
* 起動した端末で Ctrl+C を押すと、すぐに終了します。
* ゲーム中にマウスの真中のボタンを押すと、メニューが出て来ますので、
そこから 'Exit' を選んで終了させて下さい。Window Manager のCloseボタンでも
同じように動作します。
* ESC + SPACE + RET キーを同時に押すと、すぐに終了します。
4.c. xsystem35メニュー
ゲーム中にマウスの真中ボタンを押すとメニューが出て来ます。
メッセージスキップ(MessageSkip):
次の選択肢までメッセージを飛ばします。マウスの右クリックで
止まります。シナリオによっては停止しない場合もあります。
マウスカーソル移動(MouseAutoMove):
選択ウィンドなどでマウスが自動的に移動するのを制御します。
ボリュームバランス(VolumeValance):
SACTシステムで音声の人物毎に音量を変えることができます。
(ゲームがそう出来るように対応している場合のみ)
情報(About):
このゲームについて。
終了(Exit):
ゲームを終了します。
4.d. キーボード操作
アリスソフトのゲームは有史来、基本的に上下左右キーに SPACE, RET, ESC, TAB
キーしか使いません(一部のゲームはそれ以外のキーを使うこともあります)。
XSystem35 では次のキー割当を特別に使っています。
F1: メッセージスキップ
F4: フルスクリーン <-> Window表示の切替え
また、旧き良き時代の DOS への復帰キー (ESC + SPACE + RET) でゲームを確認なし
で終了出来ます。
5. コマンドラインオプション
-h : ヘルプを表示します。
-gamefile file : ゲームリソースファイルを file から読み込みます。
-no-shm : ネットワーク越しに起動する場合に指定します。
-devcd name : CD-ROM device名を name にします。
-devmidi name : MIDI device名を name にします。
-M? : MIDI の出力の種類を選択します。
-Me : External midi player (default)
-Mr : Raw Midi device
-Ms? : Sequencer device (?:device number)
-M0 : disable midi
-devjoy n : n 番目の joystick のデバイスを使用します。
-version : バージョン情報を表示します。
-fullscreen : フルスクリーンでゲームを実行します。
SDL 有効時には Widget にフォーカスが当たらないため Popup
menu 等が使用できません。
-antialias : 常に文字にアンチエリアスをかけます。
-noantialias : 常に文字にアンチエリアスをかけません。シナリオ上でアンチ
エリアスの指定があっても無視します。
-devfont : フォントデバイスを指定します。x11/ft2/sdl のいずれかが
使えます。
-noimagecursor : リソースファイルによるカーソル形状の変更(Darcrows等)を無効
にしたい場合に指定します。
6. その他情報
6.a. SYSV IPC
カーネルに SYSV IPC (SharedMemory/MessageQueue/Semaphore)の機能が
組み込まれている必要があります。
6.b. SharedMemoryの大きさについて
カーネルのSharedMemoryの大きさが十分大きい場合、MIT-SHMを利用して画面を
高速に描画する事が出来ます。起動時にエラーが出る場合、カーネルパラメータを
変更してみて下さい。(BSD 系はデフォルトの SharedMemory の大きさが小さい
ようです)
6.b.1. FreeBSDの場合 /usr/src/sys/i386/conf/LINT 中の
options SHMALL=1025
options "SHMMAX=(SHMMAXPGS*PAGE_SIZE+1)"
options SHMMAXPGS=1025
options SHMMIN=2
options SHMMNI=33
options SHMSEG=9
「SHMMAXPGS」が関連項目です。
24bppで起動する場合は SHMMAXPGS=4096 くらいにするとよいようです。
もちろん設定後はカーネルの再構築が必要です。
6.c. locale と X
libc に locale 機構が組み込まれていない環境の場合、libxpg4 などの
ライブラリ(FreeBSD) や X の locale を使うことになります。
linux の libc5 な環境では configure 時に --with-locale=ja_JP.ujis として
コンパイルしてください。
それ以外のほとんどの環境では考慮する必要はないでしょう。
7. 著作権とライセンス
プログラムの著作権は作者(chikama)に属しますが、ソースコードはGPLに基づいて
再配付できます。
(一部のソースコードは私以外に著作権があります。詳しくは、ソースコードを御覧
下さい)
ゲーム内で使われてるカーソルフォントの一部をqvwm(Windows95そっくりのWindow
Manager)からいただきました。
8. サポート
動作報告・バグ報告などは以下のメールアドレスまでお願いします。
E-Mail: chikama@nabal.aist-nara.ac.jp (private)
masaki-c@is.aist-nara.ac.jp (official)
また最新版は以下のURLからダウンロードできます。
http://www.aist-nara.ac.jp/~masaki-c/private/unitbase/xsys35/index.html
バグレポートの際は、お使いの環境を出来るだけくわしく書いて下さい。
また特定のゲームで動かない場合は、出来るだけセーブデータも添付して下さい。
プログラムやシナリオデータのバグで 'sigsegv caught @xxx,xxxxx' といって
終了する場合は、そのメッセージの部分(xxx,xxxx)も送って下さい。
可能ならば、./configure で --enable-debug を付けてコンパイルしておき、
デバッガ上で実行して segmentation fault で止まった時に、bt と打って出てくる
メッセージを添付していただけるととても助かります。
-307
View File
@@ -1,307 +0,0 @@
xsystem35 における音楽環境について
0. もくじ
1. MIDIについて
a) 外部プレーヤーを使う方法
1) xsystem35 側の準備
2) プレイヤーの準備
3) xsystem35へのリダイレクト
4) 制限事項
b) 外部 MIDI 音源を /dev/midi 経由で制御する方法
1) xsystem35 側の準備
2) 外部 MIDI 音源の準備
c) Synthesizer 音源を /dev/sequencer 経由で制御する方法
1) xsystem35 側の準備
2) Synthesizer 音源の準備
d) オプション一覧
2. 効果音(WAV)について
a) OSS 出力
b) ALSA 出力
c) ESD 出力
3. CDオーディオについて
a) CD-ROM コントロールによる演奏
b) 外部プレイヤ(mp3など)による演奏
4. PCM & MIDI(timidity) & CD-ROM(MP3) を1枚のサウンドカードで同時に使う方法
1. MIDIについて
xsystem35 では MIDI の演奏に外部プレーヤーを使う方法と、サウンドカードの
MIDI port を介して接続した外部 MIDI 機器を /dev/midi 経由で制御する方法、
さらに、synthesizer device を OSS sequencer (/dev/sequencer) 経由で制御する
方法の3種類が選択できます。
a) 外部プレーヤーを使う方法
1) xsystem35 側の準備
xsystem35 の configure 実行時に --enable-midi=extp を付けてコンパイル
しておきます。
2) プレイヤーの準備
TiMidity や playmidi など、お好みのプレーヤーをお使いください。
プレイヤーへはあらかじめパスを通しておき、~/.xsys35rc にプレイヤーと
プレイヤーへの引数を記述します。
(例) TiMidity を esd 経由で出力する場合
midi_player: timidity -A 100 -s 44100 -Oe
2a) xsystem35へのリダイレクト (オプション)
TiMidity を使っている場合、TiMidity の PCM 出力を xsystem35 へとリダ
イレクトして xsystem35 側で管理しているPCM デバイスに流す事が出来ます。
~/.xsys35rc の MIDI プレーヤーの設定の際に先頭に '-' をつけて下さい。
(例)
midi_player: -timidity -A 100 -s 44100 -Or -o-
この場合 timidity の出力は 44.1kHz, Stereo, 16bit 固定です。
3) 制限事項
外部プレイヤーを 使用する場合、MIDIファイルに埋め込まれた system35 用の
制御コマンドを実行することができず、リピート再生、ジャンプ再生などが出来
ません。このため、ゲームの進行に支障が出ることがあります。
b) 外部 MIDI 音源を /dev/midi 経由で制御する方法
1) xsystem35 側の準備
xsystem35 の configure 実行時に --enable-midi=raw を付けてコンパイル
しておきます。
2) 外部 MIDI 音源の準備
外部 MIDI 音源(SC-88など)をサウンドカード の MIDI port を介して接続
します。このポートは /dev/midi デバイスを介して制御できる必要があります。
ALSA OSS Emulation 上で SB-Live の MIDI 端子に接続した SC-88 での動作を
確認しています。
c) Synthesizer 音源を /dev/sequencer 経由で制御する方法
1) xsystem35 側の準備
xsystem35 の configure 実行時に --enable-midi=seq を付けてコンパイル
しておきます。
2) Synthesizer 音源の準備
外部 MIDI 機器を接続するか、サウンドカード上に soundfont を load するか
TiMidity を ALSA sequencer server として常駐させておいてください。
TiMidity を ALSA sequencer server にするには、コンパイル時にその機能を
有効にしておき、timidity -iA で常駐させます。
d) オプション一覧
MIDI 出力に関する、 .xsys35rc の設定項目(A)とコマンドラインオプション(B)
をまとめます。
1) MIDI プレイヤーの設定
(A) ----> midi_player:
(B) ----> -midiplayer
2) MIDI デバイスファイルの設定 (default: /dev/midi or /dev/sequencer)
(A) ----> midi_device:
(B) ----> -devmidi
3) MIDI 出力方法の選択 (default: e)
(A) ----> midi_output_device: ?
(B) ----> -M?
? .... e : 外部プレーヤ
r : midi device 経由
sX: sequencer device 経由 (X番目のポート)
0 : (ゼロ) 無効化
コンパイル時に --enable-midi=extp,raw,seq とすることで、複数の方式を有効
にし、実行時にいずれかを選択できます。その他のコンパイルオプションは
INSTALL ドキュメントを御覧ください。
sequencer device の X 番目のポートは通常、0 ですが、複数のポートがある
場合はそのポート番号を指定してください。ALSA の OSS emu では、
$ cat /proc/asound/seq/oss
と実行して出て来る
midi ?: [xxxx] ALSA port aa:bb
の ? の番号を指定します。
コマンドラインから外部MIDIプレイヤーを指定する場合は
-midiplayer "timidity -A 100 -s 44100 -Oe" のようにします。
2. 効果音(WAV)について
xsystem35ではオーディオインターフェイスとして、Linux/*BSD などで良く使われて
いる OSS およびその互換インターフェイスに加えて、ALSA(Advanced Linux Sound
Architecture) と ESD(Enligtened Sound Daemon)に対応しています。
a) OSS 出力
1) コンパイル
configure 時に --enable-audio=oss オプションを付けてコンパイルします。
2) 実行時オプション
コマンドライン: -Oo
.xsys35rc : audio_output_device: o
3) dsp デバイス (default: /dev/dsp)
コマンドライン: -devdsp
.xsys35rc : dsp_device:
4) mixer デバイス (default: /dev/mixer)
コマンドライン: -devmix
.xsys35rc : mixer_device:
b) ALSA 出力
1) コンパイル
configure 時に --enable-audio=alsa オプションを付けてコンパイルします。
2) 実行時オプション
コマンドライン: -Os
.xsys35rc : audio_output_device: s
3) dsp デバイス (default: 0:0)
コマンドライン: -devdsp
.xsys35rc : dsp_device:
c) ESD 出力
1) コンパイル
configure 時に --enable-audio=esd オプションを付けてコンパイルします。
2) 実行時オプション
コマンドライン: -Oe
.xsys35rc : audio_output_device: e
OSS/ALSA/ESD をすべて有効にしてコンパイルし、実行時にどの出力を使用するか
選択できます。configure 時に --enable-audio=oss,alsa,esd としてコンパイル
してください。
3. CDオーディオについて
CD-ROM の制御には Linux/FreeBSD/Irix のインターフェイスに対応しています。
また、CD-ROM デバイスを直接制御する他に、外部プレイヤを使って mp3 file など
を鳴らすことも出来ます。
a) CD-ROM コントロールによる演奏
環境によって自動的に適切なドライブが選択されコンパイルされます。
b) 外部プレイヤ(mp3など)による演奏
あらかじめ CD を MP3/WAV 化して起きます。また mpg123 などのプレイヤ
を用意し、パスを通しておきます。
1) コンパイル
configure 時に --enable-cdrom=mp3 オプションを追加します。CD-ROM
コントロールを実行時に使い分けたい時は --enable-cdrom=linux,mp3 などと
します。
3) プレイヤー名とファイルリストを書いた次のようなファイルを用意します。
% cat /game/kichiku.playlist
mpg123-esd -quite
/game/kichiku/mp3/trk02.mp3
/game/kichiku/mp3/trk03.mp3
/game/kichiku/mp3/trk04.mp3
/game/kichiku/mp3/trk05.mp3
/game/kichiku/mp3/trk06.mp3
というようなファイルを用意します。
1行目はプレーヤーとそのオプション
2行目以降はトラック2から順にファイルをならべます。(フルパスで指定します)
*) 適切に外部プレイヤーと演奏ファイルを用意すれば、データ形式は問いません。
3a) xsystem35 へのリダイレクト(オプション)
mpg123 などのプレイヤーのPCM 出力を xsystem35 へとリダイレクトして
xsystem35 側で管理しているPCM デバイスに流す事が出来ます。
上の kichiku.playlist ファイルのプレイヤの設定で先頭に '-' をつけて
ください。
(例)
-mpg123 -q -s
この場合 mpg123 の出力は 44.1kHz, Stereo, 16bit 固定です。
4) 実行時オプションに -devcd /game/kichiku.playlist と上で作成したファイル
を指定します。
CD-ROM に関する .xsys35rc の設定項目(A) と コマンドラインオプション(B) を
まとめます。
1) CD 出力方法の選択
(A) ----> cdrom_device: ???
(B) ----> -devcd ????
MP3 出力 => ???? にプレイリストを指定
CD-ROM => ???? にデバイスファイルを指定
2) CD-ROM デバイスファイルの設定 (defult /dev/cdrom)
(A) ----> cdrom_device: ???
(B) ----> -devcd: ????
4. PCM & MIDI(timidity) & CD-ROM(MP3) を1枚のサウンドカードで同時に使う方法
(special thanks to Fumihiko Murata)
サウンドカードを選ばない方法としては esd を使うことです。esd は対応した複数
のプログラムの音の出力を合成してサウンドカードに出力するプログラムです。
xsystem35/timidity/mp3 player を esd 対応にコンパイルすることで合成が可能
です。
また、Trident 4DWave DX/NX、SoundBlaster Live/ YAMAHA YMF724以降 などのサウ
ンドカードは PCM チャンネルを複数持っていて、対応のサウンドドライバーがあれば
PCMとMIDI(SoftwareMIDI)とMP3 を同時に鳴らすことが出来ます。たとえば
SoundBlaster Live + ALSA では
$ cat /proc/asound/pcm
00-00: emu10k1 : EMU10K1 : playback 32 : capture 1
00-01: emu10k1 mic : EMU10K1 MIC : capture 1
00-02: emu10k1 efx : EMU10K1 EFX : capture 1
のように PCM を 32 チャンネル持っていることが分かります。これは OSS でいうと
ころの /dev/dspN に最大 32 の PCM がぶら下がっているように見え、同時に 32 回
/dev/dspN を開くことが出来ます。
また Trident 4DWave DX/NX + ALSA では全部で64chあり、最大で32chを PCM playback
に割り当てる事ができます。最大チャンネルはモジュールロード時に 設定され、設定
数を使いきるまで同時に /dev/dspN を開く事ができます。
残りの 32ch は MIDI 用に設けられていて、PCM と MIDI の2つのバンクに分ける事
ができます。個々のチャンネルには PCM front volume がありますが、2つのバンク
をそれぞれ統括する Wave/Music Volume があり さらにそれらを合わせる PCM volume
があります。(最後に Master Volume)
図にすると次のようになります。
PCM Volume + - Wave Volume + - front volume- PCM Playback 0
| + - .. - PCM Playback 1
| :
| + - .. - PCM Playback 31
|
+ - Music Volume + - .. - PCM Playback 32
:
+ - .. - PCM Playback 63
ES1370/1371 でも PCM 用 と MIDI 用に 2 チャンネルの PCM 出力があります。
ALSA では
$ cat /proc/asound/pcm
00-00: ES1371/1 : ES1371 DAC2/ADC : playback 1 : capture 1
00-01: ES1371/2 : ES1371 DAC1 : playback 1
のように 0:0 と 0:1 のデバイスが再生用として使う事が出来ます。timidity 用に
0:1 のデバイスを使うと良いでしょう。OSS では /dev/dsp0 と /dev/dsp1 に割り当
てられ、 /dev/dsp1 を timidity で使います。
またその他のカードでも多チャンネル出力を持っているものもありますので、
ドライバーのドキュメントを御覧下さい。
(2003.1.23 追記)
追記を書いている時点で手に入りやすい多チャンネルPCM出力をもつ音源カード
としては SoundBlaster Live と YMF7xx くらいでしょうか。
-57
View File
@@ -1,57 +0,0 @@
TODO (順番は特に無し)
* メンテナンス
-- obsolete
* TODOを増やさない
* SYSTEM3の3.5への移植ものや、ネット上にあるSYSTEM3.5のデータへの対応
* system 3.9への対応
* Xのイベントハンドリングの改良
* oringinal の savedata(v1/v2/v3?) を convert する tool
* savedata を lt/bg でどっちでも読めるようにする
* XIM 対応?
* 関数/変数名の統一
* 技術情報のドキュメント化
* GUI付 installer (っていうか、CD-ROMの中の setup.infを直接使う)
* 異常終了時に出来るだけプロセスが残らないようにする
* global変数を減らす
* 意図的な異常シナリオデータでもsegv.らないよう努力する
* Tab/Spaceの混在などソースの見直し(随時)
* CEの残りのコマンドをさっさと実装する
* SDL を理解して cleanup
* キー入力まわりの cleanup
* UNIX+X 以外の環境へ移植しやすくする
* 王子様1/16
+ スケジュールを組む時に「もどる」「クリア」「OK!」の選択がうまくで
きない。
* ランス4
+ プチハニーの爆風に巻き込まれると、キャラの上に「防」マークがつきっぱ
なしになる。
+ 戦闘シーンでたまに左上にモンスターのかけらが表示されることがある。
DONE
* configure 化
* gtk_setup.c rewrite
* keyboard操作対応
* cd/mp3の切替えをオプションで切替えられるようにする
* packed 24bpp対応 (rewrite xcore.c)
* music server cleanup
* dri mmap化
* 汎用 data cache 処理を作る。TTF フォントと展開済み CG で使おうか。
* alphabelnd asm化
* imgae.c をもうちょっとすっきりと。(depthで関数のテーブル化
* ecopy のタイミングの最適化
* wav が鳴らない事がしばしばある(open err)のを調査&修正
* *.h の依存関係 cleanup, 特に xsystem35.h
* xcore/imageの統合とcleanup
* MIDIの自前のハンドリング(/dev/sequener ?)
* FullScreen対応(with DGA)
* 古いドキュメントをなんとかする。(FAQ/BUGS etc)
* 大悪司
+ SDLの時、MAP選択が正常に動かない。
+155
View File
@@ -0,0 +1,155 @@
= xsystem35(6)
:doctype: manpage
:manmanual: xsystem35 manual
:mansource: xsystem35 {xsystem35-version}
== Name
xsystem35 - play System 3.x games
== SYNOPSIS
*xsystem35* [_OPTION_]...
== DESCRIPTION
This man page describes *xsystem35-sdl2*, a multi-platform port of the
AliceSoft's System3.5/3.6/3.8/3.9 game engine derived from the original
*xsystem35*.
`xsystem35` reads the game resource file from the path specified by the
`-gamefile` option, or from `xsystem35.gr` in the current directory if the
option is not specified. If the game resource file is not found, `xsystem35`
finds System 3.x game files (*.ALD) from the current directory.
== OPTIONS
*-gamefile* _file_::
Load game resouce file from _file_. See <<FILES>> section for details.
*-game* _game_::
Enables game-specific hacks. Usually auto-detected, but must be specified for
games with modified / translated titles. Possible values are: `toushin2`,
`rance2`, `rance3`, `rance3_eng`, `rance4_eng`, `rance4_v2`, `persiom`,
`agake`.
*-savedir* _dir_::
Directory to save game state files. If _dir_ begins with '~', it is expanded
to the user's home directory (`$HOME`).
*-saveformat* _fmt_::
The format when writing save files. Possible values are: `xsystem35`,
`system36`, `system39` (default).
*-texthook* _mode_::
Set the text hook mode. Possible values are: `none` (default), `print` (print
text to console), `copy` (copy text to clipboard).
*-texthook_suppress* _list_::
Suppress text hook on specified scenario pages. _list_ is a comma-separated
list of page numbers. Used to suppress system messages, etc.
*-censor* _file_::
Enable Streamer Mode, which mosaics specific images to make them safe for
streaming. The _file_ is a text file containing a list of image numbers
to censor, one per line. Lines starting with '#' are treated as comments.
*-renderer* _name_::
Use the SDL rendering driver named _name_.
*-playlist* _file_::
Load the CD playlist from _file_. The playlist is a text file with one
filename per line, in the order of CD tracks. See <<FILES>> section for details.
*-Me*::
Use SDL_mixer for MIDI playback.
**-Mp**_device_number_::
Use ALSA (via PortMidi) for MIDI playback.
*-M0*::
Disable MIDI playback.
*-devjoy* _device_index_::
Use the joystick device with the given index.
*-ttfont_mincho* _file_::
Use the given TrueType or OpenType font file for mincho (serif) text.
*-ttfont_gothic* _file_::
Use the given TrueType or OpenType font file for gothic (sans-serif) text.
*-debuglv* _level_::
Set the debug level to _level_. The higher the level, the more verbose
the debug output.
*-debug*::
Start with the debugger enabled.
*-noantialias*::
Disable text antialiasing.
*-fullscreen*::
Start in fullscreen mode.
*-integerscale*::
Use integer scaling for the window.
*-noimagecursor*::
Disable custom mouse cursor images.
*-version*::
Print the version number and exit.
*-h, --help*::
Print a help message and exit.
== FILES
*.xsys35rc*::
`xsystem35` reads its configuration from `${HOME}/.xsys35rc` and `.xsys35rc`
in the game directory. The latter takes precedence over the former, so you
can put general settings in `${HOME}/.xsys35rc` and game-specific settings in
`.xsys35rc` in the game directory. Options specified on the command line
override both. See xsys35rc.sample for the format of the configuration file.
*playlist.txt*::
`xsystem35` does not support playing BGM directly from a CD. Instead, it
supports playing BGM from audio files on your filesystem. `xsystem35` reads
the playlist from a file specified by the `-playlist` option, or from
`playlist.txt` in the game directory. The first line is the path to the audio
file for track 1, the second line is the path to the audio file for track 2,
and so on. The first line is usually empty, because track 1 is not an audio
track but a data track.
*xsystem35.gr*::
Game resource file which lists the locations of various files needed to run
a game. This is optional; `xsystem35` can automatically find the files it
needs when run inside a game directory. See
xref:xsystem35.gr.adoc[*xsystem35.gr(5)*] for the format of the game resource
file.
== KEYBOARD SHORTCUTS
System 3.x games basically only use the UP, DOWN, LEFT, RIGHT, SPACE, RET, ESC,
and TAB keys (some games use other keys). `xsystem35` uses the following
special key assignments:
*F1*::
Toggle message skip mode.
*F4*::
Toggle fullscreen mode.
Also, in some platforms, the middle mouse button opens the menu.
== HISTORY
*xsystem35* was originally developed by Masaki Chikama (Wren)
<masaki-c@is.aist-nara.ac.jp> between 1998 and 2006. The project was later
forked by Kichikuou <KichikuouChrome@gmail.com> as *xsystem35-sdl2* and ported
to SDL2.
== SEE ALSO
xsystem35-sdl2 project page: https://github.com/kichikuou/xsystem35-sdl2
+103
View File
@@ -0,0 +1,103 @@
= xsystem35.gr(5)
:doctype: manpage
:manmanual: xsystem35 manual
:mansource: xsystem35 {xsystem35-version}
== Name
xsystem35.gr - game resource file for xsystem35
== DESCRIPTION
Game resource file is a plain text file that defines the locations of the
various game data files for xsystem35. This file is only needed if you want to
place game data files in a location other than the current directory.
The path to the game resource file is specified with the `-gamefile` option of
xref:xsystem35.adoc[*xsystem35(6)*]. If it is not specified, xsystem35 reads
`xsystem35.gr` in the current directory.
Each line of the file specifies a single data file and follows the format:
_keyword_ _path-to-data_
If multiple files of the same type exist, suffixes `A`, `B`, `C`... are
appended to the _keyword_.
Comments can be added by starting the line with `#`. Blank lines are ignored.
== KEYWORDS
*Scenario*::
Scenario files (`*S?.ALD`).
*Graphics*::
Graphic files (`*G?.ALD`).
*Wave*::
PCM data files (`*W?.ALD`).
*Midi*::
MIDI data files (`*M?.ALD`).
*Data*::
Miscellaneous data files (`*D?.ALD`).
*Resource*::
Resource files (`*R?.ALD`).
*BGM*::
BGM files (`*B?.ALD`).
*Save*::
Save files (`*S?.ASD`). If the path begins with '`~`', it is expanded to the
user's home directory (`$HOME`).
*Ain*::
The `System39.ain` file.
*WAI*::
Additional information for PCM data (`*WA.WAI`)
*BGI*::
Additional information for BGM data (`*BA.BGI`)
*SACT01*::
Data for SACT.DLL (`SACTEFAM.KLD`)
*ALK01* - *ALK09*::
Archive files for demo data (`*1.ALK` - `*9.ALK`)
*Init*::
The `System39.ini` file.
== NOTES
Data files not categorized under the above keywords (e.g., map files for
Kaeru nyo Panyon) should not be listed in the game resource file, and should be
placed in the same directory as the save files.
== EXAMPLES
The following is a game resource file for the English translation of Kichikuou
Rance.
ScenarioA KICHIKUSA.ALD
GraphicsA KICHIKUGA.ALD
GraphicsB KICHIKUGB.ALD
WaveA KICHIKUWA.ALD
Ain System39.ain
SaveA ~/.xsys35/saves/kichikuou/KICHIKUSA.ASD
SaveB ~/.xsys35/saves/kichikuou/KICHIKUSB.ASD
SaveC ~/.xsys35/saves/kichikuou/KICHIKUSC.ASD
SaveD ~/.xsys35/saves/kichikuou/KICHIKUSD.ASD
SaveE ~/.xsys35/saves/kichikuou/KICHIKUSE.ASD
SaveF ~/.xsys35/saves/kichikuou/KICHIKUSF.ASD
SaveG ~/.xsys35/saves/kichikuou/KICHIKUSG.ASD
SaveH ~/.xsys35/saves/kichikuou/KICHIKUSH.ASD
SaveI ~/.xsys35/saves/kichikuou/KICHIKUSI.ASD
SaveJ ~/.xsys35/saves/kichikuou/KICHIKUSJ.ASD
== SEE ALSO
xref:xsystem35.adoc[*xsystem35(6)*]
-2
View File
@@ -1,8 +1,6 @@
install(FILES
MTLc3m.ttf
MTLc3m.ttf.license
mincho.otf
mincho.otf.license
DESTINATION share/xsystem35/fonts)
# pyftsubset is included in fonttools.
+13 -11
View File
@@ -4,12 +4,12 @@ Game Compatibility
| Game | Status | Notes |
| ------------------------------------------- | ----------- | ----- |
| 鬼畜王ランス | Supported | |
| Kichikuou Rance (EN) | Supported | |
| RanceIV -教団の遺産- | Supported | Win95 edition, [Ver2.05](https://hannylaboratory.blogspot.com/2023/01/blog-post_26.html) |
| Rance4 -Legacy of the Sect- (EN) | Supported | |
| 兰斯IV -教团的遗产- (CN) | Supported | |
| ランス4.1 | Supported | [Ver1.05](https://hannylaboratory.blogspot.com/2023/02/blog-post_9.html) |
| ランス4.2 | Supported | [Ver1.05](https://hannylaboratory.blogspot.com/2023/02/blog-post_9.html) |
| Kichikuou Rance (EN) | Supported | Fan translation |
| RanceIV -教団の遺産- | Supported | Win95 edition and [Ver2.05](https://hannylaboratory.blogspot.com/2023/01/blog-post_26.html) |
| Rance4 -Legacy of the Sect- (EN) | Supported | Fan translation |
| 兰斯IV -教团的遗产- (CN) | Supported | Fan translation |
| ランス4.1 | Supported | [Ver1.05](https://hannylaboratory.blogspot.com/2023/02/blog-post_9.html). Use system3-sdl2 for older versions |
| ランス4.2 | Supported | [Ver1.05](https://hannylaboratory.blogspot.com/2023/02/blog-post_9.html). Use system3-sdl2 for older versions |
| いけないかつみ先生 | Supported | Emojis are not supported |
| 闘神都市II | Supported | Win95 edition |
| かえるにょ・ぱにょ~ん | Supported | Normal / Low-priced edition |
@@ -52,12 +52,14 @@ Game Compatibility
| 妻みぐい | Supported | Opening demo is not supported |
| 超昂天使エスカレイヤー | Supported | Opening demo is not supported |
| ランス5D | Supported | |
| Rance 5D - The Lonely Girl (MangaGamer) | Supported | |
| 俺の下であがけ | Unknown | |
| 楽園行 | Unknown | |
| 妻みぐい2 | Supported | Opening demo is not supported |
| Rance 5D - The Lonely Girl (EN) | Supported | MangaGamer version |
| 俺の下であがけ | Supported | |
| 楽園行 | Supported | |
| 妻みぐい2 | Supported | |
| シェル・クレイル | Supported | |
| ナイトデーモン | Supported | |
| Nor | Unsupported | |
| 翡翠の眸 | Unsupported | |
| 学園KING | Supported | From アリスCD |
| 学園KING 番外編 | Supported | From アリスCD |
| 蒼海に墜ちて | Supported | From アリスCD |
@@ -76,7 +78,7 @@ Game Compatibility
| マスカレイド | Supported | From アリスCD |
| キャロル ~聖なる鐘が響く夜~ | Supported | From アリスCD, Online match is not supported |
| できるかなー? | Supported | From アリスCD |
| Child Assassin | Supported | From アリスCD |
| Child Assassin | Unsupported | From アリスCD |
| Klavier | Supported | From アリスCD |
| 弱肉狂食 | Supported | From アリスCD |
| 眼鏡大戦2 | Supported | From アリスCD |
+22
View File
@@ -0,0 +1,22 @@
// NanoJPEG -- KeyJ's Tiny Baseline JPEG Decoder
// version 1.3.5 (2016-11-14)
// Copyright (c) 2009-2016 Martin J. Fiedler <martin.fiedler@gmx.net>
// published under the terms of the MIT license
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+21
View File
@@ -0,0 +1,21 @@
# Censor Lists for Streamer Mode
This directory contains sample censor lists for various games, intended for use
with xsystem35's Streamer Mode.
## Usage
To use a censor list, specify its path with the `-censor` command-line option
or in your `.xsys35rc` file. For example:
```bash
xsystem35 -censor misc/censor/kichikuou.txt
```
The list files contain image numbers (integers), one per line. Lines starting
with `#` are treated as comments.
## Contributing
We welcome contributions of censor lists for other games! If you have created
a censor list that you'd like to share, please open a Pull Request.
+164
View File
@@ -0,0 +1,164 @@
# Censor list for 鬼畜王ランス (Kichikuou Rance)
27
70
93
101
102
103
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
123
124
125
126
127
128
129
130
131
132
133
134
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
160
161
162
163
164
165
166
167
168
169
171
172
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
193
195
196
197
198
199
200
201
203
204
205
206
207
208
209
210
214
215
216
217
218
219
221
222
224
225
226
227
228
229
230
231
232
233
234
235
239
299
300
361
362
363
375
376
377
393
422
461
466
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
517
844
845
846
847
848
851
852
853
854
855
+3 -3
View File
@@ -16,21 +16,21 @@ static void Init() {
*var = 1;
DEBUG_COMMAND_YET("AliceLogo.Init %d,%d,%d,%p:", p1, p2, p3, var);
TRACE_UNIMPLEMENTED("AliceLogo.Init %d,%d,%d,%p:", p1, p2, p3, var);
}
static void SetWaveNum() {
int p1 = getCaliValue();
int p2 = getCaliValue();
DEBUG_COMMAND_YET("AliceLogo.SetWaveNum %d,%d:", p1, p2);
TRACE_UNIMPLEMENTED("AliceLogo.SetWaveNum %d,%d:", p1, p2);
}
static void Run() {
int p1 = getCaliValue();
int p2 = getCaliValue();
DEBUG_COMMAND_YET("AliceLogo.Run %d,%d:", p1, p2);
TRACE_UNIMPLEMENTED("AliceLogo.Run %d,%d:", p1, p2);
}
static const ModuleFunc functions[] = {
+9 -35
View File
@@ -5,7 +5,12 @@ add_library(modules STATIC
AliceLogo/AliceLogo.c
Confirm/Confirm.c
Gpx/Gpx.c
Gpx/cg.c
Gpx/effectcopy.c
Gpx/graph_copy_amap.c
Gpx/graph_fillrect_amap.c
Gpx/graph.c
Gpx/surface.c
Math/Math.c
MsgSkip/MsgSkip.c
NIGHTDLL/NIGHTDLL.c
@@ -23,6 +28,7 @@ add_library(modules STATIC
NIGHTDLL/nt_sound.c
NightDemonDemo/NightDemonDemo.c
RandMT/RandMT.c
S3xMusic/S3xMusic.c
SACT/SACT.c
SACT/sactcg.c
SACT/sactsound.c
@@ -60,27 +66,8 @@ add_library(modules STATIC
eeDemo/eeDemo.c
lib/alk.c
lib/drawtext.c
lib/graph.c
lib/list.c
lib/surface.c
lib/cg.c
lib/graph_expandcolor_blend.c
lib/graph_fillrect.c
lib/graph_fillrect_amap.c
lib/graph_fillrect_acolor.c
lib/graph_rect.c
lib/graph_copy.c
lib/graph_copy_amap.c
lib/graph_copy_bright.c
lib/graph_blend_amap.c
lib/graph_blend_screen.c
lib/graph_saturadd_amap.c
lib/graph_draw_amap.c
lib/graph_stretch.c
lib/graph_cg.c
lib/gre_blend_useamap.c
lib/gre_blend.c
lib/gre_blend_screen.c
nDEMO/nDEMO.c
nDEMOE/nDEMOE.c
oDEMO/oDEMO.c
@@ -98,20 +85,7 @@ endif()
target_compile_options(modules PRIVATE -Wno-pointer-sign)
if (EMSCRIPTEN)
set(LIBS
"SHELL:-s USE_ZLIB=1"
"SHELL:-s USE_SDL=2")
target_compile_options(modules PRIVATE ${LIBS})
target_link_options(modules PRIVATE ${LIBS})
elseif (ANDROID)
target_link_libraries(modules PRIVATE ${ndk_zlib})
if (SDL2MIXER_FOUND)
target_link_libraries(modules PRIVATE SDL2 SDL2_mixer)
endif()
else()
target_link_libraries(modules PRIVATE ZLIB::ZLIB)
if (SDL2MIXER_FOUND)
target_link_libraries(modules PRIVATE PkgConfig::SDL2MIXER)
endif()
target_link_libraries(modules PRIVATE sdl2 zlib)
if (TARGET sdl2_mixer)
target_link_libraries(modules PRIVATE sdl2_mixer)
endif()
+4 -4
View File
@@ -10,7 +10,7 @@
static void Init() {
int p1 = getCaliValue();
DEBUG_COMMAND_YET("Confirm.Init %d:", p1);
TRACE_UNIMPLEMENTED("Confirm.Init %d:", p1);
}
static void ExistKeyFile() {
@@ -20,7 +20,7 @@ static void ExistKeyFile() {
*var = 1;
DEBUG_COMMAND_YET("Confirm.ExistKeyFile %s,%p,%p:",p1, p2, var);
TRACE_UNIMPLEMENTED("Confirm.ExistKeyFile %s,%p,%p:",p1, p2, var);
}
static void CheckProtectFile() {
@@ -30,7 +30,7 @@ static void CheckProtectFile() {
*var = 1;
DEBUG_COMMAND_YET("Confirm.CheckProtectFile %s,%p,%p:", p1,p2,var);
TRACE_UNIMPLEMENTED("Confirm.CheckProtectFile %s,%p,%p:", p1,p2,var);
}
static void CreateKeyFile() {
@@ -40,7 +40,7 @@ static void CreateKeyFile() {
*var = 1;
DEBUG_COMMAND_YET("Confirm.CreateKeyFile %s,%p,%p:", p1,p2,var);
TRACE_UNIMPLEMENTED("Confirm.CreateKeyFile %s,%p,%p:", p1,p2,var);
}
static const ModuleFunc functions[] = {
+115 -148
View File
@@ -42,7 +42,7 @@
// #include "alpha_plane.h"
#include "surface.h"
#include "graph.h"
// #include "graph2.h"
#include "graph_blend_amap.h"
#include "effectcopy.h"
#include "ngraph.h"
@@ -68,37 +68,19 @@ static int find_null_surface() {
return 0;
}
static int sf_free_one(int no) {
surface_t *s;
if (no == 0) return NG;
s = suf[no];
if (s == NULL) return NG;
if (s->pixel) free(s->pixel);
if (s->alpha) free(s->alpha);
free(s);
static void sf_free_one(int no) {
if (no == 0 || !suf[no]) return;
sf_free(suf[no]);
suf[no] = NULL;
pre_freesurfno = no;
return OK;
}
static int sf_free_all() {
int i;
surface_t *s;
for (i = 1; i < MAX_SURFACE; i++) {
if (suf[i] == NULL) continue;
s = suf[i];
if (s->pixel) free(s->pixel);
if (s->alpha) free(s->alpha);
free(s);
static void sf_free_all() {
for (int i = 1; i < MAX_SURFACE; i++) {
sf_free(suf[i]);
suf[i] = NULL;
}
pre_freesurfno = 1;
return OK;
}
static surface_t *sf_get(int no) {
@@ -136,7 +118,7 @@ static void Init() {
// surface0 を pre_freesurfno として返さないように。
pre_freesurfno = 1;
DEBUG_COMMAND("Gpx.Init %d:", p1);
TRACE("Gpx.Init %d:", p1);
}
static void Gpx_reset(void) {
@@ -151,18 +133,15 @@ static void Create() {
0
width : surface
height: surface
bpp : surface (24bppのみサポート,
xsystem35 display depth )
bpp : surface (24bppのみサポート)
*/
int *var = getCaliVariable();
int width = getCaliValue();
int height = getCaliValue();
int bpp = getCaliValue();
surface_t *s;
//get_surface0();
s = sf_create_surface(width, height, sf_get(0)->depth);
surface_t *s = sf_create_surface(width, height);
if (s == NULL) {
*var = 0;
} else {
@@ -171,7 +150,7 @@ static void Create() {
suf[no] = s;
}
DEBUG_COMMAND("Gpx.Create %p,%d,%d,%d:", var, width, height, bpp);
TRACE("Gpx.Create %p,%d,%d,%d:", var, width, height, bpp);
}
static void CreatePixelOnly() {
@@ -187,10 +166,9 @@ static void CreatePixelOnly() {
int width = getCaliValue();
int height = getCaliValue();
int bpp = getCaliValue();
surface_t *s;
s = sf_create_pixel(width, height, sf_get(0)->depth);
surface_t *s = sf_create_pixel(width, height);
if (s == NULL) {
*var = 0;
} else {
@@ -199,7 +177,7 @@ static void CreatePixelOnly() {
suf[no] = s;
}
DEBUG_COMMAND("Gpx.CreatePixelOnly %d,%d,%d,%d:", *var, width, height, bpp);
TRACE("Gpx.CreatePixelOnly %d,%d,%d,%d:", *var, width, height, bpp);
}
static void CreateAMapOnly() {
@@ -225,30 +203,22 @@ static void CreateAMapOnly() {
suf[no] = s;
}
DEBUG_COMMAND("Gpx.CreateAMapOnly %p,%d,%d:", var, width, height);
TRACE("Gpx.CreateAMapOnly %p,%d,%d:", var, width, height);
}
static void IsSurface() {
/*
Gpx.IsSurface(): surface surface
(pixel alpha )調
Gpx.IsSurface(): surface 調
p1 : surface
var : surface 1, !surface 0
*/
int p1 = getCaliValue();
int *var = getCaliVariable();
surface_t *s;
s = sf_get(p1);
if (s == NULL) {
*var = 0;
} else {
*var = (s->alpha && s->pixel) ? 1 : 0;
}
DEBUG_COMMAND("Gpx.IsSurface %d,%p:", p1, var);
*var = sf_get(p1) ? 1 : 0;
TRACE("Gpx.IsSurface %d,%p:", p1, var);
}
static void IsPixel() {
@@ -267,10 +237,10 @@ static void IsPixel() {
if (s == NULL) {
*var = 0;
} else {
*var = s->pixel ? 1 : 0;
*var = s->sdl_surface ? 1 : 0;
}
DEBUG_COMMAND("Gpx.IsPixel %d,%p:", p1, var);
TRACE("Gpx.IsPixel %d,%p:", p1, var);
}
static void IsAlpha() {
@@ -292,7 +262,7 @@ static void IsAlpha() {
*var = s->alpha ? 1 : 0;
}
DEBUG_COMMAND("Gpx.IsAlpha %d,%p:", p1, var);
TRACE("Gpx.IsAlpha %d,%p:", p1, var);
}
static void GetWidth() {
@@ -314,7 +284,7 @@ static void GetWidth() {
*var = s->width;
}
DEBUG_COMMAND("Gpx.GetWidth %d,%d:", p1, *var);
TRACE("Gpx.GetWidth %d,%d:", p1, *var);
}
static void GetHeight() {
@@ -336,13 +306,13 @@ static void GetHeight() {
*var = s->height;
}
DEBUG_COMMAND("Gpx.GetHeight %d,%d:", p1, *var);
TRACE("Gpx.GetHeight %d,%d:", p1, *var);
}
static void GetCreatedSurface() { /* not used ? */
int *var = getCaliVariable();
DEBUG_COMMAND_YET("Gpx.GetCreatedSurface %p:", var);
TRACE_UNIMPLEMENTED("Gpx.GetCreatedSurface %p:", var);
}
static void LoadCG() {
@@ -357,21 +327,21 @@ static void LoadCG() {
*var = load_cg_main(p1 -1);
DEBUG_COMMAND("Gpx.LoadCG %p,%d (%d):", var, p1, *var);
TRACE("Gpx.LoadCG %p,%d (%d):", var, p1, *var);
}
static void GetCGPosX() { /* not useed ? */
int *var = getCaliVariable();
int p1 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.GetCgPosX %p,%d:", var, p1);
TRACE_UNIMPLEMENTED("Gpx.GetCgPosX %p,%d:", var, p1);
}
static void GetCGPosY() { /* not useed ? */
int *var = getCaliVariable();
int p1 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.GetCgPosY %p,%d:", var, p1);
TRACE_UNIMPLEMENTED("Gpx.GetCgPosY %p,%d:", var, p1);
}
static void Free() {
@@ -382,7 +352,7 @@ static void Free() {
*/
int p1 = getCaliValue();
DEBUG_COMMAND("Gpx.Free %d:", p1);
TRACE("Gpx.Free %d:", p1);
if (p1 != 0) {
sf_free_one(p1);
@@ -395,7 +365,7 @@ static void FreeAll() {
*/
sf_free_all();
DEBUG_COMMAND("Gpx.FreeAll:");
TRACE("Gpx.FreeAll:");
}
static void Copy() {
@@ -421,25 +391,29 @@ static void Copy() {
int sh = getCaliValue();
surface_t *src, *dst;
DEBUG_COMMAND("Gpx.Copy %d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, ss, sx, sy, sw, sh);
TRACE("Gpx.Copy %d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, ss, sx, sy, sw, sh);
src = sf_get(ss);
dst = sf_get(ds);
gr_copy(dst, dx, dy, src, sx, sy, sw, sh);
}
static void CopyBright() { /* not used ? */
int p1 = getCaliValue();
int p2 = getCaliValue();
int p3 = getCaliValue();
int p4 = getCaliValue();
int p5 = getCaliValue();
int p6 = getCaliValue();
int p7 = getCaliValue();
int p8 = getCaliValue();
int p9 = getCaliValue();
static void CopyBright(void) {
int ds = getCaliValue();
int dx = getCaliValue();
int dy = getCaliValue();
int ss = getCaliValue();
int sx = getCaliValue();
int sy = getCaliValue();
int w = getCaliValue();
int h = getCaliValue();
int lv = getCaliValue();
DEBUG_COMMAND_YET("Gpx.CopyBright %d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9);
surface_t *dst = sf_get(ds);
surface_t *src = sf_get(ss);
gr_copy_bright(dst, dx, dy, src, sx, sy, w, h, lv);
TRACE("Gpx.CopyBright %d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, ss, sx, sy, w, h, lv);
}
static void CopyAMap() {
@@ -465,25 +439,29 @@ static void CopyAMap() {
int sh = getCaliValue();
surface_t *src, *dst;
DEBUG_COMMAND("Gpx.CopyAMap %d,%d,%d,%d,%d,%d,%d,%d:", da, dx, dy, sa, sx, sy, sw, sh);
TRACE("Gpx.CopyAMap %d,%d,%d,%d,%d,%d,%d,%d:", da, dx, dy, sa, sx, sy, sw, sh);
src = sf_get(sa);
dst = sf_get(da);
gr_copy_alpha_map(dst, dx, dy, src, sx, sy, sw, sh);
}
static void Blend() { /* not used ? */
int p1 = getCaliValue();
int p2 = getCaliValue();
int p3 = getCaliValue();
int p4 = getCaliValue();
int p5 = getCaliValue();
int p6 = getCaliValue();
int p7 = getCaliValue();
int p8 = getCaliValue();
int p9 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.Blend %d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9);
static void Blend(void) {
int ds = getCaliValue();
int dx = getCaliValue();
int dy = getCaliValue();
int ss = getCaliValue();
int sx = getCaliValue();
int sy = getCaliValue();
int w = getCaliValue();
int h = getCaliValue();
int lv = getCaliValue();
surface_t *dst = sf_get(ds);
surface_t *src = sf_get(ss);
gr_blend(dst, dx, dy, src, sx, sy, w, h, lv);
TRACE("Gpx.Blend %d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, ss, sx, sy, w, h, lv);
}
static void BlendSrcBright() { /* not used ? */
@@ -498,7 +476,7 @@ static void BlendSrcBright() { /* not used ? */
int p9 = getCaliValue();
int p10 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendSrcBright %d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
TRACE_UNIMPLEMENTED("Gpx.BlendSrcBright %d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
}
static void BlendAddSatur() { /* not used ? */
@@ -511,7 +489,7 @@ static void BlendAddSatur() { /* not used ? */
int p7 = getCaliValue();
int p8 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendAddStatur %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
TRACE_UNIMPLEMENTED("Gpx.BlendAddStatur %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
}
static void BlendAMap() {
@@ -537,7 +515,7 @@ static void BlendAMap() {
int sh = getCaliValue();
surface_t *src, *dst;
DEBUG_COMMAND("Gpx.BlendAMap %d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, ss, sx, sy, sw, sh);
TRACE("Gpx.BlendAMap %d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, ss, sx, sy, sw, sh);
src = sf_get(ss);
dst = sf_get(ds);
@@ -554,7 +532,7 @@ static void BlendAMapSrcOnly() { /* not used ? */
int p7 = getCaliValue();
int p8 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendAMapSrcOnly %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
TRACE_UNIMPLEMENTED("Gpx.BlendAMapSrcOnly %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
}
static void BlendAMapColor() { /* not used ? */
@@ -570,7 +548,7 @@ static void BlendAMapColor() { /* not used ? */
int p10 = getCaliValue();
int p11 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendAMapColor %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
TRACE_UNIMPLEMENTED("Gpx.BlendAMapColor %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
}
static void BlendAMapColorAlpha() { /* not used ? */
@@ -587,7 +565,7 @@ static void BlendAMapColorAlpha() { /* not used ? */
int p11 = getCaliValue();
int p12 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendAMapColorAlpha %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
TRACE_UNIMPLEMENTED("Gpx.BlendAMapColorAlpha %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
}
static void BlendAMapAlpha() { /* not used ? */
@@ -601,7 +579,7 @@ static void BlendAMapAlpha() { /* not used ? */
int p8 = getCaliValue();
int p9 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendAMapAlpha %d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9);
TRACE_UNIMPLEMENTED("Gpx.BlendAMapAlpha %d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9);
}
static void BlendAMapBright() { /* not used ? */
@@ -615,7 +593,7 @@ static void BlendAMapBright() { /* not used ? */
int p8 = getCaliValue();
int p9 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendAMapBright %d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9);
TRACE_UNIMPLEMENTED("Gpx.BlendAMapBright %d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9);
}
static void BlendAMapAlphaSrcBright() { /* not used ? */
@@ -630,7 +608,7 @@ static void BlendAMapAlphaSrcBright() { /* not used ? */
int p9 = getCaliValue();
int p10 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendAMapBright %d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
TRACE_UNIMPLEMENTED("Gpx.BlendAMapBright %d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
}
static void BlendUseAMapColor() { /* not used ? */
@@ -647,7 +625,7 @@ static void BlendUseAMapColor() { /* not used ? */
int p11 = getCaliValue();
int p12 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendUseAMapColor %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
TRACE_UNIMPLEMENTED("Gpx.BlendUseAMapColor %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
}
static void BlendScreen() { /* not used ? */
@@ -660,7 +638,7 @@ static void BlendScreen() { /* not used ? */
int p7 = getCaliValue();
int p8 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendScreen %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
TRACE_UNIMPLEMENTED("Gpx.BlendScreen %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
}
static void BlendMultiply() { /* not used ? */
@@ -673,7 +651,7 @@ static void BlendMultiply() { /* not used ? */
int p7 = getCaliValue();
int p8 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendMultiply %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
TRACE_UNIMPLEMENTED("Gpx.BlendMultiply %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
}
static void BlendScreenAlpha() { /* not used ? */
@@ -687,7 +665,7 @@ static void BlendScreenAlpha() { /* not used ? */
int p8 = getCaliValue();
int p9 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.BlendScreenAlpha %d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9);
TRACE_UNIMPLEMENTED("Gpx.BlendScreenAlpha %d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9);
}
static void Fill() {
@@ -713,7 +691,7 @@ static void Fill() {
int b = getCaliValue();
surface_t *dst;
DEBUG_COMMAND("Gpx.Fill %d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, r, g, b);
TRACE("Gpx.Fill %d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, r, g, b);
dst = sf_get(ds);
gr_fill(dst, dx, dy, dw, dh, r, g, b);
@@ -731,21 +709,24 @@ static void FillAlphaColor() { /* not used ? */
int lv = getCaliValue();
surface_t *dst;
DEBUG_COMMAND_YET("Gpx.FillAlphaColor %d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, r, g, b, lv);
TRACE("Gpx.FillAlphaColor %d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, r, g, b, lv);
dst = sf_get(ds);
gr_fill_alpha_color(dst, dx, dy, dw, dh, r, g, b, lv);
}
static void FillAMap() { /* not used ? */
int p1 = getCaliValue();
int p2 = getCaliValue();
int p3 = getCaliValue();
int p4 = getCaliValue();
int p5 = getCaliValue();
int p6 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.FillAMap %d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6);
static void FillAMap(void) {
int ds = getCaliValue();
int x = getCaliValue();
int y = getCaliValue();
int w = getCaliValue();
int h = getCaliValue();
int lv = getCaliValue();
surface_t *dst = sf_get(ds);
gr_fill_alpha_map(dst, x, y, w, h, lv);
TRACE("Gpx.FillAMap %d,%d,%d,%d,%d,%d:", ds, x, y, w, h, lv);
}
static void FillAMapOverBorder() {
@@ -770,7 +751,7 @@ static void FillAMapOverBorder() {
int d = getCaliValue();
surface_t *dst;
DEBUG_COMMAND("Gpx.FillAMapOverBorder %d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, s, d);
TRACE("Gpx.FillAMapOverBorder %d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, s, d);
dst = sf_get(ds);
gr_fill_alpha_overborder(dst, dx, dy, dw, dh, s, d);
@@ -785,7 +766,7 @@ static void FillAMapUnderBorder() { /* not used ? */
int p6 = getCaliValue();
int p7 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.FillAMapUnderBorder %d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7);
TRACE_UNIMPLEMENTED("Gpx.FillAMapUnderBorder %d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7);
}
static void SaturDP_DPxSA() { /* not used ? */
@@ -798,7 +779,7 @@ static void SaturDP_DPxSA() { /* not used ? */
int p7 = getCaliValue();
int p8 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.SaturDP_DPxSA %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
TRACE_UNIMPLEMENTED("Gpx.SaturDP_DPxSA %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
}
static void ScreenDA_DAxSA() { /* not used ? */
@@ -811,7 +792,7 @@ static void ScreenDA_DAxSA() { /* not used ? */
int p7 = getCaliValue();
int p8 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.ScreenDA_DAxSA %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
TRACE_UNIMPLEMENTED("Gpx.ScreenDA_DAxSA %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
}
static void AddDA_DAxSA() { /* not used ? */
@@ -824,7 +805,7 @@ static void AddDA_DAxSA() { /* not used ? */
int p7 = getCaliValue();
int p8 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.AddDA_DAxSA %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
TRACE_UNIMPLEMENTED("Gpx.AddDA_DAxSA %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
}
static void SpriteCopyAMap() {
@@ -852,7 +833,7 @@ static void SpriteCopyAMap() {
int cl = getCaliValue();
surface_t *src, *dst;
DEBUG_COMMAND("Gpx.SpriteCopyAMap %d,%d,%d,%d,%d,%d,%d,%d,%d:", da, dx, dy, sa, sx, sy, sw, sh, cl);
TRACE("Gpx.SpriteCopyAMap %d,%d,%d,%d,%d,%d,%d,%d,%d:", da, dx, dy, sa, sx, sy, sw, sh, cl);
src = sf_get(sa);
dst = sf_get(da);
@@ -879,7 +860,7 @@ static void BrightDestOnly() {
int r = getCaliValue();
surface_t *dst;
DEBUG_COMMAND("Gpx.BrightDestOnly %d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, r);
TRACE("Gpx.BrightDestOnly %d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, r);
dst = sf_get(ds);
@@ -900,7 +881,7 @@ static void CopyTextureWrap() { /* not used ? */
int p11 = getCaliValue();
int p12 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.CopyTextureWrap %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
TRACE_UNIMPLEMENTED("Gpx.CopyTextureWrap %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
}
static void CopyTextureWrapAlpha() { /* not used ? */
@@ -918,7 +899,7 @@ static void CopyTextureWrapAlpha() { /* not used ? */
int p12 = getCaliValue();
int p13 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.CopyTextureWrapAlpha %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
TRACE_UNIMPLEMENTED("Gpx.CopyTextureWrapAlpha %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
}
static void CopyStretch() {
@@ -948,7 +929,7 @@ static void CopyStretch() {
int sh = getCaliValue();
surface_t *src, *dst;
DEBUG_COMMAND_YET("Gpx.CopyStretch %d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, ss, sx, sy, sw, sh);
TRACE("Gpx.CopyStretch %d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, ss, sx, sy, sw, sh);
src = sf_get(ss);
dst = sf_get(ds);
@@ -968,7 +949,7 @@ static void CopyStretchBlend() { /* not used ? */
int p10 = getCaliValue();
int p11 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.CopyStretchBlend %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
TRACE_UNIMPLEMENTED("Gpx.CopyStretchBlend %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
}
static void CopyStretchBlendAMap() {
@@ -998,7 +979,7 @@ static void CopyStretchBlendAMap() {
int sh = getCaliValue();
surface_t *src, *dst;
DEBUG_COMMAND("Gpx.CopyStretchBlendAMap %d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, ss, sx, sy, sw, sh);
TRACE("Gpx.CopyStretchBlendAMap %d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, dw, dh, ss, sx, sy, sw, sh);
src = sf_get(ss);
dst = sf_get(ds);
@@ -1015,7 +996,7 @@ static void StretchBlendScreen2x2() { /* not used ? */
int p7 = getCaliValue();
int p8 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.StretchBlendScreen2x2 %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
TRACE_UNIMPLEMENTED("Gpx.StretchBlendScreen2x2 %d,%d,%d,%d,%d,%d,%d,%d:", p1, p2, p3, p4, p5, p6, p7, p8);
}
@@ -1049,7 +1030,7 @@ static void StretchBlendScreen2x2WDS() {
int sh = getCaliValue();
surface_t *src1, *src2, *dst;
DEBUG_COMMAND("Gpx.StretchBlendScreen2x2WDS %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, ss1, sx1, sy1, ss2, sx2, sy2, sw, sh);
TRACE("Gpx.StretchBlendScreen2x2WDS %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, ss1, sx1, sy1, ss2, sx2, sy2, sw, sh);
src1 = sf_get(ss1);
src2 = sf_get(ss2);
@@ -1086,7 +1067,7 @@ static void BlendScreenWDS() {
int sh = getCaliValue();
surface_t *src1, *src2, *dst;
DEBUG_COMMAND("Gpx.BlendScreenWDS %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, ss1, sx1, sy1, ss2, sx2, sy2, sw, sh);
TRACE("Gpx.BlendScreenWDS %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d:", ds, dx, dy, ss1, sx1, sy1, ss2, sx2, sy2, sw, sh);
src1 = sf_get(ss1);
src2 = sf_get(ss2);
@@ -1137,25 +1118,11 @@ static void EffectCopy() {
int sh = getCaliValue();
int time = getCaliValue();
int *var = getCaliVariable();
surface_t *dib, *dst, *src;
switch(no) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 7:
case 11:
case 12:
case 13:
DEBUG_COMMAND("Gpx.EffectCopy %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%p:", no, dx, dy, ss1, sx1, sy1, ss2, sx2, sy2, sw, sh, time, var);
break;
default:
DEBUG_COMMAND_YET("Gpx.EffectCopy %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%p:", no, dx, dy, ss1, sx1, sy1, ss2, sx2, sy2, sw, sh, time, var);
}
dst = sf_get(ss1);
src = sf_get(ss2);
TRACE("Gpx.EffectCopy %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%p:", no, dx, dy, ss1, sx1, sy1, ss2, sx2, sy2, sw, sh, time, var);
surface_t *dst = sf_get(ss1);
surface_t *src = sf_get(ss2);
gpx_effect(no, dx, dy, dst, sx1, sy1, src, sx2, sy2, sw, sh, time, var);
}
@@ -1163,7 +1130,7 @@ static void EffectCopy() {
static void SetClickCancelFlag() { /* not used ? */
int p1 = getCaliValue();
DEBUG_COMMAND_YET("Gpx.SetClikCancelFlag %d:", p1);
TRACE_UNIMPLEMENTED("Gpx.SetClikCancelFlag %d:", p1);
}
static const ModuleFunc functions[] = {
+20 -53
View File
@@ -33,9 +33,7 @@
#include "ags.h"
#include "pms.h"
#include "qnt.h"
#ifdef HAVE_WEBP
#include "webp.h"
#endif
#include "gfx.h"
#include "ngraph.h"
#include "dri.h"
#include "ald_manager.h"
@@ -53,10 +51,6 @@ static CG_TYPE check_cgformat(uint8_t *data) {
return ALCG_PMS8;
} else if (pms64k_checkfmt(data)) {
return ALCG_PMS16;
#ifdef HAVE_WEBP
} else if (webp_checkfmt(data)) {
return ALCG_WEBP;
#endif
}
return ALCG_UNKNOWN;
}
@@ -68,65 +62,38 @@ static CG_TYPE check_cgformat(uint8_t *data) {
* @return CG surface
* NULL
*/
surface_t *sf_getcg(void *b, size_t size) {
surface_t *sf = NULL;
int type;
cgdata *cg = NULL;
type = check_cgformat(b);
switch(type) {
static surface_t *sf_getcg(void *b, size_t size) {
surface_t *sf;
cgdata *cg;
switch(check_cgformat(b)) {
case ALCG_PMS8:
// Load as an alpha map
cg = pms256_extract(b);
cg->alpha = cg->pic;
cg->pic = NULL;
sf = sf_create_alpha(cg->width, cg->height);
gfx_drawImageAlphaMap(cg, sf, 0, 0);
break;
case ALCG_PMS16:
cg = pms64k_extract(b);
sf = cg->alpha
? sf_create_surface(cg->width, cg->height)
: sf_create_pixel(cg->width, cg->height);
gfx_drawImage16(cg, sf, 0, 0, 255, false);
break;
case ALCG_QNT:
cg = qnt_extract(b);
sf = cg->alpha
? sf_create_surface(cg->width, cg->height)
: sf_create_pixel(cg->width, cg->height);
gfx_drawImage24(cg, sf, 0, 0, 255);
break;
#ifdef HAVE_WEBP
case ALCG_WEBP:
cg = webp_extract(b, size);
break;
#endif
default:
break;
}
if (cg == NULL) {
WARNING("Unknown Cg Type");
return NULL;
}
switch(type) {
case ALCG_PMS8:
sf = sf_create_alpha(cg->width, cg->height);
gr_draw_amap(sf, cg->x, cg->y, cg->pic, cg->width, cg->height, cg->width);
break;
case ALCG_PMS16:
if (cg->alpha) {
sf = sf_create_surface(cg->width, cg->height, sf0->depth);
gr_drawimage16(sf, cg, cg->x, cg->y);
gr_draw_amap(sf, cg->x, cg->y, cg->alpha, cg->width, cg->height, cg->width);
} else {
sf = sf_create_pixel(cg->width, cg->height, sf0->depth);
gr_drawimage16(sf, cg, cg->x, cg->y);
}
break;
case ALCG_QNT:
case ALCG_WEBP:
if (cg->alpha) {
sf = sf_create_surface(cg->width, cg->height, sf0->depth);
gr_drawimage24(sf, cg, cg->x, cg->y);
gr_draw_amap(sf, cg->x, cg->y, cg->alpha, cg->width, cg->height, cg->width);
} else {
sf = sf_create_pixel(cg->width, cg->height, sf0->depth);
gr_drawimage24(sf, cg, cg->x, cg->y);
}
break;
}
cgdata_free(cg);
return sf;
}
+5 -5
View File
@@ -5,7 +5,7 @@
#include "portab.h"
#include "system.h"
#include "surface.h"
#include "sdl_core.h"
#include "effect.h"
#include "ags.h"
#include "input.h"
#include "graph.h"
@@ -24,17 +24,17 @@ void gpx_effect(int no,
*endtype = 0;
enum sdl_effect_type type = from_sact_effect(no);
enum effect_type type = from_sact_effect(no);
if (type == EFFECT_INVALID) {
WARNING("Unimplemented effect %d", no);
type = EFFECT_CROSSFADE;
}
SDL_Rect rect = { wx, wy, width, height };
struct sdl_effect *eff = sdl_effect_init(&rect, dst, dx, dy, src, sx, sy, type);
struct effect *eff = effect_init(&rect, dst, dx, dy, src, sx, sy, type);
if (!time)
time = (no == SACT_EFFECT_CROSSFADE_DOWN || no == SACT_EFFECT_CROSSFADE_UP) ? 1150 : 2700;
ags_runEffect(time, FALSE, (ags_EffectStepFunc)sdl_effect_step, eff);
sdl_effect_finish(eff);
ags_runEffect(time, false, (ags_EffectStepFunc)effect_step, eff);
effect_finish(eff);
switch (no) {
case SACT_EFFECT_FADEOUT:
+89 -177
View File
@@ -3,25 +3,15 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL.h>
#include "portab.h"
#include "system.h"
#include "surface.h"
#include "graph.h"
#include "ngraph.h"
#include "nact.h"
/*
gr_xxxx
gre_xxxx
*/
#undef WARNING
#define WARNING(...)
#undef NOTICE
#define NOTICE(...)
#include "ags.h"
#include "gfx.h"
/**
* surface surface surface
@@ -36,80 +26,16 @@
* @param ds: surface
* @param dx:
* @param dy:
* @return TRUE ->
* FALSE->
* @return true ->
* false->
* surfaceの範囲外になり
*
*/
boolean gr_clip(surface_t *ss, int *sx, int *sy, int *sw, int *sh, surface_t *ds, int *dx, int *dy) {
int w, h;
if (ss == NULL) {
WARNING("ss surface is null");
return FALSE;
}
if (ss == NULL) {
WARNING("ss surface is null");
return FALSE;
}
if (*sx > ss->width) {
WARNING("sx is too large (sx=%d,width=%d)", *sx, ss->width);
return FALSE;
}
if (*sy > ss->height) {
WARNING("sy is too large (sy=%d,height=%d)", *sy, ss->height);
return FALSE;
}
if (*sx < 0) {
WARNING("sx is too small (sx=%d)", *sx);
return FALSE;
}
if (*sy < 0) {
WARNING("sy is too small (sy=%d)", *sy);
return FALSE;
}
if (*dx > ds->width) {
WARNING("dx is too large (dx=%d,width=%d)", *dx, ds->width);
return FALSE;
}
if (*dy > ds->height) {
WARNING("dy is too large (dy=%d,height=%d)", *dy, ds->height);
return FALSE;
}
w = *sw;
h = *sh;
if (*dx < 0) {
*sx -= *dx; *sw += *dx; *dx = 0;
}
if (*dy < 0) {
*sy -= *dy; *sh += *dy; *dy = 0;
}
*sw = min(ss->width - *sx, min(ds->width - *dx, *sw));
*sh = min(ss->height - *sy, min(ds->height - *dy, *sh));
if (*sw <= 0) {
WARNING("sw become <=0");
return FALSE;
}
if (*sh <= 0) {
WARNING("sh become <=0");
return FALSE;
}
if (*sw != w) {
NOTICE("width change %d -> %d", w, *sw);
}
if (*sh != h) {
NOTICE("height change %d -> %d", h, *sh);
}
return TRUE;
bool gr_clip(surface_t *ss, int *sx, int *sy, int *sw, int *sh, surface_t *ds, int *dx, int *dy) {
if (!ss || !ds) return false;
SDL_Rect src_window = { 0, 0, ss->width, ss->height };
SDL_Rect dst_window = { 0, 0, ds->width, ds->height };
return ags_clipCopyRect(&src_window, &dst_window, sx, sy, dx, dy, sw, sh);
}
/**
@@ -120,67 +46,75 @@ boolean gr_clip(surface_t *ss, int *sx, int *sy, int *sw, int *sh, surface_t *ds
* @param sy:
* @param sw:
* @param sh:
* @return TRUE ->
* FALSE->
* @return true ->
* false->
* surfaceの範囲外になり
*
*/
boolean gr_clip_xywh(surface_t *ss, int *sx, int *sy, int *sw, int *sh) {
int w, h;
if (ss == NULL) {
WARNING("ss surface is null");
return FALSE;
}
if (*sx > ss->width) {
WARNING("sx is too large (sx=%d,width=%d)", *sx, ss->width);
return FALSE;
}
if (*sy > ss->height) {
WARNING("sy is too large (sy=%d,height=%d)", *sy, ss->height);
return FALSE;
}
w = *sw;
h = *sh;
if (*sx < 0) {
*sw += *sx; *sx = 0;
}
if (*sy < 0) {
*sh += *sy; *sy = 0;
}
*sw = min(ss->width - *sx, *sw);
*sh = min(ss->height - *sy, *sh);
if (*sw <= 0) {
WARNING("sw become <=0");
return FALSE;
}
if (*sh <= 0) {
WARNING("sh become <=0");
return FALSE;
}
if (*sw != w) {
NOTICE("width change %d -> %d", w, *sw);
}
if (*sh != h) {
NOTICE("height change %d -> %d", h, *sh);
}
return TRUE;
bool gr_clip_xywh(surface_t *ss, int *sx, int *sy, int *sw, int *sh) {
if (!ss) return false;
SDL_Rect rect = {*sx, *sy, *sw, *sh};
if (!SDL_IntersectRect(&rect, &(SDL_Rect){ 0, 0, ss->width, ss->height }, &rect))
return false;
*sx = rect.x;
*sy = rect.y;
*sw = rect.w;
*sh = rect.h;
return true;
}
void gr_init() {
}
void gr_copy(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int sw, int sh) {
if (!dst->sdl_surface || !src->sdl_surface) return;
if (!gr_clip(src, &sx, &sy, &sw, &sh, dst, &dx, &dy)) return;
SDL_Rect src_rect = {sx, sy, sw, sh};
SDL_Rect dst_rect = {dx, dy, sw, sh};
if (dst == src) {
SDL_Rect r;
if (SDL_IntersectRect(&src_rect, &dst_rect, &r)) {
SDL_Surface *view = gfx_createSurfaceView(src->sdl_surface, sx, sy, sw, sh);
SDL_Surface *tmp = SDL_ConvertSurface(view, dst->sdl_surface->format, 0);
src_rect.x = 0;
src_rect.y = 0;
SDL_LowerBlit(tmp, &src_rect, dst->sdl_surface, &dst_rect);
SDL_FreeSurface(tmp);
SDL_FreeSurface(view);
return;
}
}
SDL_LowerBlit(src->sdl_surface, &src_rect, dst->sdl_surface, &dst_rect);
}
// Copy the specified surface area with brightness lv/255 times
void gr_copy_bright(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int lv) {
SDL_Rect src_rect = {sx, sy, width, height};
SDL_Rect dst_rect = {dx, dy, width, height};
SDL_SetSurfaceColorMod(src->sdl_surface, lv, lv, lv);
SDL_BlitSurface(src->sdl_surface, &src_rect, dst->sdl_surface, &dst_rect);
SDL_SetSurfaceColorMod(src->sdl_surface, 255, 255, 255);
}
void gr_fill(surface_t *dst, int dx, int dy, int dw, int dh, int r, int g, int b) {
SDL_Rect rect = {dx, dy, dw, dh};
uint32_t color = SDL_MapRGB(dst->sdl_surface->format, r, g, b);
SDL_FillRect(dst->sdl_surface, &rect, color);
}
void gr_copy_stretch(surface_t *dst, int dx, int dy, int dw, int dh, surface_t *src, int sx, int sy, int sw, int sh) {
SDL_Rect srcrect = {sx, sy, sw, sh};
SDL_Rect dstrect = {dx, dy, dw, dh};
SDL_BlitScaled(src->sdl_surface, &srcrect, dst->sdl_surface, &dstrect);
}
void gr_blend(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int lv) {
SDL_SetSurfaceBlendMode(src->sdl_surface, SDL_BLENDMODE_BLEND);
SDL_SetSurfaceAlphaMod(src->sdl_surface, lv);
SDL_BlitSurface(src->sdl_surface, &(SDL_Rect){sx, sy, width, height}, dst->sdl_surface, &(SDL_Rect){dx, dy, width, height});
SDL_SetSurfaceAlphaMod(src->sdl_surface, 255);
SDL_SetSurfaceBlendMode(src->sdl_surface, SDL_BLENDMODE_NONE);
}
void gr_blend_src_bright(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int alpha, int rate) {
@@ -271,56 +205,34 @@ void gr_copy_stretch_blend_alpha_map(surface_t *dst, int dx, int dy, int dw, int
row[x] = xd; xd += a1;
}
switch(dst->depth) {
case 16:
{
uint16_t *yls, *yld;
uint8_t *yla;
for (y = 0; y < dh; y++) {
yls = (uint16_t *)(sp + *(y + col) * src->bytes_per_line);
yld = (uint16_t *)(dp + y * dst->bytes_per_line);
yla = (uint8_t *)(sa + *(y + col) * src->width);
for (x = 0; x < dw; x++) {
*(yld + x) = ALPHABLEND16(*(yls+ *(row + x)), *(yld+x), *(yla+*(row+x)));
}
while(*(col + y) == *(col + y + 1)) {
yld += dst->width;
for (x = 0; x < dw; x++) {
*(yld + x) = ALPHABLEND16(*(yls+ *(row+x)), *(yld+x), *(yla+*(row+x)));
}
y++;
}
for (y = 0; y < dh; y++) {
uint32_t *yls = (uint32_t *)(sp + *(y + col) * src->sdl_surface->pitch);
uint32_t *yld = (uint32_t *)(dp + y * dst->sdl_surface->pitch);
uint8_t *yla = (uint8_t *)(sa + *(y + col) * src->width);
for (x = 0; x < dw; x++) {
*(yld + x) = ALPHABLEND24(*(yls+ *(row + x)), *(yld+x), *(yla+*(row+x)));
}
break;
}
case 24:
case 32:
{
uint32_t *yls, *yld;
uint8_t *yla;
for (y = 0; y < dh; y++) {
yls = (uint32_t *)(sp + *(y + col) * src->bytes_per_line);
yld = (uint32_t *)(dp + y * dst->bytes_per_line);
yla = (uint8_t *)(sa + *(y + col) * src->width);
while (y < dh - 1 && *(col + y) == *(col + y + 1)) {
yld += dst->width;
for (x = 0; x < dw; x++) {
*(yld + x) = ALPHABLEND24(*(yls+ *(row + x)), *(yld+x), *(yla+*(row+x)));
}
while(*(col + y) == *(col + y + 1)) {
yld += dst->width;
for (x = 0; x < dw; x++) {
*(yld + x) = ALPHABLEND24(*(yls+ *(row+x)), *(yld+x), *(yla+*(row+x)));
}
y++;
*(yld + x) = ALPHABLEND24(*(yls+ *(row+x)), *(yld+x), *(yla+*(row+x)));
}
y++;
}
break;
}
}
free(row);
free(col);
}
// Fill the rectangle with the specified color (rgb) and blend rate (lv)
void gr_fill_alpha_color(surface_t *dst, int dx, int dy, int dw, int dh, int r, int g, int b, int lv) {
SDL_Surface *src = SDL_CreateRGBSurfaceWithFormat(0, dw, dh, 32, SDL_PIXELFORMAT_ARGB8888);
SDL_FillRect(src, NULL, SDL_MapRGBA(src->format, r, g, b, lv));
SDL_SetSurfaceBlendMode(src, SDL_BLENDMODE_BLEND);
SDL_Rect dstrect = {dx, dy, dw, dh};
SDL_BlitSurface(src, NULL, dst->sdl_surface, &dstrect);
SDL_FreeSurface(src);
}
#include "graph2.c"
+23
View File
@@ -0,0 +1,23 @@
#ifndef __GRAPH_H__
#define __GRAPH_H__
#include "config.h"
#include "surface.h"
void gr_init();
void gr_copy(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int sw, int sh);
void gr_copy_bright(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int lv);
void gr_fill(surface_t *dst, int dx, int dy, int dw, int dh, int r, int g, int b);
void gr_copy_stretch(surface_t *dst, int dx, int dy, int dw, int dh, surface_t *src, int sx, int sy, int sw, int sh);
void gr_blend(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int lv);
void gr_copy_stretch_blend_alpha_map(surface_t *dst, int dx, int dy, int dw, int dh, surface_t *src, int sx, int sy, int sw, int sh);
void gr_fill_alpha_color(surface_t *dst, int dx, int dy, int dw, int dh, int r, int g, int b, int lv);
void gr_fill_alpha_overborder(surface_t *dst, int dx, int dy, int dw, int dh, int s, int d);
void gr_fill_alpha_underborder(surface_t *dst, int dx, int dy, int dw, int dh, int s, int d);
void gr_copy_alpha_map_sprite(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int sw, int sh, int cl);
void gr_blend_alpha_wds_stretch2x2(surface_t *src1, int sx1, int sy1, surface_t *src2, int sx2, int sy2, int sw, int sh, surface_t *dst, int dx, int dy);
void gr_blend_alpha_wds(surface_t *src1, int sx1, int sy1, surface_t *src2, int sx2, int sy2, int sw, int sh, surface_t *dst, int dx, int dy);
#endif /* __GRAPH_H__ */
+9 -38
View File
@@ -75,7 +75,7 @@ void gr_copy_alpha_map_sprite(surface_t *dst, int dx, int dy, surface_t *src, in
}
void gr_blend_alpha_wds_stretch2x2(surface_t *src1, int sx1, int sy1, surface_t *src2, int sx2, int sy2, int sw, int sh, surface_t *dst, int dx, int dy) {
surface_t *t = sf_create_surface(sw * 2, sh * 2, dst->depth);
surface_t *t = sf_create_surface(sw * 2, sh * 2);
gr_copy_stretch(t, 0, 0, sw * 2, sh * 2, src2, sx2, sy2, sw, sh);
gr_blend_alpha_wds(t, 0, 0, src1, sx1, sy1, sw * 2, sh * 2, dst, dx, dy);
@@ -93,45 +93,16 @@ void gr_blend_alpha_wds(surface_t *src1, int sx1, int sy1, surface_t *src2, int
sa = GETOFFSET_ALPHA(src1, sx1, sy1);
dp = GETOFFSET_PIXEL(dst, dx, dy);
switch(dst->depth) {
case 16:
{
uint16_t *yls1, *yls2, *yld;
uint8_t *yla;
for (y = 0; y < sh; y++) {
yls1 = (uint16_t *)(sp1 + y * src1->bytes_per_line);
yls2 = (uint16_t *)(sp2 + y * src2->bytes_per_line);
yld = (uint16_t *)(dp + y * dst->bytes_per_line);
yla = (uint8_t *)(sa + y * src1->width);
for (x = 0; x < sw; x++) {
*yld = SUTURADD16(*yls1, ALPHABLEND16(*yls1, *yls2, *yla));
//*yld = SUTURADD16(*yls1, ALPHALEVEL16(*yls2, *yla));
yls1++; yls2++; yld++; yla++;
}
}
}
break;
case 24:
case 32:
{
uint32_t *yls1, *yls2, *yld;
uint8_t *yla;
for (y = 0; y < sh; y++) {
uint32_t *yls1 = (uint32_t *)(sp1 + y * src1->sdl_surface->pitch);
uint32_t *yls2 = (uint32_t *)(sp2 + y * src2->sdl_surface->pitch);
uint32_t *yld = (uint32_t *)(dp + y * dst->sdl_surface->pitch);
uint8_t *yla = (uint8_t *)(sa + y * src1->width);
for (y = 0; y < sh; y++) {
yls1 = (uint32_t *)(sp1 + y * src1->bytes_per_line);
yls2 = (uint32_t *)(sp2 + y * src2->bytes_per_line);
yld = (uint32_t *)(dp + y * dst->bytes_per_line);
yla = (uint8_t *)(sa + y * src1->width);
for (x = 0; x < sw; x++) {
*yld = SUTURADD24(*yls1, ALPHABLEND24(*yls1, *yls2, *yla));
yls1++; yls2++; yld++; yla++;
}
for (x = 0; x < sw; x++) {
*yld = SUTURADD24(*yls1, ALPHABLEND24(*yls1, *yls2, *yla));
yls1++; yls2++; yld++; yla++;
}
break;
}
}
}
@@ -41,22 +41,22 @@
* @param sw:
* @param sh:
*/
int gr_copy_alpha_map(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int sw, int sh) {
void gr_copy_alpha_map(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int sw, int sh) {
uint8_t *sp, *dp;
if (!gr_clip(src, &sx, &sy, &sw, &sh, dst, &dx, &dy)) return NG;
if (!gr_clip(src, &sx, &sy, &sw, &sh, dst, &dx, &dy)) return;
sp = GETOFFSET_ALPHA(src, sx, sy);
dp = GETOFFSET_ALPHA(dst, dx, dy);
if (sp == NULL) {
WARNING("src alpha NULL");
return NG;
return;
}
if (dp == NULL) {
WARNING("dst alpha NULL");
return NG;
return;
}
if (src == dst) {
@@ -82,6 +82,4 @@ int gr_copy_alpha_map(surface_t *dst, int dx, int dy, surface_t *src, int sx, in
dp += dst->width;
}
}
return OK;
}
@@ -6,11 +6,11 @@
#include "ngraph.h"
#include "ags.h"
int gr_fill_alpha_map(surface_t *dst, int dx, int dy, int dw, int dh, int lv) {
void gr_fill_alpha_map(surface_t *dst, int dx, int dy, int dw, int dh, int lv) {
uint8_t *a;
if (!gr_clip_xywh(dst, &dx, &dy, &dw, &dh)) {
return NG;
return;
}
a = GETOFFSET_ALPHA(dst, dx, dy);
@@ -19,6 +19,4 @@ int gr_fill_alpha_map(surface_t *dst, int dx, int dy, int dw, int dh, int lv) {
memset(a, lv, dw);
a += dst->width;
}
return OK;
}
+33
View File
@@ -0,0 +1,33 @@
#ifndef __NGRAPH_H__
#define __NGRAPH_H__
#include "portab.h"
#include "nact.h"
#include "ags.h"
#include "surface.h"
#include "graph.h"
#define sf0 nact->ags.dib
struct SDL_Surface;
// DLL 用 graphic 関連関数
/* in graph.c */
bool gr_clip(surface_t *ss, int *sx, int *sy, int *sw, int *sh, surface_t *ds, int *dx, int *dy);
bool gr_clip_xywh(surface_t *ss, int *sx, int *sy, int *sw, int *sh);
/* in graph_fillrect_amap.c */
void gr_fill_alpha_map(surface_t *dst, int dx, int dy, int dw, int dh, int lv);
/* in graph_copy_amap.c */
void gr_copy_alpha_map(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int sw, int sh);
// /* in graph_bright_dst_only.c */
#define gr_bright_dst_only(dst,dx,dy,w,h,lv) gr_copy_bright(dst,dx,dy,dst,dx,dy,w,h,lv)
// void gr_bright_dst_only(surface_t *dst, int dx, int dy, int w, int h, int lv);
/* defined in cg.c */
surface_t *sf_loadcg_no(int no);
#endif /* __GRAPH_H__ */
+80
View File
@@ -0,0 +1,80 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL.h>
#include "portab.h"
#include "surface.h"
#include "system.h"
static surface_t *create(int width, int height, bool has_pixel, bool has_alpha) {
surface_t *s = calloc(1, sizeof(surface_t));
s->width = width;
s->height = height;
if (has_pixel) {
s->sdl_surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_RGB888);
}
if (has_alpha) {
s->alpha = calloc(width * (height +1), sizeof(uint8_t));
}
return s;
}
// Create a surface with pixel and alpha data
surface_t *sf_create_surface(int width, int height) {
return create(width, height, true, true);
}
// Create a surface with alpha data only
surface_t *sf_create_alpha(int width, int height) {
return create(width, height, false, true);
}
// Create a surface with pixel data only
surface_t *sf_create_pixel(int width, int height) {
return create(width, height, true, false);
}
/**
* surfaceオブジェクトの開放
* @param s:
* @return:
*/
void sf_free(surface_t *s) {
if (s == NULL) return;
if (s->sdl_surface) SDL_FreeSurface(s->sdl_surface);
if (s->alpha) free(s->alpha);
free(s);
}
/**
* surface (dupulicate)
* @param in:
* @return : surface
*/
surface_t *sf_dup(surface_t *in) {
surface_t *sf;
int len;
if (in == NULL) return NULL;
sf = malloc(sizeof(surface_t));
memcpy(sf, in, sizeof(surface_t));
if (in->sdl_surface) {
sf->sdl_surface = SDL_ConvertSurface(in->sdl_surface, in->sdl_surface->format, 0);
}
if (in->alpha) {
len = sf->width * sf->height;
sf->alpha = malloc(sizeof(uint8_t) * (len + sf->width));
memcpy(sf->alpha, in->alpha, len);
}
return sf;
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef __SURFACE_H__
#define __SURFACE_H__
#include "portab.h"
#include "ags.h"
extern surface_t *sf_create_surface(int width, int height);
extern surface_t *sf_create_alpha(int width, int height);
extern surface_t *sf_create_pixel(int width, int height);
extern void sf_free(surface_t *s);
extern surface_t *sf_dup(surface_t *in);
#endif /* __SURFACE_H__ */
+4 -4
View File
@@ -42,7 +42,7 @@ static void RandMTInit() {
*/
int p1 = getCaliValue(); /* ITimer */
DEBUG_COMMAND("Math.RandMTInit %d:", p1);
TRACE("Math.RandMTInit %d:", p1);
}
static void RandMTGet() {
@@ -61,7 +61,7 @@ static void RandMTGet() {
*var = (int)(genrand() * num) + 1;
}
DEBUG_COMMAND("Math.RandMTGet %d,%p:", num, var);
TRACE("Math.RandMTGet %d,%p:", num, var);
}
static void RandMTMakeNumTable() {
@@ -74,7 +74,7 @@ static void RandMTMakeNumTable() {
numtblmax = p1;
DEBUG_COMMAND("Math.RandMTMakeNumTable %d:", p1);
TRACE("Math.RandMTMakeNumTable %d:", p1);
}
static void RandMTGetNumTable() {
@@ -87,7 +87,7 @@ static void RandMTGetNumTable() {
*var = (int)(genrand() * numtblmax) + 1;
DEBUG_COMMAND("Math.RandMTGetNumTable %d:", *var);
TRACE("Math.RandMTGetNumTable %d:", *var);
}
static const ModuleFunc functions[] = {
+9 -9
View File
@@ -13,7 +13,7 @@
#include "msgskip.h"
#include "utfsjis.h"
static boolean valid;
static bool valid;
static int action;
static void Init() {
@@ -26,7 +26,7 @@ static void Init() {
valid = true;
*p1 = 0;
DEBUG_COMMAND("MsgSkip.Init %p,%d,%d,%d:", p1, p2, p3, p4);
TRACE("MsgSkip.Init %p,%d,%d,%d:", p1, p2, p3, p4);
}
static void Start() {
@@ -39,7 +39,7 @@ static void Start() {
free(path);
free(fname_utf8);
DEBUG_COMMAND("MsgSkip.Start %p,%d:", p1, p2);
TRACE("MsgSkip.Start %p,%d:", p1, p2);
}
static void SetValid() {
@@ -48,7 +48,7 @@ static void SetValid() {
valid = p1;
msgskip_pause(!valid);
DEBUG_COMMAND("MsgSkip.SetValid %d:", p1);
TRACE("MsgSkip.SetValid %d:", p1);
}
static void GetValid() {
@@ -56,7 +56,7 @@ static void GetValid() {
*p1 = valid;
DEBUG_COMMAND("MsgSkip.GetValid %p:", p1);
TRACE("MsgSkip.GetValid %p:", p1);
}
static void SetAction() {
@@ -64,7 +64,7 @@ static void SetAction() {
action = p1;
DEBUG_COMMAND("MsgSkip.SetAcion %d:", p1);
TRACE("MsgSkip.SetAcion %d:", p1);
}
static void GetAction() {
@@ -72,19 +72,19 @@ static void GetAction() {
*p1 = action;
DEBUG_COMMAND("MsgSkip.GetAcion %p:", p1);
TRACE("MsgSkip.GetAcion %p:", p1);
}
static void PushStr() {
int p1 = getCaliValue();
DEBUG_COMMAND_YET("MsgSkip.PushStr %d:", p1);
TRACE_UNIMPLEMENTED("MsgSkip.PushStr %d:", p1);
}
static void PopStr() {
int p1 = getCaliValue();
DEBUG_COMMAND_YET("MsgSkip.PopStr %d:", p1);
TRACE_UNIMPLEMENTED("MsgSkip.PopStr %d:", p1);
}
static const ModuleFunc functions[] = {
+71 -71
View File
@@ -36,7 +36,7 @@ static void Init(void) { /* 0 */
*var = 1;
DEBUG_COMMAND_YET("NIGHTDLL.Init %p:", var);
TRACE_UNIMPLEMENTED("NIGHTDLL.Init %p:", var);
}
static void NIGHTDLL_reset(void) {
@@ -51,7 +51,7 @@ static void NIGHTDLL_reset(void) {
}
static void InitGame() { /* 1 */
ags_setAntialiasedStringMode(TRUE);
ags_setAntialiasedStringMode(true);
sys_setHankakuMode(2);
nact->msgout = ntmsg_add;
@@ -62,7 +62,7 @@ static void InitGame() { /* 1 */
ntmsg_init();
nt_sstr_init();
DEBUG_COMMAND_YET("NIGHTDLL.InitGame:");
TRACE_UNIMPLEMENTED("NIGHTDLL.InitGame:");
}
// メッセージの枠の表示
@@ -71,7 +71,7 @@ static void SetMsgFrame() { /* 2 */
ntmsg_set_frame(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetMsgFram %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetMsgFram %d:", p1);
}
// メッセージの表示位置の設定
@@ -80,21 +80,21 @@ static void SetMsgPlaceMethod(void) { /* 3 */
// 2=メッセージ枠+顔つき
ntmsg_set_place(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetMsgPlaceMethod %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetMsgPlaceMethod %d:", p1);
}
// 未実装?
static void SetMsgDrawEffect(void) { /* 4 */
int p1 = getCaliValue(); // 0, 1, 2, 3 (実際にはどれも機能しない?)
DEBUG_COMMAND_YET("NIGHTDLL.SetMsgDrawEffect %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetMsgDrawEffect %d:", p1);
}
// 未実装?
static void SetMsgClearEffect(void) { /* 5 */
int p1 = getCaliValue(); // 0, 1, 2, 4 (実際にはどれも機能しない?)
DEBUG_COMMAND_YET("NIGHTDLL.SetMsgClearEffect %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetMsgClearEffect %d:", p1);
}
// 壁紙CGの設定
@@ -103,7 +103,7 @@ static void SetWallPaper(void) { /* 6 */
nt_gr_set_wallpaper(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetWallPaper %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetWallPaper %d:", p1);
}
// 背景CGの設定
@@ -112,7 +112,7 @@ static void SetScenery(void) { /* 7 */
nt_gr_set_scenery(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetScenery %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetScenery %d:", p1);
}
// 顔CGの設定
@@ -121,7 +121,7 @@ static void SetFace(void) { /* 8 */
nt_gr_set_face(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetFace %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetFace %d:", p1);
}
// 立ち絵左の設定
@@ -130,7 +130,7 @@ static void SetSpriteL(void) { /* 9 */
nt_gr_set_spL(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetSpriteL %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetSpriteL %d:", p1);
}
// 立ち絵中央の設定
@@ -139,7 +139,7 @@ static void SetSpriteM(void) { /* 10 */
nt_gr_set_spM(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetSpriteM %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetSpriteM %d:", p1);
}
// 立ち絵右の設定
@@ -148,7 +148,7 @@ static void SetSpriteR(void) { /* 11 */
nt_gr_set_spR(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetSpriteR %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetSpriteR %d:", p1);
}
// 立ち絵左の設定(季節違い?)
@@ -157,7 +157,7 @@ static void SetSpriteSeasonL(void) { /* 12 */
nt_gr_set_spsL(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetSpriteSeasonL %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetSpriteSeasonL %d:", p1);
}
// 立ち絵中央の設定(季節違い?)
@@ -166,7 +166,7 @@ static void SetSpriteSeasonM(void) { /* 13 */
nt_gr_set_spM(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetSpriteSeasonM %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetSpriteSeasonM %d:", p1);
}
// 立ち絵右の設定(季節違い?)
@@ -175,14 +175,14 @@ static void SetSpriteSeasonR(void) { /* 14 */
nt_gr_set_spsR(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetSpriteSeasonR %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetSpriteSeasonR %d:", p1);
}
// 改行
static void StartNewLine(void) { /* 15 */
ntmsg_newline();
DEBUG_COMMAND_YET("NIGHTDLL.StartNewLine:");
TRACE_UNIMPLEMENTED("NIGHTDLL.StartNewLine:");
}
// メッセージフォントサイズの設定
@@ -191,7 +191,7 @@ static void SetFontSize(void) { /* 16 */
night.fontsize = p1;
DEBUG_COMMAND_YET("NIGHTDLL.SetFontSize %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetFontSize %d:", p1);
}
// フォントの種類の設定
@@ -200,7 +200,7 @@ static void SetFont(void) { /* 17 */
night.fonttype = p1;
DEBUG_COMMAND_YET("NIGHTDLL.SetFont %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetFont %d:", p1);
}
// 選択肢モード ON
@@ -209,7 +209,7 @@ static void SetSelMode(void) { /* 18 */
night.selmode = p1;
DEBUG_COMMAND_YET("NIGHTDLL.SetSelMode %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetSelMode %d:", p1);
}
// キー入力待ち後、改ページ
@@ -218,7 +218,7 @@ static void AnalyzeMessage(void) { /* 19 */
*var = ntmsg_ana();
DEBUG_COMMAND_YET("NIGHTDLL.AnalyzeMessage %p:", var);
TRACE_UNIMPLEMENTED("NIGHTDLL.AnalyzeMessage %p:", var);
}
// ~DRAWの効果時間
@@ -227,7 +227,7 @@ static void SetDrawTime(void) { /* 20 */
nt_gr_set_drawtime(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetDrawTime %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetDrawTime %d:", p1);
}
// 効果つき画面更新
@@ -236,7 +236,7 @@ static void Draw(void) { /* 21 */
nt_gr_draw(p1);
DEBUG_COMMAND_YET("NIGHTDLL.Draw %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.Draw %d:", p1);
}
// 音声データを再生
@@ -245,21 +245,21 @@ static void SetVoice(void) { /* 22 */
nt_voice_set(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SetVoice %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetVoice %d:", p1);
}
// 未使用
static void WaitKey(void) { /* 23 */
int p1 = getCaliValue(); //
DEBUG_COMMAND_YET("NIGHTDLL.WaitKey %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.WaitKey %d:", p1);
}
static void AddFeeling(void) { /* 24 */
int p1 = getCaliValue(); // person(1:新開,2:星川,3:百瀬,4:いずみ,5:鏡花,6:真言美,7:マコト
int p2 = getCaliValue(); // val
DEBUG_COMMAND_YET("NIGHTDLL.AddFeeling %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.AddFeeling %d:", p1);
}
@@ -267,7 +267,7 @@ static void SubFeeling(void) { /* 25 */
int p1 = getCaliValue(); // person
int p2 = getCaliValue(); // val
DEBUG_COMMAND_YET("NIGHTDLL.SubFeeling %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SubFeeling %d:", p1);
}
static void CallEvent(void) { /* 26 */
@@ -275,7 +275,7 @@ static void CallEvent(void) { /* 26 */
nt_sco_callevent(p1);
DEBUG_COMMAND_YET("NIGHTDLL.CallEvent %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.CallEvent %d:", p1);
}
static void ScreenCG(void) { /* 27 */
@@ -294,7 +294,7 @@ static void ScreenCG(void) { /* 27 */
nt_gr_screencg(no, x, y);
DEBUG_COMMAND_YET("NIGHTDLL.ScreenCG %d,%d,%d:", x, y, no);
TRACE_UNIMPLEMENTED("NIGHTDLL.ScreenCG %d,%d,%d:", x, y, no);
}
static void RunGameMain(void) { /* 28 */
@@ -310,7 +310,7 @@ static void RunGameMain(void) { /* 28 */
*p1 = nt_sco_main(p5);
DEBUG_COMMAND_YET("NIGHTDLL.RunGameMain %p,%d,%d,%d,%d:", p1, p2, p3, p4, p5);
TRACE_UNIMPLEMENTED("NIGHTDLL.RunGameMain %p,%d,%d,%d,%d:", p1, p2, p3, p4, p5);
}
static void CheckNewGame(void) { /* 29 */
@@ -318,21 +318,21 @@ static void CheckNewGame(void) { /* 29 */
*p1 = 0;
DEBUG_COMMAND_YET("NIGHTDLL.CheckNewGame %p:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.CheckNewGame %p:", p1);
}
static void SaveStartData(void) { /* 30 */
DEBUG_COMMAND_YET("NIGHTDLL.SaveStartData:");
TRACE_UNIMPLEMENTED("NIGHTDLL.SaveStartData:");
}
static void PrintExitSystem(void) { /* 31 */
DEBUG_COMMAND_YET("NIGHTDLL.PrintExitSystem:");
TRACE_UNIMPLEMENTED("NIGHTDLL.PrintExitSystem:");
}
static void SetCalendar(void) { /* 32 */
int p1 = getCaliValue(); // 0, 1, 2
DEBUG_COMMAND_YET("NIGHTDLL.SetCalendar %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetCalendar %d:", p1);
}
static void SetDate(void) { /* 33 */
@@ -344,7 +344,7 @@ static void SetDate(void) { /* 33 */
night.Day = p2;
night.DayOfWeek = p3;
DEBUG_COMMAND_YET("NIGHTDLL.SetDate %d,%d,%d:", p1, p2, p3);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetDate %d,%d,%d:", p1, p2, p3);
}
static void GetDate(void) { /* 34 */
@@ -356,11 +356,11 @@ static void GetDate(void) { /* 34 */
*p2 = night.Day;
*p3 = night.DayOfWeek;
DEBUG_COMMAND_YET("NIGHTDLL.GetDate %p,%p,%p:", p1, p2, p3);
TRACE_UNIMPLEMENTED("NIGHTDLL.GetDate %p,%p,%p:", p1, p2, p3);
}
static void SelectGameLevel(void) { /* 35 */
DEBUG_COMMAND_YET("NIGHTDLL.SelectGameLevel:");
TRACE_UNIMPLEMENTED("NIGHTDLL.SelectGameLevel:");
}
static void RunEventDungeon(void) { /* 36 */
@@ -369,13 +369,13 @@ static void RunEventDungeon(void) { /* 36 */
*p1 = 1;
DEBUG_COMMAND_YET("NIGHTDLL.RunEventDungeon %p,%d:", p1, p2);
TRACE_UNIMPLEMENTED("NIGHTDLL.RunEventDungeon %p,%d:", p1, p2);
}
static void RunEventBattle(void) { /* 37 */
int p1 = getCaliValue(); // 実際には機能しない?
DEBUG_COMMAND_YET("NIGHTDLL.RunEventBattle %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.RunEventBattle %d:", p1);
}
// CD再生開始
@@ -384,7 +384,7 @@ static void CDPlay(void) { /* 38 */
nt_cd_play(p1);
DEBUG_COMMAND_YET("NIGHTDLL.CDPlay %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.CDPlay %d:", p1);
}
// CD再生停止
@@ -393,16 +393,16 @@ static void CDStop(void) { /* 39 */
nt_cd_stop(p1);
DEBUG_COMMAND_YET("NIGHTDLL.CDStop %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.CDStop %d:", p1);
}
// CDのmute
static void CDMute(void) { /* 40 */
int p1 = getCaliValue(); // 0: mute off, 1: mute on
nt_cd_mute(p1 == 0 ? FALSE : TRUE);
nt_cd_mute(p1 != 0);
DEBUG_COMMAND_YET("NIGHTDLL.CDMute %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.CDMute %d:", p1);
}
// ch に効果音番号をセット
@@ -412,7 +412,7 @@ static void SoundEffectSetWave(void) { /* 41 */
nt_snd_setwave(p1, p2);
DEBUG_COMMAND_YET("NIGHTDLL.SoundEffectSetWave %d,%d:", p1, p2);
TRACE_UNIMPLEMENTED("NIGHTDLL.SoundEffectSetWave %d,%d:", p1, p2);
}
// ch にくり返し数をセット
@@ -422,7 +422,7 @@ static void SoundEffectSetLoop(void) { /* 42 */
nt_snd_setloop(p1, p2);
DEBUG_COMMAND_YET("NIGHTDLL.SoundEffectSetLoop %d,%d:", p1, p2);
TRACE_UNIMPLEMENTED("NIGHTDLL.SoundEffectSetLoop %d,%d:", p1, p2);
}
// ch に音量をセット
@@ -432,7 +432,7 @@ static void SoundEffectSetVolume(void) { /* 43 */
nt_snd_setvol(p1, p2);
DEBUG_COMMAND_YET("NIGHTDLL.SoundEffectSetVolue %d,%d:", p1, p2);
TRACE_UNIMPLEMENTED("NIGHTDLL.SoundEffectSetVolue %d,%d:", p1, p2);
}
// 効果音の再生を終るまで待つか待たないか?
@@ -440,9 +440,9 @@ static void SoundEffectSetSyncFlag(void) { /* 44 */
int p1 = getCaliValue(); // ch
int p2 = getCaliValue(); // 0: 終るまで待たない, 1: 待つ
nt_snd_waitend(p1, p2 == 0 ? FALSE : TRUE);
nt_snd_waitend(p1, p2 != 0);
DEBUG_COMMAND_YET("NIGHTDLL.SoundEffectSetSyncFlag %d,%d:", p1, p2);
TRACE_UNIMPLEMENTED("NIGHTDLL.SoundEffectSetSyncFlag %d,%d:", p1, p2);
}
// ch の効果音を再生
@@ -451,7 +451,7 @@ static void SoundEffectPlay(void) { /* 45 */
nt_snd_play(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SoundEffectPlay %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SoundEffectPlay %d:", p1);
}
// ch の効果音を停止
@@ -461,7 +461,7 @@ static void SoundEffectStop(void) { /* 46 */
nt_snd_stop(p1, p2);
DEBUG_COMMAND_YET("NIGHTDLL.SoundEffectStop %d,%d:", p1,p2);
TRACE_UNIMPLEMENTED("NIGHTDLL.SoundEffectStop %d,%d:", p1,p2);
}
// 全てのチャンネルの再生を停止
@@ -470,86 +470,86 @@ static void SoundEffectStopAll(void) { /* 47 */
nt_snd_stopall(p1);
DEBUG_COMMAND_YET("NIGHTDLL.SoundEffectStopAll %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SoundEffectStopAll %d:", p1);
}
static void RunSoundMode(void) { /* 48 */
DEBUG_COMMAND_YET("NIGHTDLL.RunSoundMode:");
TRACE_UNIMPLEMENTED("NIGHTDLL.RunSoundMode:");
}
static void RunMapEditor(void) { /* 49 */
int *p1 = getCaliVariable();
DEBUG_COMMAND_YET("NIGHTDLL.RunMapEditor %p:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.RunMapEditor %p:", p1);
}
static void VisualListClear(void) { /* 50 */
DEBUG_COMMAND_YET("NIGHTDLL.VisualListClear:");
TRACE_UNIMPLEMENTED("NIGHTDLL.VisualListClear:");
}
static void VisualListAdd(void) { /* 51 */
int p1 = getCaliValue();
DEBUG_COMMAND_YET("NIGHTDLL.VisualListAdd %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.VisualListAdd %d:", p1);
}
static void GetLocalCountCG(void) { /* 52 */
int *p1 = getCaliVariable();
int p2 = getCaliValue();
DEBUG_COMMAND_YET("NIGHTDLL.GetLocalCountCG %p,%d:", p1, p2);
TRACE_UNIMPLEMENTED("NIGHTDLL.GetLocalCountCG %p,%d:", p1, p2);
}
static void PlayMemory(void) { /* 53 */
int *p1 = getCaliVariable(); // 回想ページ
int *p2 = getCaliVariable(); // 回想RESULT
DEBUG_COMMAND_YET("NIGHTDLL.PlayMemory %p,%p:", p1, p2);
TRACE_UNIMPLEMENTED("NIGHTDLL.PlayMemory %p,%p:", p1, p2);
}
static void GetEventFlagTotal(void) { /* 54 */
int *p1 = getCaliVariable();
int p2 = getCaliValue();
DEBUG_COMMAND_YET("NIGHTDLL.GetEventFlagTotal %p,%d:", p1, p2);
TRACE_UNIMPLEMENTED("NIGHTDLL.GetEventFlagTotal %p,%d:", p1, p2);
}
static void SetPlayerName(void) { /* 55 */
int p1 = getCaliValue();
DEBUG_COMMAND_YET("NIGHTDLL.SetPlayerName %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetPlayerName %d:", p1);
}
static void GetPlayerName(void) { /* 56 */
int p1 = getCaliValue();
DEBUG_COMMAND_YET("NIGHTDLL.GetPlayerName %d:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.GetPlayerName %d:", p1);
}
static void SaveGame(void) { /* 57 */
int *p1 = getCaliVariable();
DEBUG_COMMAND_YET("NIGHTDLL.SaveGame %p:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.SaveGame %p:", p1);
}
static void LoadGame(void) { /* 58 */
int *p1 = getCaliVariable();
DEBUG_COMMAND_YET("NIGHTDLL.LoadGame %p:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.LoadGame %p:", p1);
}
static void ExistSaveData(void) { /* 59 */
int *p1 = getCaliVariable();
DEBUG_COMMAND_YET("NIGHTDLL.ExistSaveData %p:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.ExistSaveData %p:", p1);
}
static void ExistStartData(void) { /* 60 */
int *p1 = getCaliVariable();
DEBUG_COMMAND_YET("NIGHTDLL.ExistStartData %p:", p1);
TRACE_UNIMPLEMENTED("NIGHTDLL.ExistStartData %p:", p1);
}
static void SetAreaData(void) { /* 61 */
@@ -557,27 +557,27 @@ static void SetAreaData(void) { /* 61 */
int p2 = getCaliValue();
int p3 = getCaliValue();
DEBUG_COMMAND_YET("NIGHTDLL.SetAreaData %d,%d,%d:", p1, p2, p3);
TRACE_UNIMPLEMENTED("NIGHTDLL.SetAreaData %d,%d,%d:", p1, p2, p3);
}
static void RunBattleTest(void) { /* 62 */
DEBUG_COMMAND_YET("NIGHTDLL.RunBattleTest:");
TRACE_UNIMPLEMENTED("NIGHTDLL.RunBattleTest:");
}
static void RunTrainingTest(void) { /* 63 */
DEBUG_COMMAND_YET("NIGHTDLL.RunTrainingTest:");
TRACE_UNIMPLEMENTED("NIGHTDLL.RunTrainingTest:");
}
static void TestEventCall(void) { /* 64 */
DEBUG_COMMAND_YET("NIGHTDLL.TestEventCall:");
TRACE_UNIMPLEMENTED("NIGHTDLL.TestEventCall:");
}
static void Test(void) { /* 65 */
DEBUG_COMMAND_YET("NIGHTDLL.Test:");
TRACE_UNIMPLEMENTED("NIGHTDLL.Test:");
}
static void DebugScenario(void) { /* 66 */
DEBUG_COMMAND_YET("NIGHTDLL.DebugScenario:");
TRACE_UNIMPLEMENTED("NIGHTDLL.DebugScenario:");
}
static void GetDLLTime(void) { /* 67 */
@@ -589,7 +589,7 @@ static void GetDLLTime(void) { /* 67 */
int *p6 = getCaliVariable();
int *p7 = getCaliVariable();
DEBUG_COMMAND_YET("NIGHTDLL.GetDLLTime %p,%p,%p,%p,%p,%p,%p:", p1, p2, p3, p4, p5, p6, p7);
TRACE_UNIMPLEMENTED("NIGHTDLL.GetDLLTime %p,%p,%p,%p,%p,%p,%p:", p1, p2, p3, p4, p5, p6, p7);
}
static const ModuleFunc functions[] = {
+3 -5
View File
@@ -3,8 +3,6 @@
#include "config.h"
#include "portab.h"
#include "graphics.h"
#include "surface.h"
#include "ags.h"
#include "sprite.h"
@@ -43,9 +41,9 @@ struct _night {
// graph
// cginfo_t *cg[CGMAX];
MyRectangle updaterect;
SDL_Rect updaterect;
int fonttype;
FontType fonttype;
int fontsize;
sprite_t *sp[SPRITEMAX];
@@ -55,7 +53,7 @@ struct _night {
// msg
char msgbuf[MSGBUFMAX];
boolean zhiding;
bool zhiding;
struct {
void (* cbmove)(agsevent_t *);
void (* cbrelease)(agsevent_t *);
+12 -19
View File
@@ -1,11 +1,10 @@
#include <stdio.h>
#include <SDL.h>
#include "portab.h"
#include "system.h"
#include "cg.h"
#include "ags.h"
#include "surface.h"
#include "ngraph.h"
#include "night.h"
#include "sprite.h"
#include "nt_scenario.h"
@@ -54,8 +53,8 @@ void nt_gr_set_wallpaper(int no) {
sp = nt_sp_new(SPNO_WALL, no, 0, 0, SPRITE_WP);
nt_sp_add_updatelist(sp);
if (no == 0) {
sp->cursize.width = sf0->width;
sp->cursize.height = sf0->height;
sp->width = main_surface->w;
sp->height = main_surface->h;
sp->update = nt_sp_draw_wall;
}
@@ -178,28 +177,22 @@ void nt_gr_draw(int effectno) {
// 全消し
break;
case 1:
nt_sp_update_all(TRUE);
nt_sp_update_all(true);
break;
default:
if (night.waitskiplv > 1) {
nt_sp_update_all(TRUE);
nt_sp_update_all(true);
break;
}
//nt_sp_eupdate(effectno, effecttime, TRUE);
nt_sp_eupdate(effectno, 1000, TRUE);
//nt_sp_eupdate(effectno, effecttime, true);
nt_sp_eupdate(effectno, 1000, true);
}
}
void nt_gr_screencg(int no, int x, int y) {
surface_t *sf;
sf = sf_loadcg_no(no -1);
gre_BlendScreen(sf0, x, y, sf0, x, y, sf, 0, 0, sf->width, sf->height);
ags_updateArea(x, y, sf->width, sf->height);
sf_free(sf);
SDL_Surface *sf = cg_load_as_sdlsurface(no - 1);
SDL_SetSurfaceBlendMode(sf, SDL_BLENDMODE_ADD);
SDL_BlitSurface(sf, NULL, main_surface, &(SDL_Rect){x, y, sf->w, sf->h});
ags_updateArea(x, y, sf->w, sf->h);
SDL_FreeSurface(sf);
}
+78 -101
View File
@@ -3,15 +3,14 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "portab.h"
#include "system.h"
#include "sdl_core.h"
#include "utfsjis.h"
#include "ags.h"
#include "nact.h"
#include "input.h"
#include "ngraph.h"
#include "drawtext.h"
#include "night.h"
#include "nt_msg.h"
@@ -25,23 +24,29 @@ extern int ntsel_dosel(void);
#define SNAME_RYO "亮    "
#define SNAME_RYO_DEF "亮"
// 通常メッセージ表示位置と大きさ
#define MSGFRAME_0_X 6
#define MSGFRAME_0_Y 347
#define MSGFRAME_0_WIDTH 628
#define MSGFRAME_0_HEIGHT 125
// Normal message window
static const SDL_Rect msgframe_0 = {
.x = 6,
.y = 347,
.w = 628,
.h = 125
};
// 画面全体メッセージ表示位置と大きさ
#define MSGFRAME_1_X 0
#define MSGFRAME_1_Y 0
#define MSGFRAME_1_WIDTH 640
#define MSGFRAME_1_HEIGHT 480
// Full screen message window
static const SDL_Rect msgframe_1 = {
.x = 0,
.y = 0,
.w = 640,
.h = 480
};
// 通常メッセージ(顔つき)表示位置と大きさ
#define MSGFRAME_2_X (6+160)
#define MSGFRAME_2_Y 347
#define MSGFRAME_2_WIDTH (628-160)
#define MSGFRAME_2_HEIGHT 125
// Normal message (with face) window
static const SDL_Rect msgframe_2 = {
.x = 6 + 160,
.y = 347,
.w = 628 - 160,
.h = 125
};
// キー入力アニメーション位置
#define HAKANIM_LOC_X 620
@@ -69,7 +74,7 @@ void ntmsg_init() {
sprite_t *sp;
// メッセージスプライト
sp = night.sp[SPNO_MSGFRAME_FG] = nt_sp_msg_new(SPNO_MSGFRAME_FG, 0, 0, sf0->width, sf0->height);
sp = night.sp[SPNO_MSGFRAME_FG] = nt_sp_msg_new(SPNO_MSGFRAME_FG, 0, 0, main_surface->w, main_surface->h);
nt_sp_add_updatelist(sp);
// メッセージ背景用CG
@@ -78,7 +83,7 @@ void ntmsg_init() {
// 文字背景CG作成
nt_scg_create(CGNO_MSGFR_BG,
sf0->width, sf0->height,
main_surface->w, main_surface->h,
0, 0, 0, 255);
// night.cg[CGNO_MSGFR_BG]->refcnt++;
@@ -95,7 +100,7 @@ void ntmsg_init() {
sp->u.anime.interval = HAKANIM_INTERVAL;
nt_sp_add_updatelist(sp);
nt_sp_set_loc(sp, HAKANIM_LOC_X, HAKANIM_LOC_Y);
nt_sp_set_show(sp, FALSE);
nt_sp_set_show(sp, false);
sp->update = nt_sp_draw_scg;
@@ -121,45 +126,34 @@ void ntmsg_init() {
// type=1 枠あり
// type=2 中央
void ntmsg_set_frame(int type) {
surface_t *sf;
night.msgframe = type;
sf = night.sp[SPNO_MSGBG]->curcg->sf;
memset(sf->pixel, 0, sf->bytes_per_line * sf->height);
memset(sf->alpha, 0, sf->width * sf->height);
SDL_Surface *sf = night.sp[SPNO_MSGBG]->curcg->sf;
SDL_FillRect(sf, NULL, 0);
switch(type) {
case 0:
nt_sp_set_show(night.sp[SPNO_MSGBG], FALSE);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_BG], FALSE);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_FG], FALSE);
nt_sp_set_show(night.sp[SPNO_MSGBG], false);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_BG], false);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_FG], false);
break;
case 1:
nt_sp_set_show(night.sp[SPNO_MSGBG], TRUE);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_BG], TRUE);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_FG], TRUE);
nt_sp_set_show(night.sp[SPNO_MSGBG], true);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_BG], true);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_FG], true);
gr_fill(sf, MSGFRAME_0_X, MSGFRAME_0_Y,
MSGFRAME_0_WIDTH, MSGFRAME_0_HEIGHT,
16, 32, 64);
gr_fill_alpha_map(sf, MSGFRAME_0_X, MSGFRAME_0_Y,
MSGFRAME_0_WIDTH, MSGFRAME_0_HEIGHT, 192);
SDL_FillRect(sf, &msgframe_0, SDL_MapRGBA(sf->format, 16, 32, 64, 192));
ntmsg_clear(SPNO_MSGFRAME_FG);
nt_sp_update_all(TRUE);
nt_sp_update_all(true);
break;
case 2:
nt_sp_set_show(night.sp[SPNO_MSGBG], TRUE);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_BG], FALSE);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_FG], TRUE);
nt_sp_set_show(night.sp[SPNO_MSGBG], true);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_BG], false);
nt_sp_set_show(night.sp[SPNO_MSGFRAME_FG], true);
gr_fill(sf, MSGFRAME_1_X, MSGFRAME_1_Y,
MSGFRAME_1_WIDTH, MSGFRAME_1_HEIGHT,
32, 32, 32);
gr_fill_alpha_map(sf, MSGFRAME_1_X, MSGFRAME_1_Y,
MSGFRAME_1_WIDTH, MSGFRAME_1_HEIGHT, 128);
SDL_FillRect(sf, &msgframe_1, SDL_MapRGBA(sf->format, 32, 32, 32, 128));
ntmsg_clear(SPNO_MSGFRAME_FG);
nt_sp_update_all(TRUE);
nt_sp_update_all(true);
break;
}
@@ -221,8 +215,8 @@ int ntmsg_ana(void) {
static void ntmsg_out(int wNum, int wSize, int wColorR, int wColorG, int wColorB, int wFont, int wSpeed, int wLineSpace) {
char *msg;
sprite_t *sp;
boolean needupdate = FALSE;
MyRectangle uparea = {0,0,0,0};
bool needupdate = false;
SDL_Rect uparea = {0,0,0,0};
int savex;
if (night.msgbuf[0] == '\0') return;
@@ -241,7 +235,7 @@ static void ntmsg_out(int wNum, int wSize, int wColorR, int wColorG, int wColorB
char mbuf[20];
int cw, delta, wcnt;
wcnt = sdl_getTicks();
wcnt = sys_get_ticks();
mbuf[0] = '\0';
msg = get_char(msg, mbuf, sizeof(mbuf) -1);
@@ -260,7 +254,7 @@ static void ntmsg_out(int wNum, int wSize, int wColorR, int wColorG, int wColorB
mbuf,
wColorR, wColorG, wColorB);
needupdate = TRUE;
needupdate = true;
if (wSpeed > 0) {
nt_sp_updateme_part(sp,
@@ -269,10 +263,10 @@ static void ntmsg_out(int wNum, int wSize, int wColorR, int wColorG, int wColorB
cw,
wSize);
nt_sp_update_clipped();
needupdate = FALSE;
needupdate = false;
// keywait
delta = sdl_getTicks() - wcnt;
delta = sys_get_ticks() - wcnt;
if (delta < wSpeed) {
if (sys_keywait(wSpeed - delta, KEYWAIT_NONCANCELABLE)) {
@@ -289,8 +283,8 @@ static void ntmsg_out(int wNum, int wSize, int wColorR, int wColorG, int wColorB
// Waitなしの出力は最後にupdate
if (needupdate) {
uparea.w = sp->cursize.width;
uparea.h = min(sp->cursize.height, uparea.y - sp->u.msg.dspcur.y + wLineSpace + wLineSpace);
uparea.w = sp->width;
uparea.h = min(sp->height, uparea.y - sp->u.msg.dspcur.y + wLineSpace + wLineSpace);
nt_sp_updateme_part(sp, uparea.x, uparea.y, uparea.w, uparea.h);
}
@@ -316,14 +310,14 @@ static int ntmsg_keywait() {
night.waitkey = -1;
while (night.waitkey == -1 && !nact->is_quit) {
int st = sdl_getTicks();
int st = sys_get_ticks();
int interval = 25;
if (!night.zhiding) {
interval = night.sp[SPNO_MSG_KEYANIM]->u.anime.interval;
hakanim(i++);
}
sys_keywait(interval - (sdl_getTicks() - st), KEYWAIT_NONCANCELABLE);
sys_keywait(interval - (sys_get_ticks() - st), KEYWAIT_NONCANCELABLE);
}
night.waittype = KEYWAIT_NONE;
@@ -337,8 +331,8 @@ static void set_align(char *msg, sprite_t *sp, int wSize) {
switch(night.msgplace) {
case 0:
sp->u.msg.dspcur.x = MSGFRAME_0_X;
sp->u.msg.dspcur.y = MSGFRAME_0_Y + 8;
sp->u.msg.dspcur.x = msgframe_0.x;
sp->u.msg.dspcur.y = msgframe_0.y + 8;
break;
case 1:
@@ -360,12 +354,12 @@ static void set_align(char *msg, sprite_t *sp, int wSize) {
maxchar = max(maxchar, c);
line++;
sp->u.msg.dspcur.x = (sp->cursize.width - (maxchar * wSize/2)) /2;
sp->u.msg.dspcur.y = (sp->cursize.height - (line * (wSize+2))) /2;
sp->u.msg.dspcur.x = (sp->width - (maxchar * wSize/2)) /2;
sp->u.msg.dspcur.y = (sp->height - (line * (wSize+2))) /2;
break;
case 2:
sp->u.msg.dspcur.x = MSGFRAME_2_X;
sp->u.msg.dspcur.y = MSGFRAME_2_Y + 8;
sp->u.msg.dspcur.x = msgframe_2.x;
sp->u.msg.dspcur.y = msgframe_2.y + 8;
break;
}
@@ -424,7 +418,7 @@ static void setup_hakanim() {
// メッセージ表示時のキー入力を促すアニメーション
static void hakanim(int i) {
sprite_t *sp;
boolean show;
bool show;
sp = night.sp[SPNO_MSG_KEYANIM];
if (sp == NULL) return;
@@ -434,60 +428,43 @@ static void hakanim(int i) {
} else {
sp->curcg = sp->cg2;
}
sp->show = TRUE;
sp->show = true;
nt_sp_updateme(sp);
nt_sp_update_clipped();
sp->show = show;
}
int ntmsg_update(sprite_t *sp, MyRectangle *r) {
int sx, sy, w, h, dx, dy;
surface_t update;
// canvas が clean のときはなにもしない
// -> 説明スプライトのように、SetShowされたときに対応できないからだめ
//if (sact.msgbufempty) return OK;
update.width = r->w;
update.height = r->h;
dx = sp->cur.x - r->x;
dy = sp->cur.y - r->y;
w = sp->cursize.width;
h = sp->cursize.height;
sx = 0; sy = 0;
if (!gr_clip(sp->u.msg.canvas, &sx, &sy, &w, &h, &update, &dx, &dy)) {
return NG;
void ntmsg_update(sprite_t *sp, SDL_Rect *r) {
SDL_Rect sp_rect = {0, 0, sp->width, sp->height};
int sx = 0;
int sy = 0;
int dx = sp->cur.x;
int dy = sp->cur.y;
int w = sp->width;
int h = sp->height;
if (!ags_clipCopyRect(&sp_rect, r, &sx, &sy, &dx, &dy, &w, &h)) {
return;
}
dx += r->x;
dy += r->y;
gre_BlendUseAMap(sf0, dx, dy, sf0, dx, dy, sp->u.msg.canvas, sx, sy, w, h, sp->u.msg.canvas, sx, sy, sp->blendrate);
SDL_SetSurfaceBlendMode(sp->u.msg.canvas, SDL_BLENDMODE_BLEND);
SDL_SetSurfaceAlphaMod(sp->u.msg.canvas, sp->blendrate);
SDL_BlitSurface(sp->u.msg.canvas, &(SDL_Rect){sx, sy, w, h}, main_surface, &(SDL_Rect){dx, dy, w, h});
SACT_DEBUG("do update no=%d, sx=%d, sy=%d, w=%d, h=%d, dx=%d, dy=%d",
sp->no, sx, sy, w, h, dx, dy);
return OK;
}
static void ntmsg_clear(int wNum) {
sprite_t *sp = night.sp[wNum];
surface_t *sf;
sp->u.msg.dspcur.x = 0;
sp->u.msg.dspcur.y = 0;
night.msgbuf[0] = '\0';
// キャンバスのクリア
sf = sp->u.msg.canvas;
memset(sf->pixel, 0, sf->bytes_per_line * sf->height);
memset(sf->alpha, 0, sf->width * sf->height);
// Clear the canvas
SDL_FillRect(sp->u.msg.canvas, NULL, 0);
nt_sp_updateme(sp);
}
+7 -7
View File
@@ -1,12 +1,12 @@
#ifndef __NT_MSG_H__
#define __NT_MSG_H__
extern void ntmsg_init();
extern void ntmsg_set_frame(int type);
extern void ntmsg_set_place(int type);
extern void ntmsg_newline();
extern void ntmsg_add(const char *msg);
extern int ntmsg_ana(void);
extern int ntmsg_update(sprite_t *sp, MyRectangle *r);
void ntmsg_init();
void ntmsg_set_frame(int type);
void ntmsg_set_place(int type);
void ntmsg_newline();
void ntmsg_add(const char *msg);
int ntmsg_ana(void);
void ntmsg_update(sprite_t *sp, SDL_Rect *r);
#endif /* __NT_MSG_H__ */
+8 -9
View File
@@ -8,7 +8,7 @@
#include "portab.h"
#include "system.h"
#include "input.h"
#include "sdl_core.h"
#include "scheduler.h"
#include "xsystem35.h"
#include "nact.h"
#include "scenario.h"
@@ -52,7 +52,8 @@ static void ntmain(struct _scoadr inadr) {
struct _scoadr curadr;
while (!nact->is_quit) {
for (int cnt = 0; !nact->is_quit && !nact->wait_vsync && cnt < 10000; cnt++) {
while (!nact->is_quit && !is_yield_requested()) {
scheduler_on_command();
//SACT_DEBUG("%d:%x", sl_getPage(), sl_getIndex());
if (!nact->popupmenu_opened) {
exec_command();
@@ -71,9 +72,7 @@ static void ntmain(struct _scoadr inadr) {
nact->callback();
}
sys_getInputInfo();
sdl_wait_vsync();
nact->frame_count++;
nact->wait_vsync = FALSE;
scheduler_yield();
}
}
@@ -107,9 +106,9 @@ void nt_sco_callevent(int ev) {
}
boolean nt_sco_is_natsu() {
if (night.Month < 6 || night.Month > 9) return FALSE;
if (night.Month == 6 && night.Day < 11) return FALSE;
return TRUE;
bool nt_sco_is_natsu() {
if (night.Month < 6 || night.Month > 9) return false;
if (night.Month == 6 && night.Day < 11) return false;
return true;
}
+1 -1
View File
@@ -3,7 +3,7 @@
extern void nt_sco_init();
extern int nt_sco_main(int mode);
extern boolean nt_sco_is_natsu();
extern bool nt_sco_is_natsu();
extern void nt_sco_callevent(int ev);
#endif /* __NT_SCENARIO_H__ */
+8 -8
View File
@@ -10,7 +10,7 @@ struct _ntsnd {
int no;
int vol;
int loop;
boolean waitend;
bool waitend;
};
static struct _ntsnd ntsnd[10];
@@ -27,14 +27,14 @@ void nt_cd_play(int no) {
}
void nt_cd_stop(int msec) {
mus_mixer_fadeout_start(MIX_CD, msec, 0, TRUE);
mus_mixer_fadeout_start(MIX_CD, msec, 0, true);
}
void nt_cd_mute(boolean mute) {
void nt_cd_mute(bool mute) {
if (mute) {
mus_mixer_fadeout_start(MIX_CD, 0, 0, FALSE);
mus_mixer_fadeout_start(MIX_CD, 0, 0, false);
} else {
mus_mixer_fadeout_start(MIX_CD, 0, 100, FALSE);
mus_mixer_fadeout_start(MIX_CD, 0, 100, false);
}
}
@@ -56,7 +56,7 @@ void nt_snd_setvol(int ch, int vol) {
ntsnd[ch -1].vol = vol;
}
void nt_snd_waitend(int ch, boolean waitend) {
void nt_snd_waitend(int ch, bool waitend) {
if (ch < 1) return;
ntsnd[ch -1].waitend = waitend;
@@ -74,13 +74,13 @@ void nt_snd_play(int ch) {
void nt_snd_stop(int ch, int msec) {
if (ch < 1) return;
mus_wav_fadeout_start(ch, msec, 0, TRUE);
mus_wav_fadeout_start(ch, msec, 0, true);
}
void nt_snd_stopall(int msec) {
int i;
for (i = 1; i <= 10; i++) {
mus_wav_fadeout_start(i, msec, 0, TRUE);
mus_wav_fadeout_start(i, msec, 0, true);
}
}
+2 -2
View File
@@ -6,11 +6,11 @@
extern void nt_voice_set(int no);
extern void nt_cd_play(int no);
extern void nt_cd_stop(int msec);
extern void nt_cd_mute(boolean mute);
extern void nt_cd_mute(bool mute);
extern void nt_snd_setwave(int ch, int no);
extern void nt_snd_setloop(int ch, int num);
extern void nt_snd_setvol(int ch, int vol);
extern void nt_snd_waitend(int ch, boolean waitend);
extern void nt_snd_waitend(int ch, bool waitend);
extern void nt_snd_play(int ch);
extern void nt_snd_stop(int ch, int msec);
extern void nt_snd_stopall(int msec);
+21 -220
View File
@@ -26,29 +26,25 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL.h>
#include "portab.h"
#include "nact.h"
#include "system.h"
#include "ags.h"
#include "surface.h"
#include "ngraph.h"
#include "cg.h"
#include "sactcg.h"
#define CGMAX 65536
static cginfo_t *cgs[CGMAX];
#include "sactcg_stretch.c"
#include "sactcg_blend.c"
#define spcg_assert_no(no) \
#define SPCG_ASSERT_NO(no) \
if ((no) > (CGMAX -1)) { \
WARNING("no is too large (should be %d < %d)", (no), CGMAX); \
return NG; \
return; \
} \
static cginfo_t *nt_scg_new(enum cgtype type, int no, surface_t *sf) {
static cginfo_t *nt_scg_new(enum cgtype type, int no, SDL_Surface *sf) {
cginfo_t *info = calloc(1, sizeof(cginfo_t));
info->type = type;
info->no = no;
@@ -78,7 +74,7 @@ static cginfo_t *nt_scg_get(int no) {
if (cgs[no] != NULL)
return cgs[no];
surface_t *sf = sf_loadcg_no(no - 1);
SDL_Surface *sf = cg_load_as_sdlsurface(no - 1);
if (!sf) {
WARNING("load fail (%d)", no -1);
return NULL;
@@ -98,248 +94,53 @@ void nt_scg_deref(cginfo_t *cg) {
return;
if (cg->sf)
sf_free(cg->sf);
SDL_FreeSurface(cg->sf);
free(cg);
}
// 指定の大きさ、色の矩形の CG を作成
int nt_scg_create(int wNumCG, int wWidth, int wHeight, int wR, int wG, int wB, int wBlendRate) {
spcg_assert_no(wNumCG);
void nt_scg_create(int wNumCG, int wWidth, int wHeight, int wR, int wG, int wB, int wBlendRate) {
SPCG_ASSERT_NO(wNumCG);
surface_t *sf = sf_create_surface(wWidth, wHeight, sf0->depth);
gr_fill(sf, 0, 0, wWidth, wHeight, wR, wG, wB);
gr_fill_alpha_map(sf, 0, 0, wWidth, wHeight, wBlendRate);
SDL_Surface *sf = SDL_CreateRGBSurfaceWithFormat(0, wWidth, wHeight, 32, SDL_PIXELFORMAT_ARGB8888);
SDL_FillRect(sf, NULL, SDL_MapRGBA(sf->format, wR, wG, wB, wBlendRate));
nt_scg_new(CG_SET, wNumCG, sf);
return OK;
}
// 指定のCGを反転させたCGを作成
int nt_scg_create_reverse(int wNumCG, int wNumSrcCG, int wReverseX, int wReverseY) {
spcg_assert_no(wNumCG);
spcg_assert_no(wNumSrcCG);
cginfo_t *src = nt_scg_get(wNumSrcCG);
if (!src)
return NG;
surface_t *sf = stretch(src->sf, src->sf->width, src->sf->height, (wReverseX << 1) | wReverseY);
nt_scg_new(CG_REVERSE, wNumCG, sf);
return OK;
}
// 指定のCGを拡大/縮小したCGを作成
int nt_scg_create_stretch(int wNumCG, int wWidth, int wHeight, int wNumSrcCG) {
spcg_assert_no(wNumCG);
spcg_assert_no(wNumSrcCG);
cginfo_t *src = nt_scg_get(wNumSrcCG);
if (!src)
return NG;
surface_t *sf = stretch(src->sf, wWidth, wHeight, 0);
nt_scg_new(CG_STRETCH, wNumCG, sf);
return OK;
}
// ベースCGの上にブレンドCGを重ねた CG を作成
int nt_scg_create_blend(int wNumDstCG, int wNumBaseCG, int wX, int wY, int wNumBlendCG, int wAlphaMapMode) {
spcg_assert_no(wNumDstCG);
spcg_assert_no(wNumBaseCG);
spcg_assert_no(wNumBlendCG);
cginfo_t *basecg = nt_scg_get(wNumBaseCG);
cginfo_t *blendcg = nt_scg_get(wNumBlendCG);
if (!basecg || !blendcg) return NG;
surface_t *sf = blend(basecg->sf, wX, wY, blendcg->sf, wAlphaMapMode);
nt_scg_new(CG_SET, wNumDstCG, sf);
return OK;
}
// 指定の文字列のCGを作成
int nt_scg_create_text(int wNumCG, int wSize, int wR, int wG, int wB, char *cText) {
spcg_assert_no(wNumCG);
// 勝手に出ていいのかな?
if (strlen(cText) == 0) return OK;
ags_setFont(FONT_GOTHIC, wSize);
agsurface_t *glyph = ags_drawStringToSurface(cText);
surface_t *sf = sf_create_surface(glyph->width, wSize, nact->ags.dib->depth);
gr_fill(sf, 0, 0, glyph->width, wSize, wR, wG, wB);
gr_draw_amap(sf, 0, 0, glyph->pixel, glyph->width, wSize, glyph->bytes_per_line);
nt_scg_new(CG_SET, wNumCG, sf);
return OK;
}
// 数字文字列のCGを作成
int nt_scg_create_textnum(int wNumCG, int wSize, int wR, int wG, int wB, int wFigs, int wZeroPadding, int wValue) {
spcg_assert_no(wNumCG);
char s[256], ss[256];
if (wZeroPadding) {
char *sss = "%%0%dd";
sprintf(ss, sss, wFigs);
} else {
char *sss = "%%%dd";
sprintf(ss, sss, wFigs);
}
sprintf(s, ss, wValue);
ags_setFont(FONT_GOTHIC, wSize);
agsurface_t *glyph = ags_drawStringToSurface(s);
surface_t *sf = sf_create_surface(glyph->width, wSize, nact->ags.dib->depth);
gr_fill(sf, 0, 0, glyph->width, wSize, wR, wG, wB);
gr_draw_amap(sf, 0, 0, glyph->pixel, glyph->width, wSize, glyph->bytes_per_line);
nt_scg_new(CG_SET, wNumCG, sf);
return OK;
}
// CGを複製
int nt_scg_copy(int wNumDstCG, int wNumSrcCG) {
spcg_assert_no(wNumDstCG);
spcg_assert_no(wNumSrcCG);
cginfo_t *src = nt_scg_get(wNumSrcCG);
if (!src)
return NG;
nt_scg_new(CG_SET, wNumDstCG, sf_dup(src->sf));
return OK;
}
// CGの一部を切りぬいたCGを作成
int nt_scg_cut(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight) {
spcg_assert_no(wNumDstCG);
spcg_assert_no(wNumSrcCG);
void nt_scg_cut(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight) {
SPCG_ASSERT_NO(wNumDstCG);
SPCG_ASSERT_NO(wNumSrcCG);
cginfo_t *src = nt_scg_get(wNumSrcCG);
if (!src)
return NG;
return;
surface_t *sf = src->sf->alpha
? sf_create_surface(wWidth, wHeight, src->sf->depth)
: sf_create_pixel(wWidth, wHeight, src->sf->depth);
if (src->sf->pixel)
gr_copy(sf, 0, 0, src->sf, wX, wY, wWidth, wHeight);
if (src->sf->alpha)
gr_copy_alpha_map(sf, 0, 0, src->sf, wX, wY, wWidth, wHeight);
SDL_Surface *sf = SDL_CreateRGBSurfaceWithFormat(0, wWidth, wHeight, src->sf->format->BitsPerPixel, src->sf->format->format);
SDL_BlitSurface(src->sf, &(SDL_Rect){wX, wY, wWidth, wHeight}, sf, NULL);
nt_scg_new(CG_SET, wNumDstCG, sf);
return OK;
}
// 元のCGの一部を切りぬいたCGを作成
int nt_scg_partcopy(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight) {
spcg_assert_no(wNumDstCG);
spcg_assert_no(wNumSrcCG);
cginfo_t *src = nt_scg_get(wNumSrcCG);
if (!src)
return NG;
surface_t *sf;
if (src->sf->alpha) {
sf = sf_create_surface(src->sf->width, src->sf->height, src->sf->depth);
gr_fill_alpha_map(sf, 0, 0, src->sf->width, src->sf->height, 255);
} else {
sf = sf_create_pixel(src->sf->width, src->sf->height, src->sf->depth);
}
if (src->sf->pixel)
gr_copy(sf, wX, wY, src->sf, wX, wY, wWidth, wHeight);
if (src->sf->alpha)
gr_copy_alpha_map(sf, wX, wY, src->sf, wX, wY, wWidth, wHeight);
nt_scg_new(CG_SET, wNumDstCG, sf);
return OK;
}
// 全てのCGの開放
int nt_scg_freeall() {
void nt_scg_freeall(void) {
int i;
for (i = 1; i < CGMAX; i++) {
nt_scg_free(i);
}
return OK;
}
/**
* CG
* (0)
*/
int nt_scg_free(int no) {
spcg_assert_no(no);
void nt_scg_free(int no) {
SPCG_ASSERT_NO(no);
cginfo_t *cg = cgs[no];
if (!cg) return NG;
if (!cg) return;
nt_scg_deref(cg);
cgs[no] = NULL;
return OK;
}
// CGの種類を取得
int nt_scg_querytype(int wNumCG, int *ret) {
if (wNumCG >= (CGMAX -1)) goto errexit;
if (cgs[wNumCG] == NULL) goto errexit;
*ret = cgs[wNumCG]->type;
return OK;
errexit:
*ret = CG_NOTUSED;
return NG;
}
// CGの大きさを取得
int nt_scg_querysize(int wNumCG, int *w, int *h) {
if (wNumCG >= (CGMAX -1)) goto errexit;
if (cgs[wNumCG] == NULL) goto errexit;
if (cgs[wNumCG]->sf == NULL) goto errexit;
*w = cgs[wNumCG]->sf->width;
*h = cgs[wNumCG]->sf->height;
return OK;
errexit:
*w = *h = 0;
return NG;
}
// CGのBPPを取得
int nt_scg_querybpp(int wNumCG, int *ret) {
if (wNumCG >= (CGMAX -1)) goto errexit;
if (cgs[wNumCG] == NULL) goto errexit;
if (cgs[wNumCG]->sf == NULL) goto errexit;
*ret = cgs[wNumCG]->sf->depth;
return OK;
errexit:
*ret = 0;
return NG;
}
// CGの alphamap が存在するかを取得
int nt_scg_existalphamap(int wNumCG, int *ret) {
if (wNumCG >= (CGMAX -1)) goto errexit;
if (cgs[wNumCG] == NULL) goto errexit;
if (cgs[wNumCG]->sf == NULL) goto errexit;
*ret = cgs[wNumCG]->sf->alpha ? 1 : 0;
errexit:
*ret = 0;
return NG;
}
+6 -18
View File
@@ -27,23 +27,11 @@
#include "portab.h"
#include "night.h"
extern cginfo_t *nt_scg_addref(int no);
extern void nt_scg_deref(cginfo_t *cg);
extern int nt_scg_create(int wNumCG, int wWidth, int wHeight, int wR, int wG, int wB, int wBlendRate);
extern int nt_scg_create_reverse(int NumCG, int wNumSrcCG, int wReverseX, int wReverseY);
extern int nt_scg_create_stretch(int wNumCG, int wWidth, int wHeight, int wNumSrcCG);
extern int nt_scg_create_blend(int wNumDstCG, int wNumBaseCG, int wX, int wY, int wNumBlendCG, int wAlphaMapMode);
extern int nt_scg_create_text(int wNumCG, int wSize, int wR, int wG, int wB, char *cText);
extern int nt_scg_create_textnum(int wNumCG, int wSize, int wR, int wG, int wB, int wFigs, int wZeroPadding, int wValue);
extern int nt_scg_copy(int wNumDstCG, int wNumSrcCG);
extern int nt_scg_cut(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight);
extern int nt_scg_partcopy(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight);
extern int nt_scg_freeall();
extern int nt_scg_free(int cg);
extern int nt_scg_querytype(int wNumCG, int *ret);
extern int nt_scg_querysize(int wNumCG, int *w, int *h);
extern int nt_scg_querybpp(int wNumCG, int *ret);
extern int nt_scg_existalphamap(int wNumCG, int *ret);
extern int nt_scg_linkcgfree(int no);
cginfo_t *nt_scg_addref(int no);
void nt_scg_deref(cginfo_t *cg);
void nt_scg_create(int wNumCG, int wWidth, int wHeight, int wR, int wG, int wB, int wBlendRate);
void nt_scg_cut(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight);
void nt_scg_freeall(void);
void nt_scg_free(int cg);
#endif
-31
View File
@@ -1,31 +0,0 @@
//
static surface_t *blend(surface_t *base, int x, int y, surface_t *blend, int mode) {
surface_t *dst = sf_create_surface(base->width, base->height, base->depth);
gr_copy(dst, 0, 0, base, 0, 0, base->width, base->height);
if (base->alpha) {
// ベースに alpha map がある場合はそれをコピー
gr_copy_alpha_map(dst, 0, 0, base, 0, 0, base->width, base->height);
} else {
// 無い場合は全て 255 の map を作成
gr_fill_alpha_map(dst, 0, 0, base->width, base->height, 255);
}
if (blend->alpha) {
// 重ね合わせ先の alpha map があるときはそれを使う
gre_BlendUseAMap(dst, x, y, base, x, y, blend, 0, 0, blend->width, blend->height, blend, 0, 0, 255);
} else {
// 無いときは dst の alpha map を使う
gre_BlendUseAMap(dst, x, y, base, x, y, blend, 0, 0, blend->width, blend->height, dst, x, y, 255);
}
// alpha 作成モードが dst + blend の時は飽和加算
if (mode == 1) {
gr_saturadd_alpha_map(dst, x, y, blend, 0, 0, blend->width, blend->height);
}
return dst;
}
-114
View File
@@ -1,114 +0,0 @@
// 拡大縮小
static surface_t *stretch(surface_t *src, int dw, int dh, int mirror) {
surface_t *dst = calloc(1, sizeof(surface_t));
float a1, a2, xd, yd;
int sw, sh;
int *row, *col;
int x, y;
uint8_t *sdata, *ddata;
dst->width = dw;
dst->height = dh;
dst->depth = src->depth;
dst->bytes_per_line = dw * src->bytes_per_pixel;
dst->bytes_per_pixel = src->bytes_per_pixel;
if (src->pixel) {
dst->pixel = malloc(dh * dst->bytes_per_line);
}
if (src->alpha) {
dst->alpha = malloc(dw * dh);
}
sdata = GETOFFSET_PIXEL(src, 0, 0);
ddata = GETOFFSET_PIXEL(dst, 0, 0);
sw = src->width;
sh = src->height;
a1 = (float)sw / (float)dw;
a2 = (float)sh / (float)dh;
row = malloc(sizeof(int) * dw);
// 1おおきくして初期化しないと col[dw-1]とcol[dw]が同じになる
// 可能性がある。
col = calloc(dh +1, sizeof(int));
if (mirror & 1) {
/* 上下反転 added by tajiri@wizard */
for (yd = sh - a2, y = 0; y < dh; y++) {
col[y] = yd; yd -= a2;
}
} else {
for (yd = 0.0, y = 0; y < dh; y++) {
col[y] = yd; yd += a2;
}
}
if (mirror & 2) {
/* 左右反転 added by tajiri@wizard */
for (xd = sw - a1, x = 0; x < dw; x++) {
row[x] = xd; xd -= a1;
}
} else {
for (xd = 0.0, x = 0; x < dw; x++) {
row[x] = xd; xd += a1;
}
}
#define SCALEDCOPYAREA(type) { \
int x, y; \
type *sl, *dl; \
uint8_t *_sl, *_dl; \
for (y = 0; y < dh; y++) { \
sl = (type *)(sdata + *(y + col) * src->bytes_per_line);\
dl = (type *)(ddata + y * dst->bytes_per_line);\
for (x = 0; x < dw; x++) { \
*(dl + x) = *(sl + *(row + x)); \
} \
_dl = (uint8_t *)dl; \
while(*(col + y) == *(col + y + 1)) { \
_sl = _dl; \
_dl += dst->bytes_per_line; \
memcpy(_dl, _sl, dw * sizeof(type)); \
y++; \
} \
}}
switch(dst->depth) {
case 8:
SCALEDCOPYAREA(uint8_t); break;
case 16:
SCALEDCOPYAREA(uint16_t); break;
case 24:
case 32:
SCALEDCOPYAREA(uint32_t); break;
default:
break;
}
if (src->alpha) {
int x, y;
uint8_t *sl, *dl;
uint8_t *_sl, *_dl;
sdata = GETOFFSET_ALPHA(src, 0, 0);
ddata = GETOFFSET_ALPHA(dst, 0, 0);
for (y = 0; y < dh; y++) {
sl = (uint8_t *)(sdata + *(y + col) * src->width);
dl = (uint8_t *)(ddata + y * dst->width);
for (x = 0; x < dw; x++) {
*(dl + x) = *(sl + *(row + x));
}
_dl = (uint8_t *)dl;
while(*(col + y) == *(col + y + 1)) {
_sl = _dl;
_dl += dst->width;
memcpy(_dl, _sl, dw);
y++;
}
}
}
free(row);
free(col);
return dst;
}
+5 -56
View File
@@ -51,14 +51,13 @@ static char *replacedst;
/**
*
*/
int nt_sstr_init() {
void nt_sstr_init(void) {
stack = malloc(sizeof(char *) * DEFSTACKSIZE);
idx = 0;
idxmax = DEFSTACKSIZE;
return OK;
}
int nt_sstr_reset(void) {
void nt_sstr_reset(void) {
for (int i = 0; i < idx; i++)
free(stack[i]);
idx = 0;
@@ -73,35 +72,6 @@ int nt_sstr_reset(void) {
}
slist_free(strreplace);
strreplace = NULL;
return OK;
}
/**
*
* @param strno:
*/
int nt_sstr_push(char *str) {
if (idx >= idxmax) {
stack = realloc(stack, sizeof(char *) * idx*2);
idxmax = idx*2;
}
stack[idx++] = strdup(str);
return OK;
}
/**
*
* @param strno:
*/
int nt_sstr_pop(char *str, int maxlen) {
if (idx == 0) return NG;
strncpy(str, stack[--idx], maxlen);
free(stack[idx]);
return OK;
}
/**
@@ -109,36 +79,15 @@ int nt_sstr_pop(char *str, int maxlen) {
* @param sstrno:
* @param dstrno:
*/
int nt_sstr_regist_replace(char *sstr, char *dstr) {
void nt_sstr_regist_replace(char *sstr, char *dstr) {
strexchange_t *ex;
if (sstr == dstr) return NG;
if (sstr == dstr) return;
ex = malloc(sizeof(strexchange_t));
ex->src = sstr;
ex->dst = dstr;
strreplace = slist_append(strreplace, ex);
return OK;
}
/**
* ->
*/
int nt_sstr_num2str(int strno, int fig, int nzeropad, int num) {
char s[256], ss[256];
if (nzeropad) {
char *sss = "%%0%dd";
sprintf(ss, sss, fig);
} else {
char *sss = "%%%dd";
sprintf(ss, sss, fig);
}
sprintf(s, ss, num);
svar_set(strno, s);
return OK;
}
// 文字列の置き換え処理
@@ -151,7 +100,7 @@ static void replacestr_cb(void* data, void* userdata) {
start = replacesrc;
out = replacedst;
while (TRUE) {
while (true) {
next = strstr(start, ex->src);
if (next == NULL) break;
strncat(out, start, (size_t)(next - start));
+4 -7
View File
@@ -24,13 +24,10 @@
#ifndef __SACTSTRING_H__
#define __SACTSTRING_H__
extern int nt_sstr_init();
extern int nt_sstr_reset(void);
extern int nt_sstr_push(char *str);
extern int nt_sstr_pop(char *str, int maxlen);
extern int nt_sstr_regist_replace(char *sstr, char *dstr);
extern int nt_sstr_num2str(int strno, int fig, int nzeropad, int num);
extern char *nt_sstr_replacestr(char *msg);
void nt_sstr_init(void);
void nt_sstr_reset(void);
void nt_sstr_regist_replace(char *sstr, char *dstr);
char *nt_sstr_replacestr(char *msg);
#endif /* __SACTSTRING_H__ */
+17 -18
View File
@@ -1,12 +1,11 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include "portab.h"
#include "sprite.h"
#include "sactcg.h"
#include "surface.h"
#include "ngraph.h"
#include "nt_msg.h"
sprite_t *nt_sp_new(int no, int cg1, int cg2, int cg3, int type) {
@@ -22,18 +21,18 @@ sprite_t *nt_sp_new(int no, int cg1, int cg2, int cg3, int type) {
sp->cg3 = cg3 ? nt_scg_addref(cg3) : NULL;
sp->curcg = sp->cg1;
sp->show = TRUE;
sp->show = true;
sp->blendrate = 255;
sp->loc.x = 0;
sp->loc.y = 0;
sp->cur = sp->loc;
if (sp->curcg == NULL) {
sp->cursize.width = 0;
sp->cursize.height = 0;
sp->width = 0;
sp->height = 0;
} else {
sp->cursize.width = sp->curcg->sf->width;
sp->cursize.height = sp->curcg->sf->height;
sp->width = sp->curcg->sf->w;
sp->height = sp->curcg->sf->h;
}
sp->update = DEFAULT_UPDATE;
@@ -54,16 +53,16 @@ sprite_t *nt_sp_msg_new(int no, int x, int y, int width, int height) {
sp->no = no;
sp->type = SPRITE_MSG;
sp->show = TRUE;
sp->show = true;
sp->blendrate = 255;
sp->loc.x = x;
sp->loc.y = y;
sp->cur = sp->loc;
sp->cursize.width = width;
sp->cursize.height = height;
sp->width = width;
sp->height = height;
sp->u.msg.dspcur.x = 0;
sp->u.msg.dspcur.y = 0;
sp->u.msg.canvas = sf_create_surface(width, height, sf0->depth);
sp->u.msg.canvas = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_ARGB8888);
sp->update = ntmsg_update;
return sp;
@@ -77,14 +76,14 @@ void nt_sp_free(sprite_t *sp) {
if (sp->cg3) nt_scg_deref(sp->cg3);
if (sp->type == SPRITE_MSG) {
sf_free(sp->u.msg.canvas);
SDL_FreeSurface(sp->u.msg.canvas);
}
free(sp);
}
void nt_sp_set_show(sprite_t *sp, boolean show) {
boolean oldshow;
void nt_sp_set_show(sprite_t *sp, bool show) {
bool oldshow;
if (sp == NULL) return;
@@ -108,11 +107,11 @@ void nt_sp_set_cg(sprite_t *sp, int no) {
cg = no ? nt_scg_addref(no) : NULL;
if (cg == NULL) {
sp->cursize.width = 0;
sp->cursize.height = 0;
sp->width = 0;
sp->height = 0;
} else {
sp->cursize.width = cg->sf->width;
sp->cursize.height = cg->sf->height;
sp->width = cg->sf->w;
sp->height = cg->sf->h;
}
sp->curcg = cg;
+27 -29
View File
@@ -3,8 +3,7 @@
#define __SPRITE_H__
#include "portab.h"
#include "surface.h"
#include "graphics.h"
#include <SDL_rect.h>
#define DEFAULT_UPDATE nt_sp_draw
@@ -54,7 +53,7 @@ enum cgtype {
struct _cginfo {
enum cgtype type; // CGの種類, 0: 未使用, 1:リンクされている, ...
int no; // CGの番号
surface_t *sf; // CG本体
struct SDL_Surface *sf;
int refcnt; // 参照カウンタ。0になったら開放してもよい。
};
typedef struct _cginfo cginfo_t;
@@ -73,20 +72,21 @@ struct _sprite {
int no;
MyDimension cursize;
int width;
int height;
cginfo_t *curcg;
cginfo_t *cg1, *cg2, *cg3;
boolean show;
bool show;
int blendrate;
MyPoint loc;
SDL_Point loc;
MyPoint cur;
SDL_Point cur;
int (* update)(struct _sprite *sp, MyRectangle *updatearea);
void (* update)(struct _sprite *sp, SDL_Rect *updatearea);
union {
struct {
@@ -97,8 +97,8 @@ struct _sprite {
} anime;
struct {
surface_t *canvas;
MyPoint dspcur;
struct SDL_Surface *canvas;
SDL_Point dspcur;
} msg;
} u;
};
@@ -107,31 +107,29 @@ typedef struct _sprite sprite_t;
/* in nt_sprite.c */
extern sprite_t *nt_sp_new(int no, int cg1, int cg2, int cg3, int type);
extern sprite_t *nt_sp_msg_new(int no, int x, int y, int width, int height);
extern void nt_sp_free(sprite_t *sp);
extern void nt_sp_set_show(sprite_t *sp, boolean show);
// extern void nt_sp_set_cg(sprite_t *sp, int no);
extern void nt_sp_set_loc(sprite_t *sp, int x, int y);
sprite_t *nt_sp_new(int no, int cg1, int cg2, int cg3, int type);
sprite_t *nt_sp_msg_new(int no, int x, int y, int width, int height);
void nt_sp_free(sprite_t *sp);
void nt_sp_set_show(sprite_t *sp, bool show);
// void nt_sp_set_cg(sprite_t *sp, int no);
void nt_sp_set_loc(sprite_t *sp, int x, int y);
/* in nt_sprite_update.c */
extern int nt_sp_update_clipped();
extern int nt_sp_update_all(boolean syncscreen);
extern int nt_sp_updateme(sprite_t *sp);
extern int nt_sp_updateme_part(sprite_t *sp, int x, int y, int w, int h);
extern void nt_sp_add_updatelist(sprite_t *sp);
extern void nt_sp_remove_updatelist(sprite_t *sp);
extern int nt_sp_draw_wall(sprite_t *sp, MyRectangle *r);
extern void nt_sp_clear_updatelist(void);
void nt_sp_update_clipped();
void nt_sp_update_all(bool syncscreen);
void nt_sp_updateme(sprite_t *sp);
void nt_sp_updateme_part(sprite_t *sp, int x, int y, int w, int h);
void nt_sp_add_updatelist(sprite_t *sp);
void nt_sp_remove_updatelist(sprite_t *sp);
void nt_sp_draw_wall(sprite_t *sp, SDL_Rect *r);
void nt_sp_clear_updatelist(void);
/* in nt_sprite_draw.c */
extern int nt_sp_draw(sprite_t *sp, MyRectangle *r);
extern int nt_sp_draw2(sprite_t *sp, cginfo_t *cg, MyRectangle *r);
extern void nt_sp_draw_dmap(void* data, void* userdata);
extern int nt_sp_draw_scg(sprite_t *sp, MyRectangle *r);
void nt_sp_draw(sprite_t *sp, SDL_Rect *r);
void nt_sp_draw_scg(sprite_t *sp, SDL_Rect *r);
/* in nt_sprite_eupdate.c */
extern int nt_sp_eupdate(int type, int time, int cancel);
void nt_sp_eupdate(int type, int time, int cancel);
#endif /* __SPRITE_H__ */
+37 -85
View File
@@ -24,13 +24,11 @@
#include "config.h"
#include <stdio.h>
#include <SDL.h>
#include "portab.h"
#include "system.h"
#include "ags.h"
#include "graphics.h"
#include "surface.h"
#include "ngraph.h"
#include "sprite.h"
/*
@@ -38,106 +36,60 @@
@param sp:
@param r :
*/
int nt_sp_draw(sprite_t *sp, MyRectangle *r) {
if (sp == NULL) return NG;
return nt_sp_draw2(sp, sp->curcg, r);
}
/*
spriteの指定のCGを surface0
(?)
@param sp:
@param cg: CG
@param r :
*/
int nt_sp_draw2(sprite_t *sp, cginfo_t *cg, MyRectangle *r) {
surface_t update;
int sx, sy, w, h, dx, dy;
if (cg == NULL) return NG;
if (cg->sf == NULL) return NG;
void nt_sp_draw(sprite_t *sp, SDL_Rect *r) {
if (sp == NULL) return;
cginfo_t *cg = sp->curcg;
if (cg == NULL) return;
if (cg->sf == NULL) return;
// 更新領域の確定
update.width = r->w;
update.height = r->h;
sx = 0;
sy = 0;
dx = sp->cur.x - r->x;
dy = sp->cur.y - r->y;
w = cg->sf->width;
h = cg->sf->height;
SDL_Rect cg_rect = {0, 0, cg->sf->w, cg->sf->h};
int sx = 0;
int sy = 0;
int dx = sp->cur.x;
int dy = sp->cur.y;
int w = cg->sf->w;
int h = cg->sf->h;
if (!gr_clip(cg->sf, &sx, &sy, &w, &h, &update, &dx, &dy)) {
return NG;
if (!ags_clipCopyRect(&cg_rect, r, &sx, &sy, &dx, &dy, &w, &h)) {
return;
}
dx += r->x;
dy += r->y;
if (cg->sf->alpha) {
// alpha map がある場合
gre_BlendUseAMap(sf0, dx, dy,
sf0, dx, dy,
cg->sf, sx, sy, w, h,
cg->sf, sx, sy,
sp->blendrate);
if (SDL_ISPIXELFORMAT_ALPHA(cg->sf->format->format) || sp->blendrate < 255) {
SDL_SetSurfaceBlendMode(cg->sf, SDL_BLENDMODE_BLEND);
SDL_SetSurfaceAlphaMod(cg->sf, sp->blendrate);
} else {
if (sp->blendrate == 255) {
// alpha値指定が無い場合
gr_copy(sf0, dx, dy, cg->sf, sx, sy, w, h);
} else if (sp->blendrate > 0) {
// alpha値指定がある場合
gre_Blend(sf0, dx, dy,
sf0, dx, dy,
cg->sf, sx, sy, w, h,
sp->blendrate);
}
SDL_SetSurfaceBlendMode(cg->sf, SDL_BLENDMODE_NONE);
}
SDL_BlitSurface(cg->sf, &(SDL_Rect){sx, sy, w, h}, main_surface, &(SDL_Rect){dx, dy, w, h});
SACT_DEBUG("do update no=%d, sx=%d, sy=%d, w=%d, h=%d, dx=%d, dy=%d",
sp->no, sx, sy, w, h, dx, dy);
return OK;
}
// BlendScreenによる描画
int nt_sp_draw_scg(sprite_t *sp, MyRectangle *r) {
surface_t update;
cginfo_t *cg;
int sx, sy, w, h, dx, dy;
if (sp == NULL) return NG;
cg = sp->curcg;
if (cg == NULL) return NG;
if (cg->sf == NULL) return NG;
void nt_sp_draw_scg(sprite_t *sp, SDL_Rect *r) {
if (sp == NULL) return;
cginfo_t *cg = sp->curcg;
if (cg == NULL) return;
if (cg->sf == NULL) return;
// 更新領域の確定
update.width = r->w;
update.height = r->h;
sx = 0;
sy = 0;
dx = sp->cur.x - r->x;
dy = sp->cur.y - r->y;
w = cg->sf->width;
h = cg->sf->height;
SDL_Rect cg_rect = {0, 0, cg->sf->w, cg->sf->h};
int sx = 0;
int sy = 0;
int dx = sp->cur.x;
int dy = sp->cur.y;
int w = cg->sf->w;
int h = cg->sf->h;
if (!gr_clip(cg->sf, &sx, &sy, &w, &h, &update, &dx, &dy)) {
return NG;
if (!ags_clipCopyRect(&cg_rect, r, &sx, &sy, &dx, &dy, &w, &h)) {
return;
}
dx += r->x;
dy += r->y;
gre_BlendScreen(sf0, dx, dy,
sf0, dx, dy,
cg->sf, sx, sy, w, h);
SDL_SetSurfaceBlendMode(cg->sf, SDL_BLENDMODE_ADD);
SDL_BlitSurface(cg->sf, &(SDL_Rect){sx, sy, w, h}, main_surface, &(SDL_Rect){dx, dy, w, h});
SACT_DEBUG("do update no=%d, sx=%d, sy=%d, w=%d, h=%d, dx=%d, dy=%d",
sp->no, sx, sy, w, h, dx, dy);
return OK;
}
+14 -15
View File
@@ -25,11 +25,11 @@
#include "portab.h"
#include "system.h"
#include "ngraph.h"
#include "ags.h"
#include "input.h"
#include "sprite.h"
#include "sdl_core.h"
#include "gfx.h"
#include "effect.h"
/*
@@ -37,34 +37,33 @@
@param time: (msec)
@param cancel: (0:, 1:)
*/
int nt_sp_eupdate(int no, int time, int cancel) {
void nt_sp_eupdate(int no, int time, int cancel) {
if (no == 1013) {
nt_sp_update_all(TRUE);
return OK;
nt_sp_update_all(true);
return;
}
nt_sp_update_all(FALSE);
nt_sp_update_all(false);
enum sdl_effect_type type = from_sact_effect(no - 100);
enum effect_type type = from_sact_effect(no - 100);
if (type == EFFECT_INVALID) {
WARNING("Unimplemented effect %d", no);
type = EFFECT_CROSSFADE;
}
SDL_Rect rect = { 0, 0, sf0->width, sf0->height };
struct sdl_effect *eff = sdl_effect_init(&rect, NULL, 0, 0, sdl_getDIB(), 0, 0, type);
SDL_Rect rect = { 0, 0, main_surface->w, main_surface->h };
struct effect *eff = effect_init(&rect, NULL, 0, 0, gfx_getDIB(), 0, 0, type);
int sttime, curtime;
sttime = curtime = sdl_getTicks();
sttime = curtime = sys_get_ticks();
int edtime = curtime + time;
while ((curtime = sdl_getTicks()) < edtime) {
sdl_effect_step(eff, (double)(curtime - sttime) / (edtime - sttime));
int rest = 16 - (sdl_getTicks() - curtime);
while ((curtime = sys_get_ticks()) < edtime) {
effect_step(eff, (float)(curtime - sttime) / (edtime - sttime));
int rest = 16 - (sys_get_ticks() - curtime);
int key = sys_keywait(rest, cancel ? KEYWAIT_CANCELABLE : KEYWAIT_NONCANCELABLE);
if (cancel && key)
break;
}
sdl_effect_finish(eff);
effect_finish(eff);
ags_updateFull();
return OK;
}
+29 -52
View File
@@ -25,15 +25,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include "portab.h"
#include "system.h"
#include "list.h"
#include "ags.h"
#include "graphics.h"
// #include "sact.h"
#include "surface.h"
#include "ngraph.h"
#include "sprite.h"
// スプライト再描画間の間に変更のあったスプライトの領域の和
@@ -43,22 +40,22 @@ static SList *updatearea;
static SList *updatelist;
static void disjunction(void* region, void* data);
static MyRectangle get_updatearea();
static SDL_Rect get_updatearea();
static void do_update_each(void* data, void* userdata);
// 領域1と領域2をすべて含む矩形領域を計算
static void disjunction(void* region, void* data) {
MyRectangle *r1 = (MyRectangle *)region;
MyRectangle *r2 = (MyRectangle *)data;
SDL_Rect *r1 = (SDL_Rect *)region;
SDL_Rect *r2 = (SDL_Rect *)data;
SDL_UnionRect(r1, r2, r2);
free(r1);
}
// 更新の必要なスプライトの領域の和をとってクリッピングする
static MyRectangle get_updatearea() {
MyRectangle clip = {0, 0, 0, 0};
MyRectangle rsf0 = {0, 0, sf0->width, sf0->height};
MyRectangle result;
static SDL_Rect get_updatearea() {
SDL_Rect clip = {0, 0, 0, 0};
SDL_Rect screen = {0, 0, main_surface->w, main_surface->h};
SDL_Rect result;
slist_foreach(updatearea, disjunction, &clip);
@@ -66,7 +63,7 @@ static MyRectangle get_updatearea() {
updatearea = NULL;
// surface0との領域の積をとる
SDL_IntersectRect(&rsf0, &clip, &result);
SDL_IntersectRect(&screen, &clip, &result);
SACT_DEBUG("clipped area x=%d y=%d w=%d h=%d",
result.x, result.y, result.w, result.h);
@@ -77,7 +74,7 @@ static MyRectangle get_updatearea() {
// updatelist に登録してあるすべてのスプライトを更新
static void do_update_each(void* data, void* userdata) {
sprite_t *sp = (sprite_t *)data;
MyRectangle *r = (MyRectangle *)userdata;
SDL_Rect *r = (SDL_Rect *)userdata;
// 非表示の場合はなにもしない
if (!sp->show) return;
@@ -92,9 +89,9 @@ static void do_update_each(void* data, void* userdata) {
@param syncscreen: surface0 Screen
*/
int nt_sp_update_all(boolean syncscreen) {
void nt_sp_update_all(bool syncscreen) {
// 画面全体を更新領域に
MyRectangle r = {0, 0, sf0->width, sf0->height };
SDL_Rect r = {0, 0, main_surface->w, main_surface->h };
// updatelistに登録してあるスプライトを再描画
// updatelistはスプライトの番号順に並んでいる
@@ -106,54 +103,48 @@ int nt_sp_update_all(boolean syncscreen) {
if (syncscreen) {
ags_updateFull();
}
return OK;
}
/*
updateme(_part)spriteの和の領域をupdate
*/
int nt_sp_update_clipped() {
MyRectangle r;
void nt_sp_update_clipped() {
SDL_Rect r;
// 更新領域の確定
r = get_updatearea();
if (SDL_RectEmpty(&r))
return OK;
return;
// 更新領域に入っているスプライトの再描画
slist_foreach(updatelist, do_update_each, &r);
// 更新領域を Window に転送
ags_updateArea(r.x, r.y, r.w, r.h);
return OK;
}
/*
sprite全体の更新を登録
@param sp:
*/
int nt_sp_updateme(sprite_t *sp) {
MyRectangle *r;
void nt_sp_updateme(sprite_t *sp) {
SDL_Rect *r;
if (sp == NULL) return NG;
if (sp->cursize.width == 0 || sp->cursize.height == 0) return NG;
if (sp == NULL) return;
if (sp->width == 0 || sp->height == 0) return;
r = malloc(sizeof(MyRectangle));
r = malloc(sizeof(SDL_Rect));
r->x = sp->cur.x;
r->y = sp->cur.y;
r->w = sp->cursize.width;
r->h = sp->cursize.height;
r->w = sp->width;
r->h = sp->height;
updatearea = slist_append(updatearea, r);
SACT_DEBUG("x = %d, y = %d, spno = %d w=%d,h=%d",
r->x, r->y, sp->no, r->w, r->h);
return OK;
}
/*
@@ -164,13 +155,13 @@ int nt_sp_updateme(sprite_t *sp) {
@param w:
@param h:
*/
int nt_sp_updateme_part(sprite_t *sp, int x, int y, int w, int h) {
MyRectangle *r;
void nt_sp_updateme_part(sprite_t *sp, int x, int y, int w, int h) {
SDL_Rect *r;
if (sp == NULL) return NG;
if (w == 0 || h == 0) return NG;
if (sp == NULL) return;
if (w == 0 || h == 0) return;
r = malloc(sizeof(MyRectangle));
r = malloc(sizeof(SDL_Rect));
r->x = sp->cur.x + x;
r->y = sp->cur.y + y;
r->w = w;
@@ -180,8 +171,6 @@ int nt_sp_updateme_part(sprite_t *sp, int x, int y, int w, int h) {
SACT_DEBUG("x = %d, y = %d, spno = %d w=%d,h=%d",
r->x, r->y, sp->no, r->w, r->h);
return OK;
}
// スプライトの番号順に更新するためにリストに順番に要れるためのcallbck
@@ -214,18 +203,6 @@ void nt_sp_clear_updatelist(void) {
}
// デフォルトの壁紙update
int nt_sp_draw_wall(sprite_t *sp, MyRectangle *area) {
int sx, sy, w, h;
sx = area->x;
sy = area->y;
w = area->w;
h = area->h;
gr_fill(sf0, sx, sy, w, h, 0, 0, 0);
SACT_DEBUG("do update no=%d, sx=%d, sy=%d, w=%d, h=%d",
sp->no, sx, sy, w, h);
return OK;
void nt_sp_draw_wall(sprite_t *sp, SDL_Rect *area) {
SDL_FillRect(main_surface, area, SDL_MapRGB(main_surface->format, 0, 0, 0));
}
+11 -9
View File
@@ -32,9 +32,8 @@
#include "nact.h"
#include "alk.h"
#include "music.h"
#include "sdl_core.h"
#include "gfx.h"
#include "input.h"
#include "ngraph.h"
#include "cg.h"
#include "jpeg.h"
@@ -51,28 +50,31 @@ static void ndd_run(int demonum) {
int mus = ndemo_mus[demonum];
if (mus)
musbgm_play(mus, 0, 100);
musbgm_play(mus, 0, 100, 0);
uint32_t start = sdl_getTicks();
uint32_t start = sys_get_ticks();
while (!nact->is_quit) {
int i = (sdl_getTicks() - start) / (1000 / FPS);
int i = (sys_get_ticks() - 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);
SDL_Surface *sf = SDL_CreateRGBSurfaceWithFormatFrom(cg->pic, cg->width, cg->height, 24, cg->width * 3, SDL_PIXELFORMAT_RGB24);
SDL_BlitSurface(sf, NULL, main_surface, NULL);
ags_updateFull();
SDL_FreeSurface(sf);
cgdata_free(cg);
} else {
WARNING("Cannot decode CG %d in %s", i, alk_path);
}
int wait_ms = (i + 1) * (1000 / FPS) - (sdl_getTicks() - start);
int wait_ms = (i + 1) * (1000 / FPS) - (sys_get_ticks() - start);
if (wait_ms > 0) {
if (sys_keywait(wait_ms, KEYWAIT_CANCELABLE))
break;
} else {
gfx_updateScreen();
if (sys_getInputInfo())
break;
}
@@ -92,7 +94,7 @@ static void Init() {
*var = 1;
DEBUG_COMMAND("NightDemonDemo.Init %d,%d,%d,%p:", p1, p2, p3, var);
TRACE("NightDemonDemo.Init %d,%d,%d,%p:", p1, p2, p3, var);
}
static void Run() {
@@ -101,7 +103,7 @@ static void Run() {
ndd_run(p1);
DEBUG_COMMAND("NightDemonDemo.Run %d,%d:", p1, p2);
TRACE("NightDemonDemo.Run %d,%d:", p1, p2);
}
static const ModuleFunc functions[] = {
+3 -3
View File
@@ -40,7 +40,7 @@ static void Init() {
*/
int p1 = getCaliValue(); /* ITimer */
DEBUG_COMMAND_YET("RandMT.Init %p:", p1);
TRACE_UNIMPLEMENTED("RandMT.Init %p:", p1);
}
static void Get() {
@@ -59,7 +59,7 @@ static void Get() {
*var = (int)(genrand() * num) + 1;
}
DEBUG_COMMAND("RandMT.Get %d,%p:", num, var);
TRACE("RandMT.Get %d,%p:", num, var);
}
static void GetNoOverlap() {
@@ -69,7 +69,7 @@ static void GetNoOverlap() {
*var = (int)(genrand() * n) + min;
DEBUG_COMMAND("RandMT.GetNoOverlap %d,%d,%p:", min, n, var);
TRACE("RandMT.GetNoOverlap %d,%d,%p:", min, n, var);
}
static const ModuleFunc functions[] = {
+238
View File
@@ -0,0 +1,238 @@
/*
* Copyright (C) 2025 <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 "modules.h"
#include "nact.h"
#include "bgm.h"
#include "music.h"
#include "music_pcm.h"
#define SLOT 128
static int current_no = 0;
static void Init(void) {
int isys3x = getCaliValue();
TRACE("S3xMusic.Init %d:", isys3x);
}
static void CreateChannel(void) {
int nr_channels = getCaliValue();
if (nr_channels != 2)
SYSERROR("Unsupported number of channels: %d", nr_channels);
TRACE("S3xMusic.CreateChannel %d:", nr_channels);
}
static void Prepare(void) {
int ch = getCaliValue();
int no = getCaliValue();
int *result = getCaliVariable();
if (ch == 0) {
current_no = no;
*result = 1;
} else {
*result = muspcm_load_bgm(SLOT, no) ? 1 : 0;
}
TRACE("S3xMusic.Prepare %d, %d => %d:", ch, no, *result);
}
static void Unprepare(void) {
int ch = getCaliValue();
if (ch == 0) {
if (current_no) {
musbgm_stop(current_no, 0);
current_no = 0;
}
} else {
muspcm_unload(SLOT);
}
TRACE("S3xMusic.Unprepare %d:", ch);
}
static void Play(void) {
int p1 = getCaliValue();
int p2 = getCaliValue();
TRACE_UNIMPLEMENTED("S3xMusic.Play %d, %d:", p1, p2);
}
static void FadePlay(void) {
int ch = getCaliValue();
int fadein_time = getCaliValue();
int volume = getCaliValue();
int loop_count = getCaliValue(); // 0 = infinite
if (ch == 0) {
musbgm_play(current_no, fadein_time, volume, loop_count);
} else {
muspcm_start(SLOT, loop_count == 0 ? -1 : loop_count);
}
TRACE("S3xMusic.FadePlay %d, %d, %d, %d:", ch, fadein_time, volume, loop_count);
}
static void PlayPosSample(void) {
int p1 = getCaliValue();
int p2 = getCaliValue();
int p3 = getCaliValue();
int p4 = getCaliValue();
TRACE_UNIMPLEMENTED("S3xMusic.PlayPosSample %d, %d, %d, %d:", p1, p2, p3, p4);
}
static void IsPlay(void) {
int ch = getCaliValue();
int *result = getCaliVariable();
if (ch == 0) {
*result = current_no && musbgm_isplaying(current_no);
} else {
*result = muspcm_isplaying(SLOT);
}
TRACE("S3xMusic.IsPlay %d => %d:", ch, *result);
}
static void Stop(void) {
int ch = getCaliValue();
if (ch == 0) {
if (current_no)
musbgm_stop(current_no, 0);
current_no = 0;
} else {
muspcm_stop(SLOT);
}
TRACE("S3xMusic.Stop %d:", ch);
}
static void Restart(void) {
int p1 = getCaliValue();
TRACE_UNIMPLEMENTED("S3xMusic.Restart %d:", p1);
}
static void GetPlayPos(void) {
int ch = getCaliValue();
int *hour = getCaliVariable();
int *min = getCaliVariable();
int *sec = getCaliVariable();
int *msec = getCaliVariable();
if (ch == 0) {
int time = musbgm_getpos(current_no);
*hour = time / 360000;
*min = (time / 6000) % 60;
*sec = (time / 100) % 60;
*msec = (time % 100) * 10;
} else {
// not implemented
*hour = 0;
*min = 0;
*sec = 0;
*msec = 0;
}
TRACE("S3xMusic.GetPlayPos %d => %d, %d, %d, %d:", ch, *hour, *min, *sec, *msec);
}
static void GetPlayPosSample(void) {
int p1 = getCaliValue();
int *var1 = getCaliVariable();
int *var2 = getCaliVariable();
TRACE_UNIMPLEMENTED("S3xMusic.GetPlayPosSample %d, %p, %p:", p1, var1, var2);
}
static void SetRepeatStart(void) {
int p1 = getCaliValue();
int p2 = getCaliValue();
int p3 = getCaliValue();
TRACE_UNIMPLEMENTED("S3xMusic.SetRepeatStart %d, %d, %d:", p1, p2, p3);
}
static void SetRepeatEnd(void) {
int p1 = getCaliValue();
int p2 = getCaliValue();
int p3 = getCaliValue();
TRACE_UNIMPLEMENTED("S3xMusic.SetRepeatEnd %d, %d, %d:", p1, p2, p3);
}
static void FadeVolume(void) {
int ch = getCaliValue();
int time = getCaliValue();
int volume = getCaliValue();
int stop_after_fade = getCaliValue();
if (ch == 0) {
if (stop_after_fade) {
musbgm_stop(current_no, time / 10);
} else {
musbgm_fade(current_no, time / 10, volume);
}
} else {
if (stop_after_fade) {
muspcm_fadeout(SLOT, time);
} else {
muspcm_setvol(SLOT, volume);
}
}
TRACE("S3xMusic.FadeVolume %d, %d, %d, %d:", ch, time, volume, stop_after_fade);
}
static void IsFade(void) {
int ch = getCaliValue();
int *result = getCaliVariable();
*result = 0;
TRACE_UNIMPLEMENTED("S3xMusic.IsFade %d => %d:", ch, *result);
}
static void StopFade(void) {
int ch = getCaliValue();
TRACE_UNIMPLEMENTED("S3xMusic.StopFade %d:", ch);
}
static void WaitEnd(void) {
int p1 = getCaliValue();
int p2 = getCaliValue(); // IWinMsg
TRACE_UNIMPLEMENTED("S3xMusic.WaitEnd %d, %d:", p1, p2);
}
static void sleep(void) {
int p1 = getCaliValue(); // IWinMsg
TRACE_UNIMPLEMENTED("S3xMusic.sleep %d:", p1);
}
static const ModuleFunc functions[] = {
{"CreateChannel", CreateChannel},
{"FadePlay", FadePlay},
{"FadeVolume", FadeVolume},
{"GetPlayPos", GetPlayPos},
{"GetPlayPosSample", GetPlayPosSample},
{"Init", Init},
{"IsFade", IsFade},
{"IsPlay", IsPlay},
{"Play", Play},
{"PlayPosSample", PlayPosSample},
{"Prepare", Prepare},
{"Restart", Restart},
{"SetRepeatEnd", SetRepeatEnd},
{"SetRepeatStart", SetRepeatStart},
{"Stop", Stop},
{"StopFade", StopFade},
{"Unprepare", Unprepare},
{"WaitEnd", WaitEnd},
{"sleep", sleep},
};
const Module module_S3xMusic = {"S3xMusic", functions, sizeof(functions) / sizeof(ModuleFunc)};
+154 -156
View File
File diff suppressed because it is too large Load Diff
+28 -28
View File
@@ -25,11 +25,10 @@
#define __SACT_H__
#include "config.h"
#include <SDL_rect.h>
#include "portab.h"
#include "list.h"
#include "graphics.h"
#include "surface.h"
#include "ags.h"
#include "sacttimer.h"
#include "variable.h"
@@ -73,7 +72,7 @@ enum cgtype {
struct _cginfo {
enum cgtype type; // CGの種類, 0: 未使用, 1:リンクされている, ...
int no; // CGの番号
surface_t *sf; // CG本体
struct SDL_Surface *sf;
int refcnt; // 参照カウンタ。0になったら開放してもよい。
};
typedef struct _cginfo cginfo_t;
@@ -107,7 +106,8 @@ struct _sprite {
int numsound1, numsound2, numsound3;
// 初期 sprite の大きさ(cg1の大きさ)
MyDimension cursize;
int width;
int height;
// それぞれの状態で表示する CG
cginfo_t *cg1, *cg2, *cg3;
@@ -116,8 +116,8 @@ struct _sprite {
cginfo_t *curcg;
// スプライトを表示するか
boolean show;
boolean show_save; // Zkey hide save用
bool show;
bool show_save; // Zkey hide save用
// 表示する際のブレンド率 0:全く見えない, 255: 通常表示
int blendrate;
@@ -126,10 +126,10 @@ struct _sprite {
int freezed_state;
// 表示位置 (SetPos)
MyPoint loc;
SDL_Point loc;
// 現在のスプライトの表示位置
MyPoint cur;
SDL_Point cur;
// event callback
int (* eventcb)(struct _sprite *sp, agsevent_t *e); // for key/mouse
@@ -137,27 +137,27 @@ struct _sprite {
// sprite削除時の callback
void (* remove)(struct _sprite *sp);
// spriteを再描画するときの callback
int (* update)(struct _sprite *sp);
void (* update)(struct _sprite *sp);
boolean focused; // forcusを得ているか
boolean pressed; // このsprite上でマウスが押されているか
bool focused; // forcusを得ているか
bool pressed; // このsprite上でマウスが押されているか
SList *expsp; // 説明スプライトのリスト
// move command 用パラメータ
struct {
MyPoint to; // 移動先
SDL_Point to; // 移動先
int time; // 移動完了時間
int speed; // 移動速度
int starttime; // 移動開始時刻
int endtime; // 移動終了予定時刻
boolean moving; // 移動中かどうか
bool moving; // 移動中かどうか
} move;
// SACT.Numeral用パラメータ
struct {
int cg[10];
MyPoint pos;
SDL_Point pos;
int span;
} numeral;
@@ -170,8 +170,8 @@ struct _sprite {
// ゲットスプライト
struct {
boolean dragging; // ドラッグ中
MyPoint dragstart; // ドラッグ開始位置
bool dragging; // ドラッグ中
SDL_Point dragstart; // ドラッグ開始位置
} get;
// プットスプライト
@@ -190,8 +190,8 @@ struct _sprite {
// メッセージスプライト
struct {
SList *buf; // 表示する文字のリスト
surface_t *canvas; // 文字を描画するsurface
MyPoint dspcur; // 現在の表示位置
struct SDL_Surface *canvas;
SDL_Point dspcur; // 現在の表示位置
} msg;
} u;
};
@@ -213,7 +213,7 @@ struct _sact {
cginfo_t *cg[CGMAX]; // cgまたはCG_xxで作った CG
// 座標系の原点
MyPoint origin;
SDL_Point origin;
// 文字列 replce 用
SList *strreplace;
@@ -234,7 +234,7 @@ struct _sact {
int align; // 行そろえ
void (* cbmove)(agsevent_t *);
void (* cbrelease)(agsevent_t *);
surface_t *charcanvas;
struct SDL_Surface *charcanvas;
} sel;
// event listener
@@ -247,14 +247,14 @@ struct _sact {
int movestarttime; // 一斉に移動を開始するための開始時間
int movecurtime;
MyRectangle updaterect; // 更新が必要なspriteの領域の和
SDL_Rect updaterect; // 更新が必要なspriteの領域の和
// sact timer
stimer_t timer[65536];
// DnDに関するもの
sprite_t *draggedsp; // drag中のスプライト
boolean dropped; // スプライトがドロップされたかどうか
bool dropped; // スプライトがドロップされたかどうか
// keywaitの種類
int waittype;
@@ -273,15 +273,15 @@ struct _sact {
int numsoundob;
// depth map
surface_t *dmap;
struct SDL_Surface *dmap;
boolean zhiding; // Zkeyによる隠し中
bool zhiding; // Zkeyによる隠し中
int zofftime;
boolean zdooff;
bool zdooff;
// バックログ
boolean logging;
List *log;
bool logging;
List *log; // UTF-8 strings
};
typedef struct _sact sact_t;
+22 -83
View File
@@ -25,23 +25,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <SDL.h>
#include "portab.h"
#include "system.h"
#include "LittleEndian.h"
#include "input.h"
#include "ags.h"
#include "sact.h"
#include "surface.h"
#include "ngraph.h"
#include "pms.h"
#include "sprite.h"
#include "sdl_core.h"
#include "effect.h"
#include "mmap.h"
static surface_t *smask_get(int no);
static surface_t *smask_mul(surface_t *sf, int val);
// SACTEFAM を使ったマスク
typedef struct {
mmap_t *mmap;
@@ -52,24 +47,14 @@ typedef struct {
static SACTEFAM_t am;
struct ecopyparam {
int sttime;
int curtime;
int edtime;
int curstep;
int oldstep;
};
typedef struct ecopyparam ecopyparam_t;
static ecopyparam_t ecp;
// SACTEFAM.KLD の読み込み
int smask_init(char *path) {
bool smask_init(char *path) {
if (am.mmap)
return OK; // already loaded
return true; // already loaded
mmap_t *m = map_file(path);
if (!m)
return NG;
return false;
am.mmap = m;
am.datanum = LittleEndian_getDW(m->addr, 0);
am.no = malloc(sizeof(int) * am.datanum);
@@ -80,11 +65,11 @@ int smask_init(char *path) {
am.offset[i] = LittleEndian_getDW(m->addr, 16 + i * 16 + 8);
}
return OK;
return true;
}
// 指定番号の alphamask ファイルをよみだす
static surface_t *smask_get(int no) {
static cgdata *smask_get(int no) {
int i;
for (i = 0; i < am.datanum; i++) {
@@ -93,71 +78,25 @@ static surface_t *smask_get(int no) {
if (i == am.datanum) return NULL;
return sf_getcg(am.mmap->addr + am.offset[i], 0 /*FIXME*/);
}
// ベースになるマスクの alpha 値を拡大して取り出す
static surface_t *smask_mul(surface_t *sf, int val) {
surface_t *out = sf_create_alpha(sf->width, sf->height);
uint8_t *src = sf->alpha;
uint8_t *dst = out->alpha;
int pix = sf->width * sf->height;
while(pix--) {
int i = (*src - val) * 16;
if (i < 0) *dst = 255; // 指定値よりも大きいのはコピー
else if (i > 255) *dst = 0; // 指定値よりも小さいのは無視
else *dst = 255-i; // それ以外は値を16倍
src++; dst++;
}
return out;
return pms256_extract(am.mmap->addr + am.offset[i]);
}
/**
*
*/
int sp_eupdate_amap(int index, int time, int cancel) {
surface_t *mask, *mask2;
surface_t *sfsrc, *sfdst;
int key;
mask = smask_get(index);
void sp_eupdate_amap(int index, int time, int cancel) {
cgdata *mask = smask_get(index);
if (mask == NULL) {
sp_update_all(TRUE);
return OK;
sp_update_all(true);
return;
}
// 現在の sf0 をセーブ
sfsrc = sf_dup(sf0);
sp_update_all(FALSE);
sfdst = sf_dup(sf0);
sf_copyall(sf0, sfsrc);
ecp.sttime = ecp.curtime = sdl_getTicks();
ecp.edtime = ecp.curtime + time*10;
ecp.oldstep = 0;
while ((ecp.curtime = sdl_getTicks()) < ecp.edtime) {
int curstep = 255 * (ecp.curtime - ecp.sttime)/ (ecp.edtime - ecp.sttime);
// 元になるマスクのalpha値を16倍して欲しいところだけ取り出す
mask2 = smask_mul(mask, curstep);
gre_BlendUseAMap(sf0, 0, 0, sfsrc, 0, 0, sfdst, 0, 0, sfsrc->width, sfsrc->height, mask2, 0, 0, 255);
ags_updateFull();
key = sys_keywait(10, cancel ? KEYWAIT_CANCELABLE : KEYWAIT_NONCANCELABLE);
if (cancel && key) break;
// 一時マスクを削除
sf_free(mask2);
}
sf_copyall(sf0, sfdst);
SDL_Surface *mask_sf = SDL_CreateRGBSurfaceFrom(mask->pic, mask->width, mask->height, 8, mask->width, 0, 0, 0, 0);
sp_update_all(false); // old = gfx_texture, new = main_surface
struct effect *eff = effect_sactamask_init(mask_sf);
ags_runEffect(time * 10, cancel, (ags_EffectStepFunc)effect_step, eff);
effect_finish(eff);
ags_updateFull();
sf_free(sfsrc);
sf_free(sfdst);
sf_free(mask);
return OK;
SDL_FreeSurface(mask_sf);
cgdata_free(mask);
}
+2 -1
View File
@@ -24,6 +24,7 @@
#ifndef __SACTAMASK_H__
#define __SACTAMASK_H__
extern int smask_init(const char *path);
bool smask_init(const char *path);
void sp_eupdate_amap(int type, int time, int key);
#endif
+143 -132
View File
@@ -23,9 +23,11 @@
#include "config.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL.h>
#include "portab.h"
#include "nact.h"
@@ -33,19 +35,16 @@
#include "ags.h"
#include "sact.h"
#include "sactcg.h"
#include "surface.h"
#include "ngraph.h"
#include "cg.h"
#include "gfx.h"
#include "sactcg_stretch.c"
#include "sactcg_blend.c"
#define spcg_assert_no(no) \
#define SPCG_ASSERT_NO(no) \
if ((no) > (CGMAX -1)) { \
WARNING("no is too large (should be %d < %d)", (no), CGMAX); \
return NG; \
return; \
} \
static cginfo_t *scg_new(enum cgtype type, int no, surface_t *sf) {
static cginfo_t *scg_new(enum cgtype type, int no, SDL_Surface *sf) {
cginfo_t *info = calloc(1, sizeof(cginfo_t));
info->type = type;
info->no = no;
@@ -75,7 +74,7 @@ static cginfo_t *scg_get(int no) {
if (sact.cg[no] != NULL)
return sact.cg[no];
surface_t *sf = sf_loadcg_no(no - 1);
SDL_Surface *sf = cg_load_as_sdlsurface(no - 1);
if (!sf) {
WARNING("load fail (%d)", no -1);
return NULL;
@@ -95,85 +94,137 @@ void scg_deref(cginfo_t *cg) {
return;
if (cg->sf)
sf_free(cg->sf);
SDL_FreeSurface(cg->sf);
free(cg);
}
// 指定の大きさ、色の矩形の CG を作成
int scg_create(int wNumCG, int wWidth, int wHeight, int wR, int wG, int wB, int wBlendRate) {
spcg_assert_no(wNumCG);
void scg_create(int wNumCG, int wWidth, int wHeight, int wR, int wG, int wB, int wBlendRate) {
SPCG_ASSERT_NO(wNumCG);
surface_t *sf = sf_create_surface(wWidth, wHeight, sf0->depth);
gr_fill(sf, 0, 0, wWidth, wHeight, wR, wG, wB);
gr_fill_alpha_map(sf, 0, 0, wWidth, wHeight, wBlendRate);
SDL_Surface *sf = SDL_CreateRGBSurfaceWithFormat(0, wWidth, wHeight, 32, SDL_PIXELFORMAT_ARGB8888);
SDL_FillRect(sf, NULL, SDL_MapRGBA(sf->format, wR, wG, wB, wBlendRate));
scg_new(CG_SET, wNumCG, sf);
return OK;
}
// 指定のCGを反転させたCGを作成
int scg_create_reverse(int wNumCG, int wNumSrcCG, int wReverseX, int wReverseY) {
spcg_assert_no(wNumCG);
spcg_assert_no(wNumSrcCG);
void scg_create_reverse(int wNumCG, int wNumSrcCG, int wReverseX, int wReverseY) {
SPCG_ASSERT_NO(wNumCG);
SPCG_ASSERT_NO(wNumSrcCG);
cginfo_t *src = scg_get(wNumSrcCG);
if (!src)
return NG;
return;
surface_t *sf = stretch(src->sf, src->sf->width, src->sf->height, (wReverseX << 1) | wReverseY);
SDL_Surface *sf = SDL_ConvertSurface(src->sf, src->sf->format, 0);
if (wReverseX)
gfx_FlipSurfaceHorizontal(sf);
if (wReverseY)
gfx_FlipSurfaceVertical(sf);
scg_new(CG_REVERSE, wNumCG, sf);
return OK;
}
// 指定のCGを拡大/縮小したCGを作成
int scg_create_stretch(int wNumCG, int wWidth, int wHeight, int wNumSrcCG) {
spcg_assert_no(wNumCG);
spcg_assert_no(wNumSrcCG);
void scg_create_stretch(int wNumCG, int wWidth, int wHeight, int wNumSrcCG) {
SPCG_ASSERT_NO(wNumCG);
SPCG_ASSERT_NO(wNumSrcCG);
cginfo_t *src = scg_get(wNumSrcCG);
if (!src)
return NG;
surface_t *sf = stretch(src->sf, wWidth, wHeight, 0);
return;
SDL_Surface *sf = SDL_CreateRGBSurfaceWithFormat(0, wWidth, wHeight, src->sf->format->BitsPerPixel, src->sf->format->format);
SDL_BlitScaled(src->sf, NULL, sf, NULL);
scg_new(CG_STRETCH, wNumCG, sf);
return OK;
}
static SDL_Surface *blend(SDL_Surface *base, int x, int y, SDL_Surface *blend, int mode) {
assert(blend->format->format == SDL_PIXELFORMAT_ARGB8888 || blend->format->format == SDL_PIXELFORMAT_XRGB8888);
bool src_has_alpha = SDL_ISPIXELFORMAT_ALPHA(blend->format->format);
SDL_Surface *dst = SDL_ConvertSurfaceFormat(base, SDL_PIXELFORMAT_ARGB8888, 0);
SDL_Rect rect = {x, y, blend->w, blend->h};
SDL_IntersectRect(&(SDL_Rect){0, 0, dst->w, dst->h}, &rect, &rect);
for (int i = 0; i < rect.h; i++) {
uint8_t *dstp = (uint8_t *)dst->pixels + (i + rect.y) * dst->pitch + rect.x * 4;
uint8_t *srcp = (uint8_t *)blend->pixels + i * blend->pitch;
for (int j = 0; j < rect.w; j++) {
uint8_t *dstpp = dstp + j * 4;
uint8_t *srcpp = srcp + j * 4;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
// Use base's alpha map if blend has no alpha map
uint8_t alpha = src_has_alpha ? srcpp[3] : dstpp[3];
if (alpha == 0) {
// do nothing
} else if (alpha == 255) {
memcpy(dstpp, srcpp, 3);
} else {
for (int k = 0; k < 3; k++) {
dstpp[k] = (dstpp[k] * (255 - alpha) + srcpp[k] * alpha) / 255;
}
}
if (mode) {
int dsta = dstpp[3] + srcpp[3];
dstpp[3] = dsta > 255 ? 255 : dsta;
}
#else
// Use base's alpha map if blend has no alpha map
uint8_t alpha = src_has_alpha ? srcpp[0] : dstpp[0];
if (alpha == 0) {
// do nothing
} else if (alpha == 255) {
memcpy(dstpp + 1, srcpp + 1, 3);
} else {
for (int k = 1; k < 4; k++) {
dstpp[k] = (dstpp[k] * (255 - alpha) + srcpp[k] * alpha) / 255;
}
}
if (mode) {
int dsta = dstpp[0] + srcpp[0];
dstpp[0] = dsta > 255 ? 255 : dsta;
}
#endif
}
}
return dst;
}
// ベースCGの上にブレンドCGを重ねた CG を作成
int scg_create_blend(int wNumDstCG, int wNumBaseCG, int wX, int wY, int wNumBlendCG, int wAlphaMapMode) {
spcg_assert_no(wNumDstCG);
spcg_assert_no(wNumBaseCG);
spcg_assert_no(wNumBlendCG);
void scg_create_blend(int wNumDstCG, int wNumBaseCG, int wX, int wY, int wNumBlendCG, int wAlphaMapMode) {
SPCG_ASSERT_NO(wNumDstCG);
SPCG_ASSERT_NO(wNumBaseCG);
SPCG_ASSERT_NO(wNumBlendCG);
cginfo_t *basecg = scg_get(wNumBaseCG);
cginfo_t *blendcg = scg_get(wNumBlendCG);
if (!basecg || !blendcg) return NG;
if (!basecg || !blendcg) return;
surface_t *sf = blend(basecg->sf, wX, wY, blendcg->sf, wAlphaMapMode);
SDL_Surface *sf = blend(basecg->sf, wX, wY, blendcg->sf, wAlphaMapMode);
scg_new(CG_SET, wNumDstCG, sf);
return OK;
}
// 指定の文字列のCGを作成
int scg_create_text(int wNumCG, int wSize, int wR, int wG, int wB, int wText) {
spcg_assert_no(wNumCG);
void scg_create_text(int wNumCG, int wSize, int wR, int wG, int wB, int wText) {
SPCG_ASSERT_NO(wNumCG);
// 勝手に出ていいのかな?
if (svar_length(wText) == 0) return OK;
if (svar_length(wText) == 0) return;
ags_setFont(FONT_GOTHIC, wSize);
agsurface_t *glyph = ags_drawStringToSurface(svar_get(wText));
SDL_Surface *glyph = ags_drawStringToSurface(svar_get(wText), wR, wG, wB);
surface_t *sf = sf_create_surface(glyph->width, wSize, nact->ags.dib->depth);
gr_fill(sf, 0, 0, glyph->width, wSize, wR, wG, wB);
gr_draw_amap(sf, 0, 0, glyph->pixel, glyph->width, wSize, glyph->bytes_per_line);
SDL_Surface *sf = SDL_CreateRGBSurfaceWithFormat(0, glyph->w, wSize, 32, SDL_PIXELFORMAT_ARGB8888);
SDL_SetSurfaceBlendMode(glyph, SDL_BLENDMODE_NONE);
SDL_BlitSurface(glyph, NULL, sf, NULL);
SDL_FreeSurface(glyph);
scg_new(CG_SET, wNumCG, sf);
return OK;
}
// 数字文字列のCGを作成
int scg_create_textnum(int wNumCG, int wSize, int wR, int wG, int wB, int wFigs, int wZeroPadding, int wValue) {
spcg_assert_no(wNumCG);
void scg_create_textnum(int wNumCG, int wSize, int wR, int wG, int wB, int wFigs, int wZeroPadding, int wValue) {
SPCG_ASSERT_NO(wNumCG);
char s[256], ss[256];
if (wZeroPadding) {
@@ -186,157 +237,117 @@ int scg_create_textnum(int wNumCG, int wSize, int wR, int wG, int wB, int wFigs,
sprintf(s, ss, wValue);
ags_setFont(FONT_GOTHIC, wSize);
agsurface_t *glyph = ags_drawStringToSurface(s);
SDL_Surface *glyph = ags_drawStringToSurface(s, wR, wG, wB);
surface_t *sf = sf_create_surface(glyph->width, wSize, nact->ags.dib->depth);
gr_fill(sf, 0, 0, glyph->width, wSize, wR, wG, wB);
gr_draw_amap(sf, 0, 0, glyph->pixel, glyph->width, wSize, glyph->bytes_per_line);
SDL_Surface *sf = SDL_CreateRGBSurfaceWithFormat(0, glyph->w, wSize, 32, SDL_PIXELFORMAT_ARGB8888);
SDL_SetSurfaceBlendMode(glyph, SDL_BLENDMODE_NONE);
SDL_BlitSurface(glyph, NULL, sf, NULL);
SDL_FreeSurface(glyph);
scg_new(CG_SET, wNumCG, sf);
return OK;
}
// CGを複製
int scg_copy(int wNumDstCG, int wNumSrcCG) {
spcg_assert_no(wNumDstCG);
spcg_assert_no(wNumSrcCG);
void scg_copy(int wNumDstCG, int wNumSrcCG) {
SPCG_ASSERT_NO(wNumDstCG);
SPCG_ASSERT_NO(wNumSrcCG);
cginfo_t *src = scg_get(wNumSrcCG);
if (!src)
return NG;
return;
scg_new(CG_SET, wNumDstCG, sf_dup(src->sf));
return OK;
scg_new(CG_SET, wNumDstCG, SDL_ConvertSurface(src->sf, src->sf->format, 0));
}
// CGの一部を切りぬいたCGを作成
int scg_cut(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight) {
spcg_assert_no(wNumDstCG);
spcg_assert_no(wNumSrcCG);
void scg_cut(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight) {
SPCG_ASSERT_NO(wNumDstCG);
SPCG_ASSERT_NO(wNumSrcCG);
cginfo_t *src = scg_get(wNumSrcCG);
if (!src)
return NG;
return;
surface_t *sf = src->sf->alpha
? sf_create_surface(wWidth, wHeight, src->sf->depth)
: sf_create_pixel(wWidth, wHeight, src->sf->depth);
if (src->sf->pixel)
gr_copy(sf, 0, 0, src->sf, wX, wY, wWidth, wHeight);
if (src->sf->alpha)
gr_copy_alpha_map(sf, 0, 0, src->sf, wX, wY, wWidth, wHeight);
SDL_Surface *sf = SDL_CreateRGBSurfaceWithFormat(0, wWidth, wHeight, src->sf->format->BitsPerPixel, src->sf->format->format);
SDL_BlitSurface(src->sf, &(SDL_Rect){wX, wY, wWidth, wHeight}, sf, NULL);
scg_new(CG_SET, wNumDstCG, sf);
return OK;
}
// 元のCGの一部を切りぬいたCGを作成
int scg_partcopy(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight) {
spcg_assert_no(wNumDstCG);
spcg_assert_no(wNumSrcCG);
void scg_partcopy(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight) {
SPCG_ASSERT_NO(wNumDstCG);
SPCG_ASSERT_NO(wNumSrcCG);
cginfo_t *src = scg_get(wNumSrcCG);
if (!src)
return NG;
return;
surface_t *sf;
if (src->sf->alpha) {
sf = sf_create_surface(src->sf->width, src->sf->height, src->sf->depth);
gr_fill_alpha_map(sf, 0, 0, src->sf->width, src->sf->height, 255);
} else {
sf = sf_create_pixel(src->sf->width, src->sf->height, src->sf->depth);
}
if (src->sf->pixel)
gr_copy(sf, wX, wY, src->sf, wX, wY, wWidth, wHeight);
if (src->sf->alpha)
gr_copy_alpha_map(sf, wX, wY, src->sf, wX, wY, wWidth, wHeight);
SDL_Surface *sf = SDL_CreateRGBSurfaceWithFormat(0, src->sf->w, src->sf->h, src->sf->format->BitsPerPixel, src->sf->format->format);
SDL_FillRect(sf, NULL, SDL_MapRGBA(sf->format, 0, 0, 0, 255));
SDL_BlitSurface(src->sf, &(SDL_Rect){wX, wY, wWidth, wHeight}, sf, &(SDL_Rect){wX, wY, wWidth, wHeight});
scg_new(CG_SET, wNumDstCG, sf);
return OK;
}
// 全てのCGの開放
int scg_freeall() {
void scg_freeall(void) {
int i;
for (i = 1; i < CGMAX; i++) {
scg_free(i);
}
return OK;
}
/**
* CG
* (0)
*/
int scg_free(int no) {
spcg_assert_no(no);
void scg_free(int no) {
SPCG_ASSERT_NO(no);
cginfo_t *cg = sact.cg[no];
if (!cg) return NG;
if (!cg) return;
scg_deref(cg);
sact.cg[no] = NULL;
return OK;
}
// CGの種類を取得
int scg_querytype(int wNumCG, int *ret) {
if (wNumCG >= (CGMAX -1)) goto errexit;
if (sact.cg[wNumCG] == NULL) goto errexit;
*ret = sact.cg[wNumCG]->type;
return OK;
errexit:
*ret = CG_NOTUSED;
return NG;
int scg_querytype(int wNumCG) {
if (wNumCG >= (CGMAX -1)) return CG_NOTUSED;
if (sact.cg[wNumCG] == NULL) return CG_NOTUSED;
return sact.cg[wNumCG]->type;
}
// CGの大きさを取得
int scg_querysize(int wNumCG, int *w, int *h) {
bool scg_querysize(int wNumCG, int *w, int *h) {
if (wNumCG >= (CGMAX -1)) goto errexit;
if (sact.cg[wNumCG] == NULL) goto errexit;
if (sact.cg[wNumCG]->sf == NULL) goto errexit;
*w = sact.cg[wNumCG]->sf->width;
*h = sact.cg[wNumCG]->sf->height;
*w = sact.cg[wNumCG]->sf->w;
*h = sact.cg[wNumCG]->sf->h;
return OK;
return true;
errexit:
*w = *h = 0;
return NG;
return false;
}
// CGのBPPを取得
int scg_querybpp(int wNumCG, int *ret) {
if (wNumCG >= (CGMAX -1)) goto errexit;
if (sact.cg[wNumCG] == NULL) goto errexit;
if (sact.cg[wNumCG]->sf == NULL) goto errexit;
*ret = sact.cg[wNumCG]->sf->depth;
return OK;
errexit:
*ret = 0;
return NG;
int scg_querybpp(int wNumCG) {
if (wNumCG >= (CGMAX -1)) return 0;
if (sact.cg[wNumCG] == NULL) return 0;
if (sact.cg[wNumCG]->sf == NULL) return 0;
return sact.cg[wNumCG]->sf->format->BitsPerPixel;
}
// CGの alphamap が存在するかを取得
int scg_existalphamap(int wNumCG, int *ret) {
if (wNumCG >= (CGMAX -1)) goto errexit;
if (sact.cg[wNumCG] == NULL) goto errexit;
if (sact.cg[wNumCG]->sf == NULL) goto errexit;
*ret = sact.cg[wNumCG]->sf->alpha ? 1 : 0;
errexit:
*ret = 0;
return NG;
bool scg_existalphamap(int wNumCG) {
if (wNumCG >= (CGMAX -1)) return false;
if (sact.cg[wNumCG] == NULL) return false;
if (sact.cg[wNumCG]->sf == NULL) return false;
return SDL_ISPIXELFORMAT_ALPHA(sact.cg[wNumCG]->sf->format->format);
}
+17 -18
View File
@@ -27,23 +27,22 @@
#include "portab.h"
#include "sact.h"
extern cginfo_t *scg_addref(int no);
extern void scg_deref(cginfo_t *cg);
extern int scg_create(int wNumCG, int wWidth, int wHeight, int wR, int wG, int wB, int wBlendRate);
extern int scg_create_reverse(int NumCG, int wNumSrcCG, int wReverseX, int wReverseY);
extern int scg_create_stretch(int wNumCG, int wWidth, int wHeight, int wNumSrcCG);
extern int scg_create_blend(int wNumDstCG, int wNumBaseCG, int wX, int wY, int wNumBlendCG, int wAlphaMapMode);
extern int scg_create_text(int wNumCG, int wSize, int wR, int wG, int wB, int wText);
extern int scg_create_textnum(int wNumCG, int wSize, int wR, int wG, int wB, int wFigs, int wZeroPadding, int wValue);
extern int scg_copy(int wNumDstCG, int wNumSrcCG);
extern int scg_cut(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight);
extern int scg_partcopy(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight);
extern int scg_freeall();
extern int scg_free(int cg);
extern int scg_querytype(int wNumCG, int *ret);
extern int scg_querysize(int wNumCG, int *w, int *h);
extern int scg_querybpp(int wNumCG, int *ret);
extern int scg_existalphamap(int wNumCG, int *ret);
extern int scg_linkcgfree(int no);
cginfo_t *scg_addref(int no);
void scg_deref(cginfo_t *cg);
void scg_create(int wNumCG, int wWidth, int wHeight, int wR, int wG, int wB, int wBlendRate);
void scg_create_reverse(int NumCG, int wNumSrcCG, int wReverseX, int wReverseY);
void scg_create_stretch(int wNumCG, int wWidth, int wHeight, int wNumSrcCG);
void scg_create_blend(int wNumDstCG, int wNumBaseCG, int wX, int wY, int wNumBlendCG, int wAlphaMapMode);
void scg_create_text(int wNumCG, int wSize, int wR, int wG, int wB, int wText);
void scg_create_textnum(int wNumCG, int wSize, int wR, int wG, int wB, int wFigs, int wZeroPadding, int wValue);
void scg_copy(int wNumDstCG, int wNumSrcCG);
void scg_cut(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight);
void scg_partcopy(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight);
void scg_freeall(void);
void scg_free(int cg);
int scg_querytype(int wNumCG);
bool scg_querysize(int wNumCG, int *w, int *h);
int scg_querybpp(int wNumCG);
bool scg_existalphamap(int wNumCG);
#endif
-31
View File
@@ -1,31 +0,0 @@
//
static surface_t *blend(surface_t *base, int x, int y, surface_t *blend, int mode) {
surface_t *dst = sf_create_surface(base->width, base->height, base->depth);
gr_copy(dst, 0, 0, base, 0, 0, base->width, base->height);
if (base->alpha) {
// ベースに alpha map がある場合はそれをコピー
gr_copy_alpha_map(dst, 0, 0, base, 0, 0, base->width, base->height);
} else {
// 無い場合は全て 255 の map を作成
gr_fill_alpha_map(dst, 0, 0, base->width, base->height, 255);
}
if (blend->alpha) {
// 重ね合わせ先の alpha map があるときはそれを使う
gre_BlendUseAMap(dst, x, y, base, x, y, blend, 0, 0, blend->width, blend->height, blend, 0, 0, 255);
} else {
// 無いときは dst の alpha map を使う
gre_BlendUseAMap(dst, x, y, base, x, y, blend, 0, 0, blend->width, blend->height, dst, x, y, 255);
}
// alpha 作成モードが dst + blend の時は飽和加算
if (mode == 1) {
gr_saturadd_alpha_map(dst, x, y, blend, 0, 0, blend->width, blend->height);
}
return dst;
}
-114
View File
@@ -1,114 +0,0 @@
// 拡大縮小
static surface_t *stretch(surface_t *src, int dw, int dh, int mirror) {
surface_t *dst = calloc(1, sizeof(surface_t));
float a1, a2, xd, yd;
int sw, sh;
int *row, *col;
int x, y;
uint8_t *sdata, *ddata;
dst->width = dw;
dst->height = dh;
dst->depth = src->depth;
dst->bytes_per_line = dw * src->bytes_per_pixel;
dst->bytes_per_pixel = src->bytes_per_pixel;
if (src->pixel) {
dst->pixel = malloc(dh * dst->bytes_per_line);
}
if (src->alpha) {
dst->alpha = malloc(dw * dh);
}
sdata = GETOFFSET_PIXEL(src, 0, 0);
ddata = GETOFFSET_PIXEL(dst, 0, 0);
sw = src->width;
sh = src->height;
a1 = (float)sw / (float)dw;
a2 = (float)sh / (float)dh;
row = malloc(sizeof(int) * dw);
// 1おおきくして初期化しないと col[dw-1]とcol[dw]が同じになる
// 可能性がある。
col = calloc(dh +1, sizeof(int));
if (mirror & 1) {
/* 上下反転 added by tajiri@wizard */
for (yd = sh - a2, y = 0; y < dh; y++) {
col[y] = yd; yd -= a2;
}
} else {
for (yd = 0.0, y = 0; y < dh; y++) {
col[y] = yd; yd += a2;
}
}
if (mirror & 2) {
/* 左右反転 added by tajiri@wizard */
for (xd = sw - a1, x = 0; x < dw; x++) {
row[x] = xd; xd -= a1;
}
} else {
for (xd = 0.0, x = 0; x < dw; x++) {
row[x] = xd; xd += a1;
}
}
#define SCALEDCOPYAREA(type) { \
int x, y; \
type *sl, *dl; \
uint8_t *_sl, *_dl; \
for (y = 0; y < dh; y++) { \
sl = (type *)(sdata + *(y + col) * src->bytes_per_line);\
dl = (type *)(ddata + y * dst->bytes_per_line);\
for (x = 0; x < dw; x++) { \
*(dl + x) = *(sl + *(row + x)); \
} \
_dl = (uint8_t *)dl; \
while(*(col + y) == *(col + y + 1)) { \
_sl = _dl; \
_dl += dst->bytes_per_line; \
memcpy(_dl, _sl, dw * sizeof(type)); \
y++; \
} \
}}
switch(dst->depth) {
case 8:
SCALEDCOPYAREA(uint8_t); break;
case 16:
SCALEDCOPYAREA(uint16_t); break;
case 24:
case 32:
SCALEDCOPYAREA(uint32_t); break;
default:
break;
}
if (src->alpha) {
int x, y;
uint8_t *sl, *dl;
uint8_t *_sl, *_dl;
sdata = GETOFFSET_ALPHA(src, 0, 0);
ddata = GETOFFSET_ALPHA(dst, 0, 0);
for (y = 0; y < dh; y++) {
sl = (uint8_t *)(sdata + *(y + col) * src->width);
dl = (uint8_t *)(ddata + y * dst->width);
for (x = 0; x < dw; x++) {
*(dl + x) = *(sl + *(row + x));
}
_dl = (uint8_t *)dl;
while(*(col + y) == *(col + y + 1)) {
_sl = _dl;
_dl += dst->width;
memcpy(_dl, _sl, dw);
y++;
}
}
}
free(row);
free(col);
return dst;
}
+1 -2
View File
@@ -25,13 +25,12 @@
#include "portab.h"
// グラフ用チャート作成
int schart_pos(int *pos, int pos1, int pos2, int val1, int val2, int val) {
void schart_pos(int *pos, int pos1, int pos2, int val1, int val2, int val) {
if (val1 == val2) {
*pos = 0;
} else {
*pos = (((pos2 - pos1) * (val - val1)) / (val2 - val1)) + pos1;
}
return OK;
}
/*

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