1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
; autorun.s - display an intro screen and a menu from which the user
; can launch dla.xex or dla2csv.xex, or exit to DOS.
; I was *going* to write this in C, using cc65's exec()... but it
; turns out to only be implemented on XDOS, which is a rather uncommon
; DOS. MyDOS has XIO 40 (execute binary file), which is a lot easier
; to deal with in asm. Other DOSes might support XIO 40, and/or this
; might support other DOSes someday... Or I could write my own xex
; file loader (rather not).
; SDX 4.41 manual says: XIO 40,#IOCB,4,X,"Dd:[path]fname.ext" where
; X=0 for load and execute (X=128 is load only, we don't want that).
; manual also says it works the same way in Sparta 3.2.
; MyDOS 4.50 technical manual says XIO 39 and 40 are identical, and
; that AUX1 should be 4 to load & execute the program (AUX2 doesn't
; do anything). MyDOS 4.30 only documents 39, but I don't care about
; versions older than 4.50.
; So for all 3 DOSes, XIO 40,#x,4,0,"filename" works... XXX: except it
; doesn't, quite. MyDOS and Sparta 3.2 can load & run both dla.xex and
; dla2csv.xex. SDX 4.42 will load & run dla2csv.xex, but fails with
; error 150 for dla.xex (error 150 is "path not found", no idea what's
; going on here). This autorun.sys only has to work on MyDOS, which
; it does...
; Eventually I should send the cc65 devs a patch to implement exec()
; on MyDOS and Sparta.
.include "atari.inc"
.include "xex.inc"
.bss
.org $80
old_sdlstl: .res 1
old_sdlsth: .res 1
old_color2: .res 1
old_color1: .res 1
keycode: .res 1
.code
; this doesn't have to be aligned on a 4K boundary, but it should
; be aligned to 1K.
loadaddr = $3000
xex_org loadaddr
screendata:
.incbin "about.dat" ; generated from ABOUT.txt, by text2screen.pl
; 960 bytes is exactly one GR.0 screen (40x24)
.if ((* - screendata) <> 960)
.error .sprintf("%c*** about.dat is %d bytes (should be 960)", 10, * - screendata)
.endif
; bog-standard GRAPHICS 0 display list (except the LMS address)
dlist:
.byte DL_BLK8, DL_BLK8, DL_BLK8
.byte DL_CHR40x8x1 | DL_LMS
.word screendata
.repeat 23
.byte DL_CHR40x8x1
.endrep
.byte DL_JVB
.word dlist
.if ((* / 1024) <> (screendata / 1024))
.error .sprintf("%c*** screendata and dlist cross a 1K boundary!", 10)
.endif
.include "io.s"
.include "printint.s"
main:
; fix things so the Reset key doesn't do a coldstart, see
; BOOT? and COLDST in Mapping.
ldx #0
stx COLDST
inx
stx BOOTQ
; save the OS's colors and display list.
lda SDLSTL
sta old_sdlstl
lda SDLSTH
sta old_sdlsth
lda COLOR1
sta old_color1
lda COLOR2
sta old_color2
; use our own colors and display list (displays our message).
lda #$90
sta COLOR2
lda #$0e
sta COLOR1
lda #<dlist
sta SDLSTL
lda #>dlist
sta SDLSTH
; wait for a keypress
keyloop:
lda CH
cmp #KEY_NONE
beq keyloop
sta keycode ; got a keypress, save it for later
; clear keypress so the loaded program won't see it
lda #$ff
sta CH
; restore OS's colors and display list (back to regular E:)
lda old_sdlstl
sta SDLSTL
lda old_sdlsth
sta SDLSTH
lda old_color1
sta COLOR1
lda old_color2
sta COLOR2
; see what key was hit
ldy #0
keytabloop:
lda keytab,y ; get table entry
cmp #KEY_NONE ; did we hit the end of the table with no match?
beq exit ; yes, we're done
cmp keycode ; no, see if this table entry matches
beq load_file ; yes, use it
iny ; no, look at next entry
bne keytabloop ; branch always
; load and run the file (Y is index into filename table)
load_file:
; first print a "Loading D1:whatever" message.
sty keycode
lda #<loadingmsg
ldx #>loadingmsg
jsr printmsg
ldy keycode
lda fntab_l,y
ldx fntab_h,y
jsr printmsg
ldy keycode
; now we can set up the IOCB and call CIO to load the file.
ldx #$10 ; IOCB #1
lda #$28 ; MyDOS, Sparta 3.2, and SDX all support this XIO
sta ICCOM,x
lda fntab_l,y ; filename
sta ICBAL,x
lda fntab_h,y
sta ICBAH,x
lda fnlentab,y ; filename length
sta ICBLL,x
lda #0
sta ICBLH,x
sta ICAX2,x ; AUX1=0: On Sparta means "load & run", on MyDOS ignored.
lda #4
sta ICAX1,x ; AUX2=4: On MyDOS means "load & run", on Sparta 4 is required.
jsr CIOV ; pull the trigger
; CIOV should never return on success, so if we get here, give up.
tya
pha ; save CIO return status (aka error number)
lda #<diskerrmsg
ldx #>diskerrmsg
jsr printmsg ; print error message
pla
jsr printdecb ; print error number
lda #<presskeymsg
ldx #>presskeymsg
jsr printmsg ; press a key...
; wait for a keypress, to give the user a chance to read the
; error message.
keyloop2:
lda CH
cmp #KEY_NONE
beq keyloop2
lda #KEY_NONE
sta CH
exit:
rts
; SDX insists these must be D1:, not just D:. There's probably
; a good reason...
dla_filename: .byte "D1:DLA.XEX"
dla_fn_len = * - dla_filename
.byte 0 ; null terminate for printmsg
csv_filename: .byte "D1:DLA2CSV.XEX"
csv_fn_len = * - csv_filename
.byte 0
; these tables only have 2 entries, but could have many more if
; we ever need them (up to 255).
fntab_l: .byte <dla_filename, <csv_filename
fntab_h: .byte >dla_filename, >csv_filename
fnlentab: .byte dla_fn_len, csv_fn_len
; KEY_NONE marks the end of this table.
keytab: .byte KEY_1, KEY_2, KEY_NONE
diskerrmsg: .byte "I/O Error ",0
presskeymsg: .byte $9b,"Press any key...",0
loadingmsg: .byte "Loading ",0
xex_run main
|