Classic99 QI3.3 - DirectX TI Emulator for Windows
by M.Brent/Tursi
http://www.harmlesslion.com/software/classic99

----------
PURPOSE

To have fun and tear apart my favourite machine - the TI99/4A. 

It's written entirely in C++, using Microsoft Visual C++ 6.0 and DirectX. 
Source is available for your review but derived works may not be distributed
without contacting me.

---------
REQUIREMENTS

-Windows 98, ME, 2000 or XP
-DirectX 8 to use DirectX/FullScreen modes

---------
SETUP

Unzip the archive with folders - in theory, you've already done that.

The emulator is now preconfigured and ready to go - just check out the menus!


---------
KEYBOARD

Thanks to Mark Wills for the encouragement, there is now a port of my PS/2
keyboard handler to Classic99. There are a few special tweaks for Classic99.

Num Lock works pretty much exactly like you would expect. I don't guarantee that
keys like page up/page down/home/end will be useful, but I tried. ;)

Caps Lock works like you would expect, but it is deliberately reversed. This is
so you don't have to switch back and forth between PC and TI.

Scroll Lock is special. When off (normal), all keys map to the TI. The arrow keys
map to FCTN+E/S/D/X, and the function keys map to FCTN+number.

When scroll lock is on, certain function keys will control debug functions of
the emulator (F1/F2/F3). Also, Home/End/Page Up and Page Down become available for
debug purposes.

Note that if joysticks are configured for keyboard, the arrow keys and Tab will
return both joystick AND their normal keyboard function.

Should the PS2 emulation cause any problems, exit Classic99, and edit Classic99.ini.
There is a setting PS2Keyboard - set it to equal 0 and the old layout will be used.

---------
DEBUGGER

This has grown a fair bit and is in need of some documentation.

Now has read-write ability. Note the keyboard shortcuts require Scroll Lock to be on.

Bring it up by pressing Home, or selecting Edit->Debugger.

The following options are available:

First, at the bottom right, the radio buttons select the list view. You can view:
-Debug - a list of debug output from the emulator

-Disasm - running disassembly from the program counter, with history

-CPU, VDP and GROM - memory dump from the specified address, which defaults to R0.
You can enter an address or a register in the box, each memory type remembers
it's own pointer. A register will track the current value of that register.
A 4-digit hex number is an address that will be displayed instead. When entering
a value, be sure to press 'Apply'. Also, 'Prev' and 'Next' will scroll roughly
one page at a time.

You can also /change/ CPU, VDP or GROM, one byte at a time, by entering either an
address or a register, followed by "=xx" (ie: 830A=0F or R14=12C0). Numbers, except
register indexes, are in hex. Remember to click Apply. You will be asked for
confirmation if you attempt to modify ROM or GROM. Note Registers only work on the
CPU and VDP views. As an extra, CPU writes (only) may be a word by entering a full
four digits for the value. You may change values while running, but as this may 
cause problems for the program, you probably should breakpoint first. :)

The four buttons above this are speed controls, like a VCR, The two bars (||) are
for Pause (F1), next (>|) is Step one instruction (F2), followed (>) by Play Normal
(F1 when paused), and finally, (>>) is Fast Forward (Options->System Maximum or F3).

At the top left is the breakpoint window. You may have up to 10 active breakpoints.
To set a breakpoint on the CPU, type a 4-digit hex address and press 'Add' The following
special breakpoints are also available:

*0000	- break when address 0000 is accessed (read or write)
>0000	- break when address 0000 is written to
<0000	- break when address 0000 is read from (including by PC!)
S0000	- start a timing counter at address 0000 (not a breakpoint)
X0000	- exit timing counter at address 0000 (will print stats in debug!)

M0000=FF	- break when the CPU memory byte at 0000 equals FF
W0000=FFFF	- break when the CPU memory word at 0000 equals FFFF
V0000=FF	- break when the VDP memory byte at 0000 equals FF
U0=FF		- break when VDP register 0 equals FF
R0=FFFF		- break when Register 0 equals FFFF

Note: there is a special case in the "memory equals" cases -- the emulator compares
the address and data that was written, it does NOT read memory back. This means you
can use those cases to find particular writes to memory mapped devices, because it's
the write that counts, and not what ends up in the memory!

All the rest are currently just read-only register dumps.

Key Summary (Scroll Lock must be ON, and TI-99/4A with extended keyboard configured):
F1 - Run
F2 - Step into one instruction (if breakpointed)
F3 - Step over one instruction (if breakpointed) (if BL or BLWP, will run till it returns)
F10- Dump CPU and VDP to file
F11- Toggle System Maximum (Turbo) mode
F12- Trigger LOAD interrupt
Home- Bring up debugger window

---------
Classic99 still relies on the configuration file a lot. Here's how to get things loaded.

TI Console ROMS
---------------
It is not necessary to provide console ROMs anymore - they are built in! The system will automatically
start with Classic99, and you may choose another under the System menu. However, note that only the
TI-99/4A is fully supported.


Cartridge ROMS
--------------
A number of cartridges are now built into Classic99, however, you may want to add more yourself.

Currently, you must modify the Classic99.ini (it will be created after one run). See the description
of the INI file below.

Save the file, and run CLASSIC99.EXE. Press a key on the title page and select the cartridge from the list.

You may now also select Cartridge->User->Open. This code is incomplete, but it will work. Currently
it loads into the first User slot (User0), does not update the GUI and does not save the data to the INI.
You must use V9T9 style cartridges with this feature - select any of the cartridge files and Classic99
will identify and load the rest automatically so long as they are named with the correct convention
and in the same folder. Classic99 expects carts to be named "fileG.BIN", where 'file' is the common part
of the filename, 'G' is either G, C or D for GROM, ROM, or XB Bank 2, and .BIN is the extension. Classic99
will accept other extensions but you will need to type it manually. Classic99 may not open GRAM files
or PC99 style cartridges with this option yet, but you can try (they still need to use the G/C/D naming
option.) You can still load them directly into the Classic99.ini without using this feature.

Disk Images (*.DSK)
-------------------
These are not ROMs, although the emulation community has taken to calling anything used with an emulator a
ROM. These are images of diskettes made popular by PC99 and V9T9. Classic99 does not currently handle disk
images very well (perhaps not at all, I haven't tested it in a while). Classic99 prefers to use files on
the hard drive as the TI File System lends itself wonderfully to expansion and we can reduce the
limitations of the original disk system this way. ;) But, eh, I'll add it in later.


Arc303 Files
------------
Arc303 is the TI's equivalent of ZIP files - they are compressed files that usually contain more than one
other file.

Usually these end with an '@' character to indicate they are archived. The Classic99 distribution includes
ARC303 on DSK1, and is ready to go with one disk drive with the default configuration.

Copy the archived file (@) into the DSK1\ folders (or any other if you set up more) using Windows. The 
example assumes you are putting everything into DSK1. If not, just substitute the correct drive number.

Start CLASSIC99.EXE. Select the Editor/Assembler under Carts->Apps. Press a key then select Editor/Assembler 
from the main menu. Next select '5 RUN PROGRAM FILE' from the Editor/Assembler menu. (Thus the term 'E/A #5'). 
Enter 'DSK1.ARC303G'.

Press a key to pass the Shareware notice, then select '2) Extract Files'. Enter your source drive (1), and
the name of the '@' file for Source Filename. Select your output drive (may still be 1), and for 'Extract
all files?' you will usually say 'Y'. If you select the same source and output drive, it will also ask
'Swap Disks?', of course with Classic99 you may say 'N'.

You'll see 'BACK / REDO / Any Key to Begin', just hit the space bar and the files will be extracted. You
can then quit the archive program and move on to running the files themselves.


TI BASIC files
--------------
No cartridges are required to be enabled.

Select TI BASIC from the main menu. The system will report 'TI BASIC READY' and provide a cursor.

You will almost certainly need CPU THROTTLING on - it's under Options. The keyboard repeat is just too
touchy.

Enter 'OLD DSK1.FILENAME', where 'DSK1' is the disk folder you have the file in, and 'FILENAME' is the name
of the file. Note that the TI likes everything in uppercase, but it often doesn't matter with Classic99.

Once it loads successfully, 'RUN' will start it up. (For programs that you don't have to type in, turning
CPU throttling back off at this point makes slow programs more bearable.)


EXTENDED BASIC files (XB)
-------------------------
You must have Extended BASIC selected as the cartridge under Carts->Apps.

Select Extended BASIC from the main menu. The system will report '* READY *' and provide a cursor.

You will almost certainly need CPU THROTTLING on - it's under Options. The keyboard repeat is just too
touchy.

Enter 'OLD DSK1.FILENAME', where 'DSK1' is the disk folder you have the file in, and 'FILENAME' is the name
of the file. Note that the TI likes everything in uppercase, but it often doesn't matter with Classic99.

Once it loads successfully, 'RUN' will start it up. (For programs that you don't have to type in, turning
CPU throttling back off at this point makes slow programs more bearable. In XB it usually will not affect
the speed of sprites, but it will improve the responsiveness!)


PROGRAM IMAGE files (E/A#5)
---------------------------
You must have Editor/Assembler selected as the cartridge under Carts->Apps.

Select Editor/Assembler from the main menu. Select '5  RUN PROGRAM FILE' from the menu. For 'File Name?',
enter 'DSK1.FILENAME', where DSK1 is the disk you have the file(s) on, and FILENAME is the first file
listed. Program images were limited to 8k, so for programs larger than 8k, multiple files were created by
adding 1 to the last character of each name. Some programs numbered the files (ie: POPEYE1, POPEYE2,
POPEYE3), but many just let the last letter increment (ie: LASSO, LASSP, LASSQ).

Program files will autostart after being loaded.


OBJECT FILES (E/A#3)
--------------------
It's very rare to come across these as Program Images were faster, smaller, and easier to load, however,
just in case...

You must have Editor/Assembler selected as the cartridge under Carts->Apps.

Select Editor/Assembler from the main menu. Select '3  LOAD AND RUN' from the menu. For 'File Name?', enter
'DSK1.FILENAME', where DSK1 is the disk you have the file(s) on, and FILENAME is the file you are currently
loading. It's possible, though even more rare, to have to load more than one file.

If the program does not autostart after loading the file(s), hit Enter on the 'File Name?' prompt to enter
a blank line. You will be prompted with 'PROGRAM NAME?', which unfortunately you need to know. However,
most E/A#3 files use 'START'.


SDGROM
------

NOT YET SUPPORTED.

Files go into the SDGROM\ folder. The default load file must be called MENU and must be appropriately
build as a single file with all ROMs to be loaded.

Since it is not yet supported, please don't use this. See SDGROM.H and SDGROM.C. Specifications are
subject to change.


USING TI PROGRAMS
-----------------
Many programs refer to 'REDO', 'BACK', etc, keys that are not immediately obvious. The TI used FCTN and the
number keys for these special terms, so on Classic99 it's Alt and the number key. They are laid out as
follows:

1 - DELETE
2 - INSERT
3 - ERASE
4 - CLEAR       ( Stops a BASIC or XB program)
5 - BEGIN
6 - PROCEED
7 - AID
8 - REDO
9 - BACK
= - QUIT        ( Restarts the TI)

Arrow Keys:
E - Up
S - Left
D - Right
X - Down

Extra characters:
~ - W
[ - R
] - T
_ - U
? - I
' - O
" - P
| - A
{ - F
} - G
\ - Z
` - C

(Also see Help->Keyboard Map for a picture!)

Classic99.ini
-------------
While all the settings in here are intended for internal use by the emulator, it's always handy to be
able to hack around a bit! So here's a quick summary of what each field is for. If you mess with it
and the emulator crashes, though, tough. ;)

[audio]
sampleidx0	(and 1 and 2, represents the voice 0-2)
	0	square wave (default)
	1	sine wave
	2	flute
	3	oboe
	4	organ
	5	piano
	6	sax
	7	strings
	8	trombone
	9	violin

sampleloop0 (and 1 and 2, again)
	0	sample does not loop (all the samples)
	1	sample loops (square and sine wave only)

max_volume
	scaler for maximum volume from (percentage) 0-100 (all audio is scaled to this)

[Disk0]
	Note: this can be Disk0 through Disk9, representing DSK0-DSK9 in the emulator
	
Type
	0	this disk is not configured
	1	this disk uses FIAD (files in a directory) access
	
Path
	Specifies the path to the folder for FIAD drives. May be a full path or a relative path.
	
FIAD_WriteV9T9
	0	write files using TIFILES headers (default)
	1	write files using V9T9 headers (not recommended, V9T9 filenames are limited to 10 characters
		and have mapping problems with non-alphanumeric characters
		
FIAD_ReadTIFILES
	0	Reading TIFILES files is disabled, files are never detected as TIFILES
	1	Reading TIFILES files is enabled (default)
	
FIAD_ReadV9T9
	0	Reading V9T9 files is disabled, files are never detected as V9T9
	1	Reading V9T9 files is enabled (default)
	
FIAD_ReadTextAsDV
	0	Do not read Windows text files as Display/Variable 
	1	Read Windows text files as Display/Variable (extensions must be TXT, COB or OBJ)

FIAD_ReadTextAsDF
	0	Do not read Windows text files as Display/Fixed 
	1	Read Windows text files as Display/Fixed (extensions must be TXT, COB or OBJ)

FIAD_ReadTextWithoutExt
	0	Do not treat files without extension as Windows text
	1	Treat files without extension as Windows text (if they are not detected as V9T9 or TIFILES)

FIAD_ReadImgAsTIAP
	0	Do not read images as TI Artist files
	1	Read images as TI Artist files (NOT IMPLEMENTED YET)

FIAD_WriteDV80AsText
	0	Write DV80 files in TI format
	1	Write DV80 files as Windows text files

FIAD_WriteAllDVAsText
	0	Write all DV files in TI format (unless WriteDV80AsText is set)
	1	Write all DV files as Windows text files (regardless of the setting of WriteDV80AsText)

FIAD_WriteDF80AsText
	0	Write DF80 files in TI format
	1	Write DF80 files as Windows text files

FIAD_WriteAllDFAsText
	0	Write all DF files in TI format (unless WriteDF80AsText is set)
	1	Write all DF files as Windows text files (regardless of the setting of WriteDF80AsText)

[emulation]
AVIFilename
	Filename that will be used with 'Start Recording' to write an AVI file.
	Defaults to C:\Classic99.AVI

cputhrottle
	0	do not throttle CPU - run as fast as possible (does not speed up vertical blank!)
	1	throttle CPU, run as fast as maxipf permits

maxipf
	Maximum instructions per frame (either 50hz or 60hz). Default is 2800, but how accurate
	that is depends on the program being executed. Has no effect on the vertical interrupt
	(unless set too low), so music and sprites will generally not change pace, and neither
	will most GPL programs in general.

pauseinactive
	0	Do not pause emulation when window is not focused
	1	pause emulation when window is not focused

slowdown_keyboard
	0	Do not slow down keyboard auto-repeat 
	1	Slow down keyboard auto-repeat (99/4A only!) (during GPL reads and when unthrottled only)

system
	0	TI-99/4
	1	TI-99/4A
	2	TI-99/4A v2.2

ps2keyboard
	0	Disable PS/2 keyboard (also for 99/4)
	1	Enable PS/2 keyboard (99/4A only)
	
sams_enabled
	0	Disable SAMS memory expansion card
	1	Enable SAMS memory expansion card
	
sams_size
	0	128k SAMS card
	1	256k SAMS card
	2	512k SAMS card
	3	1MB SAMS card (default)

[joysticks]
active
	0	Do not map joysticks
	1	Map joysticks using joy1mode and joy2mode

joy1mode	(and joy2mode for joystick 2)
	0	Keyboard (arrow keys and tab)
	1	PC Joystick 1
	2	PC Joystick 2

[debug]
scrambleRAM - if set to a non-zero value, RAM is scrambled on reset rather
than initializing it to zero. This can help find bugs. Note this only sets
the power-up default. When using the menu item 'Reset', RAM is always zeroed,
when using 'Reset - Scramble RAM', RAM is always scrambled.

[roms]
cartgroup
	0	Apps
	1	Games
	2	User

cartidx
	-1	No cartridge selected
	??	index of the cartridge from the appropriate menu

[UserCart0]	 (and so on up to 99)
name
	Name of the cartridge. If blank or missing, the cartridge is ignored.

message
	Compatibility notes, if desired

rom0	(0-3 for a total of 4 ROMs per cartridge)
	Contains notes for loading the cartridge. This is a pipe-limited row
	of data, formatted like so:
	T|AAAA|LLLL|filename

	T is the single character ROM type. Most carts only use G, C and X types.
	C	CPU ROM
	D	DSR ROM
	E	DSR ROM bank 2 (used for p-code)
	G	GROM*
	P	P-Code GROM
	R	CPU RAM - this is loaded like CPU ROM but is not flagged as read-only!
	S	Speech ROM
	V	VDP RAM
	X	XB Bank 2 ROM (called 'D' in some systems, but I used D already)
	A	AMS memory, RLE encoded (not working correctly yet)
	K	Paste string for the keyboard after boot (to autostart tasks, not a filename)
	3	Packed banks with a '379 style decoder. Similar to XB style but more banks and 
		all in one file. Note that this assumes a load at >6000, so you are specifying
		the offset in the banking space, with bank 0 at >0000, bank 1 at >2000, etc.
		SuperSpace carts (CRU >400) can be loaded this way for now, too, but will 
		likely split them up later. Max size is 64k.

	(* GROM is special - to support multiple GROM bases, you can now load GROMs
	into different memory bases - up to 16 of them! By default, GROMs load into
	memory base 0. Append a hex number 1-F after the G to specify a different
	base (like: G1). The console will detect these and add them to the start menu! 
	Note that not all GROMs will work at alternate bases. Also note, in the real 
	console, the console GROMs appear at all bases, so you can't load alternate
	bases at less than >6000. Classic99 does not support using this with cartridges that
	include CPU ROM. Each GROM base is offset 4 from the previous, ie: GROM Read
	is >9800, >9804, >9808, etc.)

	AAAA - load address in hexadecimal

	LLLL - length of data in hexadecimal (will override actual size of file)

	filename - filename on disk to load

	This system supports both raw ROM files, and ROM files with a 6 byte GRAM
	Kracker style header. The header is detected by checking if the first byte
	is >00 or >FF, and if the 5th and 6th bytes represent the load address. The
	header will be ignored if detected - the data in this INI file is
	considered authoritative.

[video]
FilterMode
	0	None
	1	2xSAI
	2	Super 2xSAI
	3	Super Eagle

frameskip
	Number of frames to skip drawing. This may affect interrupts as well. Default 0.

fullscreenmode
	Note: not all modes are supported on all cards. Classic99 does 16 bit rendering internally.
	1	320x240x8
	2	640x480x8
	3	640x480x16 (default)
	4	640x480x32
	5	800x600x16
	6	800x600x32
	7	1024x768x16
	8	1024x768x32

hzRate
	50	50hz interrupt (PAL)
	60	60hz interrupt (NTSC)

MaintainAspect
	0	Do not maintain aspect ratio (allow any size window)
	1	Force aspect ratio (fix proportions of window)

StretchMode
	0	Do not stretch (fastest)
	1	DIB - use GDI to stretch
	2	DX - use Direct-X to stretch
	3	DX Full - use a full-screen Direct-X mode (set by fullscreenmode)

----------------------------------
Example of adding a user cartridge
----------------------------------

These lines will add Pole Position assuming it's in the MODS\ folder:

[UserCart0]
name="Pole Position"
ROM0=C|6000|2000|MODS\POLEPOSC.BIN
ROM1=X|6000|2000|MODS\POLEPOSD.BIN

Pole Position is not included - this is just an example! :) Read the [UserCart0] section above
for detailed on what the fields mean!

---------
THANKS!

A new section to thank those who have helped in various ways:

Joe Delekto - for the SAMS memory card support

Roland Meier - For 9938 video subsystem, vastly improved disk support, and general fixes and
improvements throughout :)

Frank Palazolo - for your TMS5220 emulator for MAME, and for trying to help me way back 

John Butler - For writing the TMS9900 disassembler, which I borrowed for my monitor screen. ;)

Raphael Nabet - for freely sharing with me his modified version of the TMS5220 emulator, which
showed me exactly what I had been doing wrong.

Stiletto - for once being Ami99's biggest fan and sounding enthusiastic when he posted

Derek Liauw Kie Fa (Kreed) - for the 2xSaI engine - wonderful work!

SNES9x - Integration code for 2xSaI borrowed from this project :) See the 2xSaI folder for
all the credits.

Herbert Foster of Texas Instruments for answering my request for permission to include ROMs.
See ROMS.TXT

Ron Reuter of www.mainbyte.com for letting me use the keyboard graphic he drew up

Shay Green for the nifty NTSC TV emulation filter

Mark Wills for much encouragement, bug reports, and enthusiasm.

Joe Delekto for his hard work on AMS and encouragement.


