                        An Atari Emulator

                               by

                          Michael Munoz



Introduction

The Atari emulator program (atari.exe) allows programs written
for the Atari 400, and 800  (XL and XE not implemented, yet) to
run on an IBM PC compatible.  It is fairly easy to write an
emulator that partially emulates the Atari, but very difficult
to write an emulator that implements all of the Atari functions
in real time.  The IBM PC running at 33Mhz is still not fast
enough to emulate an Atari running at 1.79Mhz.  The reason is
that the Atari performs its graphics and sound tasks in parallel
with the 6502 microprocessor; the IBM PC must perform these same
tasks serially (one at a time).     The Atari computer really
was ahead of its time and the current day IBM PC is still a
kludge at best (no bias here).  All of the Atari features can be
implemented in software but they would take too much INTEL 80x86
cpu time and the emulator would run far too slow.   



This Atari emulator program is not complete, however I am
releasing the source code into the public domain so that others
interested in emulating the Atari can gain some useful insight
in one approach to emulating the Atari computer.  Understanding
this emulator may also help in writing software for the Atari. 
The program has some hitherto undiscovered bugs and is certainly
not polished;  feel free to improve upon this one, or write a
much better one.  All of the source code used to generate this
program is included.  The source code is not well documented and
for this I apologize; I simply ran out of time.  (For reference,
this program took me about six weeks to write.)  As I write
this, I am in the process of moving; if this document looks like
it was written in a hurry - that's because it was.



I originally wrote the Atari emulator in  Borland C++; I thought
I could hand code some critical routines in assembler and
achieve a reasonable emulator speed.  As it turns out (not a big
surprise) the 6502 opcode emulation is the time critical part of
the software.  So I decided to write the entire program in
assembler.  (I have included the C++ version in a file called
emu.zip.  The C++ version has the text mode working only and the
keyboard software is flaky, but it is worth a look since this
version was a test bed for the assembler version.)  My
experience is in hardware design, but I know that you can
greatly speed up development time (hardware or software) if you
can use someone else's working design.  So I started scanning
the public domain for a similar program, i.e. an emulator for
the Commodore or the Apple.  I looked at a number of emulators
for other computers; many of the programs were good, but most
were unmaintainable (i.e. I could not modify them for my purpose
without a lot of work).  Then I stumbled upon Randy W.
Spurlock's excellent Apple IIc emulator.  I never actually ran
the Apple IIc emulator so I don't know if the product itself is
any good, but the source code is wonderful.  (You may see
references to the Apple emulator in the source code.)



Randy emulated the 65c02 opcodes, which is not a problem since
the 65c02 is downward compatible with the 6502.  The 65c02
emulator is in a file named "emulate.asm".  I made some changes
to this file to accommodate the special Atari requirements (I
may have actually slowed his code down a bit).  I also kept the
keyboard routine, "keyboard.asm", and modified the keyboard
tables (and functions) to match the Atari keyboard.  I kept a
few of the functions from some of the other Apple emulator
software like the interrupt vector management routines in
"int.asm", the clear memory routine from "memory.asm", the cpu
reset routine in "reset.asm" and a few of the data tables in
"data.asm",  The rest of the code is unique to the Atari
emulator.



The Atari emulator currently implements all ANTIC/CITA graphics
modes1 in "antic.asm", and the player graphics in "gita.asm". (I
did not implement the missiles- it seemed pointless since I did
not implement collision detection.)  Also, I steal the SIOV
vector and call the my_siov() routine in "sio.asm" to handle the
disk drive.  The joystick is supported using the number pad in
the keyboard emulator, "keyboard.asm".  It would not be hard to
make a cable connected to the IBM parallel port and use real
Atari joysticks, but I had intended on using the IBM parallel
port to emulate the Atari SIO.  The prototype of the IBM
parallel port emulation of the Atari SIO is in a file called
"siocopy.zip".



Using the Atari Emulator

You will need a copy of the Atari 400 or 800 OS and BASIC ROMs
in a file called "atari.rom".  This file should use the standard
six byte Atari header telling "atari.exe" where to load the
file. The header for the OS ROM file without BASIC is FF FF 00
E0 FF FF, i.e. starts at $E000 and ends at $FFFF; the total file
length is 8198 bytes.  The header with BASIC is FF FF 00 A0 FF
FF, i.e. copy everything from $A000 to $FFFF into a file; the
total file length is 24582 bytes.  I have included an Atari
program, "romcopy.com" that will allow you to copy the Atari
Basic and OS ROMs into a file.  You will then need to get this
file onto the IBM.  To do this you will need "mule.exe", the
"util.exe" or "sio2pc.exe".



The Atari emulator is fairly straight-forward to start, simply
run the file "atari.exe".  There are no command line options,
just type "Atari" then press the "enter" key.  The first thing
you will see is the familiar blue screen and either "Ready" or
"Atari Memo Pad".  To load a program from an Atari disk image
file, hit the F12 key; a menu will pop up as follows:



The current emulator status is:

D1:

D2:

Basic is ON



1- Change the filename for D1:

2- Change the filename for D2:

3- Load Cartridge (not working)

4- Toggle Basic

5- Exit

Enter the number of the desired command 



Type 1 and the "enter" key, and you will be asked to give a
filename.  Type the name of the Atari disk image file here e.g.
"dos25.xfd".  The hit 5 to return to the Atari emulator.  You
will then need to reboot the Atari by hitting the control/F1 key
combination. You can now access the disk in the standard manner.
 You can access the F12 menu at any time; this allows the use of
"Flippies".



The emulator keys are:



F1 - reset

Control/F1 - hard reset (reboot)

F2 - Option

F3 - Select

F4 - Start

Control/F5 - Exit Atari emulator

F12 - Access Menu



Num Lock - Light on means the number key pad is in joystick mode.

Pad 8 - joystick up

Pad 2 - joystick down

pad 4 - Joystick left

pad 6 - joystick right

pad 7 - joystick left/up

pad 9 - joystick right/up

pad 1 - joystick left/down

pad 3 - joystick right/down

pad 5 - trigger down/ joystick up (jump)

Tab - trigger

Alt - trigger hold down (use tab to clear)



Control/Page up - screen move up

Alt/Page up - increase the interval between video update

Control/Page down - screen move down

Alt/Page down - decrease the interval between video update

Emulator Design Philosophy

Timing and Control

The timing on the Atari computer is critical, but there is no
critical timing for the Atari emulator.  The Atari computer has
a 6502 microprocessor and several sound and graphics
subprocessors that operate in parallel (for the most part).  The
Atari subprocessor called ANTIC can display graphics on the TV
screen while the 6502 is running your program.  The ANTIC chip
only stops the 6502 when it needs to access the Atari RAM
(memory).  Whereas, the Atari emulator is written in INTEL 80x86
assembler which performs each 80x86 instruction serially (one
instruction at a time).  Therefore to emulate the Atari on an
IBM PC we have to separate all of the operations performed by
the Atari subprocessors into a set of serial events.  These
events must occur in a certain order to properly emulate the
Atari.  Determining the order of these events is the single most
difficult part of the Atari emulator design.  Luckily I have
done this work for you.  This section describes the timing and
interrelationship between the 6502 and Atari subprocessors.



The Atari computer graphics are displayed at the same time as
the Atari user program is running.  If the programmer wants to
take control of the graphics he must synchronize the 6502 with
the ANTIC graphics subprocessor.  There are several
methods/registers that we can use to synchronize the 6502 with
ANTIC: Display list interrupts (DLIs), cycle counting, wait for
horizontal sync (WSYNC ) and the vertical scan register.  The
Atari Technical Manual describes how to program using these
methods, but we need to do the reverse; we must assume the Atari
programmer is using these methods and handle each method
appropriately.



Antic interrupts or stops the microprocessor (6502) at known
intervals.  This means that we can determine the number of 6502
clock cycles that can occur before the microprocessor is
interrupted or stopped.  The ANTIC chip is tightly synchronized
with the TV timing in that it tries to read the Atari memory and
update the graphics at the end of every horizontal TV scan line.
 A TV scan line (U.S. NTSC) is 63.5 microseconds long and the
6502 clock is 1.79Mhz, therefore we have 63.5uSx1.79Mhz = 114
clock cycles per scan line.  Each 6502 instruction (i.e. LDA,
STA, etc.) takes anywhere from 2 to 7 clock cycles.  There can
be 16 to 57 instructions completed in one horizontal scan. 
Which do we pick 16 or 57 or use some other number like an
average?  No matter which number we pick, we will eventually
find an Atari program that will not display properly.  The only
way to deal with this problem is to keep track of the number of
clock cycles each instruction requires and subtract that number
from a counter starting at 114.  When the counter is less than
or equal to zero, it is time to update the graphics.



The ANTIC chip handles the timing and memory access between the
6502 and the ANTIC and GITA chips (Note: I assume the U.S. NTSC
television display standard).  The TV paints the picture from
left to right by scanning the electron beam horizontally across
the screen; after it paints one horizontal line, the beam moves
down to paint the next horizontal line.  Each movement of the
electron beam from left to right across the TV screen is called
a horizontal scan (or just scan).  The TV standard specifies 262
horizontal scan lines (rows of video data) to display and entire
TV picture2.  There is an ANTIC register called VCOUNT that
holds the current horizontal scan line (also called the vertical
scan line) number divided by 2, i.e. VCOUNT contains a  number
from 0 to 130.  This number tells us which horizontal TV line
has just been painted.  The hardware register VCOUNT can be use
to synchronize the 6502 with the TV display since we know which
TV scan line is currently being painted by reading the VCOUNT
register.  The emulator needs to keep a counter that simulates
the ANTIC horizontal scan line counter.  The emulator maintains
a variable called Antic_evcount which stands for ANTIC extended
vertical scan line counter.  This variable holds a number from 0
to 261.  This counter is used by the emulator for various
software tests like whether the current scan line is visible
(not all scan lines are displayed on the TV screen).



The hardware register VCOUNT can be used to position graphics on
a particular scan line, ie., at a particular vertical position
on the TV screen, but how do we position the graphics at a
particular horizontal position on the TV screen?  When the Atari
program writes to the hardware location WSYNC (wait for
horizontal sync.) the 6502 is stopped until the start of the
horizontal blank interval (the time interval just after the
current scan line is painted, but before the next scan line is
painted).  The horizontal blanking interval is about 28 clock
cycles long; which means anywhere from 4 to 14 instructions can
execute before the next horizontal scan line appears on the TV. 
We can make a few changes during the horizontal blanking
interval.  WSYNC is often used to change the colors from one
scan line to the next so that we can display 256 colors at the
same time.  Now we can also change the colors in the middle of
the horizontal line by writing directly to the color registers
at a particular instant in time.  For example, the following
Atari program will display five colorful vertical bars:



10			*=$600

20	START	STA WYSNC

30			LDX #5

40	LOOP		DEX

50			BNE LOOP

60			LDA #$11

70			STA COLPF2

80			LDA #$22

90			STA COLPF2

100			LDA #$33

110			STA COLPF2

120			LDA #$44

130			STA COLPF2

140			LDA #$55

150			STA COLPF2

160			JMP START



If you run this program using the Atari Assembler/Editor
cartridge you will notice that the colorful bars have dark green
horizontal bands running through them.  These horizontal bands
are a result of ANTIC reading the character set from memory. 
During this time the 6502 is disabled so that there is no color
update; the last color (in this case dark green) is displayed
during this time.  I guarantee that this program will not work
on any Atari emulator in existence today.  The reason I am so
confident is that for this program to work, the emulator would
have to update the graphics after every pixel (graphics dot) is
displayed on the screen.  To see why, let's look at this program
in more detail.  At line 20 we write to address $d40a (WSYNC);
this cause ANTIC to stop the 6502 until after the current
horizontal line is displayed.  The processor restarts during the
horizontal blanking interval.  Nothing is displayed on the
screen at this time (about 28 clock cycles) so we have a delay
loop (lines 30 through 50) that waits 27 clock cycles.  We write
the first color (lines 60 and 70) on the 33rd clock cycle since
WSYNC; this clock count correlates to the start of the
horizontal scan line painted on the TV.  The first color on the
screen is $11, dark green.    Now these two instructions take 6
clock cycles to complete and ANTIC has some non-zero response
time (ANTIC does not change the color on the TV when you write
it, rather, there is some delay).  The 6502 instruction clock
cycles (6) and the ANTIC delay (~11) puts us on the 50 clock
cycle since WSYNC.  We have changed the color on the TV display
before the current horizontal scan line is completely painted. 
The remaining instructions do the same thing as the two previous
instructions except they write different colors to the color
register.  The only way we could emulate this program is to
write one pixel at a time then run a couple of 6502 instructions
then write the next pixel to the display.  While this would
work, it takes a lot of 80x86 code before we can display a pixel
(see antic.asm).  This would slow the program down to a crawl. 
Even if you were clever and could write a pixel quickly, you
would still have to make a jump or subroutine call the
appropriate graphics function after every 6502 instruction (or
couple of instructions).  



I considered the options and decided that there are very few
programs (other than demos) that do cycle counting to display
graphics.  As a compromise I decided to update the graphics
after every display list instruction has been completely
painted.  For example, ANTIC mode 2 (text mode) paints 40
characters on the screen (or 320x8 pixels) so during a video
update I completely paint the 40 characters and set the cycle
counter (the BP register) to 8*114 (number of scan lines
displayed multiplied by the number of cycles per scan line).  



Now what does all of this have to do with WSYNC?  Since I update
all of the scan lines for a particular graphics mode at the same
time, when a write to WSYNC occurs I have already painted more
the one scan line; therefore any changes made to the Atari
graphics registers will not take effect until the last scan line
of the current graphics mode is painted.  If we are displaying a
high resolution graphics mode like mode F where we paint only
one scan line per display list instruction, then this is not a
problem.  However, for graphics modes that paint more than one
scan line per display list instruction, the display will not be
correct when WSYNC is used.  For more information on scan lines
and graphics modes, see the Atari Technical Reference Manual.



The display list is a set of instructions that tell ANTIC how to
display the display data.  A display list for a standard text
screen might look like:

	*=$7c00

		$70		; Blank 8 scan lines

		$70		; Blank 8 scan lines

		$70		; Blank 8 scan lines

		$42		; ANTIC mode 2 and get graphics data starting at address
$7c40

		$40

		$7C

		$02		; ANTIC mode 2, one line of 40 text characters

		.

		.		; repeat $02 for each line of text that you want on the
screen

		$02		; ANTIC mode 2

		$41		; jmp to $7C00 (top of display list) and wait for
vertical blank

		$00

		$7C

Each line of the display list is an ANTIC instruction or an
Atari RAM address.  In the previous example, instruction $02
tells ANTIC to display one line (8 scan lines) of 40 text
characters.  If we had used the instruction $0F, we would
display one line (one scan line) of 320 bit graphics.  After
each ANTIC instruction we can also call a special routine called
the display list interrupt (DLI).  The DLI allows the Atari
programmer to change the color registers or player/missle
graphics before the next display list instruction executes.  If
bit 7 of the display list instruction is set, then a DLI is
requested.  The DLI occurs after the current display list
instruction is executed (all of the scan lines for the
particular graphics mode are painted).  To emulate the DLI I
only need to test the DLI bit of the display list instruction
and call the DLI routine in the user's Atari code.  The DLI test
is performed in "antic.asm" and the 6502 JSR routine is called
to jump to the display list interrupt routine (see
"hardware.asm").  The variable dli_flag is used to tell
Hardware_Update() in "hardware.asm" whether we need to call the
DLI routine.



Most of the time I spent working on this program was in figuring
out how to handle the timing between the 6502 emulator and the
graphics.  The Apple emulator (from which this code is derived)
used an interrupt and updated the screen 60 times per second. 
If you understood the above discussion, you will also understand
why this method would not work very well for the Atari.  I did
not implement the POKEY chip because the sound is much more
difficult to emulate than the graphics.  Below is a brief
description of how I handle some of the less time critical
functions of the Atari computer.



The sound chip, POKEY, runs independently with respect to the
6502 and the graphics chips.  It seems like it would be straight
foreword to use a sound card to emulate POKEY.  Pure tones can
be emulated this way, but the special effects are more
difficult.  You would need some type of translation table that
converted Atari POKEY commands into the IBM sound card commands.
 Which means someone would have to listen to the Atari sound and
find an equivalent sound on the IBM sound card for every
possible sound combination  This is a time consuming process
that I did not wish to tackle.



Pokey also handles the serial input/output communications
between the Atari computer and its peripherals.  I bypass all of
the SIO code and replace the SIOV vector with an IBM routine to
read Atari image files from the IBM hard drive.  It would also
be easy to add code for a printer and modem (if anyone wants to
tackle this).  When a 6502 'JSR' instruction is encountered, I
call a special routine that checks the jump address to see if it
is the SIOV address.  If it is, I call a subroutine called
my_SIOV in "sio.asm".  I had planned on replacing all of the
Atari OS subroutines with IBM routines, but I ran out of time.



I do not emulate the PIA chip at all.  The PIA chip handles the
joysticks and speaker (on the xl and xe series it also handles
the memory page switching).  Joystick number 1 is emulated using
the number pad on the IBM keyboard (see "keyboard.asm").



Software Structure

In this section, I briefly describe the function of the various
software modules.  But first some miscellaneous information that
might help you slog through the code.



The 8086 uses 64K pages to access code and data.  There are four
special registers that are used to access the 8086 memory; these
register are called segment registers.  The four segment
register are CS, DS, ES, SS.  Each segment register accesses
64Kbytes of IBM RAM. This emulator accesses the emulated Atari
RAM using segment register DS (data segment).  The emulator
variables are accessed using segment register CS (code segment).
 The IBM video memory uses segment ES (extra segment).  When you
look through the code notice that the local variables are
accessed using a segment override, 

			e.g. mov al,cs:nmi_flag.  

Normally the 80x86 uses the DS segment register to access all
data, however I have tied up all of the RAM available accessed
by DS register to emulate the Atari RAM. Therefore all of my
emulator variables are located in the memory accessed by CS.  I
tell the assembler that the data is accessed using the CS
register by prefacing my variable name with cs: (this is a
segment override).



If you look through the Atari Technical Reference Manual you
will notice that the hardware addresses $d000 through $d4ff have
different functions depending on whether you are reading the
register or writing to the register.  To simulate the hardware
registers, we need two separate memory locations: one for read
the register and one for writing to the register.  The Atari
only uses the first 32 hardware addresses for each hardware chip
(ANTIC, GITA, POKEY and PIA).  For example, ANTIC starts at
address $d400 and ends at address $d420; this leaves memory
locations $d421 through $d4ff available.  I map the ANTIC read
registers starting at $d400 and the write registers starting at
$d420.  The Atari hardware registers are read using the true
address, e.g.,

			 	mov di,0d400h		

				mov al,[di]



Here I have moved the Atari hardware address for DMACTL ($d400)
to the index register DI.  Then I read the data at the memory
location  pointed to by register DI, i.e. the data at memory
location 0D400h, into register AL.  When I write to a hardware
address I use a pointer to memory (Antic_RAM)  that is 32 bytes
above the hardware location, i.e. I write to address 0D420h to
write to the DMACTL register.  The variable "Antic_RAM" points
to location 0D420h, so that I can write to DMACTL using: 

				mov	di,0

				mov Antic_RAM[di],al



In file Atari.inc I have equates for all of the Atari registers
that use the names from the OS, e.g. DMACTL equ 0d400h.  I have
a second set of names that point to the write locations, e.g.
LB_DMACTL equ 0.  So that when I want to write to a hardware
location I can do: 



				mov di,LB_DMACTL

				mov Antic_RAM[di],al



You will see this type of operation throughout the code.  All it
means is that I have separated the read and write locations for
the Atari hardware.



Emulate.asm, the 6502 microprocessor emulator

This code was adapted from Randy Spurlock's Apple emulator.  The
emulator starts with the routine called "emulate".  This routine
calls the routine Initialize in "atari.asm".  Next the emulator
loads the program counter with the address in the power up
vector $FFFA.  Essentially, The 6502 emulator is a series of
jumps from one instruction to the next.  If you examine the code
you will see a table called "Opcode_Table" that contains the
addresses for the start of the code for each 6502 instruction. 
After the instruction has completed, a macro called "fetch" (see
macro.inc) is executed which gets the next instruction and uses
the instruction opcode to jump indirectly to the start of the
next instruction.  This leap frogging method is a bit confusing,
but it is faster than making subroutine calls.  



The 80x86 registers CL,CH,DL are used to emulate the 6502
registers A,X, and Y.  The register SI is used as the 6502
program counter.  The 6502 flags are kept in the DH register. 
Register BP is used to keep track of the number of 6502 clock
cycles.  The cycle count determines the number of 6502
instructions that can be executed before a Hardware_Update must
be performed.  The cycle count is set by the ANTIC graphics mode
routines.  The Ticks macro subtracts the number of cycles
required for the current instruction from the BP register.



You really do not need to know how the 6502 emulator code works
(unless you want to) to understand the Atari emulator.  There
are some possible speed improvements for the 6502 emulator. 
First, note that the emulator updates the flags after every
instruction.  Only a few 6502 instructions need these flags so
it is really a waste of time to update the flags after every
instruction.  For the N and Z flags you only need to save the
last register value that effected these flags.  The C and V
flags do need to be updated, but a simple RCL and a MOV can be
used to save the C flag.  Only four instructions effect the V
flag, so this can be updated at the end of  the instruction that
changes it.  The I and D flags rarely change so these can be
stored in memory.  The only time the flags need to be combined
into a single byte is for the PHP instruction.  I saw this
method of keeping track of the flags in at least one 6502
emulator.  I do not think that there will be much speed gained
overall by doing this sort of thing.



Second, the code for each 6502 opcode can be hand optimized to
speed things up.  Currently, a set of macros is used to
implement the 6502 instructions.  The macros are too general and
not efficient.  By hand-coding the routines some instructions
can be combined to gain some speed improvement.  However, I am
not sure that these changes will yield any significant speed
improvement.  Worst of all, these changes may make the code
un-maintainable (difficult for someone else to update). 
Currently, if you want to change the 6502 emulator code, you
alter the macro.  If all of the routines are hand coded for
speed, each routine has to be updated separately.  The more
changes you make, the more likely you are to introduce bugs.



Atari.asm, the atari.exe startup code

Load_System: This routine reads in the file "atari.rom" which
holds the Atari operating system.  The filename can be changed
by modifying the pointer System_ROM located in "data.asm".



Initialize: This routine allocates the 64K RAM for the Atari
memory and the extra 64K RAM for the XL/XE series.  Currently
the extra RAM is only used to swap out Atari Basic.  The
keyboard interrupt is initialized by calling Int_Init (int.asm).
 The MCGA 320x200x256 graphics mode is set up by calling
Video_Init (video.asm).  The keyboard LEDs are set to the
joystick off mode by calling Set_LED (keyboard.asm).  Finally,
the 6502 registers are initialized in CPU_Reset (reset.asm).



Exit: This routine makes a clean exit from the Atari emulator
program, returning control to MSDOS.



Write_Memory: Whenever a 6502 instruction wants to write to
memory, we need to check the address to make sure that the user
is not trying to write to ROM.  Also, if the address is a
hardware chip, we want to write to the memory address + 32 bytes
and take any action required. We do this by jumping to the
appropriate write routine using the ROM_Table located near the
end of this file.  Currently, we can jump to one of three
routines: STD_Mem_Write, ROM_Write, and Write_Hardware.   This
routine can be deleted to speed things up, but you will have to
make a few changes to the Atari OS.



System_Request: Simulates an Atari Break by setting the break
flag in POKMSK and setting the interrupt request flag so that
Hardware_Update can set up the interrupt address.



System_Access: Sets a flag in response to the user hitting the
F12 key so that a call to routine Access is made during
Hardware_Update.



Access: This routine displays the Atari Emulator status and
allows the user to load files and turn on and off Basic.  One
trick should be noted: the two zeros at the end Stat1 and Stat2
hold the string length for the file names in filenum1 and
filenum2.  Do not separate or reorder these variables.



Rom_Write: Does nothing



Memory.asm

Clear_Memory: Called by Initialize to clear the Atari memory



STD_Mem_Write: Called by Write_Memory to write to the Atari Ram



Video.asm

COLOR_TABLE: All of the Atari to IBM colors are mapped here. 
Many of the colors do not match the Atari colors.  This is where
you change them.



Video_Init: Sets up the IBM MCGA 320x200x256 graphics mode by
calling Video_MCGA_OPEN and set up the video address in ES.



Video_Reset: Restores the video to 80x25 text mode by calling
Video_Text_OPEN.



Int.asm

Int_Init: Replaces the keyboard interrupt routine with INT_KEY.



Int_Reset: Restores the old keyboard interrupt vector.



Reset.asm

CPU_Reset: Resets the 6502 registers



Keyboard.asm

INT_KEY: This routine checks to see if the key was pushed down
(make) or let go (break).  The the key stroke is translated to
an Atari keycode and a special routine is called if necessary. 
For example hitting the F1 key calls the Atari_Reset routine. 
The routines are numerous so just take a look at the source
code.  



Data.asm

This file contains various data tables that are used throughout
the program.



Hardware.asm

Hardware_Update: This routine is run every time the BP register
goes to zero.  The BP register is set by the ANTIC routines and
decreased by the 6502 emulator.  This routine runs a number of
tests to see if we need to call the ANTIC routines.  Next
Player_Missle routine is called if needed.  Then a check for an
nmi or interrupt flag is performed.  To understand exactly what
this routine does, you will have to go through the code line by
line.  



Note that the TV display starts when the variable Antic_evcount
is 8.  At the end of the display list there is a JVB (jump to
top of display list and wait for vertical blank).  This
instruction sets the Antic_wait flag to 1.  If this flag is 1,
nothing is displayed until Antic_evcount counts to 8.    Also
note that Antic_evcount has a maximum count of 262.  When
Antic_evcount is greater than or equal to 262 it is reset back
to zero.  



The Atari computer can display more than the 200 scan lines that
the IBM displays.  There are two variables that control what
portion of the Atari screen is visible on the IBM display. 
These variables are sTOP and sBOT.  When the program is running,
these values can be changed by using Control PageUp or Control
PageDown keys.  You will also notice that some routines test the
current Antic_evcount against the sTOP or sBOT variables.  These
checks are done to ensure that any display data in excess of 200
scan lines is truncated.



Write_Hardware: This routine determines which hardware chip is
being addressed and calls the appropriate routine.

Jsr_Steal: This routine is call from emulate.asm when the 6502
instruction is a JSR.  Currently, I only check to see if the
address is the SIOV vector.  If it is then I call my own
routine, my_siov.  You could replace all of the Atari OS
subroutines with IBM routines and eliminate the need for the
Atari ROMs. while speeding up the Atari emulator.



Do_Nothing: This is a dummy routine to account for the holes in
the Atari hardware address space.



Pokey_Update: Writes to the POKEY write memory location, reset
the interrupt status bits and resets the SKSTAT register.



Pia_Update: Currently only writes to the PIA write memory 
location.  Nothing is done with the values written there.



 Antic.asm

The routines here emulate each of the ANTIC graphics modes 2
through F.  (I also wanted to implement the GITA graphics modes,
but I simply forgot how GITA worked.)  There are two additional
ANTIC instruction: Antic_Blank and Antic_Jmp.  In order to
understand how the code that emulate ANTIC modes 2 through F
works, you need to be very familiar with each of the ANTIC
modes.  Once you understand the graphics modes, you should be
able to go through Antic_mode2() through Antic_modeF() line by
line and figure out what is going on.  I discuss the code for
the ANTIC modes in general terms.  If you need to know exactly
what is going on you will have to go through each of the
individual routines.



Antic_Blank: The Antic chip can place from 1 to 8 blank lines on
the screen.  It seems trivial to emulate a blank line function,
however there are some difficulties.  First, the TV has 262 scan
line of which anywhere from 200 to 240 are visible depending on
the TV.  The IBM leaves little choice in the screen dimension;
the closest "standard" IBM video mode to the Atari is the
320x200 pixel mode with 256 colors.  So while the Atari can
paint 240 horizontal lines on the screen, the emulator can only
paint 200.  This is not a real problem because most Atari
programs only use 200 lines anyway for the actual display.  The
problem is that many programs use the blank lines to be sure
that the next line painted onto the screen will be visible on
the TV.  So here is the problem: since the first line we paint
in the IBM display will be visible, we have no need for these
blank lines.  If we paint these blank lines anyway, we lose part
of our display.  If we do not paint these blank lines then the
whole screen may be moved up.  



I solve the problem in two ways.  First, I have two variables
sTOP and sBOT that define the top and bottom of the screen with
respect to the current vertical scan line count (Antic_evcount).
  (Note that sBOT-sTOP = 200 scan lines.)  I only paint the
blank lines that would be visible on the IBM display.  This
method will only work when the Atari program expects only 200
lines to be visible on the TV.  However, when more than 200 scan
lines are non-blank the bottom of the display will be cut off. 
In "keyboard.asm" I have two routines called ScreenUP() and
ScreenDOWN() that change sTOP and sBOT to move the image on the
screen up and down.  These routines are called when Control Page
Up or Control Page Down keys are pressed by the user.  This
allows the user to decide how the screen should be displayed.



Antic_JMP: The Antic JMP instruction has two purposes: (1) to
load a new display list address and (2) to jmp to the start of
the display list address and wait for vertical blank.  The only
trick here is with item (2).  When bit 6 of the JMP instruction
is set, this is the end of the display.  I set a flag called
Antic_wait that is used by Hardware_Update() so that no other
display instructions are called until the Antic_evcount is equal
to 8.  In addition, I clear the  rest of the screen (if we are
not already at the bottom of the display).



Antic Modes: Here is some general information that is common to
all of the ANTIC graphics modes.  



Variables:



instr_count: This value is altered in antic.asm and copied to
the bp register in hardware.asm.  The 6502 emulated instruction
subtract the number of clock cycles per second from the bp
register; when the bp register is zero, it is time to run
Hardware_Update().



Hsync: This value is the clock cycles per horizontal sync.  and
is initially set to 128.  Hsync is used by the ANTIC routines to
compute the number of clock cycles for instr_count.  Increasing
the value of Hsync results in more 6502 emulated instructions
executing before another Hardware_Update() occurs.  This value
can be increased and decreased while the Atari emulator is
running by hitting the ALT Page UP or ALT Page DOWN keys,
respectively.



sTOP: The top of the IBM screen with respect to Antic_evcount.

sBOT: The bottom of the IBM screen with respect to Antic_evcount.



Video_Pntr_Cur: This is a pointer to the IBM video RAM that
points to the current pixel location.  This value is increased
each time a pixel is written and reset to zero when the ANTIC
instruction jump and wait for vertical sync is issued.



Video_Pntr_Old: This value points to the position of the IBM
video RAM before the last ANTIC instruction was executed (before
the previous scan lines were painted).  This variable is used by
gita.asm so that the players can be drawn on top of the scan
lines just painted.



Antic_dlist: This variable points to the display list in the
emulated Atari RAM.

Antic_pc: This is the ANTIC program counter

Antic_evcount: This is the current vertical TV line out of 262
lines.

Antic_memscan: This variable points to the current address for
the data to be displayed on the emulated Atari screen.



Antic_Old_memscan: In the ANTIC modes where we are painting more
than one scan line, the display data has to be used more than
once.  We simply keep a copy so that we can display the same
data more than once.



Antic_wait: This is a flag that tells Hardware_Update() whether
it should call the Antic routines.  This flag is set to 1 by the
ANTIC instruction jmp and wait for vertical interrupt
(Antic_jmp()).  Hardware_Update set this value to 0 when
Antic_evcount = 8.



Antic_sc: The value is set by the antic routines and used by
player_missle() in gita.asm.  This value is the number of scan
lines just painted by ANTIC.



Antic_dliflag: This flag is set by the ANTIC routines if
Hardware_Update needs to perform a display list interrupt.



ch1: This variable is used by the ANTIC text modes to hold the
display data.



 Gita.asm

Player_Missile: This routine was written after I had decided not
to finish this emulator.  I only wrote this routine because I
was not sure how to explain the method I was going to use to
implement the player/missile graphics.  Obviously it is used to
display the player/missile graphics.  I did not implement the
missile graphics because it seemed pointless until I figured out
how to implement collision detection.  Instead of talking about
how the players were implemented, I want to explain my ideas on
how to implement Player-Playfield collision detection. 
Collision detection is a group of registers that tell the
program whether or not the players and missile graphics are on
top of (or underneath) the playfield colors.  It is easy to
determine if a player or missile is on top of the playfield. 
The playfield data has been written to the IBM video RAM before
the Player_Missile() routine is called.  We simply look at the
IBM video memory location where we are going to  write the
non-zero player/missile pixel and see if it is a non-background
color.  If it is then we know we have a collision.  The tricky
bit is figuring out which playfield color register is associated
with our non-background color.  I decided that the best way is
to keep a reverse playfield color table.  That is if we write
color 134 to color register COLPF1 then we would write the
address of COLPF1 into our table at location 134, e.g. 

			mov COLOR_TABLE[134],COLPF1

Now when we read the non-background color from the IBM video
RAM, we can get the associated Atari color register by using
this table.  Once we know the color register, we can set the
proper bits in the collision registers.  Player-Player collision
are fairly straightforword so I won't discuss them.

 Summary

I have not adequately discussed the theory of operation of the
Atari emulator.  Part of the problem is that the reader needs to
be very familiar with programming the Atari or I need to spend a
lot of time discussing how the Atari works.  Since I am not
qualified to write a text on programming the Atari, I have to
assume that the reader has some level of competence in Atari
programming.  Having said that, I hope that I have at least
provided some insight into how to write an Atari emulator.  

_______________________________________________________________________________

1 I had intended to also do the GITA graphics modes, but I
forgot what they were and how they worked.  I haven't done any
real programming for the Atari since 1984 when I wrote an FFT
algorithm that took 8 hours to run a 1024 point FFT and
subsequently bought an IBM PC.

2 There is actually 525 horizontal scan lines that are
interleaved, but the Atari does not do interleaving so we only
care about half of these lines, i.e. 525/2 = 262.5.

