This adds a new parameter `blend` to `gfx_draw_glyph()`. When `blend` is
true, the function performs normal alpha blending (same as
`gfx_draw_glyph_to_pmap()`).
If `blend` is false, the resulting pixel color will be the text color
and the alpha value will be copied from the glyph texture. However, if
the alpha value is less than 0.01, the pixel will not be written.
If you are drawing on a transparent texture (which will later be blended
into another texture), `blend` should be false. If you are drawing on top
of an image, `blend` should be true.
`gfx_draw_glyph()` used to fill transparent pixels with text color, but
this step is no longer needed and has been removed.
== Handles
As a general pattern, these libraries have an interface based on integer
handles allocated by Open() and released by Close(); in the AliceSoft's
implementation, handles are pointers to internal objects. Note that:
* 0 is used to represent an invalid handle, and
* Small numbers cannot be handles. For example, Mamanyonyo has code that
treats an integer as a CG number if it is less than 10000, and as a
surface handle otherwise.
In this patch, handles are generated using id_pool.h functions. In order
to achieve the above, the interface is extended so that the minimum ID
value can be specified (the `base` parameter of id_pool_init()).
== Graphics System
Surface objects (implemented in vmSurface.[ch]) plays a central role in
Mamanyonyo's graphics system, and the sprite system (vmSprite.c) is
implemented on top of it. vmSprite.c uses scene.h functions.
== vmChrLoader and vmMapLoader
Since Mamanyonyo's character data format is the same as Widenyo's,
the ChrLoader code has been refactored and used from vmChrLoader.c.
On the other hand, MapLoader and vmMapLoader do not share code because
the map file format is different from Widenyo.
This prevents glTexImage2D() from failing and resulting in an invalid
texture if a width or height specified in sact2.SP_Create() is greater
than GL_MAX_TEXTURE_SIZE.
It is very rare and is probably a programming error in the game script.
If the resulting texture is used for rendering, it may mess up the
screen, but at least it won't crash.
Fixes https://github.com/kichikuou/xsystem4-android/issues/4.
It is used (only?) in Beat Blades Haruka, when two enemies are found by
enemy seek.
This is just a screen effect and can be ignored without affecting
gameplay.
Some games (e.g. Toushin Toshi 3) malfunction when system.GetTime()
returns a negative number.
On many systems clock_gettime(CLOCK_MONOTONIC) returns the time since
OS startup, but this wraps to a negative number after about 24.8 days.
As a mitigation, use SDL_GetTicks() instead, which returns the elapsed
time since game startup.
Since this is the surface to render to, it should not be added to the
list of surfaces to draw from.
This is done by marking sprite -1 as hidden. Now SACT2.SP_GetShow(-1)
returns 0 and SACT2.SP_SetShow(-1, true) raises a runtime error. This is
consistent with the AliceSoft's implementation.
On Android, when the user enters "ら", "ん", "す" with the virtual
keyboard and converts it to "ランス", xsystem4 receives the following
events:
SDL_TEXTINPUT("ら")
SDL_TEXTINPUT("ん")
SDL_TEXTINPUT("す")
SDL_KEYDOWN(backspace)
SDL_KEYUP(backspace)
SDL_KEYDOWN(backspace)
SDL_KEYUP(backspace)
SDL_KEYDOWN(backspace)
SDL_KEYUP(backspace)
SDL_TEXTINPUT("ランス")
The backspace key events are generated by SDL to delete the unconverted
text. However, System4 games process the backspace key by polling, so
if the SDL_KEYDOWN and SDL_KEYUP events occur in close succession, the
game cannot detect that the backspace key has been pressed.
To solve this problem, this patch queues these consecutive input events
and processes them with an interval of at least 10ms.
Fixes https://github.com/kichikuou/xsystem4-android/issues/2.
This adds gestures that allow touch device users to emulate the
following mouse/keyboard actions:
- Right-click: touch outside the game's viewport
- Ctrl key: one-finger touch and hold (for one second)
- Mouse wheel: Swipe up / down with two fingers
A typical event loop in System4 game looks like this:
while (true) {
SACT2.Mouse_GetPos(x, y);
// Update the screen according to the mouse position (x, y)
...
SACT2.Update();
if (SACT2.Key_IsDown(VK_LBUTTON)) {
// A button was pressed at (x, y)
...
}
}
This works poorly with touch devices. Assume that a touch event occured
during SACT2.Update(). It updates internal mouse position and button
status. After SACT2.Update(), the game calls SACT2.Key_IsDown(VK_LBUTTON).
It returns true, but the game has not yet called SACT2.Mouse_GetPos()
after the touch event, so it assumes that the button was pressed where
the mouse pointer was before the touch.
In order to avoid this situation, this defers mouse button events
synthesized (by SDL) from touch. Such deferred events are processed when
SACT2.Mouse_GetPos() is called or after 50ms.
Writing save files in RSM format is only enabled if `--save-format=rsm`
command line flag is specified, because this implementation does not
create save files that are fully compatible with the AliceSoft's
implementation:
* There is no simple way to determine the RSM format version used by the
game.
* There are several unknown fields in the RSM format.
* Empty arrays are represented as NULL pages in xsystem4, so type
information of such objects cannot be saved.
These limitations are not a problem for the following use cases:
* Use the created save files only in xsystem4
* Load save files created by System40.exe
Also, RSM save files are much smaller and faster to read and write than
JSON.
BanMisc.{Save,Load}Struct now serializes structs in the same format as
AliceSoft's implementation, rather than in JSON format. The old JSON
format can also be loaded for backwards compatibility.