This is used for collision detection between a map object and the player
character. The current implementation is very simple, only performing
AABB intersection tests, but it is enough to allow the player to walk
around the first dungeon in Rance Quest.
V5 is used until Daiteikoku, and v7 since Rance Quest. Since both are
Ain v6, the save version is determined by the presence of the "MainVM"
field in AliceStart.ini.
Notable changes:
* The numerator / denominator parameters of AddMotion[HV]GaugeRate are
int in GoatGUIEngine but float in GUIEngine and PartsEngine.
* AnteaterADVEngine.ADVLogList_AddText has second parameter
(int WindowNo) since Oyako Rankan.
This also avoids using non-void functions where a void function is
expected. It is fine in most ABIs, but raises a runtime error in wasm32.
It is currently only used to populate a field in RSM v9 save file.
As far as I can tell from examining Rance 01's resume save, this
reference does not seem to increment the target's refcount.
Use the normal effect system for fullscreen effects. This allows effects
that are implemented via shaders to be used, such as the blind effects
which are used frequently in Daibanchou.
Delegates "weakly" reference objects, meaning that referenced objects
can be deleted. Delegate invocations must not invoke on deleted objects.
This is achieved as follows:
* Each heap object has a sequential number.
* Each delegate object is backed by a page storing (object, function,
seq) triples.
* Deleted objects can be detected by comparing the sequential number
stored in the delegate with the sequential number of the object
currently on the heap.
This is consistent with the AliceSoft's implementation (presumed from
the contents of resume save).
This implementation removes dead objects from the delegate in DG_CALL
and DG_NUMOF instructions. (We could do that more often, e.g. when an
object is added to a delegate.)
This breaks existing resume saves that contain delegates. For games that
predate delegate support, this does not affect the save format.
This reverts the following commits:
* 4b1257f "Fix delegate memory management"
* 9bb4665 "Add changes to vm.h" (partial revert)
* 75d6386 "Fix ResumeSave/ResumeLoad bugs with delegates" (partial
revert)
We are going to take a different approach to implementing weak
references in delegates.
Add an option to insert a delay when skipping messages with CTRL.
This is accomplished by overriding the 'A' function. Since the function
to check the state of a key (CTRL in this case) varies by game, an
xsystem4-specific system call is added for this purpose.
Fixes#119
gfx_render_text uses floats for layout, so the parts_text layout should
use floats to match.
This fixes an issue with off-center text in the English version of Rance
01.
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.
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.
* The "type" argument of S_MOD is 48 for bool, 56 for long int
* %b, %c, %d can consume any integer types (int, bool, or long int)
* If the value cannot be consumed, S_MOD should return the format
string instead of an empty string
It is implemented as a post-processing effect. The hack for the
projection transform matrix has been removed, because now the image is
flipped upside down in the post-processing stage.
This implementation supports only single-frame sprites with a single
child object. As far as I know, all Flash effects in AliceSoft games
meet this requirement.
The DefineSound tag in SWF has raw PCM data, so we create a WAV file in-
memory and pass it to audio_play_archive_data(). This is not strictly
necessary since libsndfile can handle raw PCM data, but keeps the audio
and mixer interfaces simple.
TapirEngine is the 3D rendering engine used in RanceQuest.
This implements the minimum functionality that is needed to render the
first battle scene. The lighting is still incorrect.
This SWF parser is far from complete, in particular it only supports
simple bitmap-filled rectangular shapes, but it covers all the features
used in Daiteikoku, Rance Quest, Pastel Chime 3 and Dorapeko.
Flash files are stored in archives in AFF format, which is an encrypted
SWF wrapper. The decryption code was adapted from GARbro.
Text sprites hold the height of the text drawn on them, and
sact_SP_TextNewLine increases the Y coordinate by this value if
nTextSize is 0.
The nTextSize argument of sact_SP_TextHome affects this value.
Beat Blades Haruka depends on this behavior.
xsystem4.scene: returns a list of scene entities
* all entities have an entityId that can be used in further requests
* SACT2 sprites have a 'sprite' member with a spriteId that can be
used in further requests
xsystem4.renderEntity: renders a scene entity and returns the texture
xsystem4.spriteTexture: returns the stored SACT2 sprite texture
xsystem4.renderParts: renders a parts object and returns the texture
xsystem4.partsTexture: returns the stored parts object texture
Image data in texture objects is RGB8888 encoded in base 64.