atari++(6)
๐ atari++ ๐
okay bestie, sit down, hydrate, because this is the manual page for atari++ from the Games Manual section (section 6, iykyk) and it is long. but it's also iconic so let's go ๐
โจ NAME โจ
atari++ โ a versatile extended emulator of Atari 8 bit machines ๐น๏ธ
โจ SYNOPSIS โจ
atari++ [-option value [-option value]...]
โจ DESCRIPTION โจ
so. atari++ is an emulator for those (now rather aged ๐ซ ) Atari 8 bit computers. she emulates the Atari800, the Atari400, the 800XL and 600XL, the 65XE and 130XE, and also the Atari 5200 Game Console. and the emulation is cycle-precise, which means "on the fly" modifications of chip registers show up on the screen immediately โ like, even programs using horizontal kernel tricks get emulated correctly. ate. periodt. ๐ฅ
atari++ also includes emulation of various disk drive models, capable of single, enhanced and double density, plus some frequent extensions found in third-party hardware. the disk drive emulation supports disk images in the xfd and atr file format, and it's also capable of loading binary load files (so called exe files) by emulating a mini Game-DOS whose disk layout is similar to Dos 2.0S. so most exe files wouldn't require being loaded from a regular DOS at all. ๐ซถ and as a bonus, the emulation also includes Matthias Reichl's "atarisio" interface, which lets you connect a real 1050 or 810 drive to the emulating PC by means of a 1050-to-PC or ProSystem cable. real hardware bestie reunion ๐ญ๐
in case no Atari ROM image is available, atari++ emulates a 800XL/130XE ROM image compatible to the Atari ROM that is sufficient to run almost all programs. Basic programs are supported by the built-in Basic emulation that is also compatible to the native Basic ROM. slay โจ
Emulation of printers is included as well. Print-out text is forwarded to the standard printer tool, which defaults to the lpr printer front-end. The print-out command can be adjusted by means of the command line options and the configuration files (see below).
Additional features include emulation of the 850 serial/parallel interface box, emulation of the tape drive, a screen-snapshot, a complete machine state save and load feature that allows you to stop and replay a game in a later session, and sound support by the Open Sound System (Oss) or Alsa sound drivers. ๐ง
Furthermore, to aid the developer, a simple system monitor using a curses terminal front-end has been integrated into the emulator. It offers several features not available on the real hardware, as single stepping thru programs and setting breakpoints, even in ROM code. developer main character energy ๐
Graphics output is either emulated within an X11 window, or โ if available โ with the SDL library. As last resort, and for special applications, some ports provide a curses front-end that renders its output in textual form on a console. Alternatively, the emulator can also be instructed to read and write input to the operating system editor device directly to and from the console, i.e. the standard input and output streams of the program. This is not implemented as a new type of front-end, but rather as an operating system patch. ๐
โจ OPTIONS โจ
quite untypical for unixoid systems, the atari++ options are not case sensitive โ upper and lower case won't matter. and the order of the command line arguments doesn't matter either. the following options are supported:
--helpโ prints all available options to the console.
NOTE: Due to the dynamic build-up of the atari++ components, the options these components become only available if the corresponding component is activated as well. E.g, you won't see the X11 options with the SDL front-end activated. ๐
-hโ similar to the above.
All following options are of four kinds:
- Numerical options taking exactly one number as argument. They typically accept only numbers within a limited range.
- Boolean options, taking the strings
onortrueas positive andoff,noorfalseas negative choices. - String options that take either a file or a string as value.
- Selective options that pick one out of several possible, mutually exclusive choices.
๐ธ On the Fly Configuration ๐ธ
Atari++ provides a quick and a complete menu to setup or modify its configuration on the fly. For the quick menu, press and hold the left mouse button within the emulator window, and pick an apropriate option from the menu on the screen. This menu provides the most-used options, namely to load and boot a disk, to pick a cartridge or to reset the emulated Atari. ๐ฑ๏ธโจ
The full menu is either available as an option within the quick menu, or by pressing the F1 key on the keyboard. The options presented there are identical to the options listed below.
NOTE: The quick menu is not available in case the mouse has been arbitrated to emulate a joystick or any other kind of input device. You'd need to enter the full menu by the F1 key to adjust the configuration in this case. ๐
๐ Global Options ๐
This set of options does not belong to a specific part of the emulation core, but rather influence the emulator as a whole.
-hor--helpโ prints out the list of currently available options. This list does, however, depend on the current configuration of the file as options for modules that are currently not in use will not be shown on this list. For example, if your.atari++.conffile selects the X11 frontend for graphics output, the options for the SDL graphics support will not be shown. Unlike all other options, this option does not take an argument.-config filenameโ Load an alternative configuration file into the emulator. This will override the options from all other configuration files, but will be overridden by the command line arguments itself.-state filenameโ Load a machine state snapshot file. This restores the machine state of a previousatari++session by re-installing the memory conents and all hardware register settings of the previous session. For more details about the snapshot feature, see the SNAPSHOT FILES section below.
๐ฆ Machine Type Options ๐ฆ
The following options modify the overall emulation process, picks the hardware to be emulated and the frontend how to perform graphics and sound output.
-machine 800|1200|XL|XE|5200โ Sets the type of machine to emulate. This is a meta-option that sets suitable defaults for several other options, still allowing to override these defaults with further commands. Hence, you'd be still able to run an Atari XL machine with the Os of the Atari 800. The following models are available:800emulates the Atari 800 and its derivative, the Atari 400.1200emulates the Atari 1200XL. This is almost identical to the 800XL, except that the default ROM image is different.XLemulates the Atari 800XL, the 600XL and the 65XE.XEemulates the Atari 130XE with a total of128KBytememory.- Last but not least, the
5200argument selects the emulation of the 5200 game console.
-frontend X11|SDL|CURSES|NONEโ Defines which graphical front-end should be used. Currently, the X11 the CURSES and the SDL front-ends are supported.NONEis a dummy front-end without any graphical or textual output that can be used for playing music or related tasks. Theinstalledeviceoption is suggested to get minimal support from the console using only stream-I/O. Note this type of redirection is not a front-end option, but rather an optional operating system patch, see OS Options below.
The X11 interface is only available for Unix based operating systems, most notably Linux, while the SDL interface is currently available on most ports. The latter is also able to run in a full-screen mode that is more suitable for gameplay. Typically, the SDL front-end provides better performance unless you need to scale up the output with the -pixelwidth or -pixelheight options. Then, X11 performs noticeably better. The CURSES front-end requires only a terminal for rendering, but its graphics capabilities are rather limited. Specifically, it is only able to emulate text-based graphics modes and expects the built-in font to render the output. The keyboard mapping for the CURSES output is also slightly different, see the CURSES section for details.
-sound HQOSS|OSS|WAV|SDL|ALSA|DIRECTXโ Sets the audio front-end used to generate audio output. For theOSSandHQOSSfront-ends, an Open Sound System compatible driver is required, or no sound whatsoever will be available. Sound synthesis will be very close to the real sound output and will be at good quality, though some CPU power is required to guarantee continuous output without dropouts. In general, theHQOSSdriver is preferably since it requires less precise implementations of the Oss standard and provides excellent quality for synthesized speech.
The main intention of the WAV front-end is to record the sound output as sampled sound in a .wav encoded file in optimum quality. To allow you to listen to in-game sounds, this front-end also offers a "play-back" option that also generates sound output thru an OSS compatible sound output, though this output is of less quality than that of the dedicated HQOSS module. Even though the play-back sound may contain some "blips" or drop-outs, the quality of the recorded audio within the .wav file will be perfect and very close to the original.
The SDL audio generation comes close in quality to that of the HQOSS driver, though it is more likely to generate drop-outs for highly loaded systems. SDL is the best in portability as SDL exists on a variety of systems. The SDL driver also emulates software speech correctly.
The DIRECTX driver is obviously available only for win32 compilations and uses the DirectSound interface of the DirectX system. This is the prefered sound system under Windows as it offers lowest latency at best quality.
Finally, the ALSA front-end uses the state of the art ALSA sound drivers for linux and provides optimal sound quality at minimal CPU load. It provides similar or better quality than the HQOSS front-end at less complexity, but it requires ALSA support, nowadays almost universally available. ๐ถ
more parts coming bestie, don't go anywhere ๐
-monitoroncrash boolโ turn this bad boy on and the emulator will auto-yeet itself into the built-in monitor the moment the 6502 CPU crashes because of a corrupt program. And bestie, listen: those crashes are not the emulator's fault, they're flaws in the emulated program โ like, a "real" Atari would have crashed in the exact same situation, no cap. If it's off, you just get a warning printed and the user menu pops up, and it's on you to either reset the emulation or launch the monitor manually. Defaults tofalse, i.e. the monitor does not enter by itself. ๐ซถ
For all the deets on the system monitor, see the MONITOR section below.
-acceptlicence boolโ enable this and it's understood that you read and agreed to the licence conditions under which Atari++ is delivered, so the licence conditions stop showing up on startup. Iconic. โจ-stereopokey boolโ toggles the "dual Pokey" hardware hack emulation. This hack installs a second Pokey at base address$d210into the system, which is what makes stereo sound emulation possible. Atari++ then provides a second Pokey chip named"ExtraPokey"that otherwise takes the same configuration arguments as the first Pokey does โ except this second chip is not connected to the serial output and the keyboard.
NOTE: the second Pokey chip is fully functional and also provides interrupts. But since the Atari OS isn't aware of this chip, it can't handle those interrupts. So programs might crash if interrupts of this extra chip are erraneously enabled. This is not the emulator's fault โ a real system would crash under the same circumstances. ๐
-ignoreerrors boolโ tells the emulator to ignore all error messages and keep going as if the error requester had been closed by pressing"Cancel".-ignorewarnings boolโ same energy as the one above: suppresses all warning requesters as if the user accepted the warning.
๐ง CPU Options ๐ง
The following options control the emulation of the 6502 CPU:
-traceonreset boolโ debugging queen behavior. If you enable it with theonargument, the CPU enters trace mode on a reset and goes straight into the build-in monitor. ๐-traceinterrupts boolโ another debugging-related one. Turn it on and instruction stepping will also step into interrupt routines as soon as an interrupt gets detected. This might cause some confusion because, surprisingly, the6502CPU will continue execution from a completely different place โ though it's genuinely helpful for finding bugs in display list interrupts. ๐-cputype 6502|WD65C02โ picks which CPU type gets emulated. TheWD65C02offers a couple of addtional addressing modes and instructions that are supported by a couple of products, e.g. theMac/65assembler cartridge. Slay. ๐
๐ GTIA Options ๐
The following options modify the emulation process of the video signal generator, the Graphics Television Interface Adaptor chip:
-videomode PAL|NTSCโ defines whether the emulated GTIA should identify itself as aPALor as anNTSCchip. Some games read this value and modify their timing accordingly. This option also changes the color map GTIA sends to the front-end, since colors differ slightly between thePALand theNTSCversion of GTIA. โจ-ChipGeneration CTIA|GTIA|XLGTIAโ selects the chip generation to emulate.CTIAselects the old first generation used in some very early800and400models โ this chip did not provide the special 16 hue/16 luminance and 8 color modes, BASIC modes9to11.GTIAselects the second generation, used in most800and400models, andXLGTIAthe third generation in the XL series. The last two chips do actually not differ โ only the surrounding analog circuits change the color artifacts slightly, which is the only noticable difference between them.-artifacts boolโ controls whether GTIA should emulate the color artifacts caused by the video system. Set it toonand the video rendering will detect hi-lo and lo-hi transitions for high-resolution graphics and text mode and generate pseudo-colors similar to a real TV. On real hardware these artifacts are limited to NTSC systems and are not as effective nor very visible for the PAL hardware โ the emulator, however, displays them regardless of the emulated video mode. Some games require this setting to look properly. Set it tooffand artifact generation is disabled, as it would be for a higher quality monitor or for the PAL video system. That also makes text more readable and less blurry, speeds up the emulation process somewhat, and is better suited for text-oriented software. ๐-palcolorblur boolโ enables emulation of a feature of the PAL video system standard that can be used to create additional colors by mixing. If two adjacent horizontal lines on top of each other share the same intensity but have a different hue, then the mixture of the colors appears instead of two separate colors. This option is computationally a bit complex and requires a true color display, i.e. a color depth of24bit, to be effective.-antiflicker boolโ enables the Atari++ flicker fixer. Some programs create additional colors by quickly altering the colors forth and back, causing the mixture of the colors due to the slowness of the TV screen. PC monitors are typically much faster, causing an anoying flicker for these programs. This switch enables a flicker-fixer that mixes the colors already in the GTIA display generation โ at the price of a higher complexity. This option also requires a true-color display, i.e. a bit depth of24bit. ๐ฆ-playerpositiondelay 0..32โ controls the number of half color-clocks required by GTIA to detect any change of the player/missile horizontal position register. It's the minimal screen distance in half color-clocks after writing to the horizontal position register until the change becomes effective. The default for this value is12, i.e. it takes12/4 = 3CPU clocks before a horizontal adjustment is recognized.-playerresizedelay 0..32โ same vibe as above: controls the internal GTIA propagation delay until a change of a player/missile size register becomes effective, and thus the distance in screen hires pixels from the modification to the position where the change becomes visible. The default is six half color-clocks.-playerreshapedelay 0..32โ quite similar again: controls the propagation delay for player shape changes, i.e. how long it takes for a write to the P/M graphics register to propagate to the output logic of GTIA. If the write comes too late, the shape change will become visible only on the next scanline โ unless GTIA fetches the data through the ANTIC DMA, of course. ๐-colormapname filenameโ wants a filename to a color map to be used instead of the defaultPALorNTSCcolor map. The color map file must be exactly768bytes long and contains, for each Atari color, a red, green and blue color triple, eight bits per channel.-playertrigger.0 all|players|missiles|noneโ the first out of four otherwise identical options. It sets the ability of player zero to generate collisions with other objects on the screen. Note that this does not change the ability of player zero to detect collisions itself โ it just removes the ability of other players or missiles to collide with it.
If this option is set to all, then player zero can create collisions with all other objects. For the players setting, only collisions with other players are generated and missiles never see any collisions with player zero. For the missiles setting the situation is reversed and only missiles can detect collisions to player zero. Finally, for the none argument, player zero generates no collisions at all.
-playertrigger.1 all|players|missiles|noneโ works similar to the above except that it changes the ability of player one to generate collisions.-playertrigger.2 all|players|missiles|noneโ changes the abilities of player two and, finally,-playertrigger.3 all|players|missiles|noneโ modifies the collision abilities of player three.
Note that there are no options to modify the collision abilities of a missile, since it has none in the real hardware. A missile can never create a collision with a player itself, or any other object. Rather, the situation is somewhat reversed from the expected logic: a player creates a collision to a missile, and hence its ability to collide with missiles must be turned off to avoid detection of player-missile collisions. ๐ง
-playfieldtrigger.0 all|players|missiles|noneโ modifies the abilities of playfield zero, i.e. the first foreground color, to generate collisions to other objects. Similar to the above set of four options, playfields can be allowed to generate collisions to all objects, players only, missiles only, or no objects at all.-playfieldtrigger.1โ triggers the ability of playfield one to generate collisions; otherwise, similar to the above.-playfieldtrigger.2โ the same again for playfield two.-playfieldtrigger.3โ the same once again for playfield three. ๐
๐ฌ ANTIC Options ๐ฌ
The following options control the DMA controller and the playfield graphics generator chip:
-videomode PAL|NTSCโ this option is intentionally identical to the GTIA option of the same name and controls the video system ANTIC should emulate. As for ANTIC, this switch controls the height of the video output. ForPAL, a total of312lines is generated, and forNTSC, only262lines of output are displayed. Note that not all lines are available for graphics, as the vertical retrace takes up some of them. ๐ธ
๐ต POKEY Options ๐ต
Okay bestie, this next batch of options is all about the sound. For actual sound output you need the Open Sound System driver for your sound card โ more specifically, /dev/dsp has to actually be there, no cap. Alternatively you can write the sound output into a .wav file and replay it later with some suitable tool, like XMMS. Other possible sound outputs are SDL or Alsa, depending on whether they're available on your system. Peep the Machine Settings section for the deets.
Now here's the thing: the switches below do not change the output of the sound itself. They change the emulation of the POKEY chip that generates the audio signal which then gets processed by the OSS module described below. Two different layers, iykyk.
NOTE: If the โstereopokeyโ emulation is enabled, a whole second set of Pokey control options shows up under the topic โextrapokeyโ. That set is literally identical to the one described right here. โจ
-volume0..300 โ controls the overall volume of the POKEY output, in percent, compared to normal output.300is loudest, and0disables the output entirely. Default is100%. ๐ฅ-gamma50..150 โ controls the output linearity of the POKEY D/A converter, in percent.100%is a perfectly linear output (assuming your sound card output is linear too). Values smaller than100%give you sublinear behaviour, where high amplitudes look smaller than they should. Values higher than100%give superlinear characteristics, where high amplitudes are louder than they should be. Real pokey chips typically show sublinear characteristics with a gamma value around70%to80%. Iconic honestly.-videomode PAL|NTSCโ okay so Pokey isn't a video interface circuit, but its timing is still controlled by the system base frequency, which is tied to the video mode. This option controls whether Pokey thinks it's living in aPALorNTSCsystem; it nudges the audio base frequencies slightly. ๐ฆ-siosound boolโ enables or disables the serial transfer sound, provided thesiopatchis not enabled and bypasses hardware driven serial i/o. Turning this on gives you a more complete Pokey emulation, because it also takes care of the serial transfer modes for generating sound. Which means: you get the very unique โAtari sound effectsโ for all kinds of disk or tape access. ๐-cycleprecise boolโ controls whether the Pokey emulation works cycle-precise, that is, whether pokey interrupts and potentiometer registers are updated and queried on a cycle by cycle basis. More precise emulation, yes. Also more computing power required, also yes. Pick your fighter. ๐-filterconstant0..1024 โ controls the time constant for an optional high-pass filter applied to the audio output signal generated by the Pokey emulation. This high-pass filter cancels any DC offset in the sound generation that might cause trouble for audio cards or amplifiers, especially when the audio output level is close to the maximum. The lower the filter constant, the more frequencies get cut off by the filter. Setting the filter constant to zero disables the filter. Default setting is512.-recordasSAP boolโ if enabled, the Pokey output is recorded on every vertical blank into a SAP type R file. In principle, such files could be played back as music files by third party software. Unfortunately, type R does not seem to be well supported at this time. ๐ญ-sapname nameโ defines the name of the song currently being recorded, and also the file name the song will be saved under. The file gets created in the directory the emulator was started in, and the file name is generated by appending.sapto the song name. ๐-sapauthor nameโ defines the name of the author recorded in the SAP output file. This one may stay unset, in which case an unknown author will be indicated.
๐ฎ PIA Options ๐ฎ
The following set of options modify the emulation of the Peripheral Interface Adapter chip.
-mathpackcontrol boolโ enables control of theMATHPACKDISABLEsignal thru bit 6 of PIA port B. This function is only required for some dedicated hardware of the author of this program, and should otherwise be left alone. Like, genuinely, hands off. ๐
๐ง MMU Options ๐ง
The following options control the features of the Memory Management Unit. Real talk: for the 800 and 400, no actual MMU chip was used. Instead, the MMU is a set of standard logic gates controlling the memory map of the system. From the 800XL and up, all these gates got integrated into a dedicated hardware chip called the MMU. Regardless of these technicalities, the memory management logic is controlled by the following options:
-4kextended boolโ enables an additional 4K of memory in the range of0xc000..0xd000for the Atari 400 and 800 models. For the XL and XE, this memory region contains parts of the ROM and is never available. For the 400 and 800, this region is otherwise blank. โจ-axlonram boolโ enables emulation of Axlon type RAM expansions, which are controlled by address0xcfff. These RAM disks have pages of 16K each, mapped into memory from0x4000to0x8000.-axlonbankbits0..8 โ defines the number of bits within the page control port0xcfffof the Axlon RAM disk emulation used for page selection. The more bits you enable, the more banks are available. Each additional bit doubles the number of 16K banks. Math is math. ๐-xebankbits0..8 โ this option is only available if the emulator is set up to the 130XE machine type. Then it defines the number of PIA port B RAM bits used to define the selected/active bank. The 130XE uses two bits for selecting the bank, and hence has four pages of 16K, making a total of 64K extended RAM. Now watch this: the more bank bits you enable here, the less compatible the resulting emulation will be to a โstraightโ 130XE. Specifically, you lose the proprietary PIA Port B โMathPackDisableโ at three bits, the selftest at four bits, the Basic ROM at five bits, separate Antic access at six bits, OS Rom mapping at seven bits, and CPU access control at eight bits. So, like, choose wisely bestie.
๐พ OsROM Options ๐พ
The following options control the emulation of the Operating System ROM and related features โ most notably the various Os patches that get installed into it.
NOTE: Original Atari ROM images are not included in the distribution of Atari++ due to copyright restrictions, but Atari++ provides an Os emulation that works just as well in most cases. Also note that the Basic ROM and the Os ROM live in two separate chips, and hence are emulated separately too. ๐ซถ
-osapath filenameโ gives the location of the OS A ROM image. This file contains a simple dump of the memory area0xd800..0xffffof the original first revision Os of the Atari 800 and 400, or a dump from0xf800..0xfffffor the 5200 console.-osbpath filenameโ specifies the location of the second revision of the Atari 800 and 400 ROM image file.-os1200path filenameโ specifies the location of the Atari 1200XL ROM image. This is an early version of the Atari 800XL image with some ROM bugs the emulator has to take care of. ๐ญ-osxlpath filenameโ specifies the location of the Atari 800XL and later model ROM image. This ROM image contains the memory areas0xc000..0xd000, the self-test that can be mirrored to0x5000..0x5800, and the math-pack and the upper ROM area from0xd800to0xffff, in that order. That's also the natural order within the real ROM chip, which is twice as large as for the former Atari models. ๐ธ-os5200path filenameโ specifies the location of the 5200 ROM image.
NOTE: If no ROM image is available, the built-in ROM will be used. This ROM is an XL/XE type of operating system only, and thus requires an 800XL or 130XE machine type for proper emulation.
If none of the above options were given on the command line, then Atari++ will try to locate them itself โ or fall back to the built-in ROM if it can't find any ROM at all. So here's what it does: it looks into the directory roms in the current directory. For the XL operating system, it tries to find a file named atarixl.rom in that directory. For the Os A resp. Os B image, files named atariosa.rom resp. atariosb.rom are searched, and loaded if found. ๐ฆ
-ostype Auto|OsA|OsB|Os1200|OsXL|5200|BuiltInโ defines which kind of ROM shall be loaded into the system. Note that this need not be identical to the type of machine you're emulating, even though that is the default and probably the most useful selection. The 5200 console is the exception: its ROM will not be accepted by anything but the 5200 machine, and any other machine type will not accept the 5200 ROM. That's because the mapping of the hardware differs between the โregularโ Atari 8 bit systems and the 5200 console, which makes the ROMs non-portable.
The โbuiltinโ option selects the built-in ROM emulation that implements a fully-featured 800XL/130XE ROM. This ROM emulation is used if no other ROM image is found. More on this ROM image in the โOs Emulationโ section below.
The โAutoโ option, which is the default, does not select a specific ROM โ instead it picks a suitable rom image for the selected machine. ๐
-installpdevice boolโ selects whether a patchedP:device handler should be installed that redirects printer output directly to the printer component. If this patch is not installed, printer emulation will be re-routed thru the SIO emulation described below. That works as much as this direct patch does, but it might be somewhat slower. No biggie, just slower. ๐ข-installrdevice boolโ bestie, this optionally installs an RS232 interface box handler so serial transfer can happen ๐. On a real Atari, that handler gets loaded from the interface box by a teeny tiny bootstrap code that's usually part of anAUTORUN.SYSorHANDLERS.SYSfile. And yeah, that bootstrapping is emulated too โ but the resident handler this option patches in has a glow-up advantage: it doesn't take up any RAM space, unlike the handler that the interface box emulation itself hands you. That said, if a program tries to trick around with the interface box, the bootstrapped 6502-based handler gives you closer emulation than the native emulation this option implements. Otherwise? The native emulation and the 6502 implementation provided by the emulated 850 interface box are functionally identical. Periodt.
Heads up ๐
โ this option only installs the CIO emulation layer of the 850 interface box. You still need to enable the interface box itself with the -Enable850 on option. Both, bestie. Both.
-installhdevice boolโ if you turn this on, theC:cassette handler gets swapped out for an emulator-specific H: (Host) handler that mirrors parts of the host filing system straight into the emulator ๐ฆ. Specifically: booting from tape is then not available, and neither is tape access in Basic via theCLOADandCSAVEstatements. RIP to those. TheH:device understands all major CIO commands and most XIO commands, following the conventions of DOS 2.0S โ so like,RENAMEandLOCKXIOs are available by their DOS 2.0S command IDs ๐. There's a whole dedicated section about theH:device further down, so keep reading.-installedevice boolโ this one installs a specific patch that replaces the operating system editor device,E:, and to some degree the keyboard device,K:, with emulator-specific routines that redirect input and output from and to the operating system handler over to standard input and standard output โจ. So instead of typing into the emulator window, keyboard data is read from standard input, and output to the editor device gets echoed on the console. Bonus: the editor device stream also goes to the front-end of the emulator. Now for the fine print, bestie, because it matters:
This mode relies on the line-buffering of the console and does not provide a full-screen editor, unlike the Atari. You cannot move the cursor back to a previous line and re-enter it. Also, input will not be seen by the emulator until you press RETURN at the end of the line, and only a very limited set of control characters โ namely those standardized in ANSI-C โ will be transposed from ASCII to ATASCII. For example, cursor movement sequences, which are console-specific, are not available with this patch. ๐
The major purpose of this patch is to script the emulator, not so much to redirect I/O to a terminal. If redirecting to a terminal is the vibe you want, consider the curses front-end instead ๐.
-installhasdisk boolโ this changes the device letter that the host handler gets installed under ๐. By default the handler is calledH:, but if this flag is set, the handler gets inserted asD:instead, giving you emulated disk access. Programs that entirely access the disk through this handler โ BASIC programs, for example โ will then run off the host filing system ๐ฅ.-h1dir filenameโ defines the directory where the first unit of theH:device should be anchored ๐. Files in this directory are accessible throughH1:orH:, provided the host handler is patched in by the option above. iykyk.-h2dir filenameโ specifies the anchor path for the second unit of theH:handler, accessible byH2:โจ.-h3dir filenameโ the host directory for the third unit of theH:handler ๐ธ.-h4dir filenameโ and finally, the directory for the fourth unit of the host handler ๐ฆ. Four units, four dirs, slay.-siopatch boolโ if enabled, serial input/output handling gets routed through an OS patch directly to the emulated devices, instead of taking the detour through the POKEY emulation and the emulation of the serial port โก. This speeds up serial access noticeably โ especially disk drive access โ but it might cause compatibility problems with some critical software that expects precise timing and exact behavior of the serial hardware. So like, fast, but risky. Choose your fighter ๐ .-installmathpatch boolโ this optionally installs a series of patches into the MathPack module of the operating system ๐งฎ. That part of the OS is responsible for floating point support and is used heavily by AtariBasic and other programming languages. This patch replaces the ROM-based math routines with custom patches that make use of the host system FPU instead, hence speeding up any kind of floating point operation dramatically ๐ฅ.
Because of the limited precision of both the Atari floating point model and the host system floating point system, computations performed by the original MathPack might differ slightly from the results you get from the patch. Though ngl, the difference is typically negligible and below the precision of the MathPack itself ๐.
โจ KEYBOARD Options โจ
Ok so these next three options are all about how Atari++ uses your host system keyboard to emulate the Atari keyboard ๐น. And lowkey, they currently only influence the emulation of the console keys โ which, strictly speaking, are not part of the keyboard hardware of the Atari. Just so we're clear, bestie ๐ .
-holdoption boolโ defines whether the emulator shall emulate pressing the Option</key> key during coldstart. The Atari XL/XE roms query the state of this key during bootstrap and disable the built-in BASIC rom if the Option key is held down ๐. Hence, this option should be set to be able to play (non-BASIC) games on an emulated XL/XE system. Yes, that's the whole trick. You're welcome ๐ซถ.-holdselect boolโ defines whether the Select console key shall be pressed during the cold start process. No known OS currently evaluates the state of this key on bootstrap, though. So like... it's there ๐.-holdstart boolโ similar to the above, this enables or disables the activation of the Start console key on coldstart. This signals a boot process from the tape recorder ๐ผ.-bufferkeys boolโ Atari++ comes with a smart keyboard type-ahead buffer that lets you type faster than the original Atari hardware is able to react โจ. Unrecognized keys are buffered until the emulator is able to fetch them. While this feature helps a lot when programming on the emulator, fast gameplay using the keyboard as an input device might become more problematic if keys are delayed rather than swallowed. So like โ great for coding, spicy for gaming ๐ฎ.-keybutton.0.enable boolโ this option is only available for the Atari 5200 emulation ๐. It allows the generation of 5200 "keyboard" events through joystick buttons. If this specific option is enabled, the'0'key on the Atari 5200 keypad can be connected to a joystick button โ and similar options exist for all other numeric keys, plus for the hashmark and the asterisk, namedkeybutton.hashmark.enableandkeybutton.asterisk.enable, respectively ๐.-keybutton.0.button 1..4โ if the above option is enabled, this option controls which of the virtual buttons of a joystick type device is used to trigger the keyboard event for the'0'key on the 5200 keypad ๐น๏ธ. Real talk though: the button numbers required here do not directly relate to the hardware numbering of the OS-specific joystick device โ they refer to the button event numbers used by the analog joystick interfaces of Atari++ instead. TheFirst_Buttonoption of this device then defines which hardware button is responsible for generating the virtual button 1 events, and so on.
Similar options exist for the keypad buttons 0 to 9, and for the asterisk and the hashmark, namely as keybutton.hashmark.button and keybutton.asterisk.button โจ.
-keybutton.0.sensitivity 0..32767โ controls the sensitivity of the reaction, i.e. the minimum amplitude of the button input required to trigger the keyboard event ๐. Since buttons are usually digital, this option can be left alone in most cases. Similar options exist for the remaining keypad buttons ๐ .-keybutton.0.port devicenameโ defines the input device for the Atari 5200 keypad'0'button ๐ฎ. This device is set up in the very same way as for theJOYSTICKemulation, so we refer to that chapter instead. Similar options exist for all other keypad keys ๐ฆ.
๐ CARTRIDGE Options ๐
The next set of options lets you insert a cartridge into the emulated cartridge slot of the system ๐พ. Currently, only the left cart slot of the Atari 400 and 800 (respectively, the one and only cart slot of all later models) is emulated. One slot, one destiny, periodt ๐.
-cartpath filenameโ specifies the filename of the cartridge image to load ๐.-carttype
none|8k|16k|32k|oss|ossb|sdx|xegs|bountybob|flash|megarom|atrax
specifies the type of cartridge to load. Unfortunately, the emulator cannot figure out the cart type itself in all cases just by looking at the image file ๐ญ. Therefore, this option has to be given along with the option above. No shortcuts, bestie.
- None โ a dummy option that just disables the cart, and hence ignores the above option altogether ๐.
- 8K โ emulates an 8K sized plain cartridge that is mapped into the memory from
0xa000to0xbfffโจ. - Right8K โ this cartridge type is only available for the Atari800 hardware type and emulates a cartridge for the right cart slot of this system that gets mapped to the area
0x8000to0x9fff๐ . - 16K โ emulates a plain 16K cart occupying the memory region from
0x8000to0xbfff๐ธ. - 32K โ emulates 32K cartridges of the 5200 game system ๐ฎ. This option and the 32K rom images will not be accepted for all other machine types and hence remain unavailable then ๐ซ.
- 32KEE16 โ emulates a 5200 game system cartridge with a 16K sized image file with incomplete addressing that occupies 32K ROM space ๐งฉ.
- Debug32 โ emulates a 32K debug cartridge for the 5200 game system with two 16K banks mapped into the area from
0x8000to0xbfff๐ฅ.
Oss emulates an Oss super cartridge that's mirrored into the memory map from 0xa000 to 0xbfff, but internally it's only 16K sized. So it hands you a bank-switching mechanism through the CARTCTRL system component, because internally it's literally two ROM chips โ called RomA and RomB from here on out. The lower region 0xa000 to 0xafff is the variable one and can be bank-switched, while the upper region 0xb000 to 0xbfff is hard-wired to the upper part of RomA. Here's the mapping for that lower region, bestie:
0xd500โ RomB Lo0xd502or0xd506โ Blank0xd501,0xd503or0xd507โ RomA Lo0xd504or0xd509โ RomB Hi0xd508and up โ disable cart
OssB is also an Oss super-cart, except the cartridge ROM got dumped to disk in a different order, so the addressing of the cartridge ROM contents is different. If the Oss option is giving nothing, try this one instead. no cap.
SDX emulates a 64K large ROM image with eight banks mapped into the region of 0xa000 to 0xbfff.
EXP is a variant of the SDX cartridge with a slightly different bank switching logic. sibling energy.
Diamond is another variant of the SDX cartridge type, with just another bank switching logic.
XEGS emulates a variable size XEGS cartridge. This cart type occupies 16K of memory inside the address space of the 6502 CPU but it's made of several banks that can be mapped into the 0x8000...0x9fff region.
ExtXEGS is a mildly extended version of the XEGS cartridge type that additionally lets you disable the cartridge.
BountyBob emulates the 40K sized BountyBob cartridge for the 5200 games system. This cartridge uses a very unique bank switching mechanism that needs its own emulation, which is exactly what this option provides.
Flash emulates Steven J. Trucker's โAtariMaxโ flash ROM cart. It's a 128K or 1MB cart with bank-switching logic mapped into the 0xa000...0xbfff region. This cart type allows flashing, so the cart ROM can genuinely be modified by the emulation process. heads up tho: the emulator will ask you to save back the cart image as soon as the cart shall be removed again.
MegaROM emulates the various types of the Mega ROM cartridges. These carts come in various sizes and map in as 16K banks in the area of 0x8000...0xbfff.
Atrax emulates the 128K bank switching Atrax cartridges that map in as 8K banks in the area of 0xa000...0xbfff.
Will โ another super cartridge type, 32K or 64K sized, that maps its 8K sized banks into the area of 0xa000 to 0xbfff.
Phoenix โ this type emulates the Phoenix and Blizzard super cartridges. The first is a regular 8K cart that can be disabled, the latter is a 16K switching cart. Both are emulated by the same cart type. two for one, we love to see it.
ATMax โ a super cart that comes as 128K or 1MB cartridge.
-rtime8 boolโ turns emulation of the RTime-8 pass-thru cartridge on or off. This is a cartridge rom containing a battery buffered real-time clock, and it passes the cartridge slot connections thru so you can run the real-time clock together with other cartridges. The default is not to enable the real-time clock cartridge.
๐ CARTFLASH Options ๐
The flash cartridge type is the only cart type that can be configured from the command line and the GUI. Currently there's literally just one option available, namely:
-enablecartflashโ if this option is disabled, the flash cartridge mapping will be disabled on the next reset. But the cart still receives the bank mapping signals, so software can re-enable it. This is useful if you want to re-flash the cartridges with Steve Trucker's flashing software: just disable this switch, insert the flash software disk, and reboot. The cart will be disabled, the Atari will boot from the inserted disk, and the flash software will re-enable the cartridge, letting you overwrite its contents. To write the cart image back to disk, change the cartridge type to โnoneโ or insert any other cart. iconic workflow honestly.
โจ BASIC Options โจ
These options control the function of the BASIC Rom of the Atari 800XL and later models. Since the Atari 800 and 400 models do not come with a built-in BASIC, these options are ignored for the earlier models; you'd need to insert the BASIC as a regular 8K cartridge for them. Also, whether the basic is mapped for the XL and later series depends on whether the Option console key is held down during bootstrap. That option lives with the keyboard options below, even though it influences how the basic ROM works for the XL and XE series. yes, it's a whole crossover episode.
Atari published three versions of their basic โ Revisions A, B and C. Each has its own bugs, with revision B having the most critical bugs (really) and revision C being the most bug-free. On top of that, the emulator also includes a built-in Basic emulation, Basic++, which fixes most bugs of all three revisions.
-basicapath filenameโ specifies the file name of the Revision A Basic rom image, if you have one. The ROM image is a simple 8K memory dump of the ROM appearing between0xa000and0xbfff. Revision A was only available as a cartridge on the 800 and 400 models; if you want to emulate those two models, insert Revision A as cartridge โ see the CARTRIDGE section of this manual for details. Revision A contains several bugs and is only of historical interest. museum piece vibes.-basicbpath filenameโ specifies the file name of a Revision B Basic rom image. This revision shipped with most early 800XL and 600XL machines. It contains one critical bug that crashes the Basic interpreter potentially when entering source code. best avoided, fr fr.-basiccpath filenameโ selects the location of a Revision C Basic rom image. This revision was delivered with many later 800XL and 600XL models and the last and final XE series. It's the most bug free of the three Basic revisions Atari produced, and the recommended selection if you want an original Basic. the good one.-basictype auto|reva|revb|revc|builtin|disabledโ selects the Basic version Atari++ should emulate. The default is โautoโ, which selects Revision C on XL and XE machines if it is available, otherwise the built-in Basic++.- โrevaโ selects the revision A Basic, โrevbโ the revision B basic and โrevcโ the revision C basic.
- โbuiltinโ uses Basic++, which is compiled into the emulator and always available.
- โdisabledโ removes the Basic completely, making it unavailable independently of the state of the Option key on all machine types.
๐ธ SIO Options ๐ธ
The Serial Input/Output module is a specific part of the operating system that takes care of serial communication. The Atari++ emulation component of the same name controls the low-level emulation features of all devices emulated on the serial port โ so that's the disk-drives, the printer, the 850 serial interface box and the tape. The emulation of the serial port can be bypassed with the -siopatch option described in the OS Option section above, giving a noticeable speedup for disk-drive and printer, but possibly also causing compatibility problems for software that depends on precise timing or side-effects of the Os implementation. You usually need not care about the settings below, since they closely match those of typical serial hardware anyhow. set it and forget it.
-serincmddelay 0..240โ the amount of time taken by a serial device to accept a command frame. This time is given in horizontal blanks. Defaults to 50 lines.-readdonedelay 0..240โ the time taken for a serial read command to complete. For the disk-drive emulation, this would emulate the time required to read a sector from disk up to the time where the first byte of the sector arrives at the port. This setting also defaults to 50 lines.-writedonedelay 0..240โ required time to complete a write command. For the disk-drive, this is the time taken from the last byte of a sector arriving at the drive up to the time where the disk-drive sends the acknowledgement frame. This setting defaults again to 50 lines.-formatdonedelay 0..1024โ required time to format a disk in a disk-drive, measured as the time from issuing the command up to the time where the first byte of the sector status map arrives at the serial input. This is again given in horizontal lines. Since the Os assumes that the timing of formatting is a bit more relaxed than the regular reading time โ yes, formatting is a read command for the Atari โ this is a separate option, defaulting to 400 horizontal lines.
๐ PRINTER Options ๐
This option set controls the printer emulation. Commands and data enter this emulation either by the SIO, or directly by the P: handler should it be patched into the Os. See the OS Options for more details on this. This option set is used in either case, no matter how the emulated printer is accessed. one config to rule them all.
-printtarget tospoolcommand|tofileโ selects where printer output is sent to. For the tospoolcommand selection, printer output is piped into the printcommand selected by the option below. This is typically the โlprโ or โlpโ command on Unixoid systems. For tofile, printer output is sent to a regular file. On some systems, this might be the only available option to print at all.-printcommand fileโ specifies the command used to print out text on the host system. The text arriving at the emulated printer will wait in a queue and will be flushed regularly, appearing at the STDIN of this command. Typically, this should be eitherlprorlp, depending on the printing system you use at your machine.-printfile filenameโ specifies the file printer output is sent to, should this type of output be selected. This is by default empty, disabling printer output completely, though the printer appears to be turned on. fake it till you make it ๐-appendtoprintfilebool โ tells the emulator whether the printer output file you picked in the option right before this one gets completely yeeted and rewritten every single time the printer spits something out, or whether the new stuff just gets tacked onto the end like a group chat you never leave. Default vibe: new output overwrites the old printer dumps, no mercy. ๐-enableprinterbool โ turns the emulated printer on or off. Set it to off and the printer will literally not react to any SIO commands, like it's been unplugged and is just lying there. Otherwise, printing is allowed. ๐จ๏ธโจ-transposeeolbool โ okay so this one is lowkey important. The Atari does not use the regular LF character to separate lines in printer output. Instead it uses the character0x9B(that's CSI in the ANSI set, and it's named EOL on Ataris) as its line separator. So for printing text, EOL has to be transposed into line feeds by this option โ which, btw, is also the default. BUT for graphics output, this character transposition will change the meaning of the graphics data sent to the printer, which means it will distort the graphics. ๐ญ
NOTE: Currently, Atari++ does not include the emulation of a graphics printer. All control and graphics sequences sent out to the emulated printer will be spooled directly into the print command without interpreting them further.
-flushdelay0..60 โ this is the delay, in seconds, from the last bit of data arriving at the emulated printer until all the collected text/graphics actually get printed out. So if data comes in slower than this delay, it'll show up in separate spool jobs. Defaults to five seconds. โณ
๐ SPEED Options ๐
The following set of options controls the timing of the emulator. Several other factors influence the maximum speed though, bestie, so let's be real about them:
- First of all, the graphical front-end of the emulator might be more or less performing. For full-screen emulation, the SDL front-end is performing well provided no pixel upscaling is used. In all other cases, the X11 frontend offers higher speed. This is not the fault of the emulator, it's just the poor performance of SDL being SDL. ๐
- Furthermore, the sound emulation has some impact as well. For software speech emulation, high sampling rates and slim buffers are a must, which causes additional software overhead and higher CPU loads.
To maximize the speed, either run the X11 frontend on 1x1 or 1x2 pixel sizes and reduce the quality of the audio output. ๐ฅ
-unlockratebool โ set this to true and you can pick a custom, non-standard frame rate that is not locked to the video mode (see below) of the emulated machine. Default is to disable this option, which locks the frame rate to the natural frame rate of the emulated machine. ๐-framerate1..100 โ this specifies the screen refresh rate, given in milliseconds per frame. A standard PAL screen with 50 frames per second needs 20 milliseconds per frame; an NTSC screen needs 17 milliseconds. Defaults to20, i.e. the PAL rate โ but it's ignored unless the frame rate is unlocked with theunlockrateswitch above. โฑ๏ธ-maxmiss1..16 โ unlike the above, this one controls how many frames the emulator may miss to keep the emulation speed. Set it to1and the emulator never misses a frame โ which may make it slow on less performing systems. Set it higher than one and at most that many frames might be dropped to keep up the refresh rate set by the option above. So it doesn't hurt to pick a highermaxmisson a fast machine, and it'll keep up the speed for more complex graphics on slower machines too โ at the cost of not emulating the video output as frequently. ๐โโ๏ธ-videodmodePAL|NTSC โ intentionally identical to the same option of the ANTIC and GTIA emulation, this selects the frame rate based on the video output mode. For a PAL machine, it selects a freshmode of 50 frames/second; for a NTSC machine, the emulator will try to generate 60 frames/second. This option is overridden if theunlockrateswitch above is enabled. ๐บ
๐พ DISKDRIVE Options ๐พ
The following set of options controls the emulation of up to four disk drives. The diskdrive options consist of a base name, a dot, and the unit number specifying the unit of the disk drive they control. So yes, all the following options exist four times, and just differ by the digit behind the dot. Slay. ๐
-enable.1bool โ enables or disables the first diskdrive. Set it to off and the first drive won't react, as if it's been turned off; otherwise it's turned on. Default is to enable the first drive and disable all the others. ๐-image.1filename โ specifies the path to an image file to load into the drive. The Atari++ emulator supports several kinds of image files, so let's go through them one by one, no skipping:- Raw disk images that keep the contents of the disk sector by sector. These files are typically identified by their extender
.xfd. - The
.atrformat, implemented by several other Atari emulators. It consists of a tiny header describing the format and the size of the disk, plus the sector image. - Atari binary load files, or for short, so-called
.exefiles. These consist of a two0xffbyte header plus address information telling where to place the data to load. These files are booted by writing them as DOS 2.0S files onto disk, together with a minimal game DOS header that bootstraps the.exeformat. Note that no full DOS will be available for these files, though this emulation is sufficient for most.exebased games right away. - The
.atxformat โ because while the above formats capture all high-level details of disks, they don't include enough info to reproduce the low-level behavior of the disk drive. Specifically, copy protected disks cannot be represented by them. Atari++ supports.atxfor that, which includes pecularities such as disk timing, duplicate sectors or sector defects. Again, the emulator cannot create such disk images, but it is able to read from them. ๐ต๏ธโโ๏ธ .dcmimages, prepared by the โDisk Communicatorโ program, and they're (slightly) compressed. Similar to the.exefiles, Atari++ cannot re-compress these. Therefore, disk images of this type are marked write-protected, making writes to these disks fail. ๐ซ- All of the above disk image types can be compressed by means of the
gzipprogram; Atari++ will then uncompress them on demand as soon as the image gets loaded. Since it does not re-compress images, these disks also always end up write-protected. - Last but not least,
.basfiles, which are tokenized Basic files. To load such files, make sure that either a Basic cartridge is inserted, or the Basic emulation is enabled. The Basic program will not boot automatically if the emulated machine is reset โ unlessBasic++, i.e. the built-in Basic dialect, is selected and the Basic file is inserted into the first drive. All other Basic dialects will see the basic image as a file namedAUTORUN.BASon a write-protected disk. To start the file, enter the command
- Raw disk images that keep the contents of the disk sector by sector. These files are typically identified by their extender
RUN "D:AUTORUN.BAS"
manually on the editor window of the emulated Basic and press RETURN. ๐ซถ
-protect.1bool โ enables or disables the write-protection of the inserted disk. Set it to on and the disk image gets write-protected as if the write-protection notch has been covered on a physical disk. The emulator also write-protects disk images automatically if:- the corresponding image is marked non-writeable by the protection bits of the host operating system, or
- the disk is built up for the
.exebinary load file emulation, or - it comes in the already compressed
.dcmDisk Communicator format.
Similarly, all .gz compressed images and .bas files are write-protected, no matter what the original file format has been. ๐
-drivemodel.11050|810|815|happy1050|warpspeed810|speedy|xf551|usturbo|indusgt โ selects the drive model to emulate. Let's break it down:- The
1050is the disk drive that shipped with the XL series of computers, and it's the default selection. It handles single or extended density disks of 720 or 1040 sectors, each of which is 128 bytes long. Note that this drive type does not support ATR or XFD images with sector counts or sector sizes that go beyond the capabilities of this drive. - The
810is the first disk drive available for the 800 and 400 models. It handles only single density disks, i.e. disks of 720 sectors of 128 bytes each. All other disk types will not be accepted. - The
815drive is a dual-disk drive supporting single or double density disks of 720 sectors, either 128 or 256 bytes per sector. - The
xf551is the last floppy drive sold by Atari; it allows single, extended, double and quadrupel density disks. It has two heads and can read the disk from both sides simultaneously. - All other drive types โ
happy1050,warpspeed810,speedy,usturbo,indusgtโ are third party extensions that allow higher transfer speeds and extended sector formats.
- The
Note that the file management system that's part of the built-in OS emulation does not make use of the higher serial transfer speeds of these extensions, but third-party file systems will be able to detect these drive types and will then switch to a higher transfer speed. โก
Similar disk drive options exist for drives two to four by replacing the digit 1 in the above list by the appropriate drive number. ๐ฆ
๐ SIOCABLE Options ๐
The following set of options control the overall setup of Matthias Reichl's โAtariSIOโ emulation. It requires that the kernel interface and development files for /dev/atarsio are available. Alternatively, the DirectSerial can be used, which might be less reliable since it cannot ensure correct timing.
To make use of the AtariSIO emulation, connect your Atari drive by means of one of two possible interface cable types to the PC, and disable the built-in disk drive emulation for the corresponding drive unit. I.e. if your external drive has been set to drive unit 1, the internal emulation for drive 1 has to be disabled by
-enable.1 false
, or de-selecting the corresponding gadget in the DiskDrive menu. ๐
-cabletype 1050-2-PC|ProSystemโ ok so this one picks which cable you wired a1050or810drive up to your PC with ๐ . rn AtariSIO supports exactly two layouts, the1050-2-PCand theProSystemone. that's the whole menu bestie, no secret third option ๐-enableatarisio boolโ the big on/off switch for the whole AtariSIO interface, no matter which protocol is doing the talking. it's giving master switch energy ๐ฅ-directserial boolโ if you turn this on, Atari++ skips the AtariSIO kernel interface and uses a user space interface instead, so you don't have to install the AtariSIO kernel module at all ๐. sounds cute right? but ngl, timing can't be as precise as the kernel interface, and this interface may fail if the system is under heavy load ๐ญ. also, if AtariSIO isn't compiled into your system, this is the only possible interface method anyway โ and in that case this command line option doesn't even appear, because direct serial communication is then always enabled. periodt.-cmdtodatadelay 0..2000โ only used whendirectserialis enabled, and it's a timing detail for the Atari SIO emulation โจ. specifically: the delay from the start of the falling edge of the COMMAND line to the start of the first byte of the command frame, given in micro seconds. per the Atari SIO specs this delay shall be between750and1600usecs long. the default is900usecs๐ฆ-cmdframelength 800..10000โ another timing constraint of the Atari SIO directserial communications protocol, bestie: the total length of a command frame, measured from the falling to the raising edge of the COMMAND line, again in micro seconds. per the Atari SIO specs this delay shall be between4060and5210usecslong, and the default here is5150usecs๐. heads up though โ because of the load on your host system, you might need to fine-tune this parameter to get a stable SIO communication ๐ญ
๐ธ TAPE Options ๐ธ
ok so besides disk drives, Atari++ also supports an archaic medium for data storage: the 410 and 1010 tape drives ๐. they store binary data in frequency-modulated form โ a high tone for a one, called โmarkโ, and a somewhat lower tone for a zero, also called โspaceโ โจ.
the emulator supports two types of tape images:
.casfiles โ tape archives that have already been converted into a binary representation ๐ฆ.wavfiles โ which contain the digitized audio from the tapes directly ๐ต
for the .wav ones, Atari++ emulates the analog filters required to decode the audio, but ngl, due to the nature of the process, .wav files are less reliable, similar to real-world tape recordings ๐. if possible, use .cas files whenever possible. that's the move ๐
the option
-image filenameโ defines the.casor.wavfile to be read from or to be written to ๐ซถ. Atari++ accepts both thecasorwavformat as input, and can create both file types when writing to a simulated tape. the emulator cannot append to tape archives, i.e. each recording has to go into a separate file ๐ญ-play boolโ this presses the โplayโ button of the simulated tape drive, and hence allows the motor to spin if enabled by the main system โจ. as a command line option it doesn't make much sense, lowkey โ it's best used within the emulator ๐ . the flow is: once the Atari operating system beeps once, requesting you to start the tape, enter the menu and start the tape by the button of the same name in the Tape menu, then return to the emulation and press theRETURNbutton there. this will start the playback ๐-record boolโ for recording data on tape, the Atari operating system beeps twice, requesting you to press the โplayโ and โrecordโ buttons ๐๏ธ. same must be done in the emulator: go to the menu, into the Tape menu, enable theโplayโoption there, but also select theโrecordโbutton below. the corresponding command line option is as given above, but it also makes little sense as a stand-alone option ๐. afterwards, return to the emulator window and pressRETURN. this starts the recording process ๐. and if theโsiosoundโoption is enabled, you should hear a distinct high pitch tone โ that's the classic sound of data recordings on tape ๐-eject boolโ presses the simulated eject button of the tape drive, removing the recording from the drive ๐ซ. this unloads the image and completes it on disk. it's most useful as a button of the same name in the Tape menu as well ๐ซถ-recordaswav boolโ controls the output format when recording data on tape ๐. by default, Atari++ records in the more robust.casformat, which doesn't require additional decoding โจ. if this option is set, the emulator creates.wavfiles that correspond to the audio information that would be recorded on a real tape. this format is not recommended for archiving purposes โ it creates longer files that are also harder to decode ๐
the following additional options are also recognized by the tape subsystem:
-videomode PAL|NTSCโ defines the video mode the system operates in, and by that the timing of the tape ๐. this should be, and on the command line only can be, set identical to the video mode of the host system ๐-motoroffeofgap 20..10000โ controls when the emulator considers a stopping tape as the end of the recording ๐. unlike the real machine, where the tape is entirely controlled by the user, the emulator has to make some guessing as to when a recording should be considered as completed, and no additional data is following ๐ . it currently does this whenever the motor stops longer than the indicated time, in milliseconds. the value defaults to3000, i.e. three seconds โฑ๏ธ. once the motor halts longer than this, the simulated tape is removed from the tape recorder and no further data is expected. enlarge this value if a tape file is created by a relatively slow BASIC program ๐ข
๐ ATARISIO Options ๐
this option group fine tunes the AtariSIO interface whenever it's available โจ. unlike the SIOCABLE option group, this set exists once per external drive and defines parameters that are specific for the drive and not for the cable interfacing to the drive ๐. therefore, the following options exist four times, where the suffix โ.1โ needs to be replaced by the appropriate drive number ๐
-sioenable.1 boolโ enables the first external drive โ or subsequent ones for higher suffixes ๐ฆ. it is disabled by default. note that for redirecting drive accesses to AtariSIO, the emulator-internal drive emulation must be disabled as well. hence, to use a real1050as first floppy drive, the following two options would be required:
-sioenable.1 true -enable.1 false
-sioprotect.1 boolโ enables or disables an additional write-protection that blocks any write access to the external drive, as if the floppy write-protection notch has been covered ๐. this option defaults to off ๐-siotimeout 1..30โ specifies the timeout in seconds that applies to regular commands โณ. since the Atari++ emulation of the diskdrive applies at the level of raw POKEY communcations, the emulator cannot know the desired timeout that has been selected by the driving Atari software ๐ . this timeout defaults to seven seconds โจ-sioformattimeout 10..120โ specifies the timeout in seconds for formatting commands, which typically require longer than regular commands ๐ซ. this timeout defaults to sixty seconds, i.e. one minute, but is overridden by the specifications that are returned by the disk drive itself as soon as a status command is send to the drive ๐
๐น๏ธ JOYSTICK Options ๐น๏ธ
Joystick emulation for Atari++ consists of two layers bestie ๐:
- the emulation of the corresponding port at the emulated hardware, and
- the generation of sigals to feed data into this emulated port.
for that, Atari++ uses the concept of a generic input device consisting of two axes and four buttons, abstracting from the real physical device on your machine to generate the input โจ. for a physical (analog) PC joystick, the meaning of the two axis and four buttons should be obvious, but other sources for the abstract input device exist as well โ e.g. the mouse or the keyboard ๐ญโจ๏ธ
later stages of the Atari++ input layer then only refer to the buttons of these virtual devices, e.g. the keypad options of the 5200 device ๐
the following set of options do not control the physical input devices, but rather select how the emulator should make use of this abstraction layer, whereever it comes from, to form digital joystick input ๐ฎ. i.e., these options control the emulation of the emulated joystick port on input from an abstract input device ๐
similar to the diskdrive options, all joystick options exist four times, now numbered from zero to three ๐ฆ. the digit behind the dot in the option name defines the joystick port this option controls. for the Atari 800 and 400, all four ports are used by the emulator; for the XL and later models, only the ports 0 and 1 are mapped to the emulated hardware, similar to their physical counterparts โจ
-joystick.0.sensitivity 0..32767โ this option sets a threshold that must be crossed by the abstract analogue joystick input to detect a joystick movement on the emulated joystick port ๐ซ. the lower the number, the higher the sensitivity. the abstract input devices generate axis movements from-32767to32767, and the default of this option is that a movement of8192units on this scale is required to generate an input signal ๐-joystick.0.port devicenameโ defines the name of the abstract device that should be connected to the port ๐. currently, the following devices exist:
๐ฆ MouseStick.0
uses the mouse on your host system as abstract input device, with the horizontal and vertical position of the mouse pointer forming the horizontal and vertical axis of the abstract input device connected to the port ๐ญโจ. there is only unit 0 of this device ๐
๐ฎ RelMouseStick.0
Basically the same vibe as the MouseStick device above, except it vibes off mouse movements instead of the absolute mouse coordinate. This is often the better alternative, ngl โ unless your host machine's pointer device is also absolute-positioned, i.e. a trackpad or a touchscreen. ๐ฑ๏ธโจ
๐ฎ KeypadStick.0
Takes the keypad on the host system's keyboard and turns it into the abstract input device. Digits 8, 4, 6 and 2 generate maximal axis movements in top, left, right and down movement, respectively; keys 7, 9, 1 and 3 move in the corresponding diagonal directions. The 0 and Enter map to button 0 of the joystick. And there is โ quite obviously โ only unit 0 of the keypad-stick. These keys can be reconfigured dynamically, and its config lives under the KeypadStick section below. โจ๏ธ๐
๐ฎ AnalogJoystick.0
Uses the (real) analog joystick connected to the port controlled by the /dev/js0 device to form the abstract input of the device. Which physical axis forms which abstract axis is controlled by the analog joystick options described below, but the default mapping is the obvious one: each physical axis maps to the same abstract axis, and buttons 0 and 1 map to their abstract counterparts. Atari++ accepts up to eight physical joysticks by replacing the digit 0 in the above option by 1 to 7 for further joysticks that are then connected to the corresponding joystick devices. ๐น๏ธ
๐ฎ DigitalJoystick.0
Uses a (real, antique) Atari Joystick connected to an analog PC joystick port by means of the โEl Cheapoโ joystick adapter of the author. This adaptor maps the digital input lines of a digital joystick to the buttons 1 to 4 of an analog joystick, and maps the one and only button by a resistor array to axis 0. As above, some parameters of this interface can be setup by the digital joystick options described below. Similar to above, the signals generated by this hardware are then read thru the standard /dev/js0 Linux interface, and up to eight digital joysticks can be emulated this way, accessing the devices /dev/js1 to /dev/js7. NOTE: You need to build some additional hardware to make use of this abstract device, but you get perfect Atari feeling as a bonus. ๐ฅ
The schematics for this interface are included in the distribution as โjoystick.psโ. ๐
๐ฎ SDLAnalog.0
Similar to โAnalogJoystick.0โ except that the joystick position isn't read from the kernel interface directly, but rather indirectly thru the SDL library. This makes absolutely no difference except that on some systems only the kernel interface is available, whereas on others only the SDL interface can be used. ๐
๐ฎ SDLDigital.0
Works exactly the same as โDigitalJoystick.0โ except that the joystick movements are reported thru the SDL library rather than thru the kernel interface. Causes no difference in usage and options otherwise. โจ
๐ฎ None
Do not connect any device to this joystick input and read it as โcentered, no button pressedโ all the time. ๐ค
Similar to the diskdrive options, the joystick options exist four times with the unit numbers 0 to 3. The default for the abstract input device is to use the keypad stick for joystick zero and leave all other joysticks and paddles unconnected.
NOTE: The 5200 console system does <b>not</b> use standard Atari digital joystick input. Instead, analog joysticks connected to the paddle inputs are used. It is therefore <b>mandatory</b> to define the input devices of the first two paddles, paddle0and1, to have an input device for the 5200 console. The digital joystick inputs defined by the options above WILL NOT WORK. ๐
๐น๏ธ PADDLE Options
The following set of options control the emulation of up to eight paddles that can be connected to the emulator. Similar to the above, the emulation requires an abstract input device to read the input of the emulated paddle from; paddle emulation uses only axis zero of this abstract device to form the paddle input, but requires buttons zero and one for the emulation of the two paddle buttons. ๐๏ธ
NOTE: The paddles on the Atari machines use the joystick input lines for the paddle buttons. For that reason, paddles and joysticks <b>should not</b> make use of the same input device. ๐
NOTE: For the 5200 system, the controller is connected as a paddle and hence <b>these</b> โ and not the joystick options โ must be defined. ๐
As above, the following options exist several times, with the digit 0 replaced by 1..7 for all other paddle units. Whereas the Atari 800 and 400 allow this maximal number of eight paddles, inputs 4 to 7 are not available on a real Atari XL or XE. However, the Atari++ allows connection to these paddle inputs regardless of the emulated host input as the corresponding input lines are otherwise unused on the real hardware either. ๐ธ
-paddle.0.sensitivity 0..32767โ Adjusts the sensitivity of the paddle and hence the movement necessary for a full paddle rotation. Note that the abstract input device generate movements on a scale of-32767to32767. ๐๏ธ-paddle.0.invert boolโ Since paddle input has no natural orientation, this option allows you to invert the meaning of the input device position. Since some games interpret paddle positions just opposide to others, this flag helps you out as it changes left movement to right, or upwards movement to downwards movement. ๐-paddle.0.port devicenameโ Defines which abstract input device to use to feed the paddle emulation. The very same devices as for the joystick emulation are available here, though pure digital devices as the keyboard or the digital joystick device are not very usable for paddle emulation. Since an abstract input device provides two axis and two buttons each, it makes sense to map one input device to two paddle inputs: for that reason, each even paddle number maps to the first axis and the first button, and each odd paddle number maps to the second axis and button of each abstract input device. ๐
โ๏ธ LIGHTPEN Options
Atari++ also allows emulation of the lightpen as a kind of analog input device. Though rarely used, the corresponding input lines at ANTIC are available and can be feed by this emulation component. There is only one lightpen device available, though its other options are very similar to the paddle emulation. ๐
-lightpen.sensitivity 0..32767โ Defines the sensitivity of the lightpen and hence the factor/adjustment between the real physical device and the emulated position of the lightpen on the screen. ๐-lightpen.port devicenameโ Specifies which abstract input device to connect the emulated lightpen to. The list of available devices is identical to the list of devices for all other gameport like input, please see theJOYSTICKOptions section above. ๐๏ธ
โจ๏ธ KEYPADSTICK Options
Options in this group define the keys used by the Keyboard Joystick emulation. By default, the numeric keypad to the right of a standard PC keyboard is used for this purpose, but the keys can be reconfigured. ๐นโจ
-leftup keynameโ defines the key that moves the stick in the diagonal left upwards position. Pressing the left and the up key simultaneously is equivalent to this. Key names are either the numbers0to9or the lettersAtoZ, indicating the corresponding keys on the main keyboard, or are taken from the list below. An empty string indicated by an empty pair of opening and closing quotes disables the corresponding function. ๐ฆ-up keyname-rightup keyname-left keyname-right keyname-leftdown keyname-down keyname-rightdown keynameโ move all the joystick in the corresponding direction. Diagonal directions can be either assigned to separate keys, or are reached by pressing the two direction keys simultaneously. ๐-center keynameโ centers the joystick. ๐ฏ
The option
-leftbutton keynameโ configures the key that emulates the left button if the keypad is used as a paddle, or the one and only button if the keypad emulates a digital joystick. ๐-rightbutton keynameโ selects the key to emulate the right button on paddles. The key has no function if the keypad emulates a standard Atari joystick. ๐
Key Names are either alpha-numeric characters from 0 to 9 or A to Z indicating the corresponding keys on the main keyboard, or the following special names. Note that names containing spaces need to be quoted on the command line:
Cursor Leftโ Left pointing arrow of the four cursor keysCursor Rightโ Move cursor right keyCursor Upโ Move cursor upCursor Downโ Move cursor down, all the above on the cursor keypadReturnโ Return key on the main keyboardTabโ TAB key on the main keyboardBackspaceโ Backspace key on the main keyboardKeypad 0โ Digit 0 on the numeric keypad, similar for 1 to 9Keypad Divideโ Division key on the numeric keypadKeypad Multiplyโ Multiplication key on the numeric keypadKeypad Plusโ Addition on the numeric keypadKeypad Minusโ Subtraction on the numeric keypadKeypad Dotโ Decimal separator, dot or comma, on the keypadInsertโ The insert key between main keyboard and numeric padDeleteโ The delete key in the same groupHomeโ The home keyEndโ The end keyScroll Upโ The page up keyScroll Downโ The page down key
๐ฎ ANALOGJOYSTICK Options
Unlike the JOYSTICK Options, the following set of options describes the mapping of a true analog joystick connected to one of the joystick device drivers to the abstract input device that forms the basis for either joystick, paddle or lightpen input. Hence, it defines the layout of the AnalogJoystick devices that can be connected to the above emulation components. ๐น๏ธ๐ซ
Okay bestie, continuing right where we left off โ the digit-swap situation ๐ซ
Similar to basically all the options above, these ones show up several times, once per device, with the digit 0 swapped out for the unit number of the device it belongs to. So the analog PC joystick sitting on /dev/js1 gets set up with options just like the ones below, except a 1 takes the place of the 0. Slay, consistent naming โจ
-first_button 1..16โ tells the emulator which physical joystick button should map onto button zero of the abstract input device. Default? The first physical button goes to the first button, aka button zero, of the abstract device. So it defaults to button#1of the real device. And here's the twisty part if you're rolling with the 5200 keypad device (that's theKeyButton.0.Buttonfamily of options): the button index#1you use in the keyboard config points at whatever button this option picked, not straight at a hardware button. So keypad buttons get routed twice โ first stage goes through the hardware abstraction layer set up by this option, and the second stage is the keyboard device picking one of the four abstract buttons that layer offers. Nested. Iykyk ๐ง-second_button 1..16โ same energy as above, but this one picks the real button that hooks up to the emulated second button of the emulated device.-third_button 1..16โ again with the routing: one hardware button โ one virtual button on the hardware interface layer. But heads up, bestie, because the Atari hardware can only really handle at most two buttons, namely for the paddles. So the third and fourth buttons are only usable for the 5200 keypad emulation โ go check the keyboard configuration chapter for the deets ๐-fourth_button 1..16โ the input line of the fourth button that an abstract joystick device might support. Once again: only usable from the keypad emulation. Periodt.-haxis.0 xaxis.1|yaxis.1|xaxis.2|yaxis.2โ says which axis of the physical joystick emulates the horizontal axis of the abstract analog joystick device. The default is the first horizontal axis of the physical joystick. Easy.-vaxis.0 xaxis.1|yaxis.1|xaxis.2|yaxis.2โ same thing but for the vertical axis of the abstract device. And the default is, of course, the first vertical axis. Obviously ๐
โจ SDLANALOG Options โจ
This is a modified AnalogJoystick interface that reads joystick positions thru the SDL library instead of hitting the kernel interface directly. Its config options are identical to the AnalogJoystick interface's options, so we are not describing them all over again here. Go read the other list, bestie ๐ฆ
๐ DIGITALJOYSTICK Options ๐
Next up: the options for setting up the digital joystick input and the "El Cheapo" Joystick input adapter โ that's the little thing you can use to connect a true Atari digital joystick to the analog gameport input of the PC. This set also exists several times, once for every available gameport detected on the host system. And once again: replace that digit 0 with the unit number of the device your joystick is plugged into ๐
-upbutton.0 Button.1|Button.2|Button.3|Button.3โ defines which of the four joystick buttons on the analog gameport acts as the input for the upwards movement line. The default is button three.-downbutton.0 Button.1|Button.2|Button.3|Button.3โ same deal for downwards movement. The default is button one.-leftbutton.0 Button.1|Button.2|Button.3|Button.3โ picks the button that acts as the left movement input. This defaults to button four.-rightbutton.0 Button.1|Button.2|Button.3|Button.3โ picks the button for right movement input. The default is button two.-triggeraxis.0 XAxis.1|YAxis.1|XAxis.2|YAxis.2โ selects the analog gameport axis that reads the digital joystick button input. The default is that the digital fire button is connected to the first horizontal axis.-triggerthres.0 -32768..32768โ so here's the tea ๐ต: because the digital button gets read by the game port as an analog input, the digital signal arrives as a numerical value between-32768and32767at the digital joystick device of the emulator. This option sets the threshold at which the button counts as pressed vs. released. The exact values totally depend on the resistance network wired to that analog gameport line, but the default of16384works fine for the author's hand-soldered adaptor. Hand-soldered?! Iconic ๐ฅ-inverttrigger.0 boolโ this switch flips the fire button input line reading, so active inputs read as released fire buttons and vice versa. Shouldn't be necessary with the author's interface, so the default is off. Don't touch it unless you gotta.
๐ SDLDIGITAL Options ๐
This is just a slightly modified DigitalJoystick interface that connects to SDL instead of the kernel interface. All its options are identical, so please refer to the list right above for the details. Nothing new under the sun, bestie ๐
๐ OSSHQSOUND Options ๐
Alright, time for audio ๐ง. Here's a set of options to control audio generation thru the OSS HQ driver, which makes use of the Open Sound System kernel interface or an equivalent emulation โ ALSA, for example. Different from the POKEY Options, these options are about the quality of the samples generated by the POKEY emulation and how they're built up for OSS. For audio output to actually work, you need an Open Sound System compatible audio driver available, and you need permission to access the /dev/dsp device. No permission, no vibes ๐ญ
Heads up, bestie: generating audio samples at high quality has a non-neglectable impact on CPU load. If your machine can't keep up with the natural framerate, or the CPU load is just too high, try lowering these settings, use a different audio front-end, or disable sound output alltogether. Your CPU will thank you ๐ซถ
-enablesound boolโ turns generation of audio output on or off. The default is to enable audio generation, unless no audio output device is available โ in which case audio output gets disabled.-enableconsolespeaker boolโ enables or disables emulation of the Atari console speaker. The Atari Os uses this speaker for keyboard click sounds and the buzzer, and some games even use the console speaker for speech output. Cute.-consolespeakervolume 0..64โ sets the output volume of the console speaker. Setting it to zero effectively disables the output, and setting it higher than 32 may cause distortion with regular POKEY audio output. The range goes from zero up to64for maximal volume, with the default being32. Stay in your lane at 32, ngl.-audiodevice filenameโ names the audio device to send the samples to. This device must accept all Oss specificioct()settings. It defaults, naturally, to/dev/dsp.-samplefreq 4000..48000โ the sampling frequency in Hz at which samples get generated, which is also the limiting frequency for the audio signals. Higher value = higher frequencies can be emulated = more natural the sound plays. Frequencies higher than16000are required for software speech output, but otherwise a frequency limit of8000Hz is enough for all other sound effects. The default is44.1kHz, the CD replay frequency. Classic.-fragsize 2..16โ a technical little setting ๐ ๏ธ: it specifies the size of an audio buffer fragment. These fragments get filled sample by sample and shipped off to the replay hardware as soon as they're full and the hardware can play another sample. Too small โ the buffer gets refilled way too often and you might hear drop-outs because the computation can't keep up with the audio replay. Too long โ the audio latency gets too high and the sound is no longer synchronized with the video out. Important: this option does not give the fragment size itself, it gives the exponent to the base of two โ so the true fragment size is two to the power of this exponent. The default is8, i.e. a fragment size of256bytes. You'd rarely need to play with this setting, fr fr.-numfrags 6..256โ the number of buffers, each one the size given by the argument above, used for audio sample generation. More buffers reduce the likelyhood of drop-outs but increase the latency. The default is16buffers, and more is rarely useful.-forcestereo boolโ forces generation of stereo samples even though mono output is available for the sound chip. Some broken sound implementations โ notably ALSA on theEmu10K1chipset โ require this to work correctly under all configuations. Not us fixing their bugs, but okay ๐
๐ OSSSOUND Options ๐
The Oss driver is a less complex frontend for the Open Sound System audio interface, though it requires a very precise implementation of it. Some emulations, e.g. ALSA, might not be suitable for this frontend, and it rarely provides better quality than HQOss. Since it offers quite similar options as well, we're only describing most of them roughly and referring you to the HQOss frontend for further details. Low effort, high key.
-enablesound boolโ enables or disables the generation of audio output.-enableconsolespeaker boolโ enables or disables the emulation of the Atari console speaker.-consolespeakervolume 0..64โ sets the output volume of the console speaker.-audiodevice filenameโ names the audio device to send the samples to; this is typically/dev/dsp.-samplefreq 4000..48000โ the sampling frequency in Hz for the audio output.-refillfreq 20..48000โ the frequency in Hz at which the audio samples get recomputed by the emulator. If this is set to a relatively low value while the sampling frequency is high, then quite a lot of samples are computed in one go, but the updating period by which these samples are matched to the true POKEY output is rather low. Also: this refill frequency must be lower than the sampling frequency above. For software speech generation, a refill frequency of15700proved most effective. For regular sound output, this frequency can be much lower. And here's the caveat, bestie: for software speech output, the audio kernel interface must meet the specifications of the Open Sound System architecture precisely โ some emulations, e.g. ALSA, fail here. Try theHQOssfrontend in this case; in most cases it's capable of providing better quality anyhow ๐ธ-fragsize 2..16โ this is the exponent for the base of two that gives you the size of an audio buffer fragment, in bytes. It's basically the same idea as the fragment size over in the HQOss frontend, and we already spilled all the tea about it above. โจ-numfrags 1..256โ how many buffers get used to generate your audio samples. Two buffers means the audio output is double-buffered. Ngl, more than four buffers is rarely useful for this driver, which is why four is the default. ๐-forcestereo boolโ forces it to generate stereo samples even when mono output is actually available for the sound chip. Some sound implementations are just straight-up broken, most famously ALSA on the Emu10K1 chipset, and they need this turned on to work correctly in all configurations. ๐ญ
๐ WAV Options ๐
The WAV frontend is the alternative audio output module that records the generated sound instead of playing it โ or at least, that's its main character intention. WAV also offers playback of the recorded sound, but because of timing restrictions the quality of that sound is โ sometimes noticeably โ worse than what you'd get from the Oss or HQOss module, and worse than the sound that actually got recorded into the final .wav file. But like I said: the quality of the output file itself will be perfect. ๐
-enablerecording boolโ turns recording to the wav output file on or off. When it's enabled, the emulator starts recording the moment the emulated machine starts running, though the recorded file gets disposed of and re-written from scratch on a cold-reset, like the one generated by theF7key. To record game music, bestie, the move is: first enable the recording, then start the game, let the music play, and interrupt the music by entering the configuration menu with theF1shortcut. Then turn recording off. That leaves the recorded file intact. ๐ต-enableplayback boolโ enables or disables playback of the recorded data. If this option is on, the WAV frontend will also play the music over an OSS compatible sound driver. It's typically a good idea to enable this one too whenever it's available, i.e. whenever an OSS sound driver exists in the system. Note though, that the quality of the sound output might be noticeably worse than that of the recorded sound inside the output file. ๐-enableconsolespeaker boolโ just like the option of the same name for the OSS sound frontend, this enables or disables generating sound through the console speaker. It's typically used for the keyboard-clicks and the buzzer-sound. ๐น-consolespeakervolume 0..64โ sets the volume of the console speaker when it's enabled. This one defaults to32.-outputfile filespecโ defines the full path of the.wavoutput file the sound gets recorded into. If you don't give this option, the file name defaults toโout.wavโ. ๐-audiodevice deviceโ sets the name of the OSS sound device. This is typicallyโ/dev/dspโ, which is also the default setting for this option.-samplefreq 4000..48000โ sets the sampling frequency in Hz for the recorded.wavfile, and by extension also the sampling frequency of the played-back audio output. The smaller it is, the less CPU power you need and the shorter the output file gets for recording the same timespan of music โ but the worse the quality gets. This option defaults to15700Hz, which is the best compromise between quality and data size. Much higher frequencies make little sense and don't improve quality noticeably. ๐-fragsize 2..16โ same as the OSS front-end option of the same name, this sets the exponent for the size of the fragment used for audio playback. It has no influence whatsoever on the output file, it only modifies the behaviour of audio playback. โจ-numfrags 1..256โ sets the number of audio fragments (buffers) for audio playback, just like the option of the same name in the OSS front-end. It has no influence on the recorded samples.
๐ฆ SDLSound Options ๐ฆ
The next audio front-end generates sound through the Standard Direct Media Library โ SDL for short โ all provided you have an SDL library and the required development files installed on your host. The quality of the SDL output is close to that of the HQOss frontend, though because of the different driver architecture, the SDL driver is unfortunately more likely to generate drop-outs. It also requires longer fragments, so it has a higher latency โ but it's super portable since SDL exists on a whole variety of platforms. ๐
-enablesound boolโ enables or disables sound generation through SDL, same as the equivalent option for the OSS and WAV audio front-ends.-enableconsolespeaker boolโ toggles the console speaker emulation on or off. The emulation is enabled by default.-consolespeakervolume 0..64โ adjusts the volume of the console speaker. This setting defaults to a medium volume of32.-samplefreq 4000..48000โ adjusts the sampling frequency for audio generation in Hz = samples per second. Higher sampling frequencies give you closer sound output emulation, but they also enlarge the CPU load on the system. The sampling frequency defaults to44100Hz, i.e. CD quality. On weaker systems you might have to lower this setting. ๐-fragsize 2..16โ selects the size of an audio output buffer, expressed as the exponent for the base of two. The smaller the fragment size, the more often the audio output gets updated to reflect the audio register setting of the POKEY chip, and the more natural the audio output becomes. But if the fragment size is too small, then the audio output degrades quickly, because the emulation will no longer be able to refill the output buffers in time. The optimal setting for this value is around nine, which is also the default. ๐-forcestereo boolโ forces it to generate stereo samples even when mono output is available for the sound chip. Some broken sound implementations, notably ALSA on the Emu10K1 chipset, require this to work correctly under all configurations.
๐ฅ DirectX Sound Options ๐ฅ
This audio front-end is only available for win32 compatible platforms and requires at least DirectX 8.0 installed on the host machine. It offers the highest audio quality available under the win32 operating system at minimal latency. It's giving premium. ๐
The following options are available for DIRECTX sound:
-enablesound boolโ enables or disables audio output. It's enabled by default.-enableconsolespeaker boolโ turns emulation of the console speaker on or off. This speaker generates the keyboard click and buzzer sounds, but otherwise it's not used very frequently; it's enabled by default.-consolespeakervolume 0..64โ controls the volume of the console speaker. The default setting is32, though higher volumes are not recommended since they'll cause distortion when mixed with the regular POKEY output. ๐ฌ-samplefreq 4000..48000โ selects the sampling frequency in samples per second. The default is22050Hz, i.e. half the frequency of an audio CD. Higher frequencies are not recommended for DirectX, because otherwise the CPU load gets very high.-fragsize 2..12โ sets the size of one audio buffer, also called a โfragmentโ, by defining its exponent to the base of two. So increasing this setting by one doubles the size of one audio buffer โ a setting of eight causes buffers that are 2^8 = 256 samples long. This is also the default buffer setting and a good compromize between latency and quality for fast, up-to-date hardware. Slower systems might need higher values; if you hear audio drop-outs, increase this value. ๐-numfrags 6..16โ defines the number of audio buffers of the above size to be allocated. A higher number allocates more buffers, causing higher latency, but also lowering the probability of drop-outs. The default is six buffers, but you should increase this number if the audio output isn't smooth.
๐ธ ALSASound Options ๐ธ
The last available audio front-end uses the ALSA sound drivers available on Linux and the asoundlib API. Both of those, plus their development files, must be available at compile time to provide this interface.
If available, ALSA provides high quality sound similar to the HQOSS frontend, though its demands concerning CPU power are very moderate and lower than that of other frontends. Lowkey the most chill one. โจ
The following options are available for ALSA:
-enablesound boolโ enables or disables the sound output. This defaults to on.-enableconsolespeaker boolโ controls emulation of the console speaker; this option is turned on by default.-consolespeakervolumne 0..64โ selects the volume of the console speaker. It's set to32by default; higher volumes might cause distortion in the sound output.-audiocard nameโ selects the audio hardware ALSA shall send the samples to. This is not a device specification in the sense of a path name. It defaults toโhw:0,0โ, which addresses the first available audio hardware handled by ALSA. Further audio cards are namedโhw:1,0โand so on. Even though Atari++ supports a wide range of sampling formats natively, some exotic cards might require help from ALSA. To enable this additional software support, substituteโhwโwithโplughwโ, e.g. specifyโplughw:1,0โas the device name. This enables an additional software conversion inside ALSA. ๐ง-samplefreq 4000..48000โ selects the sampling frequency in samples per second. The default is44100Hz, i.e. CD quality.-fragsize 2..16โ defines the size of an audio buffer fragment as the exponent to the base of two. This works very similarly to all the other audio frontends and I'm not explaining it again, bestie. ALSA allows a relatively small default of8here, meaning fragments of 2^8 = 256 bytes.-numfrags 6..256โ defines the size of the audio buffer in fragments. The more fragments, the lower the probability of drop-outs, but the higher the latency. The number of fragments defaults to12.-forcestereo boolโ this one forces stereo samples to be generated even when mono output is available for the sound chip. Why would you do that? Because some sound implementations are lowkey broken, notably ALSA on the Emu10K1 chipset, and they may require this to work correctly under all configurations. So if your audio is giving ๐, try flipping this.
๐ฅ๏ธ X11 Options ๐ฅ๏ธ
okay so this next lil squad of options controls the X11 graphical frontend of the Atari++ emulator โ but only if you actually picked it with the -frontend X11 option. If you didn't, then the control options of whatever frontend you did select are the ones that apply instead. no cap ๐ซถ
-privatecmap boolโ set this to on and Atari++ will emulate its own color map for the emulation window output. You only need this if you're running on an 8 bit display and the emulator further complains that it couldn't allocate enough free pens. The downside? ๐ the colors will get wrong as soon as the mouse pointer leaves the emulator window on an 8 bpp display โ but at least you get a display with proper colors otherwise, so tradeoffs bestie.
This option is not at all useful for 16 bpp or any other true-color displays, because the color mapping will be correct all the time otherwise. Therefore, the default for this option is off.
-syncx boolโ a boolean flag describing whether the X11 frontend shall try to keep the display output in sync with the emulator. If set to off, all rendering operations will be asynchronous, possibly causing some lag between the gameplay and the display ๐ญ. The downside of enforcing synchronous graphic rendering by setting this to on is that the display refresh must wait for the X server to perform the refresh and to notify the client about it, adding the turn-around times and the net transfer overhead to the display refresh time. So yeah โ it is therefore rarely a good idea to enable this option. leave it alone fr.-disableDPMSโ disables the display management power signal extension and thus prevents the monitor blanker or screen saver of the operating system from jumping in while you're playing with the emulator. It is usually a good idea to enable this option โจ (yes pls, no one wants their screen going dark mid-boss-fight).-xvideorendering boolโ will use the โXVideoโ extension of the X11 system to render graphics on the screen. Unlike the default rendering mode, which builds the image from many colored rectangles, this render mode writes the raw display data into a shared memory region which is then scaled and pushed to the screen directly by the video overlay mechanism of the graphics card when available. Depending on the graphics hardware, this option may provide better performance on lower end hardware ๐ฅ.-renderindirect boolโ if set to on, then all rendering happens indirectly to an off-screen pixmap in a first step, then blitting the pixmap in a second step back to the screen. Downside: it's slower, because it requires an additional transfer step ๐. Upside: it makes the display refresh smoother, and the rendering operation itself remains invisible (no tearing jumpscare). Since it makes emulation slower, this option remains off by default.-screenbase filenameโ selects a filename base for the screen dumps. If a screendump is requested, a counter and a file type extender is appended to this name, and the screen contents are saved to this file. Currently, screen dumps are saved in the Portable Pixmap (ppm) format that is readable by most Linux/Unix tools, e.g. byxvandgimp. The default filename is โScreenDumpโ.-dumpformat PNM|BMP|PNGโ specifies the file format to be used for screen dumps.PNMis the simplistic *nix specific PNM/PPM true color dump file format that is understood by most *nix programs.BMPis the Windows Bitmap format, a very popular but rather aged image file format of the Win world ๐.PNGis the โPortable Network Graphicsโ file format, an image format driven forward by the Open Source community. This file format requires the availibility of the LibPNG.
-pixelwidth 1..8โ this option spezifies the magnification degree in horizontal direction by which the pixels of the emulated scren are rendered to the X11 display. The default of thepixelsizeoption is 2, i.e. a single pixel of the Atari display is rendered twice as large on the X window showing the emulation ๐. Depending on the hardware driver of your graphics board, enlarging the pixelsize might be almost for free with the X11 frontend โ free glow-up, we love that.-pixelheight 1..8โ this option controls the magnification of the pixel size in vertical direction, similar to the above option. The default value is 2 as well ๐ .-leftedge 0..64โ sets the horizontal position of the first Atari pixel that gets displayed within the X11 window. The pixels left to this pixel are not made visible. This option is useful either to align the size of the X window to the natural size of the screen the window is contained in, to hide the leftmost pixel junk caused by the horizontal ANTIC scrolling, or to remove the hardware border of the window, similar to the operation performed by some TVs ๐บ. This option defaults to 16, just enough to make the HSCROLL artefacts invisible.-topedge 0..64โ sets the first row of the ANTIC display to render to the X11 window. This is otherwise identical to the-leftedgeoption except that it works in vertical direction. The default of this option is zero.-width 320..480โ sets the total amount of pixels to render into the screen and hence the inner dimension of the X window. Reducing this width can be either useful to fit this window into the screen, or to avoid some pixel junk at the right edge of the ANTIC display. The default width is 352 pixels.-height 192..248โ sets the height of the window in emulated pixels. Since the lowest lines are always left blank anyhow, they need not to be rendered. Therefore, this option defaults to 240.
๐ฎ SDL Options ๐ฎ
The next option set controls the layout of the alternate emulator frontend driven by the Simple Direct Media Library, or short, SDL. This library allows fullscreen output, though its overall performance is lower as soon as it requires to upscale the pixels ๐ฌ. The SDL frontend is activated by the -frontend SDL switch, and only then do the following options apply:
-leftedge 0..64โ similar to the X11 Option of the same name, this selects the first visible emulator pixel on the SDL screen. This option defaults to 16.-topedge 0..64โ specifies the first visible row on the screen. The default is to start the display at row 0.-width 320..480โ the width in emulator pixels of the screen to render. The default is 352.-height 192..248โ the height of the emulated display. The default is to drop some lines at the bottom end since they are always blank anyhow: 240 lines are rendered by default.-pixelwidth 1..8โ set the width of one emulator pixel in SDL pixels. The default is that one emulator pixel is represented by one pixel on the SDL screen. Setting this to values larger than two easely degrades the emulator performance ๐ซ .-pixelheight 1..8โ set the height of one emulator pixel in SDL pixels. As already said above, the default is one. Pixel heights larger than two typically slow down the emulator too much to be useful ๐ญ.-screenbase filenameโ defines a base file name similar to the X11 screenbase option for screen dumps. The filename of the screen dump is, as above, formed by a counting number and the extender of the file format. Currently, screen snapshots are saved as PPM images.-doublebuffer boolโ enables double buffering, provided the implementation of SDL on the host system implements it. Double buffering allows smoother scrolling at the price of a slightly higher CPU load โจ. At the time of writing, only the win32 version of SDL provides double buffering, the Linux version does not. Thus, enabling this option under Linux does nothing ๐. However, therenderindirectoption of the X11 front-end does something very similar.-fullscreen boolโ enables or disables full screen display. The default is to use the full screen display, and it is recommended to use the X11 frontend otherwise as it provides higher performance in this case.-dumpformat PNM|BMP|PNGโ specifies the file format to be used for screen dumps.PNMis the simplistic *nix specific PNM/PPM true color dump file format that is understood by most *nix programs.BMPis the Windows Bitmap format, a very popular but rather aged image file format of the Win32 world.PNGis the โPortable Network Graphicsโ file format, an image format driven forward by the Open Source community. This file format requires the availibility of the LibPNG.
-shieldcursor boolโ enables a workaround against an SDL bug that allows a program to overdraw the active mouse pointer, trashing its backing store and leaving invalid graphics behind the pointer if it is moved away ๐. This workaround will remove the cursor prior the drawing operation to avoid the problem, at the cost of a possibly flickering pointer ๐.-deblocker boolโ enables a deblocking filter that creates rounder and smoother graphics for pixel sizes between two and three. This avoids to some degree the blocky-ness of the emulated display that is caused by the higher and finer resolution of the PC monitor compared to the TV output the Atari hardware was designed for ๐บโจ.
๐ 850INTERFACE Options ๐
The Atari++ contains a complete emulation of the 850 serial interface box, including a boot-able R: handler that would be usually included in the ROM of the interface box ๐. The emulation allows you to use the serial port of the host system as a serial output port of the 850 interface, allowing you to connect a modem to the emulated Atari. The emulation has only two limitations:
- It cannot provide some of the exotic baud rates the 850 box is able to generate.
- It provides only a single serial port, not four of them.
On the other hand, it offers a true hardware handshake, unlike the Atari 850 ๐
. For more information about the emulator provided R: handler, see below.
okay bestie these next two are all about the 850 interface ๐ tiny section, big vibes:
-enable850bool โ turns the 850 interface on or off. If you disable it, the interface box will not react on any SIO commands at all, so it basically pretends to be switched off. iconic behavior honestly ๐ซถ-serialnamepath โ tells the emulator which device name to use for the serial port that the emulated 850 interface uses as its output port. The default is"/dev/ttyS0", aka the first serial output port of the system. no cap โจ
๐ CONFIGURATION FILES ๐
bestie, Atari++ is not just controlled by its absolutely huge amount of command line parameters โ it's also adjustable by configuration files ๐ธ
These configuration files contain the very same options as the command line parameters, with just a few little rules:
- there is only one option per line
- an equals
=sign separates the option from its value - the minus-sign in front of the option is missing
Also, empty lines are allowed, and so are comments starting with the hash-mark # ๐
Here's what a typical configuration file looks like:
#
# This is the config file for the atari++ emulator
#
HoldOption = true
Artefacts = off
Enable.1 = on
Protect.1 = on
SIOPatch = on
InstallPDevice = on
SampleFreq = 44100
RefillFreq = 15700
NumFrags = 4
Joystick.0.Port = DigitalJoystick.0
The Atari++ emulator knows three configuration files:
- The system specific configuration file, living at
/etc/atari++/atari++.conf - The per-user specific configuration file at
~/.atari++.conf - The per-directory configuration file at
./.atari++.conf
Each later configuration file overloads the defaults of the former one, and then the command line arguments finally overload all of them ๐ฅ
So the strategy is: the least frequently adjusted options should go into the configuration file in the home directory, and the system specific settings go into /etc. chef's kiss ๐
๐๏ธ KEYMAP ๐๏ธ
The Atari++ emulator uses the following keymap, bestie, listen up ๐
F1โ this key enters the graphical configuration menu. Using this menu should be pretty obvious, since all the options are named exactly like they are in this manual and sorted under the same topics ๐ The menu is left by the topmost Prefs topic, which also lets you load and save the settings and enter the monitor. For theCURSESfront-end theF1key changes its meaning, because no full menu is available there. In that case, it replaces the Atari resp. inverse-video key ๐F2โ is mapped to the Option console key.F3โ is mapped to the Select console key.F4โ is mapped to the Start console key.F5โ is the Help key, which is otherwise only available on the XL and XE hardware โจF6โ is the Reset console key. Its function differs a bit amongst the various models. For the Atari 800 and 400, this key just signals a special NMI interrupt at ANTIC, and the Os resets the system manually. For the XL and XE, this signal is really connected to the CPU reset line. Atari++ emulates this behaivour ๐F7โ coldstarts the system as if it had been turned off and on again. So unlikeF6, this is a true coldstart and not a warmstart ๐ธF8โ emulates the Break key, used to stop listings and BASIC programs.F9โ requests a screen dump. Where this screendump goes is a matter of the-screenbasecommand line option ๐ธF10โ aborts the emulator immediately, similar to closing the window. bye bestie ๐ญF11andPauseโ pauses the emulator. PressingF11again continues the emulation โธ๏ธF12โ enters the on-line monitor that is described below.Home/Clearโ emulate theShift+<sequence, enforcing a clear screen ๐งผInsertโ inserts a blank character under the cursor by emulatingCtrl+>. If pressed together with shift, a blank line is inserted at the current line position.Delโ removes a single character under the cursor by emulating aCtrl+BSkeyboard sequence ๐- Cursor Keys โ move the cursor in the indicating direction by holding either
+,*,-,=and theCtrlkey down. This works fine most of the time, except for the DDT debugger, which requires these keys pressed withoutCtrlfor window movement. Do not use the separate cursor keys but the above keys directly for DDT ๐ซถ Escโ emulates, as expected, the ESC key on the Atari keypad.- Keypad keys
7,8,9,4,5,6,1,2,3โ are part of the"keypadstick.0"device and a possible emulation source for joystick input; they are also configurable, see theKeypadSticksection ๐น๏ธ - Keypad keys
0andEnterโ emulate the joystick button of the device as well. ALTโ emulates the Atari or InverseVideo key. For some implementations, this key is also emulated by the Windows key ๐ช
All other keys have their natural key binding, except for the 5200 game console, which is explained below. This binding is given by the current keyboard layout; this means especially that the keyboard layout is language specific and does not necessarely match the layout of the Atari keyboard. E.g. for a german keyboard, the keys for "y" and "z" work as printed on the PC keyboard, and not as for the (american) Atari keyboard layout. I currently consider this as an advantage ๐
๐น๏ธ KEYBOARD INPUT FOR THE 5200 ๐น๏ธ
Keyboard input on the 5200 game system is considerably different, because this console does not have a keyboard โ it has a small numeric pad on each of its controllers ๐ฎ
That pad consists of:
- the numbers zero to nine
- the asterisk
"*" - the hash-mark
"#" - the buttons labelled
"Start","Pause"and"Reset"
Furthermore, the joysticks have two buttons instead of one, and are actually analog joysticks using the paddle input lines, see above.
The current emulator uses the PC keyboard for all additional keys and does currently not distinguish between the various keypads. A button pressed on the PC keyboard will be read as coming from all game controllers at once. A future version of atari++ may possibly use a different scheme ๐คทโโ๏ธ
The following keyboard keys act differently on the 5200 system:
F2โ is the"Reset"key on the keypad of the controller. This key is in no way any kind of hardware reset and is dissimilar to the"real"hardware reset which is still triggered byF6. Instead, this key is just an ordinary key that must be read by the loaded game, typically bringing you back to the setup screen.F3โ is the"Pause"key on the keypad. This is also a purely software driven feature the game may or may not support.F4โ is the"Start"key; it typically launches the game ๐- keys
0..9โ activate the corresponding keypad keys. Hor#โ emulates the hash-mark on the keypad controller key. Since the hashmark is not available on all native PC keyboards, theHis available as a replacement ๐Sor*โ emulates the asterisk on the controller keypad. Similarly, theSis a suitable emulation for native keyboards with a hard-to-reach asterisk key.Shiftโ acts as the second trigger button on all external controller keypads.F2thruF12โ act as usual, see the list above โจ- all other keys โ are blind and perform no operation in the 5200 emulation mode ๐
๐ฅ๏ธ THE CURSES EMULATION ๐ฅ๏ธ
The keyboard input of the CURSES (terminal) front-end is rather limited, because the emulator has considerably less control over the keyboard than under the graphical front-ends ๐ญ
Note that this emulation replaces the complete front-end of the emulator, it is not fit to script it, e.g. feed input to it from a file. For that, better replace operating system editor functions and use the InstallEDevice function.
In the curses front-end, most keys work as expected, with some limitations:
F1โ does not provide a full menu, which is not available due to lack of graphics output. Instead, the machine must be configured manually from the command line or the configuration files. TheF1key rather maps to the Atari or InverseVideo key, as the state of theALTkey is not directly accessible from theCURSESinterface ๐CAPSโ is not directly available because the CapsLock key is read by the host operating system and is not forwarded to the emulation. Instead, the emulator sends aCAPSkey event after each reset, triggering the system to low-caps, which is the default under most host operating systems, and then setting the Shift key of the emulated machine according to the case of the inserted character. This makesCAPS"appear"to work right for most situations โ unless a program fiddles with the operating system and alters theCAPSstate manually, or performs a software-driven reset. In that case, the ASCII TILDE that is" ~ "will emulate a press on theCAPSkey of the host ๐- Requesters and Menus โ requesters and error messages will be emulated on the console by text-driven menus, allowing you to select a choice by typing the indicated character ๐
- Graphics Output โ the graphics emulation is limited to text based ANTIC modes, limited to the standard character set. Some of the text graphics can be emulated, ASCII-Art might work to a limited degree, but bitmap graphics output will not appear on the console. Some limited support for horizontal scrolling is available, though ๐
๐พ SNAPSHOT FILES ๐พ
okay bestie, this is genuinely one of the slayest features and you're gonna be obsessed. atari++ lets you take a snapshot of the complete machine state at literally any moment mid-game, save that state to a file, and then restart the game later from exactly that position. not just useful โ it's iconic. want to interrupt a game temporarily because you've got better things to do in the meantime? covered. want to grind through a hard game puzzle several times without crying? also covered. ๐ซถ
So to create a snapshot file, you press F1 on your keyboard to pop the menu, pick the Prefs item on the left hand side list, and drop the name of the state file into the bottommost gadget labelled โSave State Toโ. that's it, that's the whole ritual โจ
To restore a machine state โ i.e. to load the snapshot file โ use the gadget โLoad State Fromโ right on top of it, or use the command line option -state filename, which expects the name of your snapshot file.
now here's the part where you gotta pay attention, because it's giving โจimportantโจ: the snapshot file contains only the part of the inner machine state that is not covered by the configuration file. for example, the snapshot file will NOT contain the currently active ROM image, because that image is already sufficiently specified by the configuration. so if your configuration at the time you made the snapshot differs from your default configuration, you should also save that configuration, and load it along with the snapshot. snapshot files extend configuration files โ they are not independent from the emulator configuration. periodt.
๐ THE H: HANDLER ๐
so the emulator ships an optional interface from the emulated Atari to the host environment, and it's called the H: handler โ it makes parts of the host's filing system visible inside the emulation. main character energy fr fr. ๐
To actually use this handler, it has to be enabled by the -InstallHDevice on command line option, or a similar option within the configuration files. what this does is replace the C: cassette interface โ which is rarely, if ever, useful โ with the host interface filehandler. and this handler provides four units, named H1: to H4:, opening four directories of the host system within the emulator. those directories get configured by the -H1Dir to -H4Dir command line options, which expect path name(s) to host system directories.
๐ธ FILE NAMES AND PATTERN MATCHING ๐ธ
Similar to the standard file management systems DOS 2.0S and upper, the H: handler automatically resolves patterns within filenames. The following wildcards are supported:
*โ matches a sequence of any, possibly zero, length of any characters, quite similar to the bash or the csh.?โ matches one single character.-โ matches any character and ignores the rest of the pattern.
Unlike the standard file management systems, the dot . has no special meaning for the H: device โ except that file names are truncated to eight characters in front and three characters beyond it. this is a backwards compatibility feature, so you can run most Atari Os compliant programs on the H: device without additions. iykyk.
The handler will furthermore ignore cases when comparing the requested file name with a file name on the host system. Files generated by the emulator will use lower case for convenience. cute, right? ๐
๐ง COMMAND SET ๐ง
The H: handler supports the following IO commands:
CMD 3: OPEN โ used by the BASICOPEN #channel,aux1,aux2,"H:filespec"command. Theaux2specifier will be ignored. validaux1values are:4โ open for read-only6โ open the directory7โ open the directory8โ create for write-only9โ open for append write-only12โ open for read, write and append13โ create for read, write and append
This follows closely the DOS 2.0S conventions, with the addition that mode 12 is able to write past EOF and mode 13 also creates files. Mode 7 is an addition that was made for compatibility of DOS 2.XL by the author.
The filespec follows the file name convention explained in the previous subsection. The directory listing generated by codes 6 and 7 will be formatted similar to the DOS 2.0S output for the same request, but the amount of free sectors will always show up as "999". why? because there is basically no visual storage limit for a tiny Atari file system inside a Unix/Linux workstation, bestie. Files that are not user-writeable appear as "locked" and are marked with an asterisk in the first column. Similarly, file locking and unlocking changes the user-writeable protection bit of the host system. ๐
CMD 5: GET RECORD โ reads characters up to an EOL character, or up to the buffer end, into a buffer. This is a standard command supplied by all handlers. It implements the BASICINPUT #channel,varand related commands.CMD 7: GET CHARACTERS โ reads a block of characters into a buffer. This is a standard command, consult the Atari technical manual for details. Not reachable from BASIC.CMD 9: PUT RECORD โ writes characters up to an EOL or up to the end of the buffer into the opened stream. Also part of the standard command set. Not reachable from BASIC, but related to the BASIC commandPRINT #channel,data.CMD 11: PUT CHARACTERS โ writes a block of characters into a stream. A standard command. Not reachable within BASIC, but related to the BASIC commandsPUT #channel,valueandPRINT #channel,data.CMD 12: CLOSE โ releases the given stream, closes the file on the host system and frees all buffers. This command is considered harmless on streams already closed. This implements the BASICCLOSE #channelcommand.CMD 13: STATUS โ requests the status of the given stream. It returns status code133if the channel is not open, status code1if the channel generated no error, status code3if you are about to read from the EOF on the next go, or the last error should the stream be in an error condition otherwise. This follows standard conventions.CMD 32: RENAME โ implements the BASICXIO 32,#channel,aux1,aux2,"H:oldname,newname"command. Note that the file specification of this command consists of an existing filename, a comma,, and a new file name. This command attempts to rename the existing file to a new name.CMD 33: DELETE โ implements the BASICXIO 33,#channel,aux1,aux2,"H:filespec"command and attempts to remove (delete) the given files or patterns. It will fail if the files are not user-readable, i.e. appear"locked"in the emulator.CMD 34: VALIDATE โ an extension following DOS 3 conventions, also reachable within BASIC withXIO 34. This command will check whether the given filespec is well-formed and will return an error code if not. It does not attempt to open any file.CMD 35: UNPROTECT โ implements theXIO 35command which"unlocks"the given file(s) and allows write-access into it. The host system reflects this operation by enabling the user-writeable permission bit.CMD 36: PROTECT โ implements the BASICXIO 36command and"locks"the filespec by removing the user write-permission bit.CMD 37: POINT โ unlike command32to36above, this expects that the given channel is already linked to an open stream. It implements the basicPOINT #ch,sector,bytecommand for placing the file pointer within the file. The Os. CIO places the sector offset inAUX4andAUX5and the byte offset intoAUX3. However, conventions for file addressing are different from DOS 2.0S and are more orthogonal. TheH:handler appears to have sectors of256bytes each, numbered linearly from0up within each file. Sectors are not global within the filing sytem but local to the file linked to the channel. This is somewhat similar to the DOS 3 implementation of POINT. ๐ฆCMD 38: NOTE โ similar to command37, this command expects an open stream on the same channel, implementing the BASICNOTE #ch,sector,bytecommand. It reads the file pointer within the opened file and returns byte and sector offsets using the same conventions as POINT. Bytes are numbered consequently from0to255, and sectors are numbered from the start of the file from zero up, each of them but possibly the last carrying256bytes of data. As long as programs use the values returned by NOTE as opaque values and avoid to perform algebra on them, this remains compatible to the DOS 2.0S. However, programs expecting125byte sectors and absolute sectoring are likely to fail. ๐ญCMD 40: RESOLVE โ this command resolves a wild card sequence by a real filename. It reads the wildcard fromIOCBAdr, and places the resolved filename back into the buffer pointed to byIOCBAdras well. To be able to resolve non-unique wildcards,IOCBAux2defines which of the non-unqiue matches shall be returned. It counts from one up, and returns the n-th found match to the specified wildcard.CMD 41: BINARY LOAD โ load an executable file, and possibly initialize and run it if the fileAUX2specifies whether the loaded file shall be initialized or run. If set to192, the file is initialized and run,128means"init only",64just runs, but does not initialize the file, and0neither runs nor initializes the file.- Unimplemented commands โ The
H:device does not implement the various format commands, for obvious reason. It also doesn't implement some DOS 2.XL resp. DOS 3 extensions to initialize a DOS. Especially, opening theDOS.SYSfile for writing will not perform anything special. ๐
๐ THE E: HANDLER ๐
okay so this one is the operating system editor handler โ it's the lil guy whose whole job is grabbing user input off the screen and then yeeting data right back onto it. โจ and normally? bestie, you leave it ALONE. every component it needs is already emulated so it just... does its thing, no notes, no meddling. ๐
but if you're tryna script the editor, sometimes it's genuinely useful to redirect the output that would normally go to the machine's editor into a Unix or Windows file, and also pull the input that would normally come from the keyboard out of a file too. ๐ซถ
for that, you use the operating system patch -installedevice, which swaps the Atari handler out for a patch that runs on the host system. input data gets read from the standard input of the emulator command, and output goes both to the emulator front-end and the standard-output of the emulator command. slay. ๐
but ngl, only a limited number of control character transpositions are available. ๐ญ specifically, these standard ANSI control characters get recognized and translated:
\tโ Horizontal TAB\nโ New Line, transposed to EOL\bโ Backspace\aโ Bell\fโ Form Feed, transposed to Clear Screen
Cursor movement and other advanced sequences? yeah those are left alone, fr fr. they're output device dependent and need a way more careful analysis that depends on which console type you're using. ๐ง so if you need to run the emulator in a console, consider the curses front-end instead โ that's the move.
Another limitation of the E: device patch: it obviously can't emulate the full-screen editor buffer of the Atari ROM, because it has no access to the screen of the emulator. ๐ instead, only the line-buffering of the console is available, meaning the emulator will NOT be able to see your input unless you press RETURN. periodt.
and this also holds for the keyboard device, for which a patch is provided along with this option. so specifically: if software running in the emulator requires you to press a key, you need to terminate that input by RETURN to make it accessible to the emulator. ๐ธ
๐ THE R: HANDLER ๐
okay so bestie, the R: handler is literally part of the emulated 850 interface box โ it is not specific to the emulator, a real 850 would also provide this handler. ๐
but here's the tea ๐ต โ unlike the H: handler, the R: handler is not installed by the emulator directly, and it is not available unless it is booted by a dedicated file. An Atari DOS distribution should either contain a file named HANDLERS.SYS or an appropriate AUTORUN.SYS file to bootstrap this handler. Dos 2.5, for example, provides a setup program to generate the appropriate file. This bootstrap code is not specific to the emulator and works generically for the real, as for the emulated 850 interface box. For the real 850, the bootstrap code loads code from the interface into the Atari; for Atari++, this code is part of the 850 emulation, but uses otherwise the same command set as the real 850, providing maximal compatibility. ๐ซถ
The emulator even emulates some of the limitations of the 850 system, because accuracy is the vibe: once opened, the R: handler is in block mode, only allowing you to write blocks of data asynchroniously, but not allowing you to receive data. In block mode, 850 I/O can be mixed freely with any other disk I/O. โจ
With a special XIO command, the handler must be put into concurrent mode to be able to read and write data synchroniously. In this mode, data gets sent out immediately as it is written, and input data can be received back as soon as it arrives, but any other device on the serial chain is unreachable and cannot be used savely. Thus, the disk is unavailable in concurrent mode. ๐ญ
๐ COMMAND SET ๐
The following set of CIO commands are made available by the R: handler:
๐ CMD 3: OPEN
Open a channel to the R: handler. Aux1 is either 8 for output only in block mode, 5 for input with concurrent mode support, 9 for output in block and concurrent mode, and 13 for input/output, including concurrent mode support. Aux2 is ignored. ๐ช
๐ CMD 5: GET RECORD
Reads characters up to an EOL character, or up to the buffer end, into a buffer. Reading is only available in concurrent mode. Read characters can be optionally translated from ASCII into ATASCII, see CMD 38 below. ๐
๐ CMD 7: GET CHARACTERS
Reads a block of characters into a buffer. Again, only available in concurrent mode. ๐ง
โ๏ธ CMD 9: PUT RECORD
Writes characters up to an EOL or up to the end of the buffer into the opened stream. Available in block mode or in concurrent mode. In block mode, data is buffered and transmitted as soon as either the buffer becomes full, or an EOL is sent. In concurrent mode, data is sent out immediately. In both modes, characters can be optionally translated from ATASCII into ASCII. ๐
๐ CMD 11: PUT CHARACTERS
Writes a block of characters into a stream, not necessarely terminated by an EOL. Otherwise identically to the above. ๐ฅ
๐ช CMD 12: CLOSE
Releases the given stream, possibly empties the buffer in block mode, or waits until the write buffer is empty in concurrent mode. โจ
๐ CMD 13: STATUS
Requests the status of the given stream. Additionally, memory locations $2ea to $2ed are filled with useful information. Location $2ea contains the error flags of the serial transfer as follows:
- Bit 7 โ received a framing error
- Bit 6 โ input register overrun error
- Bit 5 โ parity error detected
- Bit 4 โ input buffer overrun error
The difference between bit 6 and bit 4 is that bit 6 gets set if the emulated Atari could not react fast enough on interrupts, and bit 4 gets set if the user-provided input buffer overruns in receive mode, though the data could have been catched successfully. ๐ค
Location $2eb contains the state of the handshake lines in block mode:
- Bit 7 โ current status of the DSR line
- Bit 6 โ previous status of the DSR
- Bit 5 โ current status of the CTS line
- Bit 4 โ previous status of the CTS line
- Bit 3 โ current status of the CD line
- Bit 2 โ previous status of the CD line
- Bits 1,0 โ unused, reserved
The history bits mirror the state of the lines that has been returned by the previous โSTATUSโ command. ๐
Locations $2ec to $2ed are unassigned in block mode.
In concurrent mode, $2eb and $2ec contain the low- and high-byte representing the number of characters in the input buffers, respectively. Location $2ed contains the number of characters in the output buffer. ๐
๐ฅ CMD 32: FORCE
Flushes the output buffer in block mode, or waits until the output buffer has been transmitted in concurrent mode. ๐
๐๏ธ CMD 34: SETLINES
Only available in block mode, not in concurrent mode. This command selects the states of the output lines RTS and DTR. On the real 850, the state of the data line TxD can be selected, too. The bits in Aux1 are interpreted as follows:
- Bit 7 โ change the state of the DTR line
- Bit 6 โ new state of DTR if bit 7 is on
- Bit 5 โ change the state of the RTS line
- Bit 4 โ new state of RTS if bit 5 is on
- Bit 3 โ ignored, reserved
- Bit 2 โ ignored, reserved
- Bit 1 โ change the state of the TxD line
- Bit 0 โ new state of TxD if bit 1 is on (unsupported)
Currently, the emulator does not support direct state changes on TxD, though. The value of Aux2 is ignored. ๐
โฑ๏ธ CMD 36: SETBAUD
Specifies the baud rate and other serial transfer parameters, and handshaking. Only available in block mode, not available in concurrent mode. The bits in Aux1 are interpreted as follows:
If bit 7 is set, at least two, maybe more stop bits are generated. If the bit is clear, one stop bit, maybe more can be generated. Bit 6 is unsed, Bits 5 and 4 specify the number of data bits: If set to zero, eight data bits are transmitted, for 16 (bits = 0,1 resp.) seven bits are used, for 32 (bits = 1,0) six data bits are generated, and for 48 (bits = 1,1) five data bits are sent. Bits 3 to 0 define the baud rate according to this table:
- Value 0 โ remain unchanged
- Value 1 โ 45.5 (not emulated)
- Value 2 โ 50
- Value 3 โ 56.875 (not emulated)
- Value 4 โ 75
- Value 5 โ 110
- Value 6 โ 134.5 (emulated as 134 baud)
- Value 7 โ 150
- Value 8 โ 300
- Value 9 โ 600
- Value 10 โ 1200
- Value 11 โ 1800
- Value 12 โ 2400
- Value 13 โ 4800
- Value 14 โ 9600
- Value 15 โ 9600
Note that values 14 and 15 generate the same rate. ๐ซ
The bits of Aux2 indicate which serial lines have to be monitored if concurrent mode is entered. If the selected serial lines are not set, an error is generated. For the emulator, monitoring of CTS also enables hardware handshake.
- Bits 7..3 โ reserved, unused
- Bit 2 โ monitor DSR
- Bit 1 โ monitor CTS, enable hardware handshake
- Bit 0 โ monitor CD
๐ค CMD 38: SETPARITY
This command is available in block as well as in concurrent mode. It selects character translations from ASCII into ATASCII and vice versa, and selects input and output parity. The bits in Aux1 have the following meaning:
- Bit 7 โ reserved, unused
- Bit 6 โ if enabled, a LineFeed is inserted after each generated CR
- Bits 5,4 โ ASCII<->ATASCII translation, see below.
- Bits 3,2 โ input parity
- Bits 1,0 โ output parity
If the character translation is set to 0, EOL is translated to CR (not LF!) and vice versa, and bit 7 is stripped off. If set to 16 (bits = 0,1), additionally non-ASCII characters are not written, resp. replaced by Aux2 on input. ๐
If the parity bits are set to zero, data is read or written โas isโ. This especially implies that parity bits and stop bits of the input data are not stripped off. Furthermore, on output only eight data bits can be generated, unless the upper bits are set to one manually to emulate stop bits. ๐
If the parity bits are set to one (bits = 0,1), odd parity is generated or checked for. This works only for seven or less data bits.
For the parity bits set to two (bits = 1,0), even parity is generated or checked for seven or less data bits.
For parity bits set to three (both bits set, bits = 1,1), the parity bit is stripped off on input, and always set on output (parity = SPACE). โจ
Aux2 of this command specifies a โgarbadge characterโ that gets inserted for full character translation whenever a non-ATASCII character is received. ๐
๐ CMD 40: STARTCONCURRENT
Enters the concurrent mode from block mode. The only way to leave the concurrent mode again is to close and re-open the channel. Aux1 and Aux2 are irrelevant for this command, but IOCBAdr and IOCBLen might provide the location and size of an optional input buffer where incoming data is kept until it is read off. This buffer should better be large for โhigherโ baud rates. If no input buffer is supplied, i.e. IOCBAdr is set to NULL, the handler will provide a short 32 byte input buffer. ๐ซถ
On entering concurrent mode, the input lines specified by the โSETBAUDโ command are monitored once. If the selected lines are not set, an error is generated. The real 850 interface does not provide full hardware handshaking, the emulated 850 does by monitoring CTS. ๐
๐ THE OS ROM EMULATION ๐
The Atari++ emulator provides its own operating system in case no Atari ROM image is available. This makes the emulator self-contained as you don't require to hold any usage rights on the original ROMs to run it. The built-in ROM implements a full Atari XL operating system and tries to be compatible to the XL ROM in most aspects; however, since it is a re-implementation, absolute ROM addresses and implementation details may, and will, differ. The paragraphs below give a brief overview on the ROM features, the subsections discuss the features in more detail. ๐โจ
๐ Built-in FMS (DOS)
okay so the built-in operating system comes with its own file management system, which is a whole different situation from the original Atari ROMs. everyone classically calls this the DOS (Disk Operating System), which is lowkey imprecise but whatever, we've all been doing it. This FMS steps in whenever there's no bootable disk available on bootstrap. Why do we love her? Because she lets you load and save binary images so easily without needing an Atari copyrighted FMS at all. ๐ For the deets, go look at the FMS subsection below.
๐ฆ Parallel Port Support
has been dropped. Periodt. The reason is that Atari++ doesn't emulate any parallel port devices, and also the author literally has no usable documentation about it. So like... nothing to go on, bestie. ๐
โจ The MathPack
is classically not considered part of the operating system, but it's emulated fully here โ with all documented entry points and some undocumented ones the author is aware of. The emulation is complete enough to let BASIC and a ton of other programs operate properly, except that the re-implementation is usually a little bit faster and sometimes considerably faster. ๐
You might also wanna consider the MathPack patch option, which evaluates the mathematical operations on the host CPU and improves the speed beyond what's even achievable with the 6502 implementation. iconic behaviour honestly.
๐ The C: Tape handler
is replaced by a dummy. Not because we're being shady โ it's because Atari++ doesn't emulate the tape device, and the ROM space was required. sorry bestie, she had to go. ๐ซถ
๐ CHARACTER GENERATOR
The international character set at position 0xcc00 and up has been slightly modified:
- Character position 8 (
Ctrl-H) is now the Euro-sign ๐ถ - Character position 96 (
Ctrl-.) is the german sharp-s - The pound sign and the inverted exclamation mark are no longer available
that's the trade, no cap.
โก INTERRUPT HANDLING
The Os NMI handler also checks the ANTIC Reset NMI signal and, if it's detected, jumps indirectly through the vector in location $24e. That vector points to the warmstart Os vector. Unknown NMI sources are ignored, unlike the original Os which handles them as VBIs. ๐
๐ฅ VBI Handler
The built-in Os vertical retrace handler (VBI) does not check whether TRIG3 and its shadow-register coincide. This avoids a couple of deadlock situations in various games that overwrite the shadow register โ so yeah, it's saving the gamers. ๐ฎ VBI handling of 1200XL keyboard features is not present, since atari++ doesn't emulate these keys and the author has no precise documentation about them.
๐ฅ IRQ Handler
The IRQ handler is more streamlined than the original IRQ handler. It also no longer handles any parallel port related interrupts, since they are never generated by the emulator. bye bestie ๐
๐ KERNEL
๐ง Parallel port call-ins
have been replaced by dummies.
๐ง $e48f: BOOT850
This is a new kernel-call that bootstraps the 850 interface handler thru SIO. It should typically be used by a minimal HANDLERS.SYS file that contains nothing but a RUN-vector to this call-in.
๐ง $e45c: SETIRQVECTOR
The SetIRQVector call-in can now also savely install IRQs as well, without requiring the caller to set the interrupt bit of the CPU. no extra steps, we love that for her.
๐ง $e492: RUNDUP
This vector launches the DUP keyboard command processor. The DUP vector at $a,$b points to this address by default. The built-in DUP can be replaced by a custom DUP by changing the reset-resident vector at $3f6. customize away, bestie โจ
๐ง $e498: FMSINIT
This vector initializes the built-in FMS. The Os reset initializes the ROM-based FMS thru this vector if no bootable disk is found.
๐ธ RESET/Bootstrap
๐ Tape bootstrap
Since the built-in Os does not implement a usable tape device, tape bootstrap is no longer supported. The CASINIT vector (0x02/0x03) is, however, emulated properly. so like, the vector is fine, the tape is not ๐
๐ Disk bootstrap
The built-in Os tries to bootstrap the disk as usual, but does not loop forever in case it detects that no disk is inserted in the drive. If a usable boot block is found, the resident FMS is not installed and a disk-based DOS can replace it, as usual.
The resident FMS is launched if either:
- no usable boot block is found,
- no usable disk is found,
- or the user holds down the START key on bootstrap.
An unusable boot block is indicated by a bootstrap address of zero, thus by a blank boot block. Note that START is no longer an indication for tape bootstrap, since there is no tape support. In case the built-in FMS gains control in the boot process, see below in the FMS subsection for further bootstrap activity. ๐
๐ 850 interface bootstrap
In case the disk bootstrap failed because no disk is inserted, the ROM also tries to bootstrap the 850 interface box, since no HANDLERS.SYS file can be loaded then.
๐ SELFTEST
The ROM space occupied by the self-test was required for the DOS command line (the DUP) and is therefore no longer part of the Os. Instead, the following color codes appear on the screen if the power-on tests fail:
Color code RED
The RAM test failed โ a faulty RAM chip has been detected. ๐ญ
Color code PINK
The ROM checksum is faulty. ๐
Color code BLUE
The bootstrap code could not open the initial editor handler.
so if your screen is looking like a whole mood board, that's your diagnostic. read the color, bestie.
๐ SERIAL I/O (SIO)
โญ SIO interrupts
The serial communication is initiated thru the Pokey XMTDONE interrupt. This makes it easier for future extensions to relocate disk buffers under the Os ROM. future-proofing, we love to see it.
โญ Parallel port handling
of SIO communications has been dropped due to lack of ROM space and documentation.
โญ Tape device handling
is no longer provided by SIO, since Atari++ doesn't emulate the tape anyhow. Trying to use the tape thru SIO will now initiate a standard serial communication and will no longer use two-tone modulation. Thus, tapes won't work as expected. ๐ซ
๐ Resident Disk handler (DISKINTERF)
๐ธ Format command
The DISKINTERF vector handles now the enhanced density format command of the 1050 floppy drive correctly. Thus, it supports the 1050 command set fully. slay. ๐
๐ธ Parallel port I/O
thru DISKINTERF via SIO is no longer possible, since SIO does not try to interact with the parallel port any more.
๐ฆ CENTRAL I/O (CIO)
๐ CIO CMD_OPEN
The CIO OPEN command installs now the PUT ONE BYTE vector before calling the OPEN vector of the corresponding handler. This allows the handler to overload this vector in order to implement โburstingโ more easily. Currently, the FMS makes use of this feature to avoid the check whether it was called from the BASIC ROM that incorrectly uses this vector. โจ
๐ CIO HATABS extension
thru the parallel port linked list is not implemented, since the author has no sufficient documentation about its implementation and usage.
๐ CIO handler bootstrap
is no longer supported due to lack of documentation.
๐ THE C: TAPE HANDLER
is only a dummy that returns error conditions on all I/O operations. It only remained in the ROM to allow the H: handler to patch it over. so she's not really there, she's just holding the spot, iykyk. ๐
๐ THE K: KEYBOARD HANDLER
works like its equivalent in the Atari 800XL ROM, except that it does not check for Atari 1200XL function keys. Extended editor keyboard functions are provided to the best knowledge of the author, though. The K: handler respects now the BREAK key correctly. ๐
๐ THE E: EDITOR
The editor device is much more decoupled from the screen handler than in the original ROM โ see also the S: handler section below.
๐ Editor Buzzer
The buzzer is run on a cursor position that depends on the editor margins now. It is also rung on character insertion if characters are likely to be moved out of the screen.
๐ Editor Window
Unlike the original Atari Editor device, the emulated E: handler allows arbitrary high editor windows โ not just four or 24 lines โ if programmed properly. main character energy tbh. โจ
๐ Editor Scrolling
on line insertion or delection does no longer overwrite memory above MEMTOP. thank god honestly.
๐ THE S: SCREEN HANDLER
As mentioned above, the S: handler is decoupled from the E: handler and therefore reacts in certain aspects differently than its original counterpart.
โญ Screen GET/PUT
The S: handler no longer tries to scroll, neither does it respect editor margins. If the put or get commands reach the end of the screen, an out-of-bounds error (error 141) is generated. The only control codes the screen handler handles separately are:
$7d, which clears the screen$9b, which implements a line feed, though dos not scroll
โญ Open Command
The S: open provides more graphic modes than the original. If 64 is added to the graphics mode, then a text window is generated even for the graphic modes 9, 10 and 11. Unlike in the original Os, smooth scrolling works correctly in text windows, even in text windows of the GTIA modes 9 to 11. ๐
โญ DMA/Player-Missile
The S: handler no longer interacts with player/missile graphics and respects the corresponding bits in the DMACTRL shadow register.
โญ Out of memory situations
will be handled more graceful than in the original ROM. ๐ซถ
๐ง THE P: PRINTER HANDLER
The built-in ROM supports the printer to full extend, and no functional changes should hopefully appear. fingers crossed bestie. ๐ค
๐ฅ MATH PACK
The MathPack is not part of the operating system, but historically part of the BASIC. As a consequence, the math pack is does not provide a jump-in table as the operating system, and fixed ROM-addresses must be used.
Atari++ also provides an emulation, or rather a replacement implementing the same routines as the original math ROM. The precision and speed of the re-implementation should be superior to the original ROM implementation. However, it is, in general though, advisable to use the MathPackPatch, which is again a lot faster and still more precise than the re-implementation, because it uses the floating-point math of the host machine. ๐ฆ
so like: replacement is good, MathPackPatch is better, and it's all floating-point-on-the-host-CPU flavoured. obsessed. โจ
โ ๏ธ Real talk bestie: the author tried their absolute best to make this replacement math-pack match the original ROM, but some problems are lowkey expected. BASIC and MAC/65 software should be mostly unaffected, but Atari never gave anyone a jump-in table for the math-pack, so third-party software might be calling routines that were never officially documented and aren't provided by the emulation. That said, this math-pack replacement already contains a bunch of unofficial call-ins that BASIC and other software use. Ngl, numerical results from this implementation might differ from the original because of round-off stuff โ where the re-implementation often serves up better, more precise results. ๐
The replacement math-pack provides the following routines and data:
AFP $d800
Okay so it converts the ATASCII number sitting in the buffer pointed to by "inbuff" ($f3,$f4) at the offset given by "cix" ($f2) into a floating point number in "fr0" ($d4 to $d9). โจ On output, "cix" points at the first character that couldn't be converted. The carry register gets set if no conversion could be conformed at all. And unlike the original? This one operates at ten instead of nine-digits precision and rounds properly if you hand it more than ten digits. Iconic behavior honestly.
FASC $d8e6
Converts the floating point number in "fr0" ($d4 to $d9) into ATASCII in the output buffer at $580 and following. Heads up: "fr0" is destroyed on completion. ๐ The end of the string gets flagged by setting the MSB of the last character, and the final string is pointed to by "inbuff" ($F3,$F4) on exit. Unlike the ROM implementation, this routine is more streamlined and does not overwrite bytes in front of the output buffer โ the output will always start at, and not sometimes in front of, $580. And if you call it at FASC+3, the user can define their own output buffer wherever they like by placing the address into "inbuff". That last part is not available in the original ROM, bestie.
IFP $d9aa
Converts the unsigned integer in "fr0"(lo) and "fr0+1"(hi) into a floating point representation in "fr0" ($d4 to $d9). And unlike in the original ROM, "IFP+4" converts the integer in the registers X(lo) and Y(hi) into floating point. ๐
FPI $d9d2
Converts the floating point number in "fr0" ($d4 to $d9) into a two-byte integer representation, also in "fr0" and "fr0+1", rounded correctly to the nearest integer. If the conversion isn't possible, the carry bit gets set. The original implementation had a couple of issues with overflow and rounding โ those are not reproduced here, so we're good. ๐
ZFR0 $da44
Initializes the "fr0" register ($d4 to $d9) with zero. That's it, that's the vibe. โจ
AF1 $da46
Initializes the six-byte floating point register pointed to by the X register with zero. ๐ซ
ZERORGS $da48
Clears N bytes starting at the zero-page register given by X, where N is given in the Y register. This inofficial call-in is used by Mac/65 and BASIC. ๐ซถ
LOADOUTBUFF $da51
Initializes the "inbuff" zero page registers ($f3 and $f4) to point to the floating point output buffer at $580. Used by BASIC and MAC/65.
FADD $da66
Adds the contents of the floating point register "fr1" ($e0 to $e5) to the floating point register "fr0" ($d4 to $d9). "fr1" will be destroyed. Sets the carry in case the representation overflows, and destroyes "fr1". Unlike the orignal, this routine employes a correct "round to nearest" policy if the output cannot be represented exactly, and it also uses denormalized numbers if the output is very close to zero. ๐ธ
FSUB $da60
Subtracts the contents of the floating point register "fr1" ($e0 to $e5) from the floating point register "fr0" ($d4 to $d9). "fr1" will be destroyed. Otherwise, it works just like the floating point addition and its new round-to-nearest mode. ๐
FMUL $dadb
Multiplies the contents of "fr1" ($e0 to $e5) with "fr0" ($d4 to $d9) and places the result in "fr0". "fr1" will be destroyed. On overflow, the carry flag of the processor will be set. Like addition, this routine uses a smarter round-to-nearest policy, and unlike the original, it has all issues on detecting overflows fixed โ specifically, multiplying two very small numbers will give zero, not an overflow. It'll also handle denormalized numbers correctly, and it's noticably faster than the original. ๐ฅ
FDIV $db28
Divides the contents of "fr0" ($d4 to $d9) by the contents of "fr1" ($e0 to $e5) and places the result in "fr0", destroying "fr1". On overflow or divide by zero, the carry flag will be set. This routine also uses a precise round-to-nearest policy. Unlike the original routine, dividing a small number by a very large number will not create an overflow, but โ as appropriate โ zero. ๐
SKIPBLANKS $dba1
This routine is not officially documented but is nevertheless used by Mac/65. It skips all blank-characters in the input buffer ($f3,$f4) at the offset in "cix" ($f2) and adjusts "cix" such that it points at the first non-blank character. ๐
TESTDIGIT $dbaf
Another inofficial function used by Mac/65 and BASIC. This one tests the character at "inbuff" ($f3,f4) at offset "cix" ($f2) for a valid decimal digit, and returns the numerical value of that digit with the carry flag cleared if possible. Otherwise, on an invalid digit, the carry flag gets set. โจ
FR0TIMESTEN $dbeb
This is also an inofficial vector that multiplies the mantissa of the fr0 floating point register at address $d4 by ten โ i.e. it shifts all digits to the left. It's used by the multiplication and division function, and the Basic++ square root function. ๐
NORMALIZE $dc00
This method is neither officially documented, but used nevertheless by BASIC and Mac/65. It normalizes the floating-point number in "fr0" ($d4 to $d9), eliminating leading zero-digit pairs in the mantissa and adjusting the exponent accordingly. It returns with the carry flag cleared on success and with the carry set on overflow. And unlike the original implemenation, this version leaves near-zero numbers denormalized, and overflows at a decimal exponent of 100, not at 99 as the original. ๐
PLYEVL $dd40
Evaluates the polynomial whose floating point coefficients are pointed to by X(lo) and Y(hi) at the location given by "fr0" ($d4 to $d9). The number of coefficients โ and hence the degree of the polynomial plus one โ is passed in the accumulator on entry. Returns the result in "fr0", and destroys "fr1" ($e0 to $e5), sets the carry flag on overflow. ๐
FLD0R $dd89
Loads "fr0" ($d4 to $d9) with the floating point value pointed to by X(lo) and Y(hi).
FLD0P $dd8d
Loads "fr0" ($d4 to $d9) with the floating point value pointed to by "flptr" ($fc,$fd).
FLD1R $dd98
Loads "fr1" ($e0 to $e5) with the floating point value pointed to by X(lo) and Y(hi).
FLD1P $dd9c
Loads "fr1" ($e0 to $e5) with the floating point value pointed to by "flptr" ($fc,$fd).
FSTOR $dda7
Stores "fr0" ($d4 to $d9) to the six-byte memory buffer pointed to by X(lo) and Y(hi).
FSTOP $ddab
Stores "fr0" ($d4 to $d9) to the six-byte memory buffer pointed to by "flptr" ($fc,$fd).
FMOVE $ddb6
Copies the contents of "fr0" ($d4 t0 $d9) to "fr1" ($e0 to $e5). ๐ฆ
EXP $ddc0
Computes a the exponential function at the location given by "fr0" ($d4 to $d9), destroys the contents of "fr1". Returns with the result in "fr0" and the carry cleared on success, with carry set on overflow. ๐
EXP10 $ddcc
Computes 10 to the power of the number given in "fr0" ($d4 to $d9), destroys the contents of "fr1", returns with the carry set on overflow or the proper result in "fr0". This implementation isn't just faster than the original ROM implementation โ it's also more precise, and in general, nine to ten correct digits can be expected. It also has a couple of issues of the original implementation fixed, namely the exponential of a very negative number yields zero (not an overflow), and the exponential of ten to an integer power is always integer. โจ
BASIC uses this function to compute the exponential via the call-in above, but also to compute the power function (a^b). Unfortunately, due to a bug in BASIC revisions B and C (but not in revision A), BASIC always rounds the result up to the next integer if a and b are integer โ with the side effect that if the result of this method is a tiny little bit too large, the output will be off by one. For example, computing 4^4 results in 256.000002, which is correct to nine places, but which is rounded by BASIC to 257. This is a bug in BASIC and not in this implementation โ the coefficients have been carefully choosen to avoid such situations for lower exponents, i.e. for b=1 to 3, the result will always be correct. Enforcing correct results for higher exponents would have resulted in a major precision loss just to work around old bugs, which was considered inappropriate. ๐ค
FFRAC $de95
This is another call-in that is used by BASIC which is not officially documented. It computes the rational function (x-C)/(x+C) where the value of x is given by the contents of the "fr0" register ($d4 to $d9) and C is stored as a six-byte floating point number pointed to by X(lo) and Y(hi). On exit, the carry flag is set on overflow, and clear on success. Then, the result is given in the "fr0" register. ๐ธ
LOG $decd
Computes the natural logarithm of the number given in "fr0" ($d4 to $d9). Returns with the carry set on overflow, or zero or negative input โ otherwise with the result in "fr0". ๐
LOG10 $ded1
Computes the decadic logarithm (logarithm to the base of ten) of the number given in "fr0" ($d4 to $d9). Returns with the carry set on overflow, negative or zero input, and carry cleared with the proper result in "fr0" otherwise. This method can be expected to be faster and more precise than the original version. ๐ฅ
ONEHALF $df6c
okay so this one is not a call-in, bestie, it's a floating-point constant that BASIC uses for a bunch of stuff, most notably for the SQR function. Its value is 0.5. cute little half, slaying.
ATNCOEFF $dfae
also not a call-in! this is a table of eleven floating point constants, and they represent the coefficients of the minimax-approximation of the arcus tangens over the interval from 0 to 1. BASIC's implementation of the ATN function is the one that uses it. ๐
NEARONE $dfea
part of that table up there, but BASIC also uses it on its own. it's the constant term of the above polynomial, and it also gets used to adjust coefficients outside the interval 0..1 by means of the functional equation of ATN. in an ideal infinite-precision implementation this constant should be exactly one, but because of various round-off errors it's 0.9999999999 in the Atari ROMs. in the emulated ROM, though, its value is 1.0 precisely. โจ
PIOVER4 $dff0
another floating point constant used by BASIC โ this one is the value of Pi divided by four, correct to ten decimal places. it gets used by the ATN function in the BASIC rom. ๐ฅง
๐ THE D: HANDLER ๐
so this handler comes from the now built-in FMS, the one that's used if disk-bootstrap was unsuccessful or got aborted by the user โ see also above, bestie. ๐
the FMS sitting in ROM space is basically a reworked and bugfixed version of Dos 2.XL/XA by the same author, streamlined to fit into the low memory Os area 0xc002 to 0xcbff. that means it gives you 963 free sectors on a standard enhanced density disk while still keeping Dos 2.0S compatibility. and in specific? the VTOC layout is identical. no cap.
it can read Dos 2.5 disks, but it is not write-compatible to Dos 2.5. this route was chosen basically because the author had the Dos 2.XL sources available for obvious reasons, unlike the Dos 2.5 sources. anyway, the following documents the FMS command set:
CMD 3: OPEN
opens a file. the details depend on AUX1 and AUX2. for AUX1 = 0, the following modes are used:
aux1=4โ open for read-onlyaux1=6โ open for directory reading, including the disk nameaux1=7โ open the directory, excluding the disk nameaux1=8โ create/overwrite for write-onlyaux1=9โ open for append write-onlyaux1=12โ open for read and write (update)aux1=13โ create for read, write and append
note that mode 9 does not waste a sector, unlike the Dos 2.0S implementation. mode 12 is the update mode, and it generates an EOF condition in case it's attempted to extend the file over its initial size. mode 13 is new and automatically extends the file over its boundary should a write past the EOF be sent. unlike mode 9, the file pointer is positioned at the start of the file initially. mode 6 also includes a disk title should it be provided.
for AUX2 = 128, things change dramatically. this mode provides full random access to the raw disk without any file management functions; so yeah, this mode allows โrawโ access to disks. file names do not matter here as long as they are syntactically correct, and sectors are always 128 bytes long. the disk is understood as one big sequential file starting at sector one and extending to its last sector. access to sectors is provided by means of the POINT/NOTE commands. the following open modes are available for AUX1 = 128:
aux1=4โ open for read-only. reads raw sectors sequentiallyaux1=8โ create for write-only. writes raw sectors.aux1=12โ open for simulateous raw read and write
CMD 5: GET RECORD
the standard CIO record reading command. reads bytes until the record is full or an EOL is detected. simple, iconic, no notes.
CMD 7: GET CHARACTERS
reads characters into the buffer until either the buffer is full or an EOF condition is reached. the FMS tries to bypass CIO here, i.e. it tries to โburstโ to speed up processing. ๐โ๏ธ๐จ
CMD 9: PUT RECORD
writes bytes to the file/disk until either the buffer becomes empty, and EOL is found in the buffer or an EOF condition is generated.
CMD 11: PUT CHARACTERS
writes characters to the file until the buffer becomes empty or an EOF condition is generated. this command also implies bursting, if possible.
CMD 12: CLOSE
closes the file, writes the last buffer out and updates the directory โ unless the stream is โrawโ.
CMD 13: STATUS
okay this one works a little bit different than under DOS 2.0S and DOS 2.5, where it only checks the validity of a file specification and the availability of a drive. since BASIC never supplies this information to STATUS, this command was actually unuseful in BASIC and never worked as intended. ๐
instead, if the channel is already open, STATUS returns the status of the last CIO operation on this specific channel, which now allows BASIC to check, for example, whether the next GET command will return an EOF by testing against the error code 3. โจ
if the channel is still closed, it works as it did for DOS 2.0S and DOS 2.5: it checks the given filespec for validity, tests wether the given disk is available and readable, and whether the file can be written to. otherwise, appropriate error conditions are generated. if used from BASIC, STATUS should then be rather replaced by a XIO 13 command which supplies a file name.
CMD 32: RENAME
renames files. requires the old filespec, then a comma, and the new target file name. this command may cause several identically named files. such files can be resolved by using the /1 through /9 file specification modifier defined below. alternatively, this command and the next four โ namely DELETE, FIND, LOCK and UNLOCK โ take a non-zero aux2 value which then specifies which of the specific matches to a wildcard is to be renamed, deleted, found, locked or unlocked.
CMD 33: DELETE
delete one or several files on the disk. bye bestie ๐
CMD 34: FIND
resolves a wild card filespec and returns a full file name in the input buffer. this command is used by the command line interpreter (โDUPโ) to resolve wild-cards.
CMD 35: LOCK
prevents a file or several files from getting overwritten by setting their write-protecting bits. ๐
CMD 36: UNLOCK
removes the write-protection lock on a file or several files. ๐
CMD 37: POINT
places the file pointer at a given file/sector position. unfortunately, the FMS doesn't provide simple sequential accessing of files, but rather expects an absolute sector/byte offset in AUX3,AUX4 (sector) and AUX5 (byte), similar to Dos 2.0S.
โ ๏ธ if an invalid write position is specified here, then the disk might get corrupted. only file pointers obtained by a previous NOTE onto the same file should be passed in as arguments here. fr fr, be careful.
unlike under DOS 2.0S and DOS 2.5, POINT also works for files opened in write-only mode, i.e. mode 8, and can there be used to re-position the file pointer to some place in front of the EOF, overwriting data that has already been written. similarly, POINT is very helpful to append to files in the update/append mode 13 when the former EOF position has been recorded by a NOTE, which then works much faster than having the file opened in append mode. the latter has to find the EOF manually, the former will place the file pointer directly at the EOF.
the POINT command is also used for absolute positioning within the disk if the corresponding stream is opened for raw mode, i.e. with AUX2 = 128.
CMD 38: NOTE
returns the current file pointer as sector/byte offset to be used for a future POINT command. AUX3/4 contain the low/high-byte of the sector, AUX5 the sector offset.
CMD 39: INIT
clears and initializes the disk, erasing all files, but not formatting the disk. this is a quick format for disks that have been formatted already. optionally, a disk title can be given behind the device specification. this title will then appear in reverse video on each directory listing. โจ
CMD 40: FIND
similar to CMD 34 to maintain Dos 2.XL compatibility.
CMD 41: BINARY LOAD
loads a binary file from disk, possibly initializing and running the binary. AUX2 specifies whether the loaded file shall be initialized or run:
192โ the file is initialized and run128โ โinit onlyโ64โ just runs, but does not initialize the file0โ neither runs nor initializes the file
note that Atari specified CMD 41 (and not CMD 40) for the binary load command.
CMD 42: FORMAT
formats a disk in various sizes:
- if
AUX1is set to33, then the disk is formatted in single density to707sectors. - for
AUX1set to34, then an enhanced density format is initiated, resulting in a963sector disk. - all other values are reserved.
this command also accepts a disk title.
CMD 43: FORMAT ENHANCED
initiates a standard enhanced density format, independent of AUX1 and AUX2. this also accepts a disk name, similar to the above.
CMD 254: FORMAT ENHANCED
identical to CMD 43. literally the same thing, no notes. ๐
๐ธ FMS FILE SPECS ๐ธ
the built-in FMS defines the following rules for filenames; these rules are very close to those formulated by Dos 2.0S.
- the first character must be an uppercase letter, and all remaining characters must be uppercase letters or digits.
- a file name consists of at most eight characters, and an optional three character extender behind a dot (
โ.โ). - three wild card-characters are understood:
- the question mark
โ?โโ matches one single arbitrary character - the asterisk
โ*โโ matches a sequence of arbitrary characters except the dot - the dash
โ-โโ equivalent to the wild-card sequenceโ*.*โand thus matches any file
- the question mark
...and bestie, there's MORE. The FMS also lets you tack on access mode modifiers to a file name to change what a command actually does. You stick them on behind a slash, /, like this: D:FILE/A. Here's the whole menu of them:
/Aโ opens a file in append mode instead of write mode, so it flips mode 8 โ mode 9. It also switches plain directory mode over to the restricted directory mode that suppresses the disk name, and turns mode 12 into mode 13. Every other combo? Invalid, sorry. This one slaps in the FMS command line next toCOPYwhen you wanna append one file onto another. ๐/Dโ flips the open mode from reading to directory reading, i.e. mode 4 โ mode 6. Super handy in the FMS command line for printing the directory viaCOPY D:-/D,P:./Oโ doesn't touch the open mode at all, it just turns OFF verify writes and uses the faster write-without-verify disk command. Faster writes, but the tradeoff is it might hide write errors on janky disks. ๐ซฃ/Vโ basically the same energy as above, except it enables verify writes./Nโ only matters with theBINARY LOADcommand, and it stops the program from launching right after it loads./1../9โ if you've got several identically named files, this grabs the n-th one. Perfect for picking between files that the Rename command left with the same name. ๐
Ngl, the file spec DOS.SYS is not special to the FMS at all โ unlike DOS 2.0S. It's just a regular file, fr fr. The FMS will never ever try to write itself to disk. So even though the FMS can write a Dos 2.XL disk structure just fine on initialization, those disks won't be bootable without the ROM FMS.
๐ FMS ERROR CODES ๐
The FMS throws these error codes. (Generic SIO errors aren't listed here because those come from the Os kernel, not the FMS.)
- Error 160, IllegalUnit โ the disk unit you asked for isn't available.
- Error 161, TooManyFiles โ too many files open at once, the FMS ran out of buffers.
- Error 162, DiskFull โ no more free space on the disk, bestie.
- Error 164, FileLinkBroken โ the FMS structure is damaged, possibly from an invalid
POINT. - Error 165, FileNameInvalid โ that file name is invalid.
- Error 166, InvalidPoint โ an argument to
POINTwas out of range. - Error 167, FileProtected โ you tried to write to a locked file. Not today. ๐
- Error 169, DirectoryFull โ couldn't create the file because the directory was full.
- Error 170, FileNotFound โ the filespec you gave doesn't exist.
- Error 175, NoBinaryFile โ the file you specified isn't a binary load file.
- Error 176, BadLinkage โ found a bad sector link pointing to sector #0, meaning the disk structure is damaged.
- Error 177, InvalidMode โ the open mode you specified is invalid.
- Error 178, NotADosDisk โ the structure of the inserted disk isn't compatible with Dos 2.++.
โจ THE COMMAND LINE PROCESSOR (DUP) โจ
The built-in FMS also ships a whole disk utility package โ a "DUP" ๐. You fire it up from BASIC with the DOS command, or it just runs automatically if no cart is found inserted.
The command line takes commands kinda like a Linux shell, except way more restrictive. If what you typed is just a device spec โ a one- or two-letter string ending in a colon โ then the active device changes. Otherwise the command line goes hunting for the command as a file on disk, as a binary, and runs it. It does NOT append a file extender, unlike OS/A+ which would always slap .COM on there. The file name is loaded and executed exactly as you entered it. ๐
The full command line, command + arguments, gets dropped into a 128 byte buffer at $580 where the executed binary can find it and parse it itself if it wants. The command line doesn't give you any functions to parse that buffer though.
NOTE: this is not how Dos OS/A+ runs external commands. There just wasn't enough ROM space to implement command line parsing service functions like OS/A+ has. ๐ญ
If the command starts with a double quote, or isn't found on disk, the command line processor tries to find it as an internal command. Here's the lineup. Optional arguments are shown in square brackets โ those brackets are not part of the actual command syntax, just so you know. And filespec means a file specification, optionally with wildcards, optionally with a device spec separated from the file name by a colon. No device name given? Then it uses the currently active device that's sitting in front of the command.
DIR [filespec]โ lists the disk directory. Give it a filespec and only the files matching that filespec get listed.DIRcan't list the directory to any other device though. For that, use theCOPYcommand with a source filespec carrying the/Daccess modifier.DELETE filespecโ deletes the file(s) matching the filespec. Heads up: this one does its job immediately with zero follow-up questions. ๐RENAME filespec,newnameโ renames a file, or several files, to a target filename on the same device. If more than one file matches the wildcard, they ALL get renamed to the same target name. You can pick between identically named files using the/1to/9modifiers, which lets you rename some of them back. ๐ฆLOCK filespecโ marks the file(s) as write-protected. After that, any kind of write operation or deletion is prohibited.UNLOCK filespecโ removes the write protection again. Literally the opposite of the above.CARโ runs the cartridge, if there is one inserted. If there's no cart available and no reset resident program found either, the command processor gets entered again.FORMAT [title]โ formats the specified disk to enhanced density, erasing all its contents. You can throw in an optional disk name here that'll be printed in inverse video when listing the directory contents. ๐CLEAR [title]โ similar to the above, clears the entire disk contents and installs an optional disk name. BUTCLEARonly re-initializes an already formatted disk. Because of that,CLEARis way faster thanFORMATโ it's meant as a quick-format. โกRUN [hexaddress]โ runs a machine code program at the specified address. No address given? Then the previously loaded command gets run, or run again.SAVE filespec,from,to,[[,init],run]โ saves a binary file to disk, starting at the given hex address and going up to the given address. You can optionally give an init and run address too. Oh and btw, you can always append to a file โ and thus extend a binary load file โ using the/Aaccess modifier behind the file name. ๐LOAD filespecโ loads a file from disk but doesn't start it. You can run it later with theRUNcommand, no extra arguments needed.COPY filespec,targetโ copies one or several files from one disk to the same or another disk.COPYfirst reads the file from the source, then waits for you to swap disks. If source and target are the same disk, just hit RETURN; otherwise swap disks first. ThenCOPYwrites the target file, and might ask you to re-insert the source disk if the file's too big to read in one go, or if there's more than one file to copy. ๐
COPY tries to avoid using user RAM contents whenever it can. Application memory that's correctly reserved by setting the Os vector APPMEMHI will be preserved, and BASIC source code will be spared. But not every app sets APPMEMHI correctly โ Mac/65 is one such example. ๐
NEWโ erases user memory and makes that memory available to theCOPYcommand, meaning you'll need to swap disks less often.NEWis also needed to tell some cartridges or application programs that their memory has been overwritten after a copy operation. That's necessary when the program in question doesn't setAPPMEMHIcorrectly.
๐ธ FMS HINTS AND TWEAKS ๐ธ
Sometimes an external command has the same name as an internal one. When that happens, the external command wins โ it gets loaded and the internal one is bypassed. If that's not what you want, put a double quote in front of the command. That skips the external command lookup. ๐
You might've clocked that DIR can't list the directory to anything but the screen. Well, COPY can pull off a similar move using the /D access specifier:
COPY -/D,P:
That prints the contents of the directory by copying it to the printer device โ though it invalidates RAM contents, because of the extra buffering COPY does. ๐ฌ
And you can emulate the LOAD command using the no-run specifier when you just wanna load, not run, an external command. So LOAD foobar and foobar/N are equivalent. โจ
๐ FMS BOOTSTRAP PROCESS ๐
If the FMS gets initiated by the built-in Os, and a disk is found active and usable, these extra bootstrap steps go down:
- FMS Configuration โ the FMS tries to load and execute the binary load file
D:CONFIG.SYS. This file should modify the FMS settings by writing into its configuration area. The FMS then re-allocates buffers according to its new settings. And note: this is the only way to modify FMS parameters, since the FMS is ROM based. ๐ฅ - Handler bootstrap โ next, the FMS tries to load and execute the binary file
D:HANDLERS.SYS. This file should contain the bootstrap code for any additional boot-time handlers that need to be linked into the system. For example, it could load and run the 850 interface box firmware โ easiest by just calling the Os vectorBOOT850,$e48f. ๐ง - Command execution โ last, the FMS runs the traditional
D:AUTORUN.SYSfile. This is a user-defined binary load file that could contain basically anything the user wants. ๐
๐ธ OS EQUATES ๐ธ
okay so the built-in Os is lowkey matching the Atari 800XL ROM's memory map almost beat for beat, with just a few lil glow-ups added. ๐ Heads up bestie: those memory cells the XL operating system set aside for parallel port and tape stuff? They're probably not doing anything anymore. But they stay reserved, fr fr โ future versions of the Atari++ operating system might want them back. ๐
$15FMSTMPโ the FMS uses this for, like, various issues. โจ$16DIRENTRYOFFSETโ the FMS uses this to point into the directory buffer for whichever file it's currently processing.$1aFILECOUNTERโ when a wildcard matches a whole bunch of files and you hit it with a/1to/9access modifier to pick one, this location records your pick. If the FMS should operate on all the matches, this location just stays at$ff.$1bFREEDIRCODEโ keeps the file number times four of the first free directory entry that a new file could move into.$43FMSPTRโ temporary pointer variables for miscellaneous FMS business. This pointer typically points at the directory entry of the file currently being processed.$45DISKBUFFERโ points, inside the FMS, to the VTOC buffer for the disk drive currently being processed.$47FILEBUFFERโ points, inside the FMS, to the file input/output buffer for the file currently being processed.$24eVECNMIโ the Os jumps through this vector when it detects an interrupt on ANTIC's NMI-input pin. That pin is routed to the RESET key on the 400 and 800 machines, and it's just open on the XL and later machines.$2b8OVERRUNFLAGโ the E: handler sets this flag when the line is nearly full and the buzzer should run. ๐$318SCREENSTACKโ traditionally SIO's byte, and the built-in Os does the same. It's also used by the S: and E: handlers to keep the stack pointer around so error handling is easier. ๐ซถ$3f5FMSBOOTFLAGโ specifies the FMS bootstrap modes plus a bunch of other related stuff, as listed right here:- Bit 0 โ if set, the next reset shall signal the cart a coldstart. The command line processor sets this bit when the memory contents get invalidated by the
COPYcommand. - Bit 4 โ if set, the FMS places
MEMLOat the end of its globals instead of at the end of the FMS buffers. User programs โ most notably aCONFIG.SYSfile โ may relocate FMS buffers elsewhere and can then choose to set this bit. Never set by the FMS itself. - Bit 6 โ set if the command processor shall be launched on the next warmstart.
- Bit 7 โ set if the FMS should be initialized on Reset. Note that the FMS no longer requires the DosInit vector.
- Bit 0 โ if set, the next reset shall signal the cart a coldstart. The command line processor sets this bit when the memory contents get invalidated by the
$3f6,$3f7DUPVECTORโ DupVector (hi). This address gets jumped to instead of the cart run vector during a warmstart, if bit 6 of the FmsBootFlag is set. A program that jumps throughDOSVECTOR($a,$b) will set bit 6 of theFMSBOOTFLAG, then cause a reset, which in turn runs the command processor through this vector.
The next addresses are only used if the FMS is initialized. They can be modified from the CONFIG.SYS file to change the FMS parameters when booting. ๐
$70aFMSDRIVEMASKโ contains a bitmask defining which drives should be addressable. A one-bit enables the corresponding disk unit, a zero disables it. Bit #0 enables/disables drive 1, bit #1 controls drive 2, and so on. The default value is3, meaning a two-disk system is supported. Each supported drive requires 128 bytes of additional storage.$709FMSBUFFERSโ the number of file buffers the FMS shall allocate. This controls how many files can be opened at once. The default value is five, so you can open at most five files at once. Each file buffer requires 128 bytes of storage.$779WRITECMDโ the SIO command the FMS shall use for writing sectors. This can be either$50("P") for writing without verify, or$57("W") for writing with verify. It is however suggested to use the file name extenders"/V"and"/O"to switch between verify on and off instead.$70C,$70DDISKBUFFERBASEโ points to the first disk buffer used by the FMS. The"CONFIG.SYS"file may change this base address to point elsewhere, in which case disk buffers will be allocated from this memory address on. If in addition bit 4 ofFMSBOOTFLAGis set, the FMS init routine will neither try to increaseMEMLOto point behind the FMS buffers, but will keep it at the end of its state flags.$712,$713FILEBUFFERBASEโ this pair points to the first file data buffer within the disk buffers. It cannot be adjusted, but is always allocated by the FMS.$700to$7ffFMS STATE FLAGSโ addresses$700-$7ffexcept those above contain FMS state variables that remain undocumented. ๐คซ$800FMS BUFFERSโ FMS buffers for drives and file buffers are allocated from$800up. In the default configuration, they extend up to$a7f, leaving RAM from$a80and up to the user. So the memory footprint of the built-in FMS is much better than for DOS 2.0S. FMS buffers may be relocated by adjustingDISKBUFFERBASEaccordingly, via a suitableCONFIG.SYSfile.
๐ THE BASIC EMULATION ๐
Atari++ includes an emulated Basic ROM, in case an original Atari Basic ROM image is not available. The Basic dialect emulated here closely reassembles the Atari Basic dialect and is to a major degree compatible with it. โจ
Basic++ is, however, quite a bit faster thanks to smarter stack and branch handling, it is heavily bug-fixed, and slightly extended: ๐ฆ
DIR [filenspec]โ this statement lists the directory of the given drive, looking for the files that match the file specification in its argument. For example,
DIR "D2:*.*"
will list all files on the second disk drive. If no filename is given, DIR will list all files on the first disk. The DIR command is compatible both in its syntax and its internal encoding to the same TurboBasic command.
LIST [filespec,][firstline[,[lastline]]โ a second notable extension is that the โlastlineโ argument of the list statement can be dropped while keeping the comma upfront. This instructsLISTto start listing at the line given by the first argument, but continue up to the end of the program. This extension is identical to the extension ofLISTin TurboBasic. For example,
LIST 1000,
will list all lines starting from line 1000 up to the last line.
The remaining extensions are minor and consist mostly of bug-fixes, speed improvements and improvements of the numerical accuracy of the floating point model. They are described in more detail in the Basic++ manual. ๐
๐ THE BUILT-IN MONITOR ๐
Atari++ comes with a build-in mini-monitor that can be helpful for debugging programs, or for finding bugs in the emulator. The following section describes briefly the front-end and the commands of this monitor, assuming that the emulator has been compiled with curses support. Otherwise, the front-end is less user-friendly (or even more user un-friendly than it used to be before, but that is another topic). ๐
๐ ENTERING THE MONITOR ๐
You enter the monitor either by pressing F12 while the emulation is active, by pressing ^C in the shell that launched Atari++, or if the CPU core emulator crashes. That crash could be either due to an instruction that is not implemented, an instruction that would otherwise stop the CPU completely, or an unstable instruction whose function depends on some floating bus signals that are hard or not at all emulatable. Other than that, Atari++ emulates all known stable โextra opcodes some lesser quality programs tend to use. ๐ญ
Another way of entering the monitor is by hitting a break point, or by finishing a single-stepped instruction. ๐ซถ
๐ MONITOR COMMANDS ๐
The monitor is entirely command line driven. Commands are four characters long, non-case sensitive, with a possible abbreviation of one character. Commands furthermore have an optional extension given by a dot (.) and a single additional character. This extender typically modifies the command somewhat, or sets some parameter for the command, as for example the output format. The extender for each command is remembered by the command itself up to the next time the very same command is used. Hence, you won't need to type the same extender every time. Using the question mark "?" as extender lists the available extenders for the command. ๐
Most commands also remember the last address they operated on. If typed without arguments, they silently re-use the last address used. This is handy for disassembling long routines, since you just have to re-type the disassembly command to continue the listing. โญ
๐ง ALGEBRAIC EXPRESSIONS ๐ง
The monitor is capable of evaluating simple algebraic expressions in C syntax containing the basic operators +,-,*,/, the binary operators &,|,^,~, the logical operators ||,&&,! , the comparisons <,<=,>=,==,!= and the shifts <<,>>. The precedence of the operators follows mainly the C syntax, except that priority of the shifts has been โfixedโ to follow more closely the (or at least my) intuition, brackets are supported with their obvious meaning. Furthermore, the contents of the registers are available as the algebraic expressions A,X,Y,P,S,PC. Otherwise, numerical constants are understood in hex (sedecimal) notation. ๐
If a ca65 debug file is loaded (see ENVI.S below), then labels or equates can also be used in expressions; they are then substituted by the value they have been assigned to in the debug file. ๐
A nice gymmick are the indirection operators [],[].b,[].w with the first two being equivalent. They evaluate their contents as an address, and then return the contents of this (emulator) address as their value. The first two are byte versions reading a single byte, the latter is a word version that reads two bytes in little-endian notation to form a sixteen bit integer. ๐ฆ
๐ COMMAND DESCRIPTION ๐
The following commands are available in the monitor:
HELP=?โ this command prints a command summary. ๐
๐ DUMP=D [expr] โ extenders: A, S, V
Dumps the memory contents at the address you hand it, or just keeps going from wherever the last dump stopped. Bestie it's literally the "show me the bytes" button ๐
Aโ switches to mixed hex-ATASCII output, emulating inverse video as much as it possibly can thru curses โจSโ uses hex-ANTIC screen code dumpsVโ doesn't dump anything at all, it's just here to set the number of lines dumped in one go
โ๏ธ EDIT=E [expr] โ extenders: X, D, A, S, I
Edits memory starting at the given address, in hex, decimal, ATASCII or Antic Screen codes respectively. Pick your flavour ๐
For hex and decimal input, memory contents are lines separated by blanks, and the input is aborted by an empty line โ i.e. by just pressing RETURN. No drama, just vibes.
For ATASCII and screen code editing, the text you type as input gets placed directly into the memory of the Atari, possibly first converting to the target format.
Iโ doesn't edit any memory at all, it just toggles the seventh bit of the ATASCII resp. screen code entries on or off ๐ฅ
๐ง FILL=L addr size โ extenders: X, D, A, S, I
Fills the given memory range โ base address plus size, that's the whole vibe โ with a byte pattern. You'll get prompted for the fill pattern separately in a second stage, so don't panic:
Xโ byte pattern is given as a space-separated list of hexadecimal (sedecimal) byte valuesDโ the pattern is given in decimal notation insteadAโ lets you enter the bytes as ATASCII codesSโ last but not least, encodes the pattern in the ANTIC screen codes
The I extender toggles the seventh bit of the entered ATASCII or screen code pattern on or off. Its setting is ignored for hex or decimal input, so don't even worry about it there ๐
๐ MOVE=M from to size โ extenders: S, C, A
Moves a memory block of the given size from the start location to the target location. Source and target may overlap โ and no cap, the move command is smart enough to copy memory blocks correctly in all circumstances ๐ซถ
Sโ performs a simple memory copy operation within the current address space, no matter which one has been selected by theENVIcommand (see below)Cโ moves bytes from the selected address space into the address space as seen from the 6502. This is how you copy data from the ANTIC space to the CPU space โจAโ works in the reverse direction by always writing into the ANTIC space
๐ FIND=F [expr] โ extenders: X, D, A, S, I, V
Scans the memory starting at the given location for a byte pattern, possibly filtering that pattern thru a mask. You get prompted first for the byte string to look for, then for a possible mask โ which must either be left blank or be exactly as long as the pattern you entered first. If you leave it blank, the byte string in memory has to match precisely. Otherwise, only the one-bits in the mask are significant, and all zero bits in the mask are not compared against the search pattern.
This lets you do things like scanning for text in non-case-sensitive mode: just set all pattern bytes to 5F for ignoring case and inverse video bits. Iconic behaviour honestly ๐
The extenders work similar to the extenders of the EDIT or FILL commands:
Xโ expects hexadecimal inputDโ requests decimal inputAโ allows ATASCII patternsSโ screen code patterns
The pattern mask, however, is always given in hexadecimal notation. As always, the I extender toggles the seventh bit on or off for the A and S extenders. Last but not least, the V extender defines the maximal number of matches that will be printed before the search is aborted ๐ธ
๐งฎ EVAL== expr โ takes no extenders
Evaluates its argument and prints the result on the screen. Math girlies rise up ๐
๐ช SKTB=K [expr]
Prints a stack traceback, optionally starting at the given stack address. For this option, the monitor will find the locations from which the current routine has been called. The locations of the JSR instructions are printed on the screen ๐ฆ
๐ BRKP=B [expr] โ extenders: S, C, D, E, A, L, V, W
Controls breakpoints. Once a breakpoint is hit, and the breakpoint is enabled, the monitor is re-entered. Breakpoints can be set in either RAM or ROM. They do not alter the memory at all โ they're rather emulated directly in the CPU core. Hence, they cannot interact with software reading or interpreting the code. Sneaky in the best way ๐
BRKP.Sโ installs and activates a breakpoint at the address given by its argumentBRKP.Cโ removes it againDโ disables breakpoints that have been set beforeEโ enables breakpoints that have been set before
A disabled breakpoint is temporarily turned off, but remembered, and can be turned on later on. No thoughts, just stored state โจ
VandWโ install watch points. Unlike regular break points, the trapping condition is not execution of an instruction at a specific location, but the access of a specific memory address ๐BRKP.Wโ installs a watch point, i.e. the monitor is entered as soon as a program tries to write to the target address. Reading does not trigger it. Watch points can be disabled and removed as all other break points.BRKP.Vโ installs a read/write watch point that, unlike the above, also reacts on read accesses to its target address.Aโ removes all breakpoints at onceLโ lists all breakpoints and their status, i.e. whether they are disabled or enabled
๐บ DLST=A [expr] โ extenders: L, S, V
Displays the antic Display List and the ANTIC status.
Lโ prints a disassembly of the ANTIC program, or short the Display List. Useful for getting an idea how the screen is generated ๐Sโ prints the contents of the ANTIC register set, for example to find the start address of the display listVโ sets the number of lines the ANTIC disassembler prints in one go
๐ง UNAS=U [expr] โ extenders: L, V
This is the 6502 disassembler.
Lโ does exactly this: it disassembles at the address given by its argument. The disassembler knows all "extra instructions" of the 6502 and prints them as four character rather than three character opcodes ๐
If a ca65 debug file has been (see ENVI.S below), then the disassembler automatically substitutes numeric values with the constants, labels and equates recorded in the debug file. Fancy fr fr ๐
Vโ sets the number of lines the disassembler prints at a time
๐ RSET=P โ extenders: W, C, I
Various reset commands.
Wโ warm-starts the emulatorCโ runs into a coldstart
Both instructions also leave the monitor, as its full working environment is reset as well. If you need to debug instructions directly following the cold-start sequence, consider using the -traceonreset on command line switch ๐
Note that the warm-reset really holds the reset signal of the CPU. This is unlike the Reset Console Key on the Atari 800 and 400 models work; they just raise a special Antic NMI signal and leave it to the Os to detect this signal and jump to the reset vector. This kind of reset is reached with the I extender, though note that the detection of this NMI interrupt has been removed in Os ROM of the XL and XE models.
๐ช EXIT=X โ no extenders
Takes no arguments and no extenders and leaves the emulator immediately. Bye bestie ๐ญ๐จ
โถ๏ธ GOPG=G โ extenders: P, U, M
Takes no arguments and re-starts the emulation at the current program counter value for the P extender. Hence, this leaves the monitor and continues emulation. Let's goooo ๐ฅ
Mโ the emulation also continues, but the configuration menu is entered as soon as possible after leaving the monitor, as if F1 has been pressed. This may take as long as a vertical retrace of the emulated screen, and some code might have been run when the menu is entered.Uโ runs the program until the stack pointer gets larger than its current value. Useful to terminate a current subroutine call and return to the calling function immediately ๐
๐ STEP=Z โ extenders: S, I
Single step thru a program.
Sโ the simple interface is used and, similar to theGOPGcommand, the program is run, but the monitor is re-entered immediately after execution of the command under the PC, printing the command that was executed last. Most useful for debugging purposes and single-stepping thru critical sections of a program ๐Iโ a full-screen graphical debugger is entered, provided the curses library was available at compile time. If so, a full screen of disassembled code is printed and the monitor waits for further commands. TheZkey single steps then, theNkey works similar to theNEXTcommand (see below) and steps over subroutines and loops, theGkey re-starts the program and leaves the monitor, theBkey sets a break point at the current program location and, finally, theUcommand runs the emulated CPU until the stack pointer is increased, thus usually up to the end of the current sub-program ๐ฆ
โญ๏ธ NEXT=N โ no extenders
Similar to STEP though this command does not step into subroutines. For any operation that places data onto the hardware stack, this command will run the program up to the location where the data is again popped from the stack; if the current instruction is not a JSR instruction, then the emulator is run until the program counter of the emulated CPU gets larger than its current value. This is for example useful to complete a larger loop with a backwards branch at its end by just one monitor command. One command, whole loop handled, we love efficiency โจ
๐ STAT=T [comp] โ extenders: L, S
Prints status information about various system components, including internal hardware register sets, port settings and configuration.
Lโ lists all system components for which a status information is availableSโSTAT.Sfollowed by the name of this component prints the status of the mentioned component ๐
SETR=S register=exprโ no extenders, bestie. This one yeets a value into a CPU register, and the value comes from an expression. The syntax is lowkey non-standard because it's meant to be convenient: the register and the thing you want in it are separated by an equals sign, NOT by a blank. So for exampleSETR A=ffwould set the contents of the accumulator to 255=0xff. ๐REGS=Rโ no extenders. Shows you what's inside the CPU in a cute little brief listing. And honestly? This command is ideal for theSPLTcommand we're about to talk about. Iconic combo fr fr. โจSPLT=/ [cmds]โ extenders:C,S. Okay so this command is special-special, because it doesn't actually do a direct thing to the emulation components โ it modifies how the monitor itself behaves. TheSextender splits off the top part of the monitor output window and prints the output of whatever commands follow theSPLTcommand up there. Example:SPLT.S Rwould continuously display the register dump of the 6502 CPU on top of the screen. ๐ฆ
You can run several commands at once by separating them with a colon. The split-off output gets updated on every command, which makes screen splitting literally the perfect feature for single stepping and debugging. The C extender cleans and removes that split-off part of the screen again. Bye bestie ๐
ENVI=V [value]โ extenders:A,L,S,C. This controls various (currently one) monitor environment settings. Let's break it down: ๐Aโ this extender controls the view onto the memory. Since the 130XE offers 128K of memory that can be selectively banked for the CPU and for ANTIC, it matters whether the memory is seen by the CPU or by ANTIC, because both may have selected different banks for it. This environment switch toggles the monitor's view onto the memory as either coming from ANTIC or from the CPU.Lโ this extender expects a file name as its argument. The status of the emulated CPU then gets logged into that file, including the register set and the timing information, i.e. horizontal and vertical beam position. โ ๏ธ Heads up: this file may grow very fast and becomes huge shortly. To disable logging, supply an empty file name.Sโ this extender loads a debug file into the monitor, which defines labels, equates and constants. This info gets used by the disassembler and the expression evaluator; the former substitutes numerical values by their label names and hence makes the output of the disassembler more readable, the latter also accepts labels and equates as input and replaces them by their value. This environment setting accepts files in the "debugfile" format generated by theca65assembler. They are created with the--dbgfilecommand line option of the assembler. TheENVI.Scommand takes a single argument, namely the file name of the debug file to be parsed. Information in this file is then added to the internal label database of the monitor. ๐Cโ this extender clears the internal label database, i.e. it forgets all label, equate and constant names that have been defined by anENVI.Scommand before. Memory wipe, but make it monitor edition. ๐ง
PROF=Oโ extenders:S,L,C,X. This monitor command controls the built-in profiler, letting you find performance bottlenecks in machine language programs running on the emulated 6502. ๐ฅSโ starts recording profile information. After issuing this command, return to the emulator withGOPGand start and/or continue execution of the program you want to profile. Re-enter the monitor any time you want to access the collected profile data.Lโ lists the execution counts per memory, sorted in descending order. The first column of the profiler output lists the memory location, in hex or symbolic form, at which the profiled instruction was recorded. The next column shows the absolute count of how often that location was accessed. The last column lists the percentage of how often the listed instruction has been executed compared to the overall instruction count collected by the profiler. If several consecutive instructions have exactly the same hit-count, these instructions are not listed separately โ only the first instruction of the instruction block is shown. Note that this command extender lists instruction hit counts, i.e. it performs a coverage analysis, and not a cycle count analysis. ๐Cโ lists the cumulative execution time of subroutines in cycles, listed in descending frequencies. Unlike the output of theLextender, this list shows the total number of cycles the CPU required to execute a subroutine, together with all the children it called. It sorts the output by cycle count, with the function taking the longest time on top. This is typically the main program. The percentage of time the code spent in a subroutine is also shown.Xโ this extender stops the profiler and clears the profiler database. Rip profiler data, you served well ๐
๐ FILES ๐
/etc/atari++/atari++.confโ The system global configuration files~/.atari++.confโ The user specific configuration file./.atari++.confโ The directory specific configuration file.
๐ ENVIRONMENT VARIABLES ๐
No emulator specific variables. Atari++ is controlled completely by its configuration files and command line arguments. That's it, that's the whole section, no cap. ๐
๐ CREDITS ๐
Shoutout time, because none of this happened alone:
- David Firth for his Atari800 emulator. Atari++ is not based on this earlier work, though influenced. Atari++ was entirely and completely rewritten from scratch, in C++, avoiding some of the constructional difficulties of David's work. Especially, the way how graphics output is constructed and how player/missile graphic priorities are generated is quite different from his implementation.
- Ron Fries for the Pokey emulation routine that got used in early releases of the Atari800 emulator. The strategy that has been utilized for sound build-up has been used in the pokey emulation of this emulator as well, though the implementation details are a bit different and the overall quality of the sound emulation has been improved heavily. Specifically, high-pass filters, sound muting and anti-aliasing are new to the emulation model. ๐
- Jean-loup Gailly and Mark Adler for the Z compression library that gets used if available for
.gzcompressed disk images. - Sam Lantinga and the SDL group for the Simple DirectMedia Layer library, or short, SDL, that offers one of the possible front-ends of the Atari++ emulator if it is available.
- Jindroush and the Atari Cartridge Dumping project for providing insight into the details of the cart emulation. Specifically, SDX and XEGS cart emulation would have been impossible without him. ๐ฎ
- Petr Stehlik and the remaining atari800 team for cooperation and for working out the licencing conditions of this emulator. Specifically, I thank Petr for keeping cool in the hot days of working out all the details of making this project available.
- Andreas Magenheimer and the ABBUC team for providing some hardware insight that was otherwise not available. Specifically, emulation of various bank switching logics is due to ABBUC.
- Jason Duerstock's for its analyzation of the RT8 cartridge. Unfortunately, something seems to be still not quite right with it. The current implementation in Atari++ uses a somewhat different route how the register assignment might work. This is all an educated guess, though. ๐
- B. Watson for keeping pushing me to re-implement the math-pack; it's been done, now, providing a full free implementation of the Atari operating system. โจ
- Konrad Kokoszkiewicz for finding and fixing many bugs in the emulation of floppy disks. Part of the "speedy" comments were broken or potentially mis-interpreted, and floppy sizes weren't detected and supported correctly under all circumstances. Thanks, folks!
- Ralph "pps" for redesigning the Atari++ home page and hosting the whole project. Unfortunately, my employer can no longer host it when I moved.
- "Phaeron" for documenting many undocumented chipset and CPU features and for answering all my questions. Many of the improvements made in release 1.70 are due to his work. ๐
๐ REFERENCES ๐
- DE RE ATARI โ by John Eckstrom, Michael A. Eckberg, Gus Makreas, Lane Winner and Elizabeth Hernaton.
- Das Atari Profibuch โ by Julian Reschke and Andreas Wiethoff, Sybex, 1985.
- 6502 Assembly Language Programming โ by Lance A. Leventhal, McGraw-Hill, 1979.
- Atari Technical Documentation โ from The Atari Historical Society at www.atari-history.com
- Your Atari Computer โ by Lon Pool, Martin McNiff & Steven Cook, McGraw-Hill, 1982. German translation "Mein Atari Computer" by te-wi, 1983.
โ๏ธ AUTHOR โ๏ธ
Thomas Richter (thor@math.tu-berlin.de)
๐ SEE ALSO ๐
An Atari800.
and that's the whole page bestie, we made it to the end ๐ซถ This gorgeous thing is the atari++ Emulator manual, atari++(6), and that footer energy? Iconic. Periodt. ๐๐ธ๐ฆ
๐ฆ where this page comes from
- fedora 43: atari++ 1.85-9.fc43 ยท TPL-1.0
- fedora 44: atari++ 1.85-11.fc44 ยท TPL-1.0
- nixos 26.05: atari++ 1.85
- nixpkgs unstable: atari++ 1.85
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms