-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathautorun.s
216 lines (176 loc) · 6.42 KB
/
autorun.s
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
214
215
216
; ---------------------------------------------------------------
;
; AutoRun 1.5.0 for C64
;
; A small program that executes itself immediately after
; being loaded. This program loads and executes a
; program specified by the coder.
;
; The most common use of a program like this would be
; to make it the first file on a disk and load it using
; LOAD "*",8,1. You don't have to type RUN after it
; loads, it just starts. Many professional games, demos
; and utilities used this technique to display messages
; and graphics while the main program is loading.
;
; This code is public domain and you may do whatever you
; want with the source.
;
; "Michael McIntosh" [email protected] - 2003.02.14
;
; ---------------------------------------------------------------
;
; File partially generated by cc65 v 2.7.1
;
.fopt compiler,"cc65 v 2.7.1"
.autoimport on
.case on
.debuginfo off
.importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
.macpack longbranch
.export _main
; ---------------------------------------------------------------
; Begin Custom Config Section
; ---------------------------------------------------------------
;
; Modify the following defines to customize the behavior of the autoloader
;
; file name of program to load (filenames normally need to be capitalized)
.DEFINE PRG_NAME "HELLO"
; address of code to execute when file is loaded
; NOTE: $080D is the default ML entry point for cc65 compiled programs
.DEFINE PRG_ADDR $080D
; Whether or not to include to extra code to gracefully
; handle the end-user incorrectly calling LOAD "*",8, which
; causes the program to be loaded into memory at $0801
; instead of the desired location at $02A7
; Usage: 0 for No, 1 for Yes
.DEFINE USE_SAFETY_CODE 1
; Whether or not to change the border to black and turn the
; screen off until some other program turns it back on. 0 for no,
; 1 for yes. If you use this option with the USE_SAFETY_CODE
; option, the maximum file name length you can use will be 9
; characters long.
.DEFINE BLANK_SCREEN 0
; ---------------------------------------------------------------
; End Custom Config Section
; ---------------------------------------------------------------
; Location of Kernal routines
listen = $ffb1
second = $ff93
unlsn = $ffae
acptr = $ffa5
chkin = $ffc6
chkout = $ffc9
chrin = $ffcf
chrout = $ffd2
ciout = $ffa8
close = $ffc3
open = $ffc0
setmsg = $ff90
setnam = $ffbd
setlfs = $ffba
clrchn = $ffcc
getin = $ffe4
restore = $ff8a
load = $ffd5
save = $ffd8
; Location of basic routines
basicerrormsg = $E38B ; basic error message print routine
basicwarmstart = $A483 ; standard basic warm start routine
; use this segment to specify filename to load and run
.segment "DATA"
; String Format: Length, Data, Terminator
_prg_name:
.byte PRG_NAME
; file header - the first two bytes indicate a program's load address
.segment "HEAD"
_loadaddr:
; sets file load address to $02A7
.addr $02A7
; ---------------------------------------------------------------
; vectors to print error and basic warmstart
;
; By putting the address of my code ($02A7) here, the code
; gets executed immediately after file load since normally
; basic calls a warm start at that point.
; ---------------------------------------------------------------
.segment "VECTORS"
_vector_ierror:
.addr $E38B ; normally $E38B
_vector_imain:
.addr _main ; normally $A483 but set to where our
; code will start at $02A7 instead
; ---------------------------------------------------------------
; IMPORTANT NOTE: The size of the compiled "CODE" portion of this
; program cannot exceed 89 bytes ($02A7-$02FF).
; If you intend to add to this program, keep this
; in mind. You'll get a linker error if that
; becomes an issue.
; ---------------------------------------------------------------
.if USE_SAFETY_CODE
.segment "CODE"
; if user types LOAD "*",8 instead of LOAD "*",8,1 we will
; recover gracefully by providing an entry point for the basic
; interpreter to copy the machine language code to the proper
; location and execute it
.proc _basicstub
;; Encode "7 SYS2059" at beginning of basic stub
.byte $0B,$08,$07,$00,$9E,$32,$30,$35,$39,$00
;; code to copy program (93 bytes) to proper place in
;; memory ($02A7) and execute
ldx #$00
LOOP: lda $0801,x ; fetch byte relative to start of basic
sta $02A7,x ; store byte relative to proper code address
inx ; increment index
cpx #$5D ; if .x >= $5D then .c = 1 else .c = 0
bcc LOOP ; Branch if .c = 0 (.x < $5D [92 bytes])
jmp _main ; jump to the proper start of the ml
.endproc
.endif ; USE_SAFETY_CODE
.segment "CODE"
; ---------------------------------------------------------------
; void main ()
; ---------------------------------------------------------------
.proc _main
;; restore proper values for basic warm start vector
;; so runstop/restore works properly
lda #<(basicwarmstart)
sta _vector_imain
lda #>(basicwarmstart)
sta _vector_imain+1
;;
;; If you wanted to change the border color and turn the
;; screen off while a file is loading/initializing
;; this is a good place to do it. The following code
;; would turn the border black and turn the screen off
;; until something else turned it back on.
;;
.if BLANK_SCREEN
lda #$00
sta $D020 ; set border to black
lda #$0B
sta $D011 ; turn screen off (in textmode)
.endif ; BLANK_SCREEN
;; Set Logical File
ldx #$08 ; device unit #
ldy #$01 ; load at address stored in file
jsr setlfs ; set logical file (kernal call)
;; Set File Name
lda #(.strlen(PRG_NAME)) ; get length of filename
ldx #<(_prg_name) ; set lower address of filename
ldy #>(_prg_name) ; set upper address of filename
jsr setnam ; set file name (kernal call)
;; Load the File
lda #$00 ; set flag for load operation
jsr load ; load program file (kernal call)
;; Branch and execute code if there is no load error
bcc RUNPRG
.if BLANK_SCREEN
ldx #$1B
stx $D011 ; turn screen back on with textmode
.endif
;; Print error and return to basic
jmp $e104
RUNPRG: jmp PRG_ADDR ; jump to program entry point
.endproc