singe/CHANGELOG

474 lines
16 KiB
Text

SINGE 3.00
==========
Unreleased
API Changes
-----------
- The name now expands to "SINGE Is Not a Game Emulator", in the banner,
the manual, INSTALL, and the Windows file description.
- lfs.dir, lfs.attributes and lfs.symlinkattributes see inside a packed
game (the union of its loose directory, its data overlay and the
database), and lfs.mkdir and lfs.rmdir act on its data overlay, so
frameworks that list or create their own directories work packed.
- A game can be one file: singe --pack DIRECTORY GAME.game writes the game's
scripts, art, sounds, fonts, and video into an SQLite database, and
singe GAME.game (or the menu, which lists every .game file beside the game
directories) runs it. Nothing in a game has to change to be packed:
every name a script uses (dofile, require, io.open and friends,
spriteLoad, soundLoad, fontLoad, videoLoad, framefiles, controls.cfg)
goes through one lookup that tries a loose directory named like the
database, then the game's data directory, then the database, so
packed games can be modded by dropping files beside them and files a
game writes land under data/<game>/files. Inside a database names
are matched without regard to case and a leading own-directory prefix
("DLe/Cfg/x") is ignored. singe --unpack GAME.game DIRECTORY restores
the files and singe --patch GAME.game SOURCE replaces files from a
directory or a patch database in one transaction. --entry=N picks
which games.dat entry a .game launch runs. Loose games are
untouched by all of this. Scripts get SQLite for their own data with
require("sqlite3"). The archive installer (.game, .tool, and .patch
archives dropped beside the binary) is gone along with libarchive; a
game is a .game file or a directory, copied into place.
- Video is decoded by libavcodec directly; FFMS2 is gone. Seeking is still
frame exact, indexing is faster, and the index files in the data
directory use a new format (old ones are rebuilt automatically).
Multi-channel audio is downmixed to stereo instead of refused. Indexing
is a few seconds at most, so the indexing screen and its artwork are gone.
Video is
decoded by the platform's hardware decoder when there is one (VA-API or
VDPAU on Linux, D3D11VA on Windows, VideoToolbox on macOS) and falls
back to software otherwise; --softwarevideo forces software.
- Singe is built on SDL3 (SDL 3.4, SDL3_image, SDL3_mixer 3.2, SDL3_ttf)
instead of SDL2. Nothing changes for scripts: the same functions,
constants, scancodes, and controls.cfg names. SDL2_gfx is gone; sprite
and video rotation and scaling are done by the engine itself.
- The sprite handle is now the FIRST argument of spriteDraw(), spriteLoop(),
spriteQuality(), spriteRotate(), spriteRotateAndScale(), spriteScale(), and
spriteSetFrame(), matching the video*() functions. Move the last argument
of each call to the front. Games that cannot be edited can set
SINGE_LEGACY_SPRITE_ARGS = true before loading the framework, or add
LEGACY_SPRITE_ARGS = true to their games.dat entry. See "Migrating from
Singe 2.10" in the manual.
- Singe is no longer laserdisc only. A games.dat entry with a VIDEO is a
laserdisc game; one with the line missing or blank runs without a
disc, on a canvas sized by CANVAS_X/CANVAS_Y (default 720x480), the
disc functions become harmless, and discGetState() returns the new
DISC_EJECTED. On the command line --disc (implied by --framefile)
declares the disc, since a video found beside the script no longer
does; --canvas=WxH sizes the canvas. Existing games.dat files need no
change. Scripts can test SINGE_DISC.
- mouseSetEnabled(bool) and singeSetPauseKeyEnabled(bool) added. The old
mouseEnable/mouseDisable and singeEnablePauseKey/singeDisablePauseKey are
now aliases defined in Framework.singe.
- Handles, counts, and frame numbers are returned as Lua integers.
videoIsPlaying() returns a boolean. mouseSetMode() returns nothing.
- onControllerMoved() receives the controller index (0 to 3), not SDL's
instance ID. onMouseMoved() in MANY_MOUSE mode receives real relative
motion in its third and fourth arguments.
- Runtime errors inside callbacks now end the game with a traceback, the way
argument errors always have.
- Held keys no longer auto-repeat in MODE_NORMAL.
- The engine parks the disc on frame 1 before the script runs; the framework
no longer seeks when it is loaded, so threaded games keep their own
startup positioning.
- The pause key now pauses the whole game. The engine freezes the script
(no callbacks, no singeMain), holds sound completions, releases and later
re-presses held inputs, and draws a PAUSED indicator. It acts on the key
press, and SWITCH_PAUSE reaches the script only when the key is disabled
with singeSetPauseKeyEnabled(false). singeSetPauseFlag() still pauses
media without freezing the script. Gamepad and mouse buttons mapped to
pause, quit, screenshot, or grab now work in MODE_FULL too; keyboard
mappings stay raw there.
- Video decoding runs on its own thread per video, so a discSearch() far
from a keyframe no longer stalls the game loop; the previous frame stays
on screen until the new one is ready. The laserdisc and framefile videos
are handed to the GPU as YUV and converted there instead of on the CPU,
and each video reports its keyframe spacing to the program trace when
loaded, with a warning there when seeks may be slow.
- Constants that used to be duplicated in Framework.singe (SWITCH_*,
FONT_QUALITY_*, MODE_*, MOUSE_*, OVERLAY_*, RENDER_*, SOUND_ERROR_*) are
now defined by the engine. New: DISC_STOPPED/DISC_PLAYING/DISC_PAUSED
for discGetState(), SINGE_VERSION_MAJOR/MINOR/STRING, and the SINGE_*
input code layout that Framework.singe builds GAMEPAD_N and MOUSE_N from.
- Audio and video are kept in sync from the audio clock. The engine
measures the audio device's queue at startup instead of guessing, uses
small mixer buffers, and honours a container whose first video frame is
timestamped after its first audio sample. For delay the engine cannot
see (receivers, Bluetooth, DACs) there is singeSetAudioDelay(ms) /
singeGetAudioDelay(), the games.dat key AUDIO_DELAY, and
--audiodelay=MS; positive values mean the audio is heard late.
- The menu has an audio delay calibration screen for the machine's own
delay (DAC, receiver, Bluetooth, display). Press the service key on
the game list; a click plays once a second and the screen flashes.
Adjust with the stick until the flash and the click coincide, then
press button 1 to save. The value is kept in audio.cfg in the data
root and applied to every game on the machine, from the menu or the
command line, on top of any per-game AUDIO_DELAY. Scripts can read and
set it with singeGetAudioCalibration() / singeSetAudioCalibration(),
read the measured device queue with singeGetAudioLatency(), and now
have singeGetTicks() for a wall clock in milliseconds (os.clock() is
processor time and drifts).
Fixes
-----
- controllerGetButton() never worked; it rejected every framework button
code.
- The five argument form of spriteDraw() always failed.
- spriteSetFrame() on a still image crashed.
- Unloading the selected font left later fontPrint() calls using freed
memory.
- overlayCircle() drew around the origin instead of the requested center.
- overlaySetResolution() broke mouse coordinates and vldpGetPixel() because
the overlay scale was computed with integer division.
- mouseGetPosition() always returned 0,0 and controllerGetAxis() read the
wrong controller because the axis cache was indexed two different ways.
- Analog stick release events fired with a stale input code. Controllers
that were unplugged and replugged shifted their codes.
- The -o/--audio option was lost when the configuration was copied.
- --option=value forms of numeric options, and options after the script
name, were not accepted.
- Running "singe game.singe" from the game's own directory wrote its data
to the filesystem root.
- Framefile playback never advanced past the first segment, and switching
segments dropped the selected audio track.
- Video timing accumulated main loop latency, drifting behind the audio.
Audio is now the master clock: the picture follows the samples the sound
device has actually consumed, so the two cannot drift apart and the
mixer's buffering latency is accounted for. Silent videos follow the wall
clock. The first frame after a seek was shown one update late.
- Video without an audio track crashed on the first update.
- The video audio stream was shared with the mixer thread without a lock.
- onSoundCompleted was called from the audio thread. It is now delivered
from the game loop.
- Screenshots read the frame buffer through the window surface, which SDL
forbids alongside a renderer, and could corrupt memory on shutdown.
- .patch archives crashed the installer. Archives without an explicit top
level directory entry were rejected. Extraction now refuses paths that
escape the installation directory.
- The Sinden gun arguments could overflow the configuration structure.
- Support files in the Singe directory are refreshed when the installed
copy differs from the running build. Upgrading the binary used to keep
the old Framework.singe and Menu.singe forever.
- The menu background video is encoded with a keyframe every second, so
the menu's jump to the game list is instant.
- Framefiles whose first line is a relative directory produced garbage
video paths (the directory string was freed before use); a lone "." now
means the framefile's own directory.
- A crash prints a backtrace to the console (Linux and macOS) so a report
can say where it happened; run with --program and send trace.txt too.
- Mouse positions are delivered in the video's coordinates again (SDL3
stopped scaling them for us), so crosshairs follow the pointer.
- os.clock() in scripts now returns wall time rather than processor time.
Nearly every existing game times its input debounces and prompts with
it; once the GPU decodes the video the engine mostly sleeps, and those
timers ran seconds slow. A game that wanted processor time is not
known to exist. This diverges from stock Lua and from other Singe
runtimes; new code that must be portable should use singeGetTicks().
- A key or button still held when a game exits no longer counts as a
press in the script that follows. Confirming Exit in a game with
button 1 used to relaunch it from the menu.
- Audio ran late by the device queue depth on most Linux audio servers:
the clock assumed one mixer buffer of latency where PulseAudio and
PipeWire hold several. See the audio sync entry above.
- Windows builds now carry the icon and version resource, with the version
number encoded correctly.
- The build no longer depends on lyx, upx, or xxd; embedded resources, the
version header, and the manual are generated by CMake. The manual is
embedded again and extracted as Singe/Manual.pdf.
SINGE 2.10
==========
Released March 26th, 2024
New Features
------------
- spriteDraw() now has two more forms. In addition to being able to draw
regular sprites and stretched sprites it can now draw both using the
sprite's center as the anchor instead of the upper left. This is highly
useful when dealing with rotated sprites.
- Animated sprites! Both animated GIF and WEBP images are supported.
- Sprite anti-aliasing, scaling and rotation! Optional separate X & Y scaling.
- Video anti-aliasing, scaling and rotation! Optional separate X & Y scaling.
- Multiple audio track support for videos. New command line options to select
which default audio track you want (-o or --audio). For games with multiple
languages, you can specify AUDIO_TRACK in the games.dat as well.
- New keyboard methods to make handling input easier, especially multiple
keypresses for diagonal movement.
- controllerGetButton() added.
- SINGE_DEAD_ZONE global variable now available based on the DEAD_ZONE
controller configuration option.
- SINGE_FRAMEWORK_VERSION variable added.
- DIR variable added providing directory to the running script.
- All new Lua library handling. Previously Singe "injected" libraries
directly into the script context. Now there is a proper Lua module search
handler. Scripts can properly require() modules from the following:
- Lua Standard Library
- Lua Auxiliary Library
- LuaFileSystem
- LuaSocket
- LuaSec
- LuaRS232
- timerwheel
- binaryheap
- Copas
- json
- New command line option: -p (or --program). This is similar to the
existing -t (or --trace) option. Where "trace" displays and logs script
execution, "program" displays and logs Singe internals. This should make
troubleshooting difficult setups and odd script crashes easier.
- Auto-installer for the new GAME, TOOL, and PATCH archive formats to make
managing games easier.
- ZeroBrane Studio (https://studio.zerobrane.com) integration for live
debugging of running Singe scripts! A full IDE for developing games!
Fixes
-----
- USB controllers now work in games launched from the included menu.
- Default controller DEAD_ZONE increased.
- Framework.singe was missing keyboard mode constants. MODE_NORMAL and
MODE_FULL are now included.
- SINGE 2.00 added two new input events but never had them in the framework.
SWITCH_BUTTON4 and SWITCH_TILT are now available.
- Taking screenshots could sometimes crash Singe.
- PNG files no longer generate warnings on the console.
- Non-VLDP videos now honor command line volume settings.
- Menu system now performs "natural sorting" of game titles instead of brain
dead "computer sorting". It should make a lot more sense paging through
games now.
- Building Singe depended on a lot of undocumented software cobbled together
from other projects. This has been vastly improved and should be usable by
actual humans now. Humans running Linux anyway.
------------------------------------------------------------------------------
SINGE 2.00
==========
Released October 25th, 2020
New Features
------------
- Complete rewrite! No more dependency on Daphne.
- Support for almost every (non-patent encumbered) video and audio format
that can be played by FFMPEG.
- High definition video.
- 32 bit color.
- Additional videos can be played on top the laserdisc video.
- Scaled sprites.
- Graphics overlay resolution no longer dependent on video resolution.
- Analog controllers.
- LuaSocket and LuaFileSystem added to runtime.
- Ability to chain scripts together for menus or launchers.
- Specify if you want gun games to display on-screen crosshairs or not.
- Menu for launching games included.
- Many updates to Framework.singe to support the new APIs.
- New APIs:
- controllerGetAxis
- discGetHeight
- discGetWidth
- fontUnload
- mouseGetPosition
- mouseSetCaptured
- overlayBox
- overlayCircle
- overlayEllipse
- overlayLine
- overlayPlot
- overlaySetResolution
- scriptExecute
- scriptPush
- singeWantsCrosshairs
- soundUnload
- spriteGetHeight
- spriteGetWidth
- spriteUnload
- videoDraw
- videoGetFrame
- videoGetFrameCount
- videoGetHeight
- videoGetVolume
- videoGetWidth
- videoIsPlaying
- videoLoad
- videoPause
- videoPlay
- videoSeek
- videoSetVolume
- videoUnload
------------------------------------------------------------------------------
SINGE 1.14 - 1.19
=================
Released ?
Notes
-----
- Unofficial fan builds.
- Stand-alone releases.
New Features
------------
- New API functions:
- discPauseAtFrame
- mouseEnable
- mouseDisable
- mouseHowMany
- mouseSetMode
- singeDisablePauseKey
- singeEnablePauseKey
- singeGetScriptPath
- singeSetGameName
- soundFullStop
- soundGetVolume
- soundIsPlaying
- soundPause
- soundResume
------------------------------------------------------------------------------
SINGE 1.10 - 1.14
=================
Released ?
Notes
-----
- Unofficial fan builds.
- DLL releases for Daphne.
New Features
------------
- New API functions:
- discGetState
- keyboardGetMode
- keyboardSetMode
- singeGetPauseFlag
- singeSetPauseFlag
- singeQuit
- singeVersion
- soundStop
------------------------------------------------------------------------------
SINGE 1.00
==========
Released 2006
Notes
-----
- Original add-on for Daphne.
- Shipped with the ActionMax "emulator" and games.