Вы находитесь на странице: 1из 77

ARITHMETIC

CHAPTER 1

1.1.

Input and output of numbers

When working with numbers one often wants to input and output them via
the screen. The following programs show how th is can be done with
hexadecimal as well as decimal numbers.
1.1.1.

Hexadecimal input

This program allows you to enter hexadecimal numbers using the keyboard.
The number entered is displayed on the screen. The input stops if a
character different from the hexadecimal numbers (0.. F) is entered.
The program first deletes memory locations EXPR and EXPR+1. This ensures a
result equal to zero, even if an invalid number is entered. Next, the
program reads a character and checks whether or not it is a hexadecimal
number. If it is, then the upper bits of the number in the accumulator are
erased and the lower bits are shifted up. Now, these four bits can be
shifted to EXPR from the right. The preceeding number in EXPR is shifted to
the left by doing so.
If you enter a number with more- than four digits, only the last four
digits are used.
Example : ABCDEF => CDEF

HEXINPUT ROUTINE

A800:
A802:
A804:
A806:
A809:
A80B:
A80D:
A80F:
A811:
A813:
A815:
A817:
A819:
A81B:
A81C:
A81D:
A81E:
A81F:
A821:

A2
86
86
20
C9
94
C9
90
C9
90
C9
80
E9
0A
0A
0A
0A
A2
0A

00
80
81
2C A8
30
1E
3A
0A
41
16
47
12
36

EXPR
SCROUT
GETCHR

EQU
EQU
EQU
ORG

HEXIN

LDX
STX
STX
JSR
CMP
BCC
CMP
BCC
CMP
BCC
CMP
BCS
SBC
ASL
ASL
ASL
ASL
LDX
ASL

HEXINI

HEXIN2

04
HEXIN3

$80.1
$F6A4
$F6DD
$A800
#0
EXPR
EXPR+1
NEXTCH
'0
HEXRTS
'9+1
HEXIN2
'A
HEXRTS
'F+1
HEXRTS
'A-10-1

#4

A822:
A824:
A826:
A827:
A829:
A82B:

26
26
CA
DO
FO
60

80
81

EXPR
EXPR+1

JSR
JSR
RTS

GETCHR
SCROUT SHOW CHARAC'.

F8
DB

ROL
ROL
DEX
BNE
BEQ
RTS

HEXRTS

A82C: 20 DD F6
A82F: 20 A4 F6
A832: 60

NEXTCH

HEXIN3
HEXINI ALWAYS !!

PHYSICAL ENDADDRESS: $A833


*** NO WARNINGS
EXPR $80
GETCHR
HEXIN1
HEXIN3
NEXTCH

$F6DD
$A806
$A821
$A82C

SCROUT
HEXIN
HEXIN2
HEXRTS

$F6A4
$A800 UNUSED
$A81b
$A82B

1.1.2.

Hexadecimal output

The next program explains the output process of the calculated numerals.
You will recognize, that the portion of the program which controls the
output is a subroutine. This subroutine only displays the contents of the
accumulator. This means that you first have to load the accumulator with,
for example, the contents of EXPR+1, then jump into the subroutine where
first the MSB (EXPR+1 in our case) and then the LSB (EXPR) will be printed.
Subroutine PRBYTE independently prints the most significant bytes of the
accumulator first and the least significant bytes second.

HEXOUT PRINTS 1 BYTE

EXPR
SCROUTE
A800:
A802:
A805:
A807:
A80A:

A5
20
A5
20
60

81
0B A8
80
A8

PRWORD

EPZ
EQU
ORG
LDA
JSR
LDA
JSR
RTS

$80.1
$F6A4
$A800
EXPR+1
PRBYTE
EXPR
PRBYTE

* THE VERY PRBYTE ROUTINE


A80B: 48
A80C: 4A

PRBYTE

PHA
LSR

A80D:
A80E:
A80F:
A810:
A813:
A814:
A816:
A818:
A81A:
A81C:
A81E:
A820:

4A
4A
4A
20
68
29
C9
B0
09
D0
69
4C

16 A8
0E
0A
04
30
02
36
A4 F6

HEXOUT

ALFA
HXOUT

LSR
LSR
LSR
JSR
PLA
AND
CMP
BCS
ORA
BNE
ADC
JMP

HEXOUT
#$00001111
#10
ALFA
'0
HXOUT
'A-10-1
SCROUT

PHYSICAL ENDADDRESS:$A823
*** NO WARNINGS
EXPR
PRWORD
HEXOUT
HXOUT

$80
$A800
$A816
$A820

SCROUT
PRBYTE
ALFA

$F6A4
SA80P
$A81E

1.1.3.

Decimal input

UNUSED

When you calculate with numbers you probably prefer decimals over
hexadecimals. The following program can be used to read decimal numbers and
convert them into binary numbers readable by computers.
The program first checks, to see if the input is a decimal number (0..9)
or if the input has been. terminated by another character. EXPR and EXPR+1
are erased. If a digit is accepted then the upper bits are erased. Next the
contents of EXPR and EXPR+1 are multiplied by 10 and the new number is
added. In the end the MSB is in location EXPR+1 and the LSB is in location
EXPR.
Numbers greater than 65535 are displayed in modulo 65536 (the rest which
remains after deduction of 65535).

DECIMAL TO 1 WORD CONVERSION

A800: A2 00

EXPR
SCROUT
GETCHR

EQU
EQU
EQU
ORG

$80.1
$F6A4
$F6DD
$A800

DECIN

LDX

#0

A802:
A804:
A806:
A809:
A80B:
A80D:
A80F:
A811:
A813:
A815:

86
86
20
C9
90
C9
B0
29
A2
D0

80
81
26 A8
30
18
3A
14
0E
11
05

A817:
A819:
A81B:
A81C:
A81E:
A820:
A821:
A823:
A825:
A826:
A829:
A82C:

90
69
4A
66
66
CA
DO
F0
60
20
20
60

02
09

DEC2

81
80

DEC3

DEC1

F4
E1
DD F6
A4 F6

DECEND
NEXTCH

STX
STX
JSRN
CMP
BCC
CMP
BCS
AND
LDX
BNE

EXPR
EXPR+1
EXTCH
'0
DECEND
'9+1
DECEND
#$00001111
#17
DEC3

BCC
ADC
LSR
ROR
ROR
DEX
BNE
BEQ
RTS
JSR
JSR
RTS

*+4
#10-1

ALWAYS TAKEN ! !

EXPR+1
EXPR
DEC2
DEC1

ALWAYS ! !

GETCHR
SCROUT

PHYSICAL ENDADDRESS: $A82D


*** NO WARNINGS
EXPR
GETCHR
DEC1
DEC3
NEXTCH
SCROUT
DECIN
DEC2
DECEND

$80
$F6DD
$A806
$A81C
$A826
$F6A4
$A800 UNUSED
$A817
$A825

1.1.4.

Decimal output

The next program allows you to display decimal numbers.


The program works as follows:
The X-register is loaded with the ASCII equivalent of the digit 0. This
number is then incremented to the highest potency of 10 (10000) and is
displayed on the screen.
The same procedure is repeated for 1000, 100, and 10. The remaining is
converted into an ASCII number, using an OR-command, and is displayed.
You might want to change the output routine so that it avoids leading
zeroes.

2 BYTE BINARY NUMBER TO 5 DIGITS DECIMAL


CONVERSION WITH LEADING ZEROES

A800:
A802:
A804:
A805:
A807:
A80A:
A80B:
A80C:
A80E:
A811:
A813:
A815:
A816:
A818:
A819:
A81A:
A81C:
A81D:
A81E:
A820:
A823:
A825:
A826:
A828:
A82A:
A82C:

A0 07
A2 30
38
A5 80
F9 2E
48
88
A5 81
F9 30
90 09
85 81
68
85 80
E8
C8
DO E8
68
8A
84 82
20 A4
A4 82
88
10 DA
A5 80
0930
4C A4

A82F:
A831:
A833:
A835:

0A
64
E8
10

DECL
DECH
TEMP

EQU
EQU
EQU

$80
$81
$82

SCROUT

EQU
ORG

$F6A4
$A800

DECOUT
DECOUT1
DECOUT2

LDY
LDX
SEC
LDA
SBC
PHA
DEY
LDA
SBC
BCC
STA
PLA
STA
INX
INY
BNE
PLA
TXA
STY
JSR
LDY
DEY
BPL
LDA
ORA
JMP

#7
'0

DFW
DFW
DFW
DFW

10
100
1000
10000

A8

A8

DECOUT3
F6

F6

00
00
03
27

DECTAB

PHYSICAL ENDADDRESS:
*** NO WARNINGS
DECL
TEMP
DECOUT
DECOUT2
DECTAB
DECH

$80
$82
$A800
$A804
$A82F
$81

DECL
DECTAB-1,Y
DECH
DECTAB+1,Y
DECOUT3
DECH
DECL
DECOUT2
TEMP
SCROUT
TEMP
DECOUT1
DECL
'0
SCROUT

$A837

UNUSED

SCROUT
DECOUTI
DECOUT3

$F6A4
$A802
$A81C

1.2.

16-bit arithmetic without sign

1.2.1.

16-bit addition

The 16-bit addition is well known, but it is shown here one more time,
together with the subtraction.

16 BIT ADDITION UNSIGNED INTEGER


EXPR : = EXPR1 + EXPR2

EXPRl
EXPR2

A800:
A801:
A803:
A805:
A807:
A809:
A80B:
A80D:

18
A5
65
85
A5
5
85
60

$80.1
$82.3

ORG

$A800

CLC
LDA
ADC
STA
LDA
ADC
STA
RTS

EXPR1
EXPR2
EXPR1
EXPR1+1
EXPR2+1
EXPR1+1

ADD

EPZ
EPZ

80
82
80
81
83
81

PHYSICAL ENDADDRESS: $A80E


*** NO WARNINGS
EXPR1
EXPR2
ADD

$80
$82
$A800

1.2.2.

16-bit subtraction

UNUSED

16 BIT SUBTRACTION UNSIGNED INTEGER


EXPR : = EXPR1 - EXPR2

EXPR1
EXPR2

EPZ
EPZ

$80.1
$82.3

ORG

$A800

A800:
A801:
A803:
A805:
A807:
A809:
A80B:
A80D:

38
A5
E5
85
A5
E5
85
60

SUB

SEC
LDA
SBC
STA
LDA
SBC
STA
RTS

80
82
80
81
83
81

EXPR1
EXPR2
EXPR1
EXPR1+1
EXPR2+l
EXPR1+1

PHYSICAL ENDADDRESS: $A80E


*** NO WARNINGS
EXPR1
EXPR2
SUB

$80
$82
$A800

1.2.3.

16-bit multiplication

UNUSED

The multiplication is much more complicated than addition or subtraction.


Multiplication in the binary number system is actually the same as in the
decimal system. LPt's have a look at how we multiply using the decimal
system. For example, how do we calculate 5678*203?

5678

203*
17034
00000
11356
=
1152634

With each digit the previous number is shifted to the right. If the
digit is different from zero the new interim results are added. In the
binary system it works the same way. For example:
1011
1101 *
1011
0000
l0ll
l0ll
=
10001111
.
As you can see it is simpler in the binary system than in the decimal
system. Since the highest possible number for each digit is 1 the highest
interim results is equal to the multiplicand.
The following program in principle does the same as the procedure
described above, except that the interim result is shifted to the right and
the multiplicand is added, if required. The results are the same.
Six memory locations are required. Two of these (SCRATCH and SCRATCH+1)
are used only part of the time, while the other four locations keep the two
numbers to be multiplied (EXPR1 and EXPR1+1, EXPR2 and EXPR2+1). After the
calculations the result is in locations EXPR1 (LSB) and EXPR1+1 (MSB).

16 BIT MULTIPLICATION UNSIGNED INTEGER


EXPR := EXPR * EXPR2

EXPR1
EXPR2
SCRATCH

A800:
A802:
A804:
A806:
A808:
A80A:
A80B:
A80D:
A80F:
A811:
A813:
A815:
A817:
A819:
A81B:
A81D:
A81F:
A820:
A822:
A824:
A826:

A2
86
86
A0
D0
18
A5
65
85
A5
65
85
46
66
66
66
88
30
90
B0
60

00
84
85
10
0D

$80.1
$82.3
$84.5

ORG

$A800

LDX
STX
STX
LDY
BNE
CLC
LDA
ADC
STA
LDA
ADC
STA
LSR
ROR
ROR
ROR
DEY
BMI
BCC
BCS
RTS

#0
SCRATCH
SCRATCH+1
#16
MUL2 ALWAYS !!

MUL

EPZ
EPZ
EPZ

MUL1
84
82
84
85
83
85
85
84
81
80

MUL2

04
F3
E4
MULRTS

SCRATCH
EXPR2
SCRATCH
SCRATCH+1
EXPR2+1
SCRATCH+1
SCRATCH+1
SCRATCH
EXPR1+1
EXPR1
MULRTS
MUL2
MUL1

PHYSICAL ENDADDRESS: $A827


*** NO WARNINGS
EXPR1
EXPR2
SCRATCH
MUL
MUL1
MUL2
MULRTS

$80
$82
$84
$A800
$A80A
$A817
$A826

1.2.4.

16-bit division

UNUSED

The division of two numbers actually is just the opposit of the


multiplication. Therefore, you can see in the program below, that the
divisor is subtracted and the dividend is shifted to the left rather than

to the right. The memory locations used are the same as with the
multiplication, except that locations SCRATCH and SCRATCH+1 are named
REMAIN and REMAIN+1. This means the remainder of the division is stored in
those locations.

16 BIT DIVISION UNSIGNED INTEGER


EXPR1 : = EXPR1 OVER EXPR2
REMAIN : = EXPR1 MOD EXPR2

EXPR1
EXPR2
REMAIN

A800:
A802:
A804:
A806:
A808:
A80A:
A80C:
A80E:
A810:
A811:
A813:
A815:
A816:
A818:
A81A:
A81C:
A81E:
A820:
A822:
A823:
A825:

A2
86
86
A0
06
26
26
26
38
A5
E5
AA
A5
E5
90
86
85
E6
88
D0
60

00
84
85
10
80
81
84
85

$80.1
$82.3
$84.5

ORG

$A800

LDX
STX
STX
LDY
ASL
ROL
ROL
ROL
SEC
LDA
SBC
TAX
LDA
SBC
BCC
STX
STA
INC
DEY
BNE
RTS

#0
REMAIN
REMAIN+1
#16
EXPR1
EXPR1+1
REMAIN
REMAIN+1

DIV

EPZ
EPZ
EPZ

DIV1

84
82
85
83
06
84
85
80
DIV2
E3

REMAIN
EXPR2
REMAIN+1
EXPR2+1
DIV2
REMAIN
REMAIN+1
EXPR1
DIV1

PHYSICAL ENDADDRESS: $A826


*** NO WARNINGS
EXPR1
EXPR2
REMAIN
DIV
DIV1
DIV2

$80
$82
$84
$A800
$A808
$A822

UNUSED

STRINGOUTPUT
CHAPTER 2

2.1.

Output of text

With most programs it is necessary to display text (menues etc.).


The following program allows you to display strings of any length at any
location you desire. The output command can be located at any place within
your program.
How does that program work ?
As you know the 6502 microprocessor uses its stack to store the return
address if a JSR-command is to be executed. The number that is stored on
the stack actually is the return-address minus one. The trick used in this
program is, that the string to be printed is stored immediately after the
JSR-command and the last character of the string is incremented by 128. The
subroutine calculates the start address of tie string, using the number on
the stack, and reads the string byte by byte, until it finds the byte which
has been incremented by 128. The address of this byte now is stored on the
stack and an RTScommand is executed. 8y doing so, the string is jumped and
the command after it is executed.

STRINGOUTPUT FOR VARIOUS


LENGTH

AUX
SCROUT

A800:
A803:
A806:
A809:
A80C:
A80F:
A812:
A815:

20
54
53
53
4E
58
50
60

16
48
20
20
20
41
4C

A816: 68
A817: 85 80
A819: 68

A8
49
49
41
45
4D
C5

EPZ
EQU

$80
$F6A4

ORG

$A800

*
EXAMPLE
EXAMPLE
JSR PRINT
ASC \THIS IS AN EXAMPLE

RTS
*

THE VERY PRINTROUTINE

PRINT

PLA
STA
PLA

AUX

10

A81A:
A81C:
A81E:
A820:
A822:
A824:
A826:
A828:
A82B:
A82D:
A82F:
A831:
A833:
A834:
A836:
A837:

85
A2
E6
D0
E6
A1
29
20
A2
A1
10
A5
48
A5
48
60

81
00
80
02
81
80
7E
A4 F6
00
80
ED
81

STA
LDX
INC
BNE
INC
LDA
AND
JSR
LDX
LDA
BPL
LDA
PHA
LDA
PHA
RTS

PRINT1

80

AUX+1
#0
AUX
*+4
AUX+1
(AUX,X)
#$7F
SCROUT
#0
(AUX,X)
PRINTI
AUX+1
AUX

PHYSICAL ADDRESS: $A838


*** NO WARNINGS
AUX
SCROUT
EXAMPLE
PRINT
PRINT1

S80
$F6A4
$A800
$A816
$A81E

UNUSED

11

INTRODUCTION TO CIO
CHAPTER 3
The CIO can handle up to 8 devices/files at the same time. This happens
via so called Input Output Control Blocks (IOCB). This means that there are
8 IOCB's starting from $0340. Each of the IOCB's is 16 bytes long.

BLOCK #

ADDRESS

IOCB #0

$0340

IOCB #1

$0350

IOCB #2

$0360

IOCB #3

$0370

IOCB #4

$0380

IOCB #5

$0390

IOCB #6

$03A0

IOCB #7

$03B0

A single IOCB has the following internal scheme:

NAME

ADDRESS

ICHID

HANDLER ID

ICDNO

DEVICE NUMBER

ICCMD

COMMAND

ICSTA

STATUS

ICBAL
ICBAH
ICPTL
ICPTH
ICBLL
ICBLH

BUFFERADR
PUTADR
BUFFERLEN

ICAX1

AUX1

ICAX2

AUX2

ICAX3
ICAX4

Remaining

ICAX5

4 bytes

ICAX6
There are just a few locations which are important to the user:

12

- The commandbyte which contains the command to be executed by the CIO.


- The bufferaddress wh ich contains the address of the actual databuffer.
The bufferlength which contains the number of bytes to be transferred
(rounded up to a variety of 128 bytes for the cassette device)
- And there are two auxiliaries which contain device-dependent information.
There are also locations which will be altered by CIO such as:
- The handler-ID is an offset to the devicetable. This table contains all
devicenames and pointers to the device specific handlertable.

device name
one entry

handler table
address
other
entries
zero fill to
end of table

A handlertable looks like:

OPEN-1
CLOSE-1
GETBYTE-1
PUTBYTE-1
GETSTATUS-1
SPECIAL-1
JMP INIT
&

00

The CIO is thus quite clear to the user. It is easy to add new devices
by adding just 3 bytes to the devicetable and to make a specific
handlertable for this device. You can also change the handlerpointer of an
existing device and let point it to a new handler. Later we will describe
how to add or change devices.
- The devicenumber shows us which subdevice is meant. (e.g. Disknumber or
RS232 Channel).
- After calling CIO the status will be altered. A 1 means a successfull
operation while a value greater than 128 means an error has occurred.
- PUTADR is used internally by the CIO
- If there have been less bytes transferred than desired, because of an EOL
or an error, BUFLEN will contain the actual number of transferred bytes.
The standard CIO commands:
- OPEN opens a file.
Before execution the following IOCB locations have to be set:
COMMAND = $03

13

BUFFADR points to, device/filename specification (like C: or D: TEST. SRC)


terminated by an EOL ($98)
AUX1 = OPEN-directionbits (read or write) plus devicedependent information.
AUX2 = devicedependent information.
After execution:
HANDLER ID = Index to the devicetable.
DEVICE NUMBER = number taken from device/f filename specification
STATUS = result of OPEN-Operation.
- CLOSE closes an open IOCB
Before execution the following IOCB location has to be set:
COMMAND = $0C
After execution: HANDLER ID = $FF
STATUS = result of CLOSE-operation
- GET CHARACTERS read byte aligned. EOL has no termination feature.
Before execution the following IOCB locations have to be set:
COMMAND = $07
BUFFERADR = points to databuffer.
BUFFERLEN = contains number of characters to be read. If BUFFERLEN is equal
to zero the 6502 A-register contains the data.
After execution:
STATUS = result of GET CHARACTER-operation
BUFFERLEN = number of bytes read to the buffer. The value will always be
equal before execution, only if EOF or an error occurred.
- PUT CHARACTERS write byte aligned
Before execution the following IOCB locations have to be set:
COMMAND = $0B
BUFFERADR = points to the datab~ffer
BUFFERLEN = number of bytes to be put, if equal to zero the 6502 A-register
has to contain the data.
After execution:
STATUS = result of PUT CHARACTER-operation
GET RECORD characters are read to the databuffer until the buffer is full,
or an EOL is read from the device/file.
Before execution the following IOCB locations have to be set:
COMMAND = $05
BUFFERADR = points to the databuffer.
BUFFERLEN = maximum of bytes to be read (Including EOL character)
After execution:
STATUS = result of the GET RECORDoperation
BUFFERLEN = number of bytes read to buf fer this may less then the maximum
length.
- PUT RECORD characters are written to the device/file from the databuffer
until the buffer is empty or an EOL is written. If the buffer is empty CIO
will automatically send an EOL to the device/file.
Before execution the following IOCB locations have to be set:
COMMAND = $09
HUFFERADR = points to databuffer.
BUFFERLEN = maximum number of bytes in databuffer.
After execution:
STATUS = result of PUT RECORD-operation.

14

In addition to the main-commands, there is also a GET STATUS ($0D)


command, which obtains the status from the device/filecontroller and places
these four bytes from location $02EA (DVSTAT). Commands greater than $0D
are so called SPECIALS and devicehandler-dependent.
GET STATUS and SPECIALS have an implied OPEN-option. Thus the file will be
automatically opened and closed if it wasn't already opened.
How to link the CIO with machine language?
First we have to modify the IOCB before calling CIO.
The offset to the IOCB (IOCB# times 16 ) has to be in the X-register.
The STATUS will be loaded in the Y-register of ter returning from CIO. It
is not necessary to explicitly check the Y-register (Comparing with 128)
because loading the status into the Y-register was the last instruction
before leaving CIO with an RTS. We simply jump on the signflag (BMI or
BPL). The sign flag is set if an error occurred. In the next section we
will discuss it in more detail with an example.
How to read or write data in machine language?
To describe the writing of data to a device/file we will take the
cassettedevice as an example. We can also use any other device because CIO
is very clear-cut (see introduction).
Before discussing the program, some conventions must be discussed.
The user has to put the address of his databuffer into the locations
BUFFER ($80.1) and the bufferlength into the locations BUFLEN ($82.3). Then
the program should be called as a subroutine. The description of this
subroutine follows.
First we have to open the cassette, so we load the IOCB-offset in the Xregister, store the OPEN-command in ICCMD, and let the BUFADR (ICBAL and
ICBAH) point to the device/filename specification. We have to store the
write-direction in ICAX1 and the tape-recordlength (128) in ICAX2, just
call CIO ($E456). The Signflag indicates if an error occurred.
After a correct opening of the file for writing data, bit 3 is set
because AUX1 contains a $08 (bit 2 is readbit).

AUX1
1

ICCMD will be changed into the PUT CHARACTERS-command ($0B), BUFFADR


points to the User-Databuffer (contents of BUFFER) and BUFLEN (ICBLL and
ICBLH) will contain the number of bytes to write (the user stores this
value BUFLEN ($82. 3)). Next CIO will be called, and after successfull
operation, the file will be closed (ICCMD=$0C).
If, during any of these three CIO-calls, an error occurs, the file will
be closed and both the ACCUMULATOR and Y-register will contain the STATUS
(errorcode).
By changing the string at CFILE in for instance D:TEST.TST the program
will write the buffer to the specified diskfile.
The second listing shows you a program that reads from a device, only
two bytes are different, so the program is selfexplaining.

15

WRITE BUFFER TO CASSETTE

BUFFER
BUFLEN

EPZ
EPZ

ICCMD
ICBAL
ICBAH
ICBLL
ICBLH
ICAX1
ICAX2

EQU
EQU
EQU
EQU
EQU
EQU
EQU

$80.1
$82.3 - BUFLEN ROUNDED
UP TO 128 BYTES
$0342
$0344
$0345
$0348
$0349
$034A
$034B

OPEN
PUTCHR
CLOSE

EQU
EQU
EQU

3
11
2

WMODE
RECL

EQU
EQU

8
128

CIO

EQU

$E456

EOL

EQU

$9B

IOCBNUM

EQU

ORG

$A800

*
A800:
A802:
A804:
A807:
A809:
A80C:
A80E:
A811:
A813:
A816:
A818:
A81B:
A81E:

A2
A9
9D
A9
9D
A9
9D
A9
9D
A9
9D
20
30

10
03
42
08
4A
80
4B
56
44
A8
45
56
29

03
03
03
03
03
E4

OPEN FILE
LDX
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
JSR
BMI

#IOCBNUM*16
#OPEN
ICCMD,X
#WMODE
ICAXI,X
#RECL
ICAX2,X
#CFILE:L
ICBAL,X
#CFILE:H
ICBAH,X
CIO
CERR

* PUT BUFFER IN RECORDS TO CASSETTE

16

A820:
A822:
A825:
A827:
A82A:
A82C:
A82F:
A831:
A834:
A836:
A839:
A83C:

A9
9D
A5
9D
A5
9D
A5
9D
A5
9D
20
30

0B
42
80
44
81
45
82
48
83
49
56
08

LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
JSR
BMI

03
03
03
03
03
E4
*

A83E:
A840:
A843:
A846:

A9
9D
20
30

0C
42 03
56 E4
01

CLOSE CASSETTE FILE


LDA
STA
JSR
BMI

*
A848: 60

#PUTCHR
ICCMD,X
BUFFER
ICBAL,X
BUFFER+1
ICBAH,X
BUFLEN
ICBLL,X
BUFLEN+1
ICBLH, X
CIO
CERR

#CLOSE
ICCMD,X
CIO
CERR

RETURN TO SUPERVISOR
RTS

* RETURN WITH ERRORCODE IN ACCUMULATOR


A849:
A84A:
A84B:
A84D:
A850:
A853:
A854:
A855:
A856:
A858:

98
48
A9
9D
20
68
A8
60
43
9B

CERR
0C
42 03
56 E4

3A

CFILE
DFB

TYA
PHA
LDA
STA
JSR
PLA
TAY
RTS
ASC
EOL

#CLOSE
ICCMD,X
CIO

"C:"

PHYSICAL ENDADDRESS: $A859


*** NO WARNINGS
BUFFER
BUFLEN
ICCMD
ICBAL
ICBAH
ICBLL
ICBLH
ICAX1
ICAX2
OPEN
PUTCHR
CLOSE
WMODE
RECL
CIO
EOL

$80
$82
$0342
$0344
$0345
$0348
$0349
$034A
$034B
$03
$0B
$0C
$08
$80
$E456
$9B

17

IOCBNUM
CERR
CFILE

$01
$A849
$A856

READ BUFFER FROM CASSETTE

BUFFER
BUFLEN

EPZ
EPZ

$80.1
$82.3

ICCMD
ICBAL
ICBAH
ICBLL
ICBLH
ICAX1
ICAX2

EQU
EQU
EQU
EQU
EQU
EQU
EQU

$0342
$0344
$0345
$0348
$0349
$034A
$034B

OPEN
GETCHR
CLOSE

EQU
EQU
EQU

3
7
12

RMODE
RECL

EQU
EQU

4
128

CIO

EQU

$E456

EOL

EQU

$9B

IOCBNUM

EQU

ORG

$A800

*
A800:
A802:
A804:
A807:
A809:
A80C:
A80E:
A811:
A813:
A816:
A818:
A81B:
A81E:

A2
A9
9D
A9
9D
A9
9D
A9
9D
A9
9D
20
30

10
03
42
04
4A
80
4B
56
44
A8
45
56
29

OPEN FILE
LDX
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
JSR
BMI

03
03
03
03
03
E4
*

BUFLEN ROUNDED
UP TO 128 BYTES

#IOCBNUM*16
#OPEN
ICCMD,X
#RMODE
ICAXI,X
#RECL
ICAX2,X
#CFILE:L
ICBAL,X
#CFILE:H
ICBAH,X
CIO
CERR

GET BUFFER IN RECORDS FROM CASSETTE

18

A820:
A822:
A825:
A827:
A82A:
A82C:
A82F:
A831:
A834:
A836:
A839:
A83C:

A9
9D
A5
9D
A5
9D
A5
9D
A5
9D
20
30

07
42
80
44
81
45
82
48
83
49
56
0B

LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
JSR
BMI

03
03
03
03
03
E4
*

A83E:
A840:
A843:
A846:

A9
9D
20
30

0C
42 03
56 E4
01

A848: 60

A849:
A84A:
A84B:
A84D:
A850:
A853:
A854:
A855:
A856:
A858:

98
48
A9
9D
20
68
A8
60
43
9B

CLOSE CASSETTE FILE


LDA
STA
JSR
BMI

#GETCHR
ICCMD,X
BUFFER
ICBAL,X
BUFFER+1
ICBAH,X
BUFLEN
ICBLL, X
BUFLEN+1
ICBLH,X
CIO
CERR

#CLOSE
ICCMD,X
CIO
CERR

RETURN TO SUPERVISOR
RTS

RETURN WITH ERRORCODE ACCUMULATOR

CERR

TYA
PHA
LDA
STA
JSR
PLA
TAY
RTS
ASC
DFB

0C
42 03
56 E4

3A

CFILE

#CLOSE
ICCMD,X
CIO

"C:"
EOL

PHYSICAL ENDADDRESS: $A859


*** NO WARNINGS
BUFFER
BUFLEN
ICCMD
ICBAL
ICBAH
ICBLL
ICBLH
ICAX1
ICAX2
OPEN
GETCHR
CLOSE
RMODE
RECL
CIO
EOL

$80
$82
$0342
$0344
$0345
$0348
$0349
$034A
$034B
$03
$07
$0C
$04
$80
$E456
$9B

19

IOCBNUM
CERR
FILE

$01
$A849
$A856

INTRODUCTION TO THE DISK CONTROLLER


CHAPTER 4
We already know how to handle any device/file via CIO, including handle
a diskfile. Included on a disk is also a sector-IO which allows you to
address a single sector for a read or write handling. Sector-IO doesn't
need any file on the disk. The disk has only to be formatted.
A floppy disk with the ATARI drive has 720 sectors and each of them is
fully addressable.
How does the sector-IO function?
The disk controller has a simplistic design containing a single IOCB
like Data Control Block (DCB). This DCB is described in the following
scheme.
DCBSBI

Serial bus ID

DCBDRV

Disk drive #

DCBCMD

Command

DCBSTA

IO Status

DCBUF LO
DCBUF HI
DCBTO LO
DCBTO HI
DCBCNT LO
DCBCNT HI
DCBSEC LO
DCBSEC HI

Buffer IO address
Timeout counter
IO Buffer length
IO Sector number

Instead of a handler-ID there is a BUS ID (DCBSBI) to address a


particular diskdrive via the Serial-Bus of the ATARI.
Also a logical drivenumber (DCBDRV )
A commandbyte (DCBCMD), which is similar to an IOCB, and 5 commands for
sector-IO, which will be described later.
The statusbyte for error detection after, and data-direction previous to
execution of the command ($80 is write, $40 is read).
The DCBBUF locations (L and H) to point to the databuffer.
DCBTO (L and H) is a special word containing the maximum time for
executing a command, so called timeout.
DCBCNT (L and H) is a device specific word which contains the sector
length (128 for the 810-drive or 256 for the double density drives).
DCBSEC (L & H) contains the sector number to do IO on.

20

The DCB-commands
Prior to executing any DCB-command, the following DCB-entries must be
set.
DCBSBI has to contain the bus-ID of the drive:
DRIVE 1 = $31 = '1
DRIVE 2 = $32 = '2
DRIVE 3 = $33 = '3
URIVE 4 = $34 = '4
DCBDRV has to contain the logical drive number (1..4).
DCBTO the timeout (normally 15; lowbyte=$0F highbyte=$00).

-READ SECTOR reads one sector specified by the user


DCBCMD = $52 = 'R
DCBBUF = points to databuffer
DCBCNT = contains sector length
DCBSEC = number of sector to read
After execution:
DCBSTAT = result of HEAD SECTUR-operation

-PUT SECTOR writes one sector specified by the user without verify.
DCBCMD = $50 = 'P
DCBBUE' = points to databufter
DCBSEC = number of sector to write
After execution:
DCBSTAT = result of PUT SECTOR-operation

-WRITE SECTOR writes one sector specified by the user with automatic
verify.
DCBCMD = $57 = 'W
Further like PUT SECTOR.

-STATUS REQUEST obtains the status from the specified drive.


DCBCMD = $53 = 'S
After execution:
DCBSTAT = result of STATUS REQUESToperation

21

The drive outputs four bytes end the controller puts them to $02EA
(DVSTAT).
-FORMAT formats the specified disk.
DCBCMD = $21 = '!
DCBTO = has to be larger than 15 due to more time taken by the FORMATcommand. You can ignore the error, but this will be risky.
After execution:
DCBSTAT = result of the FORMAT-operation.
How is the disk controller invoked?
Because the disk controller is resident, this is a simple process. You
don't have to load DOS, nor anything similar. You just have to call the
SIO (Serial IO $E459) instead of the CIO. Therefore, you can see that it
is quite easy to link the Diskcontroller with machine language.
How to write a sector to disk
The first program writes a specified sector from a buffer to
diskdrive#1. There are a few conventions to call this program as
subroutine. The user has to put the buffer address into the pointer
locations labelled BUFFER and the sector number into the locations
labelled SECTR. The program also needs a RETRY-location, to serve as a
counter so the program is able to determine how of ten it will retry the
IO.
The next paragraph describes the subroutine.
At first we built the DCB, special we move a $80 (BIT 3 the write bit
is set) to DCBSTA and we retry the IO 4 times. SIO does, as well as CIO,
load the STATUS into the Y-register so you only have to check the
signflag again. After an error occurence we decrement the retry value
and set DCBSTA again, then try again.
By using this program, you only have to look at the signflag after
returning for error detection (signflag TRUE means error, otherwise
success).
The second program reads a sector instead of writing it. The only two
bytes which are different are the DCBCMD and the DCBSTA ($90 for read) .

WRITE A SECTOR TO DISK

SECTR
BUFFER
RETRY

EQU
EQU
EQU

$80.1
$82.3
$84

DCBSBI
DCBDRV
DCBCMD
DCBSTA
DCBBUF
DCBTO

EQU
EQU
EQU
EQU
EQU
EQU

$0300
$0301
$0302
$0303
$0304
$0306

22

A800:
A802:
A805:
A807:
A80A:
A80C:
A80F:
A811:
A814:
A816:
A819:
A81B:
A81E:
A820:
A823:
A825:
A828:
A82A:
A82D:
A82F:
A831:
A833:
A836:
A838:
A83B:
A83E:
A840:
A842:
A844:
A846:
A849:
A84C:
A84F:

A5
8D
A5
8D
A5
8D
A5
8D
A9
8D
A9
8D
A9
8D
A9
8D
A9
8D
A9
85
A9
8D
A9
8D
20
10
C6
30
A2
8E
4C
AC
60

82
04
83
05
80
0A
81
0B
57
02
80
03
31
00
01
01
0F
06
04
84
80
08
00
09
59
0C
84
08
80
03
3B
03

DCBCNT
DCBSEC

EQU
EQU

$0308
$030A

SIO

EQU

$E459

ORG
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
JSR
BPL
DEC
BMI
LDX
STX
JMP
LDY
RTS

$A80 0
BUFFER
DCBSUF
BUFFER+1
DCBBUF+1
SECTR
DCBSEC
SECTR+1
DCBS EC+1
'W
DCBCMD
#$80
DCBSTA
'1
DCBSBI
#1
DCBDRV
#15
DCBTO
#4
RETRY
# 12 8
DCBCNT
#0
DCBCNT+1
SIO
WRITEND
RETRY
WRITEND
#$80
DCBSTA
JMPSIO
DCBSTA

WRITSECT
03
03
03
03
03
03
03
03
03

03
03
E4

JMPSIO

03
A8
03

WRITEND

REPLACE "W" BY A "P" IF


YOU WANT IT FAST

PHYSICAL ENDADDRESS: $A850


*** NO WARNINGS
SECTR
RETRY
DCBDRV
DCBSTA
DCBTO

$80
$84
$0301
$0303
$0306

BUFFER
DCBSBI
DCBCMD
DCBBUF
DCBCNT

23

$82
$0300
$0302
$0304
$0308

DCBSEC
WRITSECT
WRITEND

$030A
$A800
$A84C

SIO
JMPSIO

UNUSED

READ A SECTOR FROM DISK

A800:
A802:
A805:
A807:
A80A:
A80C:
A80F:
A811:
A814:
A816:
A819:
A81B:
A81E:
A820:
A823:
A825:
A828:
A82A:
A82D:
A82F:
A831:
A833:

A5
8D
A5
8D
A5
8D
A5
8D
A9
8D
A9
8D
A9
8D
A9
8D
A9
8D
A9
85
A9
8D

82
04
83
05
80
0A
81
0B
52
02
40
03
31
00
01
01
0F
06
04
84
80
08

SECTR
BUFFER
RETRY

EQU
EQU
EQU

$80.1
$82.3
$84

DCBSBI
DCBDRV
DCBCMD
DCBSTA
DCBBUF
DCBTO
DCBCNT
DCBSEC

EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU

$0300
$0301
$0302
$0303
$0304
$0306
$0308
$030A

SIO

EQU

$E459

ORG

$A800

LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA

BUFFER
DCBSUF
BUFFER+1
DCBBUF+1
SECTR
DCBSEC
SECTR+1
DCBS EC+1
'R
DCBCMD
#40
DCBSTA
'1
DCBSBI
#1
DCBDRV
#15
DCBTO
#4
RETRY
#128
DCBCNT

READSECT
03
03
03
03
03
03
03
03
03

03

24

$E459
$A83B

A836:
A838:
A83B:
A83E:
A840:
A842:
A844:
A846:
A849:
A84C:
A84F:

A9
8D
20
10
C6
30
A2
8E
4C
AC
60

00
09
59
0C
84
08
80
03
3B
03

03
E4

JMPSIO

03
A8
03

READEND

LDA
STA
JSR
BPL
DEC
BMI
LDX
STX
JMP
LDY
RTS

#0
DCBCNT+1
SIO
READEND
RETRY
READEND
#$80
DCBSTA
JMPSIO
DCBSTA

PHYSICAL ENDADDRESS: $A850


*** NO WARNINGS
SECTR
BUFFER
RETRY
DCBSBI
DCBDRV
DCBCMD
DCBSTA
DCBBUF
DCBTO
DCBCNT
DCBSEC
SIO
READSECT
JMPSIO
READEND

$80
$82
$84
$0300
$0301
$0302
$0303
$0304
$0306
$0308
$030A
$E459
$A800
$A83B
$A84C

UNUSED

25

HOW TO MAKE A BOOTABLE PROGRAM


CHAPTER 5
What is a bootable program ?
A bootable program is a program which will be automatically loaded at
powering up the ATARI, and directly after loading be executed.
A bootable program needs a header with specific information about the
program, such as the length and the start address. The header of a bootable
program looks like the following scheme:
# Byte

Destination

unused (0)

# of 128bytes sectors

Store

Address

Initialization

Address

boot

continuation

code

The first byte is unused, and should equa1 zero.


The second byte contains the length of the program, in records (128
bytes length), (rounded up).
- The next word contains the store address of the program.
- The last word contains the initialization-address of the program. This
vector will be transferred tb the CASINI-vector ($02.3).
After these 6 bytes there has to be the boot continuation code. This is
a short program, the OS will jump to directly after loading. This program
can continue the boot process (multistage boot) or stop the cassette by the
following sequence
LDA
STA

#$3C
PACTL ; $D302

The program then allows the DUSVEC ($OA. e) to point to the start
address of the program. It is also possible, to store in MEMLO ($02E7. 8),
the first unused memory address. The continuation code must return to the
OS with C=0 (Carry clear). Now OS jumps via DOSVEC to the application
program.
So far we know what a bootable cassette looks like, but how do we create
such a bootable tape?

26

If there is a program, we only have to put the header in front of it


(including the continuation code) and to save it as nornml data on the
tape. We can use the later described program to write the contents of a
buffer on the tape or the boot generator.
If the program is saved, we can put the tape in the recorder, press the
yellow START-key, power on the ATARI and press RETURN. Now the program on
the tape will be booted.
The next listing shows us the general outline of a bootable program.

GENERAL OUTLINE OF AN
BOOTABLE PROGRAM

PROGRAM START
ORG
*

(OR AN OTHER)

THE BOOTHEADER
PST
DFW
DFW
DFW

$A800

DFB 0
SHOULD BE 0
PND-PST+127/128 # OF RECORDS
PST
STORE ADDRESS
INIT
INITALIZATION ADDRESS

THE BOOT CONTINUATION CODE


LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
CLC
RTS

#$3C
PACTL
#PND:L
MEMLO
#PND:H
MEMLO+1
#RESTART:L
DOSVEC
#RESTART:H
DOSVEC+1

STOP CASSETTE MOTOR

SET MEMLO TO END OP PROGRAM

SET RESTART VECTOR IN OOSVECTOR


RETURN WITH C=0 (SUCCESSFULL BOOT)

INITIALIZATION ADDRESS

INIT

RTS

THE MAIN PROGRAM

RESTART

EQU *

RTS IS THE MINIMUM PROGRAM

27

THE MAIN PROGRAM ENDS


PND

EQU *

HERE
NEXT FREE LOCATION

How to make a bootable disk?


Making a bootable disk is in fact the same as for the cassette. The only
exceptions are as follows.
The program (including the header) must be stored up from sector one.
The boot continuation code doesn't need to switch off anything such as the
cassette motor.
How to create a bootable disk?
This is only a bit more complicated than the cassette version. We need
our writesector program we described earlier. Then we have to write, sector
by sector, to disk. You can also make a bootable cassette first and then
copy it directly to disk with the later discussed program.

28

HOW TO MAKE A BOOTABLE CARTRIDGE


CHAPTER 6
Preparing the program.
Most of the games and some other programs written in machine language
are stored in a cartridge. Booting a program, the OS recognizes the
cartridge and starts the program.
What do you have to do when you want to make a bootable cartridge of
your own program ?
As an example we will make a cartridge with a program for testing the
memory. The bit pattern
10101010
01010101
00000000
11111111

=
=
=
=

$AA
$55
$00
$FF

is written in every memory location starting above the hardware stack at


address $200. First the content is saved, then the bit pattern is written
into and read from the memory location. If there is any difference in
writing and reading the program prints an error message : ERROR IN <~R> .
Then the program waits in an endless loop. If the error message is ERROR IN
A000, the RAM is ok because $A000 is the first address of the ROM in the
left cartridge.
The address range for the left cartride ranges from $A000 to $BFFF and
$8000 to $9FFF for the right cartridge. As starting address for our memory
test prograM we choose $BF00. This is the last page of the left cartridge.
The software for the EPROM burner is also stored in a cartridge. Therefore
the object code generated by the assembler is stored at $9000.
Like a bootable program the cartridge has a header. The following scheme
shows the outline of this cartridge header.

CARTRIDGE

$BFFA or $9FFA

START ADDRESS
00

OPTION BYTE

CARTRIDGE INIT

$BFFF or $9FFF

ADDRESS

The header for the right cartridge starts at $9FFA, for the left
cartridge (the more important for us) at $BFFA.

29

The first two bytes contain the start address of the cartridge.
The third byte is the cartridge-ID. It shows the OS that a cartridge has
been inserted. It must be 00.
- The fourth byte is the option-byte. This byte has the following options:
BIT-0 = 0 don't allow diskboot 1 allow diskboot
BIT 2 = 0 only initialize the cartridge 1 initialize and start the
cartridge
BIT 7 = 0 Cartridge is not a diagnostic cartridge
1 Cartridge is a diagnostic cartridge
before OS is initialized the cartridge takes control
- The last two bytes contain the cartridge initialiZation address.
The initialization address is the starting address of a program part
which is executed in advance of the main program. If there is no such a
program this address must be the address of an RTS instruction. In our
example the low byte of the starting address $BF00 is stored in location
$BFFA, the high byte in location $BFFB.
The option byte in location $BFFD is 04.
The program in the cartridge is initialized and started, but there is no
disk boot. The initializing address is $BF63, an RTS instruction within the
program.
After assembling and storing the object code the burning of an EPROM can
start.

GENERAL OUTLINE
OF A CARTRIDGE

THE CARTRIDGE START (LEFT CARTRIDGE)

ORG
$A000
$8000 FOR RIGHT CARTRIDGE
THE INITIALIZATION ADDRESS

INIT

RTS

THE MAIN PROGRAM

RESTART

EQU

THE CARTRIDGE HEADER

ORG

$BFFA

$9FFA FOR RIGHT CARTRIDGE

DFW
DFB
DFB
DFW

RESTART
0
OPTIONS
INIT

THE CARTRIDGE ID SHOULD BE ZERO


THE OPTION BYTE
THE CARTRIDGE INITIALIZATION ADDRESS

30

Sample program for a cartridge:

MEMORY TEST

BF00:
BF02:
BF05:
BF08:
BF0B:
BF0E:
BF11:
BF13:
BF15:
BF17:
BF19:
BF1B:
BF1D:
BF1F:
BF21:
BF24:
BF26:
BF29:
BF2B:
BF2E:
BF30:
BF33:
BF35:
BF37:
BF39:
BF3B:
BF3D:
BF3E:
BF40:
BF43:

A9 7D
20 A4 F6
20 64 BF
4D 45 4D
4F 52 59
205445
53 D4
A0 00
84 F0
A9 02
85 F1
B1 F0
85 F2
A9 AA
20 59 BF
A9 55
20 59 BF
A9 00
20 59 BF
A9 FF
20 59 BF
A5 F2
91 F0
E6 F0
D0 E0
E6 F1
18
90 DB
20 64 BF
45 52 52

AUXE
TEST
OUTCH

EPZ
EPZ
EQU
ORG

$FE
$F0
$F6A4
$BF00,$9000

START

LDA
JSR
JSR
ASC

#$7D
OUTCH
MESS
\MEMORY TEST\

LDY
STY
LDA
STA
LDA
STA
LDA
JSR
LDA
JSR
LDA
JSR
LDA
JSR
LDA
STA
INC
BNE
INC
CLC
BCC
JSR
ASC

#00
TEST
X02
TEST+1
(TEST),Y
TEST+2
#$AA
TST
#$55
TST
#00
TST
#$FF
TST
TEST+2
(TEST),Y
TEST
TESTl
TEST+1

TEST1

FIN

TEST1
MESS
\ERROR IN \

31

BF46:
aF49:
BF4C:
BF4E:
BF51:
RF53:
BF56:
BF59:
BF5B:
BF5D:
BF5F:
BF61:
BF63:
BF64:
BF65:
BF67:
BF68:
BF6A:
BF6C:
BF6E:
BF70:
BF72:
BF74:
BF76:
BF79:
BF7B:
BF7D:
BF7F:
BF81:
BF82:
BF84:
BF85:
BF86:
BF87:
BF88:
BF89:
BF8A:
BF8B:
BF8E:
BF8F:
BF91:
BF93:
BF95:
BF97:
BF99:
BF9A:
BF9C:

4F 52
49 4E
A5 F1
20 86
A5F0
20 86
4C 56
85 F3
91 F0
B1 F0
C5 F3
D0 D0
60
68
85 FE
68
85 FF
A2 00
E6 FE
D0 02
D6 FF
A1 FE
29 7F
20 A4
A2 00
Al FE
l0 ED
A5 FF
48
A5 FE
48
60
48
4A
4A
4A
4A
20 91
68
29 0F
C9 0A
B0 04
09 30
D0 03
18
69 37
4C A4

20
A0
BF
BF
BF

FINI
TST

FRTS
MESS
STA

MS1

F6

PPRTBYT

BF

HEX21

BUCHSST
F6

HEXOUT

LDA
JSR
LDA
JSR
JMP
STA
STA
LDA
CMP
BNE
RTS
PLA
AUXE
PLA
STA
LDX
INC
BNE
INC
LDA
AND
JSR
LDX
LDA
BPL
LDA
PHA
LDA
PHA
RTS
PHA
LSR
LSR
LSR
LSR
JSR
PLA
AND
CMP
BCS
ORA
BNE
CLC
ADC:
JMP

TEST+1
PRTBYT
TEST
PRTBYT
FINI
TEST+3
(TEST),Y
(TEST),Y
TEST+3
FIN

ORG

$BFFA, $90FA

AUXE+1
#0
AUXE
*+4
AUXE+1
(AUXE,X)
#$7F
OUTCH
#0
(AUXE,X)
MS1
AUXE+1
AUXE

HEX21
#$OF
#9+1
BUCHST
'0
HEXOUT
'A-10
OUTCH

32

BFFA:
BFFC:
BFFD:
BFFE:

00 BF
00
04
63 BF

DFW
DFB
DFB
DFW

START
00
04
DRTS

PHYSICAL ENDADDRESS: $9100


*** NO WARNINGS

EPROMBURNER FOR THE ATARI 800 / 400


With this epromburner you can burn your EPROMS. It is possible to burn
four different types. The four types are the 2532(4k), the 2732(k),the
2516(2k) and the 2716 (2k). The burner uses the game ports 1, 2 and 3.
1) THE HARDWARE
The circuit of the epromburner is shown in FIG.1.The data for the burner
is exchanged via game port 1 and 2. The control signals are provided by
game port 3. The addresaes are decoded by two 7 bit counters 4024. The
physieal addressesss for the EPROMS are always in the range of 0000 to 07FF
for 2k and 0000 to 0FFF for 4k. This counter is reset by a signal, decoded
from PB0 and PB1 via the 74LS139. PB2 is used to decide if a 2532, or a
2716 has to be burned.
Not all signals for the different types of EPROMS are switched by
software. A three pole, double throw switch is used to switch between the
different types. The software tells you when you have to set the switch
into the correct position. For burning, you need a burn voltage of 25
Vo1ts. This voltage is converted from the 5 Volts of the game port to 28
Volts by the DCDC converter DCP528. This voltage is limited to 25 Volts by
two Zener diodes in serie (ZN24 and ZN1). Three universal NPN transistors
are used to switch between low level voltages and the high level of the
burning voltage.

Fig.1 Eprom burner schematic


3) THE SOFTWARE

33

The software for the burner is completely written in machine code. It comes
on a bootable diskette. To load the program, insert the disk and REMOVE ALL
CARTRIDGES. Turn on the disk drive and the ATARI. After a short moment, you
will see the first menue:

WHICH EPROM DO YOU WANT TO BURN?

A)
B)
C)

2532
2732
2716, 2516

WHAT:

You are asked what type of EPROM you want to burn. After typing the
apriopriate character, you get the message to set the switch to the correct
position and insert the EPROM. This is shown in the following example:

WHICH EPROM DO YOU WANT TO BURN?

D)
E)
F)

2532
2732
2716, 2516

WHAT:
SET SWITCH TO POSITION 2532
NOW INSERT EPROM
PRESS SPACE BAR

Then, pressing the space bar, you see the main menue:

R)EAD EPROM
W)RITE EPROM
E)PROM ERASED
V)ERIFY PROGRAM
M)EMORY DUMP
R)AM
E)PROM
S)ET EPROM TYPE

34

WHAT:

First we want to R)EAD an EPROM. Type R and then the addresses FROM
and TO. The physical addresses of the EPROM are always in range between
0000 and 0FFF. You can read the whole EPROM or only a part of it. Next
you to type the address INTO which the content of the EPROM is read. All
addresses which are not used by the system or the burner software (A800
to AFFF) are accessible. By typing Y after the question OK (Y/N), the
program is loaded. There is a very important key, X key. This key cancels
tlhe input and leads back to the main menue. An example of reading an
EPROM is shown in the next figure:

R)EAD EPROM
W)RITE EPROM
E)PROM ERASED
V)ERIFY PROGRAM
M)EMORY DUMP
R)AM
E)PROM
S)ET EPROM TYPE
WHAT:
EPROM FROM:0000
TO :0FFF
RAM INTO:5000
OK. (Y/N)

To verify that the content of the RAM is identical the content of the
EPROM, type V. After specifing addresses for the EPROM and the RAM and
typing Y, the contents are compared. If there are any differences you
get an error message, such as the following:

R)EAD EPROM
W)RITE EPROM
E)PROM ERASED
V)ERIFY PROGRAM
M)EMORY DUMP
R)AM
E)PROM
S)ET EPROM TYPE
WHAT:
EPROM FROM:0000
TO :0FFF
RAM INTO:5000
OK. (Y/N)
DIFFERENT BYTES FF 00 IN 5000
PRESS SPACE BAR

35

You may then make a memory dump. Type M for M)EMORY, either R for R)AM
or E for E)PROM, and the address range. There is a slight difference in
memory dumps. With the memory dump of RAM, , the bytes are printed, if a is
possible, as ASCII characters.
Burning an EPROM begins by testing as to whether or not the EPROM is
erased in the address range you want to burn. Type E and the address
range. You will get the message EPROM ERASED when the assigned address
range has been erased, or the message EPROM NOT ERASED IN CELL NNN.
For writing the EPROM, type W, the address range in RAM, and the
starting address in EPROM. After hitting Y, you have to wait two minutes
for burning 2k and four minutes for burning 4k. Don't get angry, the
program will stop. After burning one cell the program does an automatic
verify. If there is a difference you receive the error message EPROM NOT
PROGRAMMED IN CELL NNN and the burning stops. Otherwise if all goes well
the message EPROM PROGRAMMED is printed.
For changig the type of EPROM you want to burn, type S. The first menue
is shown and you can begin a new burning procedure.
PARTS LIST.
IC1
IC2,IC3
IC4
IC5
T1,T2,T3
Rl
R2,R3
R4,R5
Z1
Z2
Ml
C1,C2
C3
S1
1
3
2
3

74LS139
4024
4016
4049
UNIVERSAL NPN TRANSISTOR 30V, 0.3W (2N3390 2N3399)
470K RESISTOR
10K
RESISTOR
33K
RESISTOR
1V
ZENER DIODE
24V
ZENER DIODE
DCP528
DCDC CONVERTER ELPAC POWER SYSTEMS
100nF CAPACITOR
10uF TANTAL CAPACITOR
3P2T SWITCH
24PIN TEXTOOL SOCKET
14PIN IC SOCKET
16PIN IC SOCKET
FEMALE PLUGS, ATARI GAME CONNECTORS

5) STEP BY STEP ASSEMBLING.


1.
Insert and solder sockets.
*
Component side showss the text EPROMBURNER.
2.
Insert and solder resistors.
3.
Insert and solder Zener diodes.
*
The anodes are closest to the transistors.
4.
Insert and solder transistors.
5.
Insert and solder capacitors.
*
The + pole of the tantal is marked.
6.
Mount the DCDC converter module.
7.
Turn the board to the soldering side.

36

8.
*
*
9.
*
l0.
11.
12.
*

Insert from this side the TEXTOOLL socket.


The knob shoulld be in the upper right corner.
Solder the socket.
Make the connections on the switch. (FIG.5)
Connect switch and board via a 7 lead flatband cable.
Connect the plugs to the board. (FIG.5)
Insert the integrated circuits. (FIG.2)
Turn off the ATARI. Insert the plugs.
Insert the diskette and turn on the ATARI.

HEXDUMP of the EPROM BURNER software


A800
A808
A810
A818
A820
A828
A830
A838
A840
A848
A850
A858
A860
A868
A870
A878
A880
A888
A890
A898
A8A0
A8A8
A8B0
A8B8
A8C0
A8C8
A8D0
A8D8
A8E0
A8E8
A8F0
A8F8
A900

2076A9204CA82078
A8006885EE6885EF
A200E6EED002E6EF
A1EE297F20A4F6A2
00A1EE10EDA5EF48
A5EE4860A5FD2940
F006A5FE0901D004
A5FE290E8D01D348
68AD00D348A5FE8D
01D36860A90085F0
85F185F8A9308D03
D3A90F8D01D385F5
A9348D03D3A9FF85
F4A9B085F9A9028D
01D360A99B4CA4F6
A97D20A4F6A90585
54A90A8555A90085
56200AA852294541
44204550524FCD20
73A8A90A8555200A
A857295249544520
4550524FCD2073A8
A90A8555200AA845
2950524F4D204552
415345C42073A8A9
0A8555200AA85629
4552494659205052
4F475241CD2073A8
A90A8555200AA84D
29454D4F52592044
554DD02073A8A90D
8555200AA8522941
CD2073A8A90D8555

v) L( x
(@hEnhEo
"@fnPBfo
!n) $v"
@!nPm%oH
%nH'% )@
pF% IAPD
% )NMASH
h-@SH% M
ASh')@Ep
EqEx)0NC
S)OMASEu
)4MCS) E
t)0Ey)BM
AS')[L$v
) $v)EE
T)JEU)@E
V J(R)EA
D EPROM
s()JEU J
(W)RITE
EPROM s(
)JEU J(E
)PROM ER
ASED s()
JEU J(V)
ERIFY PR
OGRAM s(
)JEU J(M
)EMORY D
UMP s()M
EU J(R)A
M s()MEU

37

A908
A910
A918
A920
A928
A930
A938
A940
A948
A950
A958
A960
A968
A970
A978
A980
A988
A990
A998
A9A0
A9A8
A9B0
A9B8
A9C0
A9C8
A9D0
A9D8
A9E0
A9E8
A9F0
A9F8
AA00
AA08
AA10
AA18
AA20
AA28
AA30
AA38
AA40
AA48
AA50
AA58
AA60
AA68
AA70
AA78
AA80

200AA8452950524F
CD2073A8A90A8555
200AA85329455420
4550524F4D205459
50C52073A82073A8
A90A8555200AA857
484154BA20F0AE48
20A4F668C952D003
4C30ACC957D0034C
10ADC945D0034C8B
ACC956D0034C2DAF
C953D0034C76A9C9
4DD0034CFBADA9FD
20A4F66C0A00A97D
20~A4F62073A8200A
A857484943482045
50524F4D20444F20
594F552057414E54
20544F204255524E
20BFA9088554A90A
8555200AA8412920
323533B22073A8A9
0A8555200AA84229
20323733B22073A8
A90A8555200AA843
2920323731362032
3531B62073A82073
A8A90A8555200AA8
57484154BA20F0AE
4820A4F66885FCC9
41D006A90085FDF0
12C942D006A98085
FD3008C943D078A9
C085FD2073A82073
A8200AA853455420
5357495443482054
4F20504F53495449
4F4EA0A5FCC941D0
0A200AA8323533B2
18901EC942D00A20
0AA8323733B21890
10C943D032200AA8
3237313620323531
B62073A82073A8A9
0A8555200AA84E4F
5720494E53455254
204550524FCD20D7
AB208FAA4C03A8A9

J(E)PRO
M s()JEU
J(S)ET
EPROM TY
PE s( s(
)JEU J(W
HAT: p.H
$vhIRPC
L0,IWPCL
P-IEPCLK
,IVPCL-/
ISPCLv)I
MPCL{-)
Sv1J@)
$v s( J
(WHICH E
PROM DO
YOU WANT
TO BURN
?)HET)J
EU J(A)
2532 s()
JEU J(B)
2732 s(
)JEU J(C
) 2716,2
516 s( s
()JEU J(
WHAT: p.
H $vhE|I
APF)@E p
RIBPF)@E
0HICPx)
@E s( s
( J(SET
SWITCH T
O POSITI
ON %|IAP
J J(2532
XP^IBPJ
J(2732XP
PICP2 J(
2716,251
6 s( s()
JEU J(NO
W INSERT
EPROM W
+ O*LC()

38

AA88
AA90
AA98
AAA0
AAA8
AAB0
AAB8
AAC0
AAC8
AAD0
AAD8
AAE0
AAE8
AAF0
AAF8
AB00
AB08
AB10
AB18
AB20
AB28
AB30
AB38
AB40
AB48
AB50
AB58
AB60
AB68
AB70
AB78
AB80
AB88
AB90
AB98
ABA0
ABA8
ABB0
ABB8
ABC0
ABC8
ABD0
ABD8
ABE0
ABE8
ABF0
ABF8
AC00

FD20A4F64CEDA920
73A8A90A8555200A s
A850524553532053
50414345204241D2
20F0AE602073A8A9
0A8555200.A84F4B
2028592F4EA920F0
AE4820A4F668C94E
F003A90060A90160
484A4A4A4A20DBAA
68290FC90AB00409
30D0031869374CA4
F6A90085F285F385
FEA90485FC20F0AE
48C99BF00320A4F6
68C9303025C94710
21C93A3007C94130
191869090A0A0A0A
A0042A26F226F388
D0F8A98085FEC6FC
D0CB60A9308D02D3
A9FF8D00D3A9348D
02D360A9308D02D3
A9008D00D3A9348D
02D3602073A820FD
AEA90A8555200AA8
46524F4DBA20E9AA
A5FE300DA5F120D0
AAA5F020D0AA4C79
ABA5F285F0A5F385
F12073A8A90A8555
200AA8544F2020BA
20E9AAA5FE300DA5
F520D0AAA5F420D0
AA4CA4ABA5F285F4
ASF385F5A5FB302E
2073A82015AFA90A
8555200AA8494E54
4FBA20E9AAA5FE30
0DA5F920D0AAA5F8
20D0AA4CD6ABA5F2
85F8A5F385F960A9
0185FEA90385FCA9
0985FFA5FD1021A9
041865FE85FEA904
1865FC85FCA90418
65FF85FFA5FD2940
F006A5FE290F85FE

$vLm)
s()JEU J
(PRESS S
PACE BAR
p.' s()
JEU J(OK
(Y/N) p
.H $vhIN
pC)@')A'
HJJJJ [*
h)OIJ0DI
0PCXi7L$
v)@ErEsE
)DE| p.
HI[pC $v
hI00%IGP
!I:0GIA0
YXiIJJJJ
D*&r&sH
Px)@E F|
PK')0MBS
) M@S)4M
BS')0MBS
)@M@S)4M
BS s(
.)JEU J(
FROM: i*
% 0M%q P
*%p P*Ly
+%rEp%sE
q s()JEU
J(TO :
i*% 0M%
a P*%t P
*L$+%rEt
%sEu%{0.
s( U/)J
EU J(INT
O: i*% 0
M%y P*%x
P*LV+%r
Ex%sEy')
AE )CE|)
IE % P!)
DXe E )D
Xe|E|)DX
e E % )@
pF% )OE

39

AC08
AC10
AC18
AC20
AC28
AC30
AC38
AC40
AC48
AC50
AC58
AC60
AC68
AC70
AC78
AC80
AC88
AC90
AC98
ACA0
ACA8
ACB0
ACB8
ACC0
ACC8
ACD0
ACD8
ACE0
ACE8
ACF0
ACF8
AD00
AD08
AD10
AD18
AD20
AD28
AD30
AD38
AD40
AD48
AD50
AD58
AD60
AD68
AD70
AD78
AD80

60A5F085F2A5F185
F3A5F2D002A5F3F0
16A5FC8D01D3A5FE
8D01D3C6F2A5F2C9
FFD0E6C6F310E260
A98085FAA90085FB
203BAB204BAB20AC
AAD0F820D7AB2009
ACA000202CA891F8
A5F1C5F59004A5F0
C5F4F019E6F0D002
E6F1E6F8D002E6F9
A5FC8D01D3A5FE8D
01D31890D42073A8
A90A8555200AA84C
4F414445C4208FAA
4C03A8A98085FB85
FA203BAB204BAB20
ACAAD0F820D7AB20
09ACA000202CA8C9
FFD039A5F1C5F590
04A5F0C5F4F013E6
F0D002E6F1A5FC8D
01D3A5FE8D01D318
90D82073A8A90A85
55200AA845524153
45C4208FAAA90085
FB4C03A82073A8A9
0A8555200AA84E4F
5420455241534544
20494EA0A5F12UD0
AAA5F020D0AA208F
AAA90085FB4C03A8
A90085FB85FA202B
AB204BAB20ACAAD0
F820D7ABA5F885F2
A5F985F32011ACA0
00B1F08D00D320A9
ADA5F1C5F59004A5
F0C5F4F013E6F0D0
02E6F1A5FC8D01D3
A5FE8D01D31890D7
2073A8A90A855520
0AA850524F475241
4D4D45C4208FAA4C
03A82073A8A90A85
55200AA843454C4C
A0A5F120D0AAASF0

%pEr%qE
s%rPB%sp
V%|MAS%
MASFr%rI
PfFsPb'
)@Ez)@E{
;+ K+ ,
*Px W+ I
, @ ,(Qx
%qEuPD%p
EtpYfpPB
fqfxPBfy
%|MAS% M
ASXPT s(
)JEU J(L
OADED O*
LC()@E{E
z ;+ K+
,*Px W+
I, @ ,(I
P9%qEuP
D%pEtpSf
pPBfq%|M
AS% MASX
PX s()JE
U J(ERAS
ED O*)@E
{LC( s()
JEU J(NO
T ERASED
IN %q P
*%p P* O
*)@E{LC(
)@E{Ez +
+ K+ ,*P
x W+%xEr
%yEs Q,
@lpM@S )
-%qEuPD%
pEtpSfpP
Bfq%|MAS
% MASXPW
s()JEU
J(PROGRA
MMED O*L
C( s()JE
U J(CELL
%q P*%p

40

AD88
AD90
AD98
ADA0
ADA8
ADB0
ADB8
ADC0
ADC8
ADD0
ADD8
ADE0
ADE8
ADF0
ADF8
AE00
AE08
AE10
AE18
AE20
AE28
AE30
AE38
AE40
AE48
AE50
AE58
AE60
AE68
AE70
AE78
AE80
AE88
AE90
AE98
AEA0
AEA8
AEB0
AEB8
AEC0
AEC8
AED0
AED8
AEE0
AEE8
AEF0
AEF8
AF00

20D0AA200AA8204E
4F542050524F4752
414D4D45C4208FAA
4C03A8A0FF88D0FD
60A5FF8D01D320A3
AD290E8D01D34820
DDAD6809018D01D3
A5FE8D01D320A3AD
203BAB202CA8A000
D1F0F00568684C72
AD202BAB60A9FF85
F6A90B85F7A5F6D0
02A5F7F00DC6F6A5
F6C9FFD0F0C6F718
90EB6020F0AE4820
A4F668C952D006A9
0085FAF012C945D0
06A98085FA3008A9
FD20A4F64CFBAD20
3BABA98085FB204B
AB20ACAAD0F820D7
A82037AE4C03A8A5
FA10032009ACA97D
20A4F6A90085F620
73A8A90085F7A5F1
85F320D0AAA5F085
F220D0AA20DBAEAS
FA100620E0AE1890
04A000B1F020D0AA
E6F7A5F7C908F00B
20DBAEE6F0D002E6
F1D0DCA90085F720
DBAEA5FA3021A000
B1F2C9209004C97A
9002A92E20A4F6E6
F7A5F7C908F008E6
F2D002E6F3D0DBAS
F1C5F59004A5F0C5
F49006208FAA4C03
A8E6E0D002E6F1E6
F6A5F6C914F0034C
47AE208FAA20D7AB
4C3EAEA9204CA4F6
202CA848A5FC8D01
D3A5FE8D01D36860
20E2F6C958D00568
684C03A860A90485
55A5FA1009200AA8

P* J( N
OT PROGR
AMMED O*
LC( HP
'% MAS #
-)NMASH
]-hIAMAS
% MAS #;+ ,( @
QppEhhLr
- ++') E
v)Kew%vP
B%wpMFv%
vI PpFwX
Pk' p.H
$vhIRPF)
@EzpRIEP
F)@EzOH)
$vL{;+)@{ K
+ ,*Px W
+ 7.LC(%
zPC I,)
$v)@Ev
s()@Ew%q
Es P*%pE
r P* [.%
zPF '.XP
D @1p P*
fw%wIHpK
[.fpPBf
qP\)@Ew
[.%z0! @
1rI PDIz
PB). $vf
w%wIHpHf
rPBfsP[%
qEuPD%pE
tPF O*LC
(fpPBfqf
v%vITpCL
G. O* W+
L>.) L$v
,(H%|MA
S% MASh'
bvIXPEh
hLC()DE
U%zPI J(

41

AF08
AF10
AF18
AF20
AF28
AF30
AF38
AF40
AF48
AF50
AF58
AF60
AF68
AF70
AF78
AF80
AF88
AF90
AF98
AFA0
AFA8
AFB0
AFB8
AFC0
AFC8

4550524FCD60200A
A85241CD60A90485
55A5FA1007200AA8
5241CD60200AA845
50524FCD60A98085
FAA90085FB203BAB
204BAB20ACAAD0FB
20D7AB2009ACA000
202CA848D1F8D03E
68A5F1C5F59004A5
F0C5F4F019E6F0D0
02E6F1E6F8D002E6
F9A5FC8D01D3A5FE
8D01D31890D02073
A8A90A8555200AA8
5645524946494504
208FAA4C03A82073
A8200AA844494646
4552454E54204259
544553A06820D0AA
20DBAEA000B1F820
D0AA200AA820494E
A0A5F920D0AAA5F8
20D0AA208FAA4C03
A800000000000000

EPROM' J
(RAM')DE
U%zPG J(
RAM' J(E
PROM')@E
z)@E{ ;+
K+ ,*Px
W+ I, @
,(HQxP>
h%qEuPD%
pEtpYfpP
BfqfxPBf
y%|MAS%
MASXPP s
() JEU (
VERIFIED
O*LC( s
( J(DIFF
ERENT BY
TES h P*
[. @lx
P* J( IN
%y P*%x
P* 0*LC
(@@@@@@@

This hexdump has to be keyed in starting at address A800. This


means you need a 48K RAM ATARI and a machine language monitor
(ATMONA-1, Editor/Assembler cartridge from ATARI or ATMAS-1). The
program starts at address A800 hex.
Using the EPROM board Kit from HOFACKER
After you burned an EPROM you certainly want to plug it into your
ATARI. for this you need a pc-board. You can buy those boards from
various vendors (APEX, ELCOMP PUBLISHING).
The following description shows how to use the EPROM board from ELCOMP
PUBLISHING, INC.

With this versatile ROM module you can use 2716, 2732 and 2532 type
EPROMs.
To set the board for the specific EPROM, just solder their jumpers
according to the list shown below. Without any soldering you can use the
module for the 2532 right away.
If you use only one EPROM, inxrt it into the right socket.
If you use two EPROMs, put the one with the higher address into the right
socket.
The modul must be plugged into the left slot of your ATARI computer with
the parts directed to the back of the computer.

42

EPROM
1
2
3
4
5

2716
S
O
S
O
O

2732
O
S
S
O
S

2516
S
O
S
O
O

2532
S
O
O
S
O

S = means connected (short)


O = means open

HOW TO ADD OR CHANGE A DEVICE


CHAPTER 7
If you want to add your own device, you first have to write a
handler/controller (interface). You have to submit the handler on the
following design decisions.
- There has to be an OPEN routine, which opens the device/file and returns
with the status of these operations stored in the Y-register of your
6502.
- You also need a CLOSE routine, which unlinks the device and returns the
status as the OPEN-routine does.
- Further needed is a GETBYTE routine, which receives the data from your
device and returns the data in the A-register and the status in the Yregister. If your device is a write only device (such as a printer) you
have to return with errorcode 146 (not implemented function) in the Yregister.
- A PUTBYTE routine, sends a byte (which will be in the A-register) to
your device, and returns, as the other routines do, the status. If your
device is read only, then return the 146 errorcode.
- A GET STATUS routine stores the status of your device (max. 4 bytes) at
DVSTAT ($02EA. D). If the GET STATUS function is not necessary, you have
to leave the dummy routine . with 146 in your Y-register (error).
- A SPECIAL COMMAND routine is required, if you need more commands than
previous. If not, return with Y=146.
OS will load the X-register with the IOCB number times 16 so you are
able to get specific file information out of the user IOCB.
These 6 entries have to be placed in a so called handlertable. The
vectors of these have to be one less than the real address, due to OS
requirements.
OPEN vector - 1
CLOSE vector 1
GETBYTE vector 1
PUTBYTE vector 1
GETSTAT vector 1
SPECIAL vector - 1

43

Now you have to add the device to the device table. A device entry needs 3 bytes. The device name, which is
usually character that indicates the device (first character of the full devicename) is first. Second, a vector that
points to the devicehandler.
device name
handler table
address
If you only want to change the handler of a device to your own handler, you only have to scan the devicetable
(started from $031A) and let the vector point to your handler table.
If 'it is a totally new device, you have to add it, at the next free position of the device table (filled with zero).
The first listing shows you a handler for a new printer device. Calling INITHAN will install the new handlertable. Now you can connect a printer with centronics interface at gameport 3 & 4 (see connection scheme). After
each SYSTEM RESET you have to initialize the device again. For program description see program listing.
The second listing is a listing of an inexpensive (write only) RS232 interface for your ATARI. Just call
INITHAN and the new device will be added to the device table. It is now possible to use it like any other device.
The RS232 output is on gameport 3 (see connection scheme). It is not our intention to describe detail the
working of the RS232 interface. The comments in the program should help a bit though.

CENTRONICS PARALLEL INTERFACE

PRTENTRY

EQU$031A

TRIG3
PACTL
PORTA

EQU
EQU
EQU

$D013
$D303
$D3C1

EOL
CR
LF

EQU
EQU
EQU

$9B
$0D
$0A

ORG

$0600,

*
0600:
0602:
0604:
0606:
0608:
060A:

0F
23
26
29
26
26

06
06
06
06
06
06

A930
8D 03 D3
A9 FF
8D 01 D3

$A800

THE HANDLERTABLE
HANDLTAB

060C: 00 00 00
060F: 00
*
0610:
0612:
0615:
0617:

STANDARD ENTRY BY SYSTEM

DFW
DFW
DFW
DFW
DFW
DFW

OPEN-1
CLOSE-1
GETBYTE-1
PUTBYTE-1
STATUS-1
SPECIAL-1

DFB

0,0,0,0

THE OPEN ROUTINE


OPEN
INIT

EQU
LDA
STA
LDA
STA

*
#$30
PACTL
#$FF
PORTA

44

FILL REST WITH ZER0

061A:
061C:
061F:
0621:
0624:
0626:

A9
BD
A9
8D
A0
60

34
03 D3
80
01 D3
01

SUCCES

*
*

0627: A0 92
0629: 60

CLOSE

EQU SUCCES

NOTIMPL

LDY
#146
RTS
THE POLLOWING COMMANDS ARE
NOT IMPLEMENTED SO GET ERROR
CODE 116

GETBYTE
STATUS
SPECIAL

EQU
EQU
EQU

A9
20
A9
20
A0
60

PUTBYTE

0D
3B 06
0A
3B 06
01

AC 13
D0P B
A0 80
09 80
8D 01
297F
8D 01
8C 01
60

D0

NOEOL

PARAOUT

D3
D3
D3
RTS

A9 00
8D 1B 03
A90 6
8D1C03
4C1006

#EOL
NOEOL

LDA
JSR
LDA
JSR
LDY
RTS

#CR
PARAOUT
#LF
PARAOUT
#1

TBE PARALLEL OUT

*
0650:
0652:
0655:
0657:
065A:

CMP
BNE

IF EOL THEN CRLF TO PRINTER

*
0636:
063E:
0640:
0642:
0644:
0647:
0649:
061C:
061P:

NOTIMPL
NOTIMPL
NOTIMPL

THE PUTBYTE ROUTINE 1

*
062E:
0630:
0633:
0635:
0638:
063A:

#$34
PACTL
#$80
$D301
#1

THE CLOSE DUMMY ROUTINE


ONLY RETURN SUCCESS IN Y (1)

*
*
*

062A: C9 9B
062C: D0 07

LDA
STA
LDA
STA
LDY
RTS

LDY
BNE
LDY
ORA
STA
AND
STA
STY

TRIG3
PARAOUT
WAIT IF BUSY
#%10000000
#%10000000
PORTA
STROBE ON AND PUT DATA ON BUS
#%01111111
PORTA
STROBE OFF
PORTA
CLEAR BUS

PUT NEW ADDRESS IN HANDLER VECTOR


INITHAN

LDA
STA
LDA
STA
JMP

#HANDLTAB:L
PRTENTRY+1
#HANDLTAB:H
PRTENTRY+2
OPEN

PHYSICAL ENDADDRESS: $A85D


*** NO WARNINGS

45

'

PRTENTRY
$031A
TRIG3
$D013
PACTL
$D303
PORTA
$D301
EOL
$9B
CR
$0D
LP
$0A
HANDLTAB
$0600
OPEN
$0610
INIT
$0610
UNUSED
SUCCES
$0621
CLOSE
$0624
NOTIMPL
$0627
GETBYTE
$0627
STATUS
$0627
SPECIAL
$0627
PCTBYTE
$062A
NOEOL
$0635
PARAOUT
$0638
INITHAN
$0650
UNUSED
For more information about the parallel interface refer to Page 70.
RS 232 SERIAL INTERFACE

0600:
0602:
0604:
0606:
0608:
060A:
060C:
060F:

0F
29
2C
2F
2C
2C
00
00

06
06
06
06
06
06
00 00

COUNT
RSENTRY

EPZ
EQU

$1F
$032C

PACTL
PORTA
NMIEN
DMACTL
EOL
CR
LF
K
L
*L

EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU

$D303
$D301
$D40E
$D400
$9B
$0D
$0A
150
110 AND 300 BAUD
6
300 BAUD
18
110 BAUD

ORG

$0600,$A800

DFW
DFW
DFW
DFW
DFW
DFW
DFB

OPEN-1
CLOSE-1
GETBYTE-1
PUTBYTE-1
STATUS-1
SPECIAL-1
0,0,0,0 JUST FILL WITH ZERO

HANDLTAB

0610:
0612:
0615:
0617:
061A:
061C:

A9
8D
A9
8D
A9
8D

30
03 D3
01
01 D3
34
03 D3

THE OPEN ROUTINE


OPEN
INIT

EQU
LDA
STA
LDA
STA
LDA
STA

*
1530
PACTL
#%00000001
PORTA
1534
PACTL

46

NEXT FREE POSITION IN


DEVICE TABLE

061F:
0621:
0624:
0627:
062A:
062C:

A9
8D
20
20
A0
60

00
01 D3
85 06
85 06
01

SUCCES

*
*

*
*
*

A9
20
A9
20
68
A0
60

PUTBYTE

0D
43 06
0A
43 06

NOEOL

*
0648:
0649:
0648:
064E:

78
A9 00
8D 0E D4
BD 00 D4

RETURN WITH Y=116

EQU
EQU
EQU

NOTIMPL
NOTIMPL
NOTIMPL

PHA
CMP
BNE

#EOL
NOEOL

IF EOL GIVE CRLF TO DEVICE

01

0643: 49 FF
0645: 8D A2 06

SUCCES
#146

THE PUTBYTE COMMAND


DATA IN ACCU
STATUS IN Y (=1)

*
0635:
0637:
063A:
063C:
063F:
0640:
0642:

EQU
LDY
RTS

THE FOLLOWING COMMANDS ARE NOT IMPLEMENTED


GETBYTE
STATUS
SPECIAL

0630: 48
0631: C9 98
0633: D0 07

1500
PORTA
BITWAIT
BITWAIT
#1

THE CLOSE ROUTINE IS A DUMMY


BUT Y#1 (SUCCESSFULL CLOSE)
CLOSE
NOTIMPL

062D: A0 92
062F: 60

LDA
STA
JSR
JSR
LDY
RTS

LDA
#CR
JSR
SEROUT
LDA
#LF
JSR
SEROUT
PLA
LDY #1
RTS
SERIALOUT FIRST REVERSE BYTE

SEROUT

EOR
STA

#%llllllll
BUFFER

DISABLE INTERRUPTS
SEI
LDA
STA
STA

#0
NMIEN
DMACTL

47

SEND STARTBIT

0651: A9 01
0653: BD 01 D3
0656: 20 85 06

LDA
STA
JSR

*
0659:
065B:
065D:
0660:
0663:
0664:
0667:
066A:
066C:

A0
84
AD
BD
6A
BD
20
C6
D0

08
1F
A2 06
01 D3

SEND BYTE

SENDBYTE

A2 06
85 06
1F
EF
*

066E:
0670:
0673:
0676:

A9
BD
20
20

A9
BD
A9
BD
58
60

00
01 D3
85 06
85 06

LDA
STA
JSR
JSR

A2
A0
88
D0
CA
DO
60

22
00 D4
FF
0E D4

96
06

BITWAIT
LOOPR
LOOPL

FD
FB

*
0690: A9 52
0692: BD 2C 03

#8
COUNT
BUFFER
PORTA
BUFFER
BITWAIT
COUNT
SENDBYTE

#%00000000
PORTA
BITWAIT
BITWAIT

ENABLE INTERRUPTS

*
0685:
0687:
0689:
068A:
068C:
068D:
068F:

LDY
STY
LDA
STA
ROR
STA
JSR
DEC
BNE

SEND TWO STOPBITS

*
0679:
067B:
067E:
0680:
0683:
0684:

#%00000001
PORTA
BITWAIT

LDA
STA
LDA
STA
CLI
RTS

#$22
DMACTL
#$FF
NMIEN

THE

BITTIME ROUTINE FOR AN

LDX
LDY
DEY
BNE
DEX
BNE
RTS

#K
#L

EXACT BAUDRATE

LOOPL
LOOPR

ROUTINE FOR INSTALLING THE RS232 HANDLER


INITHAN

LDA
STA

'R
RSENTRY

48

DEVICE NAME

0695:
0697:
069A:
069C:
069F:

A9
8D
A9
80
4C

00
2D 03
06
2E 03
10 06
BUFFER

LDA
STA
LDA
STA
JMP

#HANDLTAB:L
RSENTRY+1
#HANDLTAB:H
RSENTRY+2
OPEN

EQU

ONE BYTE

RSENTRY
PORTA
DMACTL
CR
K
HANDLTAB
INIT
CLOSE
GETBYTE
SPECIAL
NOEOL
SENDBYTE
LOOPK
INITHAN

$032C
$D301
$D400
$OD
$96
$0600
$0610
$062A
$062D
$062D
$063C
$065D
$0687
$0690

BUFFER

PHYSICAL END ADDRESS: $A8A2


*** NO WARNINGS
COUNT
$1F
PACTL
$D303
NMIEN
$D40E
EOL
$98
LF
$0A
L
$06
OPEN
$0610
SUCCES
$062A
NOTIMPL
$062D
STATUS
$062D
PUTBYTE
$0630
SEHUUT
$0643
BITWAIT
$0685
LOOPL
$0689
BUFFER
S06A2

49

UNUSED

UNUSED

A BOOTABLE TAPE GENERATOR PROGRAM


CHAPTER 8
The following program allows you to generate a bootable program on tape.
This generator must be in memory at the same time as the program.
After you have jumped to the generator, a dialogue will be started.
First, the boot generator asks for the address where your program is stored
(physical address). After you have entered start and end address
(physical), you will be asked to enter the address where the program has to
be stored during boot (logical address). The generator further asks for the
restart address (where OS must jump to, to start your program).
There is no feature to define your own initialization address. This
address will be generated automatically and points to a single RTS.
Also given is the boot continuation code, which will stop the cassette
motor, and store the restart address into DOSVEC ($0A.B).
So, you just have to put a cassette in your recorder, start the
generator, and the dialogue will be started.
The generator puts the boot information header in front of your program,
so there have to be at least 31 free bytes in front of the start address
(physical & logical).
The generator program will not be explained here, but after reading the
previous chapters you should have the knowledge to understand it. There are
also some helpfull comments in the program.

BOOT GENERATOR

STOREADR
ENDADR
PROGLEN
JMPADR
EXPR
LOGSTORE
HEXCOUNT

EPZ
EPZ
EPZ
EPZ
EPZ
EPZ
EPZ

$F0.1
$F2.3
$F4.5
$F6.7
$F8.9
$FA.B
$FC

DOSVEC

EPZ

$0A

50

A800: A9 7D
A802: 20 A4 F6

A805:
A808:
A80A:
A80D:
A810:
A813:
A816:
A819:
A81C:
A81F:
A822:

20
0D
42
54
4E
41
52
52
20
46
4B

00
0D
4F
47
45
54
20
4F
48
41
45

MEMLO

EPZ

$02E7

ICCOM
ICBAL
ICBAH
ICBLL
ICBLH
ICAX1
ICAX2

EQU
EQU
EQU
EQU
EQU
EQU
EQU

$0342
$0344
$0345
$0348
$0349
$034A
$034B

OPEN
PUTCHR
CLOSE

EQU
EQU
EQU

$03
$0B
$0C

OPNOT

EQU

SCROUT
GETCHR
BELL
CIOV
PACTL

EQU
EQU
EQU
EQU
EQU

$F6A4
$F6DD
$F90A
$E456
$D302

CLS
EOL
BST
CR
IOCBNUM

EQU
EQU
EQU
EQU
EQU

$7D
$9B
$1E
$0D
1

ORG

$A800

LDA
JSR

#CLS
SCROUT

START

PRINT MESSAGE

AA

JSR
DFB
ASC

4F
45
52
4F
46
4D
4F
43
D2
*

GET

PRINT
CR,CR
\BOOTGENERATOR FROM HOFACKER\

STOREADDRESS

51

A825:
A828:
A82A:
A82D:
A830:
A833:
A836:
A839:
A83C:
A83E:

20
0D
53
52
44
45
20
20
89
85

00
0D
54
45
44
53
3A
28
F0
F1

AA
4F
41
52
53
A4
AA

*
A840:
A843:
A846:
A849:
A84C:
A84F:
A852:
A855:
A858:
A85A:

A85C:
A85F:
A862:
A865:
A868:
A86B:
A86E:
A871:
A874:
A877:
A879:
A87C:
A87E:

A880:
A883:
A886:
A889:
A88C:
A88F:
A892:
A895:

20
0D
45
41
52
53
20
20
84
85

20
0D
4C
49
4C
54
45
44
53
3A
20
84
85

00
0D
4F
44
45
20
3A
28
F2
F3

00
0D
4F
43
20
4F
41
52
53
A4
28
FA
FB

JSR
DFB
ASC

PRINT
CR,CR
\STOREADDRESS :$\

JSR HEXIN
STY STOREADR
STA STOREADR+1
GET ENDADDRESS

AA
0D
44
44
53
20
A4
AA

JSR
DFB
ASC

PRINT
CR,CR,CR
\ENDADDRESS :$\

JSR
STY
STA

HEXIN
ENDADR
ENDADR+1

GET LOGICAL STORE

AA
0D
47
41
53
52
44
45
20

JSR
DFB
ASC

PRINT
CR,CR,CR
\LOGICAL STOREADDRESS :$\

AA

JSR
STY
STA

HEXIN
LOGSTORE
LOGSTORE+1

GET JUMP

20 00 AA
0D0D0D
4A 55 4D
50 41 44
44 52 45
53 53 20
20 20 20
3A A4

JSR
DFB
ASC

PRINT
CR,CR,CR .
\JUMPADDRESS :$\

52

A897: 20 28 AA
A89A: 84 F6
A89C: 85 F7
*
A89E:
A8A0:
A8A1:
A8A3:
A8A5:
A8A7:

A5
38
E9
85
B0
C6

F0
20
F0
02
F1

A5FA
38
E9 20
85 FA
B0 02
C6 FB

A8B4: 20 F5 A9
*
A8B7:
A8B9:
A8BA:
ABBC:
ABBE:
A8C0:
A8C2:
A8C4:
A8C6:

A5
38
E5
85
A5
E5
85
B0
4C

F2
F0
F4
F3
F1
F5
03
DA A9
*

A8C9:
A8CB:
A8CC:
A8CE:
A8D0:
A8D2:
A8D4:

A5
18
69
29
85
90
E6

F4

STOREADR
#(HEADEND-HEAD)+1
STOREADR
*+4
STOREADR+1

CALCULATE LOGICAL STORE


LDA
SEC
SBC
STA
BCS
DEC

HEXIN
JMPADR
JMPADR+l

CALCULATE NEW STORE


LDA
SEC
SBC
STA
BCS
DEC

*
A8A9:
A8AB:
A8AC:
A8AE:
A8B0:
A8B2:

JSR
STY
STA

LOGSTORE
#(HEADEND-HEAD)+1
LOGSTORE
*+4
LOGSTORE+1

MOVE HEADER IN FRONT OF PROGRAM


JSR

MOVEHEAD

CALCULATE LENGTHE OF PROGR.


LDA
SEC
SBC
STA
LDA
SBC
STA
BCS
JMP

ENDADR
STOREADR
PROGLEN
ENDADR+1
STOREADR+1
PROGLEN+1
*+5
ADRERR

ROUND UP TO 128 RECORDS


LDA PROGLEN
CLC
ADC
#127
AND
#128
STA
PROGLEN
BCC
*+4
INC
PROGLEN+1

7F
80
F4
02
F5
*

CALCULATE NUMBER OF RECORDS

53

A8D6:
A8D7:
A8D9:
A8DA:
A8DC:
A8DE:
A8E0:
A8E2:
A8E4:
A8E6:
A8E7:
A8E9:
A8EC:
A8EE:
A8F0:
A8F2:
A8F3:
A8F5:
A8F7:
A8F9:
A8FB:
A8FD:
A8FE:
A900:
A902:
A904:
A906:
A908:
A90A:
A90C:
A90E:
A910:
A912:
A914:

A916:
A919:
A91B:
A91E:
A921:
A924:
A927:
A92A:
A92D:
A92E:
A930:

0A
A5
2A
A0
91
A0
A5
91
A5
C8
91
A0
A5
69
91
C8
A5
69
91
A0
A5
18
65
91
A0
A5
65
91
A0
A5
91
A0
A5
91

20
0D
50
53
50
59
20
43
44
0D
41

ASL
LDA
ROL
LDY
STA
LDY
LDA
STA
LDA
INY
STA
LDY
LDA
ADC
STA
INY
LDA
ADC
STA
LDY
LDA
CLC
ADC
STA
LDY
LDA
ADC
STA
LDY
LDA
STA
LDY
LDA
STA

F5
01
F0
02
FA
F0
FB
F0
04
FA
1F
F0
FB
00
F0
0C
FA
F4
F0
11
FB
F5
F0
16
F6
F0
lA
F7
F0

00
0D
52
53
4C
20
52
4F

PROGLEN+1
#RECN-HEAD
(STOREADR),Y
#PST-HEAD
LOGSTORE
(STOREADR),Y
LOGSTORE+1
(STOREADR),Y
#PINITADR-HEAD ABEB: 18 CLC
LOGSTORE
#PINIT-HEAD
(STOREADR),Y
LOGSTORE+1
#0
(STOREADR),Y
#PNDLO-HEAD
LOGSTORE
PROGLEN
(STOREADR),Y
#PNDHI-HEAD
LOGSTORE+1
PROGLEN+1
(STOREADR),Y
#JUMPADRL-HEAD
JMPADR
(STOREADR) ,Y
#JUMPADRH-HEAD
JMPADR+1
(STOREADR),Y

BOOTTAPE GENERATION PART, GIVE INSTRUCTIONS

AA

JSR
DFB
ASC

PRINT
CR,CR
"PRESS PLAY & RECORD"

DFB
ASC

CR,CR
\AFTER THE BEEPS 'RETURN'\

45
20
41
26
45
52

0D
46 54

54

A933:
A936:
A939:
A93C:
A93F:
A942:
A945:

45
54
20
45
20
45
52

52
48
42
50
27
54
4E

20
45
45
53
52
55
A7

*
A948:
A94A:
A94C:
A94F:
A951:
A954:
A956:
A959:
A95B:
A95E:
A960:
A963:
A966:

A2
A9
9D
A9
9D
A9
9D
A9
9D
A9
9D
20
30

10
03
42
08
4A
80
4B
F2
44
A9
45
56
28

OPEN CASSETTE FOR WRITE


OPENIOCB

03
03
03
03
03
E4

*
A968:
A96A:
A96D:
A96F:
A972:
A974:
A977:
A979:
A97C:
A97E:
A981:
A984:

A9
9D
A5
9D
A5
9D
A5
9D
A5
9D
20
30

0B
42
F0
44
F1
45
F4
48
F5
49
56
0A

A9
9D
20
10

PUTPROG
03
03
03
03
03
E4

0C
42 03
56 E4
24
*

#IOCBNUM*16
#OPEN
ICCOM,X
#OPNOT
ICAXI,X
#128 ,
ICAX2,X
#CFILE:L
ICBAL,X
#CFILE:H
ICBAH,X
CIOV
CERR

PUT PROGRAM ON TAPE

*
A986:
A988:
A98B:
A98E:

LDX
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
JSR
BMI

LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
JSR
BMI

#PUTCHR
ICCOM,X
STOREADR
ICBAL,X
STOREADR+1
ICBAH,X
PROGLEN
ICBLL,X
PROGLEN+l
ICBLH,X
CIOV
CERR

CLOSE IOCB
CLOSIOCB

LDA
STA
JSR
BPL

#CLOSE
ICCOM,X
CIOV
SUCCES

IF ERROR OCCURS SHOW THE ERRORNUMBER

55

A990:
A991:
A992:
A994:
A996:
A999:
A99C:
A99F:
A9A1:
A9A4:
A9A7:
A9A8:
A9A9:
A9AA:
A9AD:
A9B0:
A9B1:

98
48
A2
A9
9D
20
20
0D
45
4F
A0
68
AA
20
20
8D
4C

CERR
10
0C
42
56
00
0D
52
52

03
E4
AA
52
2D

88 AA
00 AA
A2 AA
*

A9B4:
A9B7:
A9B9:
A9BC:
A9BF:
A9C2:
A9C5:
A9C8:
A9CB:
A9CE:
A9D1:
A9D4:
A9D7:

20 00
0D0D
53 55
43 45
46 55
4C 20
4F 4F
54 41
45 20
45 4E
52 41
49 4F
0D8D

AA

#IOCBNUM*16
#CLOSE
ICCOM,X
CIOV
PRINT
CR,CR
\ERROR- \

PLA
TAX
JSR
JSR
DFB
JMP

PUTINT
PRINT
CR+128
WAIT

IF NO ERROR OCCURS TELL IT THE USER


SUCCES

43
53
1C
42
54
50
47
45
54
4E

JSR PRINT
DFB CR,CR
ASC "SUCCESFULL BOOTTAPE GENERATION"

DFB CR,CR+128
*
*
*
*
*
*

BRK-INSTRUCTION TO TERMINATE THE PROGRAM.


MOSTLY A JUMP INTO THE MONITOR-PROGRAM FROM
WHERE YOU STARTED THE PROGRAM. INSTEAD OF THE
'BRK' YOU ALSO CAN USE THE 'RTS' THE RTS
INSTRUCTION, IF THIS PROGRAM WAS CALLED AS A
SUBROUTINE.

A9D9: 00

BRK
*

A9DA:
A9DD:
A9DF:
A9E2:

TYA
PHA
LDX
LDA
STA
JSR
JSR
DFB
ASC

20 00 AA
0D0D
41 44 44
52 45 53

IF ERROR IN THE ADDRESSES TELL IT THE USER


ADRERR

JSR
DFB
ASC

PRINT
CR,CR
\ADDRESSING ERROR\

56

A9E5:
A9EB:
A9EB:
A9EE:
A9EF:

53
47
52
D2
4C

49 4E
20 45
52 4F
A2 AA

JMP

*
*

A9F2: 43 3A
A9F4: 9B

THESE 2 CHARACTERS ARE NEEDED TO OPEN


A CASSETTE IOCB.

CFILE

*
*
A9F5:
A9F7:
A9FA:
A9FC:
A9FD:
A9FF:

A0 1F
B9 A8 AA
91 F0
88
l0F8
60

68
85
68
85
A2
E6
D0
E6
A1
29
C9
D0
A9
20
A2
A1
10
A5

MOVEHEAD
MOVELOOP

"C:"
EOL

LDY
LDA
STA
DEY
BPL
RTS

#HFADEND-HEAD
HEAD,Y
(STOREADR),Y
MOVELOOP

THIS ROUTINE PRINTS A CHARACTERS


WHICH ARE BE POINTED BY THE
STACKPOINTER (USING THE 'JSR'
TO CALL THIS ROUTINE) .
THE STRING HAS TO BE TERMINATED
BY A CHARACTER WHOSE SIGNBIT
IS ON.
PRINT

F8
F9
00
F8
02
F9
F8
7F
0D
02
9B
A4 F6
00
F8
E7
F9

ASC
DFB

ROUTINE FOR MOVING THE HEADER


IN FRONT OF THE USER-PROGRAM

*
*
*
*
*
*
*
AA00:
AA01:
AA03:
AA04:
AA06:
AA08:
AA0A:
AA0C:
AA0E:
AA10:
AA12:
AA14:
AA16:
AA18:
AA1B:
AA1D:
AA1F:
AA21:

WAIT

PRINTI

PLA
STA
PLA
STA
LDX
INC
BNE
INC
LDA
AND
CMP
BNE
LDA
NOCR
LDX
LDA
BPL
LDA

EXPR
EXPR+1
#0
EXPR
*+4
EXPR+1
(EXPR,X)
#%01111111
#CR
NOCR
#EOL
JSR
SCROUT
#0
(EXPR,X)
PRINTI
EXPR+1

57

AA23:
AA24:
AA26:
AA27:

48
A5 F8
48
60

PHA
LDA
PHA
RTS
*
*

AA28:
AA2A:
AA2C:
AA2E:
AA30:
AA32:
AA34:
AA37:
AA38:
AA3B:
AA3C:
AA3E:
AA40:
AA42:
AA44:
AA46:
AA48:
AA4A:
AA4C:
AA4E:
AA51:
AA54:
AA56:
AA58:
AA5A:
AA5C:
AA5D:
AA5F:
AA62:
AA65:
AA67:
AA69:

A9 00
85 F8
85 F9
A9 03
85 FC
30 31
20 DD
48
20 A4
68
C9 9B
F0 25
C9 58
F0 96
C9 30
90 22
C9 3A
B0 08
29 0F
20 75
4C 32
C9 41
90 12
C9 47
B00E
38
E9 37
20 75
4C 32
A4 F8
A5 F9
60

HEX INPUT ROUTINE WAITS FOR CORRECT FOUR


DIGITS OR 'RETURN'
HEXIN

HEXINI
F6
F6

AA
AA
ALFA

AA
AA
HEXRTS

*
*
AA6A:
AA6D:
AA6F:
AA72:
AA75:

20
A9
20
4C
C6

0A F9
1E
A4 F6
32 AA
FC

EXPR

LDA
STA
STA
LDA
STA
BMI
JSR
PHA
JSR
PLA
CMP
BEQ
CMP
BEQ
CMP
BCC
CMP
BCS
AND
JSR
JMP
CMP
BCC
CMP
BCS
SEC
SBC
JSR
JMP
LDY
LDA
RTS

#0
EXPR
EXPR+1
#3
HEXCOUNT
HEXRTS
GETCHR
SCROUT
#EOL
HEXRTS
'X
ADRERR
'0
HEXERR
'9+1
ALFA
#%00001111
HEXROT
HEXIN1
'A
HEXERR
'F+1
HEXERR
'A-10
HEXROT
HEXINI
EXPR
EXPR+1

IF WRONG DIGIT RINGS THE BUZZER


AND
PRINT BACKSTEP
HEXERR

HEXROT

JSR
LDA
JSR
JMP
DEC

BELL
#BST
SCROUT
HEXIN1
HEXCOUNT

58

AA77:
AA78:
AA7A:
AA7B:
AA7C:
AA7D:
AA7E:
AA7F:
AA81:
AA83:
AA84:
AA86:
AA87:

08
A2
0A
0A
0A
0A
0A
26
26
CA
D0
28
60

04

HEXROTl
F8
F9
F8

*
*
AA88:
AA89:
AA8A:
AA8C:
AA8E:

48
8A
C9 0A
90 0D
A2 FF

PHP
LDX
ASL
ASL
ASL
ASL
ASL
ROL
ROL
DEX
BNE
PLP
RTS

#4

EXPR
EXPR+1
HEXROTI

THE RECURSIVE PUTINT FOR PRINTING ONE BYTE


IN DECIMAL FORM
PUTINT

PHA
TXA
CMP
BCC
LDX

#10
PUTDIG
#-1

-IF A<10 THEN STOP RECURSION

*** WARNING: OPERAND OVERFLOW


AA90:
AA92:
AA93:
AA95:
AA97:
AA9A:
AA9B:
AA9D:
AAAO:
AAA1:

E9
E8
B0
69
20
18
69
20
68
60

0A

DIV

FB
0A
88
CLC
30
A4 F6

PUTDIG

*
AAA2: 20 DD F6
AAA5: 4C 00 A8

AAA8: 00
AAA9: 00
AAAA: 00 00

SBC
INX
BCS
ADC
JSR

#10

ADC
JSR
PLA
RTS

'0
SCROUT

DIV
#10
PUTINT - THE RECURSION STEP

WAIT FOR ANY KEY


WAIT

JSR
JMP

GETCHR
START

*
*

THE BARECODE FOR THE HEADER TO PUT IN FRONT


OF PROGRAM'

THE DUMMY HEADER DUMMY EQU 0


HEAD
RECN
PST

DFR
DFB
DFW

0
DUMMY
DUMMY

59

AAAC: 00 00

PINITADR
*

DFW

THE BOOT CONTINUATION CODE

AAAE: A9 3C
AAB0: 8D 02 D3
AAB3: A9 00

AAC3: 85 0B

LDA
STA
LDA
EQU
STA
LDA
EQU
STA
LDA
EQU
STA
LDA
EQU
STA

AAC5: 18
AAC6: 60

CLC
RTS

PNDLO
AAB5: 8D E7 02
AAB8: A9 00
PNDHI
AABA: 8D E8 02
AABD: A9 00
JUMPADRL
AABF: 85 0A
AAC1: A9 00
JUMPADRH

AAC7: 60

HEADEND
PINIT

PHYSICAL ENDADDRESS: $AAC


STOREADR
PROGLEN
EXPR
MEMLO
ICBLL
OPEN
SCROUT
PACTL
CR
PUTPROG
ADRERR
PRINT
HEXINI
HEXROT
PUTDIG
RECN
PNDHI
PINIT
DOSVEC
ICBAH
ICAX2
OPNOT
CIOV

DUMMY

$F0
$F4
$F8
$02E7
$0348
$03
$F6A4
$D302
$0D
$A968 UNUSED
$A9DA
$AA00
$AA32
$AA75
$AA9B
$AAA9
$AAB9
$AAC7
$0A
$0345
$034B
$08
$E456

EQU
RTS

#$3C
PACTL
#DUMMY
*-1
MEMLO
#DUMMY
*-1
MEMLO+1
#DUMMY
*-1
DOSVEC
#DUMMY
*-1
DOSVEC+1

8
ENDADR
JMPADR
HEXCOUNT
ICBAL
ICAX1
CLOSE
BELL
EOL
START
CERR
MOVEHEAD
NOCR
HEXRTS
PUTINT
DUMMY
PINITADR
JUMPADRH
LOGSTORE
ICCOM
ICBLH
PUTCHR
GETCHR
CLS

60

$F2
$F6
$FC
$0344
$034A
$OC
$F90A
$9B
$A800
$A990
$A9F5
$AA18
$AA65
$AA88
$00
$AAAC
$AAC2
$FA
$0342
$0349
$0B
$F6DD
$7D

BST
OPENIOCB
SUCCES
MOVELOOP
HEXIN
HEXERR
DIV
HEAD
PNDLO
HEADEND

$1E
$A948 UNUSED
$A9B4
$A9F7
$AA28
$AA6A
$AA90
$AAA8
$AAB4
$AAC7

IOCBNUM
CLOSIOCB
CFILE
PRINTI
ALFA
HEXROT1
WAIT
PST
JUMPADRL

$01
$A986 UNUSED
$A9F2
$AA08
$AA54
$AA7E
$AAA2
$AAAA
$AABE

A DIRECT CASSETTE TO DISK COPY PROGRAM


CHAPTER 9
If you have a bootable program on cassette, and you want to have it on a
bootable disk, the following program will help you.
This program is easy to understand if you have read the previous
chapters. It allows you to copy direct from tape to disk, using a buffer.
When you start your program from your machine language monitor, you must
put the cassette into the recorder and the formatted disk into the drive
(#1). After the beep, press return, and the cassette will be read. After a
succesful read the program will be written on the disk. If, during one of
these IO's an error occurrs, the program stops and shows you the error
code.
Now, power up the ATARI again and the disk will be booted. Sometimes the
program doesn't work correctly. Just press SYSTEM RESET and most of the
time the program will work.
The copy program will not be described, but it has helpful comments, and
you possess the knowledge of the IO.
It is important that the buffer (BUFADR) is large enough for the
program.

DIRECT CASSETTE TO DISK


COPY PROGRAM
SECTR
DBUFFER
BUFFER
BUFLEN
RETRY
XSAVE

EPZ
EPZ
EPZ
EPZ
EPZ
EPZ

$80.1
$82.3
$84.5
$86.7
$88
$89

DCBSBI
DCBDRV
DCBCMD
DCBSTA
DCBBUF
DCBTO
DCBCNT
DCBSEC

EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU

$0300
$0301
$0302
$0303
$0304
$0306
$0308
$030A

61

ICCMD
ICBAL
ICBAH
ICBLL
ICBLH
ICAX1
ICAX2

EQU
EQU
EQU
EQU
EQU
EQU
EQU

$0342
$0344
$0345
$0348
$0349
$034A
$034B

OPEN
GETCHR
CLOSE

EQU
EQU
EQU

3
7
12

RMODE
RECL

EQU
EQU

4
128

CIO
SIO
EOUTCH

EQU
EQU
EQU

$E456
$E459
$F6A4

EOL
EOF
IOCBNUM

EQU
EQU
EQU

$9B
$88
1

ORG

$A800

*
A800: 20 A7 A8
A803: 30 63

OPEN CASSETTE FOR READ


MAIN

*
A805:
A807:
A809:
A80B:
ASOD:
A80F:
A811:
A813:

A9
85
A9
85
A9
85
A9
85

56
84
A9
85
80
86
00
87

LDA
STA
LDA
STA
LDA
STA
LDA
STA

A815: 20 C8 A8
A818: 30 10
*
A5
18
69
85
A5
69
85
4C

84
80
84
85
00
85
15 A8

OPENCASS
IOERR

INITIALIZE BUFFERLENGTH & BUFFER POINTER

*
*

A81A:
A81C:
A81D:
A81F:
A821:
A823:
A825:
A827:

JSR
BMI

#BUFADR:L
BUFFER
#BCFADR:H
BUFFER+1
#128
BUFLEN
#0
BUFLEN+1

READ RECORD BY RECORD TO BUFFER UNTILL EOF


REACHED
READLOOP

JSR
BMI

READCASS
QEOF

IF NO ERROR OR EOF INCREASE THE BUFFERPOINTER


LDA
CLC
ADC
STA
LDA
ADC
STA
JMP

BUFFER
#128
BUFFER
BUFFER+1
#0
BUFFER+1
READLOOP

62

*
*
A82A:
A82C:
A82E:
A831:

C0
D0
20
30

88
3A
E9 A8
35

IF EOF REACHED THEN WRITE BUFFFR TO DISK


ELSE ERROR
QEOF

CPY
BNE
JSR
BMI

*
A833:
A835:
A837:
A839:
A83B:
A83D:
A83F:
A841:

A9
85
A9
85
A9
85
A9
85

INIT POINTERS FOR SECTOR WR1TE

01
80
00
81
56
82
A9
83

LDA
STA
LDA
STA
LDA
STA
LDA
STA
*

A843: 20 06 A9
A846: 30 20

A5
C5
A5
E5
B0

WRITLOOP

LDA
CMP
LDA
SBC
BCS
*

A5
18
69
85
A5
69
85

82

AB5F:
A861:
A863:
A865:

E6
D0
E6
D0

JSR
BMI

WRITSECT
IOERR

IF BUFFER IS WRITTEN THEN STOP PROGRAM

82
84
83
85
15

A852:
A854:
A855:
A857:
A859:
A85B:
AB5D:

#1
SECTR
#0
SECTOR+l
#BUFADR:L
DBUFFER
#BUFADR:H
DBUFFER+1

WRITE SECTOR BY SECTOR BUFFER TO DISK

*
A848:
A84A:
A84C:
A84E:
A850:

#EOF
IOERR
CLOSCASS
IOERR

DBUFFER
BUFFER
DBUFFER+1
BUFFER+1
READY

INCREASE BUFFER AND SECTOR POINTERS


DBUFFER

80
82
83
00
83

LDA
CLC
ADC
STA
LDA
ADC
STA

80
02
81
DC

INC
BNE
INC
BNE

SECTR
*+4
SECTR+1
WRITLOOP

JUMP ALWAYS!!!

THE BREAK FOR RETURNING TO THE CALLING MONITOR

A867: 00

READY

BRK

A868:
A869:
A86A:
A86C:

IOERR

TYA
PHA
LDX
STX

98
48
A208
86 89

#128
DBUFFER
DBUFFER+1
#0
DBUFFER+1

ERRLOOP

#LENGTH
XSAVE

63

A86E:
A871:
A874:
A876:
A877:
A879:
A87A:
A87B:
A87E:
A880:

BD 84
20 A4
A6 89
CA
l0F3
68
AA
20 8D
A9 9B
20 A4

A8
F6

LDA
JSR
LDX
DEX
BPL
PLA
TAX
JSR
LDA
JSR

A8
F6

THE

A883: 00

20 2D 52
4F 52 52
45
9B 9B

ERROR

BREAK FOR RETURNING TO THE CALLING MONITOR

ASC

" -RORRE"

DFB

$9B,$9B

EQU (*-1)-ERROR

RECURSIVE PRINT FOR DECIMAL ERRORCODE

A88D: 48
PUTINT
A88E: 8A
A88F: C9 0A
A891: 90 0D
A893: A2 FF
*** WARNING: OPERAND OVERFLOW
A895: E9 0A
DIV
A897: E8
A898: B0 FB
A89A: 69 0A
A89C: 20 8D A8
A89F: 18
A8A0: 6930
PUTDIG
A8A2: 20 A4 F6
A8A5: 68
ABAG: 60
*
*
8D 08
A9 00
8D 09
20 59
10 0C
C6 88
30 08
A280
8E 03
4C 41
AC 03
60

PUTINT
#EOL
EOUTCH

TEXT FOR ERROR MESSAGE

LENGTH

A939:
A93C:
A93E:
A941:
A944:
A946:
A948:
A94A:
A94C:
A94F:
A952:
A955:

ERRLOOP

BRK
*

A884:
A887:
A88A:
A88B:

ERROR,X
EOUTCH
XSAVE

PHA
TXA
CMP
BCC
LDX
SBC
INX
BCS
ADC
JSR
CLC
ADC
JSR
PLA
RTS

#10
PUTDIG
#-1
#10
DIV
#10
PUTINT

RECURSION STEP

'0
EOUTCH

THE WELL KNOWN CASSETTE READ SECTION JUST A LITTLE


MODIFIED
03
03
E4

JMPSIO

03
A9
03

WRITEND

STA
LDA
STA
JSR
BPL
DEC
BMI
LDX
STX
JMP
LDY
RTS

DCBCNT
#0
DCBCNT+1
SIO
WRITEND
RETRY
WRITEND
#$80
DCBSTA
JMPSIO
DCBSTA

64

BUFADR
PHYSICAL ENDADDRESS: $A956
SECTR
RETRY
DCBCMD
DCBCNT
ICBAH
ICAX2
RMODE
EOUTCH
MAIN
READY
LENGTH
OPENCASS
CFILE
BL!FADR
BUFLEN
DCBDRV
DCBTO
ICBAL
ICAX1
CLOSE
SIO
LOCBNUM
WRITLOOP
ERROR
PUTDIG
CERR
WRITEND

$80
$88
$0302
$0308
$0345
$034B
$04
$F6A4
$A800
$A867
$08
$A8A7
$A903
$A956
$86
$0301
$0306
$0344
$034A
$0C
$E459
$0l
$A843
$A884
$A8A0
$A8F6
$A952

EQU

*
BUFFER
DCBSBI
DCBBUF
ICCMD
ICBLH
GETCHR
CIO
EOF
QEOF
ERRROOP
DIV
CLOSCASS
JMPSIO
DBUFFER
XSAVE
DCBSTA
DCBSEC
ICBLL
OPEN
RECL
EOL
READLOOP
IOERR
PUTINT
READCASS
WRITSECT

UNUSED

65

$84
$0300
$0304
$0342
$0349
$07
$E456
$88
$A82A
$A86C
$A895
$A8E9
$A941
$82
$89
$0303
$030A
$0348
$03
$80
$9B
$A815
$A868
$A88D
$A8C8
$A906

HOW TO CONNECT YOUR ATARI WITH ANOTHER COMPUTER


CHAPTER 10
The following programs make it possible to communicate between an ATARI
and a PET/CBM. The output ports are referenced as PORTA and DATABUS between
the two computers. Bit 0 on the ATARI PORTB is the 'hand' of the ATARI and
bit 7 on the same port is the 'hand' of the CBM. Now a handshake
communication between both can be started. The routines PUT and GET are, in
this case, dummies. Further, you need a stop criterium to stop the
transfer. See these routines merely as a general outlines and not as
complete transfer programs.

The ATARI - CBM / PET connection-wiring diagram

RECEIVE FOR ATARI

PORTB
PBCTL
PORTA
PACTL

EQU
EQU
EQU
EQU

$D301
$D303
$D300
$D302

66

PUT

*
A800:
A802:
A805:
A807:
A80A:
A80C:

A9
8D
A9
8D
A9
8D

A814: 2C 01 D3
A817: 30 FB

$A800

#$30
PBCTL
#%00000001
PORTB
#$34
PBCTL

GIVE YOUR 'HAND' TO THE PET


RFD

LDA
STA

#1
PORTB

WAIT UNTIL PET TAKES YOUR 'HAND'


WAITDAV

BIT
BMI

PORTB
WAITDAV

GET DATA FROM BUS & PUT THEM SOMEWHERE

A819: AD 00 D3
A81C: 20 09 33

LDA
JSR

PORTA
PUT

TAKE YOUR 'HAND' BACK

A81F: A9 00
A821: 8D 01 D3

LDA
STA

*
A824: 2C01D3
A827: l0 FB

ORG

LDA
STA
LDA
STA
LDA
STA

$3309

SET BIT 0 ON PORTB AS OUTPUT

30
03 D3
01
01 D3
34
03 D3

A80F: A9 01
A811: 8D 01 D3

EQU

#0
PORTB

WAIT UNTIL PETS HAND IS IN HIS POCKET


WAITDAVN

*
A829: 4C0FA8

BIT
BPL

PORTB
WAITDAVN

START AGAIN
JMP

RFD

PHYSICAL ENDADDRESS: $A82C


*** NO WARNINGS
PORTB
PUT
PBCTL
RFD

$D301
$3309
$D303
$A80F

PORTA
WAITDAV
PACTL
WAITDAVN

67

$D300
$A814
$D302
$A824

UNUSED

SEND FOR PET CBM

PORTB
PBCTL
PORTA
GET
*

EQU
EQU
EQU
EQU

LDA
STA

*
GETDATA

DAV

GET
PORTA

LDA
STA

#0
PORTB

WAIT UNTIL ATARI GIVES HIS 'HAND'


WAITNRFD

LDA
AND
BNE

PORTB
#%00000001
WAITNRFD

SHAKE 'HANDS WITH ATARI


DANV

*
0356: AD 4F E8
0359: 29 01
035B: F0 F9

JSR
STA

TELL ATARI DATA VALID

0351: A9 80
0353: 8D 4F E8

#%10000000
PBCTL

GET DATA FROM USER PUT IT ON BUS

034A: AD 4F E8
034D: 29 01
034F: D0 F9

$033A,$A800

SET BIT 7 ON PET TO OUTPUT

033A: A9 80
033C: 8D 43 E8

0345: A9 00
0347: 8D 4F E8

LDA
STA

#%10000000
PORTB

WAIT UNTIL ATARI RELEASE HIS 'HAND'


WAITRFD

*
035D: 4C 3F 03

LDA
AND
BEQ

PORTB
#%00000001
WAITRFD

START AGAIN WITH DATA


JMP

GETDATA

PHYSICAL ENDADDRESS: $A826


*** NO WARNINGS
PORTB
PORTA

USER GET BYTE

ROUTINE
ORG

033F: 20 CF FF
0342: 8D 22 A8

$E84F
$E843
$A822
$FFCF

$E84F
$A822

68

GETDATA
WAITNRFD
WAITRfD
PBCTL
GET
DAV
DANV

$033F
$034A
$0356
$E843
$FFCF
$0345
$0351

UNUSED
UNUSED

300 BAUD SERIAL INTERFACE VIA


THE ATARI JOYSTICK PORTS
CHAPTER 11
The following construction article allows you to build your own RS232
interface for the ATARI computer. The interface only works with 300 Baud
and just in one direction (output).
The interface consists of:
a) RS232 serial interface driver on a bootable cassette or as a SYS file on
disk.
b) Two wires hooked up to game port 3 on your ATARI.

We used this interface with a DEC-writer, a NEC spinwriter, and a


Brother HR-15. The DEC-writer worked with just the two wires connected
(Transmit DATA and GND).
The Spinwriter and the Brother needed some jumper wires as shown below:

Receive data on DEC-writer

69

Receive DATA on Brother HR-15

Receive DATA on NEC Spinwriter


Depending on the printer you use you will have to make the appropriate
wiring according to the instructions in the manual.
The source code for the RS232 driver is listed on a previous page in this
book.

This is a sample printout in BASIC:


l0 OPEN #1,8,0,"R:"
20 FOR X=l TO 10
30 PRlNT #l, "ELCOMP-RS232",X
40 NEXT X
50 CLOSE #l
will generate the following printout:
ELCOMP-RS232
ELCOMP-RS232
ELCOMP-RS232
ELCOMP-RS232
ELCOMP-RS232
ELCOMP-RS232
ELCOMP-RS232
ELCOMP-RS232
ELCOMP-RS232
ELCOMP-RS232

1
1
3
4
5
6
7
8
9
l0

The source code for the RS-232 Interface you will find on page 46.

70

PRINTER INTERFACE
CHAPTER 12
Screen to Printer Interface for the ATARI 400/800
Many ATARI users would like to connect a parallel interface to the
computer. For many people buying an interface is too expensive. On the
other hand, they may not have the experience to build one by their own.
Also a lot of software is needed.
The following instructions make it easy to hook up an EPSON or
Centronics printer to the ATARI.
Only seven of the eight DATA bits are used for a printout.
DATA 8 is grounded. BUSY and STROBE are used for handshake. There is an
automatic formfeed every 66 lines. Thus it is necessary to adjust the paper
before starting to print. You may need to make several trials to find the
best position of the paper. For a different form-length you may POKE
1768, ... (number of linesl. After system reset the line counter is set to
zero, so you have to provide your own formfeed for a correct paper
position.
You can control the length of a line by a POKE 1770,xxx. After doing so,
press system reset and enter LPRINT.
The program SCREENPRINT is called by BASIC thru an USR (16701 and by the
assembler with a GOTO $0687.
You may install pnp transistors between the game output and the printer.
The figure shows the connection of the ATARI game outlets and the
connector for the MX-80 printer. This is a so-called Centronics interface
and the program can be used with each printer and this interface.

71

EPSON MX80 - ATARI 400/800 Interconnection Scheme

The next figure shows the program.

UNIVERSAL PRINT FOR ATARI


400 / 800 VERSION ELCOMP
BY HANS CHRISTOPH WAGNER

0600:
0601:
0602:
0604:
0606:
0608:
060B:
060D:
0610:
0612:
0615:
0617:
0619:
061B:
061D:
061E:

00
02
00
6E
A9
8D
A9
8D
A9
8D
A9
85
A9
85
18
60

DFB
DFB
DFW
DFW
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
CLC
RTS

061F:
0622:
0625:
0628:

2B 06 42
06 3F 06
42 06 3F
06 3F 06
HANDLTAB DFW DUMMY,
WRITE-1,RTS1-1,WRITE-1,RTS1-1, RTS1-1

062B:
062C:
062E:
0631:
0633:
0636:
0688:
063B:
063D:
0640:
0642:
0643:
0645:
0647:
064A:
064D:
0650:
0652:

01
A9
8D
A9
8D
A9
8D
A9
8D
A0
60
C9
D0
AD
8D
CE
10
A9

06
06
3C
02 D3
EB
E7 02
06
E8 02
6E
0A
06
0B

30
03
FF
03
34
03
80
01

DUMMY
OPEN
D3
D3
D3
D3
01

9B
1D
EA 06
E9 06
E8 06
0D
0C

RTS1
WRIT
CARR

DFB
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDY
RTS
CMP
BNE
LDA
STA
DEC
BPL
LDA

0
2
PST
INIT
#$3C
$D302
#PND
$02E7
#PND/256
$02E8
#INIT
$0A
#INIT/256
$0B

1
#$30
$D303
#$FF
$D301
#$34
$D303
#$80
$D301
#1
#$9B
PRINT
LINLEN
LCOUNT
COUNT
NOFF
#12

72

0654:
0657:
065A:
065C:
065F:
0662:
0664:
0667:
066A:
066C:
066E:
0670:
0673:
0675:
0678:
067A:
067D:
0680:
0683:

20
EE
A9
8D
EE
A9
20
CE
F0
D0
A9
8D
A9
8D
A9
8D
AD
8D
4C

0686:
0687:
0689:
068B:
068D:
068F:
0691:
0694:
0696:
0699:
069w:
069D:
069F:
06A1:
06A3:
06A5:
06A8:
06AA:
06AE:
06AE:
0681:
06B3:
06B5:
06B8:
06BB:
06BD:
068E:
06C1:
06C4:
06C7:
06CA:
06CD:
06D0:

68
A5
85
A5
85
A9
BD
A9
8D
A2
A1
29
E9
80
69
20
E6
D0
E6
CE
l0
A9
20
EE
10
60
48
53
41
45
32
37
31

06D1:
06D4:
06D6:
06D8:
O6DA:
06DD:
06DF:

AC
DO
A0
09
8D
29
8D

64
E9
41
E8
E9
0D
D1
E9
DB
D2
1F
1B
06
1C
41
E8
EA
E9
2C
58
FE
59
FF
17
E6
27
E7
00
FE
7F
60
02
20
D1
FE
02
FF
E7
E8
0D
0l
E6
D7
41
20
47
52
37
2E

06
06
06
06
06
06

03

JSR
INC
LDA
STA
INC
LDA
JSR
DEC
BEQ
BNE
LDA
STA
LDA
STA
LDA
STA
LDA
STA
JMP

PRINT
LCOUNT
#65
COUNT
LCOUNT
#13
OUTCHAR
LCOUNT
CARR
RTS1
#HANDLTAB
$031B
#HANDLTAB/256
$031C
#65
COUNT
LlNLEN
LCOUNT
OPEN

PLA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDX
LDA
AND
CMP
BCS
ADC
JSR
INC
BNE
INC
DEC
BPL
LDA
JSR
DEC
BPL
RTS

BASIS
PT
BASIS+1
PT+1
#23
ROW
#39
COLOMN
#0
(PT,X)
#$7F
#$60
LOOP1
#$20
OUTCHAR
PT
*+4
PT+1
COLUMN
LOOP
#13
OUTCHAR
ROW
ROWLOOP

AUTHOR

ASC

"HANS WAGNER

OUTCHAR

LDY
BNE
LDY
ORA
STA
AND
STA

$D013
OUTCHAR
#$80
#$80
$D301
#$7F
$D301

NOFF
PRINT

INIT

03
06
06
06
06
BASIC
NORMAL

06

ROWLOOP

06
LOOP

06

LOOP1

06
06
06
4E
57
4E
20
2E
38

l3 D0
FB
80
80
01 D3
7F
01 D3

73

06E2: 8C 01 D3
06E5: 60
06E6:
06E7:
06E8:
06E9:
06EA:

17
27
41
FF
FF

BASIS
PST
DUMMY
RTS1
CARR
PRlNT
BASIC
ROWLOOP
LOOP1
OUTCHAR
COLUMN
LCOUNT
PND

ROW
COLUMN
COUNT
LCOUNT
LINLEN
PND
$58
$0600
$062B
$0640
$0647
$0664
$0686 UNUSED
$0694
$06A5
$06D1
$06E7
$06E9
$06EB

STY
RTS

$D301

DFB
DFB
DFB
DFB
DFB
EQU

23
39
6S
255
255
*

PT
HANDLTAB
OPEN
WRITE
NOFF
INIT
NORMAL
LOOP
AUTHOR
ROW
COUNT
LINLEN

$FE
$061F
$062C
$0643
$065F
$066E
$0687 UNUSED
$069B
$06BE UNUSED
$06E6
$06E8
$06EA

Program description:
Address
0600-061E
0610-082b
062C-0642
0643-066D
066E-0685
0686-06BD

end of the booting start


HANTAB for the ATARI OS
opens the ports for output
printer driver
initialize. Now LPRINT and PRINT P use thee printer
driver.
Label BASIC starting address for a call by BASIC.
Label NORMAL starting address for a call by assembler.
Copyright notice
Subroutine, brings one ASCII character from the accumulator to
the printer
values for the various counters
ROW sets the number of horizontal lines to 23.
COLUMN sets the number of characters of one line to 39.
COUNT sets the number of lines between two formfeeds to 65
LCOUNT, LINLEN contains the actual parameters for the number of
characters and lines.

068E-06D0
06D1-06E5
O6E6-06EA

Boot-Routine
PST
PND
FLEN

EQU
EQU
EQU

6000: A2 10
6002: A9 03
6004: 9D 42 03

$0600
$0700
PND-PST+127/128*128
ORG
$6000
BOOTB

LDX
LDA
STA

#$10
#3
$0342,X

74

6007:
6009:
600C:
600E:
6011:
6013:
60l6:
6018:
6018:
601E:
6020:
6022:
6025:
6027:
602A:
602C:
602F:
6031:
6034:
6036:
6039:
603C:
603E:
6040:
6043:
6046:
6048:
6049:
604A:
604E:
PST
PND
FLEN
BOOTB
CERR
CFILE

A9
9D
A9
9D
A9
9D
A9
9D
20
30
A9
9D
A9
9D
A9
9D
A9
9D
A9
9D
20
30
A9
9D
20
30
00
00
43
9B

08
4A
80
4B
4A
44
60
45
56
29
0B
42
00
44
06
45
00
48
01
49
56
0B
0C
42
56
01

LDA
STA
LDA
STA
LDA
STA
LDA
STA
JSR
BMI
LDA
STA
LDA
STA
LDA
STA
LDA
STA
LDA
STA
JSR
BMI
LDA
STA
JSR
BMI
BRK
BRK
ASC
DFB

03
03
03
03
E4
03
03
03
03
03
E4
03
E4
CERR
CFILE

3A
$0600
$0700
$0100
$6000
$6049
$604A

#8
$034A,X
#$80
$034B,X
#CFILE
$0344,X
#CFILE/256
$0345,X
$E456
CERR
#$0B
$0322,X
#PST
$0344,X
#PST/256
$0345,X
#FLEN
$0348,X
#FLEN/256
$0349,X
$E456
CERR
#$0C
$0342,X
$E456
CERR
"C:
*9B

UNUSED

If you want to use this program, it has to be bootable. Therefore you


must enter both programs and start the boot routine at address $6000. This
will create a bootable cassette, you can use afterwards in the following
manner, to enter the SCREENPRINT in your comouter.
- turn off the computer
- press the start key
- turn on the computer
- release the start key
- press PLAY on the recorder and
- press RETURN
BASIC or assembler-editor cartridge must be in the left slot of your ATARI
computer.

75

COMMENT:
DIFFERENCES BETWEEN THE ATARI EDITOR/ASSEMBLER CARTRIDGE AND ATAS-1 AND
ATMAS-1
The programs in this book are developed using the ATMAS (ATAS) syntax.
In the following I would like to explain the difference of some mnemonics
of the ATARI Editor/Assembler cartridge and the Editor/Assembler and ATMAS1 from Elcomp Publishing.
Instead of the asterisk the ATAS uses the pseudo op-codes ORG. Another
difference is that the ATAS is screen oriented (no line numbers needed).
Instead of the equal sign ATAS uses EQU. Additionally ATAS allows you the
pseudo op-codes EPZ: Equal Page Zero.
There is also a difference in using the mnemonics regarding storage of
strings within the program.
ATARI
- BYTE "STRING"
- BYTE $
- WORD

ELCOMP
=
=
=

ASC "STRING"
DFB $ (Insertion of a byte)
DFW (Insertion of a word Lower byte,
higher byte)

The end of string marker of the ATARI 800/400 output routine is hex 9B.
In the listing you can see, how this command is used in the two assemblers:
ATARI Assembler: - BYTE $9B
ATMAS from ELCOMP - DFB $9B
Depending on what Editor/Assembler from ELCOMP you use, the stringoutput is
handled as follows:
1. ATAS 32K and ATAS 48K cassette version
LDX # TEXT
LDY # TEXT/256
TEXT ASC "STRING"
DFB$9B
2. ATMAS 48K
LDX # TEXT:L
LDY # TEXT:H
TEXT ASC "STRING"
DFB $9B
There is also a difference between other assemblers and the ATAS-1 or
ATMAS-1 in the mnemonic code for shift and relocate commands for the
accumulator.
(ASL A = ASL) = OA
(LSR A = LSR) = 4A
ROL A = ROL = 2A
ROR A = ROR = 6A
The ATMAS/ATAS also allows you to comment consecutive bytes as follows:

76

JUMP EQU $F5.7


$F5 = Label Jump
$F6 and $F7 are empty locations.
This is a comment and not an instruction.

77

Вам также может понравиться