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.
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.
And by extension config.save_dir. This fixes an issue where paths
retrieved by system.GetSaveFolderName and then passed to gamedir_path
would become invalid.
Fixes#115
So far only basic debugging functionality is implemented (breakpoints,
stepping, stack traces/variables).
This is not tested against an established DAP client. My intention is to
create a custom GUI frontend and extend the protocol to support
xsystem4-specific features, such as inspecting the scene. (This work is
underway.)
Instruction references are hex-encoded address strings. Clients do not
need to obtain them from DAP requests. This is outside the spec, but it
is needed for a binary-only debugger.
Functions that write directly to stdout (e.g. printf) should generally
not be used any more. Instead, use either sys_message (which respects
sys_silent) or log_message (which will send the message to the debugger
if DAP is enabled). stderr can be used as normal.
When loading a delegate, the stored objects must be registered to it.
Also, delegate_call cannot use vm_execute because the VM cannot be
resumed from such a state.
Incidentally, this means that ResumeSave cannot be called from within a
constructor/destructor (since they also use vm_execute), but this is
probably not a problem.
The game currently runs up until the first unimplemented function
(SeekEndMotion) during the intro events, using the existing PE_
functions with a few minor fixes.
The afa implementation from libsys4 now handles basename indexing, so we
use that instead of creating a separate index. Also, afa v1 is now
properly supported in libsys4, so there is no need for the
id_indexed_afa hack.
Statically link FFmpeg on Windows. This requires building a slimmed-down
version of FFmpeg from source. The build process is documented in the
README.
Also add ffmpeg dependency to the nix flake.
Try to link statically as much as possible on Windows, to reduce the
number of DLLs that have to be shipped with Windows builds.
Also document the build process on Windows.
After this, xsystem4 uses the global/group save format used by the
original System4, instead of the JSON format. Existing JSON save files
can still be loaded.
This makes save files interoperable between System4 and xsystem4 in some
games, including Sengoku Rance and Toushin Toshi III.
The 3rd argument to the instruction indicates the type of the second
argument. If there are multiple specifiers in the format string, the
first specifier matching the given type is substituted (NOT the first
specifier encountered when processing the format string).
Print usage information when there is an error in the command line
arguments. Also, wait for keypress before exiting on Windows so that the
user can read the error message.
Pointers to `struct font_size` objects are cached in `struct text_style`
objects, so the `sizes` array can't be reallocated.
This fixes a crash in Rance 02 when entering battle.
Add a mechanism for libraries to resolve incompatibilities between
library versions before linking.
This is currently used for ChipmunkSpriteEngine and GoatGUIEngine,
where early versions used integer IDs when loading CGs (later versions
use strings).
There are now two types of asset management:
1. ID-indexed assets, where IDs are not necessarily sequential
2. name-indexed assets
Name-indexed assets can have additional archives added at run-time. This
is to support the CGManager.LoadArchive function used in Rance Quest
Magnum.
Name-indexed assets always use .afa archives. ID-indexed assets mostly
use .ald archives, except for Daiteikoku and Shaman's Sanctuary.
asset_get_by_name is now case insensitive and ignores the file
extension.
asset_exists and asset_get now take 1-indexed IDs.
Custom CG indexing code for Shaman's Sanctuary is now removed and
replaced with a proper implementation of afa v1 archives in libsys4.
ReignEngine is the 3D rendering engine used in Toushin Toshi III, and is
the predecessor of the 3D engines for Rance Quest, Rance 9, Evenicle,
etc.
This implements minimal functionality to be able to draw the first 3D
dungeon scene. Many important parts such as motion and lighting are not
implemented yet.
SDL_ttf isn't really designed to be used with OpenGL. It caches glyph
bitmaps in memory, whereas we want to cache glyph textures on the GPU.
By using FreeType directly we avoid creating and destroying a new
texture every time a glyph is rendered.
Additionally, all glyph textures (including fnl-derived glyphs) now use
the GL_RED internal format instead of GL_RGBA.
Use `unlikely` (__builtin_expect) to help the compiler optimize error
checks in some hot functions (in my testing, stack_pop_var was one of
the hottest functions, right behind execute_instruction).
Only unscaled glyph bitmaps are now cached in regular memory. Scaled
glyphs are stored as textures on the GPU. Only the alpha channel on
glyph textures is used, with the color being provided as an input to the
shader.
Outline and bold rendering is improved by using a simple dilate shader.
This looks okay but could be improved (the result is a bit blurry
still).
This improves the look and (especially) the performance of text
rendering in the MangaGamer version of Sengoku Rance.
There are still some bugs/unimplemented features, but the game should be
more or less bearable to play in this state.
The game now basically runs, but with very bad performance and lots of
aliasing on text.
Need to implement anti-aliasing and caching of rendered glyphs next.
Read .xsys4-debugrc from ~/.xsystem4 and/or the game directory on
startup. This is just a text file with one debugger command per line.
Can be used to set breakpoints or log functions automatically at
startup.
This can also be used to work around a limitation on Windows where the
IME doesn't work in the debugger, making it impossible to input Japanese
text.
Add vm-state command, which prints disassembly around the current
instruction pointer and the current contents of the stack.
It was necessary to change how breakpoints are implemented for this.
When adding a breakpoint, the original opcode now remains in the
instruction stream, bitwise-or'd with BREAKPOINT. A hash table indexed
by address is used to store breakpoint objects.