Computer
Texas Instruments TI-99 / 4a is almost unknown outside the United States, but it was very popular there (produced more than two million cars). Although this computer was created as a home one, an essential feature (which largely determined its architecture, and then its fate) was that it was based on the already existing serious mini-computer
TI-990 , assembled on conventional TTL logic. In fact, the TMS9900 microprocessor in the TI99 / 4A computer is an implementation of the TI-990, but in the form of a chip. The TI-990 was released in 1975, and the TMS9900 in 1976.

Thus, TI99 / 4a (in 1979 a slightly simpler TI-99/4 was released, and in 1981 already TI-99 / 4a) inherited an extremely strange architecture for home computers. First, the TMS9900 microprocessor in it is 16-bit - with an honest 16-bit data bus (this is in the late 1970s!). Secondly, there are no registers on the chip (except for PCs, flags, and the WP “register” pointer). What can be called registers is in a separate chip of 16-bit static RAM of 256 bytes in size and can be addressed simultaneously as a memory and (first 16 words) as registers R0..R15. This is called "scratchpad".
There is no hardware stack; instead, saving values ​​when calling subprograms is done by changing the WP register start pointer in this same RAM (resembles register windows in Sparcs). In ancestor (TI-990), this was also used to switch context when implementing multitasking.
Although the clock frequency of the TMS9900 is 3 MHz, the instructions take quite a lot of clock cycles - no less than 8. At the same time, even multiplication and division are implemented (124 cycles).

Everything, except for the processor, alas, is more ascetic. In addition to the tiny static RAM mentioned, there is also video memory - 16kb of slow 8-bit DRAM, which is accessed via a video controller.
In other words, without additional peripherals, the TI99 / 4A is a 16-bit computer with 256 bytes of RAM, built-in BASIC ROMs and programs on cartridges (up to 8kB of honestly addressable ROM or more, with different tricks).
')
It’s impossible to load a normal program into a bare computer even from a cassette. There is no RAM for this (256 bytes are not counted, and the rest is video memory).
Therefore, the minimum adequate configuration of the computer is a PEB (Peripheral Expansion Box) - a special large basket for expansion cards, a drive and a 32kb memory expansion. Or NanoPEB - modern device, including all of the above.
For PEB / NanoPEB, you also need an Editor / Assembler cartridge (without which you can download and run only programs in Basic and which at the same time contains the above-mentioned additional 32kb of RAM).

The TMS9918 video controller (also used in MSX and ColecoVision) supports graphic (256x192, 15 colors) and text modes, allows changing the character generator, can output simultaneously 32 hardware sprites 8x8 and 16x16 (however, no more than four pieces can be in one line at a time).
The sound is output via the TMS9919 (its analog, SN76489, was used in IBM PCjr, BBC Micro, ColecoVision, some Sega consoles):
4 channels (three rectangle generators and one noise), 16 volume levels.
It is believed that such an uneven architecture in terms of digit capacity and in some places turned out to be due to the fact that the 8-bit version of the TMS9900 processor (TMS9985) was not ready in time.
As for software, TI99 / 4A was intended for educational purposes (in fact, as opposed to Atari and Commodore). In conjunction with the oddities of the architecture described above, this led to the fact that there are very few good games on it (if any). The fact that the computer was distributed exclusively in the United States, added to this the absence of the demoscene (my intro 99tro seemed to be the second on this platform).
MODERN CONDITION OF AFFAIRS
As already mentioned, with bare TI99 / 4a there is little that can be done, except to start something from the cartridges (if any). The PEB extension basket required for normal operation is quite expensive and takes up a lot of space. Since historically it turned out that all serious development and in general any actions with TI were tied to that very PEB, modern fans of the machine followed the path of its emulation (no one seemed to bother with the ROM cartridge emulator).
A modern substitute for PEB is
NanoPEB . With some patience, it can be found on ebay or at individual sellers for 50 ... 80e.
This device is plugged into the right computer port (the same as the speech synthesizer. Including you can plug it in through the synthesizer) and emulate 32kb of additional RAM, three drives (on the CompactFlash card) and an RS-232 port.
There is also a CF7 + device, in which everything is the same, but instead of RS-232 there is a parallel port of Centronics.
In itself, the presence of NanoPEB allows you to download only programs in BASIC (and from the standard TI BASIC it is impossible to start the program in machine codes, except for very dirty and nontrivial hacks).
Therefore, an Editor / Assembler (EA) cartridge stuck to the upper port is absolutely necessary. With it, you can already download and run normal programs. The cartridge is also searched on ebay. It seems to be, instead, you can use the cartridge Extended Basic (XB).
To transfer programs to a CompactFlash card, you must use special utilities. The most popular is ti99dir (under Windows).
It is worth mentioning the project
F18A - the implementation of the video controller TMS9918A on the FPGA, with a number of additions. Those. the video chip in the usual TI-99 / 4a is replaced with a new one, with all the old software going as before, but it becomes possible to display the image on a VGA monitor, install previously unavailable video modes, etc.
DEVELOPMENT
In addition to the Basic programs, about which we will not speak, there are two main formats in which the program can be represented in machine codes - for loading from disk through the Editor / Assembler and for the cartridge.
Files uploaded through EA are called EA3 (because in Editor / Assembler you need to select the third menu item “LOAD AND RUN” to load them). They can run in any area of ​​memory (i.e., EA will link when loaded). For the emulator, such files are stored on a disk image (.DSK) and are in Dis / Fix 80 format.
Also, less often, there may be memory image files called EA5 (loaded into EA by selecting the fifth menu item - “RUN PROGRAM FILE”). These are already linked files attached to memory addresses. The emulator is also stored in disk images as “Program”.
Loading a program from a disk in codes necessarily requires an Editor / Assembler cartridge (or equivalent).
The programs for cartridges are tightly bound to addresses and are simply a binary that is stitched into ROM (for emulators, this is the .RPK format, less often - .BIN).
There are two significantly different approaches to writing programs in assembly language. The first is the use of so-called. GPL language. This is somewhere between Extended Basic (XB) and Assembler, both in performance and in features. Those. for all of the intensively used subroutines existing in the ROM and, importantly, should be included interrupts.
The second option - the assembler, which will be discussed.
The main unusualness of the TI-99 / 4A, in fact, in the processor TMS9900. From most processors that were used in home computers of the time, it is distinguished by the following:
Physically, there are only three registers in the processor - ST (flags), PC (command pointer) and WP (workspace pointer). Registers R0-R15 are in static RAM outside the chip. The address from which they start is stored in the WP register and can be changed. It is usually set to> 8300 (the sign ">" means a hexadecimal system, the sign ":" - binary).
From> 8300 to> 83FF there are 256 bytes of static 16-bit RAM called “scratchpad”.
Working with it is about 2 times faster than with the rest of the dynamic 8-bit (standard extension 32kb).
There are many addressing modes, and with one command you can, for example, transfer a value from a memory cell to another, changing it at the same time.
There is no stack in the processor - it is supposed to use the mapping of registers to any memory area using the LWPI addr command to save and restore the context.
The subprograms are called by the BL
ADDR command, which writes the following address to the R11 register. Accordingly, B * R11 (also known as RT) is used for return. There is also a BLWP that also preserves the workspace in addition to the return address (but it is also slow).
Usually, first of all, turn off all interrupts and set the beginning of the registers to the beginning of the static RAM. Therefore, the preparation of the program looks like this:
DEF START WRKSP EQU >8300 START LIMI 0 LWPI WRKSP ... * SOME CODE HERE END START
Because of this register architecture, programming features appear. Namely:
1. Registers can be addressed not only as R1, R2, etc., but (since they are in the address space) and as memory cells. This, in particular, allows you to work separately with the lower and upper bytes of the register, which for this purpose are given in advance by constants:
ws0 equ >8300 ; Workspace 0 ; Register direct low-byte access R0L equ ws0+1 ; Workspace 0 R0 low byte R1L equ ws0+3 ; Workspace 0 R1 low byte R2L equ ws0+5 ; Workspace 0 R2 low byte
However, it is clear that it is far from always in the command that you can simply replace the register with a memory (for this command, the addressing mode you just may not have)
On the other hand, it is still necessary, because there are few commands working with register halves (MOVB, SWPB, AB, SB, some logic).
Of course, regardless of the current workspace installed, there is always access to any register in any workspace (at the corresponding address in memory).
2. Since there is no stack (sometimes, however, it is simulated programmatically), saving and restoring registers is done by switching the workspace. If you use it intensively, the available 256 bytes of fast SRAM will end quickly - they are always lacking.
To show what the code looks like for the TMS9900, a small example is Hello World:
DEF START WRKSP EQU >8300 VDPWD EQU >8C00 * VDP RAM write data VDPWA EQU >8C02 * VDP RAM read/write address START LIMI 0 * disable interrupts LWPI WRKSP * set default workspace * set VDP RAM start address (low and high byte) LI R0,>0000 ORI R0,>4000 SWPB R0 MOVB R0,@VDPWA SWPB R0 MOVB R0,@VDPWA LI R1,HELLOWORLD * ascii string address LI R2,12 * total chars NEXTCHAR MOVB *R1+,@VDPWD * put next char on screen DEC R2 JNE NEXTCHAR LOOPBACK JMP LOOPBACK * stop and do nothing HELLOWORLD TEXT 'HELLO WORLD!' * string data BYTE 0 END START
This is a modern (not quite traditional) TMS9900 assembler. In the original, in addition to the absence of colons after the labels, the registers were not written as R with a number, but as a simple number. Those. LI 4.5 and MOV 7.8 in the old assembler are LI R4.5 and MOV R7, R8 in the new one.
As it is easy to see, this did not add much readability, so now they write R (although, even modern assemblers understand the old version of the record). Some people, however, interfere with both syntaxes. As a result, in the same source code one can find a number of SLA R5.0 mnemonics (shift R5 to the left by the number of bits from the register R0) and SLA R5.1 (shift R5 to the left by _ one _ digit).
Some (medical :) interest is the command X, which executes the instruction, the code of which is transmitted to it as a parameter.
; B *R11 LI R9,>045B ; B *R11 X R9 ; LI R1,>1234 LI R0,>0201 ; LI R1,xxx X R0 DATA >1234 ; xxx (>1234)
It is believed that X can be used for debugging purposes, as well as for navigating through tables. Well and in any situations where the self-modifying code is necessary.
MEMORY CARD
> 0000 -----------
Console ROM
> 2000 -----------
Low memory expansion
> 4000 -----------
Peripheral cards ROM
> 6000 -----------
Cartridge ROM / RAM
> 8000 -----------
Scratchpad RAM memory mapped devices
(C> 8300 to> 83FF is static RAM of 256 bytes.
Processor registers are most often displayed starting from> 8300. C> 8400 to> 9C02 addresses for access to video, sound, synthesizer, GROM)
> A000 -----------
High memory expansion
(standard RAM expansion is 32kb. C> A000 usually starts a typical disk-loading program)
...
> FFFF
As for the ROM, the TI-99 / 4a uses the so-called GROM. They are not displayed entirely in the address space of the processor, and the data is accessed sequentially — the starting address of the data in the GROM is entered at a special address and then the data is read from there at another special address. At the same time, the current address of the GROM data is increased automatically, with each reading.
Printing character strings from GROM
li r0, >0874 ; starting GROM address of small character set GROMSC movb r0,@GROMWA ; set GROM read pointer to address 06B0 (high part) nop ; wait a beat (not sure if necessary) movb @WR0LB,@GROMWA ; set GROM read pointer to address 06B0 (low part) li r0,>0000+(8*32*8) ; VDP Pattern Table start address movb @R0L,@vdpwa ; Send low byte of VDP RAM write address ori r0,>4000 ; Set read/write bits 14 and 15 to write (01) movb r0,@vdpwa ; Send high byte of VDP RAM write address li r1,GROMRD li r2,32 nextchar: movb *r1,@vdpwd movb *r1,@vdpwd movb *r1,@vdpwd movb *r1,@vdpwd movb *r1,@vdpwd movb *r1,@vdpwd movb *r1,@vdpwd ; movb *r1,@vdpwd clr @vdpwd ; skip one byte dec r2 jne nextchar
GRAPHICS
To display graphics and text, the video chip VDP TMS9918a is installed in the TI-99 / 4a, which is also used in
MSX1 and
ColecoVision .
VDP allows you to display graphics with a resolution of 256x192 in 15 not very good colors (+1 transparent, through which the background shines) and single-color sprites - 32 pieces in one size 8x8 or 16x16 with a significant limitation: no more than 4 sprites on one line.
In VDP 16kb DRAM and it is distributed between graphics (text), colors and sprites.
Video memory is not displayed in the address space of the processor. To write to it, you must first write to the specific address the starting address in the video memory, which will be recorded, and then write the necessary values ​​in a row to another address (one). At the same time, each next value will be in video memory at an increasing address by one.
Depending on the video mode and memory allocation, you can choose the best one - from the point of view of convenience of addressing, memory used and the number of colors (in a pixel block) mode. At its core, all modes - text. In the sense that in all cases there is the concept of “characters” (characters) that can be placed in different places on the screen and which can be changed. But, since it is possible to reprogram characters so that their appearance matches their code, then in fact the mode is already “graphic”. However, this is typical of many video controllers of the 1980s. Even in a relatively modern VGA there was such an opportunity (the author used it to implement a fast 640x400 mode with a separate memory for colors).
Most often, TI uses Graphic Mode I (the computer turns on in this mode when it is turned on and initialized). In it you can set two colors (background and image) on the 8x8 block. Total blocks 32x24. The only advantage of this mode is the relatively high color change rate.
There is also Multicolor mode - a graphics mode with a resolution of 64x48, where each large pixel is given a color (but at this resolution, except for drawing some kind of plasma or ANSI art) and a pair of purely text modes of 40x24 characters - color and monochrome.
The most powerful and interesting mode in VDP is the so-called Graphic Mode II (aka “bitmap mode”). This mode allows you to use two colors (background and image) inside an 8x1 pixel block. In other words - 2 colors for every 8 horizontal pixels. Unfortunately, the order of the blocks (which are pixels, their colors) is extremely inconvenient for everything except the output of characters - bytes go from top to bottom 0-8, then the next to the right again from top to bottom 8-15, etc. to the right edge. Then everything repeats again from left to right.
When setting the mode, addresses are also set for attributes (Color Table), bitmap (Pattern), order of the characters that form blocks for the Namemap, data for Sprites data and Sprites Attributes. Addresses can be set not any - there are just several options that should be chosen so that in the end, without any overlaps, all 16384 bytes of video memory are rationally used. For example, for my intro "99tro" I allocated the memory like this (Graphics Mode II):
> 0000 -> 1800 Pattern table - 6144 bytes (> 1800)
> 1800 -> 2000 Sprite patterns - 64 sprites x 32 bytes = 2048 bytes (> 800)
> 2000 -> 3800 Color table - 6144 bytes (> 1800)
> 3800 -> 3b00 Name table - 768 bytes (> 300)
> 3b00 -> 3b80 Sprite attrs = 32 sprites x 4 bytes = 128 bytes (> 80)
Sprites can be in two sizes - 8x8 or 16x16 (all sprites switch at once) and you can additionally stretch them (all at once) twice.
The total number of sprites is displayed simultaneously on the screen 32 (but not more than 4 in one line). At the same time, 2k of memory for Sprite patterns is enough for two sets of 32 sprites 16x16 each.
Individually for each sprite, you can set the following parameters (via the Sprite attrubutes area, for each byte in the series):
0 - vertical coordinate (-32 - 191)
1 - horizontal coordinate (0-255). 255 - sprite for the right edge of the screen.
2 - pointer to the place where to get the pattern (in the Sprites patterns)
3 - bits 4-7 define color, bit 0 - early clock (shifts the sprite horizontally 32 pixels to the left)
The lack of direct addressing of video memory in combination with its unsuccessful organization and the absence of transfer commands in the processor more than a byte at a time - does not allow it to be updated quickly. For example, the implementation of horizontal smooth scrolling of the area of ​​256x8 pixels while playing VGM music in parallel almost completely takes the ray retraction time over the frame. Those. there’s almost no time left.
In games (modern), this problem is solved in rather clever ways, when scrolling does not update the entire scrolling area, but only requiring changes. Accordingly, the contents of the screen is thought out in such a way that these changes were minimal. Also commonly used is Graphics Mode I with a lower color resolution (two colors per 8x8 block).
As in many other systems, in TI-99 / 4a, it is highly desirable to render the image by following the vertical retrace. To do this, VDP generates a corresponding interrupt - at the beginning of drawing the bottom of the frame.

The following options exist:
1. Interrupts can be disabled completely (LIMI 0 + instruction specifically for VDP — by setting the corresponding bit in register 1). In this case, everything will be faster, but you will not be able to track the return path of the beam in any way.
2. Interrupts enable completely (LIMI 2 and VDP). Then you can hang your own interrupt handler that will do something.
3. Enable interrupts in VDP, but disable them with the LIMI 0 instruction. In this case, no handlers will not be called, but you can monitor the return path of the beam manually by checking the bit in the VDP status register (after reading the register, this bit is automatically reset. If it is not reset, then another interrupt will not be generated).
vwait: movb >8802,r12 ; read VDP status register andi r12,>8000 jeq vwait ; Wait for vsync
A quite typical scheme is when interrupts from VDP are turned on, common ones are turned off (LIMI 0), but in the main loop for a short period of time they are turned on (LIMI 2) so that the processor hanging on the interrupt (for example, playing music) sometimes gets control.
Not all emulators correctly mimic this interruption. But, let's say, MESS does it more or less adequately. In the picture you can see a simple test - the color of the frame changes with some delay relative to the vertical retrace (on a real TI and on two emulators, MESS and js99er).
SOUND
1. Standard sound
For music and sound effects in the TI-99 / 4a installed chip TMS9919 (analogues: SN76489, SN76496). It is quite simple: three independent tone generators and one noise. 15 volume levels.
Since this is a fairly popular chip (used in some consoles, in IBM PCjr / Tandy-1000, etc.), there is a lot of information on it.
For TI-99 / 4a there is a MOD2PSG tracker (it normally starts under Win7 64bit). In particular, it allows you to upload psgmod files and export vgm and epsgmod.
There are two working players - EPSGMOD Player by Tursi (requires data in epsgmod format, hangs its handler on the VDP interrupt).
It is connected as follows:
def start start: lwpi >8320 li r0,musicdata bl @SGPLAY again: limi 2 limi 0 ; .... your code (vsync etc..) ... b @again musicdata: bcopy "music.epsgmod" copy "test_music_playervbr.a99" copy "test_music_player.a99" end start
With this connection of the player, it is necessary to remove REF and END from its sources (since they are oriented to use with traditional assembler).
Note that in the main loop for an instant interrupts are enabled (limi 2). This is necessary for the operation of the player, which operates on interruptions of VDP from the return path of the beam (occurring every 1/60 of a second). The subroutine SGTICK of the player is called.
Accordingly, it is important that for the NTSC version of the computer and the music should also be NTSC (the frame rate should be the same).
The second player (of the same author) loses files of the VGM format (also includes the VGMComp utility for compressing VGM). This handler does not hang up, you need to call manually with a frequency of 60Hz.
It looks like this:
def start vdpsta equ >8802 ; VDP RAM status start: limi 0 lwpi ws0 ; player expects our workspace to be >8300 clr r2 li r1,musicdata bl @stinit again: clr r12 ; set CRU base (doesn't need to be in loop, but provides delay) tb 2 ; check VDP interrupt input (Tests a CRU bit) jeq loop ; if not set, skip calling music movb @vdpsta,r12 ; read status register, which in turn clears the interrupt bit bl @stplay ; call play function - it returns with the wrong workspace * check for song end movb @songwp+14,r3 jne notdone clr r2 ; play again li r1,musicdata bl @stinit notdone: lwpi >8300 ; so restore the right one ; .... your code (vsync etc..) ... b @again musicdata: bcopy "music.vgm" copy "tiplayer.a99" end start
In my opinion, the second version of the player has better quality (although it may depend on the particular music) and manual challenge is more flexible than the handler (which you yourself can hang if you really need) - you do not need to enable interrupts.
He also has a 30Hz player version. At the same time, it should also be called with a frequency of 60 Hz, but it will be used every second call. Accordingly, the processor load is reduced, but the sound quality of music (depending on the effects used in it) may potentially drop.
Apparently, there is a bug in the player (or when exporting to VGM), which creates incomprehensible problems with looping music.
2. Speech synthesizer

Since the speech synthesizer is a very popular peripheral device for the TI-99 / 4a, quite a few programs use it. The synthesizer connects to the port on the right side of the computer (if you have a NanoPEB, you can plug it directly into the synthesizer). Inside there is a ROM with data for words, an LPC decoder (TMS5220) and a DAC.
There are two modes of operation. In the first, the computer indicates to the synthesizer which words from the ROM should be pronounced (there are few words). In the second (Speak-External) it is possible to transfer directly compressed LPC data, which the synthesizer will simply reproduce. For packing data using the ancient program QBox Pro, which runs under WinXP (the process is shown
here ).
The synthesizer can be controlled directly from the program in assembler. If you just want to play, then you need a cartridge - for example, Speech Editor (allows you to pronounce the typed text, and also adds commands to the standard BASIC to play words). Cartridge Terminal Emulator allows you to pronounce individual phonemes and connect them into arbitrary words.
In the most famous emulators, the synthesizer is supported. It is believed that the best support (fully emulated piece of hardware) is implemented in MESS / MAME.
Below is an example that says the word “HELLO” by taking LPC data from a synthesizer ROM. Documentation indicates that status checking is not possible if the code is executed in RAM on an 8-bit bus (i.e., the code is required to be in a 16-bit scratchpad), but after checking on emulators and a real computer, I think this is reinsurance (probably, as and in the case of VDP, all these requirements apply to some very early versions of iron). This is a short code:
; speaks 'HELLO' from speech synth ROM def start SPCHRD equ >9000 ; addr to read from synth SPCHWT equ >9400 ; addr to write to synth (>10 - read, >4x - Load-Address, >50 - speak, >60 = speak-ext ) H50 BYTE >50 ; speak command start: limi 0 ; loading speech address (5 nibbles of data required) using >4x Load-Address command ; >4x >4x >4x >4x >40 (end marker >0) li r0,>351a ; address of 'HELLO' in synth ROM li r2,4 ; 4 nibbles loadlp: src r0,4 ; start with least significant nibble mov r0,r1 src r1,4 andi r1,>0f00 ; get only particular nibble ori r1,>4000 ; put in >4x00 format movb r1,@SPCHWT ; write nibble dec r2 jne loadlp li r1,>4000 movb r1,@SPCHWT ; write fifth nibble (end marker) movb @H50,@SPCHWT ; execute speak command loopback: b @loopback end start
Addresses of all words from ROM can be found in the book Editor Assembler Manual.
If you want to play an arbitrary speech converted to LPC using QBox Pro, in the simplest case, the code will look like this:
def SPEAK SPEAK li r2,1750 ; number of speech BYTEs to poke (see end of QBox data) li r3,speech ; speech data address limi 0 ; no interrupts loop movb *r3+,@>9400 ; poke a BYTE of speech data dec r2 jeq quit ; repeat until end of data jmp loop ; else go 'round again quit limi 2 ; interrupts allowed rt speech ; 10 Voiced 4 Unvoiced 8 kHz 5220 ; [Coded LPC] ; .... *.sfm QBox Pro ; nb bytes: [1750] end
For QBox Pro, you need to prepare a wav speech file. Better sound clear male speech. One phrase will take about kilobytes.
Send singing or notes - will not work. After encoding in LPC, such sounds will be completely unrecognizable.
Settings and operations in QBox Pro:
byte 8khz 5220 Project/Add files select file Process/Medium bit rate /OK Edit/Concatenations Insert/Concatenation/Concat Name/ "TEST" Insert/Phrase/OK Format/LPC 10V, 4UV /OK Project/Exit/Save
Result: test.sfm
CROSS-MEANS
To develop and test software on a PC, and then download them to a TI-99 / 4a, you need the following:
Iron:
- PC / Win7 (64bit is good)
- TI-99 / 4a
- Cartridge Editor / Assembler (or any other, allowing you to download and run programs in machine codes)
- NanoPEB or CF7 + (to emulate the drive and load the program from the CompactFlash card in the TI-99 / 4a)
Soft:
- One of the many TI-99 / 4a emulators is MESS / MAME or js99er (and preferably several).
- The xdt99 package, which includes the assembler and utilities for working with files and disk images (in particular, xvm99 for recording a disk image on a CompactFlash card, in the required format for NanoPEB)
Organization of the process:
The programs for the cartridge and for loading from disk are different things. Not only in terms of format (RPK and DSK), but also in terms of working with memory (the second version uses a 32kb memory expansion). If there is a goal to eventually run the code on a real machine, you need to focus on the disk version. And consider it.
Emulators are significantly different from each other, the best name is very difficult. This is not only a question of the quality of emulation, but also of the convenience / ease of launching the finished program.
The most famous: mess (mame), js99er, v9t9, classic99.
All of them are not perfect. It is quite possible to expect a 10% difference in speed between the emulator and the real piece of hardware (specifically, I observed that mess and js99er execute the entire code a little faster than the real TI. In the same NTSC)
When used as an xdt99 assembler, the process looks like this:
xas99.py -R --jumpstart %1.a99 ( )
The -R option allows you to normally name the registers in the source text (r0, r1, ...). In the traditional assembler TMS9900, the registers in commands are simply written in numbers, which introduces wild confusion.
xdm99.py work.dsk -a %1.obj -n %1-O -f DIS/FIX80 ( )
It is necessary to take into account that the object file is a text file with hexadecimal codes inside. Although this is not the final binary file, nevertheless, because of the peculiarities of downloading programs to the TI-99 / 4a (via Editor / Assembler), it is often considered a ready-made program. All the more convenient that it is usually not tied to a specific area of ​​memory at boot time.
If the final binary file is required, for the xas99 one should add the parameter "-i". Then you will need to download it not through point 3, but through point 5 in the Editor / Assembler. If you need a final binary file more than 8k, without splitting into separate parts, instead of -i you need to use -b.Additionally, you can get the listing file .lst by specifying the parameter "-L".The special image of the cartridge for automatic loading somewhat simplifies the work (see “jumpstarting” in the documentation on xdt99). The image allows you to do without the Editor / Assembler in the emulator, pressing the buttons in it and entering the file name. Ready code is loaded from disk automatically when you select a cartridge. For example, mess (mame) in this case starts like this: mame64.exe ti99_4a -peb:slot8 tifdc -peb:slot2 speech -flop1 %1.dsk -cart jumpstart.rpk -window -ui_active -skip_gameinfo
, -debug ( , — ` )
«ti99_4a» NTSC (.. ). PAL ti99_4ae.
, - -. 60, 50. , , ( NTSC, PAL).
- , -speed 20
CompactFlash NanoPEB xvm99.py
\\.\PHYSICALDRIVE2 1 -w work.dsk
, PHYSICALDRIVE2 CF ( !). Windows
wmic diskdrive list brief /format:list
CF , — .. DSK1 1).
CF FAT16, TI NanoPEB TI Basic «call format(1)», 1 — .
:
xvm99.py \\.\PHYSICALDRIVE2 1 -i
TI Editor/Assembler NanoPEB. NanoPEB, . «2» — «Editor/Assembler», 3 ( 5), DSK1._ ENTER.
.
1 — 99TRO
TI-99/4a
«99tro» () — invitation intro Chaos Constructions'2016, Revision'2016. ( — !) .
, cracktro Commodore 64, TI-99/4a. , - , , .

:
— ,
— ( ) ( 16-, .. VDP 8- ).
— VDP ( , TMS9918 — ). , .
— — 4 ( , ), , .
— (vgm) . Tursi, 2-20% 30 , . 10-15%.
— ( , Vectrex — , , , , , )
— . , , PC, , PC TI, TI, Editor/Assembler, , DSK1._, ENTER, ( ).
, (, , ):
— / CHAOS CONSTRUCTIONS'2016
—
— , ,
—
— (vgm)
- TI-99/4a, — Graphics mode II (Bitmap). , .. 16 , , .
, , ( demo intro) — . , , , .
bitmap .

Photoshop, VDP Convert9918 — .. , ( 15- 2 8 ) . , NTSC , , — CRT , ( , ).
, , 16 () . TI-99/4a ( , 15).
, NTSC . , ( PAL , ).
(Matthew Hagerty) . . TMS9900 , , .
VRAM. 8 .
, bitmap' — - .
— , ( , ).
, .. , , , . — .
The text behind the cursor is written in the middle of the screen. I had many ideas on how to implement it beautifully, but in the end I had to give up on all of them because of the slow video memory and VDP bugs. As a result, one letter is drawn for each iteration of the loop (i.e., 8 bytes of video memory are updated). For all possible eight lines of text, a background with a smooth transition between shades of blue and gray is set in advance.The pulsing cursor is a sprite for which the image is taken cyclically from four memory locations - i.e. It turns out four frames of a square of a different size., 16x16 ( — ). ( ).
Magellan.
workspace — ( workspace, scratchpad — 16- RAM, - ), ( , .)
intro 22. , , (12kb) RLE (1.8). , - 6-7 ( , ).
2 — Speechtro
«Speechtro» () 99tro DIHALT'2016 ( 1kb low end intro).
:
1. -, ( TI-99/4a , — MESS/MAME js99er).
2. .

.
( LPC 1 ). , , . . , «». , -, , - , .
, ( , ). ( TI — MESS js99er), — . Graphics Mode 2 8x1 , 1 . , 15 ( 10), , .
. TI-99/4a , ( GROM) , GROM () — .
«small caps» AZ ( ), .
, , 8x8.
() .
TI-99/4a
Here you can see my works for different retro platforms, and
here their sources are on github.
,
Chaos Constructions , ( ) , - .
PS