Inspector to emulator całej rodziny ZX Spectrum, sukcesywnie rozwijany przez Marka Incleya od 2005 roku - najpierw w wersji 1.x do 2017 (już nie rozwijany) i ponowny powrót do koncepcji emulacji ZX Spectrum w wersji 2.x od 2019 r. Czym może nas zaskoczyć kolejny już emulator "Gumiaczka"? Oprócz, jak zapewnia autor, wiernej emulacji otrzymujemy dobrodziejstwa skryptów LUA, program pozwala tworzyć skrypty dopasowując działanie naszego wirtualnego emeryta do naszych potrzeb, oprócz tego otrzymujemy efektowny podgląd ładowanego pliku - chyba jest to jeden z nielicznych emulatorów, który nie tylko wyświetla podgląd wybranego obrazu (chyba we wszystkich możliwych formatach), ale przy okazji w wypadku programów BASIC podgląd kodu. Od tej wersji program pozwala generować animowane gify z poziomu linii komend a pełna wersja posiada dodatkowo screensaver pozwalający na wyświetlanie rzx w czasie bezczynności komputera;)
Oprócz tego, ten mały kombajnik ma wszystko czym może pochwalić się współczesny emulator - debugger, podgląd zawartości dysku/microdrive/kasety, podgląd wydruku drukarki, możliwość podpinania wirtualnych urządzeń w locie, dość ciekawą funkcjonalność podglądu zawartości "fizycznej" napędu, RZX Studio do kontroli nagrywanego materiału i... specjalną nakładkę pozwalającą na pisanie komend skrótowych (np. nic nie stoi na przeszkodzie aby zdefiniować sobie 10 ? "Tekst", zamiast wpisywać 10 PRINT...).
Czemu nie pisałem o nim wcześniej skoro jest taki fajny i tyle potrafi? Autor gustownie wymykał się moim polowaniom na nowe wersje starych emulatorów:)
Może nie najważniejsza ale całkiem fajna funkcja podglądu - nie tylko ekranu, ale też kodu obrazu dla ZX Spectrum
v2.0.3 - 07.02.2022
Core Changes:
- Implemented two fairly recently discovered Z80 behaviours that are currently doing the rounds:
- The HALT instruction repeatedly reads the byte following the HALT instruction, not the HALT itself while in a halted state. This can make a detectable difference when the memory contention is different for the byte after the HALT. Thanks to ZJoyKiller and Tony Brewer for this information.
- The Z80 now modifies additional flags while executing a block instruction (LDIR, etc.) Thanks to David Banks, ZJoyKiller, Ped7g and Arjun Nair for the information.
- Thanks to Woody, Peter Helcmanovsky and Patrik Rak for their test programs used to verify these changes.
- Added DK'Tronics 3 Channel Sound emulation.
- Added the ability to record animated GIF files. In the GUI there's a new Recordings options page where you can configure the frame rate, optimisations used to keep the GIF sizes to a minimum and whether to include a border. The recording is started using the new Tools->Record Animated GIF menu item. [GIF] appears on the right-hand side of the status bar when a GIF is being recorded.
- This functionality is also available in the CLI tool which makes it very easy to
- produce GIFs of tapes loading or RZXs being played at the command line, e.g.
- incli jetpac.tap --playtape --makegif <- Creates jetpac.gif of the whole tape load
- incli commando.rzx --playrec --makegif <- Creates commando.gif of the whole recording
- NB incli uses the same configuration as the Inkspector GUI, so you may configure the required GIF frame rate, etc, in the GUI on the Recordings options page before running incli. Similarly, you probably want to ensure that flash tape loading is disabled, for example, before creating a .gif from a a tape image otherwise it's not going to be very long or interesting!
- Added ROM and RAM mirroring to the ZX80 and ZX81. This fixes, on the ZX81 at least, Psion's 'Space Raiders and Bomber' behaving as though the movement keys were being held down due to some odd (protection?) code in those games reading memory from $3e80 and acting as though a key was pressed if not getting the expected result from the mirrored ROM access.
- Added ZX81 Chroma 81 emulation.
- Added support for writing ZX80 tape images in .o and .80 formats.
- Added support for writing ZX81 tape images in .p, .81 and .p81 formats.
- Added support for loading from ZX81 .p81 and .tzx (GDB / type 0x19 block) files, including being able to dump BASIC listings directly from these files.
- Add 'Cursor Joystick' support to the ZX80 and ZX81.
- Improvements to the machine state reporting (accessible via the inks.get_machine_state() script function or the GUI's Tools->View Machine State menu item / Alt-A)
- Made some small optimisations to the configuration read and writer.
- The ZX Interface 1 system variables are now available when it's present (including being displayed on the System Variables window).
- Auto-loaded tapes (where LOAD "" is typed in automatically) now play rather than sitting in pause mode when auto start stop tape playback is turned off.
- Added experimental code to detect and exclude BASIC lines that look as though they contain binary data such as machine code rather than a BASIC program. This new feature is on by default, but can be turned off on the Advanced option page if you find it's excluding regular BASIC lines containing many control codes, etc.
- The assembler now has a maximum nested include level of 30 files.
GUI Changes:
- Added a 'View->Show Timestamps' item to the Message window which allows the timestamps to be disabled.
- Breakpoints can now have comments assigned to them, which are displayed when they're hit to help identify them. Thanks to Andy Dansby for the suggestion.
- On the Tape Browser, you can go straight to recording a new tape by pressing the Record button without first having to press Create New Tape.
- Improved the Message window's performance when things get busy (e.g. when noisy diagnostic options are enabled)
- Holding down CTRL while selecting File->Load Last Auto-Save now saves the auto-saved image to %TEMP%auto-save.ext (where ext is the appropriate extension for the machine being saved)
- Added a What's New? item on the Help menu to open up the whatsnew.txt file supplied with Inkspector as of this release (previously this information was buried inside Inkspector 2.txt).
CLI Changes:
- The CLI defaults to the same machine last used by the GUI. This makes it less frustrating when switching between the two. It may still be overriden with the --machine option.
- Added --makegif which records the whole session as an animated .gif. If no filename is given after --makegif, the name of the file loaded is used with a .gif extension.
- Added --playtape which plays the tape until either it comes to the end of the tape and stops, or it remains in pause mode for 5 (emulated, not real time) seconds.
Bug Fixes:
- The "...Show the Microdrive map too" option on the Interface 1 Options page didn't work!
- The Tape Browser window wasn't reopening when 'Automatically reopen active tool windows' was enabled.
- Fixed the log message 'This appears to be a .tzx file with an incorrect extension...' being shown when loading any .tzx file, which was introduced shortly before the 2.0.2 release.
- The screensaver was using the GUI's 'Additional Archive Folders' configuration settings when it should only have been using its own single archive folder setting.
- Snippets run by a breakpoint are no longer allowed to change the current machine. This change fixes a crash that could happen by attempting to do that.
v2.0.2 - 21.12.2021
Core Changes:
- Changed the Spectrum 128's contention start from cycle 14361 (as most documents specify) to 14363. This fixes the centre column of the display on the Shock megademo being out of sync. Thanks to Rich Chandler for both the report and fix!
- Reduced the ZX Spectrum's bottom border height from 56 to 48 lines following a report from Rich Chandler.
- As this is becoming the R.C. release, add Boldfield Joystick Interface emulation for the Jupiter Ace, as per his new SpudACE release :)
- Added DK'Tronics Speech Synthesizer emulation.
- BASIC token expansion, as used by Keyboard Assist, is now disabled when entering quotation marks, and re-enabled at the end of them. The backtick can now be used to change the current state of expansion within a quoted string (previously it was always off).
PRINT "scr." -> PRINT "scr."
PRINT "`scr." -> PRINT "SCREEN$ "
- In addition, the Spectrum's copyright symbol may now be specified with {C} and its pound sign with {UKP}. And this is how they appear in BASIC dumps, too.
- The tape generator now invokes the program using PRINT USR instead of RANDOMIZE USR so that if the program returns, the value of register pair BC will be printed out.
- Tape images whose contents look like .tzx files are now loaded as such, regardless of the actual file extension.
- Enhanced the logging system to capture entries early on in Inkspector's start-up before a means to display them is available.
- Upgraded to SQLite 3.37.0, Boost 1.78, Inno Setup 6.2.0
GUI Changes:
- Added a choice of CAPS and SYM SHIFT key mapping (Options->Keyboard and Joysticks), allowing CAPS SHIFT to be selected with the PC's left shift key and SYM SHIFT with the right shift key. This change also fixes a problem not allowing a '?' to be entered at the BASIC editor as it was previously being consumed by the CTRL-C copy screen shortcut. It now changes to ALT-CTRL-C when the CTRL key mapping is being used.
- Added an option to restore all tool windows on start-up (Options->Start-up and Shut Down).
- The RZX Verifier may be launched directly from the Search window with the currently selected file (File->Verify RZX File).
- The Options->Peripherals screen's Browse file selector now allows multiple snapshots to be selected at once, as requested by Pavero.
- Added a couple of extra escape points in the executor’s thread loop, which reduces - on average - the time taken for it (and therefore the Inkspector GUI) to close down,
- by up to a few milliseconds :)
- When the border size is changed to 'None', the border is no longer rendered internally, as it's not shown anyway!
Bug Fixes:
- Fixed numerous problems with the ROM and RAM drop-down selectors in the debugger.
- The Lua script functions inks.load(), inks.relative_to_script() and the file iterator
- dir() weren't handling UTF-8 characters properly.
- The assembler now guards against runaway macro recursion.
- The DI/Halt breakpoint now works correctly.
- Add a missing error string, which was the reason loading example_128k.s from within %ProgramFiles%InklandInkSpector 2Snapshotss didn't show the actual error even though the tape generation had failed.
v2.0.1 - 28.05.2021
- Core Changes:
- Enhancements to the assembler. See the updated example.s for more details and examples:
- The SAVETAP directive can now save tape images as .tzx and .pzx in addition to .tap. As it's no longer .tap specific, a directive alias called SAVETAPE has been created.
- A TAPEINFO directive has been added to add information to .tzx and .pzx tape images.
- Added an IMPORT SYSVARS directive to import system variable names for the target machine (specified with DEVICE) as labels. Imported labels do not appear in any UNREFS report.
- Added a SETREGISTER directive to initialise a Z80 register to a specific value before snapshots are written out.
- SAVESYMBOLS, SAVELISTING, SAVEBIN and SAVEHEX now default to using <current-filename>.ext if no filename is specified, where ext is .sym, .lst, .bin and .hex respectively.
- Added an ALIGN directive.
- Ignore the block length value reported by a TZX block $2A ("Stop the tape in 48K mode") and always assume it's 0, as other emulators appear to do. This allows the "Amaurote3k+3_zx7rcs.tzx" tape image (and any others there may be with non-zero length values) to load.
- The tape auto-loader now types LOAD ""CODE (i.e. the addition of CODE) if it appears to be a loader that doesn't use the usual "Program:" file type as the first file, e.g. Pheenix
- The Interface 1 shadow ROM is now mirrored at $2000, as per: https://worldofspectrum.org/forums/discussion/34702/
- When dumping BASIC programs, unprintable characters are now shown as nnn rather than ? and UDGs are shown as A, B, etc.
- Added a script that queues up multiple RZX recordings and plays them in sequence. It can be found in Snapshotsluaqueue_recordings.lua
- This was requested by Pavero: https://spectrumcomputing.co.uk/forums/viewtopic.php?p=52625#p52625
- Enable saving of .mlt screenshots for +2A and +3 machines and .sna snapshots for
- Spectrum 128s.
- Improved the source and symbols file functionality (currently used by the GUI's debugger):
- Inkspector assumed SjASMPlus .sym files were produced by its LABELSLIST directive, not its --sym command line option, but this understandably confused people when .sym files weren’t loading, so Inkspector now supports files produced by either method (Inkspector automatically detects).
- The symbols system now automatically imports the current machine's system variables and makes them available in the same way symbols loaded from files are. i.e. the numerous 'Symbol' buttons on Inkspector windows are now always visible to allow selection of them (in addition to any symbol files loaded as before) and system variable names are shown in disassemblies and are highlighted on memory view windows. This feature may be disabled if necessary from the Debugger options page: "Expose the machine's system variables as symbols"
- Symbols and listing files are now loaded when loading tape images in addition to snapshots.
- Added support for loading .sym and .lst files from within a .zip file if the snapshot or tape file is itself in a .zip.
- Other general improvements including faster loading of source and symbol files and better cache handling.
- Upgraded to Lua 5.4.3, SQLite 3.35.5
- Made numerous small improvements to the performance of the core emulation code that together reduce the CLI's unthrottled playback time of my benchmark .rzx file from 15 to 13 seconds. Every little helps!
GUI Changes:
- Added two display render methods selectable on the new Display options page: GDI+ and Direct 2D. Both offer smoothed displays but the Direct 2D is hardware accelerated, so is probably the better option, unless for some reason the Direct 2D option doesn't work on your system (the only reason GDI+ is supported, as it's slow).
- Added an Inkspector Search window (shortcut Alt+S) that quickly searches through your snapshot archive as configured in the new Options->Archives page, for files that match what is typed into the search bar. Double click a file or press the toolbar load button to load one. Holding down the CTRL key as you do so also closes the search window. File extensions may be filtered by entering "ext:<extension>[,extension]" e.g. "manic ext:szx" to find all supported files containing the word "manic" with a file extension of szx, or "manic ext:szx,sna" to find ones with extensions of szx or sna.
- Added a calculator window (shortcut Alt+C) which uses the debugger's expression evaluator, giving you access to all available symbols.
- Added View->Block Data to the Tape Browser window to see the first 20 bytes of each block.
- Added a View->Additional Information to the Tape Browser which displays additional information available for some types of tape block (e.g. TZX Archive Info).
- "..." is shown at the end of lines when additional information is available.
- Added File->Load Memory to load a file directly into a machine's memory.
- File->Save Screenshot now supports saving images as .gif in addition to .png and .bmp.
- The View System Variables window remembers the last variable selected and auto-selects it on subsequent openings.
- Added a "Start Up" menu item and button to the Snippet Editor to quickly select the current snippet for running at start up, saving a trip to the Options->Startup and Shutdown page.
- The following keys are now mapped on all systems where available:, . / ; ' # - =
- The debugger can now show elapsed T-state counts at the start or end of an instruction.
- Added an option to the Debugger options page to show a message on the emulator window when a breakpoint is hit.
- Holding down the CTRL key while selecting any "Recent->" menu item copies the path to the clipboard instead of selecting it.
- Added ZX80 and ZX81 support to the Tools->View User Variables menu item and
- inks.expand_user_variables() script function.
- Changing settings in the Options screen relevant to the currently running machine now prompts the user to reset the machine for the changes to take effect.
- Made the following audio improvements:
- Added the ability to individually control the volumes of different audio devices.
- Reduced the audio latency.
- Corrected some audio clipping.
- Improved the performance of the message window by batching updates.
- Upgraded from wxWidgets 3.0.5 to 3.1.5 which does not suffer from the same issues as 3.1.3 (that the attempted upgrade in Inkspector 2.0.0.28 revealed).
- Numerous tweaks and changes throughout.
CLI Changes:
- Added --tapelist to list any loaded tape blocks
- Added --state to display the full machine state
- --play now shows the time taken to play the recording
Bug Fixes:
- Fixed the cassette player's auto-stop/start not pausing the tape when the EAR port is read by something previously determined not to be a tape loader, such as the ROM's keyboard reader. This fixes horizons.tap failing to load 'logo'screen$ (when flashloading is off) due to the PAUSE 250 immediately before the LOAD command, allowingthe tape to continue playing during the PAUSE and resulting in missing the 'logo' header.
- Fixed the handling of TZX select blocks, which was treating the choice block offsets as absolute values and not relative offsets to the current tape block.
- The ZX Interface 2 was not being allowed to attach to a Spectrum 128 (only 16/48K) which in turn caused a crash when attempting to load Domin8tr1s. Both issues have
- been fixed.
- Spectrum 128s onwards were always displaying RAM page 5 when the disabled bit ofport $7FFD was set, rather than using the display bit to decide as usual. This issue was also highlighted by Domin8tr1s!
- Fixed the debugger's single-step not executing an instruction if an interrupt was due.
- Thanks to djnzx48 for the report.
- Fixed a crash that could occur when single-stepping RZX recordings containing
- retriggered interrupts (e.g. boulderdash.rzx).
- Fixed several issues with "Symbol" selection buttons and menu items not being visible or enabled correctly.
- Fixed the flickering on the View System Variables window, caused by the rolling back
- to the earlier version of wxWidgets in 2.0.0.51.
- Changing the "Display values in hexadecimal" option on the debugger options page would not take effect on the Z80 Registers window immediately.
- Fixed a crash when passing the name of a .dsk or .mdr file on the GUI's command line.
- Fixed an issue with the Snippet code window loading non-ASCII characters incorrectly.
- Fixed the Machine->Hot Peripheral Patching->Cheetah SpecDrum menu item which did nothing! :)
- Fixed numerous display issues with filenames containing non-ASCII characters.
- Fixed the "Recent->" lists on the tool windows (e.g. Tape Browser) not being populated after being closed and re-opened.
- View User Variables now displays unprintable characters correctly, allowing all of Wudang's variables to be seen!
- Fixed the screensaver showing the bouncing "No valid scripts available!" message after playing back an .rzx recording that fails to play to completion.
- The assembler was writing incorrect values for local labels in symbol files (it was actually writing the value of the parent label)
v2.0.0.51 - 02.06.2020
Common (GUI and CLI) Changes:
GUI Changes:
- Added a Help->Send An Email menu item that launches your default email app to send an email with the To and Subject lines pre-populated.
Bug Fixes:
- Reverted from wxWidgets 3.1.3 back to 3.0.5 which fixes the following:
- The file preview display was being scaled incorrectly on high DPI systems
- The debugger's peek disassembly tooltip window was generating unnecessary focus changes
- Game controller inputs weren't coming through
- inks.load_from_archive() was not returning the result code.
v2.0.0.50 - 28.05.2020
Common (GUI and CLI) Changes:
- ZX Spectrum +2A and +3 floating bus behaviour is now emulated.
- ZX80 and ZX81 tape images (.o, .80, .p and .81 files) are now handled as tape images
- rather than snapshots.
- Added BASIC listing dump support to the ZX80 and ZX81 and its tapes.
- Improved the spacing accuracy of BASIC listings
- Added more Lua inks.xxx() functions (these will be documented separately and soon!)
- Added a backtick (`) as a way to toggle token expansion and and off in key assist
- Added inks.get_recent(itemNum,[itemType]) to retrieve a file name from one of the recent
- items. 0 is the most recent, 1 the next, and so one. itemtype is one of the following
- strings: "snapshot" (the default), "tape", "script", "mdrv", "poke", "roll", "disk" or "source".
GUI Changes:
- Added native cursor key support to the Jupiter Ace, ZX80 and ZX81.
- Added Key Assist support to the Jupiter Ace, ZX80 and ZX81.
- Add a System Variables window (Tools->View System Variables) that shows system variables and their current values, which are updated automatically once a second.
- The system variable constants for the current machine are now available everywhere where an expression may be entered.
- Improved the full-screen view (it previously had small part of the display cropped when viewing
- with no border)
- Added a toolbar to the main and message windows.
- Added a Tools->Stop Script menu item that may be used to stop long-running scripts.
- Added a View->Raise Windows menu item and toolbar button to raise all open Inkspector
- windows to the top.
- Addded a Tools->View User Variables menu item, and exposed it via inks.expand_user_variables().
- Currently this works for ZX Spectrums only.
Bug Fixes:
- Fixed an issue displaying negative integers in the ZX81/Spectrum 5-byte number format.
- Modifying memory at the currently selected address using one of the right-button menu items
- (increment, decrement, poke, assemble) would not update the value at that address afterwards.
- Fixed the "Open disk control panel when a disk is accessed" option not working.
2.0.0.28 (Beta 1) - 12.05.2020
Common (GUI and CLI) Changes:
- The scripting framework has been re-written, with Lua being upgraded from 5.2 to the current 5.4 release candidate in the process.
- Inkspector now defines ten "snippets" which are Lua scripts, edited using the GUI's new Snippet Editor, and that may be run the following ways:
- Directly from within the Snippet Editor (Snippets->Edit Snippets)
- From the Snippets menu (shortcut keys Alt-1, Alt-2, etc.)
- By selecting one to be run on startup of Inkspector (Options->Startup)
- By selecting one to be run on a breakpoint hit within the debugger
- By using the CLI's --snippet option
- A few snippets are pre-defined as examples.
- Improved Currah uSpeech emulation in respect to ROM mirroring and blocking out the standard ROM when its own ROM is paged in. Intonation is now emulated too.
- Speech subtitling (Currah uSpeech and Fuller Orator) will automatically pauseif the same allophone is played 10 times in succession, automatically resuming when a different allophone is played. This is to avoid the message window being flooded with "PA1" as the uSpeech ROM plays it incessantly.
- Added support for reading and writing .snx snapshots.
- Added support for reading and writing .mlt screen images.
- Added support for the Cheetah SpecDrum.
- InkSpector now has its own built-in macro assembler. It will attempt to assemble files that have either a .s or .asm extension. Two sample files, example.s and example_128k.s are supplied in the Snapshotss folder that also serve as the assembler's documentation for now. The GUI can optionally load .s and .asm files for the file preview window too, but it is disabled by default. You may enable it on the "General" options page.
- To assemble using the CLI use the usual load file method: incli --load example.s
- The assembler also includes a .tap file generator that can automatically create a full .tap image (with optional loading screen) from the assembled output, including loading of 128K RAM pages.
- Emulation is paused and a message displayed should the Z80 execute 64K's worth of contiguous DD/FD opcode prefixes.
- The emulator core used by the GUI, CLI and the screensaver now uses UTF-8 exclusively for messages and file paths internally. The only visible change is more consistent Unicode support throughout Inkspector.
- Many other minor tweaks and improvements.
GUI Changes:
- Added a snippet editor.
- On the General options page, a snippet may be selected to be run at start-up.
- The numerous placeholder toolbar button icons have been replaced with proper ones.
- Added support for physical joysticks.
- Added a navigation drop-down menu to the Navigate Backward debugger toolbar button.
- Added a Load Most Recent Tape Image (Shift-F9) and Load Most Recent Source File (Ctrl-F9) menu items.
- The message window now uses a fixed pitch font to make it more readable.
- Tape browser window updates (particularly block % updates) are now more efficient. You may only notice this change on tape images containing thousands of small blocks, such as Rescate Atlantida.tzx
- The tape browser's File->Open menu item has been wired up.
- Added Tools->View In-Memory BASIC Program to the main window and Tools->View BASIC Program on the Tape Browser window which displays in the message window any BASIC programs present.
- The Tape Browser window can save out an individual tape block (Tools->Save Individual Tape Block). This currently works only for .tap blocks.
- Added an 'Advanced' page to Options, containing a 'show additional messages' option. This may be enabled to help diagnose issues with snapshots as it causes additional information about them to be displayed, mainly on the messages window, but also some of it on the file load/save preview window. Also added fine-grained diagnostic options that may produce a lot of information, so a warning is shown when Inkspector is started when one or more of them are enabled.
- The Key Assist dialog is disabled when an RZX recording is playing.
- Key Assist now also supports the Prototype ZX Spectrum ROM: http://www.computinghistory.org.uk/det/51620/Sinclair-ZX-Spectrum-Prototype
- The debugger breakpoint 'Comment' field has been replaced with 'Run Snippet' where you can now select one of the ten snippets to run when a breakpoint is hit. A new 'Never break' option has been added to the 'Break When...' drop-down list to allow the Lua commands to be executed without pausing execution and launching the debugger in the process.
- Once I've documented the Lua extensions, snippets will make sense :)
- Upgraded from wxWidgets 3.0.5 to 3.1.3
- Unfortunately this upgrade has also introduced a regression which causes the debugger peek disassembly tooltip to steal window focus when it appears, which manifests as the debugger's main window frame changing colour as focus changes. Hopefully this will be fixed in 3.1.4.
CLI Changes:
- Added a --dumpbasic option which will list a BASIC program stored within a snapshot or one or more tape image blocks.
Bug Fixes:
- A couple of tape block types (including PZX's PULS block) always showed 0% progress on the tape browser window.
- Fixed a problem with drag and dropping a .pok file onto the GUI that could cause an unhandled exeption to be reported.
- Fixed a crash that could occur when loading an .szx snapshot (including ones embedded within .rzx recordings) that references a tape image containing a drive letter than doesn't exist on the local machine. Thanks to Woody for unwittingly supplying an offending .rzx file!
- Fixed an issue with loading a snapshot with the debugger open, which could sometimes allow the machine to execute for a very short period before showing the first line of disassembly.
- Removed a harmless duplicate "Fuller Box present" message on the file preview dialog.
- Key Assist didn't work correctly when the Currah uSpeech unit was attached.
- Fixed the occasional allophone being dropped when the uSpeech or Orator were talking and the code wasn't querying the ready status before sending the allophone. This was most prominent at the start of Jungle Fever which proudly announced "Welcome to Jung Fever".
- The Spectrum's issue2/issue3 configuration setting wasn't being applied.
- Z80 opcode ed71 is now disassembled correctly as 'out (c),0' instead of 'out (c),f'
- The disassembler was skipping too many bytes following an undocumented instruction.
- Port writes to the 128K AY chip were being consumed even when the AY chip wasn't present (i.e. 48K machines) which manifested as flickering in the FPGA48all.tap tester as it eventually writes to port $8004! Thanks to azesmbog for reporting this. Similarly, reading the AY port when it wasn't present was returning $FF instead of reading the floating bus, which prevented 'Lord Bromley's Estate' from working.
- Fixed an issue with interrupt handling that caused minfo.tap ("INT time") and Woody's nointpfx.tap to fail.
- The 128K Spectrum was only holding the INT line low for 32 t-states, not 36. Thanks to Woody for diagnosing and reporting this! :)
- Improvements to accelerated tape loading compatibility.
- Fixed an issue that could allow AY chip tone counters to runaway, which resulted in some channels not sounding for a while. E.g. loading "Batman - The Movie.rzx" would result in the instruments appearing one by one when it first started to play the music on the menu. Thanks to Woody for the report.
- Fixed the Z80 snapshot reader wanting to select a Pentagon 128 for any unrecognised machine type, or machine type #3 when in a version 3 image (should be Spectrum 48K). This would result in a Spectrum 128 being selected, as the Pentagon isn't emulated.
- When the GUI's menu was active the machine was still running.
2.0.0.27 - First preview version - 13th October 2019
- InkSpector has been re-written from the ground up and is now called Inkspector 2. It is a separate program to Inkspector (1.0) and both may be installed on the same machine without conflicts.
- The GUI version is now the main focus of development, with another new program 'incli' which is a command line headless version of the emulator that may be used to convert between snapshot formats, disassemble directly from snapshots, display snapshot and tape information, etc.
→ NOWSZY [ZX] Inkspector 2.0.5 13/04/2022
InkSpector 2.0.5 - 13.04.2023
Core Changes:
- The assembler can now produce .pok files directly using the new SAVEPOK and POKTRAINER directives. For example, assembling:
SAVEPOK "test.pok"
POKTRAINER "Trainer One"
ORG 0x8052
jp 0xB701
ORG 0xB701
ret
POKTRAINER "Trainer Two"
ORG 0xC000
ld a,ixl
ret
...will product a file called test.pok that looks like this:
NTrainer One
M 8 32850 195 0
M 8 32851 1 0
M 8 32852 183 0
Z 8 46849 201 0
NTrainer Two
M 8 49152 221 0
M 8 49153 125 0
Z 8 49154 201 0
Y
- To fully demonstrate this new feature, I've included make_oink128.s in the Snapshotss folder. This patches the original 48K Oink! release which was an annoying tape-multi load, into a everso-slightly-less-annoying 128k version that loads all the sub-games into RAM at once.
- Adding or removing most peripherals no longer requires the machine to be hard-reset.
- Added support for the Kempston '55' Joystick Interface, which is read using port 55 (A7=A6=A3 = 0).
- Added support for the Lex Van AY board for the Jupiter ACE, that appeared in ACE User 4 in 1983.
- Added the ability to breakpoint on a NMI being taken.
- Breakpoints with conditions that hit now additionally show the values of any symbols that took part in the condition. e.g. a breakpoint with a condition of "@addr<50000" might additionally show "@addr=49999".
CLI Changes:
- The --script option has been split into two: --prescript to run a Lua command before any specified file has been loaded, and --postscript to run afterwards.
- --tapelist now shows any additional information for a block, just as the GUI's Tape Browser does with view Additional Block Data enabled.
- Added --listdirectives to list the assembler's directives
- Added a --quiet option to turn off information log and user messages (warnings, errors and successes are always shown), enabling a cleaner output when used with --tapelist for example.
GUI Changes:
- Added the ability to configure the physical keyboard and joysticks as redefinable keys, using the name "COMCON" (as suggested by Luzie) as a big-up to the programmable joystick interface from back in the day.
- In addition, the COMCON settings are saved against a profile, so you can create different profiles for different games and select them as you need without having to create them from scratch each time. Each profile contains separate settings for the physical keyboard and controllers, so if you happen to use two controllers they can have different redefined keys assigned to them, too.
- Wait, there's more! Profiles can also be made to activate automatically for specific files, just as peripherals can be made to attach to them, so you could create a Mayhem profile and have it so it's selected whenever you load mayhem.szx. Not that you'd want to play Mayhem, but you get the gist. The automatic profiles are selected on the Peripherals options page.
- Added an option to the debugger to display all video writes immediately on a breakpoint being hit (including single stepping, etc.) even if they've been made behind the TV's beam. This is useful for debugging code that writes to the display behind the beam to avoid flicker. Or maybe you'd just like to see how Uridium updates the screen?
- Added an option to the Options->General page to temporarily set the machine to unthrottled (i.e. maximum speed) when spooling, restoring the original speed when spooling has finished or has been cancelled.
- Added graphical indicators to the debugger and memory windows for Memory Read (cyan), Memory write (yellow), Memory read/write (green) breakpoints, in addition to the existing red ones for Opcode Read.
- Added a Lua bar to the messages window to allow you directly enter a Lua command, which can be useful for entering the odd script command rather than having to edit then run a snippet to do so. You can hide this new bar by selecting View -> Lua Bar.
- Added two new default snippets: Snippet #7 and #8 to reduce and increase respectively the speed of emulation. Existing installations of Inkspector can access these by resetting the snippets to the defaults (Snippets->Edit Snippets->Edit->Reset Snippets).
- The Machine->Hot Peripheral Patching sub-menu has been re-worked to show only peripherals compatible with the current machine as it was becoming too long
- The absence of the D3DX9_43.DLL file (needed only by the screensaver) on the user's system no longer prevents the installer from proceeding.
- Greatly reduced the CPU usage when a physical controller is plugged in.
Bug Fixes:
- The debugger was not picking up on source symbol notification changes, meaning Refresh had to be manually selected after pressing its View Symbols or Source Listing toolbar buttons for them to take effect. This was broken in 2.0.4.
- Several controller issues that have just gone away as a result of re-writing the controller code for the COMCON keyboard and joystick support. For example, a long-standing issue with the physical controllers not working with keyboard-based joysticks (native cursor, AGF, Interface 2, etc.) has gone.
- Fixed an issue where the progress % value on the Tape Browser's status bar for some less common block types would remain at 0%.
- Fixed the maskable interrupt breakpoints not working.
- Fixed 'Find Memory' not always updating the debugger's disassemble window's address correctly when crossing RAM page boundaries on the 16k/48k Spectrums when repeatedly pressing Find Next.
- Fixed nested IFs not always working correctly in the assembler.
- Fixed a crash that could occur in the assembler when specifying a zero byte instruction (e.g. DS 0) at address 65535.
- Unlike all the Sinclair models, the Jupiter ACE's cursor up key is Shift-6 (not Shift-7) and down is Shift-7 (not Shift-6), so I've corrected the cursor key mappings accordingly.
- Fixed a fairly rare dropping of spooled characters on the ZX81.
- Fixed some options on the GUI's ROM Management options page that should have taken effect immediately rather than after restarting Inkspector.
- Fixed some minor text colour issues on the debugger window when the emulator was running and opcodes were not being shown.
- Fixed the screensaver that was properly broken in 2.0.4 and crashed immediately when it ran :D I guess there's not too many people using the screensaver as I didn't hear anyone complaining :D It might be time to retire it...
- Restored the screensaver’s ability to remember the chosen allow-Spectrum-to-be-played-hotkey (default F1) on its configuration screen. It appears the relevent code was commented out early on in InkSpector 2.0 development!
→ NOWSZY [ZX] Inkspector 2.0.4 31/12/2022
v2.0.4 - 31.12.2022
Core Changes:
- Added a feature called Spooling that types in the contents of the clipboard or an ASCII text file into the current machine. This works for all emulated machines and is accessible via the GUI's new Tools->Spool Clipboard and Spool File menu items or from script using inks.spool(path). Lines starting with # are ignored.
- Key Assist (which also powers the new Spooling feature) now automatically regulates the typing speed to avoid keypresses getting dropped as the edited line becomes longer and the emulated system takes longer to update and redraw it.
- Added ZX80 (.o, .80) and ZX81 (.p, .81, .p81) tape loader generation support to the assembler. There is also a new directive DEFNM - Define Native Message - that converts from ASCII to the target machine's character set to help make life a little easier. See snapshotssexample_zx80.s and example_zx81.s for details.
- The data bus value used by the Jupiter ACE when calculating the IM2 interrupt vector has changed from $FF to $20 as per the original hardware. The original valkyr.tap game (in addition to the version modified for emulators) now plays fine rather than crashing when the game starts.
- Added .tap load (including auto-load) and save support for the Jupiter ACE.
- Added emulation of the Big Mouth speech board designed by Martyn Davis for the Jupiter ACE.
- Added ZX 128 AY sound chip emulation for the Jupiter ACE, primarily so I can hear the music in the Old School Demo :)
- Add 'Cursor Joystick' support to the Jupiter ACE.
- Pressing TAB on the ZX81 with the keyboard in 'Native Cursor Keys' mode toggles [F]unction mode (as it already does [E] mode on the Spectrum).
- Improved the dumping of BASIC program lines that report themselves as 0-length (usually as a form of protection), such as the one in Quazatron's loader.
- Added an option to only show the hidden floating point value of a number in a BASIC line if it differs from the text version that precedes it (i.e. when it appears an attempt to hide the true value has been made). For example, the line of BASIC in Quazatron's loader reads:
- 0<<< 0-length line >>> CLEAR 00000[25000]: POKE 00000[23659],0: LOAD ""CODE: RANDOMIZE USR EXP 00.000000[10.435528]
- Note that POKE's second argument really is zero, so no actual value is shown in square brackets.
- Improved the heuristic that determines whether a line of BASIC is machine code or not to reduce the number of false positives, although it's still not perfect.
- Added system variables for the +2A and +3 Spectrums.
- Screenshot files (.scr and .mlt) are now classed as screenshots and no longer as snapshots. The most visible effect of this change is a new Recent Screenshots item on the GUI's File menu, and machine state is no longer dumped out (if so configured) after loading one.
- Added support for loading ZX32's .zxs snapshot files, including any embedded tape and disk images.
- Added textual bitwise operators to Inkspector's expression evaluator (i.e. in the debugger, calculator, and anywhere where values may be entered as text) and assembler to complement the existing C-style ones:
- NOT (^), AND (&), OR (|) and XOR (^)
- Added a dereference operator * to the debugger's expression evaluator (not available in the assembler, but everywhere else) that evaluates to the 16-bit address pointed to by the argument. For example, while running a Spectrum:
- CHARS evaluates to $5C36
*CHARS or *$5c36 evaluates to $3C00
(i.e. the address CHARS is pointing to)
Put another way, it's equivalent to
PEEK() + 256 * PEEK(+1)
- Added a TAPELOADEREXEC directive to the assembler that specifies the BASIC line used to start the assembled program in the generated tape loader (i.e. whether to use PRINT USR, RANDOMISE USR or LET R=USR). See example.s for details.
- The assembler's SAVESNA (and SAVESNAP alias) and SAVETAP directives now behave as per SjASMPlus as not to make it unnecessarily difficult to switch between it and the Inkspector assembler. i.e. the optional second argument specifies the start address of the program. If this is not specified, the value specified by the END directive is used. See the updated example.s for more details.
- Added batch_scr_to_gif.lua and batch_z80_to_szx.lua script files to the Snapshotslua folder to demonstrate how to generate .gif screenshots from a folder full of snapshots and/or .scr and .mlt files, and convert a folder of .z80 snapshots to .szx files, respectively.
- Added the ability for the CLI and GUI to additionally send log messages to the Inkspector database's log table. The GUI additionally can clear them or export them to a text file. As a result, the screensaver no longer writes its messages to that table (not that anyone knew it did!), but it does keep its own option to write messages to a .txt file should screensaver logging be required (I doubt it!). This addition is really to help with troubleshooting and isn't expected to be particularly exciting for anyone :)
- Changed the Fuller Box AY clock speed to 1.63819 MHz as per https://spectrumcomputing.co.uk/forums/viewtopic.php?p=91917#p91917
- Further hardening of some file loaders against malformed files following some ramping up of the fuzz testing done prior to a release.
- When writing out a .szx file containing a ZX Interface 1 block, the final byte of the ZXSTIF1 structure (chRomData[1]) is now omitted if there's no custom IF1 ROM present, resulting in a 40 byte block. This is to appease Fuse, which, as of 1.6.0 at least, appears to assume ZXSTIF1 is 40 bytes long in such cases (ignoring the length in ZXSTBLOCK reporting 41), which prevents it from loading such files. Spectaculator 8.0 also saves 40 byte ZXSTIF1 blocks when there's no custom IF1 ROM (although it does load the 41 byte versions fine), so this seems a reasonable change to make.
- When loading a tape image that requires LOAD ""CODE (and not LOAD "") into a 16K Spectrum with flash loading and auto loading enabled, a PAUSE 1 command is issued first. This kludge is to allow Pheenix to load successfully and not fall foul of its protection, which loads the value $1142 into FRAMES from the final block of the tape, then on start of the program it adds the value $EEBE to (FRAMES) and if the result is not zero, it assumes someone's been poking around and displays the screen wipe with the purple asterisks before resetting the machine. Previously on Inkspector, Pheenix always ended up with the value 1 in this specific scenario after adding those two values together, indicating FRAMES had been incremented between BASIC loading the final code block and launching the machine code program at 30105 (not 30121 as it would appear at first glance ;) Incidentally if you do start the program at 30121 you get the same result as if the FRAMES protection check had failed). The PAUSE 1 is used to sync the system as it uses a HALT to achieve the delay, which hopefully buys the system time (or at least puts it out of sync with an interrupt occurring), so FRAMES is not incremented before the protection check is performed. That's enough about Pheenix for today.
- Added a breakpoint ROM/RAM page type of 'Any' which makes it a little easier to set up conditional breakpoints (particularly breaking on a read/write address range). Along with the rest of Inkspector, this is all being documented fully, but in the meantime this is an example how to set up a breakpoint on a memory write between addresses 52000 and 52100 using the GUI's "Add Breakpoint" menu items on the main or debugger windows:
- Breakpoint Type: Memory Write
- Address: 0 (this value doesn't actually matter when address mask is 0)
- Address Mask: 0 (so that all addresses are considered)
- ROM/RAM Pages: Any
- Condition: @addr >= 5200 && @addr <= 52100
- Additionally you can set Condition breakpoints that break whenever the specified condition becomes true, e.g. to break when HL becomes 49153:
- Breakpoint Type: Condition
- Condition: hl==49153
- Made further optimisations when Inkspector saves out the configuration.
- A fair bit of the usual tinkering throughout.
CLI Changes:
- Added --savegif that saves out a single frame (non-animated) .gif file from the current state of the machine, e.g.
- incli jsw.z80 --savegif <- Creates jsw.gif from the snapshot
- Added --listconstants that lists all the Inkspector scripting constants.
GUI Changes:
- Added an option to specify the start-up machine. As with other configuration options, this is used by the CLI too.
- Added an option on the Tapes options page to specify the machine to be used for loading Spectrum tape images.
- The memory view window now allows the display to be updated while the machine is running (View->Update While Running), which makes the highlighted changed (tracked) bytes display much more useful. Also added menu items to clear changed bytes after 5 seconds and one to clear them all on demand.
- You can now create a breakpoint directly from the Tools->Add Breakpoint menu, (i.e. without having to open the debugger first). The debugger will open automatically when a breakpoint's hit.
- When viewing a system variable in a memory tab (View->System Variables->View->View In Memory Tab), if the variable is a pointer to an address, such as CHARS, the address used for the memory tab uses the new dereference operator (see above in Core Changes) unless CTRL is held down while clicking on the View In Memory menu item, in which case the address of the variable itself is used, as in previous versions.
- Added the ability to show BASIC runtime errors as meaningful pop-up messages on the ZX80 and ZX81, individually configurable on the ZX80,ZX81, Jupiter ACE options page.
- Performing "view BASIC Program" when the Jupiter ACE is running shows all the currently defined Forth words, similar to how its own VLIST command does, except words are grouped into whether they're defined in ROM or RAM.
- The debugger's View->View Symbols and View Source Code are now always enabled, regardless of the actual availability of such things. This makes it easier to use these features and fixes an issue where if the current ROM (e.g. 48K) does not have symbols or source available for it and the debugger is then switched, for example, to the Interface 1 and it does have such things available, the menu items would have remained disabled.
- The debugger's Add Breakpoint (CTRL-B) has been renamed "Add Breakpoint At Cursor" and its shortcut changed to CTRL-SHIFT-B. Add Breakpoint (CTRL-B) now adds a new breakpoint unassociated with the address at the cursor, making it equivalent to Add Breakpoint on the main window's Tools menu. This change also makes it slightly easier setting up more complicated breakpoints (see "Added a breakpoint ROM/RAM page type of 'Any'" in the core changes above).
- Added "Break On Branch" and "Break On No Branch" breakpoints to the debugger's Debug menu, which work on instructions that conditionally branch, such as djnz, ret z, jr c, etc.
- Added debugger menu items to enable or disable all breakpoints.
- The debugger's list of breakpoints now displays breakpoint comments too.
- Added an option to generate an NMI (Machine->Generate an NMI)
- Performing a Copy on the messages window now copies all text if none is selected.
- The Z80 Registers window is now a regular tools window and no longer opened and closed by the debugger. It's opened from the main window's View menu (shortcut Alt-F). Added a Refresh (F5) menu command to refresh the values of the registers while the machine is running.
- Added a Tools->Assemble Clipboard Contents that assembles the text contents of the clipboard to the current machine. Unlike loading a .s or .asm file, the current machine's memory is not cleared before assembling over the top, so it may be useful for applying patches to games.
- Added a 'View->Show Headers' item to the Message window which allows the log line headers which show which bit of Inkspector code generated it (e.g. [MACH]) to be hidden. This can be useful when wishing to copy and paste the output of one of Inkspector's tools without timestamps (which may already be hidden) or headers getting in the way.
- Added options to the Advanced page to show the Inkspector version number and manifest version on the main window's title bar.
- Added --machine and --script command line options to match the CLI.
- Drastically reduced the time take to shutdown the GUI when the current machine has a large tape image loaded (e.g. a .wav file) and the shut down option to save the current machine state is enabled.
- Simplified the snippet editor colours by making all Lua and Inkspector function names blue, with Inkspector constants in blue italics.
- Added two new default snippets: Snippet #5 to toggle the global hex/decimal mode, and snippet #6 that demonstrates use of the in-line assembler. Existing installations of Inkspector can access these by resetting the snippets to the defaults (Snippets->Edit Snippets-> Edit->Reset Snippets).
- Improved the handling of 'secret' filenames on the Microdrive Map and Microdrive Sector windows.
- Re-written the code that captures window sizes, positions and states (such as being maximised) to work more reliably.
Bug Fixes:
- When recording an RZX, the post-EI scenario (where normally a maskable interrupt wouldn't be taken, so the RZX frame is extended) is handled more reliably, and should fix an issue where the resulting recordings could lose sync at that point. After writing some test programs to assist fixing this, I discovered that all I needed to do to generate a post-EI frame was hold down DELETE in the 128k Spectrum's BASIC editor on an empty line until it repeatedly beeps.
- Fixed a long-standing issue when saving a .z80 snapshot when writing compressed versions of them. It was not honouring the rule about the first byte immediately following a single ED not taking part in a run. For example ED, 00 x 7 was being encoded as ED ED ED 07 00 and not ED 00 ED ED 06 00.
- Fixed an off-by-one error that could prevent the last few bytes of some Jupiter ACE .ace files from loading.
- The ETI Colourboard (Jupiter ACE) wasn't working correctly. The contrived test mode I had made it appear it was working. I have now verified it with the demo program supplied with the original ETI project.
- Fixed a problem with the assembler trying to apply indirect addressing to non-Z80 instructions such as DB, DW, preventing such lines as 'DB (10+2)*2' from assembling.
- Fixed an issue with the assembler sometimes showing the wrong filename if it fails to resolve a forward reference.
- Fixed a crash if the MACRO and STRUCT directives were used without adding the name parameter.
- Fixed Key Assist typing TAB and _ incorrectly on the Spectrum, and / RND INKEY$ and PI on the ZX81.
- On the Spectrum, Key Assist now re-enables keywords after a colon in REM statements just as the BASIC editor does. e.g. REM: DEF FN a()=10
- The ZX80 Keyboard Assist code that was supposed to dismiss any "0/-2" style report message that may be active before inserting the requested key presses was not working properly.
- Added a workaround so that key assist on the ZX80 works immediately after a LOAD command. Previously it required a BASIC variable to be added or removed before it would work again. This was so the end of variables marker byte $80 was once again locatable via the E_LINE system variable - 1. Key Assist looks for its presence to verify the system is up and running.
- The detection of whether LOAD "" or LOAD ""CODE should be used to auto load a tape image could get the wrong result if there was a mix of TZX standard and turbo blocks present in the file. Thanks to TheShich for the report.
- Fixed an issue that prevented tapes requiring LOAD ""CODE from loading automatically on 128s and later (the code to navigate their system menus broke a couple of versions ago!).
- The Fuller Box joystick emulation was using active-high bits, not low. One reason (OK, excuse!) this went unnoticed for so long was that Imagine's Fuller joystick reading code (certainly in Arcadia and Zzoom) was correcting Inkspector's bug! :)
- From Arcadia:
ld bc,127
in a,(c) ; Read the Fuller Box's joystick
bit 4,a ; Inkspector 2.0.3 and earlier return bit4 low
jr z,.active-high ; Looks like active-high - no need to flip the bits
- xor 255 ; Flip the bits, making active-high
; (we'll forgive them not using CPL here)
- ; This is the path taken with Inkspector 2.0.4
- .active-high:
- Fixed an issue in the floating bus emulation where the calculation to determine which bit of the display was being read by the ULA went a little awry when the beam was in the lower parts of the screen. This was the reason the Ah Diddums! bear didn't have the bout of St. Vitus' dance he should have had when the Fuller Box, which steadies him, is absent.
- Fixed some system variables having incorrect details.
- When (the very slow) GDI+ render method was being used, the status bar updates could become intermittent.
- Restored the GUI's Tools->Stop Script functionality that was broken in 2.0.3.
- Fixed the debugger's breakpoint list not being rebuilt until the machine was paused, which could give the impression that breakpoints weren't being saved and restored correctly when switching between different machine types. Of all the text boxes on the Z80 registers window, only the PC box was being applied to the Z80 on pressing ENTER!
- Fixed a crash that could occur when loading a TZX file containing a nested loop (ironically, due to attempting to display some helpful information when encountering one).
- Fixed the superfluous spaces that were being inserted around some tokens when running View BASIC Program on the ZX80 and ZX81.
- Fixed a bug when determining the most common colour being displayed (the .scr and .mlt loaders set the border colour to it to complement the display) as it was only sampling the first 8 pixel lines of each third of the display memory, although this did seem to work pretty well in most cases!
- Fixed the Tape Browser's Save button that stopped lighting up in Inkspector 2.0.3. Thanks to PeterJ for the report.
- All of the text character columns on the Memory window are now always visible when View->Full Address is being used.
- When loading a .mdr Microdrive cartridge image file, it could take the trailing read/write flag from a byte somewhere before the end of image, causing the R/W flag to be set to the wrong value.
- The Microdrive cartridge checksum calculator could sometimes generate the wrong value, causing sectors in the Microdrive Cartridge Sector List window to be highlighted in red to indicate checksum error when they were actually OK. In addition, checksums are now coloured green when they pass.
- Fixed a bug with the Spectrum issue 2 emulation that prevented the Softlock release of Rasputin (which doesn't work on issue 3s) from being able to start the game.
- Fixed a regression introduced in 2.0.3 in the +2A/+3 memory contention timing handling when the Z80 was in a HALTed state. Running Hikaru / Intense's floating bus tester now shows the same results as on a real +3 again.
- Reverted the change made in 2.0.2 where the Spectrum 128's contention timings were changed to start from 14363 instead of 14361. They now start from 14361 again. This fixes an issue where the Castle Escape demo would not start the game on a 128K Spectrum (it was fine on other models) as it waited for a red attribute to appear on the floating bus that never arrived. The only down-side of this change is that the centre column of the display on the Shock megademo is 8 pixels to the left again. I'll take a look at this in a future version. Thanks to Craig Hackney for the report.
- When loading a tape image by passing it on the GUI's command line, the previously used machine was not selected first, so it would have been loaded into a Spectrum 48K regardless.
- Many additional pesky little buglettes fixed as a result of documenting Inkspector (I really am working on such a document!).