Classic99 - 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++ and DirectX. 
Source is available for your review but derived works may not be distributed
without contacting me.

---------
REQUIREMENTS

-Windows 98, ME, 2000, XP, Vista, 7
-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 function 
keys map to FCTN+number.

When scroll lock is on, the function keys will control debug functions of
the emulator (F1-F12). All F keys stop being passed to the emulator. Also, 
Home is used to launch the debugger window.

The arrow keys normally return FCTN+E/S/D/X. If joystick emulation is set to
keyboard, and the program scans the joystick, then these keys (and Tab) respond
to the joystick request only. After about 3 seconds if the joystick is not
scanned again, they return to being keyboard keys.

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.

-----
DISKS

Classic99 supports up to 10 disk directories. These are configured in the Classic99.ini,
by default as it ships, DSK1, DSK2 and DSK3 are configured as like-named folders in
the Classic99 folder. Supported disk indexes are from 0-9.

Today, only FIAD (Files In A Directory) format is supported. Classic99 by default can
read TIFILES and V9T9 files, as well as Windows text files if they have the appropriate
extension (as DF80 or DV80). Configuration options let you disable any of these options
if they are problematic.

The configuration also lets you specify whether written files are TIFILES or V9T9 files
by default (TIFILES is preferred and the default). You can also configure the system
to always write DV80 as Windows text instead of a TI format file.

Classic99 also supports DISPLAY mode access to the Windows clipboard. The devicename
is "CLIP". Full access is available, including read, write, update and append. Note,
however, for update and append, the clipboard is read and cached on the open call,
then replaced when the file is flushed or closed. Intermediate external changes won't be
reflected.

There is a bug in the TI Editor/Assembler that will report error 0 if you attempt to
load from any device without a filename. Appending a period is enough to work around
this error, so E/A can load from "CLIP."

The clipboard supports fixed and variable lengths up to 254 bytes.

---------
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. :) Note that 
you must be on the appropriate memory type! Only CPU and VDP have registers.

You can change the PC by sitting on the disassembly view, and using "PC=XXXX"

There are also step buttons in the debug window itself, as well as buttons
that trigger the LOAD interrupt and dump memory.

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!)
T(0000-0001) start a timing counter between address 0000 and 0001 - each time 0001 is reached
			it will print how many cycles elapsed since 0000 was executed. This does not breakpoint,
			the information is emitted into the debug view.

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!

Except for the VDP and CPU registers, all addresses may be specified as a range
by using (0000-0001) -- the parenthesis indicate a range, and all values within
that range will be considered. Note how the timing option requires a range!

All the rest are currently just read-only register dumps, although with breakdowns
of the VDP and CPU status registers.

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)
F5 - take incrementing screenshot, unfiltered. The first one will ask for a filename if needed
F6 - take incrementing screenshot, filtered. The first one will ask for a filename if needed
F9 - VDP character dump - shows the current character set instead of the picture (except in bitmap mode)
F10- Dump CPU and VDP to file
F11- Toggle System Maximum (Turbo) mode
F12- Trigger LOAD interrupt

CTRL+F5  - Set CPU normal
CTRL+F6  - Set CPU Overdrive
CTRL+F7  - Set System Maximum
CTRL+F8  - Set CPU slow
CTRL+F12 - Reset Emulator (reloads all ROMs)

Home- Bring up debugger window

-------
HEATMAP

Related to the debugger, but potentially also just fun to watch, the Heatmap
shows you memory activity inside the console in real time. It can take a fair bit
of CPU to run, be warned!

RED shows CPU memory accesses.
GREEN shows GROM memory accesses.
BLUE shows VDP memory accesses.

A full 64k space is available. Paging is not taken into consideration.

---------
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.


Files on a Disk
---------------
The most popular way to extract file images from disk images is to use TI99Dir by Fred Kaal, which you can
find here: http://members.ziggo.nl/fgkaal/Software/sw_ti99dir.html

Once you have the files on the disk, they are usually in V9T9 format. V9T9 was one of the original
TI Emulators for DOS - and the first free one. To work around differences in the TI filesystem to DOS,
it does a couple of unusual things.

First, certain characters are replaced with high ASCII replacements in order to work in the file
system. For instance, a forward slash becomes an overscore line. Classic99 doesn't support this
renaming scheme. Instead, the following TI characters should be replaced with '~' on the disk:
?, /, >, <, :, ", *, |

Classic99 will deal with the internal name. Also, the length of these files was limited to the old
DOS 8.3 naming format, meaning any filename longer than 8 characters (TI supported at least 10) has
an extension. For instance: MYFILENA.ME -- rename it to remove the '.' (MYFILENAME) for Classic99.

Except for the changing of certain characters to '~' and removing the period, do not rename
V9T9 files on the disk. Doing so will break them, because the real filename is embedded in the
header and must match.

This does hurt interaction back to V9T9 and other emulators stuck in the past. If you need to interwork
with them, I recommend keeping filenames to 8 characters or less, and avoid all punctuation except
for ';' and '_'.

Classic99's preferred file format is called 'TIFILES' or sometimes 'XMODEM'. If is the format that
was globally used by file transfer programs to upload and download files to BBSs, which were likely
running on PCs, while preserving the TI standard information. The filename is not included in the
header, meaning that the file on disk is the only filename. The same limitation of punctuation above
must be followed, however, you are free to rename or move these files on your disks at will. They
can also be sent directly back and forth with real TIs using a terminal program and a serial connection,
while V9T9 files must be converted to do so.


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]
max_volume
	scaler for maximum volume from (percentage) 0-100 (all audio is scaled to this)

sid_blaster
	0	SID Blaster is disabled
	1	SID Blaster is enabled

[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

heatmapfadespeed
	Number of pixels updated in heat map per frame
	Higher number is faster fade but more CPU needed
	Default is 25.

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.

Marc Hull for his SID Blaster card and documentation on supporting it.



