8bitworkshop/res/altirra/kernelxl.lst

12416 lines
435 KiB
Plaintext

mads 2.1.0
Source: source/main.xasm
1 ; Altirra - Atari 800/800XL emulator
2 ; Kernel ROM replacement
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11
12 .if _KERNEL_XLXE
13 = 0001 _KERNEL_PBI_SUPPORT = 1
14 = 0001 _KERNEL_USE_BOOT_SCREEN = 1
15 .macro _KERNELSTR_BIOS_NAME_INTERNAL
16 .ifdef _KERNEL_816
17 dta d" for 65C816"
18 .else
19 dta d" for XL/XE/XEGS"
20 .endif
21 .endm
22 .else
23 _KERNEL_PBI_SUPPORT = 0
24 _KERNEL_USE_BOOT_SCREEN = 0
25 .endif
26
27 = 0001 _KERNEL_PRINTER_SUPPORT = 1
28
29 ;==========================================================================
30
31 icl 'version.inc'
Source: source/Shared/version.inc
1 ; Altirra - Atari 800/800XL emulator
2 ; Kernel ROM replacement - version info
3 ; Copyright (C) 2008-2020 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 .macro _KERNELSTR_VERSION
11 dta '3.26'
12 .endm
13
14 .macro _KERNELSTR_VERSION_INTERNAL
15 dta "3.26"
16 .endm
32 icl 'hardware.inc'
Source: source/Shared/hardware.inc
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Hardware register definitions
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 .ifndef f_HARDWARE_INC
11 .def f_HARDWARE_INC
12
13 ;==========================================================================
14 ; GTIA
15 ;
16 m0pf equ $d000
17 m1pf equ $d001
18 m2pf equ $d002
19 m3pf equ $d003
20 p0pf equ $d004
21 p1pf equ $d005
22 p2pf equ $d006
23 p3pf equ $d007
24 m0pl equ $d008
25 m1pl equ $d009
26 m2pl equ $d00a
27 m3pl equ $d00b
28 p0pl equ $d00c
29 p1pl equ $d00d
30 p2pl equ $d00e
31 p3pl equ $d00f
32
33 hposp0 equ $d000
34 hposp1 equ $d001
35 hposp2 equ $d002
36 hposp3 equ $d003
37 hposm0 equ $d004
38 hposm1 equ $d005
39 hposm2 equ $d006
40 hposm3 equ $d007
41 sizep0 equ $d008
42 sizep1 equ $d009
43 sizep2 equ $d00a
44 sizep3 equ $d00b
45 sizem equ $d00c
46 grafp0 equ $d00d
47 grafp1 equ $d00e
48 grafp2 equ $d00f
49 grafp3 equ $d010
50 grafm equ $d011
51 trig0 equ $d010
52 trig1 equ $d011
53 trig2 equ $d012
54 colpm0 equ $d012
55 trig3 equ $d013
56 colpm1 equ $d013
57 pal equ $d014
58 colpm2 equ $d014
59 colpm3 equ $d015
60 colpf0 equ $d016
61 colpf1 equ $d017
62 colpf2 equ $d018
63 colpf3 equ $d019
64 colbk equ $d01a
65 prior equ $d01b
66 vdelay equ $d01c
67 gractl equ $d01d
68 hitclr equ $d01e
69 consol equ $d01f
70
71 ;==========================================================================
72 ; POKEY
73 ;
74 pot0 equ $d200
75 audf1 equ $d200
76 pot1 equ $d201
77 audc1 equ $d201
78 pot2 equ $d202
79 audf2 equ $d202
80 pot3 equ $d203
81 audc2 equ $d203
82 pot4 equ $d204
83 audf3 equ $d204
84 pot5 equ $d205
85 audc3 equ $d205
86 pot6 equ $d206
87 audf4 equ $d206
88 pot7 equ $d207
89 audc4 equ $d207
90 audctl equ $d208
91 kbcode equ $d209
92 skres equ $d20a
93 potgo equ $d20b
94 serin equ $d20d
95 serout equ $d20d
96 irqen equ $d20e
97 irqst equ $d20e
98 skctl equ $d20f
99 skstat equ $d20f
100
101 ;==========================================================================
102 ; PIA
103 ;
104 porta equ $d300
105 portb equ $d301
106 pactl equ $d302
107 pbctl equ $d303
108
109 ;==========================================================================
110 ; ANTIC
111 ;
112 dmactl equ $d400
113 chactl equ $d401
114 dlistl equ $d402
115 dlisth equ $d403
116 hscrol equ $d404
117 vscrol equ $d405
118 pmbase equ $d407
119 chbase equ $d409
120 wsync equ $d40a
121 vcount equ $d40b
122 penh equ $d40c
123 penv equ $d40d
124 nmien equ $d40e
125 nmist equ $d40f
126 nmires equ $d40f
127
128 ;==========================================================================
129 ; 6502
130 ;
131 nmivec equ $fffa
132 resvec equ $fffc
133 irqvec equ $fffe
134
135 .endif
33 icl 'kerneldb.inc'
Source: source/Shared/kerneldb.inc
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Kernel Database Definitions
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 .ifndef f_KERNELDB_INC
11 .def f_KERNELDB_INC
12
13 casini = $0002 ;cassette initialization vector
14 ramlo = $0004 ;
15 tramsz = $0006 ;temporary ram size / cart A flag
16 tstdat = $0007 ;RAM test data register / cart B flag
17 ;(also CMCMD for T:)
18 warmst = $0008 ;warmstart flag
19 boot? = $0009 ;boot flag; 0 if none, 1 for disk, 2 for cassette
20 dosvec = $000a
21 dosini = $000c
22 appmhi = $000e
23 pokmsk = $0010
24 brkkey = $0011 ;set on [BREAK]
25 rtclok = $0012
26 bufadr = $0015 ;indirect buffer address pointer (temp for disk buffer)
27 ; $0016
28 iccomt = $0017 ;CIO: command byte
29 ziocb = $0020 ;zero-page IOCB
30 ichidz = $0020 ;Zero page IOCB: device index ($FF = not open)
31 icdnoz = $0021 ;Zero page IOCB: device number
32 iccomz = $0022 ;Zero page IOCB: command byte
33 icstaz = $0023 ;Zero page IOCB: status byte
34 icbalz = $0024 ;Zero page IOCB: address of device/filename spec lo
35 icbahz = $0025 ;Zero page IOCB: address of device/filename spec hi
36 icptlz = $0026 ;Zero page IOCB: put byte address lo (-1)
37 icpthz = $0027 ;Zero page IOCB: put byte address hi (-1)
38 icbllz = $0028 ;Zero page IOCB: buffer length/byte count lo (-1)
39 icblhz = $0029 ;Zero page IOCB: buffer length/byte count hi (-1)
40 icax1z = $002a ;Zero page IOCB: device-specific information 1
41 icax2z = $002b ;Zero page IOCB: device-specific information 2
42 icax3z = $002c ;Zero page IOCB: device-specific information 3
43 icax4z = $002d ;Zero page IOCB: device-specific information 4
44 icax5z = $002e ;Zero page IOCB: device-specific information 5
45 icidno = $002e ;CIO: call X register save/restore
46 icax6z = $002f ;Zero page IOCB: device-specific information 6
47 ciochr = $002f ;CIO: call A register save/restore
48 status = $0030 ;SIO: temporay status byte
49 chksum = $0031 ;SIO: temporary checksum byte (used by IRQ routines)
50 bufrlo = $0032 ;SIO: buffer pointer lo (incremented by IRQ routines)
51 bufrhi = $0033 ;SIO: buffer pointer hi (incremented by IRQ routines)
52 bfenlo = $0034 ;SIO: buffer end lo
53 bfenhi = $0035 ;SIO: buffer end hi
54 ltemp = $0036 ;Relocating loader: loader temp address (XL/XE)
55 ; $0037
56 bufrfl = $0038 ;SIO: buffer full flag
57 recvdn = $0039 ;SIO: receive completed flag
58 xmtdon = $003a ;SIO: transmit completed flag
59 chksnt = $003b ;SIO: checksum sent flag
60 nocksm = $003c ;SIO: no-checksum flag
61 bptr = $003d ;Cassette: Buffer pointer
62 ftype = $003e ;Cassette: Interrecord gap (IRG) type; bit7=1 means continuous mode
63 feof = $003f ;Cassette: EOF flag
64 soundr = $0041 ;SIO: noisy audio flag
65 critic = $0042 ;critical flag for vbi
66 zchain = $004a ;Peripheral Handler: zero-page chain address
67 ; $004b
68 atract = $004d ;screen attract counter
69 drkmsk = $004e ;screen attract mask
70 colrsh = $004f ;screen attract color shift
71 tmpchr = $0050 ;Screen Editor
72 hold1 = $0051 ;Display/Editor: temporary storage
73 lmargn = $0052 ;left margin column
74 rmargn = $0053 ;right margin column
75 rowcrs = $0054 ;cursor row
76 colcrs = $0055 ;cursor column
77 ; $0056
78 dindex = $0057 ;display mode index
79 savmsc = $0058 ;lowest address of screen region
80 oldrow = $005a ;
81 oldcol = $005b ;
82 oldchr = $005d ;cursor character save/restore
83 oldadr = $005e ;cursor memory address
84 ; $005f
85 palnts = $0062 ;PAL/NTSC flag
86 logcol = $0063 ;Display/Editor: Logical column (0-119)
87 adress = $0064 ;temporary storage (display code)
88 ; $0065
89 toadr = $0066 ;temporary storage (display code)
90 a1 = toadr
91 ; $0067
92 frmadr = $0068 ;temporary storage (display code)
93 ; $0069
94 ramtop = $006a ;ram size
95 bufcnt = $006b
96 bufstr = $006c ;row/column of start of logical line
97 bitmsk = $006e ;Screen Editor
98 shfamt = $006f ;Screen Editor
99 rowac = $0070 ;Screen Editor: line drawing
100 ; $0071 ;
101 colac = $0072 ;Screen Editor: line drawing
102 ; $0073 ;
103 endpt = $0074 ;Screen Editor: line drawing
104 ; $0075 ;
105 deltar = $0076 ;Screen Editor: delta row (line drawing)
106 deltac = $0077 ;Screen Editor: delta column (line drawing)
107 ; $0078 ;
108 keydef = $0079 ;XL/XE: Keyboard definition table
109 ; $007a
110 swpflg = $007b ;current display var state ($00 = main, $FF = split screen)
111 holdch = $007c ;temporary key hold area prior to shift/control lock logic
112 countr = $007e ;Screen Editor: line length
113 ; $007f
114 fr0 = $00d4 ;FP: Accumulator 0
115 _fr3 = $00da ;FP: Accumulator 3 (officially FRE)
116 fr1 = $00e0 ;FP: Accumulator 1
117 fr2 = $00e6 ;FP: Accumulator 2
118 _fpcocnt= $00ec ;FP: temporary storage - polynomial coefficient counter
119 _fptemp0= $00ed ;FP: temporary storage - transcendental temporary (officially EEXP)
120 _fptemp1= $00ee ;FP: temporary storage - transcendental temporary (officially NSIGN)
121 ;esign $00ef ;BASIC: Used in sqr() routine -- must not be touched by FP elementary functions
122 ;fchrflg $00f0 ;BASIC: Used in sin() routine -- must not be touched by any FP functions
123 cix = $00f2 ;FP: Character index
124 inbuff = $00f3 ;FP: ASCII conversion buffer
125 ; $00f4
126 ; $00f5 ;FP: temporary storage -- also temporarily used by BASIC power routine
127 ; $00f6 ;FP: temporary storage
128 ztemp4 = $00f7 ;FP: temporary storage -- also temporarily used by BASIC power routine
129 ; $00f8 ;FP: temporary storage
130 ; $00f9 ;FP: temporary storage
131 ; $00fa ;FP: temporary storage
132 degflg = $00fb ;FP: degree/radian flag (0=radians, 6=degrees)
133 flptr = $00fc ;FP: pointer for floating-point loads and stores
134 fptr2 = $00fe ;FP: pointer for polynomial evaluation
135
136 vdslst = $0200 ;display list interrupt vector
137 vprced = $0202 ;serial bus proceed interrupt vector
138 vinter = $0204 ;serial bus interrupt vector
139 vbreak = $0206 ;BRK instruction vector
140 vkeybd = $0208 ;keyboard interrupt vector
141 vserin = $020a ;serial input ready interrupt vector
142 vseror = $020c ;serial output ready interrupt vector
143 vseroc = $020e ;serial output completed interrupt vector
144 vtimr1 = $0210 ;pokey timer 1 interrupt vector
145 vtimr2 = $0212 ;pokey timer 2 interrupt vector
146 vtimr4 = $0214 ;pokey timer 4 interrupt vector
147 vimirq = $0216 ;immediate IRQ vector
148 cdtmv1 = $0218 ;countdown timer 1
149 cdtmv2 = $021a ;countdown timer 2
150 cdtmv3 = $021c ;countdown timer 3
151 cdtmv4 = $021e ;countdown timer 4
152 cdtmv5 = $0220 ;countdown timer 5
153 vvblki = $0222 ;vertical blank immediate vector
154 vvblkd = $0224 ;vertical blank deferred vector
155 cdtma1 = $0226 ;timer 1 vector
156 cdtma2 = $0228 ;timer 2 vector
157 cdtmf3 = $022a ;timer 3 flag
158 srtimr = $022b ;autorepeat timer
159 cdtmf4 = $022c ;timer 4 flag
160 intemp = $022d ;temp value used by SETVBV
161 cdtmf5 = $022e ;timer 5 flag
162 sdmctl = $022f ;shadow for DMACTL ($D400)
163 sdlstl = $0230 ;shadow for DLISTL ($D402)
164 sdlsth = $0231 ;shadow for DLISTH ($D403)
165 sskctl = $0232 ;shadow for SKCTL ($D20F)
166 lcount = $0233 ;Relocating loader: (XL/XE)
167 lpenh = $0234 ;light pen horizontal pos
168 lpenv = $0235 ;light pen vertical pos
169 brkky = $0236 ;break key interrupt vector (OS B+ only)
170 vpirq = $0238 ;PBI device interrupt vector (XL/XE)
171 ; $0239
172 cdevic = $023a ;SIO: command frame device ID
173 ccomnd = $023b ;SIO: command frame command ID
174 caux1 = $023c ;SIO: command aux byte 1
175 caux2 = $023d ;SIO: command aux byte 2
176 temp = $023e ;SIO: temp space
177 errflg = $023f ;SIO: error flag
178 dflags = $0240 ;disk boot flags
179 dbsect = $0241 ;disk boot sector count
180 bootad = $0242 ;disk boot address
181 coldst = $0244 ;cold start flag
182 reclen = $0245 ;Relocating loader: record length (XL/XE)
183 dsktim = $0246 ;Disk Handler: Disk operation timeout
184 pdvmsk = $0247 ;PBI device mask (XL/XE)
185 shpdvs = $0248 ;PBI device selection register shadow ($D1FF) (XL/XE)
186 pdmsk = $0249 ;PBI device interrupt mask (XL/XE)
187 reladr = $024a ;Relocating loader: temp address (XL/XE)
188 ; $024b
189
190 .if _KERNEL_816
191 vabte = $024f ;(816) Emulation ABORT vector
192 ; $0250
193 vcope = $0251 ;(816) Emulation COP vector
194 ; $0252
195 vabtn = $0253 ;(816) Native ABORT vector
196 ; $0254
197 ; $0255
198 vcopn = $0256 ;(816) Native COP vector
199 ; $0257
200 ; $0258
201 vnmin = $0259 ;(816) Native NMI vector
202 ; $025a
203 ; $025b
204 virqn = $025c ;(816) Native IRQ vector
205 ; $025d
206 ; $025e
207 vbrkn = $025f ;(816) Native BREAK vector
208 ; $0260
209 ; $0261
210 vcop0 = $0262 ;(816) Native COP #0 vector
211 ; $0263
212 ; $0264
213 vcopu = $0265 ;(816) Native COP #1-127 vector
214 ; $0266
215 ; $0267
216 vcopc = $0268 ;(816) Native COP #128-255 vector
217 ; $0269
218 ; $026a
219 .endif
220
221 fine = $026e ;fine scrolling flag (XL/XE)
222 gprior = $026f ;shadow for PRIOR ($D01B)
223 paddl0 = $0270 ;shadow for POT0 ($D200)
224 paddl1 = $0271 ;shadow for POT1 ($D201)
225 paddl2 = $0272 ;shadow for POT2 ($D202)
226 paddl3 = $0273 ;shadow for POT3 ($D203)
227 paddl4 = $0274 ;shadow for POT4 ($D204)
228 paddl5 = $0275 ;shadow for POT5 ($D205)
229 paddl6 = $0276 ;shadow for POT6 ($D206)
230 paddl7 = $0277 ;shadow for POT7 ($D207)
231 stick0 = $0278 ;shadow for PORTA lo ($D300)
232 stick1 = $0279 ;shadow for PORTA hi ($D300)
233 stick2 = $027A ;shadow for PORTB lo ($D302)
234 stick3 = $027B ;shadow for PORTB hih ($D302)
235 ptrig0 = $027c ;paddle trigger 0
236 ptrig1 = $027d ;paddle trigger 1
237 ptrig2 = $027e ;paddle trigger 2
238 ptrig3 = $027f ;paddle trigger 3
239 ptrig4 = $0280 ;paddle trigger 4
240 ptrig5 = $0281 ;paddle trigger 5
241 ptrig6 = $0282 ;paddle trigger 6
242 ptrig7 = $0283 ;paddle trigger 7
243 strig0 = $0284 ;shadow for TRIG0 ($D001)
244 strig1 = $0285 ;shadow for TRIG1 ($D002)
245 strig2 = $0286 ;shadow for TRIG2 ($D003)
246 strig3 = $0287 ;shadow for TRIG3 ($D004)
247 hibyte = $0288 ;Relocating loader (XL/XE)
248 wmode = $0289 ;Cassette: Write mode (00 = read, 80 = write)
249 blim = $028a ;Cassette: Buffer limit
250 jveck = $028c ;XL/XE: IRQ jump vector
251 newadr = $028e ;Relocating loader (XL/XE)
252 txtrow = $0290
253 txtcol = $0291
254 ; $0292
255 tindex = $0293 ;text mode index
256 txtmsc = $0294 ;text window pointer
257 ; $0295
258 cretry = $029c ;SIO: command retries (XL/XE)
259 hold3 = $029d ;Screen Editor
260 hold2 = $029f ;Screen Editor
261 dmask = $02a0 ;Display/Editor: Graphics merge mask
262 tmplbt = $02a1
263 escflg = $02a2 ;Display/Editor: Escape next character
264 tabmap = $02a3 ;Display/Editor: Bitfield indicating tabs (note reversed bit positions)
265 logmap = $02b2 ;Display/Editor: Logical line start map (4 bytes)
266 invflg = $02b6 ;Keyboard Handler: inverse flag ($00/$80)
267 tmprow = $02b8 ;Screen Editor
268 tmpcol = $02b9 ;Screen Editor
269 ; $02ba
270 scrflg = $02bb ;Display/Editor: Scroll counter
271 hold4 = $02bc ;Screen Editor
272 dretry = $02bd ;SIO: device retries (XL/XE)
273 shflok = $02be ;shift/control lock flags
274 botscr = $02bf ;number of text rows in text window
275 pcolr0 = $02c0 ;shadow for COLPM0 ($D012)
276 pcolr1 = $02c1 ;shadow for COLPM1 ($D013)
277 pcolr2 = $02c2 ;shadow for COLPM2 ($D014)
278 pcolr3 = $02c3 ;shadow for COLPM3 ($D015)
279 color0 = $02c4 ;shadow for COLPF0 ($D016)
280 color1 = $02c5 ;shadow for COLPF1 ($D017)
281 color2 = $02c6 ;shadow for COLPF2 ($D018)
282 color3 = $02c7 ;shadow for COLPF3 ($D019)
283 color4 = $02c8 ;shadow for COLBK ($D01A)
284 runadr = $02c9 ;Relocating loader: run address (XL/XE)
285 ; $02ca
286 hiused = $02cb ;Relocating loader: Next available memory location (out) (XL/XE)
287 ; $02cc
288 zhiuse = $02cd ;Relocating loader: Next available zero-page address (out) (XL/XE)
289 ; $02ce
290 gbytea = $02cf ;Relocating loader: GET BYTE address (XL/XE)
291 ; $02d0
292 loadad = $02d1 ;Relocating loader: Load address (XL/XE)
293 ; $02d2
294 zloada = $02d3 ;Relocating loader: Zero-page load address (XL/XE)
295 ; $02d4
296 dsctln = $02d5 ;Disk sector size (XL/XE)
297 krpdel = $02d9 ;Keyboard repeat delay (XL/XE)
298 keyrep = $02da ;Keyboard repeat rate (XL/XE)
299 helpfg = $02dc ;Help flag (XL/XE)
300 pbpnt = $02de ;Printer: Buffer index (XL/XE location)
301 pbufsz = $02df ;Printer: Record size (XL/XE location)
302 ramsiz = $02e4 ;ram size in pages
303 memtop = $02e5 ;highest location for programs and data
304 memlo = $02e7 ;base of application memory
305 hndlod = $02e9 ;CIO: Handler load flag (XL/XE)
306 dvstat = $02ea ;DISK: Status request buffer area (4 bytes)
307 ; $02eb
308 ; $02ec
309 ; $02ed
310 cbaudl = $02ee ;Cassette baud rate as POKEY divisor. Set to nominal ($05CC) by C: init.
311 cbaudh = $02ef ;
312 crsinh = $02f0 ;Display/Editor: cursor inhibit flag
313 keydel = $02f1 ;keyboard debounce delay (set to 3 vblanks per key)
314 ch1 = $02f2 ;last keyboard code read
315 chact = $02f3 ;shadow for CHACTL ($D401)
316 chbas = $02f4 ;shadow for CHBASE ($D409)
317 rowinc = $02f8 ;Screen Editor: row direction (XL/XE location)
318 colinc = $02f9 ;Screen Editor: col direction (XL/XE location)
319 atachr = $02fb ;Screen Editor
320 ch = $02fc ;keyboard FIFO byte
321 fildat = $02fd ;Screen Editor: fill color
322 dspflg = $02fe ;enable/disable of control codes by screen editor (E:)
323 ssflag = $02ff ;display/screen editor suspend flag
324 ddevic = $0300 ;serial bus ID
325 dunit = $0301 ;device number
326 dcomnd = $0302 ;command byte
327 dstats = $0303 ;status byte
328 dbuflo = $0304 ;buffer address lo
329 dbufhi = $0305 ;buffer address hi
330 dtimlo = $0306 ;disk timeout value
331 dbytlo = $0308 ;byte count lo
332 dbythi = $0309 ;byte count hi
333 daux1 = $030a ;sector number lo
334 daux2 = $030b ;sector number hi
335 timer1 = $030c ;SIO: baud rate determination - first timer value
336 addcor = $030e ;SIO: baud rate determination - correction value
337 casflg = $030f ;SIO: cassette I/O flag (0=normal, nonzero=cassette)
338 timer2 = $0310 ;SIO: baud rate determination - second timer value
339 temp1 = $0312 ;SIO: baud rate determination - temp
340 ; $0313
341 ptimot = $0314 ;Printer: Timeout (XL/XE location)
342 temp3 = $0315 ;SIO: baud rate determination - temp
343 timflg = $0317 ;SIO: operation timeout flag (set by countdown timer 1 IRQ)
344 stackp = $0318 ;SIO: stack pointer save
345 hatabs = $031a ;handler table
346 pupbt1 = $033d ;(XL/XE) Power-up boot flag #1 - $5C
347 pupbt2 = $033e ;(XL/XE) Power-up boot flag #2 - $93
348 pupbt3 = $033f ;(XL/XE) Power-up boot flag #3 - $25
349 ichid = $0340 ;IOCB #0 handler ID
350 icdno = $0341 ;IOCB #0 device number
351 iccmd = $0342 ;IOCB #0 command byte
352 icsta = $0343 ;IOCB #0 status
353 icbal = $0344 ;IOCB #0 buffer address lo
354 icbah = $0345 ;IOCB #0 buffer address hi
355 icptl = $0346 ;IOCB #0 PUT address lo
356 icpth = $0347 ;IOCB #0 PUT address hi
357 icbll = $0348 ;IOCB #0 buffer length/byte count lo
358 icblh = $0349 ;IOCB #0 buffer length/byte count hi
359 icax1 = $034a ;IOCB #0 auxiliary information lo
360 icax2 = $034b ;IOCB #0 auxiliary information hi
361 icax3 = $034c ;
362 icax4 = $034d ;
363 icax5 = $034e ;
364 icax6 = $034f ;
365 prnbuf = $03c0 ;printer buffer
366 ckey = $03e9 ;cassette boot key
367 basicf = $03f8 ;XL/XE: ROM BASIC flag. 0 = enabled
368 gintlk = $03fa ;XL/XE: Cartridge interlock (clone of TRIG3).
369 chlink = $03fb ;XL/XE: Relocated loader chain
370 casbuf = $03fd ;Cassette buffer (03FD-047F)
371 lbuff = $0580 ;
372 plyarg = $05e0 ;FP: Polynomial evaluation temp register
373 fpscr = $05e6 ;FP: Temp evaluation register (used by LOG/LOG10)
374
375 .endif
34
35 opt h-o+f+
36
37 .ifdef _KERNEL_816
38 opt c+
39 .endif
40
41 .if _KERNEL_XLXE
42 org $c000
43
44 ;==============================================================================
45 ; lower ROM identification block (XL/XE)
46 ;==============================================================================
47
48 C000 00 00 dta a(0)
49 C002 01 01 13 dta $01,$01,$13
50 C005 02 dta $02
51 C006 43 58 00 00 00 dta 'CX',$00,$00,$00
52 C00B 00 dta $00
53
54 C00C _KERNEL_REPORT_MODULE_MARK
Macro: _KERNEL_REPORT_MODULE_MARK [Source: source/main.xasm]
1 = C00C .def ?@_kernel_lastpt = *
Source: source/main.xasm
55
56 .ifdef _KERNEL_816
57 icl 'vbi816.s'
58 .else
59 C00C icl 'vbi.s'
Source: source/Shared/vbi.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Vertical Blank Interrupt Services
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 ; VBIExit - Vertical Blank Interrupt Exit Routine
12 ;
13 ; This is a drop-in replacement for XITVBV.
14 ;
15 = C050 VBIExit = VBIProcess.xit
16
17 ;==========================================================================
18 ; VBIProcess - Vertical Blank Processor
19 ;
20 = C00C VBIStage1 = VBIProcess.stage_1
21 = C061 VBIStage2 = VBIProcess.stage_2
22 C00C .proc VBIProcess
23 C00C stage_1:
24 ;increment real-time clock and do attract processing
25 C00C E6 14 inc rtclok+2
26 C00E D0 08 bne clock_done
27 C010 E6 4D inc atract
28 C012 E6 13 inc rtclok+1
29 C014 D0 02 bne clock_done
30 C016 E6 12 inc rtclok
31 C018 clock_done:
32
33 ;Pole Position depends on DRKMSK and COLRSH being reset from VBI as it
34 ;clears kernel vars after startup.
35 C018 A2 FE ldx #$fe ;default to no mask
36 C01A A9 00 lda #$00 ;default to no color alteration
37 C01C A4 4D ldy atract ;check attract counter
38 C01E 10 06 bpl attract_off ;skip if attract is off
39 C020 86 4D stx atract ;lock the attract counter
40 C022 A2 F6 ldx #$f6 ;set mask to dim colors
41 C024 A5 13 lda rtclok+1 ;use clock to randomize colors
42 C026 attract_off:
43 C026 86 4E stx drkmsk ;set color mask
44 C028 85 4F sta colrsh ;set color modifier
45
46 ;atract color 1 only
47 C02A 4D C5 02 eor color1
48 C02D 25 4E and drkmsk
49 C02F 8D 17 D0 sta colpf1
50
51 ;decrement timer 1 and check for underflow
52 C032 AD 18 02 lda cdtmv1 ;check low byte
53 C035 D0 08 bne timer1_lobytezero ;if non-zero, decrement and check for fire
54 C037 AD 19 02 lda cdtmv1+1 ;check high byte
55 C03A F0 10 beq timer1_done ;if clear, timer's not running
56 C03C CE 19 02 dec cdtmv1+1 ;decrement high byte
57 C03F timer1_lobytezero:
58 C03F CE 18 02 dec cdtmv1 ;decrement low byte
59 C042 D0 08 bne timer1_done ;no underflow if non-zero
60 C044 AD 19 02 lda cdtmv1+1 ;low byte is zero... check if high byte is too
61 C047 D0 03 bne timer1_done ;if it's not, we're not done yet ($xx00 > 0)
62 C049 20 56 C0 jsr timer1_dispatch ;jump through timer vector
63 C04C timer1_done:
64
65 ;check for critical operation
66 C04C A5 42 lda critic
67 C04E F0 09 beq no_critic
68 C050 xit:
69 C050 68 pla
70 C051 A8 tay
71 C052 68 pla
72 C053 AA tax
73 C054 exit_a:
74 C054 68 pla
75 C055 exit_none:
76 C055 40 rti
77
78 C056 timer1_dispatch:
79 C056 6C 26 02 jmp (cdtma1)
80
81 C059 no_critic:
82 C059 A9 04 lda #$04 ;I flag
83 C05B BA tsx
84 C05C 3D 04 01 and $0104,x ;I flag set on pushed stack?
85 C05F D0 EF bne xit ;exit if so
86
87 ;======== stage 2 processing
88
89 C061 stage_2:
90 ;re-enable interrupts
91 C061 58 cli
92
93 ;update shadow registers
94 C062 AD 31 02 8D 03 D4 mva sdlsth dlisth
95 C068 AD 30 02 8D 02 D4 mva sdlstl dlistl
96 C06E AD 2F 02 8D 00 D4 mva sdmctl dmactl
97 C074 AD F4 02 8D 09 D4 mva chbas chbase
98 C07A AD F3 02 8D 01 D4 mva chact chactl
99 C080 AD 6F 02 8D 1B D0 mva gprior prior
100
101 C086 A2 08 ldx #8
102 C088 8E 1F D0 stx consol ;sneak in speaker reset while we have an 8
103 C08B ColorLoop
104 C08B BD C0 02 lda pcolr0,x
105 C08E 45 4F eor colrsh
106 C090 25 4E and drkmsk
107 C092 9D 12 D0 sta colpm0,x
108 C095 CA dex
109 C096 10 F3 bpl ColorLoop
110
111 ;decrement timer 2 and check for underflow
112 C098 A2 03 ldx #3
113 C09A 20 47 C1 jsr VBIDecrementTimer
114 C09D D0 03 20 44 C1 sne:jsr Timer2Dispatch
115
116 ;Decrement timers 3-5 and set flags
117 ;
118 ;[OS Manual] Appendix L, page 254 says that the OS never modifies CDTMF3-5
119 ;except to set them to zero on timeout at init. This is a LIE. It also sets
120 ;the flags to $FF when they are running. It does not write the flags when
121 ;the timer is idle. Spider Quake depends on this.
122 ;
123 C0A2 A2 09 ldx #9
124 C0A4 timer_n_loop:
125 C0A4 18 clc
126 C0A5 20 47 C1 jsr VBIDecrementTimer
127 C0A8 B0 07 bcs timer_n_not_running
128 C0AA F0 02 A9 FF seq:lda #$ff
129 C0AE timer_n_not_expired:
130 C0AE 9D 25 02 sta cdtmf3-5,x
131 C0B1 timer_n_not_running:
132 C0B1 CA dex
133 C0B2 CA dex
134 C0B3 E0 05 cpx #5
135 C0B5 B0 ED bcs timer_n_loop
136
137 ;Read POKEY keyboard register and handle auto-repeat
138 C0B7 AD 0F D2 lda skstat ;get key status
139 C0BA 29 04 and #$04 ;check if key is down
140 C0BC D0 13 bne no_repeat_key ;skip if not
141 C0BE CE 2B 02 dec srtimr ;decrement repeat timer
142 C0C1 D0 13 bne no_repeat ;skip if not time to repeat yet
143 C0C3 AD 09 D2 8D FC 02 mva kbcode ch ;repeat last key
144
145 .if _KERNEL_XLXE
146 C0C9 AD DA 02 8D 2B 02 mva keyrep srtimr ;reset repeat timer
147 .else
148 mva #$06 srtimr ;reset repeat timer
149 .endif
150
151 C0CF D0 0D bne no_keydel ;skip debounce counter decrement
152
153 C0D1 no_repeat_key:
154 C0D1 A9 00 lda #0
155 C0D3 8D 2B 02 sta srtimr
156 C0D6 no_repeat:
157 ;decrement keyboard debounce counter
158 C0D6 AD F1 02 lda keydel
159 C0D9 F0 03 CE F1 02 seq:dec keydel
160 C0DE no_keydel:
161
162 ;Update controller shadows.
163 ;
164 ;The PORTA/PORTB decoding is a bit complex:
165 ;
166 ; bits 0-3 -> STICK0/4 (and no, we cannot leave junk in the high bits)
167 ; bits 4-7 -> STICK1/5
168 ; bit 2 -> PTRIG0/4
169 ; bit 3 -> PTRIG1/5
170 ; bit 6 -> PTRIG2/6
171 ; bit 7 -> PTRIG3/7
172 ;
173 ;XL/XE machines only have two joystick ports, so the results of ports 0-1
174 ;are mapped onto ports 2-3.
175 ;
176
177 .if _KERNEL_XLXE
178 C0DE AD 00 D3 lda porta
179 C0E1 AA tax
180 C0E2 29 0F and #$0f
181 C0E4 8D 78 02 sta stick0
182 C0E7 8D 7A 02 sta stick2
183 C0EA 8A txa
184 C0EB 4A lsr ;shr1
185 C0EC 4A lsr ;shr2
186 C0ED AA tax
187 C0EE 4A lsr ;shr3
188 C0EF 4A lsr ;shr4
189 C0F0 8D 79 02 sta stick1
190 C0F3 8D 7B 02 sta stick3
191 C0F6 4A lsr ;shr5
192 C0F7 4A lsr ;shr6
193 C0F8 A8 tay
194 C0F9 29 01 and #$01
195 C0FB 8D 7E 02 sta ptrig2
196 C0FE 98 tya
197 C0FF 4A lsr
198 C100 8D 7F 02 sta ptrig3
199 C103 8A txa
200 C104 29 01 and #$01
201 C106 8D 7C 02 sta ptrig0
202 C109 8A txa
203 C10A 4A lsr
204 C10B 29 01 and #$01
205 C10D 8D 7D 02 sta ptrig1
206
207 C110 A2 03 ldx #3
208 C112 pot_loop:
209 C112 BD 00 D2 lda pot0,x
210 C115 9D 70 02 sta paddl0,x
211 C118 9D 74 02 sta paddl4,x
212 C11B BD 7C 02 lda ptrig0,x
213 C11E 9D 80 02 sta ptrig4,x
214 C121 CA dex
215 C122 10 EE bpl pot_loop
216
217 C124 A2 01 ldx #1
218 C126 port_loop:
219 C126 BD 10 D0 lda trig0,x
220 C129 9D 84 02 sta strig0,x
221 C12C 9D 86 02 sta strig2,x
222 C12F CA dex
223 C130 10 F4 bpl port_loop
224
225 .else
226 ldx #7
227 pot_loop:
228 lda pot0,x
229 sta paddl0,x
230 lda #0
231 sta ptrig0,x
232 dex
233 bpl pot_loop
234
235 ldx #3
236 trig_loop:
237 lda trig0,x
238 sta strig0,x
239 dex
240 bpl trig_loop
241
242 lda porta
243 ldx #0
244 ldy #0
245 jsr do_stick_ptrigs
246 lda portb
247 ldx #4
248 ldy #2
249 jsr do_stick_ptrigs
250 .endif
251
252 ;restart pots (required for SysInfo)
253 C132 8D 0B D2 sta potgo
254
255 ;update light pen
256 C135 AD 0C D4 8D 34 02 mva penh lpenh
257 C13B AD 0D D4 8D 35 02 mva penv lpenv
258
259 C141 6C 24 02 jmp (vvblkd) ;jump through vblank deferred vector
260
261 C144 Timer2Dispatch
262 C144 6C 28 02 jmp (cdtma2)
263
264 .if !_KERNEL_XLXE
265 do_stick_ptrigs:
266 pha
267 and #$0f
268 sta stick0,y
269 pla
270 lsr
271 lsr
272 lsr
273 rol ptrig0,x
274 lsr
275 rol ptrig1,x
276 sta stick1,y
277 lsr
278 lsr
279 lsr
280 rol ptrig2,x
281 lsr
282 rol ptrig3,x
283 rts
284 .endif
285
286 .endp
287
288 ;==========================================================================
289 ; VBIDecrementTimer
290 ;
291 ; Entry:
292 ; X = timer index *2+1 (1-9)
293 ;
294 ; Exit:
295 ; C=1, Z=0, A!0 timer not running
296 ; C=0/same, Z=1, A=0 timer just expired
297 ; C=0/same, Z=0, A=? timer still running
298 ;
299 C147 .proc VBIDecrementTimer
300 ;check low byte
301 C147 BD 17 02 lda cdtmv1-1,x
302 C14A D0 0A bne lononzero
303
304 ;check high byte; set C=1/Z=1 if zero, C=0/Z=0 otherwise
305 C14C DD 18 02 cmp cdtmv1,x
306 C14F D0 02 bne lozero_hinonzero
307
308 ;both bytes are zero, so timer's not running
309 C151 8A txa
310 C152 60 rts
311
312 C153 lozero_hinonzero:
313 ;decrement high byte
314 C153 DE 18 02 dec cdtmv1,x
315
316 C156 lononzero:
317 ;decrement low byte
318 C156 DE 17 02 dec cdtmv1-1,x
319 C159 D0 03 bne still_running
320
321 ;return high byte to set Z appropriately
322 C15B BD 18 02 lda cdtmv1,x
323 C15E still_running:
324 C15E 60 rts
325 .endp
326
327 ;==========================================================================
328 ; VBISetVector - set vertical blank vector or counter
329 ;
330 ; This is a drop-in replacement for SETVBV.
331 ;
332 ; A = item to update
333 ; 1-5 timer 1-5 counter value
334 ; 6 VVBLKI
335 ; 7 VVBLKD
336 ; X = MSB
337 ; Y = LSB
338 ;
339 C15F .proc VBISetVector
340 ;A = item to update
341 ; 1-5 timer 1-5 counter value
342 ; 6 VVBLKI
343 ; 7 VVBLKD
344 ;X = MSB
345 ;Y = LSB
346 ;
347 ;NOTE:
348 ;The Atari OS Manual says that DLIs will be disabled after SETVBV is called.
349 ;This is a lie -- neither the OS-B nor XL kernels do this, and the Bewesoft
350 ;8-players demo depends on it being left enabled.
351 ;
352 ;IRQ mask state must be saved across this proc. DOSDISKA.ATR breaks if IRQs
353 ;are unmasked.
354
355 C15F 0A asl
356 C160 8D 2D 02 sta intemp
357 C163 08 php
358 C164 78 sei
359 C165 98 tya
360 C166 AC 2D 02 ldy intemp
361
362 ;We're relying on a rather tight window here. We can't touch NMIEN, so we have
363 ;to wing it with DLIs enabled. Problem is, in certain conditions we can be under
364 ;very tight timing constraints. In order to do this safely we have to finish
365 ;before a DLI can execute. The worst case is a wide mode 2 line at the end of
366 ;a vertically scrolled region with P/M graphics enabled and an LMS on the next
367 ;mode line. In that case we only have 7 cycles before we hit the P/M graphics
368 ;and another two cycles after that until the DLI fires. The exact cycle timing
369 ;looks like this:
370 ;
371 ;* inc wsync
372 ;ANTIC halts CPU until cycle 105
373 ;105 playfield DMA
374 ;106 refresh DMA
375 ;107 sta abs,y (1/5)
376 ;108 sta abs,y (2/5)
377 ;109 sta abs,y (3/5)
378 ;110 sta abs,y (4/5)
379 ;111 sta abs,y (5/5)
380 ;112 txa (1/2)
381 ;113 txa (2/2)
382 ;0 missiles
383 ;1 display list
384 ;2 player 0
385 ;3 player 1
386 ;4 player 2
387 ;5 player 3
388 ;6 display list address low
389 ;7 display list address high
390 ;8 sta abs,y (1/5)
391 ;9 sta abs,y (2/5)
392 ;10 sta abs,y (3/5)
393 ;11 sta abs,y (4/5)
394 ;12 sta abs,y (5/5)
395 ;
396 ;We rely on the 6502 not being able to service interrupts until the end of an
397 ;instruction for this to work. The INC WSYNC is necessary to combat the case
398 ;where the NMI is triggered across the WSYNC wait; without it, the VBI could
399 ;fire immediately after the first STA.
400
401 C169 EE 0A D4 inc wsync
402 C16C 99 16 02 sta cdtmv1-2,y
403 C16F 8A txa
404 C170 99 17 02 sta cdtmv1-1,y
405 C173 28 plp
406 C174 60 rts
407 .endp
60 .endif
61
62 C175 _KERNEL_REPORT_MODULE_SIZE 'VBI routines', 0
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'VBI routines'
1 $C175 -> $0169($0000) VBI routines
3 = C175 .def ?@_kernel_lastpt = *
Source: source/main.xasm
63
64 .ifdef _KERNEL_816
65 icl 'interrupt816.s'
66 .else
67 C175 icl 'interrupt.s'
Source: source/Shared/interrupt.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Interrupt Handlers
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 ; Dispatched from INTINV. Used by SpartaDOS X.
12 ;
13 C175 .proc IntInitInterrupts
14 C175 A9 40 8D 0E D4 mva #$40 nmien
15
16 .if _KERNEL_XLXE
17 ;Required by XEGS carts to run since they have a clone of the XL/XE
18 ;OS in them.
19 C17A AD 13 D0 8D FA 03 mva trig3 gintlk
20 .endif
21
22 C180 60 rts
23 .endp
24
25 ;==========================================================================
26 C181 .proc IntDispatchNMI
27 C181 2C 0F D4 bit nmist ;check nmi status
28 C184 10 03 bpl not_dli ;skip if not a DLI
29 C186 6C 00 02 jmp (vdslst) ;jump to display list vector
30
31 .if !_KERNEL_XLXE
32 is_system_reset:
33 jmp warmsv
34 .endif
35
36 C189 not_dli:
37 C189 48 pha
38
39 .if _KERNEL_XLXE
40 ;Only XL/XE OSes cleared the decimal bit.
41 C18A D8 cld
42 .else
43 ;The stock OS treats 'not RNMI' as VBI. We'd best follow its example.
44 lda #$20
45 bit nmist
46 bne is_system_reset
47 .endif
48
49 C18B 8A txa
50 C18C 48 pha
51 C18D 98 tya
52 C18E 48 pha
53 C18F 8D 0F D4 sta nmires ;reset VBI interrupt
54 C192 6C 22 02 jmp (vvblki) ;jump through vblank immediate vector
55 .endp
56
57 C195 .proc IntDispatchIRQ
58 .if _KERNEL_XLXE
59 C195 D8 cld
60 .endif
61 C196 6C 16 02 jmp (vimirq)
62 .endp
63
64 ;==============================================================================
65 = C054 IntExitHandler_A = VBIProcess.exit_a
66 = C055 IntExitHandler_None = VBIProcess.exit_none
68 .endif
69
70 C199 _KERNEL_REPORT_MODULE_SIZE 'Base interrupt routines', 0
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'Base interrupt routines'
1 $C199 -> $0024($0000) Base interrupt routines
3 = C199 .def ?@_kernel_lastpt = *
Source: source/main.xasm
71
72 .ifdef _KERNEL_816
73 icl 'irq816.s'
74 .else
75 C199 icl 'irq.s'
Source: source/Shared/irq.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - IRQ routines
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 ; _KERNEL_FAST_IRQ
12 ;
13 ; If set, expands the IRQ module slightly to save 12 cycles when ack'ing
14 ; POKEY IRQs. This is still faster than the stock XL/XE OS. If cleared,
15 ; an additional subroutine call is used to reduce code size.
16 ;
17 .ifndef _KERNEL_FAST_IRQ
18 _KERNEL_FAST_IRQ = 0
19 .endif
20
21 ;==========================================================================
22 .if _KERNEL_FAST_IRQ
23 _ACK_IRQ .macro
24 sta irqen
25 lda pokmsk
26 sta irqen
27 .endm
28 .else
29 _ACK_IRQ .macro
30 jsr IrqAcknowledge
31 .endm
32 .endif
33
34 ;==========================================================================
35 ; The canonical IRQ priority order for the XL/XE is:
36 ; - Serial input ready ($20)
37 ; - PBI devices
38 ; - Serial output ready ($10)
39 ; - Serial output complete ($08)
40 ; - Timer 1 ($01)
41 ; - Timer 2 ($02)
42 ; - Timer 4 ($04)
43 ; - Keyboard ($80)
44 ; - Break ($40)
45 ; - PIA proceed
46 ; - PIA interrupt
47 ; - BRK instruction
48 ;
49 = C1D1 IRQHandler = _IRQHandler._entry
50 C199 .proc _IRQHandler
51 .if _KERNEL_PBI_SUPPORT
52 C199 check_pbi:
53 ;check if a device interrupt is active
54 C199 2D FF D1 and $d1ff
55 C19C F0 4D beq no_pbi_interrupt
56
57 ;save X
58 C19E 8D 8C 02 sta jveck
59 C1A1 8A txa
60 C1A2 48 pha
61
62 ;jump through PBI interrupt vector
63 C1A3 AD 8C 02 lda jveck
64 C1A6 6C 38 02 jmp (vpirq)
65 .endif
66
67 C1A9 dispatch_serout:
68 C1A9 A9 EF lda #$ef
69 C1AB _ACK_IRQ
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
1 C1AB 20 45 C2 jsr IrqAcknowledge
Source: source/Shared/irq.s
70 C1AE 6C 0C 02 jmp (vseror)
71
72 C1B1 check_seroc:
73 C1B1 2C 0E D2 bit irqst
74 C1B4 D0 41 bne not_seroc
75 C1B6 dispatch_seroc:
76 C1B6 6C 0E 02 jmp (vseroc)
77
78 C1B9 dispatch_timer1:
79 C1B9 A9 FE lda #$fe
80 C1BB _ACK_IRQ
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
1 C1BB 20 45 C2 jsr IrqAcknowledge
Source: source/Shared/irq.s
81 C1BE 6C 10 02 jmp (vtimr1)
82
83 C1C1 dispatch_timer2:
84 C1C1 A9 FD lda #$fd
85 C1C3 _ACK_IRQ
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
1 C1C3 20 45 C2 jsr IrqAcknowledge
Source: source/Shared/irq.s
86 C1C6 6C 12 02 jmp (vtimr2)
87
88 C1C9 dispatch_timer4:
89 C1C9 A9 FB lda #$fb
90 C1CB _ACK_IRQ
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
1 C1CB 20 45 C2 jsr IrqAcknowledge
Source: source/Shared/irq.s
91 C1CE 6C 14 02 jmp (vtimr4)
92
93 C1D1 _entry:
94 C1D1 48 pha
95
96 ;check for serial input ready IRQ
97 C1D2 A9 20 lda #$20
98 C1D4 2C 0E D2 bit irqst
99 C1D7 D0 0D bne not_serin
100 C1D9 A9 DF lda #$df
101 C1DB 8D 0E D2 sta irqen
102 C1DE A5 10 lda pokmsk
103 C1E0 8D 0E D2 sta irqen
104 C1E3 6C 0A 02 jmp (vserin)
105 C1E6 not_serin:
106
107 .if _KERNEL_PBI_SUPPORT
108 ;check for PBI devices requiring interrupt handling
109 C1E6 AD 49 02 lda pdmsk
110 C1E9 D0 AE bne check_pbi
111 C1EB no_pbi_interrupt:
112 .endif
113
114 ;check for serial output ready IRQ
115 C1EB A9 10 lda #$10
116 C1ED 2C 0E D2 bit irqst
117 C1F0 F0 B7 beq dispatch_serout
118
119 ;check for serial output complete (not a latch, so must mask)
120 C1F2 4A lsr
121 C1F3 24 10 bit pokmsk
122 C1F5 D0 BA bne check_seroc
123 C1F7 not_seroc:
124
125 C1F7 AD 0E D2 lda irqst
126 C1FA 4A lsr
127 C1FB 90 BC bcc dispatch_timer1
128 C1FD 4A lsr
129 C1FE 90 C1 bcc dispatch_timer2
130 C200 4A lsr
131 C201 90 C6 bcc dispatch_timer4
132 C203 2C 0E D2 bit irqst
133 C206 50 21 bvc dispatch_keyboard
134 C208 10 27 bpl dispatch_break
135
136 ;check for serial bus proceed line
137 C20A 2C 02 D3 bit pactl
138 C20D 30 2A bmi dispatch_pia_irqa
139
140 ;check for serial bus interrupt line
141 C20F 2C 03 D3 bit pbctl
142 C212 30 2B bmi dispatch_pia_irqb
143
144 ;check for break instruction
145 ;
146 ;we used to use TSX here, but this takes too many insns to
147 ;handle stack wrapping properly
148 C214 68 pla
149 C215 8D 8C 02 sta jveck
150 C218 68 pla
151 C219 48 pha
152 C21A 29 10 and #$10
153 C21C F0 07 beq not_brk
154 C21E AD 8C 02 lda jveck
155 C221 48 pha
156 C222 6C 06 02 jmp (vbreak)
157 C225 not_brk:
158 C225 AD 8C 02 lda jveck
159 C228 40 rti
160
161
162 C229 dispatch_keyboard:
163 C229 A9 BF lda #$bf
164 C22B _ACK_IRQ
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
1 C22B 20 45 C2 jsr IrqAcknowledge
Source: source/Shared/irq.s
165 C22E 6C 08 02 jmp (vkeybd)
166
167 C231 dispatch_break:
168 C231 A9 7F lda #$7f
169 C233 _ACK_IRQ
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
1 C233 20 45 C2 jsr IrqAcknowledge
Source: source/Shared/irq.s
170 C236 6C 36 02 jmp (brkky)
171
172 C239 dispatch_pia_irqa:
173 ;clear serial bus proceed interrupt
174 C239 AD 00 D3 lda porta
175 C23C 6C 02 02 jmp (vprced)
176
177 C23F dispatch_pia_irqb:
178 ;clear serial bus interrupt interrupt
179 C23F AD 01 D3 lda portb
180 C242 6C 04 02 jmp (vinter)
181
182 .endp
183
184 ;==========================================================================
185 .if !_KERNEL_FAST_IRQ
186 C245 .proc IrqAcknowledge
187 C245 8D 0E D2 sta irqen
188 C248 A5 10 lda pokmsk
189 C24A 8D 0E D2 sta irqen
190 C24D 60 rts
191 .endp
192 .endif
76 .endif
77
78 C24E _KERNEL_REPORT_MODULE_SIZE 'IRQ routines', 0
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'IRQ routines'
1 $C24E -> $00B5($0000) IRQ routines
3 = C24E .def ?@_kernel_lastpt = *
Source: source/main.xasm
79
80 C24E icl 'pbi.s'
Source: source/Shared/pbi.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Parallel Bus Interface routines
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 .if _KERNEL_PBI_SUPPORT
11
12 C24E icl 'cio.inc'
Source: source/Shared/cio.inc
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Character Input/Output Definitions
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 .ifndef f_CIO_INC
11 .def f_CIO_INC
12
13 CIOStatBreak = $80 ;break key abort
14 CIOStatIOCBInUse = $81 ;IOCB in use
15 CIOStatUnkDevice = $82 ;unknown device
16 CIOStatWriteOnly = $83 ;opened for write only
17 CIOStatInvalidCmd = $84 ;invalid command
18 CIOStatNotOpen = $85 ;device or file not open
19 CIOStatInvalidIOCB = $86 ;invalid IOCB number
20 CIOStatReadOnly = $87 ;opened for read only
21 CIOStatEndOfFile = $88 ;end of file reached
22 CIOStatTruncRecord = $89 ;record truncated
23 CIOStatTimeout = $8A ;device timeout
24 CIOStatNAK = $8B ;device NAK
25 CIOStatSerFrameErr = $8C ;serial bus framing error
26 CIOStatCursorRange = $8D ;cursor out of range
27 CIOStatSerOverrun = $8E ;serial frame overrun error
28 CIOStatSerChecksum = $8F ;serial checksum error
29 CIOStatDeviceDone = $90 ;device done error
30 CIOStatBadScrnMode = $91 ;bad screen mode
31 CIOStatNotSupported = $92 ;function not supported by handler
32 CIOStatOutOfMemory = $93 ;not enough memory
33 CIOStatDriveNumErr = $A0 ;disk drive # error
34 CIOStatTooManyFiles = $A1 ;too many open disk files
35 CIOStatDiskFull = $A2 ;disk full
36 CIOStatFatalDiskIO = $A3 ;fatal disk I/O error
37 CIOStatFileNumDiff = $A4 ;internal file # mismatch
38 CIOStatFileNameErr = $A5 ;filename error
39 CIOStatPointDLen = $A6 ;point data length error
40 CIOStatFileLocked = $A7 ;file locked
41 CIOStatInvDiskCmd = $A8 ;invalid command for disk
42 CIOStatDirFull = $A9 ;directory full (64 files)
43 CIOStatFileNotFound = $AA ;file not found
44 CIOStatInvPoint = $AB ;invalid point
45
46 CIOCmdOpen = $03
47 CIOCmdGetRecord = $05
48 CIOCmdGetChars = $07
49 CIOCmdPutRecord = $09
50 ; $0A ;PUT CHARS alias (required by K-Razy Shoot Out)
51 CIOCmdPutChars = $0B
52 CIOCmdClose = $0C
53 CIOCmdGetStatus = $0D
54 CIOCmdSpecial = $0E ;$0E and up is escape
55
56 .endif
13
14 ;==========================================================================
15 ; PBI device ROM entry points:
16 ; $D800 Checksum low (unused)
17 ; $D801 Checksum high (unused)
18 ; $D802 Revision (unused)
19 ; $D803 ID byte; must be $80.
20 ; $D804 Device type (unused)
21 ; $D805 JMP sio_vector
22 ; $D806 (cont.)
23 ; $D807 (cont.)
24 ; $D808 JMP irq_vector
25 ; $D809 (cont.)
26 ; $D80A (cont.)
27 ; $D80B ID byte; must be $91
28 ; $D80C Device name (unused)
29 ; $D80D CIO open vector - 1
30 ; $D80E (cont.)
31 ; $D80F CIO close vector - 1
32 ; $D810 (cont.)
33 ; $D811 CIO get byte vector - 1
34 ; $D812 (cont.)
35 ; $D813 CIO put byte vector - 1
36 ; $D814 (cont.)
37 ; $D815 CIO get status vector - 1
38 ; $D816 (cont.)
39 ; $D817 CIO special vector - 1
40 ; $D818 (cont.)
41 ; $D819 JMP init_vector
42 ; $D81A (cont.)
43 ; $D81B (cont.)
44 ;
45
46 ;==========================================================================
47 ; Scan for PBI devices.
48 ;
49 ; The details:
50 ; - $D1FF is the PBI device select register; 1 selects a device.
51 ; - A selected device, if it exists, maps its ROM into $D800-DFFF, on
52 ; top of the math pack.
53 ; - ID bytes are checked to ensure that a device ROM is actually present.
54 ; (This means that the math pack must not match those bytes!)
55 ; - SHPDVS is the device selection shadow variable. It must match the
56 ; value written to $D1FF whenever the PBI ROM is invoked so that the
57 ; PBI device code can detect its ID.
58 ; - PDVMSK is the device enable mask and is used by SIO to call into
59 ; PBI devices. Each bit in this mask indicates that a PBI device is
60 ; available to possibly service requests. It is NOT set by this
61 ; routine, but by the PBI device init code.
62 ;
63 C24E .proc PBIScan
64 ;set up interrupt handler
65 C24E A9 7E 8D 38 02 A9 + mwa #PBIHandleIRQ vpirq
66
67 ;begin scan
68 C258 A9 01 lda #$01
69 C25A loop:
70 ;select next device
71 C25A 8D 48 02 sta shpdvs
72 C25D 8D FF D1 sta $d1ff
73
74 ;check ID bytes
75 C260 AC 03 D8 ldy $d803
76 C263 C0 80 cpy #$80
77 C265 D0 0A bne invalid
78
79 C267 AC 0B D8 ldy $d80b
80 C26A C0 91 cpy #$91
81 C26C D0 03 bne invalid
82
83 ;init PBI device
84 C26E 20 19 D8 jsr $d819
85 C271 invalid:
86
87 ;next device
88 C271 AD 48 02 lda shpdvs
89 C274 0A asl
90 C275 D0 E3 bne loop
91
92 ;deselect last device
93 C277 8D 48 02 sta shpdvs
94 C27A 8D FF D1 sta $d1ff
95 C27D 60 rts
96 .endp
97
98 ;==========================================================================
99 ; Entry:
100 ; A, X saved on stack
101 ; A = active PBI IRQ mask ($D1FF AND PDMSK)
102 ;
103 ; Exit:
104 ; A, X restored
105 ; Interrupt exit
106 ;
107 C27E .proc PBIHandleIRQ
108 ;isolate lowest bit (ID of highest priority device)
109 C27E 8D 8C 02 sta jveck
110 C281 49 FF eor #$ff
111 C283 18 clc
112 C284 69 01 adc #1
113 C286 2D 8C 02 and jveck
114
115 ;save off the current device mask and select interrupting device
116 C289 AE 48 02 ldx shpdvs
117 C28C 8D 48 02 sta shpdvs
118 C28F 8D FF D1 sta $d1ff
119 C292 8A txa
120 C293 48 pha
121
122 ;call through interrupt vector
123 C294 20 08 D8 jsr $d808
124
125 ;restore previously (un)selected device
126 C297 68 pla
127 C298 8D 48 02 sta shpdvs
128 C29B 8D FF D1 sta $d1ff
129
130 ;restore X, A and exit
131 C29E 68 pla
132 C29F AA tax
133 C2A0 68 pla
134 C2A1 40 rti
135 .endp
136
137 ;==========================================================================
138 C2A2 .proc PBIAttemptSIO
139 C2A2 AD 47 02 lda pdvmsk
140 C2A5 D0 08 bne begin_scan
141 C2A7 fail:
142 C2A7 8D 48 02 sta shpdvs
143 C2AA 8D FF D1 sta $d1ff
144 C2AD 18 clc
145 C2AE 60 rts
146
147 C2AF begin_scan:
148 C2AF A9 00 lda #0
149 C2B1 38 sec
150 C2B2 loop:
151 ;advance to next device bit
152 C2B2 2A rol
153
154 ;check if we've scanned all 8 IDs
155 C2B3 B0 F2 bcs fail
156
157 ;check if device exists
158 C2B5 2C 47 02 bit pdvmsk
159
160 ;keep scanning if not
161 C2B8 F0 F8 beq loop
162
163 ;select the device
164 C2BA 8D 48 02 sta shpdvs
165 C2BD 8D FF D1 sta $d1ff
166
167 ;attempt I/O
168 C2C0 48 pha
169 C2C1 20 05 D8 jsr $d805
170 C2C4 68 pla
171
172 ;loop back if PBI handler didn't claim the I/O
173 C2C5 90 EB bcc loop
174
175 ;deselect last device
176 C2C7 A9 00 lda #0
177 C2C9 8D 48 02 sta shpdvs
178 C2CC 8D FF D1 sta $d1ff
179
180 ;all done
181 C2CF 60 rts
182 .endp
183
184 ;==========================================================================
185 C2D0 .proc PBIGenericDeviceOpen
186 C2D0 A0 00 ldy #0
187 C2D2 10 0A bpl PBIGenericDevicePutByte.vector_entry
188 .endp
189
190 ;==========================================================================
191 C2D4 .proc PBIGenericDeviceClose
192 C2D4 A0 02 ldy #2
193 C2D6 10 06 bpl PBIGenericDevicePutByte.vector_entry
194 .endp
195
196 ;==========================================================================
197 C2D8 .proc PBIGenericDeviceGetByte
198 C2D8 A0 04 ldy #4
199 C2DA 10 02 bpl PBIGenericDevicePutByte.vector_entry
200 .endp
201
202 ;==========================================================================
203 C2DC .proc PBIGenericDevicePutByte
204 C2DC A0 06 ldy #6
205 C2DE vector_entry:
206 C2DE 8C 4A 02 sty reladr
207 C2E1 8D 4B 02 sta reladr+1
208 C2E4 A9 00 lda #0
209 C2E6 38 sec
210 C2E7 loop:
211 ;advance to next device bit
212 C2E7 2A rol
213
214 ;check if we've scanned all 8 IDs
215 C2E8 B0 1B bcs fail
216
217 ;check if device exists and keep scanning if not
218 C2EA 2C 47 02 bit pdvmsk
219 C2ED F0 F8 beq loop
220
221 ;select the device -- note that the write to SHPDVS *MUST* come
222 ;first, in case a PBI IRQ happens, since we do *NOT* have IRQs
223 ;masked here!
224 C2EF 8D 48 02 sta shpdvs
225 C2F2 8D FF D1 sta $d1ff
226
227 ;attempt I/O
228 C2F5 A5 2F lda ciochr
229 C2F7 20 09 C3 jsr dispatch
230
231 ;loop back if PBI handler didn't claim the I/O
232 C2FA 90 EB bcc loop
233
234 ;all done
235 C2FC done:
236 C2FC A2 00 ldx #0
237 C2FE 8E 48 02 stx shpdvs
238 C301 8E FF D1 stx $d1ff
239 C304 60 rts
240
241 C305 fail:
242 C305 A0 82 ldy #CIOStatUnkDevice
243 C307 D0 F3 bne done
244
245 C309 dispatch:
246 C309 AC 4A 02 ldy reladr
247 C30C B9 0E D8 lda $d80e,y
248 C30F 48 pha
249 C310 B9 0D D8 lda $d80d,y
250 C313 48 pha
251 C314 AD 4B 02 lda reladr+1
252 C317 A0 92 ldy #CIOStatNotSupported
253 C319 60 rts
254
255 .endp
256
257 ;==========================================================================
258 C31A .proc PBIGenericDeviceGetStatus
259 C31A A0 08 ldy #8
260 C31C 10 C0 bpl PBIGenericDevicePutByte.vector_entry
261 .endp
262
263 ;==========================================================================
264 C31E .proc PBIGenericDeviceSpecial
265 C31E A0 0A ldy #10
266 C320 10 BC bpl PBIGenericDevicePutByte.vector_entry
267 .endp
268
269 ;==========================================================================
270 .macro PBI_VECTOR_TABLE
271 dta a(PBIGenericDeviceOpen-1)
272 dta a(PBIGenericDeviceClose-1)
273 dta a(PBIGenericDeviceGetByte-1)
274 dta a(PBIGenericDevicePutByte-1)
275 dta a(PBIGenericDeviceGetStatus-1)
276 dta a(PBIGenericDeviceSpecial-1)
277 .endm
278
279 .endif
81 C322 _KERNEL_REPORT_MODULE_SIZE 'PBI routines', 0
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'PBI routines'
1 $C322 -> $00D4($0000) PBI routines
3 = C322 .def ?@_kernel_lastpt = *
Source: source/main.xasm
82 C322 icl 'phandler.s'
Source: source/Shared/phandler.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Peripheral Handler routines
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 ; Add handler to HATABS.
12 ;
13 ; Input:
14 ; X Name of device
15 ; A:Y CIO handler table address
16 ;
17 ; Returns:
18 ; N=1 HATABS is full.
19 ; C=0 Handler added successfully.
20 ; C=1 Handler already exists; X points to address entry
21 ; A:Y preserved (required by SDX 4.43rc)
22 ;
23 C322 .proc PHAddHandler
24 C322 48 pha
25 C323 98 tya
26 C324 48 pha
27 C325 8A txa
28 C326 A2 21 ldx #33
29 C328 search_loop:
30 C328 DD 1A 03 cmp hatabs,x
31 C32B F0 17 beq found_existing
32 C32D CA dex
33 C32E CA dex
34 C32F CA dex
35 C330 10 F6 bpl search_loop
36
37 C332 insert_loop:
38 C332 E8 inx
39 C333 E8 inx
40 C334 E8 inx
41 C335 BC 1A 03 ldy hatabs,x
42 C338 F0 10 beq found_empty
43 C33A E0 24 cpx #36
44 C33C D0 F4 bne insert_loop
45
46 ;oops... table is full!
47 C33E 68 pla
48 C33F 68 pla
49 C340 A9 FF lda #$ff
50 C342 38 sec
51 C343 60 rts
52
53 C344 found_existing:
54 C344 68 pla
55 C345 A8 tay
56 C346 68 pla
57 C347 E8 inx ;X=address offset, N=0 (not full)
58 C348 38 sec ;C=1 (already exists)
59 C349 60 rts
60
61 C34A found_empty:
62 C34A 9D 1A 03 sta hatabs,x
63 C34D 68 pla
64 C34E 9D 1B 03 sta hatabs+1,x
65 C351 68 pla
66 C352 9D 1C 03 sta hatabs+2,x
67 C355 0A asl ;N=0 (not full)
68 C356 18 clc ;C=0 (added successfully)
69 C357 60 rts
70 .endp
71
72 ;==========================================================================
73 ; Remove peripheral handler.
74 ;
75 ; Entry:
76 ; A:Y Address of handler to remove
77 ;
78 ; Exit:
79 ; C=0 Removal was successful
80 ; C=1 Removal failed (not found, broken chain or handler size was
81 ; non-zero)
82 ;
83 ; This routine unlinks a peripheral handler from the CHLINK chain. It fails
84 ; if the handler size in the handler table is non-zero, which means that it
85 ; was loaded on power-up.
86 ;
87 ; Note that this routine does NOT remove any handler entries in HATABS.
88 ;
89 C358 .proc PHRemoveHandler
90 ;stash handler address
91 C358 8C 4A 02 sty reladr
92 C35B 8D 4B 02 sta reladr+1
93
94 ;load "chain head" by pretending the chain address is in a handler
95 ;entry
96 C35E A2 E9 ldx #<(chlink-$12)
97 C360 A9 03 lda #>(chlink-$12)
98
99 C362 search_loop:
100 ;check if we're at the end
101 C362 A8 tay
102 C363 D0 04 bne not_end
103 C365 E0 00 cpx #0
104 C367 F0 23 beq epic_fail
105
106 C369 not_end:
107 ;save off the prev pointer
108 C369 86 36 stx ltemp
109 C36B 85 37 sta ltemp+1
110
111 ;load the next pointer
112 C36D A0 12 ldy #$12
113 C36F B1 36 lda (ltemp),y
114 C371 AA tax
115 C372 C8 iny
116 C373 B1 36 lda (ltemp),y
117 C375 CD 4B 02 cmp reladr+1
118 C378 D0 E8 bne search_loop
119 C37A EC 4A 02 cpx reladr
120 C37D D0 E3 bne search_loop
121
122 ;we've found it -- move it into a pointer var
123 C37F 86 4A stx zchain
124 C381 85 4B sta zchain+1
125
126 ;check if the handler size is zero
127 C383 A0 10 ldy #$10
128 C385 B1 4A lda (zchain),y
129 C387 C8 iny
130 C388 11 4A ora (zchain),y
131 C38A F0 02 beq size_ok
132
133 ;whoops... we can't remove this handler.
134 C38C epic_fail:
135 C38C 38 sec
136 C38D 60 rts
137
138 C38E size_ok:
139 ;unlink the handler
140 C38E A0 12 ldy #$12
141 C390 B1 4A lda (zchain),y ;load low byte
142 C392 AA tax ;stash it
143 C393 C8 iny
144 C394 B1 4A lda (zchain),y ;load high byte
145 C396 91 36 sta (ltemp),y ;prev->link_hi = next->link_hi
146 C398 88 dey
147 C399 8A txa
148 C39A 91 36 sta (ltemp),y ;prev->link_lo = next->link_lo
149
150 ;all done
151 C39C 18 clc
152 C39D 60 rts
153 .endp
154
155
156 ;==========================================================================
157 ; Init peripheral handler.
158 ;
159 ; Entry:
160 ; A:Y Address of handler table
161 ; C Set if MEMLO should be adjusted, cleared otherwise
162 ;
163 ; Exit:
164 ; C Cleared on success, set on failure
165 ;
166 ; Modified:
167 ; DVSTAT+2, DVSTAT+3
168 ;
169 ; See also: Sweet 16 OS Supplement part 3, Handler Loader
170 ;
171 C39E .proc PHInitHandler
172 ;save off the table pointer; we use DVSTAT+2/3 per the Sweet16 spec
173 C39E 8C EC 02 sty dvstat+2
174 C3A1 8D ED 02 sta dvstat+3
175
176 ;save off MEMLO adjust flag
177 C3A4 08 php
178
179 ;move chain to zero page pointer
180 C3A5 A2 E9 ldx #<(chlink-$12)
181 C3A7 A9 03 lda #>(chlink-$11)
182
183 ;find zero link
184 C3A9 end_search_loop:
185 ;move to next link
186 C3A9 86 4A stx zchain
187 C3AB 85 4B sta zchain+1
188
189 ;load low byte
190 C3AD A0 12 ldy #$12
191 C3AF B1 4A lda (zchain),y
192 C3B1 AA tax
193 C3B2 C8 iny
194
195 ;load high byte and check if it is zero
196 C3B3 B1 4A lda (zchain),y
197 C3B5 D0 F2 bne end_search_loop
198
199 ;check if low byte is zero too
200 C3B7 E0 00 cpx #0
201 C3B9 D0 EE bne end_search_loop
202
203 ;alright, we've found the end of the chain -- link in the table
204 C3BB AD ED 02 lda dvstat+3
205 C3BE 91 4A sta (zchain),y
206 C3C0 AA tax
207 C3C1 88 dey
208 C3C2 AD EC 02 lda dvstat+2
209 C3C5 91 4A sta (zchain),y
210
211 ;switch to the new link
212 C3C7 86 4B stx zchain+1
213 C3C9 85 4A sta zchain
214
215 ;zero the forward pointer
216 C3CB A0 13 ldy #$13
217 C3CD A9 00 lda #0
218 C3CF 91 4A sta (zchain),y
219 C3D1 88 dey
220 C3D2 91 4A sta (zchain),y
221
222 ;jump to handler init
223 C3D4 20 20 C4 jsr PHCallHandlerInit
224 C3D7 90 0A bcc init_ok
225
226 ;remove handler and return with error (C=1)
227 C3D9 A5 4A lda zchain
228 C3DB A4 4B ldy zchain+1
229 C3DD 20 58 C3 jsr PHRemoveHandler
230 C3E0 28 plp
231 C3E1 38 sec
232 C3E2 60 rts
233
234 C3E3 init_ok:
235 ;retrieve the MEMLO adjust flag
236 C3E3 28 plp
237
238 ;zero out the handler size if we aren't adjusting MEMLO
239 C3E4 B0 0A bcs adjust_memlo
240
241 C3E6 A0 10 ldy #$10
242 C3E8 A9 00 lda #0
243 C3EA AA tax
244 C3EB 91 4A sta (zchain),y
245 C3ED C8 iny
246 C3EE 91 4A sta (zchain),y
247
248 C3F0 adjust_memlo:
249 C3F0 20 09 C4 jsr PHAdjustMemlo
250
251 ;zero checksum
252 C3F3 A0 0F ldy #$0f
253 C3F5 A9 00 lda #0
254 C3F7 91 4A sta (zchain),y
255
256 ;compute checksum
257 C3F9 A0 11 ldy #$11
258 C3FB 18 clc
259 C3FC checksum_loop:
260 C3FC 71 4A adc (zchain),y
261 C3FE 88 dey
262 C3FF 10 FB bpl checksum_loop
263 C401 69 00 adc #0
264
265 ;store checksum
266 C403 A0 0F ldy #$0f
267 C405 91 4A sta (zchain),y
268
269 ;all done - return success
270 C407 18 clc
271 C408 60 rts
272 .endp
273
274 ;==========================================================================
275 C409 .proc PHAdjustMemlo
276 ;load handler size
277 C409 A0 11 ldy #$11
278 C40B B1 4A lda (zchain),y
279 C40D AA tax
280 C40E 88 dey
281 C40F B1 4A lda (zchain),y
282
283 ;adjust MEMLO by handler size
284 C411 18 clc
285 C412 6D E7 02 adc memlo
286 C415 8D E7 02 sta memlo
287 C418 8A txa
288 C419 6D E8 02 adc memlo+1
289 C41C 8D E8 02 sta memlo+1
290 C41F 60 rts
291 .endp
292
293 ;==========================================================================
294 ; Initializes a single handler pointed to by ZCHAIN.
295 ;
296 C420 .proc PHCallHandlerInit
297 C420 A5 4A lda zchain
298 C422 18 clc
299 C423 69 0B adc #$0b
300 C425 AA tax
301 C426 A5 4B lda zchain+1
302 C428 69 00 adc #0
303 C42A 48 pha
304 C42B 8A txa
305 C42C 48 pha
306 C42D 60 rts
307 .endp
308
309 ;==========================================================================
310 ; Reinitialize all handlers in the handler chain.
311 ;
312 C42E .proc PHReinitHandlers
313 ;move chain to zero page pointer
314 C42E AE FB 03 ldx chlink
315 C431 AD FC 03 lda chlink+1
316
317 ;find zero link
318 C434 init_loop:
319 ;move to next link
320 C434 86 4A stx zchain
321 C436 85 4B sta zchain+1
322 C438 05 4A ora zchain
323 C43A F0 2D beq init_done
324
325 ;recompute checksum (except for checksum byte)
326 C43C A0 11 ldy #$11
327 C43E 18 clc
328 C43F B1 4A 88 lda (zchain),y-
329 C442 71 4A 88 adc (zchain),y-
330 C445 88 dey
331 C446 71 4A 88 10 FB adc:rpl (zchain),y-
332 C44B 69 00 adc #0
333
334 ;check if the checksum matches
335 C44D A0 0F ldy #$0f
336 C44F D1 4A cmp (zchain),y
337 C451 D0 16 bne init_done
338
339 ;reinitialize the handler
340 C453 20 20 C4 jsr PHCallHandlerInit
341 C456 B0 11 bcs init_done
342
343 ;adjust MEMLO
344 C458 20 09 C4 jsr PHAdjustMemlo
345
346 ;check for a next link
347 C45B A0 13 ldy #$13
348 C45D B1 4A lda (zchain),y
349 C45F AA tax
350 C460 C8 iny
351 C461 B1 4A lda (zchain),y
352 C463 D0 CF bne init_loop
353
354 ;load high byte and check if it is zero
355 C465 E0 00 cpx #0
356 C467 D0 CB bne init_loop
357
358 C469 init_done:
359 C469 60 rts
360 .endp
361
362 ;==========================================================================
363 ; Startup poll for peripheral handlers.
364 ;
365 ; The protocol for initing handlers from the SIO bus is as follows:
366 ;
367 ; 1. Issue type 3 poll reset (4F/40/4F/4F).
368 ; 2. Issue type 3 poll (4F/40/00/00), reading 4 bytes.
369 ; 2a. If this poll fails with a timeout, we're done.
370 ; 2b. If the poll fails for any other reason, issue a type 3 null poll
371 ; (4F/40/4E/4E) and go back to step 2.
372 ; 3. Compare the size in DVSTAT+0/1 against the amount of memory between
373 ; MEMTOP and MEMLO. If there isn't enough, issue a type 3 null poll
374 ; and go to step 2.
375 ; 4. Call the relocating loader to load the handler. The handler is
376 ; loaded 128 bytes at a time using command $26 (&), AUX1=block, where
377 ; block 0 is the first block.
378 ; 5. Go back to step 2.
379 ;
380 C46A .proc PHStartupPoll
381 ;issue type 3 poll reset (address $4F, command $40, aux $4F4F, no data)
382 C46A A2 4F ldx #$4F
383 C46C 20 E4 C4 jsr do_simple_poll
384
385 ;issue type 3 poll (address $4F, command $40, aux $0000, read 4 bytes)
386 C46F poll_loop:
387 C46F A9 00 lda #$00
388 C471 8D 0A 03 sta daux1
389 C474 8D 0B 03 sta daux2
390 C477 8D 09 03 sta dbythi
391 C47A A9 EA 8D 04 03 A9 + mwa #dvstat dbuflo
392 C484 A9 04 8D 08 03 mva #4 dbytlo
393 C489 A9 40 8D 03 03 mva #$40 dstats
394 C48E 20 59 E4 jsr siov
395 C491 10 11 bpl poll_ok
396 C493 C0 8A cpy #SIOErrorTimeout
397 C495 D0 01 bne poll_fail
398 C497 exit:
399 C497 60 rts
400 C498 poll_fail:
401 ;!! - Black Box 2.16 firmware intercepts type 3 polls and forces
402 ;a user abort error (Y=$80), which we must exit on to avoid an infinite
403 ;loop.
404 C498 C0 80 cpy #$80
405 C49A F0 FB beq exit
406
407 ;we had a failure -- issue a null poll before trying another device
408 C49C A2 4E ldx #$4e
409 C49E 20 E4 C4 jsr do_simple_poll
410 C4A1 4C 6F C4 jmp poll_loop
411
412 C4A4 poll_ok:
413 ;DVSTAT now contains the following frame:
414 ;
415 ; DVSTAT+0 handler size, low byte (should be even)
416 ; DVSTAT+1 handler size, high byte
417 ; DVSTAT+2 device address
418 ; DVSTAT+3 peripheral revision number
419
420 ;Check whether we have enough room between MEMLO and MEMTOP to load
421 ;this handler -- remember that MEMTOP is inclusive. Also, we need to
422 ;alloc an additional byte if MEMLO is odd.
423 C4A4 AD E7 02 lda memlo
424 C4A7 AA tax
425 C4A8 6A ror
426 C4A9 8A txa
427 C4AA 6D EA 02 adc dvstat
428 C4AD AA tax
429 C4AE AD E8 02 lda memlo+1
430 C4B1 6D EB 02 adc dvstat+1
431 C4B4 CD E6 02 cmp memtop+1
432 C4B7 90 09 bcc mem_ok
433 C4B9 D0 DD bne poll_fail
434 C4BB EC E5 02 cpx memtop
435 C4BE B0 02 bcs mem_ok
436 C4C0 D0 D6 bne poll_fail
437 C4C2 mem_ok:
438
439 ;set up for handler load
440 C4C2 AD E7 02 lda memlo
441 C4C5 AA tax
442 C4C6 6A ror
443 C4C7 8A txa
444 C4C8 69 00 adc #0
445 C4CA 8D D1 02 sta loadad
446 C4CD AD E8 02 lda memlo+1
447 C4D0 69 00 adc #0
448 C4D2 8D D2 02 sta loadad+1
449
450 C4D5 AD EC 02 8D 00 03 mva dvstat+2 ddevic
451
452 C4DB 38 sec
453 C4DC 20 01 C5 jsr PHLoadHandler
454 C4DF B0 B7 bcs poll_fail
455
456 ;look for another device
457 C4E1 4C 6F C4 jmp poll_loop
458
459 ;--------------------------------------------------------------------------
460 C4E4 do_simple_poll:
461 C4E4 A9 4F lda #$4f
462 C4E6 8D 00 03 sta ddevic
463 C4E9 8E 0A 03 stx daux1
464 C4EC 8E 0B 03 stx daux2
465 C4EF A9 40 lda #$40
466 C4F1 8D 02 03 sta dcomnd
467 C4F4 A9 01 lda #$01
468 C4F6 8D 01 03 sta dunit
469 C4F9 A9 00 lda #$00
470 C4FB 8D 03 03 sta dstats
471 C4FE 4C 59 E4 jmp siov
472
473 .endp
474
475 ;==========================================================================
476 ; Load peripheral handler over the SIO bus.
477 ;
478 ; Entry:
479 ; C Set to adjust MEMLO, clear to not
480 ; DDEVIC SIO address to load for loading
481 ; LOADAD Handler load address
482 ;
483 ; Modified:
484 ; All relocatable handler variables
485 ; DCB
486 ; DVSTAT
487 ;
488 C501 .proc PHLoadHandler
489 ;save MEMLO adjustment flag
490 C501 08 php
491
492 ;set zero-page relocation destination to $80 (should never be used)
493 C502 A9 80 8D D3 02 mva #$80 zloada
494
495 ;set up relocator get byte handler
496 C507 A9 40 8D CF 02 A9 + mwa #PHGetByte gbytea
497
498 ;set up for get byte, using command $26 and the cassette buffer
499 C511 A9 26 8D 02 03 mva #$26 dcomnd
500 C516 A2 00 8E 0A 03 mvx #0 daux1
501 C51B 8E 09 03 stx dbythi
502 C51E 8E 04 03 stx dbuflo
503 C521 CA dex
504 C522 86 3D stx bptr
505 C524 A9 04 8D 05 03 mva #$04 dbufhi
506 C529 A9 80 8D 08 03 mva #$80 dbytlo
507
508 ;load the handler
509 C52E 20 5A C5 jsr PHRelocateHandler
510 C531 B0 0B bcs reloc_fail
511
512 ;try to init handler, adjusting MEMLO as necessary
513 C533 AC D1 02 ldy loadad
514 C536 AD D2 02 lda loadad+1
515 C539 28 plp
516 C53A 20 9E C3 jsr PHInitHandler
517 C53D failed:
518 C53D 60 rts
519 C53E reloc_fail:
520 C53E 68 pla
521 C53F 60 rts
522 .endp
523
524 ;==========================================================================
525 ; Get byte handler used with relocating loader when loading handlers over
526 ; the SIO bus.
527 ;
528 C540 .proc PHGetByte
529 ;try to grab a byte
530 C540 A6 3D ldx bptr
531 C542 10 0C bpl fetch
532
533 ;issue SIO call to fetch next block
534 C544 A9 40 8D 03 03 mva #$40 dstats
535 C549 20 59 E4 jsr siov
536 C54C 30 0A bmi get_byte_fail
537 C54E A2 00 ldx #0
538
539 C550 fetch:
540 ;read next byte from cassette buffer
541 C550 BD 00 04 lda $0400,x
542 C553 E8 inx
543 C554 86 3D stx bptr
544
545 ;all clear
546 C556 18 clc
547 C557 60 rts
548
549 C558 get_byte_fail:
550 C558 38 sec
551 C559 60 rts
552
553 .endp
554
555 ;==========================================================================
556 ; Relocating loader.
557 ;
558 ; Modified:
559 ; LTEMP (word)
560 ; LCOUNT
561 ; RELADR
562 ; RECLEN
563 ; HIBYTE
564 ; RUNADR (word)
565 ; HIUSED (word)
566 ; ZHIUSE
567 ;
568 ; Record types:
569 ; Non-zp text $00 len { offset-lo offset-hi data* }
570 ; Zero-page text $01 len { offset-lo offset-hi data* }
571 ; Non-zp <ref to non-zp $02 len { offset* }
572 ; Zp <ref to non-zp $03 len { offset* }
573 ; Non-zp ref to zp $04 len { offset* }
574 ; Zp ref to zp $05 len { offset* }
575 ; Non-zp ref to non-zp $06 len { offset* }
576 ; Zp ref to non-zp $07 len { offset* }
577 ; Non-zp >ref to non-zp $08 len { {offset lo-byte}* }
578 ; Zp >ref to non-zp $09 len { {offset lo-byte}* }
579 ; Absolute text $0A len { addr-lo addr-hi data* }
580 ; End record $0B self-start addr-lo addr-hi
581 ;
582 ; The references need some explanation:
583 ; - The program is split into two sections, a zero-page section and a
584 ; non-zero page section. The two sections are each contiguous.
585 ; - Both the zero-page and non-zero-page sections can reference each
586 ; other.
587 ; - Low-byte references include only the low byte of an address.
588 ; - High-byte references include only the high byte of an address. A
589 ; low byte offset is included in the relocation to enable this.
590 ; - Relocation records are always applied to the last text record
591 ; that was loaded.
592 ;
593 C55A .proc PHRelocateHandler
594 ;make the zero-page load address 16-bit
595 C55A A9 00 lda #0
596 C55C 8D D4 02 sta zloada+1
597
598 C55F reloc_loop:
599 ;get a control byte and stash it
600 C55F 20 58 C6 jsr PHRelocateGetByte
601 C562 8D 33 02 sta lcount
602
603 ;get the length or self-start byte
604 C565 20 58 C6 jsr PHRelocateGetByte
605 C568 8D 45 02 sta reclen
606
607 ;dispatch to handler
608 C56B 20 71 C5 jsr dispatch
609
610 ;process more records
611 C56E 4C 5F C5 jmp reloc_loop
612
613 C571 dispatch:
614 C571 AE 33 02 ldx lcount
615 C574 BC 80 C5 ldy cmd_table_ind_tab,x
616 C577 B9 90 C5 lda cmd_table_hi,y
617 C57A 48 pha
618 C57B B9 8C C5 lda cmd_table_lo,y
619 C57E 48 pha
620 C57F 60 rts
621
622 ;---------------------------------------------------------
623 C580 cmd_table_ind_tab:
624 C580 00 00 01 01 01 01 + dta 0,0,1,1,1,1,1,1,2,2,0,3
625
626 C58C cmd_table_lo:
627 C58C 93 dta <(PHRelocateLoadText-1)
628 C58D D0 dta <(PHRelocateApplyFixups-1)
629 C58E 01 dta <(PHRelocateApplyHiFixups-1)
630 C58F 1F dta <(PHRelocateEnd-1)
631
632 C590 cmd_table_hi:
633 C590 C5 dta >(PHRelocateLoadText-1)
634 C591 C5 dta >(PHRelocateApplyFixups-1)
635 C592 C6 dta >(PHRelocateApplyHiFixups-1)
636 C593 C6 dta >(PHRelocateEnd-1)
637 .endp
638
639 ;==========================================================================
640 C594 .proc PHRelocateLoadText
641 ;retrieve the address into LTEMP
642 C594 20 58 C6 jsr PHRelocateGetByte
643 C597 85 36 sta ltemp
644 C599 20 58 C6 jsr PHRelocateGetByte
645 C59C 85 37 sta ltemp+1
646
647 ;check if we are doing an absolute load ($0A)
648 C59E AD 33 02 lda lcount
649 C5A1 C9 0A cmp #$0a
650 C5A3 F0 11 beq is_absolute
651
652 ;check whether we should use zero-page ($01) or non-zero-page ($00),
653 ;and adjust LTEMP
654 C5A5 0A asl
655 C5A6 AA tax
656 C5A7 18 BD D1 02 65 36 + adw loadad,x ltemp ltemp
657
658 C5B6 is_absolute:
659 ;init counter
660 C5B6 A9 00 lda #0
661 C5B8 8D 33 02 sta lcount
662
663 ;load reclen-2 bytes
664 C5BB CE 45 02 dec reclen
665 C5BE D0 0B bne load_loop_start
666
667 C5C0 load_loop:
668 C5C0 20 58 C6 jsr PHRelocateGetByte
669 C5C3 AC 33 02 ldy lcount
670 C5C6 EE 33 02 inc lcount
671 C5C9 91 36 sta (ltemp),y
672 C5CB load_loop_start:
673 C5CB CE 45 02 dec reclen
674 C5CE D0 F0 bne load_loop
675 C5D0 60 rts
676 .endp
677
678 ;==========================================================================
679 C5D1 .proc PHRelocateApplyFixups
680 ;get command byte and copy the appropriate reloc target into zchain
681 C5D1 AD 33 02 lda lcount
682 C5D4 4A lsr
683 C5D5 AE D1 02 ldx loadad
684 C5D8 C9 02 cmp #2
685 C5DA D0 03 sne
686 C5DC AE D3 02 ldx zloada
687 C5DF 86 4A stx zchain
688
689 ;set flag if we are doing a word reloc (types $06, $07)
690 C5E1 C9 03 cmp #3
691 C5E3 66 4B ror zchain+1
692
693 C5E5 reloc_loop:
694 ;fetch offset byte
695 C5E5 20 58 C6 jsr PHRelocateGetByte
696 C5E8 A8 tay
697
698 ;fixup low byte
699 C5E9 B1 36 lda (ltemp),y
700 C5EB 18 clc
701 C5EC 65 4A adc zchain
702 C5EE 91 36 sta (ltemp),y
703
704 ;check if we're doing a high byte reloc
705 C5F0 24 4B bit zchain+1
706 C5F2 10 08 bpl low_byte_only
707
708 ;fixup high byte
709 C5F4 C8 iny
710 C5F5 B1 36 lda (ltemp),y
711 C5F7 6D D2 02 adc loadad+1
712 C5FA 91 36 sta (ltemp),y
713
714 C5FC low_byte_only:
715 ;loop back if there is more fixup data
716 C5FC CE 45 02 dec reclen
717 C5FF D0 E4 bne reloc_loop
718 C601 60 rts
719 .endp
720
721 ;==========================================================================
722 C602 .proc PHRelocateApplyHiFixups
723 C602 reloc_loop:
724 ;fetch offset byte
725 C602 20 58 C6 jsr PHRelocateGetByte
726 C605 85 4A sta zchain
727
728 ;fetch low fixup byte
729 C607 20 58 C6 jsr PHRelocateGetByte
730
731 ;add low byte to base
732 C60A 18 clc
733 C60B 6D D1 02 adc loadad
734
735 ;fixup high byte
736 C60E A4 4A ldy zchain
737 C610 AD D2 02 lda loadad+1
738 C613 71 36 adc (ltemp),y
739 C615 91 36 sta (ltemp),y
740
741 ;loop back if there is more fixup data
742 C617 CE 45 02 dec reclen
743 C61A CE 45 02 dec reclen
744 C61D D0 E3 bne reloc_loop
745 C61F 60 rts
746 .endp
747
748 ;==========================================================================
749 C620 .proc PHRelocateEnd
750 ;read in the address to RUNADR
751 C620 20 58 C6 jsr PHRelocateGetByte
752 C623 8D C9 02 sta runadr
753 C626 20 58 C6 jsr PHRelocateGetByte
754 C629 8D CA 02 sta runadr+1
755
756 ;check the self-start byte
757 C62C AE 33 02 ldx lcount
758 C62F D0 0E bne do_self_start
759
760 ;no self-start... zero the addr and exit
761 C631 A9 00 lda #0
762 C633 8D C9 02 sta runadr
763 C636 8D CA 02 sta runadr+1
764 C639 xit:
765 C639 18 clc
766 C63A 68 pla
767 C63B 68 pla
768 C63C A0 01 ldy #1
769 C63E 60 rts
770
771 C63F do_self_start:
772 ;check if we need to relocate the address... if it
773 ;is absolute ($01), we're done
774 C63F CA dex
775 C640 F0 F7 beq xit
776
777 ;add the non-zp base address and exit
778 C642 18 AD C9 02 6D D1 + adw runadr loadad runadr
779 C655 4C 39 C6 jmp xit
780 .endp
781
782 ;==========================================================================
783 C658 .proc PHRelocateGetByte
784 C658 20 60 C6 jsr call_get_byte
785 C65B 90 02 bcc get_byte_ok
786 C65D 68 pla
787 C65E 68 pla
788 C65F get_byte_ok:
789 C65F 60 rts
790
791 C660 call_get_byte:
792 C660 6C CF 02 jmp (gbytea)
793 .endp
83 C663 _KERNEL_REPORT_MODULE_SIZE 'Peripheral Handler routines', 0
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'Peripheral Handler routines'
1 $C663 -> $0341($0000) Peripheral Handler routines
3 = C663 .def ?@_kernel_lastpt = *
Source: source/main.xasm
84
85 .ifdef _KERNEL_816
86 icl 'syscall816.s'
87 icl 'sysdev816.s'
88 .endif
89
90 C663 org $cc00
91 CC00 icl 'atariifont.inc'
Source: source/Shared/atariifont.inc
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Character Font
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 CC00 00 00 00 00 00 00 + ins 'atariifont.bin',$0,$400
92
93 D000 org $d000
94 D000 icl 'bootscreen.s'
Source: source/Shared/bootscreen.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Boot Screen
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
37 opt l+
38
39 009B org $5000,$d000
40 opt o+f+
41
42 5000 .proc BootScreen
43 D000 18 clc
44 5001 24 dta {bit $00}
45 5002 boot_entry:
46 5002 38 sec
47 5003 08 php
48
49 5004 20 6C 52 jsr BootClearRam
50
51 5007 28 plp
52 5008 66 80 ror canboot
53
54 ;relocate data down to RAM
55 500A A9 D0 85 8A A9 56 + mwa #[.adr BootRamDataStart]+$5000-$D000 scrnad1
56 5012 A9 00 85 8C A9 30 + mwa #BootRamDataStart scrnad2
57
58 .if >[BootRamDataEnd-BootRamDataStart]
59 ldx #>[BootRamDataEnd-BootRamDataStart]
60 ldy #0
61 page_copy:
62 mva:rne (scrnad1),y (scrnad2),y+
63 inc scrnad1+1
64 inc scrnad2+1
65 dex
66 bne page_copy
67 .endif
68
69 .if <[BootRamDataEnd-BootRamDataStart]
70 501A byte_copy:
71 501A B1 8A 91 8C C8 mva (scrnad1),y (scrnad2),y+
72 501F C0 7A cpy #<[BootRamDataEnd-BootRamDataStart]
73 5021 D0 F7 bne byte_copy
74 .endif
75
76 ;copy down bitmap graphics
77 5023 A9 13 85 8C A9 32 + mwa #playfield3+19 scrnad2
78 502B A9 C8 85 8A A9 54 + mwa #BootDriveImage scrnad1
79 5033 A2 28 ldx #40
80 5035 blit_loop:
81 5035 A0 0C ldy #12
82 5037 B1 8A 91 8C 88 10 + mva:rpl (scrnad1),y (scrnad2),y-
83 503E 18 clc
84 503F A5 8C lda scrnad2
85 5041 69 20 adc #$20
86 5043 85 8C sta scrnad2
87 5045 90 02 E6 8D scc:inc scrnad2+1
88 5049 A5 8A lda scrnad1
89 504B 18 clc
90 504C 69 0D adc #13
91 504E 85 8A sta scrnad1
92 5050 90 02 E6 8B scc:inc scrnad1+1
93 5054 CA dex
94 5055 D0 DE bne blit_loop
95
96 ;set up display and interrupts
97 5057 78 sei
98 5058 20 9D 54 jsr BootSwapVectors
99 505B A9 00 8D 0E D4 mva #0 nmien
100 5060 A9 C0 8D 0E D4 mva #$c0 nmien
101 5065 A9 2C 8D 07 D4 mva #>player0 pmbase
102
103 506A A2 0C ldx #$0c
104 506C BD 16 52 9D 00 D0 + mva:rpl gtia_data,x hposp0,x-
105
106 5075 A9 03 8D 1D D0 mva #$03 gractl
107 507A 58 cli
108
109 ;init sprites 0,1
110 507B A2 00 ldx #0
111 507D A0 20 ldy #32
112 507F sprinit:
113 507F BD 3F 54 99 00 2C mva spr0dat,x player0,y
114 5085 BD 47 54 99 00 2D + mva spr1dat,x player1,y+
115 508C 98 tya
116 508D 29 0F and #$0f
117 508F D0 EE bne sprinit
118 5091 E8 inx
119 5092 E0 08 cpx #8
120 5094 D0 E9 bne sprinit
121
122 5096 A9 00 lda #0
123 5098 85 88 sta char_x
124 509A 85 89 sta char_y
125
126 509C 85 8E sta msgadr
127 509E imloop:
128 509E A4 8E ldy msgadr
129 50A0 E6 8E inc msgadr
130 50A2 B9 D6 52 lda BootMessage,y
131 50A5 C9 FF cmp #$ff
132 50A7 F0 06 beq imdone
133 50A9 20 A9 53 jsr PlotChar
134 50AC 4C 9E 50 jmp imloop
135 50AF imdone:
136
137 50AF A9 00 lda #0
138 50B1 85 9A sta phase
139 50B3 loop1:
140 50B3 A2 00 ldx #0
141 50B5 8A txa
142 50B6 sprclr:
143 50B6 9D 00 2E sta player2,x
144 50B9 9D 00 2F sta player3,x
145 50BC CA dex
146 50BD D0 F7 bne sprclr
147
148 ;save off the current RTCLOK
149 50BF AD 0B D4 D0 FB lda:rne vcount
150 50C4 A2 02 ldx #2
151 50C6 B5 12 95 94 CA 10 + mva:rpl rtclok,x rtcsav,x-
152
153 ;clear the break key in case it was pressed to interrupt the last read
154 50CD 86 11 stx brkkey
155
156 ;issue status request to D1:
157 50CF A9 01 lda #1
158 50D1 8D 01 03 sta dunit
159 50D4 A9 53 8D 02 03 mva #$53 dcomnd
160 50D9 20 53 E4 jsr dskinv
161 50DC 30 21 bmi loop2
162
163 ;try to read sector #1 on D1:
164 50DE A9 52 8D 02 03 mva #$52 dcomnd
165 50E3 A9 00 8D 04 03 A9 + mwa #$0400 dbuflo
166 50ED A9 01 8D 0A 03 A9 + mwa #1 daux1
167 50F7 20 53 E4 jsr dskinv
168 50FA 30 03 bmi loop2
169 50FC 4C 23 52 jmp BootScreenExit
170 50FF loop2:
171 50FF A5 14 lda rtclok+2
172 5101 C5 14 F0 FC cmp:req rtclok+2
173 5105 A5 14 lda rtclok+2
174 5107 C5 14 F0 FC cmp:req rtclok+2
175
176 510B A6 9A ldx phase
177 510D BD 87 51 85 92 BD + mwa phasetab+1,x spricl
178
179 5117 BC 86 51 ldy phasetab,x
180 511A A9 00 lda #0
181 511C 85 90 sta spracl
182 511E 85 91 sta sprach
183 5120 clloop:
184 5120 99 00 2B sta missiles,y
185 5123 99 00 2E sta player2,y
186 5126 99 00 2F sta player3,y
187 5129 88 dey
188 512A 30 F4 bmi clloop
189
190 512C BC 86 51 ldy phasetab,x
191 512F A9 FF lda #$ff
192 5131 blitloop:
193 5131 A6 91 ldx sprach
194 5133 BD 4F 54 lda sprdat2,x
195 5136 99 00 2E sta player2,y
196 5139 BD 6F 54 lda sprdat3,x
197 513C 99 00 2F sta player3,y
198
199 513F C8 iny
200 5140 18 A5 90 65 92 85 + adw spracl spricl spracl
201 514D A5 91 lda sprach
202 514F C9 20 cmp #$20
203 5151 90 DE bcc blitloop
204 5153 A9 00 lda #0
205 5155 blitloop2:
206 5155 99 00 2B sta missiles,y
207 5158 99 00 2E sta player2,y
208 515B 99 00 2F sta player3,y
209 515E C8 iny
210 515F C0 40 cpy #$40
211 5161 D0 F2 bne blitloop2
212
213 ;if this is the first animation frame, wait a bit after it
214 5163 A5 9A lda phase
215 5165 D0 0C bne no_wait
216
217 5167 A2 19 ldx #25
218 5169 waitloop:
219 5169 A5 14 lda rtclok+2
220 516B C5 14 F0 FC cmp:req rtclok+2
221 516F CA dex
222 5170 D0 F7 bne waitloop
223 5172 8A txa
224
225 5173 no_wait:
226 5173 18 clc
227 5174 69 03 adc #3
228 5176 85 9A sta phase
229 5178 C9 90 cmp #phasetab_end-phasetab
230 517A B0 03 4C FF 50 scs:jmp loop2
231
232 517F A9 00 lda #0
233 5181 85 9A sta phase
234 5183 4C B3 50 jmp loop1
235
236 5186 phasetab:
237 5186 8A AA 00 89 AB 00 + :48 dta $7a+[48-#]/3, a([$200+#*#*3]/3)
238 5216 phasetab_end:
239
240 5216 gtia_data:
241 5216 40 60 A4 98 68 60 + dta $40,$60,$a4,$98,$68,$60,$00,$00
242 521E 03 03 00 03 0F dta $03,$03,$00,$03,$0f
243 .endp
244
245 ;==========================================================================
246 5223 .proc BootScreenExit
247 5223 78 sei
248 5224 A9 00 lda #0
249 5226 8D 0E D4 sta nmien
250
251 ;wait for vertical blank
252 5229 A2 7C ldx #248/2
253 522B EC 0B D4 D0 FB cpx:rne vcount
254
255 ;shut off display
256 5230 8D 00 D4 sta dmactl
257 5233 8D 2F 02 sta sdmctl
258
259 ;reset GTIA (but not VBXE)
260 5236 9D 00 D0 E8 10 FA sta:rpl $d000,x+
261
262 ;check if we can continue the initial boot process
263 523C 24 80 bit canboot
264 523E 30 03 bmi continue_boot
265
266 ;invoke cold start
267 5240 4C 77 E4 jmp coldsv
268
269 5243 continue_boot:
270 ;swap interrupt handler registers back
271 5243 20 9D 54 jsr BootSwapVectors
272
273 ;re-wipe RAM areas we used
274 5246 20 6C 52 jsr BootClearRam
275
276 ;re-enable IRQs (but VBI is still disabled)
277 5249 58 cli
278
279 ;print a clear screen character to clear any latent BOOT ERRORs
280 524A A9 7D lda #$7d
281 524C A2 00 ldx #0
282 524E 8E 48 03 stx icbll
283 5251 8E 49 03 stx icblh
284 5254 A0 0B ldy #CIOCmdPutChars
285 5256 8C 42 03 sty iccmd
286 5259 20 56 E4 jsr ciov
287
288 ;re-enable VBI and wait for VBI stage 2 to run once
289 525C A9 40 8D 0E D4 mva #$40 nmien
290
291 5261 A9 FF lda #$ff
292 5263 8D 83 02 sta ptrig7
293 5266 2C 83 02 30 FB bit:rmi ptrig7
294
295 ;all done, return to boot code with sector 1 loaded at $0400
296 526B 60 rts
297 .endp
298
299 ;==========================================================================
300 526C .proc BootClearRam
301 ;clear $2000-$37FF
302 526C A9 00 lda #0
303 526E A8 tay
304 526F 85 84 sta charadr
305 5271 A2 20 ldx #$20
306 5273 86 85 stx charadr+1
307 5275 A2 18 ldx #$18
308 5277 clear_loop:
309 5277 91 84 C8 D0 FB sta:rne (charadr),y+
310 527C E6 85 inc charadr+1
311 527E CA dex
312 527F D0 F6 bne clear_loop
313
314 ;clear user page zero
315 5281 95 80 E8 10 FB sta:rpl $80,x+
316
317 ;all done
318 5286 60 rts
319 .endp
320
321 ;==========================================================================
322 5287 .proc BootScreenVbi
323 5287 AD 4E 30 lda pfadr+1
324 528A 49 05 eor #$05
325 528C 8D 4E 30 sta pfadr+1
326 528F AD C5 02 lda color1
327 5292 8D 17 D0 sta colpf1
328 5295 AD C6 02 lda color2
329 5298 8D 18 D0 sta colpf2
330 529B 6C 00 30 jmp (BootVecVbi)
331 .endp
332
333 ;==========================================================================
334 529E .proc BootScreenIrq
335 529E 2C 0F D4 bit nmist
336 52A1 10 20 bpl do_irq
337 = 52A3 .def :BootScreenDli
338 52A3 48 pha
339 52A4 8A txa
340 52A5 48 pha
341 52A6 AD 0B D4 lda vcount
342 52A9 C9 48 cmp #72
343 52AB B0 19 bcs split
344 52AD 4A lsr
345 52AE 4A lsr
346 52AF AA tax
347 52B0 BD 8A 54 lda coltab-5,x
348 52B3 8D 0A D4 sta wsync
349 52B6 8D 12 D0 sta colpm0
350 52B9 8D 13 D0 sta colpm1
351 52BC xit:
352 52BC 8D 0F D4 sta nmires
353 52BF 68 pla
354 52C0 AA tax
355 52C1 68 pla
356 52C2 40 rti
357 52C3 do_irq:
358 52C3 6C 02 30 jmp (BootVecIrq)
359 52C6 split:
360 52C6 A9 50 lda #$50
361 52C8 A2 5C ldx #$5c
362 52CA 8D 0A D4 sta wsync
363 52CD 8D 18 D0 sta colpf2
364 52D0 8E 17 D0 stx colpf1
365
366 52D3 4C BC 52 jmp xit
367 .endp
368
369 ;==========================================================================
370 52D6 .local BootMessage
371 ; 0123456789012345678901234567890123456789012345678901234567890123
372 52D6 21 6C 74 69 72 72 + dta d"AltirraOS"
373 52DF _KERNELSTR_BIOS_NAME_INTERNAL
Macro: _KERNELSTR_BIOS_NAME_INTERNAL [Source: source/main.xasm]
4 52DF 00 66 6F 72 00 38 + dta d" for XL/XE/XEGS"
Source: source/Shared/bootscreen.s
374 52EE 00 dta d" "
375 52EF _KERNELSTR_VERSION_INTERNAL
Macro: _KERNELSTR_VERSION_INTERNAL [Source: source/Shared/version.inc]
1 52EF 13 0E 12 16 dta "3.26"
Source: source/Shared/bootscreen.s
376
377 52F3 9B dta $9b
378
379 .ifdef _KERNEL_816
380 dta d"Copyright (C) 2018-2019 Avery Lee",$9b
381 .else
382 52F4 23 6F 70 79 72 69 + dta d"Copyright (C) 2012-2019 Avery Lee",$9b
383 .endif
384
385 5316 21 6C 6C 00 32 69 + dta d"All Rights Reserved",$9b
386 532A 34 68 69 73 00 69 + dta d"This is a substitute for the standard OS ROM. See the help file",$9b
387 536A 66 6F 72 00 68 6F + dta d"for how to use real Atari ROM images for higher compatibility."
388 53A8 FF dta $ff
389 .endl
390
391 ;==========================================================================
392 53A9 plotchar:
393 53A9 C9 9B cmp #$9b
394 53AB D0 07 bne not_eol
395 53AD A9 00 85 88 mva #0 char_x
396 53B1 E6 89 inc char_y
397 53B3 60 rts
398 53B4 not_eol:
399 53B4 85 84 sta charadr
400
401 53B6 A9 00 lda #0
402 53B8 85 8A sta scrnad1
403 53BA 85 8C sta scrnad2
404 53BC A5 89 lda char_y
405 53BE 09 20 ora #>playfield
406 53C0 85 8B sta scrnad1+1
407 53C2 18 clc
408 53C3 69 05 adc #$05
409 53C5 85 8D sta scrnad2+1
410
411 53C7 A5 88 lda char_x
412 53C9 4A lsr
413 53CA 85 83 sta charpos
414 53CC 6A ror
415 53CD 85 87 sta charodd
416
417 53CF A9 1C lda #$e0/8
418 53D1 A2 03 ldx #3
419 53D3 shlloop:
420 53D3 06 84 asl charadr
421 53D5 2A rol
422 53D6 CA dex
423 53D7 D0 FA bne shlloop
424 53D9 85 85 sta charadr+1
425
426 53DB 18 clc
427 53DC rowloop:
428 53DC A2 04 ldx #4
429 53DE A0 00 ldy #0
430 53E0 B1 84 lda (charadr),y
431 53E2 4A lsr
432 53E3 bitloop:
433 53E3 4A lsr
434 53E4 66 81 ror chardt1
435 53E6 4A lsr
436 53E7 66 82 ror chardt2
437 53E9 CA dex
438 53EA D0 F7 bne bitloop
439
440 53EC A4 83 ldy charpos
441 53EE 24 87 bit charodd
442 53F0 30 12 bmi odd
443 53F2 A5 82 lda chardt2
444 53F4 51 8C eor (scrnad2),y
445 53F6 29 0F and #$0f
446 53F8 45 82 eor chardt2
447 53FA 91 8C sta (scrnad2),y
448
449 53FC A5 81 lda chardt1
450 53FE 51 8A eor (scrnad1),y
451 5400 29 0F and #$0f
452
453 5402 10 1E bpl even
454 5404 odd:
455 5404 A5 81 lda chardt1
456 5406 4A lsr
457 5407 4A lsr
458 5408 4A lsr
459 5409 4A lsr
460 540A 85 81 sta chardt1
461 540C A5 82 lda chardt2
462 540E 4A lsr
463 540F 4A lsr
464 5410 4A lsr
465 5411 4A lsr
466 5412 85 82 sta chardt2
467 5414 51 8C eor (scrnad2),y
468 5416 29 F0 and #$f0
469 5418 45 82 eor chardt2
470 541A 91 8C sta (scrnad2),y
471 541C A5 81 lda chardt1
472 541E 51 8A eor (scrnad1),y
473 5420 29 F0 and #$f0
474 5422 even:
475 5422 45 81 eor chardt1
476 5424 91 8A sta (scrnad1),y
477 5426 E6 84 inc charadr
478 5428 98 tya
479 5429 18 clc
480 542A 69 20 adc #$20
481 542C 85 83 sta charpos
482 542E 90 AC bcc rowloop
483
484 ;update position
485 5430 E6 88 inc char_x
486 5432 A6 88 ldx char_x
487 5434 E0 40 cpx #64
488 5436 90 06 bcc done
489 5438 A9 00 85 88 mva #0 char_x
490 543C E6 89 inc char_y
491 543E done:
492 543E 60 rts
493
494 ;==========================================================================
495 543F spr0dat:
496 543F 00 dta %00000000
497 5440 03 dta %00000011
498 5441 0F dta %00001111
499 5442 3C dta %00111100
500 5443 3C dta %00111100
501 5444 3F dta %00111111
502 5445 3C dta %00111100
503 5446 00 dta %00000000
504
505 5447 spr1dat:
506 5447 00 dta %00000000
507 5448 C0 dta %11000000
508 5449 F0 dta %11110000
509 544A 3C dta %00111100
510 544B 3C dta %00111100
511 544C FC dta %11111100
512 544D 3C dta %00111100
513 544E 00 dta %00000000
514
515 544F sprdat2:
516 544F 00 dta %00000000
517 5450 00 dta %00000000
518 5451 18 dta %00011000
519 5452 3C dta %00111100
520 5453 3C dta %00111100
521 5454 3C dta %00111100
522 5455 3C dta %00111100
523 5456 3C dta %00111100
524 5457 3C dta %00111100
525 5458 18 dta %00011000
526 5459 00 dta %00000000
527 545A 00 dta %00000000
528 545B E7 dta %11100111
529 545C 81 dta %10000001
530 545D 81 dta %10000001
531 545E 00 dta %00000000
532 545F 00 dta %00000000
533 5460 81 dta %10000001
534 5461 81 dta %10000001
535 5462 E7 dta %11100111
536 5463 00 dta %00000000
537 5464 00 dta %00000000
538 5465 00 dta %00000000
539 5466 00 dta %00000000
540 5467 00 dta %00000000
541 5468 00 dta %00000000
542 5469 00 dta %00000000
543 546A 00 dta %00000000
544 546B 00 dta %00000000
545 546C 00 dta %00000000
546 546D 00 dta %00000000
547 546E 00 dta %00000000
548
549 546F sprdat3:
550 546F FF dta %11111111
551 5470 FF dta %11111111
552 5471 FF dta %11111111
553 5472 FF dta %11111111
554 5473 FF dta %11111111
555 5474 FF dta %11111111
556 5475 FF dta %11111111
557 5476 FF dta %11111111
558 5477 FF dta %11111111
559 5478 FF dta %11111111
560 5479 FF dta %11111111
561 547A FF dta %11111111
562 547B E7 dta %11100111
563 547C E7 dta %11100111
564 547D E7 dta %11100111
565 547E E7 dta %11100111
566 547F E7 dta %11100111
567 5480 E7 dta %11100111
568 5481 E7 dta %11100111
569 5482 E7 dta %11100111
570 5483 FF dta %11111111
571 5484 FF dta %11111111
572 5485 FF dta %11111111
573 5486 FF dta %11111111
574 5487 FF dta %11111111
575 5488 FF dta %11111111
576 5489 7F dta %01111111
577 548A FF dta %11111111
578 548B FF dta %11111111
579 548C FF dta %11111111
580 548D FF dta %11111111
581 548E FF dta %11111111
582
583 ;==========================================================================
584
585 ;==========================================================================
586 548F coltab:
587 548F 1A dta $1a
588 5490 FA dta $fa
589 5491 EA dta $ea
590 5492 DA dta $da
591 5493 CA dta $ca
592 5494 BA dta $ba
593 5495 AA dta $aa
594 5496 9A dta $9a
595 5497 8A dta $8a
596 5498 7A dta $7a
597 5499 6A dta $6a
598 549A 5A dta $5a
599
600 549B 0E 50 dta $0E,$50
601
602 ;==========================================================================
603 549D .proc BootSwapVectors
604 549D A2 13 ldx #vec_offsets_end-vec_offsets-1
605 549F loop:
606 549F BC B4 54 ldy vec_offsets,x
607 54A2 B9 00 02 lda $0200,y
608 54A5 48 pha
609 54A6 BD 00 30 lda BootVectors,x
610 54A9 99 00 02 sta $0200,y
611 54AC 68 pla
612 54AD 9D 00 30 sta BootVectors,x
613 54B0 CA dex
614 54B1 10 EC bpl loop
615 54B3 60 rts
616
617 54B4 vec_offsets:
618 54B4 22 dta vvblki-$0200
619 54B5 23 dta vvblki-$0200+1
620 54B6 16 dta vimirq-$0200
621 54B7 17 dta vimirq-$0200+1
622 54B8 00 dta vdslst-$0200
623 54B9 01 dta vdslst-$0200+1
624 54BA 30 dta sdlstl-$0200
625 54BB 31 dta sdlsth-$0200
626 54BC C0 dta pcolr0-$0200
627 54BD C1 dta pcolr1-$0200
628 54BE C2 dta pcolr2-$0200
629 54BF C3 dta pcolr3-$0200
630 54C0 C4 dta color0-$0200
631 54C1 C5 dta color1-$0200
632 54C2 C6 dta color2-$0200
633 54C3 C7 dta color3-$0200
634 54C4 C8 dta color4-$0200
635 54C5 2F dta sdmctl-$0200
636 54C6 6F dta gprior-$0200
637 54C7 44 dta coldst-$0200
638 54C8 vec_offsets_end:
639 .endp
640
641 ;==========================================================================
642 54C8 .proc BootDriveImage
643 54C8 icl 'driveimage.inc'
Source: source/Shared/driveimage.inc
1 ;Made from driveimage.bmp using driveimageconv.cpp
2 54C8 00 00 00 0A AA AA + dta %00000000,%00000000,%00000000,%00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000,%00000000,%00000000,%00000000
3 54D5 02 AA AA AA AA AA + dta %00000010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101000,%00000000
4 54E2 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000
5 54EF 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000
6 54FC 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000
7 5509 0A 55 55 55 55 55 + dta %00001010,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01011010,%00000000
8 5516 2A 55 55 55 55 55 + dta %00101010,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01011010,%10000000
9 5523 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10000000
10 5530 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10000000
11 553D 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10000000
12 554A 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10000000
13 5557 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000
14 5564 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000
15 5571 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000
16 557E A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000
17 558B A5 55 55 55 55 55 + dta %10100101,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010101,%10100000
18 5598 A5 55 55 55 55 55 + dta %10100101,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010101,%10100000
19 55A5 A5 55 57 FF FF FF + dta %10100101,%01010101,%01010111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11010101,%10100000
20 55B2 A5 55 57 FF FF FF + dta %10100101,%01010101,%01010111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11010101,%10100000
21 55BF A5 55 57 FF FF FF + dta %10100101,%01010101,%01010111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11010101,%10100000
22 55CC A5 55 55 55 55 55 + dta %10100101,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010101,%10100000
23 55D9 A5 55 55 55 55 55 + dta %10100101,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010101,%10100000
24 55E6 A5 55 55 55 55 55 + dta %10100101,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010101,%10100000
25 55F3 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000
26 5600 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000
27 560D A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000
28 561A A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000
29 5627 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000
30 5634 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000
31 5641 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10000000
32 564E 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010110,%10000000
33 565B 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010110,%10000000
34 5668 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010110,%10000000
35 5675 2A 55 55 55 55 55 + dta %00101010,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01011010,%10000000
36 5682 0A 55 55 55 55 55 + dta %00001010,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01011010,%00000000
37 568F 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000
38 569C 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000
39 56A9 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000
40 56B6 02 AA AA AA AA AA + dta %00000010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101000,%00000000
41 56C3 00 00 00 0A AA AA + dta %00000000,%00000000,%00000000,%00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000,%00000000,%00000000,%00000000
644 .endp
645
646 ;==========================================================================
647 ; Data relocated to RAM
648 ;
649 56D0 org $3000,*-$5000+$d000
650
651 = 3000 BootRamDataStart = *
652
653 3000 BootVectors:
654 3000 87 52 BootVecVbi dta a(BootScreenVbi)
655 3002 9E 52 BootVecIrq dta a(BootScreenIrq)
656 3004 A3 52 BootVecDli dta a(BootScreenDli)
657 3006 14 30 BootVecDlist dta a(BootDlist)
658 3008 color_table:
659 3008 00 dta $00
660 3009 00 dta $00
661 300A 02 dta $02
662 300B 00 dta $00
663 300C 08 dta $08
664 300D 0C dta $0C
665 300E 02 dta $02
666 300F 14 dta $14
667 3010 50 dta $50
668 3011 3D dta $3d ;sdmctl
669 3012 01 dta $01 ;gprior
670 3013 FF dta $ff ;coldst, to force cold reboot if RESET pressed
671
672 3014 BootDlist:
673 3014 70 70 70 70 :4 dta $70
674 3018 F0 F0 F0 F0 F0 F0 + :8 dta $F0
675
676 ;drive image (40 lines x 32 bytes = $500 bytes
677 3020 4E 00 32 dta $4E,a(playfield3)
678 3023 0E 0E 0E 0E 0E 0E :6 dta $0E
679 3029 8E dta $8E
680 302A 0E 0E 0E 0E 0E 0E + :4 dta $0E,$0E,$0E,$0E,$0E,$0E,$0E,$8E
681
682 304A F0 dta $F0
683 304B 70 dta $70
684
685 ;80-col text screen (2x 40 rows)
686 304C 4F 00 20 dta $4F,a(playfield)
687 = 304D pfadr = *-2
688 304F 0F 0F 0F 0F 0F 0F + :7 dta $0F
689 3056 0F 0F 0F 0F 0F 0F + :8 dta $0F
690 305E 0F 0F 0F 0F 0F 0F + :8 dta $0F
691 3066 70 dta $70
692 3067 0F 0F 0F 0F 0F 0F + :8 dta $0F
693 306F 0F 0F 0F 0F 0F 0F + :8 dta $0F
694 3077 41 14 30 dta $41,a(BootDlist)
695
696 = 307A BootRamDataEnd = *
697
698 ;==========================================================================
699 ; Version block for emulator
700 ;
701 307A org $d7f8
702 D7F8 _KERNELSTR_VERSION
Macro: _KERNELSTR_VERSION [Source: source/Shared/version.inc]
1 D7F8 33 2E 32 36 dta '3.26'
Source: source/Shared/bootscreen.s
703 D7FC 00 dta 0
704
705
706 D7FD org $d7ff
707 D7FF 00 dta 0
708
729 opt l+
730 3200 org $d800
95
96 opt f+
97 .endif
98
99 D800 org $d800
100
101 D800 icl 'mathpack.s'
Source: source/Shared/mathpack.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Decimal Floating-Point Math Pack
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 ;
12 ; Known problems:
13 ; Currently incompatible with BASIC XE due to it relying on $DE-DF not
14 ; being modified by FADD/FSUB.
15 ;
16 ;==========================================================================
17 ;
18 ; Notes
19 ;
20 ; AFP FMUL
21 ; |FASC.FDIV
22 ; |.IPF.|PLYEVL
23 ; |.|FPI|.EXP
24 ; |.|.FADD|REDRNG
25 ; |.|.|.|.|.LOG
26 ; vvvvvvvvvvv
27 ; $D4 FR0 M MMM.
28 ; $D5 | M MMM.
29 ; $D6 | M MMM.
30 ; $D7 | M MMM.
31 ; $D8 | M MMM.
32 ; $D9 v M MMM.
33 ; $DA FR2 {FRE} TTTTTTT.
34 ; $DB | TT TTTT.
35 ; $DC | TT TTTT.
36 ; $DD | TT TTTT.
37 ; $DE | T TTT. [1,2]
38 ; $DF v TTT. [1,2]
39 ; $E0 FR1 MM . [3]
40 ; $E1 | MM . [3]
41 ; $E2 | MM . [3]
42 ; $E3 | MM . [3]
43 ; $E4 | MM . [3]
44 ; $E5 v MM . [3]
45 ; $E6 FR3 {FR2} . .
46 ; $E7 . .
47 ; $E8 . .
48 ; $E9 . .
49 ; $EA . .
50 ; $EB . .
51 ; $EC {FRX} . .
52 ; $ED {EEXP} . .
53 ; $EE {NSIGN} . .
54 ; $EF {ESIGN} . .
55 ; $F0 {FCHRFLG} . .
56 ; $F1 {DIGRT} . .
57 ; $F2 CIX . .
58 ; $F3 INBUFF . .
59 ; $F4 v . .
60 ; $F5 {ZTEMP1} . .
61 ; $F6 v . .
62 ; $F7 {ZTEMP4} . .
63 ; $F8 v . .
64 ; $F9 {ZTEMP3} . .
65 ; $FA v . .
66 ; $FB DEGFLG/RADFLG . .
67 ; $FC FLPTR . .
68 ; $FD v . .
69 ; $FE FPTR2 . .
70 ; $FF v . .
71 ; $05E0 PLYARG T T
72 ; $05E1 | T T
73 ; $05E2 | T T
74 ; $05E3 | T T
75 ; $05E4 | T T
76 ; $05E5 v T T
77 ; $05E6 FPSCR TT
78 ; $05E7 | TT
79 ; $05E8 | TT
80 ; $05E9 | TT
81 ; $05EA | TT
82 ; $05EB v TT
83 ; $05EC FPSCR1
84 ; $05ED |
85 ; $05EE |
86 ; $05EF |
87 ; $05F0 |
88 ; $05F1 v
89 ;
90 ; Notes:
91 ; [1] BASIC XE relies on $DE/DF not being touched by FADD, or FOR/NEXT
92 ; breaks.
93 ; [2] MAC/65 relies on $DE/DF not being touched by IPF.
94 ; [3] DARG relies on FPI not touching FR1.
95 ; [4] ACTris 1.2 relies on FASC not touching lower parts of FR2.
96 ;
97
98 .macro ckaddr
99 .if * <> %%1
100 .error 'Incorrect address: ',*,' != ',%%1
101 .endif
102 .endm
103
104 .macro fixadr
105 .if * < %%1
106 .print (%%1-*),' bytes free before ',%%1
107 org %%1
108 .elif * > %%1
109 .error 'Out of space: ',*,' > ',%%1,' (',*-%%1,' bytes over)'
110 .endif
111 .endm
112
113 ;==========================================================================
114 ; AFP [D800] Convert ASCII string at INBUFF[CIX] to FR0
115 ;
116 D800 org $d800
117 = D800 _afp = afp
118 D800 .proc afp
119 = 00E6 dotflag = fr2
120 = 00E7 xinvert = fr2+1
121 = 00E8 cix0 = fr2+2
122 = 00E9 sign = fr2+3
123 = 00EA digit2 = fr2+4
124
125 ;skip initial spaces
126 D800 20 A1 DB jsr skpspc
127
128 ;init FR0 and one extra mantissa byte
129 D803 A9 7F lda #$7f
130 D805 85 D4 sta fr0
131 D807 85 EA sta digit2
132
133 D809 A2 D5 ldx #fr0+1
134 D80B 20 46 DA jsr zf1
135
136 ;clear decimal flag
137 D80E 85 E6 sta dotflag
138 D810 85 E9 sta sign
139
140 ;check for sign
141 D812 A4 F2 ldy cix
142 D814 B1 F3 lda (inbuff),y
143 D816 C9 2B cmp #'+'
144 D818 F0 06 beq isplus
145 D81A C9 2D cmp #'-'
146 D81C D0 03 bne postsign
147 D81E 66 E9 ror sign
148 D820 isplus:
149 D820 C8 iny
150 D821 postsign:
151 D821 84 E8 sty cix0
152
153 ;skip leading zeroes
154 D823 A9 30 lda #'0'
155 D825 20 A5 DB jsr fp_skipchar
156
157 ;check if next char is a dot, indicating mantissa <1
158 D828 B1 F3 lda (inbuff),y
159 D82A C9 2E cmp #'.'
160 D82C D0 10 bne not_tiny
161 D82E C8 iny
162
163 ;set dot flag
164 D82F 66 E6 ror dotflag
165
166 ;increment anchor so we don't count the dot as a digit for purposes
167 ;of seeing if we got any digits
168 D831 E6 E8 inc cix0
169
170 ;skip zeroes and adjust exponent
171 D833 A9 30 lda #'0'
172 D835 tiny_denorm_loop:
173 D835 D1 F3 cmp (inbuff),y
174 D837 D0 05 bne tiny_denorm_loop_exit
175 D839 C6 D4 dec fr0
176 D83B C8 iny
177 D83C D0 F7 bne tiny_denorm_loop
178 D83E tiny_denorm_loop_exit:
179
180 D83E not_tiny:
181
182 ;grab digits left of decimal point
183 D83E A2 01 ldx #1
184 D840 nextdigit:
185 D840 B1 F3 lda (inbuff),y
186 D842 C9 45 cmp #'E'
187 D844 F0 55 beq isexp
188 D846 C8 iny
189 D847 C9 2E cmp #'.'
190 D849 F0 28 beq isdot
191 D84B 49 30 eor #'0'
192 D84D C9 0A cmp #10
193 D84F B0 2A bcs termcheck
194
195 ;write digit if we haven't exceeded digit count
196 D851 E0 06 cpx #6
197 D853 B0 15 bcs afterwrite
198
199 D855 24 EA bit digit2
200 D857 10 09 bpl writehi
201
202 ;clear second digit flag
203 D859 C6 EA dec digit2
204
205 ;merge in low digit
206 D85B 15 D4 ora fr0,x
207 D85D 95 D4 sta fr0,x
208
209 ;advance to next byte
210 D85F E8 inx
211 D860 D0 08 bne afterwrite
212
213 D862 writehi:
214 ;set second digit flag
215 D862 E6 EA inc digit2
216
217 ;shift digit to high nibble and write
218 D864 0A asl
219 D865 0A asl
220 D866 0A asl
221 D867 0A asl
222 D868 95 D4 sta fr0,x
223
224 D86A afterwrite:
225 ;adjust digit exponent if we haven't seen a dot yet
226 D86A 24 E6 bit dotflag
227 D86C 30 02 E6 D4 smi:inc fr0
228
229 ;go back for more
230 D870 4C 40 D8 jmp nextdigit
231
232 D873 isdot:
233 D873 A5 E6 lda dotflag
234 D875 D0 04 bne termcheck
235
236 ;set the dot flag and loop back for more
237 D877 66 E6 ror dotflag
238 D879 D0 C5 bne nextdigit
239
240 D87B termcheck:
241 D87B 88 dey
242 D87C C4 E8 cpy cix0
243 D87E F0 1A beq err_carryset
244 D880 term:
245 ;stash offset
246 D880 84 F2 sty cix
247
248 D882 term_rollback_exp:
249 ;divide digit exponent by two and merge in sign
250 D882 26 E9 rol sign
251 D884 66 D4 ror fr0
252
253 ;check if we need a one digit shift
254 D886 B0 0F bcs nodigitshift
255
256 ;shift right one digit
257 D888 A2 04 ldx #4
258 D88A digitshift:
259 D88A 46 D5 lsr fr0+1
260 D88C 66 D6 ror fr0+2
261 D88E 66 D7 ror fr0+3
262 D890 66 D8 ror fr0+4
263 D892 66 D9 ror fr0+5
264 D894 CA dex
265 D895 D0 F3 bne digitshift
266
267 D897 nodigitshift:
268 D897 4C 00 DC jmp fp_normalize
269
270 D89A err_carryset:
271 D89A 60 rts
272
273 D89B isexp:
274 D89B C4 E8 cpy cix0
275 D89D F0 FB beq err_carryset
276
277 ;save off this point as a fallback in case we don't actually have
278 ;exponential notation
279 D89F 84 F2 sty cix
280
281 ;check for sign
282 D8A1 A2 00 ldx #0
283 D8A3 C8 iny
284 D8A4 B1 F3 lda (inbuff),y
285 D8A6 C9 2B cmp #'+'
286 D8A8 F0 05 beq isexpplus
287 D8AA C9 2D cmp #'-'
288 D8AC D0 02 bne postexpsign
289 D8AE CA dex ;x=$ff
290 D8AF isexpplus:
291 D8AF C8 iny
292 D8B0 postexpsign:
293 D8B0 86 E7 stx xinvert
294
295 ;pull up to two exponent digits -- check first digit
296 D8B2 20 B1 DB jsr fp_isdigit_y
297 D8B5 C8 iny
298 D8B6 B0 CA bcs term_rollback_exp
299
300 ;stash first digit
301 D8B8 AA tax
302
303 ;check for another digit
304 D8B9 20 B1 DB jsr fp_isdigit_y
305 D8BC B0 05 bcs notexpzero2
306 D8BE C8 iny
307
308 D8BF 7D 39 DA adc fp_mul10,x
309 D8C2 AA tax
310 D8C3 notexpzero2:
311 D8C3 8A txa
312
313 ;zero is not a valid exponent
314 D8C4 F0 BC beq term_rollback_exp
315
316 ;check if mantissa is zero -- if so, don't bias
317 ; ldx fr0+1
318 ; beq term
319
320 ;apply sign to exponent
321 D8C6 45 E7 eor xinvert
322 D8C8 26 E7 rol xinvert
323
324 ;bias digit exponent
325 D8CA 65 D4 adc fr0
326 D8CC 85 D4 sta fr0
327 D8CE expterm:
328 D8CE 4C 80 D8 jmp term
329
330 .endp
331
332 ;==========================================================================
333 D8D1 .proc fp_fmul_carryup
334 D8D1 round_loop:
335 D8D1 75 D4 adc fr0,x
336 D8D3 95 D4 sta fr0,x
337 D8D5 dec_entry:
338 D8D5 CA dex
339 D8D6 A9 00 lda #0
340 D8D8 B0 F7 bcs round_loop
341 D8DA 60 rts
342 .endp
343
344 ;==========================================================================
345 D8DB .proc fp_tab_lo_100
346 D8DB 00 64 C8 2C 90 F4 + :10 dta <[100*#]
347 .endp
348
349 ;==========================================================================
350 D8E5 fixadr $d8e6
Macro: FIXADR [Source: source/Shared/mathpack.s]
2 .print ($D8E6-*),' bytes free before ',$D8E6
2 $0001 bytes free before $D8E6
3 D8E5 org $D8E6
Source: source/Shared/mathpack.s
351 = D8E6 _fasc = fasc
352 D8E6 .proc fasc
353 = 00F7 dotcntr = ztemp4
354 = 00F8 expval = ztemp4+1
355 = 00F9 trimbase = ztemp4+2
356 D8E6 20 51 DA jsr ldbufa
357 D8E9 A0 00 ldy #0
358
359 ;read exponent and check if number is zero
360 D8EB A5 D4 lda fr0
361 D8ED D0 05 bne notzero
362
363 D8EF A9 B0 lda #$b0
364 D8F1 91 F3 sta (inbuff),y
365 D8F3 60 rts
366
367 D8F4 notzero:
368 D8F4 84 F8 sty expval
369 D8F6 84 F9 sty trimbase
370
371 ;insert sixth mantissa byte
372 D8F8 84 D4 sty fr0
373
374 ;check if number is negative
375 D8FA 10 0A bpl ispos
376 D8FC A2 2D ldx #'-'
377 D8FE C6 F3 dec inbuff
378 D900 8E 7F 05 stx lbuff-1
379 D903 E6 F9 inc trimbase
380 D905 C8 iny
381 D906 ispos:
382
383 ;set up for 5 mantissa bytes
384 D906 A2 FB ldx #-5
385
386 ;compute digit offset to place dot
387 ; 0.001 (10.0E-04) = 3E 10 00 00 00 00 -> -1
388 ; 0.01 ( 1.0E-02) = 3F 01 00 00 00 00 -> 1
389 ; 0.1 (10.0E-02) = 3F 10 00 00 00 00 -> 1
390 ; 1.0 ( 1.0E+00) = 40 01 00 00 00 00 -> 3
391 ; 10.0 (10.0E+00) = 40 10 00 00 00 00 -> 3
392 ; 100.0 ( 1.0E+02) = 40 01 00 00 00 00 -> 5
393 ; 1000.0 (10.0E+02) = 40 10 00 00 00 00 -> 5
394
395 D908 0A asl
396 D909 38 sec
397 D90A E9 7D sbc #125
398
399 ;check if we should go to exponential form (exp >= 10 or <=-3)
400 D90C C9 0C cmp #12
401 D90E 90 0A bcc noexp
402
403 ;yes - compute and stash explicit exponent
404 D910 E9 02 sbc #2 ;!! - carry set from BCC fail
405 D912 85 F8 sta expval ;$0A <= expval < $FE
406
407 ;reset dot counter
408 D914 A9 02 lda #2
409
410 ;exclude first two digits from zero trim
411 D916 E6 F9 inc trimbase
412 D918 E6 F9 inc trimbase
413
414 D91A noexp:
415 ;check if number is less than 1.0 and init dot counter
416 D91A C9 02 cmp #2
417 D91C B0 03 bcs not_tiny
418
419 ;use sixth mantissa byte
420 D91E 69 02 adc #2
421 D920 CA dex
422 D921 not_tiny:
423 D921 85 F7 sta dotcntr ;$02 <= dotcntr < $0C
424
425 ;check if number begins with a leading zero
426 D923 B5 DA lda fr0+6,x
427 D925 C9 10 cmp #$10
428 D927 B0 0C bcs digitloop
429
430 D929 C6 F9 dec trimbase
431
432 ;yes - skip the high digit
433 D92B 46 F8 lsr expval
434 D92D 06 F8 asl expval
435 D92F D0 18 bne writelow
436 D931 C6 F7 dec dotcntr
437 D933 90 14 bcc writelow
438
439 ;write out mantissa digits
440 D935 digitloop:
441 D935 C6 F7 dec dotcntr
442 D937 D0 05 bne no_hidot
443 D939 A9 2E lda #'.'
444 D93B 91 F3 sta (inbuff),y
445 D93D C8 iny
446 D93E no_hidot:
447
448 ;write out high digit
449 D93E B5 DA lda fr0+6,x
450 D940 4A lsr
451 D941 4A lsr
452 D942 4A lsr
453 D943 4A lsr
454 D944 09 30 ora #$30
455 D946 91 F3 sta (inbuff),y
456 D948 C8 iny
457
458 D949 writelow:
459 ;write out low digit
460 D949 C6 F7 dec dotcntr
461 D94B D0 05 bne no_lodot
462 D94D A9 2E lda #'.'
463 D94F 91 F3 sta (inbuff),y
464 D951 C8 iny
465 D952 no_lodot:
466
467 D952 B5 DA lda fr0+6,x
468 D954 29 0F and #$0f
469 D956 09 30 ora #$30
470 D958 91 F3 sta (inbuff),y
471 D95A C8 iny
472
473 ;next digit
474 D95B E8 inx
475 D95C D0 D7 bne digitloop
476
477 ;skip trim if dot hasn't been written
478 D95E A5 F7 lda dotcntr
479 D960 10 11 bpl skip_zero_trim
480
481 ;trim off leading zeroes
482 D962 A9 30 lda #'0'
483 D964 lzloop:
484 D964 C4 F9 cpy trimbase
485 D966 F0 05 beq stop_zero_trim
486 D968 88 dey
487 D969 D1 F3 cmp (inbuff),y
488 D96B F0 F7 beq lzloop
489
490 ;trim off dot
491 D96D stop_zero_trim:
492 D96D B1 F3 lda (inbuff),y
493 D96F C9 2E cmp #'.'
494 D971 D0 03 bne no_trailing_dot
495
496 D973 skip_zero_trim:
497 D973 88 dey
498 D974 B1 F3 lda (inbuff),y
499 D976 no_trailing_dot:
500
501 ;check if we have an exponent to deal with
502 D976 A6 F8 ldx expval
503 D978 F0 26 beq noexp2
504
505 ;print an 'E'
506 D97A A9 45 lda #'E'
507 D97C C8 iny
508 D97D 91 F3 sta (inbuff),y
509
510 ;check for a negative exponent
511 D97F 8A txa
512 D980 10 07 bpl exppos
513 D982 49 FF eor #$ff
514 D984 AA tax
515 D985 E8 inx
516 D986 A9 2D lda #'-'
517 D988 2C dta {bit $0100}
518 D989 exppos:
519 D989 A9 2B lda #'+'
520 D98B expneg:
521 D98B C8 iny
522 D98C 91 F3 sta (inbuff),y
523
524 ;print tens digit, if any
525 D98E 8A txa
526 D98F 38 sec
527 D990 A2 2F ldx #$2f
528 D992 tensloop:
529 D992 E8 inx
530 D993 E9 0A sbc #10
531 D995 B0 FB bcs tensloop
532 D997 48 pha
533 D998 8A txa
534 D999 C8 iny
535 D99A 91 F3 sta (inbuff),y
536 D99C 68 pla
537 D99D 69 3A adc #$3a
538 D99F C8 iny
539 D9A0 noexp2:
540 ;set high bit on last char
541 D9A0 09 80 ora #$80
542 D9A2 91 F3 sta (inbuff),y
543 D9A4 60 rts
544 .endp
545
546 ;==========================================================================
547 ; IPF [D9AA] Convert 16-bit integer at FR0 to FP
548 ;
549 ; !NOTE! Cannot use FR2/FR3 -- MAC/65 requires that $DE-DF be preserved.
550 ;
551 D9A5 fixadr $d9aa
Macro: FIXADR [Source: source/Shared/mathpack.s]
2 .print ($D9AA-*),' bytes free before ',$D9AA
2 $0005 bytes free before $D9AA
3 D9A5 org $D9AA
Source: source/Shared/mathpack.s
552 D9AA .proc ipf
553 D9AA F8 sed
554
555 D9AB A2 D6 ldx #fr0+2
556 D9AD A0 05 ldy #5
557 D9AF 20 48 DA jsr zfl
558
559 D9B2 A0 10 ldy #16
560 D9B4 byteloop:
561 ;shift out binary bit
562 D9B4 06 D4 asl fr0
563 D9B6 26 D5 rol fr0+1
564
565 ;shift in BCD bit
566 D9B8 A5 D8 lda fr0+4
567 D9BA 65 D8 adc fr0+4
568 D9BC 85 D8 sta fr0+4
569 D9BE A5 D7 lda fr0+3
570 D9C0 65 D7 adc fr0+3
571 D9C2 85 D7 sta fr0+3
572 D9C4 26 D6 rol fr0+2
573
574 D9C6 88 dey
575 D9C7 D0 EB bne byteloop
576
577 D9C9 A9 43 lda #$43
578 D9CB 85 D4 sta fr0
579
580 D9CD 4C FF DB jmp fp_normalize_cld
581 .endp
582
583 ;==========================================================================
584 ; FPI [D9D2] Convert FR0 to 16-bit integer at FR0 with rounding
585 ;
586 ; This cannot overwrite FR1. Darg relies on being able to stash a value
587 ; there across a call to FPI in its startup.
588 ;
589 D9D0 fixadr $d9d2
Macro: FIXADR [Source: source/Shared/mathpack.s]
2 .print ($D9D2-*),' bytes free before ',$D9D2
2 $0002 bytes free before $D9D2
3 D9D0 org $D9D2
Source: source/Shared/mathpack.s
590 D9D2 .nowarn .proc fpi
591 = 00E6 _acc0 = fr2
592 = 00E7 _acc1 = fr2+1
593
594 ;error out if it's guaranteed to be too big or negative (>999999)
595 D9D2 A5 D4 lda fr0
596 D9D4 C9 43 cmp #$43
597 D9D6 B0 60 bcs err
598
599 ;zero number if it's guaranteed to be too small (<0.01)
600 D9D8 E9 3E sbc #$3f-1 ;!!- carry is clear
601 D9DA 90 68 bcc zfr0
602
603 D9DC AA tax
604
605 ;clear temp accum and set up rounding
606 D9DD A9 00 lda #0
607 D9DF B4 D5 ldy fr0+1,x
608 D9E1 C0 50 cpy #$50
609 D9E3 2A rol ;!! - clears carry too
610 D9E4 85 D4 sta fr0
611 D9E6 A9 00 lda #0
612
613 ;check for [0.01, 1)
614 D9E8 CA dex
615 D9E9 30 4B bmi done
616
617 ;convert ones/tens digit pair to binary (one result byte: 0-100)
618 D9EB B5 D5 lda fr0+1,x
619 D9ED 20 CD DA jsr fp_dectobin
620 D9F0 65 D4 adc fr0
621 D9F2 79 F6 DF adc fp_dectobin_tab,y
622 D9F5 18 clc
623 D9F6 85 D4 sta fr0
624 D9F8 A9 00 lda #0
625
626 ;check if we're done
627 D9FA CA dex
628 D9FB 30 39 bmi done
629
630 ;convert hundreds/thousands digit pair to binary (two result bytes: 0-10000)
631 D9FD B5 D5 lda fr0+1,x
632 D9FF 20 CD DA jsr fp_dectobin
633 DA02 A5 D4 lda fr0
634 DA04 79 48 DF adc fp_tab_lo_1000,y
635 DA07 85 D4 sta fr0
636 DA09 B9 52 DF lda fp_tab_hi_1000,y
637 DA0C 69 00 adc #0
638 DA0E 48 pha
639 DA0F B5 D5 lda fr0+1,x
640 DA11 29 0F and #$0f
641 DA13 A8 tay
642 DA14 A5 D4 lda fr0
643 DA16 79 DB D8 adc fp_tab_lo_100,y
644 DA19 85 D4 sta fr0
645 DA1B 68 pla
646 DA1C 79 5C DF adc fp_tab_hi_100,y
647
648 ;check if we're done
649 DA1F CA dex
650 DA20 30 14 bmi done
651
652 ;convert ten thousands digit pair to binary (two result bytes: 0-100000, overflow possible)
653 DA22 B4 D5 ldy fr0+1,x
654 DA24 C0 07 cpy #$07
655 DA26 B0 10 bcs err
656 DA28 AA tax
657 DA29 98 tya
658 DA2A 0A asl
659 DA2B 0A asl
660 DA2C 0A asl
661 DA2D 0A asl
662 DA2E 65 D4 adc fr0
663 DA30 85 D4 sta fr0
664 DA32 8A txa
665 DA33 79 65 DF adc fp_tab_hi_10000-1,y
666
667 DA36 done:
668 ;move result back to FR0, with rounding
669 DA36 85 D5 sta fr0+1
670 DA38 err:
671 DA38 60 rts
672 .endp
673
674 ;==========================================================================
675 DA39 fp_mul10:
676 DA39 00 0A 14 1E 28 32 + dta 0,10,20,30,40,50,60,70,80,90
677
678 ;==========================================================================
679 ; ZFR0 [DA44] Zero FR0
680 ; ZF1 [DA46] Zero float at (X)
681 ; ZFL [DA48] Zero float at (X) with length Y (UNDOCUMENTED)
682 ;
683 DA43 fixadr $da44
Macro: FIXADR [Source: source/Shared/mathpack.s]
2 .print ($DA44-*),' bytes free before ',$DA44
2 $0001 bytes free before $DA44
3 DA43 org $DA44
Source: source/Shared/mathpack.s
684 DA44 zfr0:
685 DA44 A2 D4 ldx #fr0
686 DA46 ckaddr $da46
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
687 DA46 zf1:
688 DA46 A0 06 ldy #6
689 DA48 ckaddr $da48
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
690 DA48 zfl:
691 DA48 A9 00 lda #0
692 DA4A zflloop:
693 DA4A 95 00 sta 0,x
694 DA4C E8 inx
695 DA4D 88 dey
696 DA4E D0 FA bne zflloop
697 DA50 60 rts
698
699 ;==========================================================================
700 ; LDBUFA [DA51] Set LBUFF to #INBUFF (UNDOCUMENTED)
701 ;
702 DA51 fixadr $da51
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
703 DA51 ldbufa:
704 DA51 A9 80 85 F3 A9 05 + mwa #lbuff inbuff
705 DA59 60 rts
706
707 ;==========================================================================
708 ; FPILL_SHL16 [DA5A] Shift left 16-bit word at $F7:F8 (UNDOCUMENTED)
709 ;
710 ; Illegal entry point used by MAC/65 when doing hex conversion.
711 ;
712 ; Yes, even the byte ordering is wrong.
713 ;
714 DA5A fixadr $da5a
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
715
716 DA5A .nowarn .proc fpill_shl16
717 DA5A 06 F8 asl $f8
718 DA5C 26 F7 rol $f7
719 DA5E 60 rts
720 .endp
721
722 ;** 1 byte free**
723
724 ;==========================================================================
725 ; FSUB [DA60] Subtract FR1 from FR0; FR1 is altered
726 ; FADD [DA66] Add FR1 to FR0; FR1 is altered
727 DA5F fixadr $da60
Macro: FIXADR [Source: source/Shared/mathpack.s]
2 .print ($DA60-*),' bytes free before ',$DA60
2 $0001 bytes free before $DA60
3 DA5F org $DA60
Source: source/Shared/mathpack.s
728 = DA66 fadd = fsub._fadd
729 DA60 .proc fsub
730
731 = 00E0 _diffmode = fr1
732
733 ;toggle sign on FR1
734 DA60 A5 E0 lda fr1
735 DA62 49 80 eor #$80
736 DA64 85 E0 sta fr1
737
738 ;fall through to FADD
739
740 DA66 ckaddr $da66
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
741 DA66 _fadd:
742 ;if fr1 is zero, we're done
743 DA66 A5 E0 lda fr1
744 DA68 F0 4E beq sum_xit
745
746 ;if fr0 is zero, swap
747 DA6A A5 D4 lda fr0
748 DA6C F0 0E beq swap
749
750 ;compute difference in exponents, ignoring sign
751 DA6E A5 E0 lda fr1 ;load fr1 sign
752 DA70 45 D4 eor fr0 ;compute fr0 ^ fr1 signs
753 DA72 29 80 and #$80 ;mask to just sign
754 DA74 AA tax
755 DA75 45 E0 eor fr1 ;flip fr1 sign to match fr0
756 DA77 18 clc
757 DA78 E5 D4 sbc fr0 ;compute difference in exponents - 1
758 DA7A 90 05 bcc noswap
759
760 ;swap FR0 and FR1
761 DA7C swap:
762 DA7C 20 74 DD jsr fp_swap
763
764 ;loop back and retry
765 DA7F 30 E5 bmi _fadd
766
767 DA81 noswap:
768 ;A = FR1 - FR0 - 1
769 ;X = add/sub flag
770
771 ;compute positions for add/subtract
772 DA81 69 06 adc #6 ;A = (FR1) - (FR0) + 6 !! carry is clear coming in
773 DA83 A8 tay
774
775 ;check if FR1 is too small in magnitude to matter
776 DA84 30 32 bmi sum_xit
777
778 ;jump to decimal mode and prepare for add/sub loops
779 DA86 F8 sed
780
781 ;check if we are doing a sum or a difference
782 DA87 E0 80 cpx #$80
783 DA89 A2 05 ldx #5
784 DA8B B0 2E bcs do_subtract
785
786 ;set up rounding
787 DA8D A9 00 lda #0
788 DA8F C0 05 cpy #5
789 DA91 B0 03 bcs add_no_round
790 DA93 B9 E1 00 lda fr1+1,y
791 DA96 add_no_round:
792 DA96 C9 50 cmp #$50
793
794 ;add mantissas
795 DA98 98 tya
796 DA99 F0 0B beq post_add_loop
797 DA9B add_loop:
798 DA9B B9 E0 00 lda fr1,y
799 DA9E 75 D4 adc fr0,x
800 DAA0 95 D4 sta fr0,x
801 DAA2 CA dex
802 DAA3 88 dey
803 DAA4 D0 F5 bne add_loop
804 DAA6 post_add_loop:
805
806 ;check if we had a carry out
807 DAA6 90 10 bcc sum_xit
808
809 ;carry it up
810 DAA8 B0 08 bcs sum_carryloop_start
811 DAAA sum_carryloop:
812 DAAA B5 D5 lda fr0+1,x
813 DAAC 69 00 adc #0
814 DAAE 95 D5 sta fr0+1,x
815 DAB0 90 06 bcc sum_xit
816 DAB2 sum_carryloop_start:
817 DAB2 CA dex
818 DAB3 10 F5 bpl sum_carryloop
819
820 DAB5 20 6A DE jsr fp_carry_expup
821
822 DAB8 sum_xit:
823 ;exit decimal mode
824 ;normalize if necessary and exit (needed for borrow, as well to check over/underflow)
825 DAB8 4C FF DB jmp fp_normalize_cld
826
827 DABB do_subtract:
828 ;subtract FR0 and FR1 mantissas (!! carry is set coming in)
829 DABB 84 E0 sty fr1
830 DABD B0 08 bcs sub_loop_entry
831 DABF sub_loop:
832 DABF B5 D4 lda fr0,x
833 DAC1 F9 E1 00 sbc fr1+1,y
834 DAC4 95 D4 sta fr0,x
835 DAC6 CA dex
836 DAC7 sub_loop_entry:
837 DAC7 88 dey
838 DAC8 10 F5 bpl sub_loop
839 DACA 4C 5E DC jmp fp_fsub_cont
840 .endp
841
842 ;==========================================================================
843 ; Entry:
844 ; A = BCD value
845 ; P.D = clear
846 ;
847 ; Exit:
848 ; A = binary value
849 ; Y = modified
850 ;
851 DACD .proc fp_dectobin
852 DACD 48 pha
853 DACE 4A lsr
854 DACF 4A lsr
855 DAD0 4A lsr
856 DAD1 4A lsr
857 DAD2 A8 tay
858 DAD3 68 pla
859 = DAD4 .def :fp_exit_success
860 DAD4 18 clc
861 DAD5 60 rts
862 .endp
863
864 ;==========================================================================
865 ; FMUL [DADB]: Multiply FR0 * FR1 -> FR0
866 ;
867 DAD6 fixadr $dad6
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
868 DAD6 fp_fld1r_const_fmul:
869 DAD6 A0 DB ldy #>fpconst_ten
870 DAD8 fp_fld1r_fmul:
871 DAD8 20 98 DD jsr fld1r
872 DADB ckaddr $dadb
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
873 DADB .proc fmul
874
875 ;We use FR0:FR3 as a double-precision accumulator, and copy the
876 ;original multiplicand value in FR0 to FR1. The multiplier in
877 ;FR1 is converted to binary digit pairs into FR2.
878
879 = 00DF _offset = _fr3+5
880 = 00E6 _offset2 = fr2
881
882 ;if FR0 is zero, we're done
883 DADB A5 D4 lda fr0
884 DADD F0 F5 beq fp_exit_success
885
886 ;if FR1 is zero, zero FR0 and exit
887 DADF A5 E0 lda fr1
888 DAE1 18 clc
889 DAE2 F0 17 beq fp_exit_zero
890
891 ;move fr0 to fr2
892 DAE4 20 79 DE jsr fp_fmul_fr0_to_binfr2
893
894 ;compute new exponent and stash
895 DAE7 A5 E0 lda fr1
896 DAE9 18 clc
897 DAEA 20 03 DB jsr fp_adjust_exponent.fmul_entry
898
899 DAED 85 D4 sta fr0
900 DAEF E6 D4 inc fr0
901
902 ;clear accumulator through to exponent byte of fr1
903 DAF1 A2 D5 ldx #fr0+1
904 DAF3 A0 0C ldy #12
905 DAF5 F8 sed
906
907 DAF6 4C C3 DC jmp fp_fmul_innerloop
908 .endp
909
910 DAF9 underflow_overflow:
911 DAF9 68 pla
912 DAFA 68 pla
913 DAFB fp_exit_zero:
914 DAFB 4C 44 DA jmp zfr0
915
916 DAFE .proc fp_adjust_exponent
917 DAFE fdiv_entry:
918 DAFE A5 E0 lda fr1
919 DB00 49 7F eor #$7f
920 DB02 38 sec
921 DB03 fmul_entry:
922 ;stash modified exp1
923 DB03 AA tax
924
925 ;compute new sign
926 DB04 45 D4 eor fr0
927 DB06 29 80 and #$80
928 DB08 85 E0 sta fr1
929
930 ;merge exponents
931 DB0A 8A txa
932 DB0B 65 D4 adc fr0
933 DB0D AA tax
934 DB0E 45 E0 eor fr1
935
936 ;check for underflow/overflow
937 DB10 C9 4F cmp #128-49
938 DB12 90 E5 bcc underflow_overflow
939
940 DB14 C9 B1 cmp #128+49
941 DB16 B0 E1 bcs underflow_overflow
942
943 ;rebias exponent
944 DB18 8A txa
945 DB19 E9 3F sbc #$40-1 ;!! - C=0 from bcs fail
946 DB1B 60 rts
947 .endp
948
949 ;==========================================================================
950 DB1C .pages 1 ;optimized by fp_fld1r_const_fmul
951
952 DB1C fpconst_ten:
953 DB1C 40 10 00 00 00 00 .fl 10
954
955 DB22 fpconst_ln10:
956 DB22 40 02 30 25 85 09 .fl 2.3025850929940456840179914546844
957
958 DB28 .endpg
959 ;==========================================================================
960 ; FDIV [DB28] Divide FR0 / FR1 -> FR0
961 ;
962 ; Compatibility:
963 ; - It is important that FDIV rounds if FADD/FMUL do. Otherwise, some
964 ; forms of square root computation can have a slight error on integers,
965 ; which breaks TICKTOCK.BAS.
966 ;
967 DB28 fixadr $db28
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
968 DB28 .proc fdiv
969 = 00DB _digit = _fr3+1
970 = 00DC _index = _fr3+2
971 ;check if divisor is zero
972 DB28 A5 E0 lda fr1
973 DB2A F0 72 beq err
974
975 ;check if dividend is zero
976 DB2C A5 D4 lda fr0
977 DB2E F0 6C beq ok
978
979 ;compute new exponent
980 DB30 20 FE DA jsr fp_adjust_exponent.fdiv_entry
981
982 DB33 20 2D DC jsr fp_fdiv_init
983
984 DB36 digitloop:
985 ;just keep going if we're accurate
986 DB36 A5 D4 lda fr0
987 DB38 05 D5 ora fr0+1
988 DB3A F0 3D beq nextdigit
989
990 ;check if we should either divide or add based on current sign (stored in carry)
991 DB3C 90 05 bcc incloop
992
993 DB3E 20 B9 DB jsr fp_fdiv_decloop
994 DB41 90 36 bcc nextdigit
995
996 DB43 incloop:
997 ;decrement quotient mantissa byte
998 DB43 A9 00 lda #0
999 DB45 E5 DB sbc _digit
1000 DB47 A6 DC ldx _index
1001 DB49 downloop:
1002 DB49 75 ED adc fr2+7,x
1003 DB4B 95 ED sta fr2+7,x
1004 DB4D A9 99 lda #$99
1005 DB4F CA dex
1006 DB50 90 F7 bcc downloop
1007
1008 ;add mantissas
1009 DB52 18 clc
1010 .rept 6
1011 LDA FR0+(5-#)
1012 ADC FR1+(5-#)
1013 STA FR0+(5-#)
1014 .ENDR
1014 .endr
Source: REPT
1011 DB53 A5 D9 LDA FR0+(5-#)
1011 DB55 65 E5 ADC FR1+(5-#)
1011 DB57 85 D9 STA FR0+(5-#)
1011 DB59 A5 D8 LDA FR0+(5-#)
1011 DB5B 65 E4 ADC FR1+(5-#)
1011 DB5D 85 D8 STA FR0+(5-#)
1011 DB5F A5 D7 LDA FR0+(5-#)
1011 DB61 65 E3 ADC FR1+(5-#)
1011 DB63 85 D7 STA FR0+(5-#)
1011 DB65 A5 D6 LDA FR0+(5-#)
1011 DB67 65 E2 ADC FR1+(5-#)
1011 DB69 85 D6 STA FR0+(5-#)
1011 DB6B A5 D5 LDA FR0+(5-#)
1011 DB6D 65 E1 ADC FR1+(5-#)
1011 DB6F 85 D5 STA FR0+(5-#)
1011 DB71 A5 D4 LDA FR0+(5-#)
1011 DB73 65 E0 ADC FR1+(5-#)
1011 DB75 85 D4 STA FR0+(5-#)
Source: source/Shared/mathpack.s
1015
1016 ;keep going until we overflow
1017 DB77 90 CA bcc incloop
1018
1019 DB79 nextdigit:
1020 ;shift dividend (make sure to save carry state)
1021 DB79 08 php
1022 DB7A A2 04 ldx #4
1023 DB7C bitloop:
1024 DB7C 06 D9 asl fr0+5
1025 DB7E 26 D8 rol fr0+4
1026 DB80 26 D7 rol fr0+3
1027 DB82 26 D6 rol fr0+2
1028 DB84 26 D5 rol fr0+1
1029 DB86 26 D4 rol fr0
1030 DB88 CA dex
1031 DB89 D0 F1 bne bitloop
1032 DB8B 28 plp
1033
1034 ;next digit
1035 DB8C A5 DB lda _digit
1036 DB8E 49 09 eor #$09
1037 DB90 85 DB sta _digit
1038 DB92 F0 A2 beq digitloop
1039
1040 ;next quo byte
1041 DB94 E6 DC inc _index
1042 DB96 D0 9E bne digitloop
1043
1044 ;move back to fr0
1045 DB98 20 EE DB jsr fp_fdiv_complete
1046 DB9B D8 cld
1047 DB9C ok:
1048 DB9C 18 clc
1049 DB9D 60 rts
1050 DB9E err:
1051 DB9E 38 sec
1052 DB9F 60 rts
1053 .endp
1054
1055 ;==========================================================================
1056 ; SKPSPC [DBA1] Increment CIX while INBUFF[CIX] is a space
1057 DBA0 fixadr $dba1
Macro: FIXADR [Source: source/Shared/mathpack.s]
2 .print ($DBA1-*),' bytes free before ',$DBA1
2 $0001 bytes free before $DBA1
3 DBA0 org $DBA1
Source: source/Shared/mathpack.s
1058 DBA1 skpspc:
1059 DBA1 A9 20 lda #' '
1060 DBA3 A4 F2 ldy cix
1061 DBA5 fp_skipchar:
1062 DBA5 skpspc_loop:
1063 DBA5 D1 F3 cmp (inbuff),y
1064 DBA7 D0 03 bne skpspc_xit
1065 DBA9 C8 iny
1066 DBAA D0 F9 bne skpspc_loop
1067 DBAC skpspc_xit:
1068 DBAC 84 F2 sty cix
1069 DBAE 60 rts
1070
1071 ;==========================================================================
1072 ; ISDIGT [DBAF] Check if INBUFF[CIX] is a digit (UNDOCUMENTED)
1073 DBAF fixadr $dbaf
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1074 = DBAF isdigt = _isdigt
1075 DBAF .proc _isdigt
1076 DBAF A4 F2 ldy cix
1077 = DBB1 .def :fp_isdigit_y = *
1078 DBB1 B1 F3 lda (inbuff),y
1079 DBB3 38 sec
1080 DBB4 E9 30 sbc #'0'
1081 DBB6 C9 0A cmp #10
1082 DBB8 60 rts
1083 .endp
1084
1085 ;==========================================================================
1086 DBB9 .proc fp_fdiv_decloop
1087 DBB9 decloop:
1088 ;increment quotient mantissa byte
1089 DBB9 A5 DB lda fdiv._digit
1090 DBBB A6 DC ldx fdiv._index
1091 DBBD uploop:
1092 DBBD 75 ED adc fr2+7,x
1093 DBBF 95 ED sta fr2+7,x
1094 DBC1 A9 00 lda #0
1095 DBC3 CA dex
1096 DBC4 B0 F7 bcs uploop
1097
1098 ;subtract mantissas
1099 DBC6 38 sec
1100 DBC7 A5 D9 lda fr0+5
1101 DBC9 E5 E5 sbc fr1+5
1102 DBCB 85 D9 sta fr0+5
1103 DBCD A5 D8 lda fr0+4
1104 DBCF E5 E4 sbc fr1+4
1105 DBD1 85 D8 sta fr0+4
1106 DBD3 A5 D7 lda fr0+3
1107 DBD5 E5 E3 sbc fr1+3
1108 DBD7 85 D7 sta fr0+3
1109 DBD9 A5 D6 lda fr0+2
1110 DBDB E5 E2 sbc fr1+2
1111 DBDD 85 D6 sta fr0+2
1112 DBDF A5 D5 lda fr0+1
1113 DBE1 E5 E1 sbc fr1+1
1114 DBE3 85 D5 sta fr0+1
1115 DBE5 A5 D4 lda fr0
1116 DBE7 E9 00 sbc #0
1117 DBE9 85 D4 sta fr0
1118
1119 ;keep going until we underflow
1120 DBEB B0 CC bcs decloop
1121 DBED 60 rts
1122 .endp
1123
1124 DBEE .proc fp_fdiv_complete
1125 DBEE A2 E5 ldx #fr2-1
1126 DBF0 A4 DA ldy _fr3
1127 DBF2 A5 E6 lda fr2
1128 DBF4 D0 02 bne no_normstep
1129 DBF6 E8 inx
1130 DBF7 88 dey
1131 DBF8 no_normstep:
1132 DBF8 94 00 sty 0,x
1133 DBFA 4C 87 DD jmp fld0r_zp
1134 .endp
1135
1136 ;==========================================================================
1137 ; NORMALIZE [DC00] Normalize FR0 (UNDOCUMENTED)
1138 DBFD fixadr $dc00-1
Macro: FIXADR [Source: source/Shared/mathpack.s]
2 .print ($DC00-1-*),' bytes free before ',$DC00-1
2 $0002 bytes free before $DBFF
3 DBFD org $DC00-1
Source: source/Shared/mathpack.s
1139 DBFF fp_normalize_cld:
1140 DBFF D8 cld
1141 DC00 ckaddr $dc00
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1142 DC00 fp_normalize:
1143 DC00 .nowarn .proc normalize
1144 DC00 A0 05 ldy #5
1145 DC02 normloop:
1146 DC02 A5 D4 lda fr0
1147 DC04 29 7F and #$7f
1148 DC06 F0 21 beq underflow2
1149
1150 DC08 A6 D5 ldx fr0+1
1151 DC0A F0 07 beq need_norm
1152
1153 ;Okay, we're done normalizing... check if the exponent is in bounds.
1154 ;It needs to be within +/-48 to be valid. If the exponent is <-49,
1155 ;we set it to zero; otherwise, we mark overflow.
1156
1157 DC0C C9 0F cmp #64-49
1158 DC0E 90 1A bcc underflow
1159 DC10 C9 71 cmp #64+49
1160 DC12 60 rts
1161
1162 DC13 need_norm:
1163 DC13 C6 D4 dec fr0
1164 DC15 A2 FB ldx #-5
1165 DC17 normloop2:
1166 DC17 B5 DB 95 DA mva fr0+7,x fr0+6,x
1167 DC1B E8 inx
1168 DC1C D0 F9 bne normloop2
1169 DC1E 86 DA stx fr0+6
1170 DC20 88 dey
1171 DC21 D0 DF bne normloop
1172
1173 ;Hmm, we shifted out everything... must be zero; reset exponent. This
1174 ;is critical since Atari Basic depends on the exponent being zero for
1175 ;a zero result.
1176 DC23 84 D4 sty fr0
1177 DC25 84 D5 sty fr0+1
1178 DC27 xit:
1179 DC27 18 clc
1180 DC28 60 rts
1181
1182 DC29 underflow2:
1183 DC29 18 clc
1184 DC2A underflow:
1185 DC2A 4C 44 DA jmp zfr0
1186
1187 .endp
1188
1189 ;==========================================================================
1190 ; HELPER ROUTINES
1191 ;==========================================================================
1192
1193 DC2D .proc fp_fdiv_init
1194 DC2D 85 DA sta _fr3
1195
1196 DC2F A2 E6 ldx #fr2
1197 DC31 20 46 DA jsr zf1
1198 DC34 A9 50 lda #$50
1199 DC36 85 EC sta fr2+6
1200
1201 DC38 A2 00 ldx #0
1202 DC3A 86 D4 stx fr0
1203 DC3C 86 E0 stx fr1
1204
1205 ;check if dividend begins with a leading zero digit -- if so, shift it left 4
1206 ;and begin with the tens digit
1207 DC3E A5 E1 lda fr1+1
1208 DC40 C9 10 cmp #$10
1209 DC42 B0 11 bcs start_with_ones
1210
1211 DC44 A0 04 ldy #4
1212 DC46 bitloop:
1213 DC46 06 E5 asl fr1+5
1214 DC48 26 E4 rol fr1+4
1215 DC4A 26 E3 rol fr1+3
1216 DC4C 26 E2 rol fr1+2
1217 DC4E 26 E1 rol fr1+1
1218 DC50 88 dey
1219 DC51 D0 F3 bne bitloop
1220
1221 DC53 A2 09 ldx #$09
1222
1223 DC55 start_with_ones:
1224
1225 DC55 86 DB stx fdiv._digit
1226 DC57 F8 sed
1227
1228 DC58 A2 F9 ldx #0-7
1229 DC5A 86 DC stx fdiv._index
1230 DC5C 38 sec
1231 DC5D 60 rts
1232 .endp
1233
1234 ;--------------------------------------------------------------------------
1235 DC5E .proc fp_fsub_cont
1236 ;check if we had a borrow
1237 DC5E B0 1F bcs sub_xit
1238 DC60 90 08 bcc borrow_loop_start
1239
1240 ;propagate borrow up
1241 DC62 borrow_loop:
1242 DC62 B5 D5 lda fr0+1,x
1243 DC64 E9 00 sbc #0
1244 DC66 95 D5 sta fr0+1,x
1245 DC68 B0 15 bcs sub_xit
1246 DC6A borrow_loop_start:
1247 DC6A CA dex
1248 DC6B 10 F5 bpl borrow_loop
1249
1250 DC6D A2 05 ldx #5
1251 DC6F 38 sec
1252 DC70 diff_borrow:
1253 DC70 A9 00 lda #0
1254 DC72 F5 D4 sbc fr0,x
1255 DC74 95 D4 sta fr0,x
1256 DC76 CA dex
1257 DC77 D0 F7 bne diff_borrow
1258 DC79 A9 80 lda #$80
1259 DC7B 45 D4 eor fr0
1260 DC7D 85 D4 sta fr0
1261 DC7F sub_xit:
1262
1263 DC7F norm_loop:
1264 ;Check if the exponent is in bounds.
1265 ;It needs to be within +/-48 to be valid. If the exponent is <-49,
1266 ;we set it to zero. Overflow isn't possible as this is the mantissa
1267 ;subtraction path.
1268 DC7F A5 D4 lda fr0
1269 DC81 29 7F and #$7f
1270 DC83 C9 0F cmp #64-49
1271 DC85 90 1F bcc underflow
1272
1273 DC87 A6 D5 ldx fr0+1
1274 DC89 F0 0F beq need_norm
1275
1276 ;check if we need to round, i.e.:
1277 ; 2.00000000
1278 ;-0.000000005
1279 ;load rounding byte offset
1280 DC8B A6 E0 ldx fr1
1281 DC8D E0 04 cpx #4
1282 DC8F B0 06 bcs no_round
1283 DC91 B5 E2 lda fr1+2,x
1284 DC93 C9 50 cmp #$50
1285 DC95 B0 27 bcs round_up
1286 DC97 no_round:
1287
1288 DC97 18 clc
1289 DC98 D8 cld
1290 DC99 60 rts
1291
1292 DC9A need_norm:
1293 DC9A A2 FC ldx #-4
1294 DC9C scan_loop:
1295 DC9C C6 D4 dec fr0
1296 DC9E B4 DA ldy fr0+6,x
1297 DCA0 D0 08 bne found_pos
1298 DCA2 E8 inx
1299 DCA3 D0 F7 bne scan_loop
1300
1301 ;hmm... mantissa is all zero.
1302 DCA5 underflow2:
1303 DCA5 18 clc
1304 DCA6 underflow:
1305 DCA6 D8 cld
1306 DCA7 4C 44 DA jmp zfr0
1307
1308 DCAA found_pos:
1309 ;shift up mantissa
1310 DCAA A0 00 ldy #0
1311 DCAC shift_loop:
1312 DCAC B5 DA 99 D5 00 mva fr0+6,x fr0+1,y
1313 DCB1 C8 iny
1314 DCB2 E8 inx
1315 DCB3 D0 F7 bne shift_loop
1316
1317 ;clear remaining mantissa bytes
1318 DCB5 clear_loop:
1319 DCB5 96 D5 C8 stx fr0+1,y+
1320 DCB8 C0 06 cpy #6
1321 DCBA D0 F9 bne clear_loop
1322
1323 ;check if we need to round
1324
1325
1326 ;if not, loop back to check the exponent and exit
1327 ; bcc norm_loop
1328 DCBC F0 C1 beq norm_loop
1329
1330 DCBE round_up:
1331 ;jump back into fadd code to carry up and exit
1332 DCBE A2 05 ldx #5
1333 DCC0 4C AA DA jmp fsub.sum_carryloop
1334 .endp
1335
1336 ;--------------------------------------------------------------------------
1337 DCC3 .proc fp_fmul_innerloop
1338 = 00DF _offset = _fr3+5
1339 = 00E6 _offset2 = fr2
1340
1341 DCC3 20 48 DA jsr zfl
1342
1343 ;set up for 7 bits per digit pair (0-99 in 0-127)
1344 DCC6 A0 07 ldy #7
1345
1346 ;set rounding byte, assuming renormalize needed (fr0+2 through fr0+6)
1347 DCC8 A9 50 lda #$50
1348 DCCA 85 DB sta fr0+7
1349
1350 ;begin outer loop -- this is where we process one _bit_ out of each
1351 ;multiplier byte in FR2's mantissa (note that this is inverted in that
1352 ;it is bytes-in-bits instead of bits-in-bytes)
1353 DCCC offloop:
1354
1355 ;begin inner loop -- here we process the same bit in each multiplier
1356 ;byte, going from byte 5 down to byte 1
1357 DCCC A2 05 ldx #5
1358 DCCE offloop2:
1359 ;shift an inverted bit out of fr1 mantissa
1360 DCCE 56 E6 lsr fr2,x
1361 DCD0 B0 2D bcs noadd
1362
1363 ;add fr1 to fr0 at offset
1364 .rept 6
1365 LDA FR0+(5-#),X
1366 ADC FR1+(5-#)
1367 STA FR0+(5-#),X
1368 .ENDR
1368 .endr
Source: REPT
1365 DCD2 B5 D9 LDA FR0+(5-#),X
1365 DCD4 65 E5 ADC FR1+(5-#)
1365 DCD6 95 D9 STA FR0+(5-#),X
1365 DCD8 B5 D8 LDA FR0+(5-#),X
1365 DCDA 65 E4 ADC FR1+(5-#)
1365 DCDC 95 D8 STA FR0+(5-#),X
1365 DCDE B5 D7 LDA FR0+(5-#),X
1365 DCE0 65 E3 ADC FR1+(5-#)
1365 DCE2 95 D7 STA FR0+(5-#),X
1365 DCE4 B5 D6 LDA FR0+(5-#),X
1365 DCE6 65 E2 ADC FR1+(5-#)
1365 DCE8 95 D6 STA FR0+(5-#),X
1365 DCEA B5 D5 LDA FR0+(5-#),X
1365 DCEC 65 E1 ADC FR1+(5-#)
1365 DCEE 95 D5 STA FR0+(5-#),X
1365 DCF0 B5 D4 LDA FR0+(5-#),X
1365 DCF2 65 E0 ADC FR1+(5-#)
1365 DCF4 95 D4 STA FR0+(5-#),X
Source: source/Shared/mathpack.s
1369
1370 ;check if we have a carry out to the upper bytes
1371 DCF6 90 07 bcc no_carry
1372 DCF8 86 E6 stx _offset2
1373 DCFA 20 D5 D8 jsr fp_fmul_carryup.dec_entry
1374 DCFD A6 E6 ldx _offset2
1375 DCFF no_carry:
1376
1377 DCFF noadd:
1378 ;go back for next byte
1379 DCFF CA dex
1380 DD00 D0 CC bne offloop2
1381
1382 ;double fr1
1383 DD02 18 clc
1384 DD03 A5 E5 lda fr1+5
1385 DD05 65 E5 adc fr1+5
1386 DD07 85 E5 sta fr1+5
1387 DD09 A5 E4 lda fr1+4
1388 DD0B 65 E4 adc fr1+4
1389 DD0D 85 E4 sta fr1+4
1390 DD0F A5 E3 lda fr1+3
1391 DD11 65 E3 adc fr1+3
1392 DD13 85 E3 sta fr1+3
1393 DD15 A5 E2 lda fr1+2
1394 DD17 65 E2 adc fr1+2
1395 DD19 85 E2 sta fr1+2
1396 DD1B A5 E1 lda fr1+1
1397 DD1D 65 E1 adc fr1+1
1398 DD1F 85 E1 sta fr1+1
1399 DD21 A5 E0 lda fr1+0
1400 DD23 65 E0 adc fr1+0
1401 DD25 85 E0 sta fr1+0
1402
1403 ;loop back until all mantissa bytes finished
1404 DD27 88 dey
1405 DD28 D0 A2 bne offloop
1406
1407 ;check if no renormalize is needed, and if so, re-add new rounding
1408 DD2A A5 D5 lda fr0+1
1409 DD2C F0 07 beq renorm_needed
1410
1411 DD2E A9 50 lda #$50
1412 DD30 A2 06 ldx #6
1413 DD32 20 D1 D8 jsr fp_fmul_carryup
1414
1415 DD35 renorm_needed:
1416 ;all done
1417 DD35 4C FF DB jmp fp_normalize_cld
1418 .endp
1419
1420 ;==========================================================================
1421 ; PLYEVL [DD40] Eval polynomial at (X:Y) with A coefficients using FR0
1422 ;
1423 DD38 fixadr $dd3e
Macro: FIXADR [Source: source/Shared/mathpack.s]
2 .print ($DD3E-*),' bytes free before ',$DD3E
2 $0006 bytes free before $DD3E
3 DD38 org $DD3E
Source: source/Shared/mathpack.s
1424 DD3E fp_plyevl_10:
1425 DD3E A9 0A lda #10
1426 DD40 .nowarn .proc plyevl
1427 ;stash arguments
1428 DD40 86 FE stx fptr2
1429 DD42 84 FF sty fptr2+1
1430 DD44 85 EC sta _fpcocnt
1431
1432 ;copy FR0 -> PLYARG
1433 DD46 A2 E0 ldx #<plyarg
1434 DD48 A0 05 ldy #>plyarg
1435 DD4A 20 A7 DD jsr fst0r
1436
1437 DD4D 20 44 DA jsr zfr0
1438
1439 DD50 loop:
1440 ;load next coefficient and increment coptr
1441 DD50 A5 FE lda fptr2
1442 DD52 AA tax
1443 DD53 18 clc
1444 DD54 69 06 adc #6
1445 DD56 85 FE sta fptr2
1446 DD58 A4 FF ldy fptr2+1
1447 DD5A 90 02 E6 FF scc:inc fptr2+1
1448 DD5E 20 98 DD jsr fld1r
1449
1450 ;add coefficient to acc
1451 DD61 20 66 DA jsr fadd
1452 DD64 B0 0D bcs xit
1453
1454 DD66 C6 EC dec _fpcocnt
1455 DD68 F0 09 beq xit
1456
1457 ;copy PLYARG -> FR1
1458 ;multiply accumulator by Z and continue
1459 DD6A A2 E0 ldx #<plyarg
1460 DD6C A0 05 ldy #>plyarg
1461 DD6E 20 D8 DA jsr fp_fld1r_fmul
1462 DD71 90 DD bcc loop
1463 DD73 xit:
1464 DD73 60 rts
1465 .endp
1466
1467 ;==========================================================================
1468 DD74 .proc fp_swap
1469 DD74 A2 05 ldx #5
1470 DD76 swaploop:
1471 DD76 B5 D4 lda fr0,x
1472 DD78 B4 E0 ldy fr1,x
1473 DD7A 95 E0 sta fr1,x
1474 DD7C 94 D4 sty fr0,x
1475 DD7E CA dex
1476 DD7F 10 F5 bpl swaploop
1477 DD81 60 rts
1478 .endp
1479
1480 ;==========================================================================
1481 ; FLD0R [DD89] Load FR0 from (X:Y)
1482 ; FLD0P [DD8D] Load FR0 from (FLPTR)
1483 ;
1484 DD82 fixadr $dd87
Macro: FIXADR [Source: source/Shared/mathpack.s]
2 .print ($DD87-*),' bytes free before ',$DD87
2 $0005 bytes free before $DD87
3 DD82 org $DD87
Source: source/Shared/mathpack.s
1485 DD87 fld0r_zp:
1486 DD87 A0 00 ldy #0
1487 DD89 ckaddr $dd89
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1488 DD89 fld0r:
1489 DD89 86 FC stx flptr
1490 DD8B 84 FD sty flptr+1
1491 DD8D ckaddr $dd8d
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1492 DD8D fld0p:
1493 DD8D A0 05 ldy #5
1494 DD8F fld0ploop:
1495 DD8F B1 FC lda (flptr),y
1496 DD91 99 D4 00 sta fr0,y
1497 DD94 88 dey
1498 DD95 10 F8 bpl fld0ploop
1499 DD97 60 rts
1500
1501 ;==========================================================================
1502 ; FLD1R [DD98] Load FR1 from (X:Y)
1503 ; FLD1P [DD9C] Load FR1 from (FLPTR)
1504 ;
1505 DD98 fixadr $dd98
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1506 DD98 fld1r:
1507 DD98 86 FC stx flptr
1508 DD9A 84 FD sty flptr+1
1509 DD9C ckaddr $dd9c
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1510 DD9C fld1p:
1511 DD9C A0 05 ldy #5
1512 DD9E fld1ploop:
1513 DD9E B1 FC lda (flptr),y
1514 DDA0 99 E0 00 sta fr1,y
1515 DDA3 88 dey
1516 DDA4 10 F8 bpl fld1ploop
1517 DDA6 60 rts
1518
1519 ;==========================================================================
1520 ; FST0R [DDA7] Store FR0 to (X:Y)
1521 ; FST0P [DDAB] Store FR0 to (FLPTR)
1522 ;
1523 DDA7 fixadr $dda7
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1524 DDA7 fst0r:
1525 DDA7 86 FC stx flptr
1526 DDA9 84 FD sty flptr+1
1527 DDAB ckaddr $ddab
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1528 DDAB fst0p:
1529 DDAB A0 05 ldy #5
1530 DDAD fst0ploop:
1531 DDAD B9 D4 00 lda fr0,y
1532 DDB0 91 FC sta (flptr),y
1533 DDB2 88 dey
1534 DDB3 10 F8 bpl fst0ploop
1535 DDB5 60 rts
1536
1537 ;==========================================================================
1538 ; FMOVE [DDB6] Move FR0 to FR1
1539 ;
1540 DDB6 fixadr $ddb6
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1541 DDB6 fmove:
1542 DDB6 A2 05 ldx #5
1543 DDB8 fmoveloop:
1544 DDB8 B5 D4 lda fr0,x
1545 DDBA 95 E0 sta fr1,x
1546 DDBC CA dex
1547 DDBD 10 F9 bpl fmoveloop
1548 DDBF 60 rts
1549
1550 ;==========================================================================
1551 ; EXP [DDC0] Compute e^x
1552 ; EXP10 [DDCC] Compute 10^x
1553 ;
1554 DDC0 fixadr $ddc0
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1555 = DDCC exp10 = exp._exp10
1556 DDC0 .proc exp
1557 DDC0 A2 64 ldx #<fpconst_log10_e
1558 DDC2 A0 DE ldy #>fpconst_log10_e
1559 DDC4 20 98 DD jsr fld1r ;we could use fp_fld1r_fmul, but then we have a hole :(
1560 DDC7 20 DB DA jsr fmul
1561 DDCA B0 5B bcs err2
1562
1563 DDCC ckaddr $ddcc
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1564 DDCC _exp10:
1565 ;stash sign and compute abs
1566 DDCC A5 D4 lda fr0
1567 DDCE 85 EE sta _fptemp1
1568 DDD0 29 7F and #$7f
1569 DDD2 85 D4 sta fr0
1570
1571 DDD4 A0 00 ldy #0
1572
1573 ;check for |exp| >= 100 which would guarantee over/underflow
1574 DDD6 C9 40 cmp #$40
1575 DDD8 90 1E bcc abs_ok
1576 DDDA F0 08 beq abs_large
1577
1578 DDDC abs_too_big:
1579 ;okay, the |x| is too big... check if the original was negative.
1580 ;if so, zero and exit, otherwise error.
1581 DDDC A5 EE lda _fptemp1
1582 DDDE 10 47 bpl err2
1583 DDE0 18 clc
1584 DDE1 4C 44 DA jmp zfr0
1585
1586 DDE4 abs_large:
1587 ;|exp|>=1, so split it into integer/fraction
1588 DDE4 A5 D5 lda fr0+1
1589 DDE6 20 CD DA jsr fp_dectobin
1590 DDE9 79 F6 DF adc fp_dectobin_tab,y
1591 DDEC 48 pha
1592 DDED A9 00 lda #0
1593 DDEF 85 D5 sta fr0+1
1594 DDF1 85 DA sta fr0+6
1595 DDF3 20 00 DC jsr fp_normalize
1596 DDF6 68 pla
1597 DDF7 A8 tay
1598
1599 DDF8 abs_ok:
1600 ;stash integer portion of exponent
1601 DDF8 84 ED sty _fptemp0
1602
1603 ;compute approximation z = 10^y
1604 DDFA A2 28 ldx #<coeff
1605 DDFC A0 DE ldy #>coeff
1606 DDFE 20 3E DD jsr fp_plyevl_10
1607
1608 ;tweak exponent
1609 DE01 46 ED lsr _fptemp0
1610
1611 ;scale by 10 if necessary
1612 DE03 90 07 bcc even
1613 DE05 A2 1C ldx #<fpconst_ten
1614 DE07 20 D6 DA jsr fp_fld1r_const_fmul
1615 DE0A B0 D0 bcs abs_too_big
1616 DE0C even:
1617
1618 ;bias exponent
1619 DE0C A5 ED lda _fptemp0
1620 DE0E 65 D4 adc fr0
1621 DE10 C9 71 cmp #64+49
1622 DE12 B0 C8 bcs abs_too_big
1623 DE14 85 D4 sta fr0
1624
1625 ;check if we should invert
1626 DE16 26 EE rol _fptemp1
1627 DE18 90 0D bcc xit2
1628
1629 DE1A 20 B6 DD jsr fmove
1630 DE1D A2 EA ldx #<fp_one
1631 DE1F A0 DF ldy #>fp_one
1632 DE21 20 89 DD jsr fld0r
1633 DE24 4C 28 DB jmp fdiv
1634
1635 DE27 err2:
1636 DE27 xit2:
1637 DE27 60 rts
1638
1639 DE28 coeff: ;Minimax polynomial for 10^x over 0 <= x < 1
1640 DE28 3F 01 46 90 83 08 .fl 0.0146908308
1641 DE2E BE 20 05 33 11 71 .fl -0.002005331171
1642 DE34 3F 09 19 45 20 45 .fl 0.0919452045
1643 DE3A 3F 19 21 38 38 84 .fl 0.1921383884
1644 DE40 3F 54 47 32 51 97 .fl 0.5447325197
1645 DE46 40 01 17 01 82 49 .fl 1.17018250
1646 DE4C 40 02 03 47 85 80 .fl 2.03478581
1647 DE52 40 02 65 09 44 94 .fl 2.65094494
1648 DE58 40 02 30 25 85 11 .fl 2.30258512
1649 DE5E 40 01 00 00 00 00 .fl 1
1650 .endp
1651
1652 ;==========================================================================
1653 DE64 fpconst_log10_e:
1654 DE64 3F 43 42 94 48 18 .fl 0.43429448190325182765112891891661
1655
1656 DE6A .proc fp_carry_expup
1657 ;adjust exponent
1658 DE6A E6 D4 inc fr0
1659
1660 ;shift down FR0
1661 DE6C A2 04 ldx #4
1662 DE6E sum_shiftloop:
1663 DE6E B5 D4 lda fr0,x
1664 DE70 95 D5 sta fr0+1,x
1665 DE72 CA dex
1666 DE73 D0 F9 bne sum_shiftloop
1667
1668 ;add a $01 at the top
1669 DE75 E8 inx
1670 DE76 86 D5 stx fr0+1
1671 DE78 60 rts
1672 .endp
1673
1674 ;==========================================================================
1675 DE79 .proc fp_fmul_fr0_to_binfr2 ;$15 bytes
1676 DE79 A2 04 ldx #4
1677 DE7B loop:
1678 DE7B B5 D5 lda fr0+1,x
1679 DE7D 4A lsr
1680 DE7E 4A lsr
1681 DE7F 4A lsr
1682 DE80 4A lsr
1683 DE81 A8 tay
1684 DE82 18 clc
1685 DE83 B5 D5 lda fr0+1,x
1686 DE85 79 F6 DF adc fp_dectobin_tab,y
1687 DE88 49 FF eor #$ff
1688 DE8A 95 E7 sta fr2+1,x
1689 DE8C CA dex
1690 DE8D 10 EC bpl loop
1691 = DE8F .def :fp_rts1
1692 DE8F 60 rts
1693 .endp
1694
1695 ;==========================================================================
1696 ; REDRNG [DE95] Reduce range via y = (x-C)/(x+C) (undocumented)
1697 ;
1698 ; X:Y = pointer to C argument
1699 ;
1700 DE90 fixadr $de95
Macro: FIXADR [Source: source/Shared/mathpack.s]
2 .print ($DE95-*),' bytes free before ',$DE95
2 $0005 bytes free before $DE95
3 DE90 org $DE95
Source: source/Shared/mathpack.s
1701 = DE95 redrng = _redrng
1702 DE95 .proc _redrng
1703 DE95 86 FE stx fptr2
1704 DE97 84 FF sty fptr2+1
1705 DE99 20 98 DD jsr fld1r
1706 DE9C A2 E6 ldx #<fpscr
1707 DE9E A0 05 ldy #>fpscr
1708 DEA0 20 A7 DD jsr fst0r
1709 DEA3 20 66 DA jsr fadd
1710 DEA6 B0 E7 bcs fail
1711 DEA8 A2 E0 ldx #<plyarg
1712 DEAA A0 05 ldy #>plyarg
1713 DEAC 20 A7 DD jsr fst0r
1714 DEAF A2 E6 ldx #<fpscr
1715 DEB1 A0 05 ldy #>fpscr
1716 DEB3 20 89 DD jsr fld0r
1717 DEB6 A6 FE ldx fptr2
1718 DEB8 A4 FF ldy fptr2+1
1719 DEBA 20 98 DD jsr fld1r
1720 DEBD 20 60 DA jsr fsub
1721 DEC0 B0 CD bcs fail
1722 DEC2 A2 E0 ldx #<plyarg
1723 DEC4 A0 05 ldy #>plyarg
1724 DEC6 20 98 DD jsr fld1r
1725 DEC9 4C 28 DB jmp fdiv
1726
1727 = DE8F fail = fp_rts1
1728 .endp
1729
1730 ;==========================================================================
1731 ; LOG [DECD] Compute ln x
1732 ; LOG10 [DED1] Compute log10 x
1733 ;
1734 DECC fixadr $decd
Macro: FIXADR [Source: source/Shared/mathpack.s]
2 .print ($DECD-*),' bytes free before ',$DECD
2 $0001 bytes free before $DECD
3 DECC org $DECD
Source: source/Shared/mathpack.s
1735 = DED1 log10 = log._log10
1736 DECD .proc log
1737 DECD 46 EE lsr _fptemp1
1738 DECF 10 03 bpl entry
1739 DED1 ckaddr $ded1
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1740 DED1 _log10:
1741 DED1 38 sec
1742 DED2 66 EE ror _fptemp1
1743 DED4 entry:
1744 ;throw error on negative number
1745 DED4 A5 D4 lda fr0
1746 DED6 30 6E bmi err
1747
1748 ;stash exponentx2 - 128
1749 DED8 0A asl
1750 DED9 49 80 eor #$80
1751 DEDB 85 ED sta _fptemp0
1752
1753 ;raise error if argument is zero
1754 DEDD A5 D5 lda fr0+1
1755 DEDF F0 65 beq err
1756
1757 ;reset exponent so we are in 1 <= z < 100
1758 DEE1 A2 40 ldx #$40
1759 DEE3 86 D4 stx fr0
1760
1761 ;split into three ranges based on mantissa:
1762 ; 1/sqrt(10) <= x < 1: [31, 99] divide by 100
1763 ; sqrt(10)/100 <= x < 1/sqrt(10): [ 3, 30] divide by 10
1764 ; 0 < x < sqrt(10)/100: [ 1, 2] leave as-is
1765
1766 DEE5 C9 03 cmp #$03
1767 DEE7 90 13 bcc post_range_adjust
1768 DEE9 C9 31 cmp #$31
1769 DEEB 90 04 bcc mid_range
1770
1771 ;increase result by 1 (equivalent to *10 input)
1772 DEED E6 ED inc _fptemp0
1773 DEEF D0 07 bne adjust_exponent
1774
1775 DEF1 mid_range:
1776 ;multiply by 10
1777 DEF1 A2 1C ldx #<fpconst_ten
1778 DEF3 20 D6 DA jsr fp_fld1r_const_fmul
1779 DEF6 B0 4F bcs err2
1780
1781 DEF8 adjust_exponent:
1782 ;increase result by 1 (equivalent to *10 input)
1783 DEF8 E6 ED inc _fptemp0
1784
1785 ;divide fraction by 100
1786 DEFA C6 D4 dec fr0
1787
1788 DEFC post_range_adjust:
1789 ;at this point, we have 0.30 <= z <= 3; apply y = (z-1)/(z+1) transform
1790 ;so we can use a faster converging series... this reduces y to
1791 ;0 <= y < 0.81
1792 DEFC A2 EA ldx #<fp_one
1793 DEFE A0 DF ldy #>fp_one
1794 DF00 20 95 DE jsr redrng
1795
1796 ;stash y so we can later multiply it back in
1797 DF03 A2 E6 ldx #<fpscr
1798 DF05 A0 05 ldy #>fpscr
1799 DF07 20 A7 DD jsr fst0r
1800
1801 ;square the value so we compute a series on y^2n
1802 DF0A 20 B6 DD jsr fmove
1803 DF0D 20 DB DA jsr fmul
1804
1805 ;do polynomial expansion
1806 DF10 A2 72 ldx #<fpconst_log10coeff
1807 DF12 A0 DF ldy #>fpconst_log10coeff
1808 DF14 20 3E DD jsr fp_plyevl_10
1809 DF17 B0 2E bcs err2
1810
1811 ;multiply back in so we have series on y^(2n+1)
1812 DF19 A2 E6 ldx #<fpscr
1813 DF1B A0 05 ldy #>fpscr
1814 DF1D 20 D8 DA jsr fp_fld1r_fmul
1815
1816 ;stash
1817 DF20 20 B6 DD jsr fmove
1818
1819 ;convert exponent adjustment back to float (signed)
1820 DF23 A9 00 lda #0
1821 DF25 85 D5 sta fr0+1
1822 DF27 A6 ED ldx _fptemp0
1823 DF29 10 04 bpl expadj_positive
1824 DF2B 38 sec
1825 DF2C E5 ED sbc _fptemp0
1826 DF2E AA tax
1827 DF2F expadj_positive:
1828 DF2F 86 D4 stx fr0
1829 DF31 20 AA D9 jsr ipf
1830
1831 ;merge (cannot fail)
1832 DF34 06 D4 asl fr0
1833 DF36 06 ED asl _fptemp0
1834 DF38 66 D4 ror fr0
1835 DF3A 20 66 DA jsr fadd
1836
1837 ;scale if doing log
1838 DF3D 24 EE bit _fptemp1
1839 DF3F 30 06 bmi xit2
1840
1841 DF41 A2 22 ldx #<fpconst_ln10
1842 DF43 4C D6 DA jmp fp_fld1r_const_fmul
1843
1844 DF46 err:
1845 DF46 38 sec
1846 DF47 xit2:
1847 DF47 err2:
1848 DF47 60 rts
1849 .endp
1850
1851 ;==========================================================================
1852 DF48 .proc fp_tab_lo_1000
1853 DF48 00 E8 D0 B8 A0 88 + :10 dta <[1000*#]
1854 .endp
1855
1856 DF52 .proc fp_tab_hi_1000
1857 DF52 00 03 07 0B 0F 13 + :10 dta >[1000*#]
1858 .endp
1859
1860 DF5C .proc fp_tab_hi_100
1861 DF5C 00 00 00 01 01 01 + :10 dta >[100*#]
1862 .endp
1863
1864 DF66 .proc fp_tab_hi_10000
1865 DF66 27 4E 75 9C C3 EA :6 dta >[10000*[#+1]]
1866 .endp
1867
1868 ;==========================================================================
1869 ; HALF (used by Atari BASIC)
1870 ;
1871 DF6C fixadr $df6c
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1872 DF6C fpconst_half:
1873 DF6C 3F 50 00 00 00 00 .fl 0.5
1874
1875 ;==========================================================================
1876 ; log10(x) coefficients
1877 ;
1878 ; LOG10 computes:
1879 ; -0.30 <= z <= 3.0
1880 ; y = (z-1)/(z+1) -0.54 <= y <= 0.5
1881 ; x = y^2 0 <= x <= 0.29
1882 ; log10(z) = f(x)*y
1883 ;
1884 ; Therefore:
1885 ; f(x) = log10((1+y)/(1-y))/y
1886 ;
1887 DF72 fpconst_log10coeff: ;Maclaurin series expansion for log10((z-1)/(z+1))
1888 DF72 3F 20 26 22 71 53 .fl 0.2026227154
1889 DF78 BF 07 32 04 49 21 .fl -0.0732044921
1890 DF7E 3F 10 60 98 35 64 .fl 0.1060983564
1891 DF84 3F 05 60 41 73 29 .fl 0.0560417329
1892 DF8A 3F 08 04 18 84 06 .fl 0.0804188407
1893 DF90 3F 09 63 91 60 14 .fl 0.0963916015
1894 DF96 3F 12 40 89 61 35 .fl 0.1240896135
1895 DF9C 3F 17 37 17 66 45 .fl 0.1737176646
1896 DFA2 3F 28 95 29 65 58 .fl 0.2895296558
1897 DFA8 3F 86 85 88 96 37 .fl 0.8685889638
1898
1899 ;==========================================================================
1900 ; Arctangent coefficients
1901 ;
1902 ; The 11 coefficients here form a power series approximation
1903 ; f(x^2) ~= atn(x)/x. This is not an official feature of the math pack but
1904 ; is relied upon by BASIC.
1905 ;
1906 ; We used to use the coefficients from Abramowitz & Stegun 4.4.49 here, but
1907 ; there seems to be an error there such that the result falls far short
1908 ; of the specified 2x10^-8 accuracy over 0<=x<=1 at x=1. Instead, we now
1909 ; use a custom minimax polynomial for f(y)=atn(sqrt(y))/sqrt(y) where y=x^2.
1910 ;
1911 DFAE fixadr $dfae
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1912 DFAE atncoef: ;coefficients for atn(x)/x ~= f(x^2)
1913 ;see Abramowitz & Stegun 4.4.49
1914
1915 DFAE 3E 11 12 07 58 81 .fl 0.001112075881 ;x**10*1.11207588057982e-3
1916 DFB4 BE 73 04 08 75 20 .fl -0.007304087520 ;x**9*-7.30408751951452e-3
1917 DFBA 3F 02 24 96 55 73 .fl 0.0224965573 ;x**8*2.24965572957342e-2
1918 DFC0 BF 04 46 18 51 71 .fl -0.0446185172 ;x**7*-4.46185172165888e-2
1919 DFC6 3F 06 73 46 32 44 .fl 0.0673463245 ;x**6*6.73463245104305e-2
1920 DFCC BF 08 80 69 06 64 .fl -0.0880690664 ;x**5*-8.80690663570546e-2
1921 DFD2 3F 11 05 66 74 99 .fl 0.1105667499 ;x**4*1.10566749879313e-1
1922 DFD8 BF 14 27 94 93 12 .fl -0.1427949312 ;x**3*-1.42794931245212e-1
1923 DFDE 3F 19 99 96 30 60 .fl 0.1999963060 ;x**2*1.99996306023439e-1
1924 DFE4 BF 33 33 33 24 72 .fl -0.3333332472 ;x**1*-3.33333247188074e-1
1925 ;x**0*9.99999999667198e-1
1926 DFEA fp_one:
1927 DFEA 40 01 00 00 00 00 .fl 1.0 ;also an arctan coeff
1928 DFF0 fixadr $dff0
Macro: FIXADR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
1929 DFF0 fp_pi4: ;pi/4 - needed by Atari Basic ATN()
1930 DFF0 3F 78 53 98 16 34 .fl 0.78539816339744830961566084581988
1931
1932 DFF6 fp_dectobin_tab:
1933 DFF6 00 FA F4 EE E8 E2 + :10 dta <[-6*#]
1934
1935 E000 ckaddr $e000
Macro: CKADDR [Source: source/Shared/mathpack.s]
Source: source/Shared/mathpack.s
102
103 E000 org $e000
104 E000 icl 'atarifont.inc'
Source: source/Shared/atarifont.inc
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Character Font
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 E000 00 00 00 00 00 00 + ins 'atarifont.bin',$0,$400
105
106 E400 org $e400
107 E400 F9 F9 editrv dta a(EditorOpen-1)
108 E402 27 FE dta a(EditorClose-1)
109 E404 05 FA dta a(EditorGetByte-1)
110 E406 B7 FA dta a(EditorPutByte-1)
111 E408 C8 E4 dta a(EditorGetStatus-1)
112 E40A CA E4 dta a(EditorSpecial-1)
113 E40C 4C CB E4 jmp EditorInit
114 E40F 00 dta $00
115
116 E410 F5 F3 screnv dta a(ScreenOpen-1)
117 E412 27 FE dta a(ScreenClose-1)
118 E414 D1 F5 dta a(ScreenGetByte-1)
119 E416 11 F6 dta a(ScreenPutByte-1)
120 E418 C8 E4 dta a(ScreenGetStatus-1)
121 E41A F5 F6 dta a(ScreenSpecial-1)
122 E41C 20 C4 F5 jsr ScreenInit
123 E41F 00 dta $00
124
125 E420 C8 E4 keybdv dta a(KeyboardOpen-1)
126 E422 C8 E4 dta a(KeyboardClose-1)
127 E424 68 FE dta a(KeyboardGetByte-1)
128 E426 CA E4 dta a(KeyboardPutByte-1)
129 E428 C8 E4 dta a(KeyboardGetStatus-1)
130 E42A CA E4 dta a(KeyboardSpecial-1)
131 E42C 4C 3F FE jmp KeyboardInit
132 E42F 00 dta $00
133
134 E430 83 EC printv dta a(PrinterOpen-1)
135 E432 98 EC dta a(PrinterClose-1)
136 E434 CA E4 dta a(PrinterGetByte-1)
137 E436 9F EC dta a(PrinterPutByte-1)
138 E438 ED EC dta a(PrinterGetStatus-1)
139 E43A CA E4 dta a(PrinterSpecial-1)
140 E43C 20 7E EC jsr PrinterInit
141 E43F 00 dta $00
142
143 E440 19 ED casetv dta a(CassetteOpen-1)
144 E442 6E ED dta a(CassetteClose-1)
145 E444 8F ED dta a(CassetteGetByte-1)
146 E446 CF ED dta a(CassettePutByte-1)
147 E448 C8 E4 dta a(CassetteGetStatus-1)
148 E44A CA E4 dta a(CassetteSpecial-1)
149 E44C 4C 0F ED jmp CassetteInit
150 E44F 00 dta $00
151
152 ;vector table
153 E450 org $e450
154 E450 4C 0E EC diskiv jmp DiskInit ;$E450
155 E453 4C 19 EC dskinv jmp DiskHandler ;$E453
156 E456 4C FC E4 ciov jmp CIO ;$E456
157 E459 4C F6 E7 siov jmp SIO ;$E459
158 E45C 4C 5F C1 setvbv jmp VBISetVector ;$E45C
159 E45F 4C 0C C0 sysvbv jmp VBIStage1 ;$E45F
160 E462 4C 50 C0 xitvbv jmp VBIExit ;$E462
161 E465 4C EB E7 sioinv jmp SIOInit ;$E465
162 E468 4C 47 E9 sendev jmp SIOSendEnable ;$E468
163 E46B 4C 75 C1 intinv jmp IntInitInterrupts ;$E46B
164 E46E 4C EA E4 cioinv jmp CIOInit ;$E46E
165
166 .if _KERNEL_XLXE
167 E471 4C 9B E4 blkbdv jmp SelfTestEntry ;$E471
168 .else
169 blkbdv jmp Blackboard ;$E471
170 .endif
171
172 E474 4C 4F EF warmsv jmp InitWarmStart ;$E474
173 E477 4C D6 EE coldsv jmp InitColdStart ;$E477
174 E47A 4C 10 EE rblokv jmp CassetteReadBlock ;$E47A
175 E47D 4C 2D ED csopiv jmp CassetteOpenRead ;$E47D
176
177 .if _KERNEL_XLXE
178 E480 4C 9B E4 pupdiv jmp SelfTestEntry ;$E480 XL/XE: power-up display
179 E483 4C 00 50 slftsv jmp $5000 ;$E483 XL/XE: self-test entry
180 E486 4C 22 C3 pentv jmp PHAddHandler ;$E486 XL/XE: peripheral handler add
181 E489 4C 58 C3 phunlv jmp PHRemoveHandler ;$E489 XL/XE: peripheral handler remove
182 E48C 4C 9E C3 phiniv jmp PHInitHandler ;$E48C XL/XE: peripheral handler init
183 E48F gpdvv PBI_VECTOR_TABLE ;$E48F XL/XE: Generic device vector
Macro: PBI_VECTOR_TABLE [Source: source/Shared/pbi.s]
1 E48F CF C2 dta a(PBIGenericDeviceOpen-1)
2 E491 D3 C2 dta a(PBIGenericDeviceClose-1)
3 E493 D7 C2 dta a(PBIGenericDeviceGetByte-1)
4 E495 DB C2 dta a(PBIGenericDevicePutByte-1)
5 E497 19 C3 dta a(PBIGenericDeviceGetStatus-1)
6 E499 1D C3 dta a(PBIGenericDeviceSpecial-1)
Source: source/main.xasm
184 .endif
185
186 .if _KERNEL_XLXE
187 E49B icl 'selftestentry.s'
Source: source/Shared/selftestentry.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Self Test Entry Trampoline
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 E49B .proc SelfTestEntry
11 E49B AD 01 D3 lda portb
12 E49E 29 7F and #$7f
13 E4A0 8D 01 D3 sta portb
14 E4A3 4C 00 50 jmp BootScreen
15 .endp
188 .else
189 icl 'blackboard.s'
190 .endif
191
192 ;==============================================================================
193 ; $E4C0 Known RTS instruction
194 ;
195 ; The Atari 850 handler uses this as a "known RTS" instruction, as does
196 ; Altirra's internal R: handler emulation.
197 ;
198 E4A6 org $e4c0
199
200 E4C0 .nowarn .proc KnownRTS
201 E4C0 60 rts
202 .endp
203
204 ;==============================================================================
205 ; Main modules.
206 ;
207 ; We report the sizes here as well as reference sizes. The reference sizes for
208 ; OS-B come from Mapping the Atari.
209 ;
210
211 .echo 'Module sizes:'
211 Module sizes:
212
213 .macro _KERNEL_REPORT_MODULE_MARK
214 .def ?@_kernel_lastpt = *
215 .endm
216
217 .macro _KERNEL_REPORT_MODULE_PAD_ADJUST
218 .def ?@_kernel_lastpt = ?@_kernel_lastpt + :1
219 .endm
220
221 .macro _KERNEL_REPORT_MODULE_SIZE
222 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', :2, ')', ' ', :1
223
224 .def ?@_kernel_lastpt = *
225 .endm
226
227 E4C1 icl 'misc.s'
Source: source/Shared/misc.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Miscellaneous data
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 ;Used by PBI and display/editor.
12 ;
13 E4C1 .proc ReversedBitMasks
14 E4C1 80 40 20 10 08 04 + dta $80,$40,$20,$10,$08,$04,$02,$01
15 .endp
16
17 ;==========================================================================
18 ;Used by CIO devices
19 E4C9 .proc CIOExitSuccess
20 E4C9 A0 01 ldy #1
21 E4CB exit_not_supported:
22 E4CB 60 rts
23 .endp
24
25 = E4CB CIOExitNotSupported = CIOExitSuccess.exit_not_supported
26
27 ;==========================================================================
28 ; Sound a bell using the console speaker.
29 ;
30 ; Entry:
31 ; Y = duration
32 ;
33 ; Modified:
34 ; X
35 ;
36 ; Preserved:
37 ; A
38 ;
39 E4CC .proc Bell
40 E4CC 48 pha
41 E4CD A9 08 lda #$08
42 E4CF soundloop:
43 E4CF A2 04 ldx #4
44 E4D1 48 pha
45 E4D2 delay:
46 E4D2 AD 0B D4 lda vcount
47 E4D5 CD 0B D4 F0 FB cmp:req vcount
48 E4DA CA dex
49 E4DB D0 F5 bne delay
50 E4DD 68 pla
51 E4DE 49 08 eor #$08
52 E4E0 8D 1F D0 sta consol
53 E4E3 D0 EA bne soundloop
54 E4E5 88 dey
55 E4E6 D0 E7 bne soundloop
56 E4E8 68 pla
57 E4E9 60 rts
58 .endp
228 E4EA _KERNEL_REPORT_MODULE_MARK
Macro: _KERNEL_REPORT_MODULE_MARK [Source: source/main.xasm]
1 = E4EA .def ?@_kernel_lastpt = *
Source: source/main.xasm
229
230 E4EA icl 'cio.inc'
Source: source/Shared/cio.inc
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Character Input/Output Definitions
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 .ifndef f_CIO_INC
11 .def f_CIO_INC
12
13 CIOStatBreak = $80 ;break key abort
14 CIOStatIOCBInUse = $81 ;IOCB in use
15 CIOStatUnkDevice = $82 ;unknown device
16 CIOStatWriteOnly = $83 ;opened for write only
17 CIOStatInvalidCmd = $84 ;invalid command
18 CIOStatNotOpen = $85 ;device or file not open
19 CIOStatInvalidIOCB = $86 ;invalid IOCB number
20 CIOStatReadOnly = $87 ;opened for read only
21 CIOStatEndOfFile = $88 ;end of file reached
22 CIOStatTruncRecord = $89 ;record truncated
23 CIOStatTimeout = $8A ;device timeout
24 CIOStatNAK = $8B ;device NAK
25 CIOStatSerFrameErr = $8C ;serial bus framing error
26 CIOStatCursorRange = $8D ;cursor out of range
27 CIOStatSerOverrun = $8E ;serial frame overrun error
28 CIOStatSerChecksum = $8F ;serial checksum error
29 CIOStatDeviceDone = $90 ;device done error
30 CIOStatBadScrnMode = $91 ;bad screen mode
31 CIOStatNotSupported = $92 ;function not supported by handler
32 CIOStatOutOfMemory = $93 ;not enough memory
33 CIOStatDriveNumErr = $A0 ;disk drive # error
34 CIOStatTooManyFiles = $A1 ;too many open disk files
35 CIOStatDiskFull = $A2 ;disk full
36 CIOStatFatalDiskIO = $A3 ;fatal disk I/O error
37 CIOStatFileNumDiff = $A4 ;internal file # mismatch
38 CIOStatFileNameErr = $A5 ;filename error
39 CIOStatPointDLen = $A6 ;point data length error
40 CIOStatFileLocked = $A7 ;file locked
41 CIOStatInvDiskCmd = $A8 ;invalid command for disk
42 CIOStatDirFull = $A9 ;directory full (64 files)
43 CIOStatFileNotFound = $AA ;file not found
44 CIOStatInvPoint = $AB ;invalid point
45
46 CIOCmdOpen = $03
47 CIOCmdGetRecord = $05
48 CIOCmdGetChars = $07
49 CIOCmdPutRecord = $09
50 ; $0A ;PUT CHARS alias (required by K-Razy Shoot Out)
51 CIOCmdPutChars = $0B
52 CIOCmdClose = $0C
53 CIOCmdGetStatus = $0D
54 CIOCmdSpecial = $0E ;$0E and up is escape
55
56 .endif
231
232 .ifdef _KERNEL_816
233 icl 'cio816.s'
234 .else
235 E4EA icl 'cio.s'
Source: source/Shared/cio.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Character Input/Output Facility
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 E4EA .proc CIOInit
11 E4EA 38 sec
12 E4EB A2 70 ldx #$70
13 E4ED iocb_loop:
14 E4ED A9 FF lda #$ff
15 E4EF 9D 40 03 sta ichid,x
16 E4F2 20 5E E7 jsr CIOSetPutByteClosed
17 E4F5 8A txa
18 E4F6 E9 10 sbc #$10
19 E4F8 AA tax
20 E4F9 10 F2 bpl iocb_loop
21 E4FB 60 rts
22 .endp
23
24 ;==============================================================================
25 ; Character I/O entry vector
26 ;
27 ; On entry:
28 ; X = IOCB offset (# x 16)
29 ;
30 ; Returns:
31 ; A = depends on operation
32 ; X = IOCB offset (# x 16)
33 ; Y = status (reflected in P)
34 ;
35 ; Notes:
36 ; BUFADR must not be touched from CIO. DOS XE relies on this for
37 ; temporary storage and breaks if it is modified.
38 ;
39 ; XL/XE mode notes:
40 ; HNDLOD is always set to $00 afterward, per Sweet 16 supplement 3.
41 ;
42 ; CIO can optionally attempt a provisional open by doing a type 4 poll
43 ; over the SIO bus. This happens unconditionally if HNDLOD is non-zero
44 ; and only after the device is not found in HATABS if HNDLOD is zero.
45 ; If this succeeds, the IOCB is provisionally opened. Type 4 polling
46 ; ONLY happens for direct opens -- it does not happen for a soft open.
47 ;
48 E4FC .proc CIO
49 ;stash IOCB offset (X) and acc (A)
50 E4FC 85 2F sta ciochr
51 E4FE 86 2E stx icidno
52 E500 20 13 E5 jsr process
53 E503 xit:
54 ;copy status back to IOCB
55 E503 A6 2E ldx icidno
56 E505 98 tya
57 E506 9D 43 03 sta icsta,x
58 E509 08 php
59
60 .if _KERNEL_XLXE
61 E50A A9 00 8D E9 02 mva #0 hndlod
62 .endif
63
64 E50F A5 2F lda ciochr
65 E511 28 plp
66 E512 60 rts
67
68 E513 process:
69 ;validate IOCB offset
70 E513 8A txa
71 E514 29 8F and #$8f
72 E516 F0 06 beq validIOCB
73
74 ;return invalid IOCB error
75 E518 A0 86 ldy #CIOStatInvalidIOCB
76 E51A 60 rts
77
78 E51B cmdInvalid:
79 ;invalid command <$03
80 E51B A0 84 ldy #CIOStatInvalidCmd
81 E51D 60 rts
82
83 E51E validIOCB:
84 E51E 20 EB E6 jsr CIOLoadZIOCB
85
86 ;check if we're handling the OPEN command
87 E521 A5 22 lda iccomz
88 E523 C9 03 cmp #CIOCmdOpen
89 E525 F0 7B beq cmdOpen
90 E527 90 F2 bcc cmdInvalid
91
92 ;check if the IOCB is open
93 E529 A4 20 ldy ichidz
94
95 .if !_KERNEL_XLXE
96 bpl isOpen
97 .else
98 E52B 30 15 bmi not_open
99
100 ;check for a provisionally open IOCB
101 E52D C8 iny
102 E52E 10 2E bpl isOpen
103
104 ;okay, it's provisionally open... check if it's a close
105 E530 C9 0C cmp #CIOCmdClose
106 E532 D0 03 4C A2 E6 sne:jmp cmdCloseProvisional
107
108 ;check if we're allowed to load a handler
109 E537 AD E9 02 lda hndlod
110 E53A F0 06 beq not_open
111
112 ;try to load the handler
113 E53C 20 9C E7 jsr CIOLoadHandler
114 E53F 10 1D bpl isOpen
115 E541 60 rts
116 .endif
117
118 E542 not_open:
119 ;IOCB isn't open - issue error
120 ;
121 ;Special cases;
122 ; - No error issued for close ($0C). This is needed so that extra CLOSE
123 ; commands from BASIC don't trip errors.
124 ; - Get status ($0D) and special ($0E+) do soft open and close if needed.
125 ; $0D case is required for Top Dos 1.5a to boot; $0E+ case is encountered
126 ; with R: device XIO commands.
127 ;
128 E542 A0 01 ldy #1
129 E544 A5 22 lda iccomz
130 E546 C9 0C cmp #CIOCmdClose
131 E548 F0 06 beq ignoreOpen
132 E54A C9 0D cmp #CIOCmdGetStatus
133 E54C B0 03 bcs preOpen ;closed IOCB is OK for get status and special
134 E54E not_open_handler:
135 E54E A0 85 ldy #CIOStatNotOpen
136 E550 ignoreOpen:
137 E550 60 rts
138
139 E551 preOpen:
140 ;If the device is not open when a SPECIAL command is issued, parse the path
141 ;and soft-open the device in the zero page IOCB.
142 E551 20 FA E6 jsr CIOParsePath
143
144 ;check for special command
145 E554 A5 22 lda iccomz
146 E556 C9 0D cmp #CIOCmdGetStatus
147 E558 F0 40 beq cmdGetStatusSoftOpen
148 E55A C9 0E cmp #CIOCmdSpecial
149 E55C B0 3F bcs cmdSpecialSoftOpen
150
151 E55E isOpen:
152 E55E A6 22 ldx iccomz
153 E560 E0 0E cpx #CIOCmdSpecial
154 E562 90 02 A2 0E scc:ldx #$0e
155
156 ;do permissions check
157 E566 BD A9 E6 lda perm_check_table-4,x
158 E569 30 04 bmi skip_perm_check
159 E56B 24 2A bit icax1z
160 E56D F0 26 beq perm_check_fail
161 E56F skip_perm_check:
162
163 ;load command table vector
164 E56F BD CA E6 lda command_table_hi-4,x
165 E572 48 pha
166 E573 BD BF E6 lda command_table_lo-4,x
167 E576 48 pha
168
169 ;preload dispatch vector and dispatch to command
170 E577 BC B4 E6 ldy vector_preload_table-4,x
171 E57A load_vector:
172 E57A A6 20 ldx ichidz
173 E57C BD 1B 03 85 2C BD + mwa hatabs+1,x icax3z
174 E586 B1 2C lda (icax3z),y
175 E588 AA tax
176 E589 88 dey
177 E58A B1 2C lda (icax3z),y
178 E58C 85 2C sta icax3z
179 E58E 86 2D stx icax3z+1
180
181 ;many commands want to check length=0 on entry
182 E590 A5 28 lda icbllz
183 E592 05 29 ora icblhz
184 E594 60 rts
185
186 E595 perm_check_fail:
187 ;at this point we have A=$04 if we failed a get perm check, and A=$08
188 ;if we failed a put perm check -- these need to be translated to Y=$83
189 ;and Y=$87.
190 E595 18 clc
191 E596 69 7F adc #$7f
192 E598 A8 tay
193 E599 60 rts
194
195 ;--------------------------------------------------------------------------
196 E59A cmdGetStatusSoftOpen:
197 E59A A0 09 ldy #9
198 E59C 2C dta {bit $0100}
199 E59D cmdSpecialSoftOpen:
200 E59D A0 0B ldy #11
201 E59F invoke_and_soft_close_xit:
202 E59F 4C D9 E6 jmp CIOInvoke
203
204 ;--------------------------------------------------------------------------
205 ; Open command ($03).
206 ;
207 E5A2 cmdOpen:
208 ;check if the IOCB is already open
209 E5A2 A4 20 ldy ichidz
210 E5A4 C8 iny
211 E5A5 F0 03 beq notAlreadyOpen
212
213 ;IOCB is already open - error
214 E5A7 A0 81 ldy #CIOStatIOCBInUse
215 E5A9 60 rts
216
217 E5AA notAlreadyOpen:
218 ;attempt to parse and open -- note that this will fail out directly
219 ;on an unknown device or provisional open
220 E5AA 20 FA E6 jsr CIOParsePath
221
222 E5AD open_entry:
223 ;request open
224 E5AD A0 01 ldy #1
225 E5AF 20 D9 E6 jsr CIOInvoke
226
227 ;move handler ID and device number to IOCB
228 E5B2 A6 2E ldx icidno
229 E5B4 A5 20 9D 40 03 mva ichidz ichid,x
230 E5B9 A5 21 9D 41 03 mva icdnoz icdno,x
231
232 E5BE 98 tya
233 E5BF 10 01 bpl openOK
234 E5C1 60 rts
235
236 E5C2 openOK:
237
238 ;copy PUT BYTE vector for Atari Basic
239 E5C2 A6 20 ldx ichidz
240 E5C4 BD 1B 03 85 2C BD + mwa hatabs+1,x icax3z
241 E5CE A0 06 ldy #6
242 E5D0 B1 2C lda (icax3z),y
243 E5D2 A6 2E ldx icidno
244 E5D4 9D 46 03 sta icptl,x
245 E5D7 C8 iny
246 E5D8 B1 2C lda (icax3z),y
247 E5DA 9D 47 03 sta icpth,x
248 E5DD A0 01 ldy #1
249 E5DF 60 rts
250
251 = E6DC cmdGetStatus = CIOInvoke.invoke_vector
252 E5E0 cmdSpecial:
253 E5E0 20 DC E6 jsr CIOInvoke.invoke_vector
254
255 ;need to copy AUX1/2 back for R:
256 E5E3 A6 2E ldx icidno
257 E5E5 A5 2A 9D 4A 03 mva icax1z icax1,x
258 E5EA A5 2B 9D 4B 03 mva icax2z icax2,x
259 E5EF 60 rts
260
261 ;--------------------------------------------------------------------------
262 E5F0 cmdGetRecord:
263 ;check if buffer is full on entry
264 E5F0 F0 16 beq cmdGetRecordBufferFull
265 E5F2 cmdGetRecordLoop:
266 E5F2 cmdGetRecordGetByte:
267 ;fetch byte
268 E5F2 20 DC E6 jsr CIOInvoke.invoke_vector
269 E5F5 C0 00 cpy #0
270 E5F7 30 1C bmi cmdGetRecordXit
271
272 ;store byte (even if EOL)
273 E5F9 A2 00 ldx #0
274 E5FB 81 24 sta (icbalz,x)
275
276 ;check for EOL
277 E5FD 49 9B eor #$9b
278 E5FF C9 01 cmp #1
279
280 ;increment buffer pointer and decrement length
281 E601 20 8C E6 jsr advance_pointers
282
283 ;skip buffer full check if we had an EOL
284 E604 90 0F bcc cmdGetRecordXit
285
286 ;loop back for more bytes if buffer not full
287 E606 D0 EA bne cmdGetRecordLoop
288
289 E608 cmdGetRecordBufferFull:
290 ;read byte to discard
291 E608 20 DC E6 jsr CIOInvoke.invoke_vector
292 E60B C0 00 cpy #0
293 E60D 30 06 bmi cmdGetRecordXit
294
295 ;continue if not EOL
296 E60F C9 9B cmp #$9b
297 E611 D0 F5 bne cmdGetRecordBufferFull
298
299 ;return truncated record
300 E613 A0 89 ldy #CIOStatTruncRecord
301
302 E615 cmdGetRecordXit:
303 E615 cmdGetPutDone:
304 ;update byte count in IOCB
305 E615 A6 2E ldx icidno
306 E617 38 sec
307 E618 BD 48 03 lda icbll,x
308 E61B E5 28 sbc icbllz
309 E61D 85 28 sta icbllz ;required by Lightspeed DOS
310 E61F 9D 48 03 sta icbll,x
311 E622 BD 49 03 lda icblh,x
312 E625 E5 29 sbc icblhz
313 E627 85 29 sta icblhz
314 E629 9D 49 03 sta icblh,x
315
316 ;NOMAM 2013 BASIC Ten-Liners disk requires ICBALZ to be untouched :P
317 E62C BD 44 03 85 24 BD + mwa icbal,x icbalz
318
319 ;Pacem in Terris requires Y=1 exit.
320 ;DOS 3.0 with 128K/XE mode requires Y=3 for EOF imminent.
321 E636 60 rts
322
323 ;--------------------------------------------------------------------------
324 E637 cmdGetChars:
325 E637 F0 15 beq cmdGetCharsSingle
326 E639 cmdGetCharsLoop:
327 E639 20 DC E6 jsr CIOInvoke.invoke_vector
328 E63C C0 00 cpy #0
329 E63E 30 0B bmi cmdGetCharsError
330 E640 A2 00 ldx #0
331 E642 85 2F sta ciochr ;required by HOTEL title screen
332 E644 81 24 sta (icbalz,x)
333 E646 20 8C E6 jsr advance_pointers
334 E649 D0 EE bne cmdGetCharsLoop
335 E64B cmdGetCharsError:
336 E64B 4C 15 E6 jmp cmdGetPutDone
337
338 E64E cmdGetCharsSingle:
339 E64E 20 DC E6 jsr CIOInvoke.invoke_vector
340 E651 85 2F sta ciochr
341 E653 60 rts
342
343 ;--------------------------------------------------------------------------
344 ; PUT RECORD handler ($09)
345 ;
346 ; Exit:
347 ; ICBAL/ICBAH: Not changed
348 ; ICBLL/ICBLH: Number of bytes processed
349 ;
350 ; If the string does not contain an EOL character, one is printed at the
351 ; end. Also, in this case CIOCHR must reflect the last character in the
352 ; buffer and not the EOL. (Required by Atari DOS 2.5 RAMDISK banner)
353 ;
354 ; If length=0, the character in the A register is output without an EOL.
355 ; This behavior is required by the graphics library for Mad Pascal.
356 ;
357 E654 cmdPutRecord:
358 E654 F0 33 beq cmdPutCharsSingle
359 E656 cmdPutRecordLoop:
360 E656 A0 00 ldy #0
361 E658 B1 24 lda (icbalz),y
362 E65A 20 DC E6 jsr CIOInvoke.invoke_vector
363 E65D 98 tya
364 E65E 30 12 bmi cmdPutRecordError
365 E660 20 8C E6 jsr advance_pointers
366 E663 F0 08 beq cmdPutRecordEOL
367 E665 A9 9B lda #$9b
368 E667 C5 2F cmp ciochr
369 E669 F0 07 beq cmdPutRecordDone
370 E66B D0 E7 bne cmdPutRecord
371
372 E66D cmdPutRecordEOL:
373 E66D A9 9B lda #$9b
374 E66F 20 DC E6 jsr CIOInvoke.invoke_vector
375 E672 cmdPutRecordError:
376 E672 cmdPutRecordDone:
377 E672 4C 15 E6 jmp cmdGetPutDone
378
379 ;--------------------------------------------------------------------------
380 E675 cmdPutChars:
381 E675 F0 12 beq cmdPutCharsSingle
382 E677 cmdPutCharsLoop:
383 E677 A0 00 ldy #0
384 E679 B1 24 lda (icbalz),y
385 E67B 20 DC E6 jsr CIOInvoke.invoke_vector
386 E67E 98 tya
387 E67F 30 F1 bmi cmdPutRecordError
388 E681 20 8C E6 jsr advance_pointers
389 E684 D0 F1 bne cmdPutCharsLoop
390 E686 4C 15 E6 jmp cmdGetPutDone
391 E689 cmdPutCharsSingle:
392 E689 4C DE E6 jmp CIOInvoke.invoke_vector_ciochr
393
394 ;--------------------------------------------------------------------------
395
396 E68C advance_pointers:
397 E68C E6 24 D0 02 E6 25 inw icbalz
398 E692 A5 28 D0 02 C6 29 + dew icbllz
399 E69A D0 02 A5 29 sne:lda icblhz
400 E69E 60 rts
401
402 ;--------------------------------------------------------------------------
403 E69F cmdClose:
404 E69F 20 DC E6 jsr CIOInvoke.invoke_vector
405 E6A2 cmdCloseProvisional:
406 E6A2 A6 2E ldx icidno
407 E6A4 20 5E E7 jsr CIOSetPutByteClosed
408 E6A7 A9 FF 9D 40 03 mva #$ff ichid,x
409 E6AC 60 rts
410
411 E6AD perm_check_table:
412 E6AD 04 dta $04 ;$04 (get record)
413 E6AE 04 dta $04 ;$05 (get record)
414 E6AF 04 dta $04 ;$06 (get chars)
415 E6B0 04 dta $04 ;$07 (get chars)
416 E6B1 08 dta $08 ;$08 (put record)
417 E6B2 08 dta $08 ;$09 (put record)
418 E6B3 08 dta $08 ;$0A (put chars)
419 E6B4 08 dta $08 ;$0B (put chars)
420 E6B5 FF dta $ff ;$0C (close)
421 E6B6 FF dta $ff ;$0D (get status)
422 E6B7 FF dta $ff ;$0E (special)
423
424 E6B8 vector_preload_table:
425 E6B8 05 dta $05 ;$04 (get record)
426 E6B9 05 dta $05 ;$05 (get record)
427 E6BA 05 dta $05 ;$06 (get chars)
428 E6BB 05 dta $05 ;$07 (get chars)
429 E6BC 07 dta $07 ;$08 (put record)
430 E6BD 07 dta $07 ;$09 (put record)
431 E6BE 07 dta $07 ;$0A (put chars)
432 E6BF 07 dta $07 ;$0B (put chars)
433 E6C0 03 dta $03 ;$0C (close)
434 E6C1 09 dta $09 ;$0D (get status)
435 E6C2 0B dta $0b ;$0E (special)
436
437 E6C3 command_table_lo:
438 E6C3 EF dta <(cmdGetRecord-1) ;$04
439 E6C4 EF dta <(cmdGetRecord-1) ;$05
440 E6C5 36 dta <(cmdGetChars-1) ;$06
441 E6C6 36 dta <(cmdGetChars-1) ;$07
442 E6C7 53 dta <(cmdPutRecord-1) ;$08
443 E6C8 53 dta <(cmdPutRecord-1) ;$09
444 E6C9 74 dta <(cmdPutChars-1) ;$0A
445 E6CA 74 dta <(cmdPutChars-1) ;$0B
446 E6CB 9E dta <(cmdClose-1) ;$0C
447 E6CC DB dta <(cmdGetStatus-1) ;$0D
448 E6CD DF dta <(cmdSpecial-1) ;$0E
449
450 E6CE command_table_hi:
451 E6CE E5 dta >(cmdGetRecord-1) ;$04
452 E6CF E5 dta >(cmdGetRecord-1) ;$05
453 E6D0 E6 dta >(cmdGetChars-1) ;$06
454 E6D1 E6 dta >(cmdGetChars-1) ;$07
455 E6D2 E6 dta >(cmdPutRecord-1) ;$08
456 E6D3 E6 dta >(cmdPutRecord-1) ;$09
457 E6D4 E6 dta >(cmdPutChars-1) ;$0A
458 E6D5 E6 dta >(cmdPutChars-1) ;$0B
459 E6D6 E6 dta >(cmdClose-1) ;$0C
460 E6D7 E6 dta >(cmdGetStatus-1) ;$0D
461 E6D8 E5 dta >(cmdSpecial-1) ;$0E
462 .endp
463
464 ;==========================================================================
465 ; Invoke device vector.
466 ;
467 ; Entry (standard):
468 ; A, X = ignored
469 ; Y = offset to high vector byte in device table
470 ;
471 ; Entry (invoke_vector):
472 ; A = byte to pass to PUT CHAR vector
473 ; X, Y = ignored
474 ;
475 ; Exit:
476 ; A = byte returned from GET CHAR vector
477 ; Y = status
478 ;
479 E6D9 .proc CIOInvoke
480 E6D9 20 7A E5 jsr CIO.load_vector
481 E6DC invoke_vector:
482 E6DC 85 2F sta ciochr
483 E6DE invoke_vector_ciochr:
484 E6DE A5 2D lda icax3z+1
485 E6E0 48 pha
486 E6E1 A5 2C lda icax3z
487 E6E3 48 pha
488 E6E4 A0 92 ldy #CIOStatNotSupported
489 E6E6 A6 2E ldx icidno
490 E6E8 A5 2F lda ciochr
491 E6EA 60 rts
492 .endp
493
494 ;==========================================================================
495 ; Copy IOCB to ZIOCB.
496 ;
497 ; Entry:
498 ; X = IOCB
499 ;
500 ; [OSManual p236] "Although both the outer level IOCB and the Zero-page
501 ; IOCB are defined to be 16 bytes in size, only the first 12 bytes are
502 ; moved by CIO."
503 ;
504 E6EB .proc CIOLoadZIOCB
505 ;We used to do a trick here where we would count Y from $F4 to $00...
506 ;but we can't do that because the 65C816 doesn't wrap abs,Y within
507 ;bank 0 even in emulation mode. Argh!
508
509 E6EB A0 00 ldy #0
510 E6ED copyToZIOCB:
511 E6ED BD 40 03 lda ichid,x
512 E6F0 99 20 00 sta ziocb,y
513 E6F3 E8 inx
514 E6F4 C8 iny
515 E6F5 C0 0C cpy #12
516 E6F7 D0 F4 bne copyToZIOCB
517 E6F9 60 rts
518 .endp
519
520 ;==========================================================================
521 E6FA .proc CIOParsePath
522 ;default to device #1
523 E6FA A2 01 ldx #1
524
525 ;pull first character of filename and stash it
526 E6FC A1 23 lda (icbalz-1,x)
527 E6FE 85 2D sta icax4z
528
529 ;Check for a device number.
530 ;
531 ; - D1:-D9: is supported. D0: also gives unit 1, and any digits beyond
532 ; the first are ignored.
533 ;
534 ; We don't validate the colon anymore -- Atari OS allows opening just "C" to get
535 ; to the cassette.
536 ;
537 E700 A0 01 ldy #1
538 E702 B1 24 lda (icbalz),y
539 E704 38 sec
540 E705 E9 30 sbc #'0'
541 E707 F0 06 beq nodevnum
542 E709 C9 0A cmp #10
543 E70B B0 02 bcs nodevnum
544 E70D AA tax
545
546 E70E C8 iny
547
548 E70F nodevnum:
549 E70F 86 21 stx icdnoz
550
551 .if _KERNEL_XLXE
552 ;check if we are doing a true open and if we should do a type 4 poll
553 E711 A5 22 lda iccomz
554 E713 C9 03 cmp #CIOCmdOpen
555 E715 D0 3D bne skip_poll
556
557 ;clear DVSTAT+0/+1 to indicate no poll
558 E717 A9 00 lda #0
559 E719 8D EA 02 sta dvstat
560 E71C 8D EB 02 sta dvstat+1
561
562 ;check if we should do an unconditional poll (HNDLOD nonzero).
563 E71F AD E9 02 lda hndlod
564 E722 D0 05 bne unconditional_poll
565
566 ;search handler table
567 E724 20 69 E7 jsr CIOFindHandler
568 E727 F0 34 beq found
569
570 E729 unconditional_poll:
571 ;do type 4 poll
572 E729 20 7A E7 jsr CIOPollForDevice
573 E72C 30 2B bmi unknown_device
574
575 ;mark provisionally open
576 E72E A6 2E ldx icidno
577 E730 A9 7F 9D 40 03 mva #$7f ichid,x
578 E735 A5 2D 9D 4C 03 mva icax4z icax3,x
579 E73A AD EC 02 9D 4D 03 mva dvstat+2 icax4,x
580 E740 A9 C8 9D 46 03 A9 + mwa #CIOPutByteLoadHandler-1 icptl,x
581 E74A A5 21 9D 41 03 mva icdnoz icdno,x
582
583 ;do direct exit, bypassing regular open path
584 E74F 68 pla
585 E750 68 pla
586 E751 A0 01 ldy #1
587 E753 60 rts
588
589 E754 skip_poll:
590 .endif
591
592 ;search handler table
593 E754 20 69 E7 jsr CIOFindHandler
594 E757 F0 04 beq found
595
596 E759 unknown_device:
597 ;return unknown device error
598 E759 A0 82 ldy #CIOStatUnkDevice
599 E75B 68 pla
600 E75C 68 pla
601 E75D found:
602 E75D 60 rts
603 .endp
604
605 ;==========================================================================
606 E75E .proc CIOSetPutByteClosed
607 E75E A9 4D lda #<[CIO.not_open_handler-1]
608 E760 9D 46 03 sta icptl,x
609 E763 A9 E5 lda #>[CIO.not_open_handler-1]
610 E765 9D 47 03 sta icpth,x
611 E768 60 rts
612 .endp
613
614 ;==========================================================================
615 ; Attempt to find a handler entry in HATABS.
616 ;
617 E769 .proc CIOFindHandler
618 ;search for handler
619 E769 A5 2D lda icax4z
620 E76B A2 21 ldx #11*3
621 E76D findHandler:
622 E76D DD 1A 03 cmp hatabs,x
623 E770 F0 05 beq foundHandler
624 E772 CA dex
625 E773 CA dex
626 E774 CA dex
627 E775 10 F6 bpl findHandler
628 E777 foundHandler:
629 ;store handler ID
630 E777 86 20 stx ichidz
631 E779 60 rts
632 .endp
633
634 ;==========================================================================
635 ; Poll SIO bus for CIO device
636 ;
637 ; Issues a type 4 poll ($4F/$40/devname/devnumber).
638 ;
639 .if _KERNEL_XLXE
640 E77A .proc CIOPollForDevice
641 E77A A5 2D lda icax4z
642 E77C 8D 0A 03 sta daux1
643 E77F A5 21 lda icdnoz
644 E781 8D 0B 03 sta daux2
645
646 E784 A2 09 ldx #9
647 E786 BD 92 E7 9D 00 03 + mva:rpl cmd_tab,x ddevic,x-
648
649 E78F 4C 59 E4 jmp siov
650
651 E792 cmd_tab:
652 E792 4F dta $4f ;device
653 E793 01 dta $01 ;unit
654 E794 40 dta $40 ;command
655 E795 40 dta $40 ;status (transfer flags)
656 E796 EA dta <dvstat ;dbuflo
657 E797 02 dta >dvstat ;dbufhi
658 E798 40 dta $40 ;dtimlo
659 E799 00 dta $00 ;unused
660 E79A 04 dta $04 ;dbytlo
661 E79B 00 dta $00 ;dbythi
662 .endp
663 .endif
664
665 ;==========================================================================
666 ; Load handler for a provisionally open IOCB.
667 ;
668 .if _KERNEL_XLXE
669 E79C .proc CIOLoadHandler
670 ;load handler over SIO bus
671 E79C AD EC 02 8D D1 02 + mwa dvstat+2 loadad
672 E7A8 A6 2E ldx icidno
673 E7AA BD 4D 03 8D 00 03 mva icax4,x ddevic
674 E7B0 20 01 C5 jsr PHLoadHandler
675 E7B3 B0 11 bcs fail
676
677 ;let's see if we can look up the handler now
678 E7B5 A6 2E ldx icidno
679 E7B7 BD 4C 03 85 2D mva icax3,x icax4z
680 E7BC 20 69 E7 jsr CIOFindHandler
681 E7BF D0 05 bne fail
682
683 ;follow through with open
684 E7C1 20 AD E5 jsr CIO.open_entry
685 E7C4 10 02 bpl ok
686 E7C6 fail:
687 E7C6 A0 82 ldy #CIOStatUnkDevice
688 E7C8 ok:
689 E7C8 60 rts
690 .endp
691 .endif
692
693 ;==========================================================================
694 ; PUT BYTE handler for provisionally open IOCBs.
695 ;
696 ; This handler is used when an IOCB has been provisionally opened pending
697 ; a handler load over the SIO bus. It is used when a direct call is made
698 ; through ICPTL/ICPTH. If HNDLOD=0, the call fails as handler loading is
699 ; not set up; if it is nonzero, the handler is loaded over the SIO bus and
700 ; then the PUT BYTE call continues if everything is good.
701 ;
702 .if _KERNEL_XLXE
703 E7C9 .proc CIOPutByteLoadHandler
704 ;save off A/X
705 E7C9 85 2F sta ciochr
706 E7CB 86 2E stx icidno
707
708 ;check if we're allowed to load a handler and bail if not
709 E7CD AD E9 02 lda hndlod
710 E7D0 F0 10 beq load_error
711
712 ;copy IOCB to ZIOCB
713 E7D2 20 EB E6 jsr CIOLoadZIOCB
714
715 ;try to load the handler
716 E7D5 20 9C E7 jsr CIOLoadHandler
717 E7D8 30 08 bmi load_error
718
719 ;all good... let's invoke the standard handler
720 E7DA A0 07 ldy #7
721 E7DC 20 D9 E6 jsr CIOInvoke
722 E7DF 4C E4 E7 jmp xit
723
724 E7E2 load_error:
725 E7E2 A0 82 ldy #CIOStatUnkDevice
726 E7E4 xit:
727 E7E4 08 php
728 E7E5 A5 2F lda ciochr
729 E7E7 A6 2E ldx icidno
730 E7E9 28 plp
731 E7EA 60 rts
732 .endp
733 .endif
236 .endif
237
238 E7EB _KERNEL_REPORT_MODULE_SIZE 'Central Input/Output (CIO)', $E6D5-$E4A6
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $E6D5-$E4A6, ')', ' ', 'Central Input/Output (CIO)'
1 $E7EB -> $0301($022F) Central Input/Output (CIO)
3 = E7EB .def ?@_kernel_lastpt = *
Source: source/main.xasm
239
240 .if !_KERNEL_XLXE
241 icl 'vbi.s'
242 icl 'interrupt.s'
243 icl 'irq.s'
244 .endif
245 E7EB _KERNEL_REPORT_MODULE_SIZE 'Interrupt routines', $E944-$E6D5
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $E944-$E6D5, ')', ' ', 'Interrupt routines'
1 $E7EB -> $0000($026F) Interrupt routines
3 = E7EB .def ?@_kernel_lastpt = *
Source: source/main.xasm
246
247 E7EB icl 'sio.inc'
Source: source/Shared/sio.inc
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - SIO definitions
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 .ifndef f_SIO_INC
11 .def f_SIO_INC
12
13 SIOSuccess = $01
14 SIOErrorTimeout = $8A
15 SIOErrorNAK = $8B
16 SIOErrorBadFrame = $8C
17 SIOErrorOverrun = $8E
18 SIOErrorChecksum = $8F
19 SIOErrorDeviceError = $90
20
21 .endif
248 E7EB icl 'sio.s'
Source: source/Shared/sio.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; AltirraOS modular Kernel ROM - Serial Input/Output (SIO) routines
3 ; Copyright (C) 2008-2019 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 E7EB .proc SIOInit
11 ;turn off POKEY init mode so polynomial counters and audio run
12 E7EB A9 03 8D 0F D2 mva #3 skctl
13 E7F0 8D 32 02 sta sskctl
14
15 ;enable noisy sound (yes, this is actually documented as being inited to
16 ;3)
17 E7F3 85 41 sta soundr
18 E7F5 60 rts
19 .endp
20
21 ;==============================================================================
22 E7F6 .proc SIO
23 ;set retry counters
24 E7F6 A9 01 8D BD 02 mva #$01 dretry
25
26 ;enter critical section
27 E7FB 85 42 sta critic
28
29 .if _KERNEL_PBI_SUPPORT
30 ;attempt PBI transfer
31 E7FD 20 A2 C2 jsr PBIAttemptSIO
32 E800 90 03 4C EC E8 scc:jmp xit_pbi
33 .endif
34
35 ;we must not save STACKP until after PBI devices are polled -- the
36 ;BlackBox PBI routines depend on being able to reuse this location
37 E805 BA tsx
38 E806 8E 18 03 stx stackp
39
40 ;Set timeout timer address -- MUST be done on each call to SIO, or
41 ;Cross-Town Crazy Eight hangs on load due to taking over this vector
42 ;previously. This is guaranteed by the OS Manual in Appendix L, H27.
43 E809 20 13 E9 jsr SIOSetTimeoutVector
44
45 ;check for cassette -- needs to match $60 or else Prisma: Alien Ambush
46 ;fails to load.
47 E80C A2 00 ldx #0
48 E80E AD 00 03 lda ddevic
49 E811 C9 60 cmp #$60
50 E813 D0 01 CA sne:dex
51 E816 8E 0F 03 stx casflg
52
53 ;init POKEY hardware
54 E819 20 66 E9 jsr SIOInitHardware
55
56 ;go do cassette now
57 E81C 2C 0F 03 bit casflg
58 E81F 10 03 bpl retry_command
59 E821 4C DC EA jmp SIOCassette
60
61 E824 retry_command:
62 ;We try 13 times to get a command accepted by a device; after that it
63 ;counts as a device failure and we try one more round of 13 tries.
64 E824 A9 0D 8D 9C 02 mva #$0d cretry
65
66 E829 retry_command_2:
67 ;init command buffer
68 E829 AD 00 03 lda ddevic
69 E82C 18 clc
70 E82D 6D 01 03 adc dunit
71 E830 38 sec
72 E831 E9 01 sbc #1
73 E833 8D 3A 02 sta cdevic
74
75 E836 AD 02 03 8D 3B 02 mva dcomnd ccomnd
76 E83C AD 0A 03 8D 3C 02 mva daux1 caux1
77 E842 AD 0B 03 8D 3D 02 mva daux2 caux2
78
79 ;assert command line
80 E848 A9 34 8D 03 D3 mva #$34 pbctl
81
82 ;wait ~600us to ensure 750us minimum delay (~1k cycles or ~10 scanlines)
83 E84D A2 05 ldx #5
84 E84F AC 0B D4 ldy vcount
85 E852 cmddelay:
86 E852 CC 0B D4 F0 FB cpy:req vcount
87 E857 C8 iny
88 E858 CA dex
89 E859 D0 F7 bne cmddelay
90
91 ;send command frame
92 E85B A9 00 85 3C mva #0 nocksm
93 E85F A9 02 lda #>cdevic
94 E861 85 33 sta bufrhi
95 E863 85 35 sta bfenhi
96 E865 A9 3A 85 32 mva #<cdevic bufrlo
97 E869 A9 3E 85 34 mva #<caux2+1 bfenlo
98 E86D 20 CB E9 jsr SIOSend
99 E870 30 65 bmi xit
100
101 ;wait for the ACK
102 E872 20 1E E9 jsr SIOWaitForACK
103 E875 10 0A bpl ackOK
104
105 E877 command_error:
106 E877 20 38 EA jsr SIOReceiveStop
107 E87A CE 9C 02 dec cretry
108 E87D 10 AA bpl retry_command_2
109 E87F 30 4B bmi transfer_error
110
111 E881 ackOK:
112
113 ;check if we should send a data frame
114 E881 2C 03 03 bit dstats
115 E884 10 0D bpl no_send_frame
116
117 ;setup buffer pointers
118 E886 20 B5 E9 jsr SIOSetupBufferPointers
119
120 ;send data frame
121 E889 20 CB E9 jsr SIOSend
122 E88C 30 49 bmi xit
123
124 ;wait for ACK
125 E88E 20 1E E9 jsr SIOWaitForACK
126 E891 30 E4 bmi command_error
127
128 E893 no_send_frame:
129
130 ;setup for receiving complete
131 E893 A2 FF ldx #$ff
132 E895 8E 17 03 stx timflg
133 E898 86 3C stx nocksm
134
135 ;setup frame delay for complete
136 E89A AD 06 03 lda dtimlo
137 E89D 6A ror
138 E89E 6A ror
139 E89F 48 pha
140 E8A0 6A ror
141 E8A1 29 C0 and #$c0
142 E8A3 A8 tay
143 E8A4 68 pla
144 E8A5 29 3F and #$3f
145 E8A7 AA tax
146
147 E8A8 A9 01 lda #1
148 E8AA 20 5C E4 jsr setvbv
149
150 E8AD A2 3E ldx #<temp
151 E8AF 86 32 stx bufrlo
152 E8B1 E8 inx
153 E8B2 86 34 stx bfenlo
154 E8B4 A2 02 ldx #>temp
155 E8B6 86 33 stx bufrhi
156 E8B8 86 35 stx bfenhi
157 E8BA 20 FA E9 jsr SIOReceive
158 E8BD 30 0D bmi transfer_error
159
160 ;Check if we received a C ($43) or E ($45) -- we must NOT abort immediately
161 ;on a device error, as the device still sends back data we need to read, and
162 ;Music Studio relies on the data coming back from a CRC error.
163 E8BF AD 3E 02 lda temp
164 E8C2 C9 43 cmp #$43
165 E8C4 F0 32 beq completeOK
166 E8C6 C9 45 cmp #$45
167 E8C8 F0 2E beq completeOK
168
169 ;we received crap... fail it now
170 E8CA device_error:
171 E8CA A0 90 ldy #SIOErrorDeviceError
172
173 E8CC transfer_error:
174 E8CC 20 38 EA jsr SIOReceiveStop
175
176 E8CF CE BD 02 dec dretry
177 E8D2 30 03 bmi device_retries_exhausted
178 E8D4 4C 24 E8 jmp retry_command
179
180 E8D7 device_retries_exhausted:
181 E8D7 xit:
182 E8D7 AE 0F 03 ldx casflg
183 E8DA D0 0C bne leave_cassette_audio_on
184 E8DC 8E 01 D2 stx audc1
185 E8DF 8E 03 D2 stx audc2
186 E8E2 8E 05 D2 stx audc3
187 E8E5 8E 07 D2 stx audc4
188 E8E8 leave_cassette_audio_on:
189
190 .ifdef _KERNEL_816
191 ;we may be in native mode, so we can't f-up the high byte of the stack pointer
192 lda #1
193 xba
194 lda stackp
195 tcs
196 .else
197 E8E8 AE 18 03 ldx stackp
198 E8EB 9A txs
199 .endif
200
201 E8EC xit_pbi:
202 E8EC A9 00 lda #0
203 E8EE 85 42 sta critic
204
205 E8F0 C0 00 cpy #0 ;!! - A=0 must be preserved for LiteDOS
206 E8F2 8C 03 03 sty dstats
207 E8F5 84 30 sty status
208 E8F7 60 rts
209
210 E8F8 completeOK:
211 ;check if we should read a data frame
212 E8F8 2C 03 03 bit dstats
213 E8FB 50 08 bvc no_receive_frame
214
215 ;setup buffer pointers
216 E8FD 20 B5 E9 jsr SIOSetupBufferPointers
217
218 ;receive the rest of the frame
219 E900 20 FA E9 jsr SIOReceive
220 E903 30 C7 bmi transfer_error
221
222 E905 no_receive_frame:
223 ;now we can finally shut off the receive IRQ
224 E905 20 38 EA jsr SIOReceiveStop
225
226 ;Now check whether we got a device error earlier. If we did, return
227 ;that instead of success.
228 E908 AD 3E 02 lda temp
229 E90B C9 43 cmp #'C'
230 E90D D0 BB bne device_error
231
232 ;nope, we're good... exit OK.
233 E90F A0 01 ldy #SIOSuccess
234 E911 D0 C4 bne xit
235 .endp
236
237 ;==============================================================================
238 E913 .proc SIOSetTimeoutVector
239 E913 A9 D6 8D 26 02 A9 + mwa #SIOCountdown1Handler cdtma1
240 E91D 60 rts
241 .endp
242
243 ;==============================================================================
244 E91E .proc SIOWaitForACK
245 ;setup 2 frame delay for ack
246 E91E A2 FF ldx #$ff
247 E920 8E 17 03 stx timflg
248 E923 86 3C stx nocksm
249 E925 E8 inx ;X=0
250 E926 A9 01 lda #1
251 E928 A0 02 ldy #2
252 E92A 84 33 sty bufrhi ;>temp = 2
253 E92C 84 35 sty bfenhi ;>temp+1 = 2
254 E92E 20 5C E4 jsr setvbv
255
256 ;setup for receiving ACK
257 E931 A2 3E ldx #<temp
258 E933 86 32 stx bufrlo
259 E935 E8 inx
260 E936 86 34 stx bfenlo ;#<[temp+1]
261
262 E938 20 FA E9 jsr SIOReceive
263
264 ;check if we had a receive error
265 E93B 30 09 bmi xit
266
267 ;check if we got an ACK
268 E93D AD 3E 02 lda temp
269 E940 C9 41 cmp #'A'
270 E942 F0 02 beq xit
271
272 ;doh
273 E944 A0 8B ldy #SIOErrorNAK
274 E946 xit:
275 E946 60 rts
276 .endp
277
278 ;==============================================================================
279 ;SIO send enable routine
280 ;
281 ; This is one of those routines that Atari inadvisably exposed in the OS jump
282 ; table even though they shouldn't. Responsibilities of this routine are:
283 ;
284 ; - Hit SKCTL to reset serial hardware and init for sending
285 ; - Hit SKRES to clear status
286 ; - Enable send interrupts
287 ; - Configure AUDF3/AUDF4 frequency (19200 baud or 600 baud)
288 ; - Set AUDC3/AUDC4 for noisy or non-noisy audio
289 ; - Set AUDCTL
290 ;
291 ; It does not init any of the SIO variables, only hardware/shadow state.
292 ;
293 = E966 SIOInitHardware = SIOSendEnable.init_hardware
294 E947 .proc SIOSendEnable
295 ;enable serial output ready IRQ and suppress serial output complete IRQ
296 E947 A5 10 lda pokmsk
297 E949 09 10 ora #$10
298 E94B 29 F7 and #$f7
299 E94D 85 10 sta pokmsk
300 E94F 8D 0E D2 sta irqen
301
302 E952 no_irq_setup:
303 ;clear forced break mode and reset serial clocking mode to timer 4
304 ;synchronous; also enable two-tone mode if in cassette mode
305 E952 AD 32 02 lda sskctl
306 E955 29 0F and #$0f
307 E957 09 20 ora #$20
308 E959 AE 0F 03 ldx casflg
309 E95C F0 02 09 08 seq:ora #$08
310 E960 8D 32 02 sta sskctl
311 E963 8D 0F D2 sta skctl
312
313 E966 init_hardware:
314 ;clock channel 3 and 4 together at 1.79MHz
315 ;configure pokey timers 3 and 4 for 19200 baud (1789773/(2*40+7) = 19040)
316 E966 A2 08 ldx #8
317
318 ;check if we are doing a cassette transfer; if so, use the cassette
319 ;register table instead
320 E968 AD 0F 03 lda casflg
321 E96B F0 02 beq not_cassette
322
323 E96D A2 11 ldx #17
324
325 E96F not_cassette:
326
327 = E96F .def :SIOInitPOKEYWithRegOffsetX
328 ;load POKEY audio registers
329 E96F A0 08 ldy #8
330 E971 BD 9A E9 CA 99 00 + mva:rpl regdata_normal,x- audf1,y-
331
332 ;go noisy audio if requested
333 E97B A5 41 lda soundr
334 E97D F0 17 beq no_noise
335
336 E97F A9 A8 lda #$a8
337 E981 8D 07 D2 sta audc4
338 E984 AE 0F 03 ldx casflg
339 E987 F0 0D beq no_noise
340 E989 A9 10 lda #$10
341 E98B 2C 32 02 bit sskctl
342 E98E D0 06 bne no_noise
343 E990 8D 01 D2 sta audc1
344 E993 8D 03 D2 sta audc2
345
346 E996 no_noise:
347
348 ;reset serial status
349 E996 8D 0A D2 sta skres
350 E999 60 rts
351
352 E99A regdata:
353 E99A regdata_normal:
354 E99A 00 dta $00 ;audf1
355 E99B A0 dta $a0 ;audc1
356 E99C 00 dta $00 ;audf2
357 E99D A0 dta $a0 ;audc2
358 E99E 28 dta $28 ;audf3
359 E99F A0 dta $a0 ;audc3
360 E9A0 00 dta $00 ;audf4
361 E9A1 A0 dta $a0 ;audc4
362 E9A2 28 dta $28 ;audctl
363
364 E9A3 regdata_cassette_write:
365 E9A3 05 dta $05 ;audf1
366 E9A4 A0 dta $a0 ;audc1
367 E9A5 07 dta $07 ;audf2
368 E9A6 A0 dta $a0 ;audc2
369 E9A7 CC dta $cc ;audf3
370 E9A8 A0 dta $a0 ;audc3
371 E9A9 05 dta $05 ;audf4
372 E9AA A0 dta $a0 ;audc4
373 E9AB 28 dta $28 ;audctl
374
375 E9AC regdata_cassette_read:
376 E9AC 00 dta $00 ;audf1
377 E9AD A0 dta $a0 ;audc1
378 E9AE 00 dta $00 ;audf2
379 E9AF A0 dta $a0 ;audc2
380 E9B0 CC dta $cc ;audf3
381 E9B1 A0 dta $a0 ;audc3
382 E9B2 05 dta $05 ;audf4
383 E9B3 A0 dta $a0 ;audc4
384 E9B4 28 dta $28 ;audctl
385 .endp
386
387 ;==============================================================================
388 E9B5 .proc SIOSetupBufferPointers
389 E9B5 18 clc
390 E9B6 AD 04 03 lda dbuflo
391 E9B9 85 32 sta bufrlo
392 E9BB 6D 08 03 adc dbytlo
393 E9BE 85 34 sta bfenlo
394 E9C0 AD 05 03 lda dbufhi
395 E9C3 85 33 sta bufrhi
396 E9C5 6D 09 03 adc dbythi
397 E9C8 85 35 sta bfenhi
398 E9CA 60 rts
399 .endp
400
401 ;==============================================================================
402 ;SIO send routine
403 ;
404 E9CB .proc SIOSend
405 ;configure serial port for synchronous transmission
406 ;enable transmission IRQs
407 E9CB 78 sei
408 E9CC 20 47 E9 jsr SIOSendEnable
409
410 E9CF A0 00 ldy #0
411 E9D1 84 3A sty xmtdon
412 E9D3 84 30 sty status
413 E9D5 84 3B sty chksnt
414
415 ;send first byte and set checksum (must be atomic)
416 E9D7 B1 32 lda (bufrlo),y
417 E9D9 8D 0D D2 sta serout
418 E9DC 85 31 sta chksum
419
420 ;unmask IRQs
421 E9DE 58 cli
422
423 ;wait for transmit to complete or Break to be pressed
424 E9DF wait:
425 E9DF A5 11 lda brkkey
426 E9E1 F0 06 beq break_detected
427 E9E3 A5 3A lda xmtdon
428 E9E5 F0 F8 beq wait
429 E9E7 D0 04 bne send_completed
430
431 E9E9 break_detected:
432 E9E9 A0 80 ldy #$80
433 E9EB 84 30 sty status
434
435 E9ED send_completed:
436 ;shut off transmission IRQs
437 E9ED 78 sei
438 E9EE A5 10 lda pokmsk
439 E9F0 29 E7 and #$e7
440 E9F2 85 10 sta pokmsk
441 E9F4 8D 0E D2 sta irqen
442 E9F7 58 cli
443
444 ;we're done
445 E9F8 98 tya
446 E9F9 60 rts
447 .endp
448
449 ;==============================================================================
450 ; SIO receive routine
451 ;
452 ; The exit and entry paths of this routine are time critical when receiving
453 ; the Complete/Error byte and data frame since there may be no delay at all
454 ; in between. The exit path needs to exit with the receive IRQ hot but IRQs
455 ; masked; the entry path in turn needs to keep the IRQ enabled but not unmask
456 ; IRQs until ready to receive.
457 ;
458 E9FA .proc SIOReceive
459 E9FA A9 00 lda #0
460 E9FC use_checksum:
461 E9FC 85 31 sta chksum
462 E9FE A2 00 ldx #0
463 EA00 86 39 stx recvdn ;receive done flag = false
464 EA02 86 38 stx bufrfl ;buffer full flag = false
465 EA04 E8 inx
466 EA05 86 30 stx status ;set status to success (1)
467
468 ;configure serial port for asynchronous receive
469 ;enable receive IRQ
470 EA07 78 sei
471 EA08 AD 32 02 lda sskctl
472 EA0B 29 8F and #$8f
473 EA0D 09 10 ora #$10
474 EA0F 8D 32 02 sta sskctl
475 EA12 8D 0F D2 sta skctl
476 EA15 A5 10 lda pokmsk
477 EA17 09 20 ora #$20
478 EA19 85 10 sta pokmsk
479 EA1B 8D 0E D2 sta irqen
480 EA1E 58 cli
481
482 ;Negate command line (if it isn't already negated).
483 ;
484 ;Note that we DON'T do this until we are entirely ready to receive,
485 ;because as soon as we do this we can get data.
486 EA1F A9 3C 8D 03 D3 mva #$3c pbctl
487
488 ;wait for receive to complete
489 EA24 wait:
490 EA24 AD 17 03 lda timflg ;check for timeout
491 EA27 F0 0B beq timeout ;bail if so
492 EA29 A4 30 ldy status ;check for another error code
493 EA2B 30 05 bmi error ;bail if so
494 EA2D A5 39 lda recvdn ;check for receive complete
495 EA2F F0 F3 beq wait ;keep waiting if not
496 EA31 98 tya ;set flags from status
497
498 EA32 error:
499 ;Mask interrupts, but exit with them masked. We do this in order to
500 ;handle the transition from Complete to data frame during receive. There
501 ;is no guaranteed device delay in between these and some disk drives
502 ;send back-to-back bytes. In addition, there are demos that have DLIs
503 ;active during SIO loads. Therefore, we avoid turning off the receive
504 ;interrupt and instead hold it off to give us the best chance of snagging
505 ;the first and second bytes successfully, even if delayed.
506 EA32 78 sei
507 EA33 60 rts
508
509 EA34 timeout:
510 EA34 A0 8A ldy #SIOErrorTimeout
511 EA36 78 sei
512 EA37 60 rts
513 .endp
514
515 ;==============================================================================
516 EA38 .proc SIOReceiveStop
517 ;shut off receive IRQs
518 EA38 A5 10 lda pokmsk
519 EA3A 29 D7 and #$d7
520 EA3C 85 10 sta pokmsk
521 EA3E 8D 0E D2 sta irqen
522 EA41 58 cli
523 EA42 60 rts
524 .endp
525
526 ;==============================================================================
527 ; SIO serial input routine
528 ;
529 ; DOS 2.0S replaces (VSERIN), so it's critical that this routine follow the
530 ; rules compatible with DOS. The rules are as follows:
531 ;
532 ; BUFRLO/BUFRHI: Points to next byte to read. Note that this is different
533 ; from (VSEROR)!
534 ; BFENLO/BFENHI: Points one after last byte in buffer.
535 ; BUFRFL: Set when all data bytes have been read.
536 ; NOCKSM: Set if no checksum byte is expected. Cleared after checked.
537 ; RECVDN: Set when receive is complete, including any checksum.
538 ;
539 EA43 .proc SIOInputReadyHandler
540 EA43 A5 38 lda bufrfl
541 EA45 D0 2A bne receiveChecksum
542
543 ;receive data byte
544 EA47 98 tya
545 EA48 48 pha
546 EA49 AD 0D D2 lda serin
547 EA4C A0 00 ldy #$00
548 EA4E 91 32 sta (bufrlo),y
549 EA50 18 clc
550 EA51 65 31 adc chksum
551 EA53 69 00 adc #$00
552 EA55 85 31 sta chksum
553
554 ;restore Y now
555 EA57 68 pla
556 EA58 A8 tay
557
558 ;bump buffer pointer
559 EA59 E6 32 D0 02 E6 33 inw bufrlo
560
561 ;check for EOB
562 EA5F A5 32 lda bufrlo
563 EA61 C5 34 cmp bfenlo
564 EA63 A5 33 lda bufrhi
565 EA65 E5 35 sbc bfenhi
566 EA67 90 06 bcc xit
567
568 EA69 C6 38 dec bufrfl ;!! - this was $00 coming in
569
570 ;should there be a checksum?
571 EA6B A5 3C lda nocksm
572 EA6D D0 15 bne skipChecksum
573 EA6F xit:
574 EA6F 68 pla
575 EA70 40 rti
576
577 EA71 receiveChecksum:
578 ;read and compare checksum
579 EA71 AD 0D D2 lda serin
580 EA74 C5 31 cmp chksum
581 EA76 D0 06 bne checksum_fail
582
583 EA78 signal_end:
584 ;set receive done flag
585 EA78 A9 FF 85 39 mva #$ff recvdn
586
587 ;exit
588 EA7C 68 pla
589 EA7D 40 rti
590
591 EA7E checksum_fail:
592 EA7E A9 8F lda #SIOErrorChecksum
593 EA80 85 30 sta status
594 EA82 D0 F4 bne signal_end ;!! - unconditional
595
596 EA84 skipChecksum:
597 ;set receive done flag
598 EA84 85 39 sta recvdn
599
600 ;clear no checksum flag
601 EA86 A9 00 lda #0
602 EA88 85 3C sta nocksm
603 EA8A 68 pla
604 EA8B 40 rti
605 .endp
606
607 ;==============================================================================
608 ; SIO serial output ready routine
609 ;
610 ; DOS 2.0S replaces (VSEROR), so it's critical that this routine follow the
611 ; rules compatible with DOS. The rules are as follows:
612 ;
613 ; BUFRLO/BUFRHI: On entry, points to one LESS than the next byte to write.
614 ; BFENLO/BFENHI: Points to byte immediately after buffer.
615 ; CHKSUM: Holds running checksum as bytes are output.
616 ; CHKSNT: $00 if checksum not yet sent, $FF if checksum sent.
617 ; POKMSK: Used to enable the serial output complete IRQ after sending
618 ; checksum.
619 ;
620 EA8C .proc SIOOutputReadyHandler
621 ;increment buffer pointer
622 EA8C E6 32 inc bufrlo
623 EA8E D0 02 bne addrcc
624 EA90 E6 33 inc bufrhi
625 EA92 addrcc:
626
627 ;compare against buffer end
628 EA92 A5 32 lda bufrlo
629 EA94 C5 34 cmp bfenlo
630 EA96 A5 33 lda bufrhi
631 EA98 E5 35 sbc bfenhi ;set flags according to (dst - end)
632 EA9A B0 13 bcs doChecksum
633
634 ;save Y
635 EA9C 98 tya
636 EA9D 48 pha
637
638 ;send out next byte
639 EA9E A0 00 ldy #0
640 EAA0 B1 32 lda (bufrlo),y
641 EAA2 8D 0D D2 sta serout
642
643 ;update checksum
644 EAA5 65 31 adc chksum
645 EAA7 69 00 adc #0
646 EAA9 85 31 sta chksum
647
648 ;restore registers and exit
649 EAAB 68 pla
650 EAAC A8 tay
651 EAAD 68 pla
652 EAAE 40 rti
653
654 EAAF doChecksum:
655 ;send checksum
656 EAAF A5 31 lda chksum
657 EAB1 8D 0D D2 sta serout
658
659 ;set checksum sent flag
660 EAB4 A9 FF 85 3B mva #$ff chksnt
661
662 ;enable output complete IRQ and disable serial output IRQ
663 EAB8 A5 10 lda pokmsk
664 EABA 09 08 ora #$08
665 EABC 29 EF and #$ef
666 EABE 85 10 sta pokmsk
667 EAC0 8D 0E D2 sta irqen
668
669 EAC3 68 pla
670 EAC4 40 rti
671 .endp
672
673 ;==============================================================================
674 EAC5 .proc SIOOutputCompleteHandler
675 ;check that we've sent the checksum
676 EAC5 A5 3B lda chksnt
677 EAC7 F0 0B beq xit
678
679 ;we're done sending the checksum
680 EAC9 85 3A sta xmtdon
681
682 ;need to shut off this interrupt as it is not latched
683 EACB A5 10 lda pokmsk
684 EACD 29 F7 and #$f7
685 EACF 85 10 sta pokmsk
686 EAD1 8D 0E D2 sta irqen
687
688 EAD4 xit:
689 EAD4 68 pla
690 EAD5 40 rti
691 .endp
692
693 ;==============================================================================
694 EAD6 .proc SIOCountdown1Handler
695 ;signal operation timeout
696 EAD6 A9 00 8D 17 03 mva #0 timflg
697 EADB 60 rts
698 .endp
699
700 ;==============================================================================
701 EADC .proc SIOCassette
702 ;check if it's read sector
703 EADC AD 02 03 lda dcomnd
704 EADF C9 52 cmp #$52
705 EAE1 F0 0F beq isread
706
707 ;check if it's put sector
708 EAE3 C9 50 cmp #$50
709 EAE5 F0 05 beq iswrite
710
711 ;nope, bail
712 EAE7 A0 8B ldy #SIOErrorNAK
713 EAE9 4C D7 E8 jmp SIO.xit
714
715 EAEC iswrite:
716 EAEC 20 F8 EA jsr SIOCassetteWriteFrame
717 EAEF 4C D7 E8 jmp SIO.xit
718
719 EAF2 isread:
720 EAF2 20 09 EB jsr SIOCassetteReadFrame
721 EAF5 4C D7 E8 jmp SIO.xit
722 .endp
723
724 ;==============================================================================
725 EAF8 .proc SIOCassetteWriteFrame
726 ;wait for pre-record write tone or IRG read delay
727 EAF8 A2 02 ldx #2
728 EAFA 20 5B EE jsr CassetteWaitLongShortCheck
729
730 ;set up to transmit
731 EAFD 20 47 E9 jsr SIOSendEnable
732
733 ;setup buffer pointers
734 EB00 20 B5 E9 jsr SIOSetupBufferPointers
735
736 ;send data frame
737 EB03 20 CB E9 jsr SIOSend
738
739 ;all done
740 EB06 4C D7 E8 jmp SIO.xit
741 .endp
742
743 ;==============================================================================
744 ; Read cassette frame
745 ;
746 ; Wait for long/short IRG, measure baud rate from sync mark, and read frame.
747 ;
748 ; When reading a cassette frame, the audio configuration is expected to be
749 ; as follows:
750 ;
751 ; Channel 1: Inaudible (31.5KHz)
752 ; Channel 2: Inaudible (31.5KHz)
753 ; Channel 3: Silent
754 ; Channel 4: Audible if enabled in SOUNDR (600Hz modulated by async read)
755 ;
756 ; This is necessary for proper tape loading sounds.
757 ;
758 EB09 .proc SIOCassetteReadFrame
759 ;wait for pre-record write tone or IRG read delay
760 EB09 A2 04 ldx #4
761 EB0B 20 5B EE jsr CassetteWaitLongShortCheck
762
763 ;set to 600 baud, turn on async read to shut off annoying tone
764 EB0E A2 1A ldx #SIOSendEnable.regdata_cassette_read-SIOSendEnable.regdata+8
765 EB10 20 6F E9 jsr SIOInitPOKEYWithRegOffsetX
766
767 EB13 AD 32 02 lda sskctl
768 EB16 29 8F and #$8f
769 EB18 09 10 ora #$10
770 EB1A 8D 32 02 sta sskctl
771
772 ;set timeout (approx; no NTSC/PAL switching yet)
773 EB1D A9 FF 8D 17 03 mva #$ff timflg
774 EB22 A9 01 lda #1
775 EB24 A2 0E ldx #>3600
776 EB26 A0 10 ldy #<3600
777 EB28 20 5F C1 jsr VBISetVector
778
779 ;wait for beginning of frame
780 EB2B A9 10 lda #$10 ;test bit 4 of SKSTAT
781 EB2D waitzerostart:
782 EB2D 2C 17 03 bit timflg
783 EB30 10 2B bpl timeout
784 EB32 2C 0F D2 bit skstat
785 EB35 D0 F6 bne waitzerostart
786
787 ;take first time measurement
788 EB37 20 F7 EB jsr readtimer
789 EB3A 8C 0D 03 sty timer1+1
790 EB3D 8D 0C 03 sta timer1
791
792 ;wait for 19 bit transitions
793 EB40 A9 10 lda #$10 ;test bit 4 of SKSTAT
794 EB42 A2 0A ldx #10 ;test 10 pairs of bits
795 EB44 waitone:
796 EB44 2C 17 03 bit timflg
797 EB47 10 14 bpl timeout
798 EB49 2C 0F D2 bit skstat
799 EB4C F0 F6 beq waitone
800 EB4E CA dex
801 EB4F F0 11 beq waitdone
802 EB51 waitzero:
803 EB51 2C 17 03 bit timflg
804 EB54 10 07 bpl timeout
805 EB56 2C 0F D2 bit skstat
806 EB59 D0 F6 bne waitzero
807 EB5B F0 E7 beq waitone
808
809 EB5D timeout:
810 EB5D A0 8A ldy #SIOErrorTimeout
811 EB5F 4C D7 E8 jmp SIO.xit
812
813 EB62 waitdone:
814
815 ;take second time measurement
816 EB62 20 F7 EB jsr readtimer
817 EB65 8D 10 03 sta timer2
818 EB68 8C 11 03 sty timer2+1
819
820 ;compute baud rate and adjust pokey divisor
821 ;
822 ; counts = (pal ? 156 : 131)*rtdelta + vdelta;
823 ; lines = counts * 2
824 ; lines_per_bit = lines / 19
825 ; cycles_per_bit = lines_per_bit * 114
826 ; pokey_divisor = cycles_per_bit / 2 - 7
827 ;
828 ; -or-
829 ;
830 ; pokey_divisor = counts * 2 * 114 / 19 / 2 - 7
831 ; = counts * 6 - 7
832 ;
833 ;16 bits at 600 baud is nominally 209 scanline pairs. This means that we
834 ;don't have to worry about more than two frames, which is at least 262
835 ;scanline pairs or less than 480 baud.
836
837 ;set frame height - 262 scanlines for NTSC, 312 for PAL
838 EB6B A2 83 ldx #131
839 EB6D AD 14 D0 lda pal
840 EB70 4A lsr
841 EB71 D0 02 A2 9C sne:ldx #156
842 EB75 8E 15 03 stx temp3
843
844 ;compute line difference
845 EB78 AD 0C 03 lda timer1
846 EB7B 20 05 EC jsr correct_time
847 EB7E 85 34 sta bfenlo
848
849 EB80 AD 10 03 lda timer2
850 EB83 20 05 EC jsr correct_time
851 EB86 18 clc ;!! this decrements one line from the line delta
852 EB87 E5 34 sbc bfenlo
853 EB89 85 34 sta bfenlo
854 EB8B A0 00 ldy #0
855 EB8D B0 01 88 scs:dey
856
857 ;compute frame difference
858 EB90 AD 11 03 lda timer2+1
859 EB93 38 ED 0D 03 sub timer1+1
860 EB97 AA tax
861
862 ;accumulate frame difference
863 EB98 F0 0C beq no_frames
864 EB9A A5 34 lda bfenlo
865 EB9C add_frame_loop:
866 EB9C 18 clc
867 EB9D 6D 15 03 adc temp3
868 EBA0 90 01 C8 scc:iny
869 EBA3 CA dex
870 EBA4 D0 F6 bne add_frame_loop
871 EBA6 no_frames:
872 EBA6 84 35 sty bfenhi
873
874 ;compute lines*6 - 7 = (lines-1)*6 - 1
875 EBA8 0A asl ;(lines-1)*2 (lo)
876 EBA9 26 35 rol bfenhi ;(lines-1)*2 (hi)
877 EBAB 85 34 sta bfenlo
878 EBAD A4 35 ldy bfenhi ;
879 EBAF 06 34 asl bfenlo ;(lines-1)*4 (lo)
880 EBB1 26 35 rol bfenhi ;(lines-1)*4 (hi)
881 EBB3 65 34 adc bfenlo ;(lines-1)*6 (lo)
882 EBB5 AA tax ;
883 EBB6 98 tya ;
884 EBB7 65 35 adc bfenhi ;(lines-1)*6 (hi) (and c=0)
885 EBB9 CA dex ;-1 line, bringing us to -7
886 EBBA 8E 04 D2 stx audf3
887 EBBD 8E EE 02 stx cbaudl
888 EBC0 E8 inx
889 EBC1 D0 02 E9 00 sne:sbc #0
890 EBC5 8D 06 D2 sta audf4
891 EBC8 8D EF 02 sta cbaudh
892
893 ;kick pokey into init mode to reset serial input shift hw
894 EBCB AE 32 02 ldx sskctl
895 EBCE 8A txa
896 EBCF 29 FC and #$fc
897 EBD1 8D 0F D2 sta skctl
898
899 ;reset serial port status
900 EBD4 8D 0A D2 sta skres
901
902 ;re-enable serial input hw
903 EBD7 8E 0F D2 stx skctl
904
905 EBDA 20 B5 E9 jsr SIOSetupBufferPointers
906
907 ;stuff two $55 bytes into the buffer, which we "read" above
908 EBDD A9 55 lda #$55
909 EBDF A0 00 ldy #0
910 EBE1 A2 02 ldx #2
911 EBE3 aaloop:
912 EBE3 91 32 sta (bufrlo),y
913 EBE5 E6 32 D0 02 E6 33 inw bufrlo
914 EBEB CA D0 F5 dex:bne aaloop
915
916 ;reset checksum for two $55 bytes and receive frame
917 EBEE 0A asl
918 EBEF 85 31 sta chksum
919
920 EBF1 20 FC E9 jsr SIOReceive.use_checksum
921 EBF4 4C 38 EA jmp SIOReceiveStop
922
923 ;-------------------------------------------------------------------------
924 ; We have to be VERY careful when reading (RTCLOK+2, VCOUNT), because
925 ; the VBI can strike in between. First, we double-check RTCLOK+2 to see
926 ; if it has changed. If so, we retry the read. Second, we check if
927 ; VCOUNT=124, which corresponds to lines 248/249. This can correspond to
928 ; either before or after the VBI -- with CRITIC off the VBI ends around
929 ; (249, 20-50) -- so we don't know which side of the frame boundary we're
930 ; on.
931 ;
932 EBF7 readtimer:
933 EBF7 A4 14 ldy rtclok+2
934 EBF9 AD 0B D4 lda vcount
935 EBFC C4 14 cpy rtclok+2
936 EBFE D0 F7 bne readtimer
937 EC00 C9 7C cmp #124
938 EC02 F0 F3 beq readtimer
939 EC04 60 rts
940
941 EC05 correct_time:
942 EC05 38 sec
943 EC06 E9 7C sbc #124
944 EC08 B0 03 bcs time_ok
945 EC0A 6D 15 03 adc temp3
946 EC0D time_ok:
947 EC0D 60 rts
948
949 .endp
950
249 EC0E _KERNEL_REPORT_MODULE_SIZE 'Serial Input/Output (SIO)', $EDEA-$E944
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $EDEA-$E944, ')', ' ', 'Serial Input/Output (SIO)'
1 $EC0E -> $0423($04A6) Serial Input/Output (SIO)
3 = EC0E .def ?@_kernel_lastpt = *
Source: source/main.xasm
250
251 EC0E icl 'disk.s'
Source: source/Shared/disk.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Disk Routines
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 EC0E .proc DiskInit
11 .if _KERNEL_XLXE
12 ;set disk sector size to 128 bytes
13 EC0E A9 80 8D D5 02 A9 + mwa #$80 dsctln
14 .endif
15 EC18 60 rts
16 .endp
17
18 ;==========================================================================
19 ; Disk handler routine (pointed to by DSKINV)
20 ;
21 ; Exit:
22 ; A = command byte (undocumented; required by Pooyan)
23 ; Y = status
24 ; N = 1 if error, 0 if success (high bit of Y)
25 ; C = 1 if command is >=$21 (undocumented; required by Arcade Machine)
26 ;
27 EC19 .proc DiskHandler
28 EC19 A9 31 8D 00 03 mva #$31 ddevic
29 EC1E A9 0F 8D 06 03 mva #$0f dtimlo
30
31 ;check for status command
32 EC23 AD 02 03 lda dcomnd
33 EC26 8D 3B 02 sta ccomnd
34 EC29 C9 53 cmp #$53
35 EC2B D0 20 bne notStatus
36
37 EC2D A9 EA lda #<dvstat
38 EC2F 8D 04 03 sta dbuflo
39 EC32 A9 02 lda #>dvstat
40 EC34 8D 05 03 sta dbufhi
41 EC37 0A asl ;hack to save a byte to get $04 since >dvstat is $02
42 EC38 8D 08 03 sta dbytlo
43 EC3B A9 00 lda #0
44 EC3D 8D 09 03 sta dbythi
45
46 EC40 20 6B EC jsr do_read
47 EC43 30 07 bmi xit
48
49 ;update format timeout
50 EC45 AE EC 02 8E 46 02 mvx dvstat+2 dsktim
51 EC4B AA tax
52 EC4C xit:
53 EC4C 60 rts
54
55 EC4D notStatus:
56
57 ;set disk sector length
58 .if _KERNEL_XLXE
59 EC4D AC D5 02 8C 08 03 + mwy dsctln dbytlo
60 .else
61 mwy #$80 dbytlo
62 .endif
63
64 ;check for put/write
65 .if _KERNEL_XLXE
66 EC59 C9 50 cmp #$50
67 EC5B F0 1D beq do_write
68 .endif
69 EC5D C9 57 cmp #$57
70 EC5F F0 19 beq do_write
71
72 ;check for format, or else assume it's a read command ($52) or similar
73 EC61 C9 21 cmp #$21
74 EC63 D0 06 bne do_read
75
76 ;it's format... use the format timeout
77 EC65 AD 46 02 8D 06 03 mva dsktim dtimlo
78
79 EC6B do_read:
80 EC6B A9 40 lda #$40
81 EC6D do_io:
82 EC6D 8D 03 03 sta dstats
83 EC70 20 59 E4 jsr siov
84
85 ;load disk command back into A (required by Pooyan)
86 ;emulate compare against format command (required by Arcade Machine)
87 ;sort-of emulate compare against status (required by Micropainter)
88 EC73 AD 02 03 lda dcomnd
89 EC76 C0 00 cpy #0 ;!! Atari800WinPlus's SIO patch doesn't set STATUS
90 EC78 38 sec
91 EC79 60 rts
92
93 EC7A do_write:
94 EC7A A9 80 lda #$80
95 EC7C D0 EF bne do_io
96 .endp
252 EC7E _KERNEL_REPORT_MODULE_SIZE 'Disk Handler', $EE78-$EDEA
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $EE78-$EDEA, ')', ' ', 'Disk Handler'
1 $EC7E -> $0070($008E) Disk Handler
3 = EC7E .def ?@_kernel_lastpt = *
Source: source/main.xasm
253
254 EC7E icl 'printer.s'
Source: source/Shared/printer.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Printer Handler
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 EC7E .proc PrinterInit
12 ;set printer timeout to default
13 EC7E A9 1E 8D 14 03 mva #30 ptimot
14 EC83 60 rts
15 .endp
16
17 ;==========================================================================
18 EC84 .proc PrinterOpen
19 ;check for sideways mode and compute line size
20 EC84 A2 28 ldx #40
21 EC86 A5 2B lda icax2z
22 EC88 C9 53 cmp #$53
23 EC8A D0 02 A2 1D sne:ldx #29
24 EC8E 8E DF 02 stx pbufsz
25
26 EC91 A9 00 lda #0
27 EC93 8D DE 02 sta pbpnt
28
29 EC96 xit:
30 EC96 A0 01 ldy #1
31 EC98 60 rts
32 .endp
33
34 ;==========================================================================
35 = EC99 PrinterClose = _PrinterPutByte.close_entry
36 = ECA0 PrinterPutByte = _PrinterPutByte.put_entry
37
38 EC99 .proc _PrinterPutByte
39 EC99 close_entry:
40 ;check if we have anything in the buffer
41 EC99 AD DE 02 lda pbpnt
42
43 ;exit if buffer is empty
44 EC9C F0 F8 beq PrinterOpen.xit
45
46 ;fall through to put with EOL
47 EC9E A9 9B lda #$9b
48
49 ECA0 put_entry:
50 ;preload buffer index (useful later)
51 ECA0 AE DE 02 ldx pbpnt
52
53 ;check for EOL
54 ECA3 C9 9B cmp #$9b
55 ECA5 F0 0E beq do_eol
56
57 ;mask off MSB
58 ECA7 29 7F and #$7f
59
60 ;put char and advance
61 ECA9 9D C0 03 sta prnbuf,x
62 ECAC E8 inx
63 ECAD 8E DE 02 stx pbpnt
64
65 ;check for end of line and exit if not
66 ECB0 EC DF 02 cpx pbufsz
67 ECB3 90 E1 bcc PrinterOpen.xit
68
69 ;fall through to EOL
70
71 ECB5 do_eol:
72 ;fill remainder of buffer with spaces
73 ECB5 A9 20 lda #$20
74 ECB7 fill_loop:
75 ECB7 EC DF 02 cpx pbufsz
76 ECBA B0 06 bcs fill_done
77 ECBC 9D C0 03 sta prnbuf,x
78 ECBF E8 inx
79 ECC0 90 F5 bcc fill_loop
80 ECC2 fill_done:
81
82 ;send line to printer
83 ECC2 A0 0A ldy #10
84 ECC4 B9 E3 EC 99 FF 02 + mva:rne iocbdat-1,y ddevic-1,y-
85
86 ;empty buffer
87 ECCD 8C DE 02 sty pbpnt
88
89 ;set line length
90 ECD0 8E 08 03 stx dbytlo
91
92 ;Compute AUX1 byte from length.
93 ;
94 ;Note that the OS manual is wrong -- this byte needs to go into AUX1 and
95 ;not AUX2 as the manual says.
96 ;
97 ; normal (40): 00101000 -> 01001110 ($4E 'N')
98 ; sideways (29): 00011101 -> 01010011 ($53 'S')
99 ; 010_1I1_
100 ECD3 8A txa
101 ECD4 29 15 and #%00010101
102 ECD6 49 4E eor #%01001110
103 ECD8 8D 0A 03 sta daux1 ;set AUX1 to indicate width to device
104
105 ;send to printer and exit
106 ECDB do_io:
107 ECDB AD 14 03 8D 06 03 mva ptimot dtimlo
108 ECE1 4C 59 E4 jmp siov
109
110 ECE4 iocbdat:
111 ECE4 40 dta $40 ;device
112 ECE5 01 dta $01 ;unit
113 ECE6 57 dta $57 ;command 'W'
114 ECE7 80 dta $80 ;input/output mode (write)
115 ECE8 C0 03 dta a(prnbuf) ;buffer address
116 ECEA 00 00 dta a(0) ;timeout
117 ECEC 00 00 dta a(0) ;buffer length
118 .endp
119
120 ;==============================================================================
121 ECEE .proc PrinterGetStatus
122 ;setup parameter block
123 ECEE A2 09 ldx #9
124 ECF0 BD 05 ED 9D 00 03 + mva:rpl iocbdat,x ddevic,x-
125
126 ;issue status call
127 ECF9 20 DB EC jsr _PrinterPutByte.do_io
128 ECFC 30 06 bmi error
129
130 ;update timeout
131 ECFE AD EC 02 8D 14 03 mva dvstat+2 ptimot
132
133 ED04 error:
134 ED04 60 rts
135
136 ED05 iocbdat:
137 ED05 40 dta $40 ;device
138 ED06 01 dta $01 ;unit
139 ED07 53 dta $53 ;command 'S'
140 ED08 40 dta $40 ;input/output mode (read)
141 ED09 EA 02 dta a(dvstat) ;buffer address
142 ED0B 00 00 dta a(0) ;timeout
143 ED0D 04 00 dta a(4) ;buffer length
144 .endp
145
146 ;==============================================================================
147 = E4CB PrinterGetByte = CIOExitNotSupported
148 = E4CB PrinterSpecial = CIOExitNotSupported
255 ED0F _KERNEL_REPORT_MODULE_SIZE 'Printer Handler', $EF41-$EE78
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $EF41-$EE78, ')', ' ', 'Printer Handler'
1 $ED0F -> $0091($00C9) Printer Handler
3 = ED0F .def ?@_kernel_lastpt = *
Source: source/main.xasm
256
257 ED0F icl 'cassette.s'
Source: source/Shared/cassette.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Cassette tape support
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 ED0F .proc CassetteInit
12 ;Set CBAUDL/CBAUDH to $05CC, the nominal POKEY divisor for 600
13 ;baud. We don't care about this, but it's documented in the OS
14 ;Manual.
15 ED0F A9 CC 8D EE 02 A9 + mwa #$05CC cbaudl
16 ED19 60 rts
17 .endp
18
19 ;==========================================================================
20 ; Cassette open routine.
21 ;
22 ; XL/XE OS behavior notes:
23 ; - Attempting to open for none (AUX1=$00) or read/write (AUX1=$0C)
24 ; results in a Not Supported error (146).
25 ; - Open for read gives one beep, while open for write gives two beeps.
26 ; - Break will break out of the wait.
27 ; - Ctrl+3 during the keypress causes an EOF error (!). This is a side
28 ; effect of reusing the keyboard handler.
29 ;
30 ; CSOPIV behavior:
31 ; - Does NOT set FTYPE (continuous mode flag).
32 ; - Sets read mode (WMODE).
33 ; - Does NOT require ICAX1Z or ICAX2Z to be set.
34 ;
35 = ED2D CassetteOpenRead = CassetteOpen.do_open_read
36 ED1A .proc CassetteOpen
37 ;stash continuous mode flag
38 ED1A A5 2B lda icax2z ;!! FIRST TWO BYTES CHECKED BY ARCHON
39 ED1C 85 3E sta ftype
40
41 ;check mode byte for read/write modes
42 ED1E A2 80 ldx #$80
43 ED20 A5 2A lda icax1z
44 ED22 29 0C and #$0c
45 ED24 C9 04 cmp #$04 ;read?
46 ED26 F0 05 beq found_read_mode
47 ED28 C9 08 cmp #$08 ;write?
48 ED2A F0 03 beq found_write_mode
49
50 ;invalid mode -- return not supported
51 ED2C 60 rts
52
53 ED2D do_open_read:
54 ED2D found_read_mode:
55 ED2D A2 00 ldx #$00
56 ED2F found_write_mode:
57 ED2F 8E 89 02 stx wmode
58
59 ;set cassette buffer size to 128 bytes and mark it empty
60 ED32 A9 80 lda #$80
61 ED34 85 3D sta bptr
62 ED36 8D 8A 02 sta blim
63
64 ;clear EOF flag
65 ED39 0A asl
66 ED3A 85 3F sta feof
67
68 ;request one beep for read, or two for write
69 ED3C 2C 89 02 bit wmode
70 ED3F 10 05 bpl one_ping_only
71
72 ED41 06 3D asl bptr ;!! - set bptr=0 when starting write
73
74 ED43 20 87 EE jsr CassetteBell
75
76 ED46 one_ping_only:
77 ED46 20 87 EE jsr CassetteBell
78
79 ;wait for a key press
80 ED49 20 69 FE jsr KeyboardGetByte
81 ED4C 30 20 bmi aborted
82
83 ;need to set up POKEY for writes now to write leader
84 ED4E 2C 89 02 bit wmode
85 ED51 10 08 bpl no_write_init
86 ED53 A9 FF lda #$ff
87 ED55 8D 0F 03 sta casflg
88 ED58 20 52 E9 jsr SIOSendEnable.no_irq_setup
89 ED5B no_write_init:
90
91 ;turn on motor (continuous mode or not)
92 ED5B A9 34 lda #$34
93 ED5D 8D 02 D3 sta pactl
94
95 ;wait for leader (9.6 seconds read, 19.2s write)
96 ED60 A2 00 ldx #0
97 ED62 2C 89 02 bit wmode
98 ED65 30 02 A2 01 smi:ldx #1
99 ED69 20 61 EE jsr CassetteWait
100
101 ;all done
102 ED6C A0 01 ldy #1
103 ED6E aborted:
104 ED6E 60 rts
105 .endp
106
107 ;==========================================================================
108 ED6F .proc CassetteClose
109 ;check if we are in write mode
110 ED6F AD 89 02 lda wmode ;!! FIRST TWO BYTES CHECKED BY ARCHON
111 ED72 10 0A bpl notwrite
112
113 ;check if we have data to write
114 ED74 A5 3D lda bptr
115 ED76 F0 03 beq nopartial
116
117 ;flush partial record ($FA)
118 ED78 20 E0 ED jsr CassetteFlush
119
120 ED7B nopartial:
121 ;write EOF record ($FE)
122 ED7B 20 E0 ED jsr CassetteFlush
123
124 ED7E notwrite:
125 ;stop the motor
126 ED7E A9 3C lda #$3c
127 ED80 8D 02 D3 sta pactl
128
129 ;kill audio
130 ED83 A0 00 ldy #0
131 ED85 8C 01 D2 sty audc1
132 ED88 8C 03 D2 sty audc2
133 ED8B 8C 07 D2 sty audc4
134
135 ;all done
136 ED8E C8 iny
137 ED8F 60 rts
138 .endp
139
140 ;==========================================================================
141 ED90 .proc CassetteGetByte
142 ;check if we have an EOF condition
143 ED90 A5 3F lda feof ;!! FIRST TWO BYTES CHECKED BY ARCHON
144 ED92 D0 1D bne xit_eof
145
146 ED94 fetchbyte:
147 ;check if we can still fetch a byte
148 ED94 A6 3D ldx bptr
149 ED96 EC 8A 02 cpx blim
150 ED99 F0 08 beq nobytes
151
152 ED9B BD 00 04 lda casbuf+3,x
153 ED9E E6 3D inc bptr
154 EDA0 A0 01 ldy #1
155 EDA2 60 rts
156
157 EDA3 nobytes:
158 ;fetch more bytes
159 EDA3 20 10 EE jsr CassetteReadBlock
160 EDA6 30 0B bmi error
161
162 ;check control byte
163 EDA8 AD FF 03 lda casbuf+2
164 EDAB C9 FE cmp #$fe
165 EDAD D0 05 bne noteofbyte
166
167 ;found $FE (EOF) - set flag and return EOF
168 EDAF 85 3F sta feof
169 EDB1 xit_eof:
170 EDB1 A0 88 ldy #CIOStatEndOfFile
171 EDB3 error:
172 EDB3 60 rts
173
174 EDB4 noteofbyte:
175 ;reset buffer ptr
176 EDB4 A2 00 86 3D mvx #0 bptr
177
178 ;assume full block first (128 bytes)
179 EDB8 A2 80 ldx #$80
180
181 ;check if it actually is one
182 EDBA C9 FC cmp #$fc
183 EDBC D0 06 bne not_full_block
184
185 EDBE init_new_block:
186 ;reset block length and loop back
187 EDBE 8E 8A 02 stx blim
188 EDC1 4C 94 ED jmp fetchbyte
189
190 EDC4 not_full_block:
191 ;check if we have a partial block
192 EDC4 C9 FA cmp #$fa
193 EDC6 D0 05 bne not_partial_block
194
195 ;set length of partial block and the jump to init+loop
196 EDC8 AE 7F 04 ldx casbuf+130
197 EDCB B0 F1 bcs init_new_block
198
199 EDCD not_partial_block:
200 ;uh oh... bad control byte.
201 EDCD A0 A3 ldy #CIOStatFatalDiskIO
202 EDCF 60 rts
203 .endp
204
205 ;==========================================================================
206 EDD0 .proc CassettePutByte
207 ;put a byte into the buffer
208 EDD0 A6 3D ldx bptr ;!! FIRST TWO BYTES CHECKED BY ARCHON
209 EDD2 9D 00 04 sta casbuf+3,x
210
211 ;bump and check if it's time to write
212 EDD5 E8 inx
213 EDD6 86 3D stx bptr
214 EDD8 EC 8A 02 cpx blim
215 EDDB B0 03 bcs CassetteFlush
216
217 ;all done
218 EDDD A0 01 ldy #1
219 EDDF 60 rts
220 .endp
221
222 ;==========================================================================
223 EDE0 .proc CassetteFlush
224 EDE0 A9 00 lda #0
225
226 ;set control byte based on buffer level
227 EDE2 A2 FE ldx #$fe ;empty -> EOF
228 EDE4 A4 3D ldy bptr ;get buffer level
229 EDE6 D0 08 bne not_empty ;skip not empty
230
231 ;clear buffer for EOF
232 EDE8 99 00 04 C8 10 FA sta:rpl casbuf+3,y+
233 EDEE 30 0C bmi is_empty ;!! - unconditional
234
235 EDF0 not_empty:
236 EDF0 A2 FC ldx #$fc ;load complete code
237 EDF2 CC 8A 02 cpy blim ;check if buffer is full
238 EDF5 B0 05 bcs is_complete ;skip if so
239 EDF7 A2 FA ldx #$fa ;load partial code
240 EDF9 8C 7F 04 sty casbuf+130 ;store level in last byte
241 EDFC is_complete:
242 EDFC is_empty:
243
244 ;store code
245 EDFC 8E FF 03 stx casbuf+2
246
247 ;reset buffer level
248 EDFF 85 3D sta bptr
249
250 ;setup sync bytes
251 EE01 A9 55 lda #$55
252 EE03 8D FD 03 sta casbuf
253 EE06 8D FE 03 sta casbuf+1
254
255 ;issue write request and exit
256 EE09 A2 80 ldx #$80
257 EE0B A0 50 ldy #'P'
258 EE0D 4C 14 EE jmp CassetteDoIO
259 .endp
260
261 ;==========================================================================
262 = E4C9 CassetteGetStatus = CIOExitSuccess
263 = E4CB CassetteSpecial = CIOExitNotSupported
264
265 ;==========================================================================
266 ; CassetteDoIO
267 ;
268 ; X = DSTATS value
269 ; Y = SIO command byte
270 ;
271 ; Note that SOUNDR must take effect each time a cassette I/O operation
272 ; occurs.
273 ;
274 = EE14 CassetteDoIO = _CassetteDoIO.do_io
275 = EE10 CassetteReadBlock = _CassetteDoIO.read_block
276
277 EE10 .proc _CassetteDoIO
278 EE10 read_block:
279 EE10 A2 40 ldx #$40
280 EE12 A0 52 ldy #'R'
281 EE14 do_io:
282 ;start the motor if not already running
283 EE14 A9 34 lda #$34
284 EE16 8D 02 D3 sta pactl
285
286 ;set up SIO read/write
287 EE19 8E 03 03 stx dstats
288 EE1C 8C 02 03 sty dcomnd
289 EE1F A9 FD 8D 04 03 A9 + mwa #casbuf dbuflo
290 EE29 A9 83 8D 08 03 A9 + mwa #131 dbytlo
291 EE33 A9 60 8D 00 03 mva #$60 ddevic
292 EE38 A9 00 8D 01 03 mva #0 dunit
293 EE3D A5 3E 8D 0B 03 mva ftype daux2
294
295 ;do it
296 EE42 20 59 E4 jsr siov
297
298 ;check if we are in continuous mode (again)
299 EE45 A5 3E lda ftype
300 EE47 30 0F bmi rolling_stop
301
302 ;not in continuous mode -- wait for post-write tone if writing
303 EE49 2C 89 02 bit wmode
304 EE4C 10 05 bpl no_pwt
305 EE4E A2 06 ldx #6
306 EE50 20 61 EE jsr CassetteWait
307 EE53 no_pwt:
308
309 ;stop the motor
310 EE53 A9 3C lda #$3c
311 EE55 8D 02 D3 sta pactl
312
313 EE58 rolling_stop:
314 EE58 A4 30 ldy status
315 EE5A 60 rts
316 .endp
317
318 ;==========================================================================
319 ;Entry:
320 ; X = delay type
321 ;
322 = EE61 CassetteWait = CassetteWaitLongShortCheck.normal_entry
323 EE5B .proc CassetteWaitLongShortCheck
324 EE5B 2C 0B 03 bit daux2
325 EE5E 10 01 E8 spl:inx
326 EE61 normal_entry:
327 EE61 20 13 E9 jsr SIOSetTimeoutVector
328 EE64 BC 79 EE ldy wait_table_lo,x
329 EE67 BD 80 EE lda wait_table_hi,x
330 EE6A AA tax
331 EE6B A9 01 lda #1
332 EE6D 8D 17 03 sta timflg
333 EE70 20 5F C1 jsr VBISetVector
334 EE73 AD 17 03 D0 FB lda:rne timflg
335 EE78 60 rts
336
337 EE79 wait_table_lo:
338 EE79 80 dta <$0480 ;$00 - write file leader (19.2 seconds NTSC)
339 EE7A 40 dta <$0240 ;$01 - read leader delay (9.6 seconds NTSC)
340 EE7B B4 dta <$00B4 ;$02 - long pre-record write tone (3.0s NTSC)
341 EE7C 0F dta <$000F ;$03 - short pre-record write tone (0.25s NTSC)
342 EE7D 78 dta <$0078 ;$04 - long read IRG (2.0s NTSC)
343 EE7E 0A dta <$000A ;$05 - short read IRG (0.16s NTSC)
344 EE7F 3C dta <$003C ;$06 - post record gap (1s NTSC)
345
346 EE80 wait_table_hi:
347 EE80 04 dta >$0480 ;$00 - write file leader (19.2 seconds NTSC)
348 EE81 02 dta >$0240 ;$01 - read leader delay (9.6 seconds NTSC)
349 EE82 00 dta >$00B4 ;$02 - long pre-record write tone (3.0s NTSC)
350 EE83 00 dta >$000F ;$03 - short pre-record write tone (0.25s NTSC)
351 EE84 00 dta >$0078 ;$04 - long read IRG (2.0s NTSC)
352 EE85 00 dta >$000A ;$05 - short read IRG (0.16s NTSC)
353 EE86 00 dta >$003C ;$06 - post record gap (1s NTSC)
354 .endp
355
356 ;==========================================================================
357 ; Sound a bell using the console speaker (cassette version)
358 ;
359 ; Modified:
360 ; A, X, Y
361 ;
362 EE87 .proc CassetteBell
363 EE87 A0 00 ldy #0
364 EE89 98 tya
365 EE8A soundloop:
366 EE8A A2 0A ldx #10
367 EE8C 48 pha
368 EE8D delay:
369 EE8D AD 0B D4 lda vcount
370 EE90 CD 0B D4 F0 FB cmp:req vcount
371 EE95 CA dex
372 EE96 D0 F5 bne delay
373 EE98 68 pla
374 EE99 49 08 eor #$08
375 EE9B 8D 1F D0 sta consol
376 EE9E D0 EA bne soundloop
377 EEA0 88 dey
378 EEA1 D0 E7 bne soundloop
379 EEA3 60 rts
380 .endp
258 EEA4 _KERNEL_REPORT_MODULE_SIZE 'Cassette Handler', $F0E3-$EF41
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $F0E3-$EF41, ')', ' ', 'Cassette Handler'
1 $EEA4 -> $0195($01A2) Cassette Handler
3 = EEA4 .def ?@_kernel_lastpt = *
Source: source/main.xasm
259
260 .ifdef _KERNEL_816
261 icl 'init816.s'
262 .else
263 EEA4 icl 'init.s'
Source: source/Shared/init.s
1 ; Altirra - Atari 800/800XL emulator
2 ; Kernel ROM replacement - Initialization
3 ; Copyright (C) 2008-2019 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 .if _KERNEL_XLXE
11 EEA4 .proc InitBootSignature
12 EEA4 5C 93 25 dta $5C,$93,$25
13 .endp
14 .endif
15
16 EEA7 .proc InitHandlerTable
17 EEA7 50 30 E4 dta c'P',a(printv)
18 EEAA 43 40 E4 dta c'C',a(casetv)
19 EEAD 45 00 E4 dta c'E',a(editrv)
20 EEB0 53 10 E4 dta c'S',a(screnv)
21 EEB3 4B 20 E4 dta c'K',a(keybdv)
22 .endp
23
24 EEB6 .nowarn .proc _InitReset
25 EEB6 run_diag:
26 ; start diagnostic cartridge
27 EEB6 6C FE BF jmp ($bffe)
28
29 = EEB9 .def :InitReset
30 ;mask interrupts and initialize CPU
31 EEB9 78 sei
32 EEBA D8 cld
33 EEBB A2 FF ldx #$ff
34 EEBD 9A txs
35
36 .if _KERNEL_XLXE
37 ;wait for everything to stabilize (0.1s) (XL/XE only)
38 EEBE A0 8C ldy #140
39 EEC0 stabilize_loop:
40 EEC0 CA D0 FD dex:rne
41 EEC3 88 dey
42 EEC4 D0 FA bne stabilize_loop
43
44 ;check for warmstart signature (XL/XE)
45 EEC6 A2 02 ldx #2
46 EEC8 warm_check:
47 EEC8 BD 3D 03 lda pupbt1,x
48 EECB DD A4 EE cmp InitBootSignature,x
49 EECE D0 06 bne cold_boot
50 EED0 CA dex
51 EED1 10 F5 bpl warm_check
52
53 EED3 4C 4F EF jmp InitWarmStart
54 .endif
55
56 = EED6 .def :InitColdStart
57 EED6 cold_boot:
58 ; 1. initialize CPU
59 EED6 78 sei
60 EED7 D8 cld
61 EED8 A2 FF ldx #$ff
62 EEDA 9A txs
63
64 ; 2. clear warmstart flag
65 EEDB E8 inx
66 EEDC 86 08 stx warmst
67
68 ; 3. test for diagnostic cartridge
69 EEDE AD FC BF lda $bffc
70 EEE1 D0 17 bne not_diag
71 EEE3 A2 FF ldx #$ff
72 EEE5 EC FF BF cpx $bfff ;prevent diagnostic cart from activating if addr is $FFxx
73 EEE8 F0 10 beq not_diag
74 EEEA 8E FC BF stx $bffc
75 EEED CD FC BF cmp $bffc
76 EEF0 8D FC BF sta $bffc
77 EEF3 D0 05 bne not_diag
78
79 ; is it enabled?
80 EEF5 2C FD BF bit $bffd
81 EEF8 30 BC bmi run_diag
82
83 EEFA not_diag:
84
85 EEFA 20 80 EF jsr InitHardwareReset
86
87 .if _KERNEL_XLXE
88 ;check for OPTION and enable BASIC (note that we do NOT set BASICF just yet)
89 EEFD A9 04 lda #4
90 EEFF 2C 1F D0 bit consol
91 EF02 F0 12 beq no_basic
92
93 .ifdef _KERNEL_SOFTKICK
94 ldx #$fc
95 .else
96 EF04 A2 FD ldx #$fd
97 .endif
98
99 ;check for keyboard present + SELECT or no keyboard + no SELECT and enable game if so
100 EF06 AD 12 D0 lda trig2 ;check keyboard present (1 = present)
101 EF09 0A asl
102 EF0A 4D 1F D0 eor consol ;XOR against select (0 = pressed)
103 EF0D 29 02 and #$02
104
105 .ifdef _KERNEL_SOFTKICK
106 seq:ldx #$be
107 .else
108 EF0F F0 02 A2 BF seq:ldx #$bf
109 .endif
110
111 EF13 8E 01 D3 stx portb ;enable GAME or BASIC
112
113 EF16 no_basic:
114 .endif
115
116 ; 4. measure memory -> tramsz
117 EF16 20 B0 EF jsr InitMemory
118
119 ; 6. clear memory from $0008 up to [tramsz,0]
120 .ifdef _KERNEL_SOFTKICK
121 ldx #$50
122 .else
123 EF19 A6 06 ldx tramsz
124 .endif
125 EF1B A0 08 ldy #8
126 EF1D A9 00 85 66 mva #0 a1
127 EF21 85 67 sta a1+1
128 EF23 clearloop:
129 EF23 91 66 C8 D0 FB sta:rne (a1),y+
130 EF28 E6 67 inc a1+1
131 EF2A CA dex
132 EF2B D0 F6 bne clearloop
133
134 .if _KERNEL_XLXE
135 ;Blip the self test ROM for a second -- this is one way that Altirra detects
136 ;that Option has been used by the OS. The XL/XE OS does this as part of its
137 ;ROM checksum routine (which we don't bother with).
138 EF2D AE 01 D3 ldx portb
139 EF30 8A txa
140 EF31 29 7F and #$7f
141 EF33 8D 01 D3 sta portb
142 EF36 8E 01 D3 stx portb
143 .endif
144
145 ; 7. set dosvec to blackboard routine
146 .if _KERNEL_USE_BOOT_SCREEN
147 EF39 A9 9B 85 0A A9 E4 + mwa #SelfTestEntry dosvec
148 .else
149 mwa #Blackboard dosvec
150 .endif
151
152 ; 8. set coldstart flag
153 EF41 CE 44 02 dec coldst ;!! coldst=0 from clear loop above, now $ff
154
155 .if _KERNEL_XLXE
156 ; set BASIC flag
157 EF44 AD 01 D3 lda portb
158 EF47 29 02 and #$02
159 EF49 8D F8 03 sta basicf
160 .endif
161
162 ; 9. set screen margins
163 ; 10. initialize RAM vectors
164 ; 11. set misc database values
165 ; 12. enable IRQ interrupts
166 ; 13. initialize device table
167 ; 14. initialize cartridges
168 ; 15. use IOCB #0 to open screen editor (E)
169 ; 16. wait for VBLANK so screen is initialized
170 ; 17. do cassette boot, if it was requested
171 ; 18. do disk boot
172 ; 19. reset coldstart flag
173 ; 20. run cartridges or blackboard
174 EF4C 4C EE EF jmp InitEnvironment
175 .endp
176
177 ;==============================================================================
178 EF4F .proc InitWarmStart
179 ; A. initialize CPU
180 ;
181 ; Undocumented: Check if cold start completed (COLDST=0); if not, force
182 ; a cold start. ACTris 2.1 relies on this since its boot doesn't reset
183 ; COLDST. This is also required to work on Atari800WinPLus, which doesn't
184 ; clear memory on a cold start.
185 ;
186 EF4F 78 sei ;!! FIRST TWO BYTES CHECKED BY ARCHON
187 EF50 AD 44 02 lda coldst
188 EF53 D0 81 bne InitColdStart
189 EF55 D8 cld
190 EF56 A2 FF ldx #$ff
191 EF58 9A txs
192
193 ; B. set warmstart flag
194 EF59 86 08 stx warmst
195
196 ; reinitialize hardware without doing a full clear
197 EF5B 20 80 EF jsr InitHardwareReset
198
199 .if _KERNEL_XLXE
200 ; reinitialize BASIC
201 EF5E AD F8 03 lda basicf
202 EF61 D0 05 A9 FD 8D 01 + sne:mva #$fd portb
203 .endif
204
205 ; C. check for diag, measure memory, clear hw registers
206 EF68 20 B0 EF jsr InitMemory
207
208 ; D. zero 0010-007F and 0200-03EC (must not clear BASICF).
209 EF6B A2 60 ldx #$60
210 EF6D A9 00 lda #0
211 EF6F 95 0F CA D0 FB sta:rne $0f,x-
212
213 EF74 dbclear:
214 EF74 9D 00 02 sta $0200,x
215 EF77 9D ED 02 sta $02ed,x
216 EF7A E8 inx
217 EF7B D0 F7 bne dbclear
218
219 ; E. steps 9-16 above
220 ; F. if cassette boot was successful on cold boot, execute cassette init
221 ; G. if disk boot was successful on cold boot, execute disk init
222 ; H. same as steps 19 and 20
223 EF7D 4C EE EF jmp InitEnvironment
224 .endp
225
226 ;==============================================================================
227 EF80 .proc InitHardwareReset
228 ; clear all hardware registers
229 EF80 A0 00 ldy #0
230 EF82 98 tya
231 EF83 hwclear:
232 EF83 99 00 D0 sta $d000,y
233 EF86 99 00 D2 sta $d200,y
234 EF89 99 00 D4 sta $d400,y
235 EF8C C8 iny
236 EF8D D0 F4 bne hwclear
237
238 ;initialize PIA
239 EF8F A9 3C lda #$3c
240 EF91 A2 38 ldx #$38
241
242 .ifdef _KERNEL_SOFTKICK
243 stx pactl ;switch to DDRA
244 sty porta ;portA -> input
245 sta pactl ;switch to IORA
246 sty porta ;portA -> $00
247 sta pbctl ;switch to IORB
248 dey
249 dey
250 sty portb ;portB -> $FE
251 stx pbctl ;switch to DDRB
252 iny
253 sty portb ;portB -> all output
254 sta pbctl ;switch to IORB
255 .elseif _KERNEL_XLXE
256 EF93 8E 02 D3 stx pactl ;switch to DDRA
257 EF96 8C 00 D3 sty porta ;portA -> input
258 EF99 8D 02 D3 sta pactl ;switch to IORA
259 EF9C 8C 00 D3 sty porta ;portA -> $00
260 EF9F 8D 03 D3 sta pbctl ;switch to IORB
261 EFA2 88 dey
262 EFA3 8C 01 D3 sty portb ;portB -> $FF
263 EFA6 8E 03 D3 stx pbctl ;switch to DDRB
264 EFA9 8C 01 D3 sty portb ;portB -> all output
265 EFAC 8D 03 D3 sta pbctl ;switch to IORB
266 .else
267 stx pactl ;switch to DDRA
268 stx pbctl ;switch to DDRB
269 sty porta ;portA -> input
270 sty portb ;portB -> input
271 sta pactl ;switch to IORA
272 sta pbctl ;switch to IORB
273 sty porta ;portA -> $00
274 sty portb ;portB -> $00
275 .endif
276 EFAF 60 rts
277 .endp
278
279 ;==============================================================================
280 EFB0 .proc InitMemory
281 ; 4. measure memory -> tramsz
282 EFB0 A0 00 ldy #$00
283 EFB2 84 64 sty adress
284 EFB4 A2 02 ldx #$02
285 EFB6 pageloop:
286 EFB6 86 65 stx adress+1
287 EFB8 B1 64 lda (adress),y
288 EFBA 49 FF eor #$ff
289 EFBC 91 64 sta (adress),y
290 EFBE D1 64 cmp (adress),y
291 EFC0 D0 09 bne notRAM
292 EFC2 49 FF eor #$ff
293 EFC4 91 64 sta (adress),y
294 EFC6 E8 inx
295
296 .if _KERNEL_XLXE
297 EFC7 E0 C0 cpx #$c0
298 .else
299 cpx #$d0
300 .endif
301
302 EFC9 D0 EB bne pageloop
303 EFCB notRAM:
304 EFCB 86 06 stx tramsz
305
306 EFCD 60 rts
307 .endp
308
309 ;==============================================================================
310 EFCE .proc InitVectorTable1
311 EFCE 55 C0 dta a(IntExitHandler_None) ;$0200 VDSLST
312 EFD0 54 C0 dta a(IntExitHandler_A) ;$0202 VPRCED
313 EFD2 54 C0 dta a(IntExitHandler_A) ;$0204 VINTER
314 EFD4 54 C0 dta a(IntExitHandler_A) ;$0206 VBREAK
315 EFD6 CE FE dta a(KeyboardIRQ) ;$0208 VKEYBD
316 EFD8 43 EA dta a(SIOInputReadyHandler) ;$020A VSERIN
317 EFDA 8C EA dta a(SIOOutputReadyHandler) ;$020C VSEROR
318 EFDC C5 EA dta a(SIOOutputCompleteHandler) ;$020E VSEROC
319 EFDE 54 C0 dta a(IntExitHandler_A) ;$0210 VTIMR1
320 EFE0 54 C0 dta a(IntExitHandler_A) ;$0212 VTIMR2
321 EFE2 54 C0 dta a(IntExitHandler_A) ;$0214 VTIMR4
322 EFE4 D1 C1 dta a(IrqHandler) ;$0216 VIMIRQ
323 EFE6 end:
324 .endp
325
326 EFE6 .proc InitVectorTable2
327 EFE6 0C C0 dta a(VBIStage1) ;$0222 VVBLKI
328 EFE8 50 C0 dta a(VBIExit) ;$0224 VVBLKD
329 EFEA 00 00 dta a(0) ;$0226 CDTMA1
330 .endp
331
332 EFEC krpdel_table:
333 EFEC 30 28 dta 48,40
334
335 ;==============================================================================
336 EFEE .proc InitEnvironment
337 EFEE A5 06 8D E4 02 mva tramsz ramsiz
338
339 .if _KERNEL_XLXE
340 ; set warmstart signature -- must be done before cart init, because
341 ; SDX doesn't return.
342 EFF3 A2 03 ldx #3
343 EFF5 BD A3 EE 9D 3C 03 + mva:rne InitBootSignature-1,x pupbt1-1,x-
344 .endif
345
346 ; 9. set screen margins
347 EFFE A9 02 85 52 mva #2 lmargn
348 F002 A9 27 85 53 mva #39 rmargn
349
350 ;set PAL/NTSC flag (XL/XE only)
351 .if _KERNEL_XLXE
352 F006 A2 00 ldx #0
353 F008 AD 14 D0 lda pal
354 F00B A0 06 ldy #6
355 F00D 29 0E and #$0e
356 F00F D0 04 bne is_ntsc
357 F011 D0 01 E8 sne:inx
358 F014 88 dey
359 F015 is_ntsc:
360 F015 86 62 stx palnts
361 F017 8C DA 02 sty keyrep
362 F01A BD EC EF 8D D9 02 mva krpdel_table,x krpdel
363 .endif
364
365 ; 10. initialize RAM vectors
366
367 ;VDSLST-VIMIRQ
368 F020 A2 17 ldx #[.len InitVectorTable1]-1
369 F022 BD CE EF 9D 00 02 + mva:rpl InitVectorTable1,x vdslst,x-
370
371 ;VVBLKI-CDTMA1
372 F02B A2 05 ldx #[.len InitVectorTable2]-1
373 F02D BD E6 EF 9D 22 02 + mva:rpl InitVectorTable2,x vvblki,x-
374
375 F036 A9 11 8D 36 02 A9 + mwa #KeyboardBreakIRQ brkky
376
377 ; 11. set misc database values
378 F040 A2 FF ldx #$ff
379 F042 86 11 stx brkkey
380 F044 E8 inx
381 F045 8E E5 02 stx memtop
382 F048 8E E7 02 stx memlo
383 F04B A5 06 8D E6 02 mva tramsz memtop+1
384 F050 A2 07 8E E8 02 mvx #$07 memlo+1
385
386 F055 20 0E EC jsr DiskInit
387 F058 20 C4 F5 jsr ScreenInit
388 ;jsr DisplayInit
389 F05B 20 3F FE jsr KeyboardInit
390
391 .if _KERNEL_PRINTER_SUPPORT
392 F05E 20 7E EC jsr PrinterInit
393 .endif
394
395 ; 13. initialize device table (HATABS has already been cleared)
396 ; NOTE: The R: emulation relies on this being before CIOINV is invoked.
397 F061 A2 0E ldx #14
398 F063 BD A7 EE 9D 1A 03 + mva:rpl InitHandlerTable,x hatabs,x-
399
400 ;jsr CassetteInit
401 F06C 20 6E E4 jsr cioinv
402 F06F 20 EB E7 jsr SIOInit
403 F072 20 75 C1 jsr IntInitInterrupts
404
405 ; check for START key, and if so, set cassette boot flag
406 F075 AD 1F D0 lda consol
407 F078 29 01 and #1
408 F07A 49 01 eor #1
409 F07C 8D E9 03 sta ckey
410
411 .if _KERNEL_PBI_SUPPORT
412 F07F 20 4E C2 jsr PBIScan
413 .endif
414
415 ; 12. enable IRQ interrupts
416 ;
417 ; We do this later than the original OS specification because the PBI scan needs
418 ; to happen with IRQs disabled (a PBI device with interrupts may not have been
419 ; inited yet) and that PBI scan in turn needs to happen after HATABS has been
420 ; set up. There's no harm in initing HATABS with interrupts masked, so we do so.
421
422 F082 58 cli
423
424 ; 14. initialize cartridges
425 F083 A9 00 85 07 mva #0 tstdat
426
427 .if !_KERNEL_XLXE
428 lda $9ffc
429 bne skipCartBInit
430 lda $9ffb
431 tax
432 eor #$ff
433 sta $9ffb
434 cmp $9ffb
435 stx $9ffb
436 beq skipCartBInit
437 jsr InitCartB
438 mva #1 tstdat
439 skipCartBInit:
440 .endif
441
442 F087 A9 00 85 06 mva #0 tramsz
443 F08B AD FC BF lda $bffc
444 F08E D0 18 bne skipCartAInit
445 F090 AD FB BF lda $bffb
446 F093 AA tax
447 F094 49 FF eor #$ff
448 F096 8D FB BF sta $bffb
449 F099 CD FB BF cmp $bffb
450 F09C 8E FB BF stx $bffb
451 F09F F0 07 beq skipCartAInit
452 F0A1 20 2D F1 jsr InitCartA
453 F0A4 A9 01 85 06 mva #1 tramsz
454 F0A8 skipCartAInit:
455
456 ; 15. use IOCB #0 ($0340) to open screen editor (E)
457 ;
458 ; NOTE: We _must_ leave $0C in the A register when invoking CIO. Pooyan
459 ; relies on $0C being left in CIOCHR after the last call to CIO before
460 ; disk boot!
461
462 F0A8 A9 03 8D 42 03 mva #$03 iccmd ;OPEN
463 F0AD A9 33 8D 44 03 A9 + mwa #ScreenEditorName icbal
464 F0B7 A9 0C 8D 4A 03 mva #$0c icax1 ;read/write, no forced read
465 F0BC A2 00 ldx #0
466 F0BE 8E 4B 03 stx icax2 ;mode 0
467 F0C1 20 56 E4 jsr ciov
468
469 ; 16. wait for VBLANK so screen is initialized
470 F0C4 A5 14 lda rtclok+2
471 F0C6 waitvbl:
472 F0C6 C5 14 cmp rtclok+2
473 F0C8 F0 FC beq waitvbl
474
475 ;-------------------------------------------------------------------------
476 ; Pre-boot hook (AltirraOS-specific)
477 ;
478
479 .ifdef _KERNEL_PRE_BOOT_HOOK
480 jsr InitPreBootHook
481 .endif
482
483 ;-------------------------------------------------------------------------
484 ; Run cartridge/cassette/disk
485 ;
486
487 ; 17. do cassette boot, if it was requested
488 ; F. if cassette boot was successful on cold boot, execute cassette init
489
490 ; The cold boot path must check the warm start flag and switch paths if
491 ; necessary. SpartaDOS X relies on being able to set the warm start
492 ; flag from its cart init handler.
493 ;
494 ; Disk boot must be attempted after cassette boot. Besides support for
495 ; using DOS from tape-based software, this is also required by the tape
496 ; version of Fun With Spelling (featuring Heathcliff), which depends on
497 ; the SIO request causing the tape start vector to be invoked shortly
498 ; after VBI so it can do an unsafe screen swap.
499 ;
500
501 F0CA A5 08 lda warmst
502 F0CC D0 0B bne reinitcas
503
504 F0CE AD E9 03 lda ckey
505 F0D1 F0 0F beq postcasboot
506 F0D3 20 A4 F1 jsr BootCassette
507 F0D6 4C E2 F0 jmp postcasboot
508
509 F0D9 reinitcas:
510 F0D9 A9 02 lda #2
511 F0DB 24 09 bit boot?
512 F0DD F0 03 beq postcasboot
513 F0DF 20 37 F1 jsr InitCassetteBoot
514 F0E2 postcasboot:
515
516 ;-------------------------------------------------------------------------
517 ; 18. do disk boot
518 ; G. if disk boot was successful on cold boot, execute disk init
519 ;
520 ; For 800 mode, we must check if either cart A or cart B is present,
521 ; doing a disk boot if either there are no carts or one of the carts
522 ; requests disk boot. For the XL/XE case, cart B doesn't exist and we
523 ; can simplify the logic.
524 ;
525
526 F0E2 A5 08 lda warmst
527 F0E4 D0 10 bne reinitDisk
528
529 .if !_KERNEL_XLXE
530
531 ;check if we have cart B
532 lda tstdat
533 bne have_cart_b
534
535 ;no cart B -- if no cart A either, do disk boot
536 ldx tramsz ;cart A
537 beq boot_disk
538 bne have_cart_a
539
540 have_cart_b:
541 ;have cart B - grab boot disk flag (bit 0)
542 lda $9ffd
543
544 ;merge cart A's flags if it is present
545 ldx tramsz
546 beq no_cart_a
547
548 have_cart_a:
549 ora $bffd
550
551 no_cart_a:
552 ;skip disk boot if neither cart requested it
553 lsr
554 bcc skip_disk_boot
555
556 .else
557
558 ;check for cart A requesting boot
559 F0E6 A5 06 lda tramsz
560 F0E8 F0 06 beq boot_disk
561
562 ;have cart A - boot disk if requested
563 F0EA AD FD BF lda $bffd
564 F0ED 4A lsr
565 F0EE 90 1B bcc skip_disk_boot
566
567 .endif
568
569 F0F0 boot_disk:
570 F0F0 20 3B F1 jsr BootDisk
571 F0F3 4C FE F0 jmp post_disk_boot
572
573 F0F6 reinitDisk:
574 F0F6 A5 09 lda boot?
575 F0F8 4A lsr
576 F0F9 90 10 bcc skip_disk_boot
577 F0FB 20 34 F1 jsr InitDiskBoot
578
579 F0FE post_disk_boot:
580 .if _KERNEL_XLXE
581 ; (XL/XE only) do type 3 poll or reinit handlers
582 ; !! - must only do this if a disk boot occurs; Pole Position audio breaks if
583 ; we do this and hit SKCTL before booting the cart
584 F0FE A5 08 lda warmst
585 F100 D0 06 bne reinit_handlers
586 F102 20 6A C4 jsr PHStartupPoll
587 F105 4C 0B F1 jmp post_reinit
588 F108 reinit_handlers:
589 F108 20 2E C4 jsr PHReinitHandlers
590 F10B post_reinit:
591 .endif
592
593 F10B skip_disk_boot:
594
595 ;-------------------------------------------------------------------------
596 ; H. same as steps 19 and 20
597 ; 19. reset coldstart flag
598
599 F10B A2 00 ldx #0
600 F10D 8E 44 02 stx coldst
601
602 ;-------------------------------------------------------------------------
603 ; 20. run cartridges or blackboard
604 ;
605 ; Weird quirk here: if the left cart is absent or doesn't request
606 ; cart start, and the right cart is present and also doesn't request
607 ; cart start, OS-B endlessly does disk boots instead of running (DOSVEC).
608 ; We don't emulate this behavior for now since in practice it just seems
609 ; useless, boot looping until DOS crashes. It is moot starting with the
610 ; 1200XL DOS due to support for cart B being dropped.
611 ;
612
613 ; try to boot cart A
614 F110 A9 04 lda #$04
615 F112 A6 06 ldx tramsz
616 F114 F0 08 beq NoBootCartA
617 F116 2C FD BF bit $bffd
618 F119 F0 03 6C FA BF seq:jmp ($bffa)
619 F11E NoBootCartA:
620
621 ; try to boot cart B
622 F11E A6 07 ldx tstdat
623 F120 F0 08 beq NoBootCartB
624 F122 2C FD 9F bit $9ffd
625 F125 F0 03 6C FA 9F seq:jmp ($9ffa)
626 F12A NoBootCartB:
627
628 ; run blackboard
629 F12A 6C 0A 00 jmp (dosvec)
630
631 F12D InitCartA:
632 F12D 6C FE BF jmp ($bffe)
633
634 F130 InitCartB:
635 F130 6C FE 9F jmp ($9ffe)
636
637 F133 ScreenEditorName:
638 F133 45 dta c"E"
639
640 .endp
641
642 ;==============================================================================
643 F134 .proc InitDiskBoot
644 F134 6C 0C 00 jmp (dosini)
645 .endp
646
647 F137 .proc InitCassetteBoot
648 .endp
649 F137 6C 02 00 jmp (casini)
650
651 ;==============================================================================
652
653 F13A EA nop
264 .endif
265
266 F13B icl 'boot.s'
Source: source/Shared/boot.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Boot Code
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 ; Disk boot routine.
12 ;
13 ; Exit:
14 ; DBUFLO/DBUFHI = $0400 (Undoc; required by Ankh and the 1.atr SMB demo)
15 ; Last sector in $0400 (Undoc; required by Ankh)
16 ;
17 F13B .proc BootDisk
18 ;issue a status request first to see if the disk is active; if this
19 ;doesn't come back, don't bother trying to read
20 F13B A9 53 lda #$53
21 F13D 8D 02 03 sta dcomnd
22 F140 A2 01 ldx #1
23 F142 8E 01 03 stx dunit
24 F145 20 53 E4 jsr dskinv
25 F148 30 3C bmi xit
26
27 ;read first sector to $0400
28 F14A A2 01 ldx #1
29 F14C 8E 01 03 stx dunit
30 F14F 8E 0A 03 stx daux1
31 F152 CA dex
32 F153 8E 04 03 stx dbuflo
33 F156 8E 0B 03 stx daux2
34 F159 A9 52 8D 02 03 mva #$52 dcomnd
35 F15E A9 04 8D 05 03 mva #$04 dbufhi
36 F163 20 53 E4 jsr dskinv
37 F166 30 1A bmi fail
38
39 F168 sector1_ok:
40 F168 A2 0C ldx #dosini
41 F16A 20 DF F1 jsr BootInitHeaders
42
43 ;load remaining sectors
44 F16D sectorloop:
45 ;copy sector from $0400 to destination (required by Ankh; see above)
46 ;bump destination address for next sector copy
47 F16D 20 0C F2 jsr BootCopyBlock
48
49 ;exit if this was the last sector (note that 0 means to load 256 sectors!)
50 F170 CE 41 02 dec dbsect
51 F173 F0 22 beq loaddone
52
53 ;increment sector (yes, this can overflow to 256)
54 F175 EE 0A 03 D0 03 EE + inw daux1
55
56 ;read next sector
57 F17D 20 53 E4 jsr dskinv
58
59 ;keep going if we succeeded
60 F180 10 EB bpl sectorloop
61
62 ;read failed
63 F182 fail:
64 F182 C0 8A cpy #SIOErrorTimeout
65 F184 D0 01 bne failmsg
66 F186 xit:
67 F186 60 rts
68
69 F187 failmsg:
70 .if _KERNEL_USE_BOOT_SCREEN
71 F187 st_loop:
72 F187 AD 01 D3 lda portb
73 F18A 49 80 eor #$80
74 F18C 8D 01 D3 sta portb
75 F18F 30 D7 bmi sector1_ok
76 F191 20 02 50 jsr BootScreen.boot_entry
77 F194 4C 87 F1 jmp st_loop
78 .else
79 jsr BootShowError
80 jmp BootDisk
81 .endif
82
83 F197 loaddone:
84 F197 20 FC F1 jsr BootRunLoader
85 F19A B0 EB bcs failmsg
86
87 ;Diskette Boot Process, step 7 (p.161 of the OS Manual) is misleading. It
88 ;says that DOSVEC is invoked after DOSINI, but actually that should NOT
89 ;happen here -- it happens AFTER cartridges have had a chance to run.
90 ;This is necessary for BASIC to gain control before DOS goes to load
91 ;DUP.SYS.
92 F19C 20 34 F1 jsr InitDiskBoot
93
94 ;Must not occur until after init routine is called -- SpartaDOS 3.2 does
95 ;an INC on this flag and never exits.
96 F19F A9 01 85 09 mva #1 boot?
97 F1A3 60 rts
98 .endp
99
100
101 ;============================================================================
102
103 F1A4 .proc BootCassette
104 ;set continuous mode -- must do this as CSOPIV doesn't
105 F1A4 A9 80 lda #$80
106 F1A6 85 3E sta ftype
107
108 ;open cassette device
109 F1A8 20 7D E4 jsr csopiv
110
111 ;read first block
112 F1AB 20 7A E4 jsr rblokv
113 F1AE 30 24 bmi load_failure
114
115 F1B0 A2 02 ldx #casini
116 F1B2 20 DF F1 jsr BootInitHeaders
117
118 F1B5 block_loop:
119 ;copy 128 bytes from CASBUF+3 ($0400) to destination
120 ;update destination pointer
121 F1B5 20 0C F2 jsr BootCopyBlock
122
123 ;read next block
124 ;we always need to do one more to catch the EOF block, which is
125 ;required by STDBLOAD2
126 F1B8 20 7A E4 jsr rblokv
127 F1BB 30 17 bmi load_failure
128
129 F1BD CE 41 02 dec dbsect
130 F1C0 D0 F3 bne block_loop
131
132 ;run loader
133 F1C2 20 FC F1 jsr BootRunLoader
134
135 ;run cassette init routine
136 F1C5 20 37 F1 jsr InitCassetteBoot
137
138 ;clear cassette boot key flag
139 F1C8 A9 00 lda #0
140 F1CA 8D E9 03 sta ckey
141
142 ;set cassette boot flag
143 F1CD A9 02 85 09 mva #2 boot?
144
145 ;run application
146 F1D1 6C 0A 00 jmp (dosvec)
147
148 F1D4 load_failure:
149 F1D4 A9 00 lda #0
150 F1D6 8D E9 03 sta ckey
151 F1D9 20 6F ED jsr CassetteClose
152 F1DC 4C 21 F2 jmp BootShowError
153 .endp
154
155 ;============================================================================
156 F1DF .proc BootInitHeaders
157 ;copy the first four bytes to DFLAGS, DBSECT, and BOOTAD
158 F1DF A0 FC ldy #$fc
159 F1E1 B9 04 03 99 44 01 + mva:rne $0400-$fc,y dflags-$fc,y+
160
161 ;copy boot address in BOOTAD to BUFADR
162 F1EA 85 16 sta bufadr+1
163 F1EC AD 42 02 lda bootad
164 F1EF 85 15 sta bufadr
165
166 ;copy init vector
167 F1F1 AD 04 04 95 00 AD + mwa $0404 0,x
168 F1FB 60 rts
169 .endp
170
171 ;============================================================================
172 F1FC .proc BootRunLoader
173 ;loader is at load address + 6
174 F1FC AD 42 02 lda bootad
175 F1FF 18 69 05 add #$05
176 F202 AA tax
177 F203 AD 43 02 lda bootad+1
178 F206 69 00 adc #0
179 F208 48 pha
180 F209 8A txa
181 F20A 48 pha
182 F20B 60 rts
183 .endp
184
185 ;============================================================================
186 F20C .proc BootCopyBlock
187 F20C A0 7F ldy #$7f
188 F20E B9 00 04 91 15 88 + mva:rpl $0400,y (bufadr),y-
189
190 F216 A5 15 lda bufadr
191 F218 49 80 eor #$80
192 F21A 85 15 sta bufadr
193 F21C 30 02 E6 16 smi:inc bufadr+1
194 F220 60 rts
195 .endp
196
197 ;============================================================================
198
199 F221 .proc BootShowError
200 F221 A2 F5 ldx #$f5
201 F223 msgloop:
202 F223 8A txa
203 F224 48 pha
204 F225 BD 3C F1 lda errormsg-$f5,x
205 F228 20 B8 FA jsr EditorPutByte
206 F22B 68 pla
207 F22C AA tax
208 F22D E8 inx
209 F22E D0 F3 bne msgloop
210 F230 60 rts
211
212 F231 errormsg:
213 F231 42 4F 4F 54 20 45 + dta 'BOOT ERROR',$9B
214 .endp
267 F23C _KERNEL_REPORT_MODULE_SIZE 'Monitor routines', $F3E4-$F0E3
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $F3E4-$F0E3, ')', ' ', 'Monitor routines'
1 $F23C -> $0398($0301) Monitor routines
3 = F23C .def ?@_kernel_lastpt = *
Source: source/main.xasm
268
269 F23C icl 'screen.s'
Source: source/Shared/screen.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Screen Handler
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;Display list:
11 ; 24 blank lines (3 bytes)
12 ; initial mode line with LMS (3 bytes)
13 ; mode lines
14 ; LMS for modes >4 pages
15 ; wait VBL (3 bytes)
16 ;
17 ; total is 8-10 bytes + mode lines
18
19 ; These are the addresses produced by the normal XL/XE OS:
20 ;
21 ; Normal Split, coarse Split, fine
22 ; Mode DL PF TX DL PF TX DL PF TX
23 ; 0 9C20 9C40 9F60 9C20 9C40 9F60 9C1F 9C40 9F60
24 ; 1 9D60 9D80 9F60 9D5E 9D80 9F60 9D5D 9D80 9F60
25 ; 2 9E5C 9E70 9F60 9E58 9E70 9F60 9E57 9E70 9F60
26 ; 3 9E50 9E70 9F60 9E4E 9E70 9F60 9E4D 9E70 9F60
27 ; 4 9D48 9D80 9F60 9D4A 9D80 9F60 9D49 9D80 9F60
28 ; 5 9B68 9BA0 9F60 9B6A 9BA0 9F60 9B69 9BA0 9F60
29 ; 6 9778 97E0 9F60 9782 97E0 9F60 9781 97E0 9F60
30 ; 7 8F98 9060 9F60 8FA2 9060 9F60 8FA1 9060 9F60
31 ; 8 8036 8150 9F60 8050 8150 9F60 804F 8150 9F60
32 ; 9 8036 8150 9F60 8036 8150 9F60 8036 8150 9F60
33 ; 10 8036 8150 9F60 8036 8150 9F60 8036 8150 9F60
34 ; 11 8036 8150 9F60 8036 8150 9F60 8036 8150 9F60
35 ; 12 9B80 9BA0 9F60 9B7E 9BA0 9F60 9B7D 9BA0 9F60
36 ; 13 9D6C 9D80 9F60 9D68 9D80 9F60 9D67 9D80 9F60
37 ; 14 8F38 9060 9F60 8F52 9060 9F60 8F51 9060 9F60
38 ; 15 8036 8150 9F60 8050 8150 9F60 804F 8150 9F60
39 ;
40 ; *DL = display list (SDLSTL/SDLSTH)
41 ; *PF = playfield (SAVMSC)
42 ; *TX = text window (TXTMSC)
43 ;
44 ; From this, we can derive a few things:
45 ; - The text window is always 160 ($A0) bytes below the ceiling.
46 ; - The playfield is always positioned to have enough room for
47 ; the text window, even though this wastes a little bit of
48 ; memory for modes 1, 2, 3, 4, and 13. This means that the
49 ; PF address does not have to be adjusted for split mode.
50 ; - The display list and playfield addresses are sometimes
51 ; adjusted in order to avoid crossing 1K boundaries for the
52 ; display list (gr.7) and 4K boundaries for the playfield (gr.8).
53 ; However, these are fixed offsets -- adjusting RAMTOP to $9F
54 ; does not remove the DL padding in GR.7 and breaks GR.7/8.
55 ; - Fine-scrolled modes take one additional byte for the extra
56 ; mode 2 line. In fact, it displays garbage that is masked by
57 ; a DLI that sets COLPF1 equal to COLPF2. (!)
58 ;
59 ; You might ask, why bother replicating these? Well, there are a
60 ; number of programs that rely on the layout of the default screen
61 ; and break if the memory addressing is different, such as ForemXEP.
62
63 .macro _SCREEN_TABLES_2
64
65 ;Mode Type Res Colors ANTIC Mem(unsplit) Mem(split)
66 ; 0 Text 40x24 1.5 2 960+32 (4) 960+32 (4)
67 ; 1 Text 20x24 5 6 480+32 (2) 560+32 (3)
68 ; 2 Text 20x12 5 7 240+20 (2) 360+22 (2)
69 ; 3 Bitmap 40x24 4 8 240+32 (2) 360+32 (2)
70 ; 4 Bitmap 80x48 2 9 480+56 (3) 560+52 (3)
71 ; 5 Bitmap 80x48 4 A 960+56 (4) 960+52 (4)
72 ; 6 Bitmap 160x96 2 B 1920+104 (8) 1760+92 (8)
73 ; 7 Bitmap 160x96 4 D 3840+104 (16) 3360+92 (14)
74 ; 8 Bitmap 320x192 1.5 F 7680+202 (32) 6560+174 (27)
75 ; 9 Bitmap 80x192 16 F 7680+202 (32) 6560+174 (27)
76 ; 10 Bitmap 80x192 9 F 7680+202 (32) 6560+174 (27)
77 ; 11 Bitmap 80x192 16 F 7680+202 (32) 6560+174 (27)
78 ; 12 Text 40x24 5 4 960+32 (4) 960+32 (4)
79 ; 13 Text 40x12 5 5 480+20 (2) 560+24 (3)
80 ; 14 Bitmap 160x192 2 C 3840+200 (16) 3360+172 (14)
81 ; 15 Bitmap 160x192 4 E 7680+202 (32) 6560+172 (27)
82
83 ;==========================================================================
84 ;
85 .proc ScreenPlayfieldSizesLo
86 dta <($10000-$03C0) ;gr.0 960 bytes = 40*24 = 40*24
87 dta <($10000-$0280) ;gr.1 640 bytes = 20*24 + 40*4 = 40*12 + 40*4
88 dta <($10000-$0190) ;gr.2 400 bytes = 10*24 + 40*4 = 40*6 + 40*4
89 dta <($10000-$0190) ;gr.3 400 bytes = 10*24 + 40*4 = 40*6 + 40*4
90 dta <($10000-$0280) ;gr.4 640 bytes = 10*48 + 40*4 = 40*12 + 40*4
91 dta <($10000-$0460) ;gr.5 1120 bytes = 20*48 + 40*4 = 40*24 + 40*4
92 dta <($10000-$0820) ;gr.6 2080 bytes = 20*96 + 40*4 = 40*48 + 40*4
93 dta <($10000-$0FA0) ;gr.7 4000 bytes = 40*96 + 40*4 = 40*96 + 40*4
94 dta <($10000-$1EB0) ;gr.8 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
95 dta <($10000-$1EB0) ;gr.9 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
96 dta <($10000-$1EB0) ;gr.10 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
97 dta <($10000-$1EB0) ;gr.11 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
98 dta <($10000-$0460) ;gr.12 1120 bytes = 40*24 + 40*4 = 40*24 + 40*4
99 dta <($10000-$0280) ;gr.13 640 bytes = 40*12 + 40*4 = 40*12 + 40*4
100 dta <($10000-$0FA0) ;gr.14 4000 bytes = 20*192 + 40*4 = 40*96 + 40*4
101 dta <($10000-$1EB0) ;gr.15 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
102 .endp
103
104 .proc ScreenPlayfieldSizesHi
105 dta >($10000-$03C0) ;gr.0
106 dta >($10000-$0280) ;gr.1
107 dta >($10000-$0190) ;gr.2
108 dta >($10000-$0190) ;gr.3
109 dta >($10000-$0280) ;gr.4
110 dta >($10000-$0460) ;gr.5
111 dta >($10000-$0820) ;gr.6
112 dta >($10000-$0FA0) ;gr.7
113 dta >($10000-$1EB0) ;gr.8
114 dta >($10000-$1EB0) ;gr.9
115 dta >($10000-$1EB0) ;gr.10
116 dta >($10000-$1EB0) ;gr.11
117 dta >($10000-$0460) ;gr.12
118 dta >($10000-$0280) ;gr.13
119 dta >($10000-$0FA0) ;gr.14
120 dta >($10000-$1EB0) ;gr.15
121 .endp
122
123 ;==========================================================================
124 ; ANTIC mode is in bits 0-3, PRIOR bits in 6-7.
125 ; DL 1K hop: bit 4
126 ; playfield 4K hop: bit 5
127 ;
128 .proc ScreenModeTable
129 dta $02,$06,$07,$08,$09,$0A,$0B,$1D,$3F,$7F,$BF,$FF,$04,$05,$1C,$3E
130 .endp
131
132 ;==========================================================================
133 ;
134 .proc ScreenHeightShifts
135 dta 1
136 dta 1
137 dta 0
138 dta 1
139 dta 2
140 dta 2
141 dta 3
142 dta 3
143 dta 4
144 dta 4
145 dta 4
146 dta 4
147 dta 1
148 dta 0
149 dta 4
150 dta 4
151 .endp
152
153 .proc ScreenHeights
154 dta 12, 24, 48, 96, 192
155 .endp
156
157 .proc ScreenPixelWidthIds
158 dta 1 ;gr.0 40 pixels
159 dta 0 ;gr.1 20 pixels
160 dta 0 ;gr.2 20 pixels
161 dta 1 ;gr.3 40 pixels
162 dta 2 ;gr.4 80 pixels
163 dta 2 ;gr.5 80 pixels
164 dta 3 ;gr.6 160 pixels
165 dta 3 ;gr.7 160 pixels
166 dta 4 ;gr.8 320 pixels
167 dta 2 ;gr.9 80 pixels
168 dta 2 ;gr.10 80 pixels
169 dta 2 ;gr.11 80 pixels
170 dta 1 ;gr.12 40 pixels
171 dta 1 ;gr.13 40 pixels
172 dta 3 ;gr.14 160 pixels
173 dta 3 ;gr.15 160 pixels
174 .endp
175 .endm
176
177 = F2A7 ScreenHeightsSplit = ScreenWidths
178 ; dta 10, 20, 40, 80, 160
179
180 = F2A8 ScreenPixelWidthsLo = ScreenWidths + 1
181
182 .macro _SCREEN_TABLES_1
183
184 .proc ScreenWidths
185 dta <10
186 dta <20
187 dta <40
188 dta <80
189 dta <160
190 dta <320
191 .endp
192
193 .proc ScreenPixelWidthsHi
194 dta >20
195 dta >40
196 dta >80
197 dta >160
198 dta >320
199 .endp
200
201 .proc ScreenEncodingTab
202 dta 0 ;gr.0 direct bytes
203 dta 0 ;gr.1 direct bytes
204 dta 0 ;gr.2 direct bytes
205 dta 2 ;gr.3 two bits per pixel
206 dta 3 ;gr.4 one bit per pixel
207 dta 2 ;gr.5 two bits per pixel
208 dta 3 ;gr.6 one bit per pixel
209 dta 2 ;gr.7 two bits per pixel
210 dta 3 ;gr.8 one bit per pixel
211 dta 1 ;gr.9 four bits per pixel
212 dta 1 ;gr.10 four bits per pixel
213 dta 1 ;gr.11 four bits per pixel
214 dta 0 ;gr.12 direct bytes
215 dta 0 ;gr.13 direct bytes
216 dta 3 ;gr.14 one bit per pixel
217 dta 2 ;gr.15 two bits per pixel
218 .endp
219
220 .proc ScreenPixelMasks
221 dta $ff, $0f, $03, $01, $ff, $f0, $c0, $80
222 .endp
223 .endm
224
225 .macro _SCREEN_TABLES_3
226 .proc ScreenEncodingTable
227 dta $00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$aa,$bb,$cc,$dd,$ee,$ff
228 dta $00,$55,$aa,$ff
229 dta $00,$ff
230 .endp
231 .endm
232
233 .if _KERNEL_XLXE
234 F23C _SCREEN_TABLES_3
Macro: _SCREEN_TABLES_3 [Source: source/Shared/screen.s]
2 F23C 00 11 22 33 44 55 + dta $00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$aa,$bb,$cc,$dd,$ee,$ff
3 F24C 00 55 AA FF dta $00,$55,$aa,$ff
4 F250 00 FF dta $00,$ff
Source: source/Shared/screen.s
235 F252 _SCREEN_TABLES_2
Macro: _SCREEN_TABLES_2 [Source: source/Shared/screen.s]
23 F252 40 dta <($10000-$03C0) ;gr.0 960 bytes = 40*24 = 40*24
24 F253 80 dta <($10000-$0280) ;gr.1 640 bytes = 20*24 + 40*4 = 40*12 + 40*4
25 F254 70 dta <($10000-$0190) ;gr.2 400 bytes = 10*24 + 40*4 = 40*6 + 40*4
26 F255 70 dta <($10000-$0190) ;gr.3 400 bytes = 10*24 + 40*4 = 40*6 + 40*4
27 F256 80 dta <($10000-$0280) ;gr.4 640 bytes = 10*48 + 40*4 = 40*12 + 40*4
28 F257 A0 dta <($10000-$0460) ;gr.5 1120 bytes = 20*48 + 40*4 = 40*24 + 40*4
29 F258 E0 dta <($10000-$0820) ;gr.6 2080 bytes = 20*96 + 40*4 = 40*48 + 40*4
30 F259 60 dta <($10000-$0FA0) ;gr.7 4000 bytes = 40*96 + 40*4 = 40*96 + 40*4
31 F25A 50 dta <($10000-$1EB0) ;gr.8 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
32 F25B 50 dta <($10000-$1EB0) ;gr.9 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
33 F25C 50 dta <($10000-$1EB0) ;gr.10 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
34 F25D 50 dta <($10000-$1EB0) ;gr.11 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
35 F25E A0 dta <($10000-$0460) ;gr.12 1120 bytes = 40*24 + 40*4 = 40*24 + 40*4
36 F25F 80 dta <($10000-$0280) ;gr.13 640 bytes = 40*12 + 40*4 = 40*12 + 40*4
37 F260 60 dta <($10000-$0FA0) ;gr.14 4000 bytes = 20*192 + 40*4 = 40*96 + 40*4
38 F261 50 dta <($10000-$1EB0) ;gr.15 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
42 F262 FC dta >($10000-$03C0) ;gr.0
43 F263 FD dta >($10000-$0280) ;gr.1
44 F264 FE dta >($10000-$0190) ;gr.2
45 F265 FE dta >($10000-$0190) ;gr.3
46 F266 FD dta >($10000-$0280) ;gr.4
47 F267 FB dta >($10000-$0460) ;gr.5
48 F268 F7 dta >($10000-$0820) ;gr.6
49 F269 F0 dta >($10000-$0FA0) ;gr.7
50 F26A E1 dta >($10000-$1EB0) ;gr.8
51 F26B E1 dta >($10000-$1EB0) ;gr.9
52 F26C E1 dta >($10000-$1EB0) ;gr.10
53 F26D E1 dta >($10000-$1EB0) ;gr.11
54 F26E FB dta >($10000-$0460) ;gr.12
55 F26F FD dta >($10000-$0280) ;gr.13
56 F270 F0 dta >($10000-$0FA0) ;gr.14
57 F271 E1 dta >($10000-$1EB0) ;gr.15
66 F272 02 06 07 08 09 0A + dta $02,$06,$07,$08,$09,$0A,$0B,$1D,$3F,$7F,$BF,$FF,$04,$05,$1C,$3E
72 F282 01 dta 1
73 F283 01 dta 1
74 F284 00 dta 0
75 F285 01 dta 1
76 F286 02 dta 2
77 F287 02 dta 2
78 F288 03 dta 3
79 F289 03 dta 3
80 F28A 04 dta 4
81 F28B 04 dta 4
82 F28C 04 dta 4
83 F28D 04 dta 4
84 F28E 01 dta 1
85 F28F 00 dta 0
86 F290 04 dta 4
87 F291 04 dta 4
91 F292 0C 18 30 60 C0 dta 12, 24, 48, 96, 192
95 F297 01 dta 1 ;gr.0 40 pixels
96 F298 00 dta 0 ;gr.1 20 pixels
97 F299 00 dta 0 ;gr.2 20 pixels
98 F29A 01 dta 1 ;gr.3 40 pixels
99 F29B 02 dta 2 ;gr.4 80 pixels
100 F29C 02 dta 2 ;gr.5 80 pixels
101 F29D 03 dta 3 ;gr.6 160 pixels
102 F29E 03 dta 3 ;gr.7 160 pixels
103 F29F 04 dta 4 ;gr.8 320 pixels
104 F2A0 02 dta 2 ;gr.9 80 pixels
105 F2A1 02 dta 2 ;gr.10 80 pixels
106 F2A2 02 dta 2 ;gr.11 80 pixels
107 F2A3 01 dta 1 ;gr.12 40 pixels
108 F2A4 01 dta 1 ;gr.13 40 pixels
109 F2A5 03 dta 3 ;gr.14 160 pixels
110 F2A6 03 dta 3 ;gr.15 160 pixels
Source: source/Shared/screen.s
236 F2A7 _SCREEN_TABLES_1
Macro: _SCREEN_TABLES_1 [Source: source/Shared/screen.s]
3 F2A7 0A dta <10
4 F2A8 14 dta <20
5 F2A9 28 dta <40
6 F2AA 50 dta <80
7 F2AB A0 dta <160
8 F2AC 40 dta <320
12 F2AD 00 dta >20
13 F2AE 00 dta >40
14 F2AF 00 dta >80
15 F2B0 00 dta >160
16 F2B1 01 dta >320
20 F2B2 00 dta 0 ;gr.0 direct bytes
21 F2B3 00 dta 0 ;gr.1 direct bytes
22 F2B4 00 dta 0 ;gr.2 direct bytes
23 F2B5 02 dta 2 ;gr.3 two bits per pixel
24 F2B6 03 dta 3 ;gr.4 one bit per pixel
25 F2B7 02 dta 2 ;gr.5 two bits per pixel
26 F2B8 03 dta 3 ;gr.6 one bit per pixel
27 F2B9 02 dta 2 ;gr.7 two bits per pixel
28 F2BA 03 dta 3 ;gr.8 one bit per pixel
29 F2BB 01 dta 1 ;gr.9 four bits per pixel
30 F2BC 01 dta 1 ;gr.10 four bits per pixel
31 F2BD 01 dta 1 ;gr.11 four bits per pixel
32 F2BE 00 dta 0 ;gr.12 direct bytes
33 F2BF 00 dta 0 ;gr.13 direct bytes
34 F2C0 03 dta 3 ;gr.14 one bit per pixel
35 F2C1 02 dta 2 ;gr.15 two bits per pixel
39 F2C2 FF 0F 03 01 FF F0 + dta $ff, $0f, $03, $01, $ff, $f0, $c0, $80
Source: source/Shared/screen.s
237 .endif
238
239 ;==========================================================================
240 ;==========================================================================
241
242 ;Many compilation disks rely on ScreenOpen being at $F3F6.
243
244 .if *>$f3f6-8
245 .error 'ROM overflow into Screen Handler region: ',*,' > $F3EE.'
246 .endif
247
248 .ifdef _KERNEL_REPORT_MODULE_PAD_ADJUST
249 F2CA _KERNEL_REPORT_MODULE_PAD_ADJUST [$f3f6-8]-*
Macro: _KERNEL_REPORT_MODULE_PAD_ADJUST [Source: source/main.xasm]
1 = F360 .def ?@_kernel_lastpt = ?@_kernel_lastpt + [$F3F6-8]-*
Source: source/Shared/screen.s
250 .endif
251
252 F2CA org $f3f6-8
253
254 ;==========================================================================
255 ;==========================================================================
256
257 ;==========================================================================
258 ;
259 ; Return:
260 ; MEMTOP = first byte used by display
261 ;
262 ; Errors:
263 ; - If there is not enough memory (MEMTOP > APPMHI), GR.0 is reopened
264 ; automatically and an error is returned.
265 ;
266 ; Notes:
267 ; - Resets character base (CHBAS).
268 ; - Resets character attributes (CHACT).
269 ; - Resets playfield colors (COLOR0-COLOR4).
270 ; - Resets tab map, even if the mode does not have a text window.
271 ; - Resets logical line map, even if the mode does not have a text window.
272 ; - Does NOT reset P/M colors (PCOLR0-PCOLR3).
273 ; - Does NOT reset margins (LMARGN/RMARGN).
274 ; - Sets up fine scrolling if FINE bit 7 is set. Note that this is
275 ; different than the scroll logic itself, which tests the whole byte.
276 ; - Returns error $80 if BREAK has been pressed.
277 ; - If clear is bypassed, ROWCRS and COLCRS are preserved.
278 ;
279 ; Modified:
280 ; - FRMADR: used for bitflags
281 ; bit 7 = skip clear
282 ; bit 6 = split screen
283 ; bit 0 = fine scrolling (XL/XE only)
284 ; - ADRESS: temporary addressing
285 ;
286 = F3F6 ScreenOpen = ScreenOpenGr0.use_iocb
287 = F3F2 ScreenOpenMode0 = ScreenOpenGr0.use_mode0
288 F3EE .proc ScreenOpenGr0
289 F3EE A9 0C 85 2A mva #12 icax1z
290 F3F2 use_mode0:
291 F3F2 A9 00 85 2B mva #0 icax2z
292 F3F6 use_iocb:
293 ;shut off ANTIC playfield and instruction DMA
294 F3F6 AD 2F 02 lda sdmctl
295 F3F9 29 DC and #$dc
296 F3FB 8D 2F 02 sta sdmctl
297 F3FE 8D 00 D4 sta dmactl
298
299 ;reset cursor parameters
300 F401 A2 0B ldx #11
301 F403 A9 00 lda #0
302 F405 clear_parms:
303 F405 95 54 sta rowcrs,x
304 F407 9D 90 02 sta txtrow,x
305 F40A CA dex
306 F40B D0 F8 bne clear_parms
307
308 ;mark us as being in main screen context
309 F40D 86 7B stx swpflg
310
311 ;copy mode value to dindex
312 F40F A5 2B lda icax2z
313 F411 29 0F and #15
314 F413 85 57 sta dindex
315 F415 AA tax
316
317 ;poke PRIOR value (saves us some time to do it now)
318 ;note that we must preserve bits 0-5 of GPRIOR or else Wayout shows logo artifacts
319 F416 BD 72 F2 lda ScreenModeTable,x
320 F419 4D 6F 02 eor gprior
321 F41C 29 C0 and #$c0
322 F41E 4D 6F 02 eor gprior
323 F421 8D 6F 02 sta gprior
324
325 ;if a GTIA mode is active or we're in mode 0, force off split mode
326 F424 C9 40 cmp #$40
327 F426 A5 2A lda icax1z
328 F428 B0 04 bcs kill_split
329 F42A E0 00 cpx #0
330 F42C D0 02 bne not_gtia_mode_or_gr0
331 F42E kill_split:
332 F42E 29 EF and #$ef
333 F430 not_gtia_mode_or_gr0:
334
335 ;save off the split screen and clear flags in a more convenient form
336 F430 0A asl
337 F431 0A asl
338 F432 85 68 sta frmadr
339
340 ;compute number of mode lines that we're going to have and save it off
341 F434 BC 82 F2 ldy ScreenHeightShifts,x
342 F437 BE 92 F2 ldx ScreenHeights,y
343 F43A 0A asl
344 F43B 10 03 BE A7 F2 spl:ldx ScreenHeightsSplit,y
345 F440 86 69 stx frmadr+1
346
347 ;attempt to allocate playfield memory
348 F442 A5 6A lda ramtop
349 F444 A6 57 ldx dindex
350 F446 18 clc
351 F447 7D 62 F2 adc ScreenPlayfieldSizesHi,x
352 F44A B0 09 bcs pf_alloc_ok
353
354 F44C alloc_fail:
355 ;we ran out of memory -- attempt to reopen with gr.0 if we aren't
356 ;already (to prevent recursion), and exit with an error
357 F44C 8A txa
358 F44D F0 03 beq cant_reopen_gr0
359
360 F44F 20 EE F3 jsr ScreenOpenGr0
361 F452 cant_reopen_gr0:
362 F452 A0 93 ldy #CIOStatOutOfMemory
363 F454 60 rts
364
365 F455 pf_alloc_ok:
366 F455 85 59 sta savmsc+1
367 F457 BC 52 F2 ldy ScreenPlayfieldSizesLo,x
368 F45A 84 58 sty savmsc
369
370 ;Gr. modes 7 and 14 consume enough space for the playfield that there
371 ;is not enough space left between the playfield and the next 1K
372 ;boundary to contain the display list. In these cases, we preallocate
373 ;to the 1K boundary to prevent a DL crossing error. Gr.8-11 and 15
374 ;do this too -- I have no idea why, as it's not like the OS correctly
375 ;handles moving the 4K page split for those modes if RAMTOP is
376 ;misaligned.
377 F45C BD 72 F2 lda ScreenModeTable,x
378 F45F A6 59 ldx savmsc+1
379 F461 29 30 and #$30
380 F463 F0 03 beq no_dlist_page_crossing
381 F465 A0 00 ldy #0
382 F467 CA dex
383 F468 no_dlist_page_crossing:
384 F468 84 70 sty rowac
385 F46A 8E E6 02 stx memtop+1
386 F46D 86 71 stx rowac+1
387 F46F 8E 31 02 stx sdlsth
388
389 ;Compute display list size.
390 ;
391 ; We need:
392 ; - 8 fixed bytes (24 blank lines, LMS address, JVB)
393 ; - N bytes for mode lines
394 ; - 2 bytes for LMS split address (ANTIC modes E-F only)
395 ; - 6 bytes for split
396 ;
397 ;Note that the display list never crosses a page boundary. This is
398 ;conservative, as the display list only can't cross 1K boundaries.
399
400 F472 C9 20 cmp #$20 ;test 4K hop bit (bit 5)
401 F474 A9 F8 lda #$f8 ;start with -8 (if carry is clear after test)
402 F476 90 02 A9 F5 scc:lda #$f5 ;use -11 if so (carry is set)
403 F47A E5 69 sbc frmadr+1 ;subtract mode line count
404 F47C 24 68 bit frmadr
405 F47E 50 02 E9 06 svc:sbc #6 ;subtract 6 bytes for a split
406
407 .if _KERNEL_XLXE
408 F482 A0 01 ldy #1
409 F484 CC 6E 02 cpy fine ;clear carry to alloc +1 byte if fine scrolling is enabled
410 .endif
411
412 F487 65 70 adc rowac ;allocate dl bytes (note that carry is set!)
413 F489 8D E5 02 sta memtop
414 F48C 85 70 sta rowac
415 F48E 8D 30 02 sta sdlstl
416
417 ;check if we're below APPMHI
418 F491 E4 0F cpx appmhi+1
419 F493 90 B7 bcc alloc_fail
420 F495 D0 04 bne alloc_ok
421 F497 C5 0E cmp appmhi
422 F499 90 B1 bcc alloc_fail
423
424 F49B alloc_ok:
425 ;MEMTOP is -1 from first used byte; we cheat here with the knowledge that
426 ;the low byte of MEMTOP is never $00
427 F49B CE E5 02 dec memtop
428
429 ;set up text window address (-160 from top)
430 F49E A6 6A ldx ramtop
431 F4A0 CA dex
432 F4A1 8E 95 02 stx txtmsc+1
433 F4A4 A9 60 8D 94 02 mva #$60 txtmsc
434
435 ;Turn on keyboard and break interrupts; note that this is done both for S:
436 ;and E: opens. Close does not do this.
437 F4A9 08 php
438 F4AA 78 sei
439 F4AB 0A asl ;!! - A = $C0
440 F4AC 05 10 ora pokmsk
441 F4AE 85 10 sta pokmsk
442 F4B0 8D 0E D2 sta irqen
443 F4B3 28 plp
444
445 ;Set row count: 24 for full-screen. We will fix up the split case to 4 later
446 ;while we are writing the display list. Mapping the Atari incorrectly states
447 ;that this value is set to 0 when no text window is present; this is wrong
448 ;and in fact BAYPILOT.BAS relies on this being set to 24 for a GR.7+16
449 ;screen since it later aliases it to GR.0.
450 F4B4 A0 18 ldy #24
451 F4B6 8C BF 02 sty botscr
452
453 ;init colors -- note that we do NOT overwrite pcolr0-3!
454 F4B9 A0 05 ldy #5
455 F4BB B9 BB F5 99 C3 02 + mva:rne standard_colors-1,y color0-1,y-
456
457 F4C4 8C F0 02 sty crsinh ;!! - Y=0 for this and for write index
458
459 ;add 24 blank lines
460 F4C7 A9 70 lda #$70
461 F4C9 A2 03 ldx #3
462 F4CB 20 85 F5 jsr write_repeat
463
464 ;override COLOR4 (background) to $06 for GR.11 so it isn't dark
465 F4CE A5 57 lda dindex
466 F4D0 C9 0B cmp #11
467 F4D2 D0 05 bne not_gr11
468 F4D4 A9 06 lda #$06
469 F4D6 8D C8 02 sta color4
470 F4D9 not_gr11:
471
472 ;add in the main screen
473 F4D9 20 3B F5 jsr setup_display
474
475 ;save off the DL ptr
476 F4DC 84 7E sty countr
477
478 ;clear it if necessary
479 F4DE 20 B5 F5 jsr try_clear
480
481 ;check if we are doing a split
482 F4E1 24 68 bit frmadr
483 F4E3 50 12 bvc nosplit
484
485 ;change text screen height to four lines
486 F4E5 A2 04 ldx #4
487 F4E7 8E BF 02 stx botscr
488
489 ;swap to the text screen
490 F4EA 20 3D F9 jsr EditorSwapToText
491
492 ;add text screen dlist
493 F4ED A4 7E ldy countr
494 F4EF 20 3B F5 jsr setup_display
495 F4F2 84 7E sty countr
496
497 ;clear the split screen
498 F4F4 20 B5 F5 jsr try_clear
499
500 F4F7 nosplit:
501 F4F7 A9 02 8D F3 02 mva #2 chact
502
503 ;init tab map to every 8 columns
504 F4FC A2 0F ldx #15
505 F4FE 4A lsr ;!! A=1
506 F4FF 9D A2 02 CA D0 FA sta:rne tabmap-1,x-
507
508 ;reset line status
509 F505 86 6B stx bufcnt
510
511 ;init character set
512 F507 A2 E0 8E F4 02 mvx #$e0 chbas ;!! - also used for NMIEN
513
514 ;enable VBI; note that we have not yet enabled display DMA
515 .if _KERNEL_XLXE
516 F50C 24 68 bit frmadr
517 F50E D0 02 A2 40 sne:ldx #$40
518 .else
519 ldx #$40
520 .endif
521 F512 8E 0E D4 stx nmien
522
523 ;terminate display list with jvb
524 F515 A4 7E ldy countr
525 F517 A2 70 ldx #rowac
526 F519 A9 41 lda #$41
527 F51B 20 A7 F5 jsr write_with_zp_address
528
529 ;init display list and playfield dma
530 F51E AD 2F 02 lda sdmctl
531 F521 09 22 ora #$22
532 F523 8D 2F 02 sta sdmctl
533
534 ;wait for screen to establish (necessary for Timewise splash screen to render)
535 F526 A5 14 lda rtclok+2
536 F528 C5 14 F0 FC cmp:req rtclok+2
537
538 ;If we're in screen mode 0, show the cursor; otherwise, skip it and wait for
539 ;E: to do so. We need to skip this even if a split screen is present, or else
540 ;ACTris 2.1 displays a bogus cursor. Unfortunately we may have swapped to the
541 ;split screen, so the mode we need may be in either DINDEX or TINDEX; it's
542 ;easier for us just to re-check AUX2 bits 0-3.
543 F52C A5 2B lda icax2z
544 F52E 29 0F and #$0f
545 F530 D0 03 bne no_cursor
546
547 ;show cursor
548 F532 20 B5 F6 jsr ScreenPutByte.recompute_show_cursor_exit
549 F535 no_cursor:
550 ;swap back to main context
551 F535 20 9C FD jsr EditorSwapToScreen_Y1
552
553 ;exit
554 F538 A2 00 ldx #0 ;required by Qix (v3)
555 F53A 60 rts
556
557
558 ;--------------------------------------------------------
559 F53B setup_display:
560 ;Add initial mode line with LMS, and check if we need to do an LMS
561 ;split (playfield exceeds 4K). As it turns out, this only happens if
562 ;we're using ANTIC mode E or F.
563 F53B A6 57 ldx dindex
564 F53D BD 72 F2 lda ScreenModeTable,x
565 F540 29 0F and #$0f
566
567 .if _KERNEL_XLXE
568 ;check if we are doing fine scrolling and set the vscrol bit if so
569 F542 A6 57 ldx dindex
570 F544 D0 07 bne nofine
571 F546 AE 6E 02 ldx fine
572 F549 F0 02 beq nofine
573 F54B 09 20 ora #$20
574 F54D nofine:
575 .endif
576
577 F54D 48 pha
578 F54E 09 40 ora #$40
579 F550 A2 58 ldx #savmsc
580 F552 20 A7 F5 jsr write_with_zp_address
581
582 ;retrieve row count
583 F555 A6 69 ldx frmadr+1
584 F557 A5 57 lda dindex
585 F559 D0 03 AE BF 02 sne:ldx botscr
586
587 ;dec row count since we already did the LMS
588 F55E CA dex
589 F55F 68 pla
590
591 .if _KERNEL_XLXE
592 ;subtract two rows if we are fine scrolling, as we need to do DLI
593 ;and non-vscrolled row
594 F560 C9 22 cmp #$22
595 F562 F0 28 beq dofine
596 .endif
597
598 ;check if this is a split mode
599 F564 C9 0E cmp #$0e
600 F566 90 1D bcc no_lms_split
601
602 ;yes it is -- write 93 lines
603 F568 A2 5D ldx #93
604 F56A 20 85 F5 jsr write_repeat
605
606 ;write LMS to jump over 4K boundary
607 F56D 48 pha
608 F56E 09 40 ora #$40
609 F570 91 70 C8 sta (rowac),y+
610 F573 A9 00 lda #0
611 F575 91 70 C8 sta (rowac),y+
612 F578 A5 59 lda savmsc+1
613 F57A 69 0E adc #$0f-1 ;!! - C=1 from bcc above
614 F57C 91 70 C8 sta (rowac),y+
615
616 ;set up to write 95 fewer lines (note that carry is cleared)
617 F57F A5 69 lda frmadr+1
618 F581 E9 5E sbc #94
619 F583 AA tax
620 F584 68 pla
621
622 ;write mode lines and return
623 F585 no_lms_split:
624 F585 write_repeat:
625 F585 91 70 C8 sta (rowac),y+
626 F588 CA dex
627 F589 D0 FA bne write_repeat
628 F58B no_clear:
629 F58B 60 rts
630
631 .if _KERNEL_XLXE
632 F58C dofine:
633 ;write the regular lines (22 or 2)
634 F58C CA dex
635 F58D 20 85 F5 jsr write_repeat
636
637 ;write DLI line
638 F590 09 80 ora #$80
639 F592 91 70 C8 sta (rowac),y+
640
641 ;write non-scrolled line
642 F595 29 5F and #$5f
643 F597 91 70 C8 sta (rowac),y+
644
645 ;indicate to mainline that DLIs should be turned on
646 F59A E6 68 inc frmadr
647
648 ;set up DLI routine
649 F59C A2 DE ldx #<ScreenFineScrollDLI
650 F59E A9 FD lda #>ScreenFineScrollDLI
651 F5A0 write_vdslst:
652 F5A0 8E 00 02 stx vdslst
653 F5A3 8D 01 02 sta vdslst+1
654 F5A6 60 rts
655 .endif
656
657 ;--------------------------------------------------------
658 F5A7 write_with_zp_address:
659 F5A7 91 70 C8 sta (rowac),y+
660 F5AA B5 00 lda 0,x
661 F5AC 91 70 C8 sta (rowac),y+
662 F5AF B5 01 lda 1,x
663 F5B1 A2 01 ldx #1
664 F5B3 D0 D0 bne write_repeat ;!! - unconditional
665
666 F5B5 try_clear:
667 F5B5 24 68 bit frmadr
668 F5B7 30 D2 bmi no_clear
669 F5B9 4C 4A F8 jmp ScreenClear
670
671 ;--------------------------------------------------------
672 F5BC standard_colors:
673 F5BC 28 dta $28
674 F5BD CA dta $ca
675 F5BE 94 dta $94
676 F5BF 46 dta $46
677 = F5C0 .def :ScreenBitposFlipTab
678 F5C0 00 dta $00 ;!! - shared value between tables
679 F5C1 01 dta $01
680 F5C2 03 dta $03
681 F5C3 07 dta $07
682
683 .endp
684
685 ;==========================================================================
686 F5C4 .proc ScreenInit
687 F5C4 AD E6 02 85 6A mva memtop+1 ramtop
688
689 .ifdef _KERNEL_816
690 stz colrsh
691 .else
692 F5C9 A9 00 85 4F mva #0 colrsh
693 .endif
694
695 F5CD A9 FE 85 4E mva #$FE drkmsk
696 F5D1 60 rts
697 .endp
698
699 ;==========================================================================
700 ; Behavior in gr.0:
701 ; - Reading char advances to next position, but cursor is not moved
702 ; - Cursor is picked up ($A0)
703 ; - Wrapping from end goes to left margin on next row
704 ; - Cursor may be outside of horizontal margins
705 ; - Error 141 (cursor out of range) if out of range
706 ; - Cursor will wrap to out of range if at end of screen (no automatic
707 ; vertical wrap)
708 ; - Does NOT update OLDROW/OLDCOL
709 ;
710 F5D2 .proc ScreenGetByte
711 F5D2 20 FA F8 jsr ScreenCheckPosition
712 F5D5 30 3A bmi xit
713
714 ;compute addressing
715 F5D7 A4 54 ldy rowcrs
716 F5D9 20 75 F9 jsr ScreenComputeToAddrX0
717 F5DC A5 55 lda colcrs
718 F5DE A6 57 ldx dindex
719 F5E0 BC B2 F2 ldy ScreenEncodingTab,x
720 F5E3 59 C0 F5 eor ScreenBitposFlipTab,y
721 F5E6 AA tax
722 F5E7 A5 56 lda colcrs+1
723 F5E9 20 BE F9 jsr ScreenSetupPixelAddr.phase2
724
725 ;retrieve byte containing pixel
726 F5EC A4 6F ldy shfamt
727 F5EE B1 66 lda (toadr),y
728
729 ;shift down
730 F5F0 20 AB F9 jsr ScreenAlignPixel
731
732 ;convert from Internal to ATASCII - must be done before we mask
733 ;Internal ATASCII
734 ;00-1F 20-3F
735 ;20-3F 40-5F
736 ;40-5F 00-1F
737 ;60-7F 60-7F
738 F5F3 0A asl
739 F5F4 08 php
740 F5F5 10 02 49 40 spl:eor #$40 ;00>20, 20>40, 40>60, 60>40
741 F5F9 69 40 adc #$40 ;00>20, 20>40, 40>00, 60>60
742 F5FB 28 plp
743 F5FC 6A ror
744
745 ;mask using right-justified pixel mask for mode
746 F5FD A6 57 ldx dindex
747 F5FF BC B2 F2 ldy ScreenEncodingTab,x
748 F602 39 C2 F2 and ScreenPixelMasks,y
749
750 ;advance to next position
751 F605 A6 57 ldx dindex
752 F607 F0 03 beq mode0
753 F609 4C D6 F9 jmp ScreenAdvancePosNonMode0
754 F60C mode0:
755 F60C 20 08 FE jsr ScreenAdvancePosMode0
756 F60F A0 01 ldy #1
757 F611 xit:
758 F611 60 rts
759 .endp
760
761 ;==========================================================================
762 ; Common behavior:
763 ; - Output is suspended if SSFLAG is set for non-clear and non-EOL chars
764 ; - Clear screen ($7D) and EOL ($9B) are always handled
765 ; - ESCFLG and DSPFLG are ignored (they are E: features)
766 ;
767 ; Behavior in gr.0:
768 ; - Logical lines are extended
769 ; - Scrolling occurs if bottom is hit
770 ; - Control chars other than clear and EOL are NOT handled by S:
771 ; - ROWCRS or COLCRS out of range results in an error.
772 ; - COLCRS in left margin is ignored and prints within margin.
773 ; - COLCRS in right margin prints one char and then does EOL.
774 ; - Previous cursor is not erased by S:, regardless of CRSINH state
775 ; - New cursor is drawn if CRSINH=0
776 ;
777 ; Behavior in gr.1+:
778 ; - No cursor is displayed
779 ; - LMARGN/RMARGN are ignored
780 ; - Cursor wraps from right side to next line
781 ; - ROWCRS may be below split screen boundary as long as it is within the
782 ; full screen size.
783 ;
784 F612 .proc ScreenPutByte
785 F612 8D FB 02 sta atachr
786 F615 20 FA F8 jsr ScreenCheckPosition
787 F618 30 0C bmi error
788
789 ;check for screen clear
790 F61A AD FB 02 lda atachr
791 F61D C9 7D cmp #$7d
792 F61F D0 0E bne not_clear_2
793 F621 20 4A F8 jsr ScreenClear
794 F624 A0 01 ldy #1
795 F626 error:
796 F626 60 rts
797
798 F627 graphics_eol:
799 F627 4C EF F9 jmp ScreenAdvancePosNonMode0.graphics_eol
800
801 ;*** ENTRY POINT FROM EDITOR FOR ESC HANDLING ***
802 F62A not_clear:
803 F62A 20 FA F8 jsr ScreenCheckPosition
804 F62D 30 F7 bmi error
805
806 F62F not_clear_2:
807 ;set old position now (used by setup code for plot pixel)
808 F62F 20 FE FD jsr ScreenSetLastPosition
809
810 ;restore char
811 F632 AD FB 02 lda atachr
812
813 ;check if we're in gr.0
814 F635 A6 57 ldx dindex
815 F637 F0 1E beq mode_0
816
817 ;nope, we're in a graphics mode... that makes this easier.
818 ;check if it's an EOL
819 F639 C9 9B cmp #$9b
820 F63B F0 EA beq graphics_eol
821
822 ;check for display suspend (ctrl+1) and wait until it is cleared
823 F63D AE FF 02 D0 FB ldx:rne ssflag
824
825 ;fold the pixel, compute masks, and convert ATASCII to Internal
826 F642 20 CE F6 jsr ScreenFoldColor
827 F645 48 pha
828
829 ;compute addressing and shift mask
830 F646 20 A6 F9 jsr ScreenSetupPlotPixel
831
832 F649 68 pla
833 F64A A4 6F ldy shfamt
834 F64C 51 66 eor (toadr),y
835 F64E 25 6E and bitmsk
836 F650 51 66 eor (toadr),y
837 F652 91 66 sta (toadr),y
838
839 ;advance cursor position and exit
840 F654 4C D6 F9 jmp ScreenAdvancePosNonMode0
841
842 F657 mode_0:
843 ;check for EOL, which bypasses the ESC check
844 F657 C9 9B cmp #$9b
845 F659 D0 18 bne not_eol
846
847 ;it's an EOL
848 F65B A5 52 lda lmargn
849 F65D 85 55 sta colcrs
850 F65F E6 54 inc rowcrs
851 F661 A5 54 lda rowcrs
852 F663 CD BF 02 cmp botscr
853 F666 90 08 bcc noywrap
854
855 ;We've gone over -- delete logical line 0 to make room.
856 ;Note that we need to set ROWCRS here first because the scroll may
857 ;delete more than one physical line.
858 F668 AE BF 02 ldx botscr
859 F66B 86 54 stx rowcrs
860
861 F66D 20 CC FC jsr EditorDeleteLine0
862 F670 noywrap:
863 F670 4C B5 F6 jmp recompute_show_cursor_exit
864
865 F673 not_eol:
866 ;check for display suspend (ctrl+1) and wait until it is cleared
867 F673 AE FF 02 D0 FB ldx:rne ssflag
868
869 F678 48 pha
870 F679 20 C0 FC jsr EditorRecomputeCursorAddr
871 F67C 68 pla
872 F67D 20 EB F6 jsr ScreenConvertATASCIIToInternal
873
874 ;plot character
875 F680 A0 00 ldy #0
876 F682 91 5E sta (oldadr),y
877
878 ;inc pos
879 F684 E6 5E D0 02 E6 5F inw oldadr
880 F68A 20 08 FE jsr ScreenAdvancePosMode0
881
882 ;check if we've gone beyond the right margin
883 F68D B0 29 bcs nowrap
884
885 ;check if we're beyond the bottom of the screen
886 F68F A5 54 lda rowcrs
887 F691 CD BF 02 cmp botscr
888 F694 90 12 bcc no_scroll
889
890 ;yes -- scroll up
891 F696 20 CC FC jsr EditorDeleteLine0
892
893 ;check if we can extend the current logical line -- 3 rows max.
894 F699 20 BB F6 jsr check_extend
895
896 ;Mark the current physical line as part of the last logical line.
897 ;
898 ;NOTE: There is a subtlety here in that we may delete multiple physical
899 ; lines if the top logical line is more than one line long, but we
900 ; only want to add one physical line onto our current logical line.
901 F69C 20 6F FD jsr EditorGetCurLogicalLineInfo
902 F69F 59 B2 02 eor logmap,y
903 F6A2 99 B2 02 sta logmap,y
904
905 F6A5 4C B5 F6 jmp post_scroll
906
907 F6A8 no_scroll:
908 ;check if we can extend the current logical line -- 3 rows max.
909 F6A8 20 BB F6 jsr check_extend
910
911 ;okay, here's the fun part -- we didn't scroll beyond, but we might
912 ;be on another logical line, in which case we need to scroll everything
913 ;down to extend it.
914 F6AB A5 54 lda rowcrs
915 F6AD 20 7E FD jsr EditorTestLogicalLineBit
916 F6B0 F0 03 beq post_scroll
917
918 ;yup, insert a physical line
919 F6B2 20 8D F8 jsr ScreenInsertPhysLine
920
921 F6B5 recompute_show_cursor_exit:
922 F6B5 post_scroll:
923 F6B5 20 C0 FC jsr EditorRecomputeCursorAddr
924 F6B8 nowrap:
925 F6B8 4C 17 FE jmp ScreenShowCursorAndXitOK
926
927 F6BB check_extend:
928 F6BB A6 54 ldx rowcrs
929 F6BD CA dex
930 F6BE 8A txa
931 F6BF 20 87 FD jsr EditorPhysToLogicalRow
932
933 .ifdef _KERNEL_816
934 inc
935 inc
936 .else
937 F6C2 18 clc
938 F6C3 69 02 adc #2
939 .endif
940
941 F6C5 C5 54 cmp rowcrs
942 F6C7 90 01 60 scc:rts
943 F6CA 68 pla
944 F6CB 68 pla
945 F6CC 90 E7 bcc post_scroll
946 .endp
947
948 ;==========================================================================
949 = E4C9 ScreenGetStatus = CIOExitSuccess
950
951 ;==========================================================================
952 ; Given a color byte, mask it off to the pertinent bits and reflect it
953 ; throughout a byte. The byte is converted from ATASCII to Internal
954 ; if the mode uses byte encoding.
955 ;
956 ; Entry:
957 ; A = color value
958 ;
959 ; Exit:
960 ; A = folded color byte
961 ; Y = encoding mode
962 ; DMASK = right-justified bit mask
963 ; DELTAC = left-justified bit mask
964 ;
965 ; Modified:
966 ; HOLD1, ADRESS
967 ;
968 F6CE .proc ScreenFoldColor
969 F6CE A6 57 ldx dindex
970 F6D0 BC B2 F2 ldy ScreenEncodingTab,x ;0 = 8-bit, 1 = 4-bit, 2 = 2-bit, 3 = 1-bit
971 F6D3 BE C6 F2 86 77 mvx ScreenPixelMasks+4,y deltac
972 F6D8 BE C2 F2 8E A0 02 mvx ScreenPixelMasks,y dmask
973 F6DE 30 0B bmi fold_byte
974 F6E0 2D A0 02 and dmask
975 F6E3 19 DA FD ora ScreenEncodingOffsetTable-1,y
976 F6E6 AA tax
977 F6E7 BD 3C F2 lda ScreenEncodingTable,x
978 F6EA 60 rts
979
980 F6EB fold_byte:
981 ;convert byte from ATASCII to Internal -- this is required for gr.1
982 ;and gr.2 to work correctly, and harmless for other modes
983
984 ;==========================================================================
985 ; Convert an ATASCII character to displayable INTERNAL format.
986 ;
987 ; Entry:
988 ; A = ATASCII char
989 ;
990 ; Exit:
991 ; A = INTERNAL char
992 ;
993 = F6EB .def :ScreenConvertATASCIIToInternal
994 ;ATASCII Internal
995 ;00-1F 40-5F
996 ;20-3F 00-1F
997 ;40-5F 20-3F
998 ;60-7F 60-7F
999
1000 F6EB 0A asl
1001 F6EC 08 php
1002 F6ED E9 3F sbc #$3f ;00>60, 20>00, 40>20, 60>40
1003 F6EF 10 02 49 40 spl:eor #$40 ;00>40, 20>00, 40>20, 60>60
1004 F6F3 28 plp
1005 F6F4 6A ror
1006 F6F5 60 rts
1007 .endp
1008
1009
1010 ;==========================================================================
1011 F6F6 .proc ScreenSpecial
1012 F6F6 A5 22 lda iccomz
1013 F6F8 C9 11 cmp #$11
1014 F6FA F0 05 beq ScreenDrawLineFill ;draw line
1015 F6FC C9 12 cmp #$12
1016 F6FE F0 01 beq ScreenDrawLineFill ;fill
1017 F700 60 rts
1018 .endp
1019
1020 ;==========================================================================
1021 ;
1022 ; Inputs:
1023 ; COLCRS,ROWCRS = next point
1024 ; OLDCOL,OLDROW = previous point
1025 ; ATACHR = color/character to use
1026 ;
1027 ; Outputs:
1028 ; OLDCOL,OLDROW = next point
1029 ;
1030 ; Behavior:
1031 ; - In GR.0:
1032 ; - Cursor is not drawn, even with CRSINH=0
1033 ; - OLDADR is updated to ending location, but not OLDCHR. If CRSINH=0,
1034 ; this can lead to a subsequent E: write stomping the last line draw
1035 ; cell with the under-cursor char from the last time the cursor was
1036 ; drawn elsewhere.
1037 ;
1038 ; Some test cases:
1039 ; - Ryba Pila
1040 ; - SPACEWAY.BAS
1041 ; - Worm of Bemer
1042 ;
1043 ; The Bresenham algorithm we use (from Wikipedia):
1044 ; dx = |x2 - x1|
1045 ; dy = |y2 - y1|
1046 ; e = dx - dy
1047 ;
1048 ; loop
1049 ; plot(x1, y1)
1050 ; if x1 == x2 and y1 == y2 then exit
1051 ; e2 = 2*e
1052 ; if e2 + dy > 0 then
1053 ; err = err - dy
1054 ; x0 = x0 + sign(dx)
1055 ; endif
1056 ; if e2 < dx then
1057 ; err = err + dx
1058 ; y0 = y0 + sign(dy)
1059 ; endif
1060 ; end
1061 ;
1062 F701 .proc ScreenDrawLineFill
1063 ;;##TRACE "Drawing line (%d,%d)-(%d,%d) in mode %d" dw(oldcol) db(oldrow) dw(colcrs) db(rowcrs) db(dindex)
1064
1065 ;initialize bit mask and repeat pertinent pixel bits throughout byte
1066 F701 AD FD 02 lda fildat
1067 F704 20 CE F6 jsr ScreenFoldColor
1068 F707 8D BC 02 sta hold4
1069 F70A AD FB 02 lda atachr
1070 F70D 20 CE F6 jsr ScreenFoldColor
1071 F710 85 51 sta hold1
1072
1073 F712 20 A6 F9 jsr ScreenSetupPlotPixel
1074
1075 ;compute screen pitch
1076 F715 A0 01 ldy #1
1077 F717 20 7F F9 jsr ScreenComputeRangeSize
1078 F71A 85 78 sta deltac+1
1079 F71C AA tax
1080 F71D A0 00 ldy #0
1081
1082 ;compute abs(dy) and sign(dy)
1083 F71F A5 54 lda rowcrs
1084 F721 38 E5 5A sub oldrow
1085 F724 B0 0C bcs going_down
1086 F726 49 FF eor #$ff ;take abs(dy)
1087 F728 69 01 adc #1 ;
1088 ;negate screen pitch
1089 F72A 48 pha
1090 F72B 8A txa
1091 F72C 49 FF eor #$ff
1092 F72E AA tax
1093 F72F E8 inx
1094 F730 88 dey
1095 F731 68 pla
1096 F732 going_down:
1097 F732 86 70 stx rowac
1098 F734 85 76 sta deltar
1099 F736 84 71 sty rowac+1
1100
1101 ;;##TRACE "dy = %d" db(deltar)
1102
1103 ;compute abs(dx) and sign(dx)
1104 F738 A2 00 ldx #0
1105 F73A A5 55 lda colcrs
1106 F73C 38 E5 5B sub oldcol
1107 F73F 85 72 sta colac
1108 F741 A5 56 lda colcrs+1
1109 F743 E5 5C sbc oldcol+1
1110 F745 B0 10 bcs going_right
1111 F747 49 FF eor #$ff
1112 F749 A8 tay
1113 F74A A5 72 lda colac
1114 F74C 49 FF eor #$ff
1115 F74E 69 01 adc #1
1116 F750 85 72 sta colac
1117 F752 98 tya
1118 F753 69 00 adc #0
1119 F755 A2 CC ldx #left_shift_8-right_shift_8
1120 F757 going_right:
1121 F757 85 73 sta colac+1
1122
1123 ;;##TRACE "dx = %d" dw(colac)
1124
1125 ;set up x shift routine
1126 F759 8A txa
1127 F75A A6 57 ldx dindex
1128 F75C BC B2 F2 ldy ScreenEncodingTab,x
1129 F75F 18 clc
1130 F760 79 AD F7 adc shift_lo_tab,y
1131 F763 85 64 sta adress
1132 F765 A9 F7 lda #>left_shift_8
1133 F767 85 65 sta adress+1
1134 F769 85 75 sta endpt+1
1135
1136 ;set up x fill shift routine
1137 F76B B9 AD F7 lda shift_lo_tab,y
1138 F76E 18 clc
1139 F76F 69 D9 adc #fill_right_8-right_shift_8
1140 F771 85 74 sta endpt
1141
1142 ;compute initial error accumulator in frmadr (dx-dy)
1143 F773 A6 72 ldx colac
1144 F775 8A txa
1145 F776 38 E5 76 sub deltar
1146 F779 85 68 sta frmadr
1147 F77B A4 73 ldy colac+1 ;leave dx in y:x for max() below
1148 F77D 98 tya
1149 F77E E9 00 sbc #0
1150 F780 85 69 sta frmadr+1
1151
1152 ;compute max(dx, dy) based on sign of (dx - dy)
1153 F782 B0 04 bcs dx_larger
1154 F784 A0 00 ldy #0
1155 F786 A6 76 ldx deltar
1156 F788 dx_larger:
1157 F788 86 7E stx countr
1158 F78A 84 7F sty countr+1
1159
1160 F78C 98 tya
1161 F78D D0 03 bne not_empty
1162 F78F 8A txa
1163 F790 F0 0D beq skip_showcursor
1164 F792 not_empty:
1165
1166 ;;##TRACE "Pixel count = %d" dw(countr)
1167
1168 ;enter pixel loop (this will do a decrement for us)
1169 F792 4C 02 F8 jmp next_pixel
1170
1171 ;----------------------------------------------
1172 F795 done:
1173 F795 20 FE FD jsr ScreenSetLastPosition
1174
1175 ;RYBA PILA requires the quirky behavior of the last character of a non-zero length
1176 ;DRAWTO being stomped by the character saved from the cursor draw of the last PLOT
1177 ;(write to S:). Note that we must NOT do this for length 0 or it breaks SPACEWAY.
1178 F798 A4 57 ldy dindex
1179 F79A D0 03 bne skip_showcursor
1180 F79C 20 C0 FC jsr EditorRecomputeCursorAddr
1181 F79F skip_showcursor:
1182 F79F A0 01 ldy #1
1183 F7A1 60 rts
1184
1185 ;----------------------------------------------
1186 F7A2 fill_done:
1187 F7A2 86 6E stx bitmsk
1188 F7A4 4C 02 F8 jmp next_pixel
1189
1190 ;----------------------------------------------
1191 F7A7 do_fill:
1192 F7A7 A4 6F ldy shfamt ;load current byte offset
1193 F7A9 A6 6E ldx bitmsk ;save current bitmask
1194 F7AB D0 33 bne fill_start ;!! - unconditional
1195
1196 ;----------------------------------------------
1197 F7AD shift_lo_tab:
1198 F7AD EB dta <right_shift_8
1199 F7AE E5 dta <right_shift_4
1200 F7AF E7 dta <right_shift_2
1201 F7B0 E8 dta <right_shift_1
1202
1203 ;----------------------------------------------
1204 F7B1 left_shift_4:
1205 F7B1 0A asl
1206 F7B2 0A asl
1207 F7B3 left_shift_2:
1208 F7B3 0A asl
1209 F7B4 left_shift_1:
1210 F7B4 0A asl
1211 F7B5 90 05 bcc left_shift_ok
1212 F7B7 left_shift_8:
1213 F7B7 C6 6F dec shfamt
1214 F7B9 AD A0 02 lda dmask
1215 F7BC left_shift_ok:
1216 F7BC D0 31 bne post_xinc ;!! - unconditional
1217
1218 ;----------------------------------------------
1219 F7BE fill_right_4:
1220 F7BE 4A lsr
1221 F7BF 4A lsr
1222 F7C0 fill_right_2:
1223 F7C0 4A lsr
1224 F7C1 fill_right_1:
1225 F7C1 4A lsr
1226 F7C2 90 09 bcc fill_right_ok
1227 F7C4 fill_right_8:
1228 F7C4 A5 77 lda deltac
1229 F7C6 C8 iny
1230 F7C7 C4 78 cpy deltac+1
1231 F7C9 90 02 A0 00 scc:ldy #0
1232 F7CD fill_right_ok:
1233 F7CD 85 6E sta bitmsk
1234 F7CF F0 D1 beq fill_done
1235 F7D1 fill_loop:
1236 F7D1 B1 66 lda (toadr),y ;load screen byte
1237 F7D3 24 6E bit bitmsk ;mask to current pixel
1238 F7D5 D0 CB bne fill_done ;exit loop if non-zero
1239 F7D7 4D BC 02 eor hold4 ;XOR with fill color
1240 F7DA 25 6E and bitmsk ;mask change bits to current pixel
1241 F7DC 51 66 eor (toadr),y ;merge with screen byte
1242 F7DE 91 66 sta (toadr),y ;save screen byte
1243 F7E0 fill_start:
1244 F7E0 A5 6E lda bitmsk
1245 F7E2 6C 74 00 jmp (endpt)
1246
1247 ;----------------------------------------------
1248 F7E5 right_shift_4:
1249 F7E5 4A lsr
1250 F7E6 4A lsr
1251 F7E7 right_shift_2:
1252 F7E7 4A lsr
1253 F7E8 right_shift_1:
1254 F7E8 4A lsr
1255 F7E9 90 04 bcc right_shift_ok
1256 F7EB right_shift_8:
1257 F7EB E6 6F inc shfamt
1258 F7ED A5 77 lda deltac
1259 F7EF right_shift_ok:
1260 ;fall through to post_xinc
1261 F7EF post_xinc:
1262 F7EF 85 6E sta bitmsk
1263 F7F1 no_xinc:
1264
1265 ;plot pixel
1266 ;;##TRACE "Plotting at $%04X+%d with mask $%02X" dw(toadr) db(shfamt) db(bitmsk)
1267 F7F1 A4 6F ldy shfamt
1268 F7F3 A5 51 lda hold1
1269 F7F5 51 66 eor (toadr),y
1270 F7F7 25 6E and bitmsk
1271 F7F9 51 66 eor (toadr),y
1272 F7FB 91 66 sta (toadr),y
1273
1274 ;do fill if needed
1275 F7FD A5 22 lda iccomz
1276 F7FF 4A lsr
1277 F800 90 A5 bcc do_fill
1278
1279 F802 next_pixel:
1280 ;loop back for next pixel
1281 F802 A5 7E lda countr
1282 F804 D0 04 bne next_pixel_2
1283 F806 C6 7F dec countr+1
1284 F808 30 8B bmi done
1285 F80A next_pixel_2:
1286 F80A C6 7E dec countr
1287
1288 ;!! - fall through to pixel loop
1289
1290 ;------- pixel loop state -------
1291 ; (zp) frmadr error accumulator
1292 ; (zp) toadr current row address
1293 ; (abs) dmask right-justified bit mask
1294 ; (zp) deltac left-justified bit mask
1295 ; (zp) bitmsk current bit mask
1296 ; (zp) shfamt current byte offset within row
1297 ; (zp) rowac y step address increment/decrement (note different from Atari OS)
1298 ; (zp) adress left/right shift routine
1299 ; (zp) deltac+1 screen pitch, in bytes (for fill)
1300 ; (zp) endpt right shift routine
1301 ; (zp) colac dy
1302 F80C pixel_loop:
1303 ;compute 2*err
1304 ;;##TRACE "Error accum = %d (dx=%d, dy=%d(%d))" dsw(frmadr) dw(colac) db(deltar) dsw(rowac)
1305 F80C A5 68 lda frmadr
1306 F80E 0A asl
1307 F80F A8 tay
1308 F810 A5 69 lda frmadr+1
1309 F812 2A rol
1310 F813 AA tax
1311
1312 ;check for y increment (2*e < dx, or A:Y < colac)
1313 F814 98 tya
1314 F815 18 clc
1315 F816 E5 72 sbc colac
1316 F818 8A txa
1317 F819 48 pha
1318 F81A E5 73 sbc colac+1
1319 F81C 10 13 bpl no_yinc
1320
1321 F81E do_yinc:
1322 ;bump y (add/subtract pitch, e += dx)
1323 F81E A2 02 ldx #2
1324 F820 yinc_loop:
1325 F820 B5 70 lda rowac,x
1326 F822 18 clc
1327 F823 75 66 adc toadr,x
1328 F825 95 66 sta toadr,x
1329 F827 B5 71 lda rowac+1,x
1330 F829 75 67 adc toadr+1,x
1331 F82B 95 67 sta toadr+1,x
1332 F82D CA dex
1333 F82E CA dex
1334 F82F 10 EF bpl yinc_loop
1335 F831 no_yinc:
1336
1337 ;check for x increment (2*e + dy > 0, or Y:[S] + deltar > 0)
1338 F831 98 tya
1339 F832 18 clc
1340 F833 65 76 adc deltar
1341 F835 68 pla
1342 F836 69 00 adc #0
1343 F838 30 B7 bmi no_xinc
1344
1345 ;update error accumulator
1346 F83A A5 68 lda frmadr
1347 F83C 38 E5 76 sub deltar
1348 F83F 85 68 sta frmadr
1349 F841 B0 02 C6 69 scs:dec frmadr+1
1350
1351 ;bump x
1352 F845 A5 6E lda bitmsk
1353 F847 6C 64 00 jmp (adress)
1354
1355 .if [right_shift_4 ^ right_shift_8]&$ff00
1356 .error "Right draw routines cross page: ",right_shift_4,"-",right_shift_8
1357 .endif
1358 .if [left_shift_4 ^ left_shift_8]&$ff00
1359 .error "Left draw routines cross page: ",left_shift_4,"-",left_shift_8
1360 .endif
1361 .if [fill_right_4 ^ fill_right_8]&$ff00
1362 .error "Fill routines cross page: ",fill_right_4,"-",fill_right_8
1363 .endif
1364 .if [[right_shift_4^left_shift_4]|[left_shift_4^fill_right_4]]&$ff00
1365 .error "Line/fill routines cross page: ",left_shift_4,',',right_shift_4,',',fill_right_4
1366 .endif
1367
1368 .endp
1369
1370 ;==========================================================================
1371 ; Clear the screen.
1372 ;
1373 ; Used:
1374 ; ADRESS
1375 ; TOADR
1376 ;
1377 ; Quirks:
1378 ; Clears the split-screen text area even if the main screen (S:) receives
1379 ; the clear. The In-Store Demonstration Cart depends on this. The cursor
1380 ; state of the split screen is NOT reset, so if the cursor was over a
1381 ; non-blank character, that character will be restored when the cursor
1382 ; moves.
1383 ;
1384 ; The logical line map is always reset.
1385 ;
1386 F84A .proc ScreenClear
1387 ;first, set up for clearing the split-screen window (4*40 bytes main)
1388 F84A A0 04 ldy #4
1389
1390 ;check if we are in the split screen text window
1391 F84C A6 7B ldx swpflg
1392 F84E D0 08 bne is_text_window
1393
1394 ;nope, it's the main screen... compute size
1395 F850 A4 57 ldy dindex
1396 F852 BE 82 F2 ldx ScreenHeightShifts,y
1397 F855 BC 92 F2 ldy ScreenHeights,x
1398 F858 is_text_window:
1399 F858 20 7F F9 jsr ScreenComputeRangeSize
1400
1401 ;add 160 bytes to size if not GR.0 -- important to avoid clearing
1402 ;beyond GR.0 screen (the font breaks in BIKERDAV.BAS otherwise!)
1403 F85B 18 clc
1404 F85C A6 57 ldx dindex
1405 F85E F0 02 beq is_gr0
1406 F860 69 A0 adc #160
1407 F862 is_gr0:
1408 F862 A8 tay
1409 F863 A5 65 lda adress+1
1410 F865 69 00 adc #0
1411
1412 F867 AA tax
1413 F868 65 59 adc savmsc+1
1414 F86A 85 67 sta toadr+1
1415 F86C A5 58 85 66 mva savmsc toadr
1416
1417 ;As it turns out, there are no cases where the main screen
1418 ;is an exact number of pages... so we can simply plow into
1419 ;the clear loop.
1420 F870 A9 00 lda #0
1421 F872 loop:
1422 F872 88 dey
1423 F873 91 66 sta (toadr),y
1424 F875 D0 FB bne loop
1425 F877 C6 67 dec toadr+1
1426 F879 CA dex
1427 F87A 10 F6 bpl loop
1428
1429 ;reset coordinates and cursor (we're going to wipe the cursor)
1430 F87C 85 56 sta colcrs+1
1431 F87E 85 54 sta rowcrs
1432 F880 85 5D sta oldchr
1433
1434 ;always reset the logical line map
1435 F882 A6 57 ldx dindex
1436 F884 D0 02 bne is_graphic_screen
1437 F886 A5 52 lda lmargn
1438 F888 is_graphic_screen:
1439 F888 85 55 sta colcrs
1440
1441 ;always reset the logical line map and exit
1442 F88A 4C EB FD jmp ScreenResetLogicalLineMap
1443 .endp
1444
1445 ;==========================================================================
1446 ; Insert a physical line at the current location.
1447 ;
1448 ; Entry:
1449 ; ROWCRS = row before which to insert new line
1450 ; C = 0 if physical line only, C = 1 if should start new logical line
1451 ;
1452 ; Modified:
1453 ; HOLD1, ADRESS
1454 ;
1455 = F88E ScreenInsertLine = ScreenInsertPhysLine.use_c
1456 F88D .proc ScreenInsertPhysLine
1457 F88D 18 clc
1458 F88E use_c:
1459 ;save new logline flag
1460 F88E 08 php
1461
1462 ;compute addresses
1463 F88F AC BF 02 ldy botscr
1464 F892 88 dey
1465 F893 20 75 F9 jsr ScreenComputeToAddrX0
1466 F896 20 C5 FD jsr EditorNextLineAddr
1467
1468 ;copy lines
1469 F899 AE BF 02 ldx botscr
1470 F89C D0 09 bne line_loop_start
1471 F89E line_loop:
1472 F89E A0 27 ldy #39
1473 F8A0 char_loop:
1474 F8A0 B1 68 lda (frmadr),y
1475 F8A2 91 66 sta (toadr),y
1476 F8A4 88 dey
1477 F8A5 10 F9 bpl char_loop
1478 F8A7 line_loop_start:
1479 F8A7 A5 68 lda frmadr
1480 F8A9 85 66 sta toadr
1481 F8AB 38 sec
1482 F8AC E9 28 sbc #40
1483 F8AE 85 68 sta frmadr
1484 F8B0 A5 69 lda frmadr+1
1485 F8B2 85 67 sta toadr+1
1486 F8B4 E9 00 sbc #0
1487 F8B6 85 69 sta frmadr+1
1488
1489 F8B8 CA dex
1490 F8B9 E4 54 cpx rowcrs
1491 F8BB D0 E1 bne line_loop
1492
1493 F8BD no_copy:
1494 ;clear the current line
1495 F8BD A0 27 ldy #39
1496 F8BF A9 00 lda #0
1497 F8C1 clear_loop:
1498 F8C1 91 66 sta (toadr),y
1499 F8C3 88 dey
1500 F8C4 10 FB bpl clear_loop
1501
1502 ;insert bit into logical line mask
1503 F8C6 20 6F FD jsr EditorGetCurLogicalLineInfo
1504
1505 F8C9 28 plp
1506 F8CA B0 02 A9 00 scs:lda #0
1507 F8CE 85 51 sta hold1
1508
1509 F8D0 A9 00 lda #0
1510 F8D2 38 sec
1511 F8D3 FD C1 E4 sbc ReversedBitMasks,x ;-bit
1512 F8D6 0A asl
1513 F8D7 39 B2 02 and logmap,y
1514 F8DA 18 clc
1515 F8DB 79 B2 02 adc logmap,y
1516 F8DE 6A ror
1517 F8DF 05 51 ora hold1
1518 F8E1 99 B2 02 sta logmap,y
1519
1520 F8E4 88 dey
1521 F8E5 10 03 6E B3 02 spl:ror logmap+1
1522 F8EA 88 dey
1523 F8EB 10 03 6E B4 02 spl:ror logmap+2
1524 F8F0 60 rts
1525 .endp
1526
1527 ;==========================================================================
1528 ; Hide the screen cursor, if it is present.
1529 ;
1530 ; Modified:
1531 ; Y
1532 ;
1533 ; Preserved:
1534 ; A
1535 ;
1536 F8F1 .proc ScreenHideCursor
1537 ;erase the cursor
1538 F8F1 48 pha
1539 F8F2 A0 00 ldy #0
1540 F8F4 A5 5D lda oldchr
1541 F8F6 91 5E sta (oldadr),y
1542 F8F8 68 pla
1543 F8F9 no_cursor:
1544 F8F9 60 rts
1545 .endp
1546
1547 ;==========================================================================
1548 F8FA .proc ScreenCheckPosition
1549 ;Check for ROWCRS out of range. Note that for split screen modes we still
1550 ;check against the full height!
1551 F8FA AD BF 02 lda botscr
1552 F8FD A6 57 ldx dindex
1553 F8FF F0 06 beq rowcheck_gr0
1554 F901 BC 82 F2 ldy ScreenHeightShifts,x
1555 F904 B9 92 F2 lda ScreenHeights,y
1556 F907 rowcheck_gr0:
1557 ;while we know it's GR.0, clamp RMARGN to 39 (required for ARTILLERY.BAS)
1558 F907 A0 27 ldy #39
1559 F909 C4 53 cpy rmargn
1560 F90B B0 02 bcs rmargn_ok
1561 F90D 84 53 sty rmargn
1562 F90F rmargn_ok:
1563 F90F 18 clc
1564 F910 E5 54 sbc rowcrs
1565 F912 B0 0E bcs rowcheck_pass
1566 F914 invalid_position:
1567
1568 ;If the cursor is out of range, reset it within bounds.
1569 F914 A0 00 ldy #0
1570 F916 84 56 sty colcrs+1 ;X high = 0
1571 F918 8A txa
1572 F919 D0 02 A4 52 sne:ldy lmargn
1573 F91D 84 55 sty colcrs ;X low = X origin
1574
1575 F91F A0 8D ldy #CIOStatCursorRange
1576 F921 60 rts
1577
1578 F922 rowcheck_pass:
1579 ;check width
1580 F922 BC 97 F2 ldy ScreenPixelWidthIds,x
1581 F925 A5 55 lda colcrs
1582 F927 D9 A8 F2 cmp ScreenPixelWidthsLo,y
1583 F92A A5 56 lda colcrs+1
1584 F92C F9 AD F2 sbc ScreenPixelWidthsHi,y
1585 F92F B0 E3 bcs invalid_position
1586
1587 ;check for BREAK
1588 F931 A0 FF ldy #$ff
1589 F933 A5 11 lda brkkey
1590 F935 D0 04 bne no_break
1591 F937 84 11 sty brkkey
1592 F939 A0 7F ldy #CIOStatBreak-1
1593 F93B no_break:
1594 F93B C8 iny
1595 F93C 60 rts
1596 .endp
1597
1598 ;==========================================================================
1599 ; Swap between the main screen and the split screen.
1600 ;
1601 ; Conventionally, the main screen is left as the selected context when
1602 ; the display handler is not active.
1603 ;
1604 ; Inputs:
1605 ; C = 0 for main screen
1606 ; C = 1 for split screen
1607 ;
1608 ; Modified:
1609 ; X
1610 ;
1611 ; Preserved:
1612 ; A
1613 ;
1614 ;==========================================================================
1615 ; Swap in the text screen (main if gr.0, split otherwise).
1616 ;
1617 F93D .proc EditorSwapToText
1618 ;set C=0 (main) if gr.0, C=1 (split) otherwise
1619 F93D A0 17 ldy #23
1620 F93F CC BF 02 cpy botscr
1621
1622 = F942 .def :ScreenSwap = *
1623 ;check if the correct set is in place
1624 F942 48 pha
1625 F943 A9 00 lda #0
1626 F945 65 7B adc swpflg
1627 F947 F0 14 beq already_there
1628
1629 ;Nope, we need to swap. Conveniently, the data to be swapped
1630 ;is in a 12 byte block:
1631 ;
1632 ; ROWCRS ($0054) TXTROW ($0290)
1633 ; COLCRS ($0055) TXTCOL ($0291)
1634 ; DINDEX ($0057) TINDEX ($0293)
1635 ; SAVMSC ($0058) TXTMSC ($0294)
1636 ; OLDROW ($005A) TXTOLD ($0296)
1637 ; OLDCOL ($005B) TXTOLD ($0297)
1638 ; OLDCHR ($005D) TXTOLD ($0299)
1639 ; OLDADR ($005E) TXTOLD ($029A)
1640
1641 F949 A2 0B ldx #11
1642 F94B swap_loop:
1643 F94B B5 54 lda rowcrs,x
1644 F94D BC 90 02 ldy txtrow,x
1645 F950 94 54 sty rowcrs,x
1646 F952 9D 90 02 sta txtrow,x
1647 F955 CA dex
1648 F956 10 F3 bpl swap_loop
1649
1650 ;invert swap flag
1651 F958 8A txa
1652 F959 45 7B eor swpflg
1653 F95B 85 7B sta swpflg
1654
1655 F95D already_there:
1656 F95D 68 pla
1657 F95E 60 rts
1658 .endp
1659
1660 ;==========================================================================
1661 ; Compute character address.
1662 ;
1663 ; Entry:
1664 ; X = byte index
1665 ; Y = line index
1666 ;
1667 ; Exit:
1668 ; A:X = address
1669 ;
1670 ; Used:
1671 ; ADRESS
1672 ;
1673 F95F .proc ScreenComputeAddr
1674 F95F 20 7F F9 jsr ScreenComputeRangeSize
1675 F962 85 64 sta adress
1676 F964 8A txa
1677 F965 18 clc
1678 F966 65 64 adc adress ;row*10,20,40+col
1679 F968 90 02 E6 65 scc:inc adress+1
1680 F96C 18 clc
1681 F96D 65 58 adc savmsc
1682 F96F AA tax
1683 F970 A5 65 lda adress+1
1684 F972 65 59 adc savmsc+1
1685 F974 60 rts
1686 .endp
1687
1688 ;==========================================================================
1689 = F977 ScreenComputeToAddr = ScreenComputeToAddrX0.with_x
1690 F975 .proc ScreenComputeToAddrX0
1691 F975 A2 00 ldx #0
1692 F977 with_x:
1693 F977 20 5F F9 jsr ScreenComputeAddr
1694 F97A 86 66 stx toadr
1695 F97C 85 67 sta toadr+1
1696 F97E 60 rts
1697 .endp
1698
1699 ;==========================================================================
1700 ; Compute size, in bytes, of a series of lines.
1701 ;
1702 ; Entry:
1703 ; Y = line count
1704 ;
1705 ; Exit:
1706 ; ADRESS+1 High byte of size
1707 ; A Low byte of size
1708 ;
1709 ; Preserved:
1710 ; X
1711 ;
1712 ; Modified:
1713 ; Y
1714 ;
1715 F97F .proc ScreenComputeRangeSize
1716 F97F A9 00 85 65 mva #0 adress+1
1717 F983 84 64 sty adress
1718 F985 A4 57 ldy dindex
1719 F987 B9 97 F2 lda ScreenPixelWidthIds,y
1720 F98A 38 sec
1721 F98B F9 B2 F2 sbc ScreenEncodingTab,y
1722 F98E A8 tay
1723 F98F C8 iny
1724 F990 A5 64 lda adress
1725 F992 0A asl
1726 F993 26 65 rol adress+1 ;row*2
1727 F995 0A asl
1728 F996 26 65 rol adress+1 ;row*4
1729 F998 18 clc
1730 F999 65 64 adc adress ;row*5
1731 F99B 90 02 E6 65 scc:inc adress+1
1732 F99F shift_loop:
1733 F99F 0A asl
1734 F9A0 26 65 rol adress+1 ;row*10,20,40
1735 F9A2 88 dey
1736 F9A3 10 FA bpl shift_loop
1737 F9A5 60 rts
1738 .endp
1739
1740 ;==========================================================================
1741 ; Setup for pixel plot.
1742 ;
1743 ; Entry:
1744 ; OLDCOL, OLDROW = position
1745 ; DELTAC = left-justified pixel mask
1746 ;
1747 ; Exit:
1748 ; TOADR = screen row
1749 ; SHFAMT = byte offset within row
1750 ; BITMSK = shifted bit mask for pixel
1751 ;
1752 ; Modified:
1753 ; ADRESS
1754 ;
1755 = F9AB ScreenAlignPixel = ScreenSetupPlotPixel.rshift_mask
1756 F9A6 .proc ScreenSetupPlotPixel
1757 ;;##TRACE "Folded pixel = $%02X" db(hold1)
1758 F9A6 20 B5 F9 jsr ScreenSetupPixelAddr
1759
1760 ;preshift bit mask
1761 F9A9 A5 77 lda deltac
1762 F9AB rshift_mask:
1763 F9AB CA dex
1764 F9AC 30 04 bmi xmaskshift_done
1765 F9AE xmaskshift_loop:
1766 F9AE 4A lsr
1767 F9AF CA dex
1768 F9B0 10 FC bpl xmaskshift_loop
1769 F9B2 xmaskshift_done:
1770 F9B2 85 6E sta bitmsk
1771
1772 ;;##TRACE "Initial bitmasks = $%02X $%02X" db(bitmsk) db(dmask)
1773 F9B4 60 rts
1774 .endp
1775
1776 ;==========================================================================
1777 ; Setup for pixel addressing.
1778 ;
1779 ; Entry:
1780 ; COLCRS, ROWCRS = position (ScreenSetupPixelAddr)
1781 ; OLDCOL, OLDROW = position (ScreenSetupPixelAddrOld)
1782 ;
1783 ; Exit:
1784 ; TOADR = screen row
1785 ; SHFAMT = byte offset within row
1786 ; X = number of bits from left side of byte to left side of pixel
1787 ;
1788 F9B5 .proc ScreenSetupPixelAddr
1789 ;compute initial address
1790 F9B5 A4 5A ldy oldrow
1791 F9B7 20 75 F9 jsr ScreenComputeToAddrX0
1792
1793 ;;##TRACE "Initial row address = $%04X" dw(toadr)
1794
1795 ;compute initial byte offset
1796 F9BA A5 5C lda oldcol+1
1797 F9BC A6 5B ldx oldcol
1798 F9BE phase2:
1799 F9BE 6A ror
1800 F9BF 86 6F stx shfamt
1801 F9C1 A9 00 lda #0
1802 F9C3 A6 57 ldx dindex
1803 F9C5 BC B2 F2 ldy ScreenEncodingTab,x
1804 F9C8 F0 06 beq no_xshift
1805 F9CA xshift_loop:
1806 F9CA 66 6F ror shfamt
1807 F9CC 6A ror
1808 F9CD 88 dey
1809 F9CE D0 FA bne xshift_loop
1810 F9D0 no_xshift:
1811 F9D0 2A rol
1812 F9D1 2A rol
1813 F9D2 2A rol
1814 F9D3 2A rol
1815 F9D4 AA tax
1816
1817 ;;##TRACE "Initial row offset = $%02X" db(shfamt)
1818 F9D5 60 rts
1819 .endp
1820
1821 ;==========================================================================
1822 ; ScreenAdvancePosNonMode0
1823 ;
1824 F9D6 .proc ScreenAdvancePosNonMode0
1825 ;advance position
1826 F9D6 E6 55 inc colcrs
1827 F9D8 D0 02 E6 56 sne:inc colcrs+1
1828 F9DC A6 57 ldx dindex
1829 F9DE BC 97 F2 ldy ScreenPixelWidthIds,x
1830 F9E1 BE AD F2 ldx ScreenPixelWidthsHi,y
1831 F9E4 E4 56 cpx colcrs+1
1832 F9E6 D0 0F bne graphics_no_wrap
1833 F9E8 BE A8 F2 ldx ScreenPixelWidthsLo,y
1834 F9EB E4 55 cpx colcrs
1835 F9ED D0 08 bne graphics_no_wrap
1836
1837 F9EF graphics_eol:
1838 ;move to left side and then one row down -- note that this may
1839 ;push us into an invalid coordinate, which will result on an error
1840 ;on the next call if not corrected
1841 F9EF A0 00 ldy #0
1842 F9F1 84 55 sty colcrs
1843 F9F3 84 56 sty colcrs+1
1844 F9F5 E6 54 inc rowcrs
1845 F9F7 graphics_no_wrap:
1846 F9F7 A0 01 ldy #1
1847 F9F9 60 rts
1848 .endp
1849
1850 ;==========================================================================
1851 .if !_KERNEL_XLXE
1852 _SCREEN_TABLES_1
1853 .endif
270 F9FA icl 'editor.s'
Source: source/Shared/editor.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Editor Handler
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 F9FA .proc EditorOpen
12 F9FA 20 EB FD jsr ScreenResetLogicalLineMap
13 F9FD 8E FE 02 stx dspflg ;!! relies on X=0 from ScreenResetLogicalLineMap
14 FA00 8E A2 02 stx escflg
15
16 ;we must force mode 0 here -- ACTION calls this with $0C in AUX2 and
17 ;expects mode 0 to be set
18 FA03 4C F2 F3 jmp ScreenOpenMode0
19 .endp
20
21 ;==========================================================================
22 = FE28 EditorClose = ScreenClose
23
24 ;==========================================================================
25 ;
26 ; === Forced read mode ===
27 ;
28 ; If bit 0 if AUX1 is set on the IOCB, it means to read in forced read
29 ; mode. In forced read mode, no keyboard input is fetched and instead
30 ; line read immediately commences, as if ENTER were pressed.
31 ;
32 ; Note that since AUX1 is tested on the IOCB used, it is possible to have
33 ; E: open on more than one IOCB with different forced read modes.
34 ;
35 FA06 .proc EditorGetByte
36 ;check if we have anything left in the current line
37 FA06 A5 6B lda bufcnt
38 FA08 D0 06 bne have_line
39
40 ;nope, fetch a line
41 FA0A 20 26 FA jsr EditorGetLine
42 FA0D 10 01 bpl have_line
43 FA0F 60 rts
44
45 FA10 have_line:
46 ;swap to text context
47 FA10 20 3D F9 jsr EditorSwapToText
48
49 ;subtract off a char
50 FA13 C6 6B dec bufcnt
51
52 ;check if we're at the EOL
53 FA15 D0 09 bne have_char
54
55 ;yes, we're at the EOL -- print it and return it (this will re-enable
56 ;the cursor, too)
57 FA17 A9 9B lda #$9b
58 FA19 20 12 F6 jsr ScreenPutByte
59
60 FA1C A9 9B lda #$9b
61 FA1E D0 03 bne done
62
63 FA20 have_char:
64 ;read a char from the screen
65 FA20 20 D2 F5 jsr ScreenGetByte
66 FA23 done:
67 FA23 4C 9E FD jmp EditorSwapToScreen
68 .endp
69
70 ;==========================================================================
71 ; This behavior is quite complex:
72 ; - The editor remembers the cursor position within the initial logical
73 ; line. Only contents beyond the initial position are returned. This
74 ; is true even if the cursor is moved out of the logical line and back
75 ; in again.
76 ; - Margins are not included.
77 ; - Trailing spaces at the end of a logical line are not returned even
78 ; if the cursor is after them.
79 ; - If the cursor is moved to another logical line, that logical line is
80 ; read instead. There is no memory of the line start for previous
81 ; logical lines, so if there was a prompt on that line it will be
82 ; picked up too.
83 ; - If the logical line length is exceeded, a beep sounds near the end
84 ; and after three lines (120ch) the logical line is terminated and a
85 ; new logical line is started. However, the previous logical line that
86 ; was overflowed is still returned. This still happens if the new
87 ; logical line extends to more than one physical line or even if
88 ; itself overflows (!). If the physical line is changed with up/down,
89 ; this memory is lost, but left/right don't do this.
90 ; - If a logical line extends exactly to the end of a physical line, an
91 ; extra blank line is printed on EOL.
92 ; - If a logical line extends exactly to the end of the screen, a cursor
93 ; out of bounds error results. (We currently do not implement this...
94 ; feature.)
95 ;
96 ; === The BUFSTR variable ===
97 ;
98 ; The BUFSTR variable is critical to the way that the get line algorithm
99 ; works. It actually consists of two bytes, the row followed by the column
100 ; of the origin of the line to be read. This is updated whenever a read
101 ; request arrives that starts a new line or whenever the cursor is moved
102 ; to a different logical line. This is how the screen editor knows to
103 ; read at the end of a prompt or from a different line that you have moved
104 ; to, and how it tracks that when scrolling occurs. It does not, however,
105 ; get updated when regular characters are typed, even when spilling to a
106 ; new logical line.
107 ;
108 ; === BUFCNT ===
109 ;
110 ; BUFCNT contains the number of characters left to return before we have
111 ; to get a new line: $00 means we will wait for keys, $01 is the EOL, and
112 ; >$01 returns a typed character. We need to follow this convention or
113 ; else the combination of S_VBXE.SYS + CON.SYS /E from SDX 4.46 acts
114 ; strangely on launch.
115 ;
116 FA26 .proc EditorGetLine
117 = 006D _start_x equ bufstr+1
118 = 006C _start_y equ bufstr
119
120 ;Set line buffer start to current position (NOT the start of the logical
121 ;line -- this is a special case).
122 FA26 20 3D F9 jsr EditorSwapToText
123 FA29 A5 55 85 6D mva colcrs _start_x
124 FA2D A5 54 85 6C mva rowcrs _start_y
125 FA31 20 9E FD jsr EditorSwapToScreen
126
127 ;check if forced read is enabled on the IOCB -- if so, assume we've gotten
128 ;an EOL
129 FA34 A5 2A lda icax1z
130 FA36 4A lsr
131 FA37 B0 25 bcs do_eol
132
133 FA39 read_loop:
134 ;get a character
135 FA39 20 69 FE jsr KeyboardGetByte
136 FA3C 10 01 bpl read_ok
137 FA3E read_error:
138 FA3E 60 rts
139
140 FA3F read_ok:
141 FA3F C9 9B cmp #$9b
142 FA41 F0 1D beq is_eol
143
144 ;echo the character
145 FA43 20 B8 FA jsr EditorPutByte
146 FA46 30 F6 bmi read_error
147
148 ;check if we've hit the warning point (logical pos 113)
149 FA48 A5 55 lda colcrs
150 FA4A C9 21 cmp #33
151 FA4C D0 EB bne read_loop
152
153 ;convert current row to logical start row
154 FA4E 20 85 FD jsr EditorGetCurLogicalRow
155
156 ;check if we're on the third row
157 FA51 18 clc
158 FA52 69 02 adc #2
159 FA54 C5 54 cmp rowcrs
160
161 ;if so, sound the bell
162 FA56 D0 E1 bne read_loop
163 FA58 20 97 FD jsr EditorBell
164
165 FA5B 4C 39 FA jmp read_loop
166
167 FA5E do_eol:
168 FA5E A9 9B lda #$9b
169 FA60 is_eol:
170 ;echo the character
171 FA60 20 B8 FA jsr EditorPutByte
172 FA63 30 D9 bmi read_error
173
174 ;swap to text screen context
175 FA65 20 3D F9 jsr EditorSwapToText
176
177 ;hide the cursor so we can scan text properly
178 FA68 20 F1 F8 jsr ScreenHideCursor
179
180 ;compute address
181 FA6B A2 00 ldx #0
182 FA6D 86 63 stx logcol
183 FA6F A4 6C ldy _start_y
184 FA71 84 54 sty rowcrs
185 FA73 20 77 F9 jsr ScreenComputeToAddr
186
187 FA76 A4 6D ldy _start_x
188 FA78 char_loop:
189 FA78 E6 63 inc logcol
190 FA7A B1 66 lda (toadr),y
191 FA7C F0 04 beq blank
192 FA7E A5 63 85 6B mva logcol bufcnt
193 FA82 blank:
194 FA82 C4 53 cpy rmargn
195 FA84 C8 iny
196 FA85 90 F1 bcc char_loop
197 FA87 20 C5 FD jsr EditorNextLineAddr
198
199 ;check if we're at the bottom of the screen
200 FA8A E6 54 inc rowcrs
201 FA8C A5 54 lda rowcrs
202 FA8E CD BF 02 cmp botscr
203 FA91 B0 0A bcs scan_scroll
204
205 ;check if we're at the end of the logical line
206 FA93 20 7E FD jsr EditorTestLogicalLineBit
207 FA96 D0 08 bne scan_done
208
209 FA98 A4 52 ldy lmargn
210 FA9A 4C 78 FA jmp char_loop
211
212 FA9D scan_scroll:
213 ;we're below the screen... need to scroll up
214 FA9D 20 CC FC jsr EditorDeleteLine0
215
216 FAA0 scan_done:
217 ;adjust BUFCNT so it is the number of chars to read (scanned + EOL)
218 FAA0 E6 6B inc bufcnt
219
220 ;mark this as the start of a new logical line, trimming off any extra
221 ;blank lines
222 FAA2 A5 54 lda rowcrs
223 FAA4 20 71 FD jsr EditorGetLogicalLineInfo
224 FAA7 19 B2 02 ora logmap,y
225 FAAA 99 B2 02 sta logmap,y
226
227 ;reset cursor to line start, but leave the cursor off
228 FAAD A6 6D 86 55 mvx _start_x colcrs
229 FAB1 A4 6C 84 54 mvy _start_y rowcrs
230
231 ;swap back to main context and exit successfully
232 FAB5 4C 9C FD jmp EditorSwapToScreen_Y1
233 .endp
234
235 ;==========================================================================
236 ; This routine must NOT write BUFADR -- doing so breaks the DLT flasher.
237 ;
238 ; Behavior notes:
239 ; - Ctrl+1 (suspend display) does not affect control codes handled only
240 ; by E:. In particular, EOL, move up/down/left/right, ESC, insert, and
241 ; delete are not affected by it. CLEAR on the other hand, is, because
242 ; it's handled by S:.
243 ;
244 FAB8 .proc EditorPutByte
245 ;open the text screen if it is not open already
246 FAB8 A4 57 ldy dindex
247 FABA F0 0C beq screenok
248 FABC AC BF 02 ldy botscr
249 FABF C0 04 cpy #4
250 FAC1 F0 05 beq screenok
251
252 FAC3 48 pha
253 FAC4 20 EE F3 jsr ScreenOpenGr0
254 FAC7 68 pla
255 FAC8 screenok:
256
257 ;swap to text context
258 FAC8 20 3D F9 jsr EditorSwapToText
259
260 ;hide the cursor -- this must be done before we suspend display on
261 ;Ctrl+1.
262 FACB 20 F1 F8 jsr ScreenHideCursor
263
264 ;save off character to free up acc
265 FACE A8 tay
266
267 ;Check if [esc] is active
268 ;
269 ;Note that the ASL trick relies on ESCFLG being $80 when set; this
270 ;is in fact guaranteed by the spec in the OS Manual, Appendix L, B26.
271 ;
272 FACF 0E A2 02 asl escflg ;test and clear escape flag
273 FAD2 B0 1E bcs not_special
274
275 ;check if this might be a special character
276 FAD4 29 1F and #$1f
277 FAD6 C9 1B cmp #$1b
278 FAD8 90 18 bcc not_special
279
280 ;might be special, but not EOL... search the special char table
281 FADA A2 0E ldx #special_code_tab_end-special_code_tab-1
282 FADC 98 tya
283 FADD 20 B7 FC jsr EditorIsSpecial
284 FAE0 D0 10 bne not_special
285
286 FAE2 special_found:
287 ;check if display of control codes is desired; if so, we need to ignore this
288 FAE2 AD FE 02 lda dspflg
289 FAE5 D0 0B bne not_special
290
291 ;jump to routine
292 FAE7 20 63 FC jsr dispatch
293 FAEA 20 C0 FC jsr EditorRecomputeCursorAddr
294 FAED 20 17 FE jsr ScreenShowCursorAndXitOK
295 FAF0 10 06 bpl xit2 ;!! - unconditional jump
296
297 FAF2 not_special:
298 ;ok, just put the char to the screen
299 FAF2 8C FB 02 sty atachr
300 FAF5 20 2A F6 jsr ScreenPutByte.not_clear
301 FAF8 xit2:
302 ;swap back to main context and exit
303 FAF8 4C 9E FD jmp EditorSwapToScreen
304
305 ;---------------
306 FAFB special_code_tab:
307 FAFB 1B dta $1b
308 FAFC 1C dta $1c
309 FAFD 1D dta $1d
310 FAFE 1E dta $1e
311 FAFF 1F dta $1f
312 FB00 7D dta $7d
313 FB01 7E dta $7e
314 FB02 7F dta $7f
315 FB03 9C dta $9c
316 FB04 9D dta $9d
317 FB05 9E dta $9e
318 FB06 9F dta $9f
319 FB07 FD dta $fd
320 FB08 FE dta $fe
321 FB09 FF dta $ff
322 FB0A special_code_tab_end:
323 FB0A 9B dta $9b ;these are only for the K: check
324 FB0B 7C dta $7c
325 FB0C special_code_tab_end_2:
326
327 ;----------------
328
329 FB0C special_dispatch_lo_tab:
330 FB0C 1A dta <(special_escape-1)
331 FB0D 23 dta <(special_up-1)
332 FB0E 2D dta <(special_down-1)
333 FB0F C1 dta <(special_left-1)
334 FB10 CE dta <(special_right-1)
335 FB11 20 dta <(special_clear-1)
336 FB12 48 dta <(special_backspace-1)
337 FB13 87 dta <(special_tab-1)
338 FB14 D7 dta <(special_delete_line-1)
339 FB15 DD dta <(special_insert_line-1)
340 FB16 74 dta <(special_clear_tab-1)
341 FB17 6C dta <(special_set_tab-1)
342 FB18 69 dta <(special_bell-1)
343 FB19 E4 dta <(special_delete_char-1)
344 FB1A F0 dta <(special_insert_char-1)
345
346 .if [((special_escape-1)^(special_insert_char-1))&$ff00]
347 .error 'Special character routines cross a page boundary: ',special_escape,'-',special_insert_char
348 .endif
349
350 ;---------------
351 FB1B special_escape:
352 FB1B A9 80 8D A2 02 mva #$80 escflg
353 FB20 60 rts
354
355 ;---------------
356 FB21 special_clear:
357 FB21 4C 4A F8 jmp ScreenClear
358
359 ;---------------
360 FB24 special_up:
361 FB24 A6 54 ldx rowcrs
362 FB26 D0 03 bne isup2
363 FB28 AE BF 02 ldx botscr
364 FB2B isup2:
365 FB2B CA dex
366 FB2C 10 0A bpl vmoveexit
367
368 ;---------------
369 FB2E special_down:
370 FB2E A6 54 ldx rowcrs
371 FB30 E8 inx
372 FB31 EC BF 02 cpx botscr
373 FB34 90 02 A2 00 scc:ldx #0
374
375 FB38 vmoveexit:
376 FB38 86 54 stx rowcrs
377
378 ;check if we have moved into a different logical line -- if so,
379 ;we need to reset the read row
380 FB3A 8A txa
381 FB3B 20 87 FD jsr EditorPhysToLogicalRow
382 FB3E C5 6C cmp bufstr
383 FB40 F0 06 beq moveexit
384
385 ;we switched rows -- reset read row
386 FB42 85 6C sta bufstr
387 FB44 A5 52 85 6D mva lmargn bufstr+1
388
389 FB48 moveexit:
390 FB48 60 rts
391
392 ;---------------
393 FB49 special_backspace:
394 ;check if we are at the left column
395 FB49 A5 52 lda lmargn
396 FB4B C5 55 cmp colcrs
397 FB4D B0 0B bcs sbks_wrap
398
399 ;nope, we can just back up
400 FB4F C6 55 dec colcrs
401
402 ;recompute pos and clear character
403 FB51 sbks_recomp:
404 FB51 20 C0 FC jsr EditorRecomputeCursorAddr
405 FB54 A0 00 ldy #0
406 FB56 98 tya
407 FB57 91 5E sta (oldadr),y
408 FB59 sbks_xit:
409 FB59 60 rts
410
411 FB5A sbks_wrap:
412 ;check if we're at the start of the logical line
413 FB5A A5 54 lda rowcrs
414 FB5C 20 7E FD jsr EditorTestLogicalLineBit
415 FB5F D0 F8 bne sbks_xit
416
417 ;no, so we need to wrap to the right column of the prev line...
418 FB61 C6 54 dec rowcrs
419 FB63 A5 53 lda rmargn
420 FB65 85 55 sta colcrs
421
422 ;recompute everything and exit
423 FB67 4C 51 FB jmp sbks_recomp
424
425 ;----------------
426 FB6A special_bell:
427 FB6A 4C 97 FD jmp EditorBell
428
429 ;----------------
430 FB6D special_set_tab:
431 FB6D 20 81 FB jsr special_common_tab
432 FB70 1D A3 02 ora tabmap,x
433 FB73 D0 08 bne special_common_exit_tab
434
435 FB75 special_clear_tab:
436 FB75 20 81 FB jsr special_common_tab
437 FB78 49 FF eor #$ff
438 FB7A 3D A3 02 and tabmap,x
439 FB7D special_common_exit_tab:
440 FB7D 9D A3 02 sta tabmap,x
441 FB80 60 rts
442
443 FB81 special_common_tab:
444 FB81 20 A7 FD jsr EditorGetLogicalColumn
445 FB84 A8 tay
446 FB85 4C B6 FD jmp EditorSetupTabIndex
447
448 ;--------------------------------------------------------------------------
449 ; Tab behavior:
450 ; - Moves cursor to the next tab position within the logical line.
451 ; - If there are no more tabs, moves cursor to beginning of next line.
452 ; This may cause a scroll.
453 ; - Tab does NOT adjust the read row.
454 ;
455 FB88 special_tab:
456 FB88 20 A7 FD jsr EditorGetLogicalColumn
457 FB8B A8 tay
458 FB8C 8A txa
459 FB8D 38 sec
460 FB8E 65 54 adc rowcrs
461 FB90 85 54 sta rowcrs
462
463 ;scan forward until we find the next bit set, or we hit position 120
464 FB92 tab_scan_loop:
465 FB92 C8 iny
466 FB93 C0 78 cpy #120
467 FB95 B0 08 bcs tab_found
468 FB97 20 B6 FD jsr EditorSetupTabIndex
469 FB9A 3D A3 02 and tabmap,x
470 FB9D F0 F3 beq tab_scan_loop
471 FB9F tab_found:
472 FB9F 84 55 sty colcrs
473 FBA1 tab_adjust_row:
474 FBA1 A5 55 lda colcrs
475 FBA3 38 sec
476 FBA4 E9 28 sbc #40 ;subtract a row worth of columns
477 FBA6 90 19 bcc tab_adjust_done ;exit if <40
478 FBA8 85 55 sta colcrs
479 FBAA E6 54 inc rowcrs ;next row
480 FBAC A5 54 lda rowcrs ;
481 FBAE CD BF 02 cmp botscr ;check if we're below the screen
482 FBB1 B0 07 bcs tab_adjust_scroll ;if so, do a scroll
483 FBB3 20 7E FD jsr EditorTestLogicalLineBit ;check if we're on a new log line
484 FBB6 F0 E9 beq tab_adjust_row ;if not, keep adjusting
485 FBB8 10 03 bpl tab_adjust_left ;position at beginning of new line
486
487 FBBA tab_adjust_scroll:
488 FBBA 20 CC FC jsr EditorDeleteLine0
489 FBBD tab_adjust_left:
490 FBBD hmove_to_lmargn:
491 ;move to left margin
492 FBBD A6 52 ldx lmargn
493 FBBF hmove_to_x:
494 FBBF 86 55 stx colcrs
495 FBC1 tab_adjust_done:
496 FBC1 60 rts
497
498 ;--------------------------------------------------------------------------
499 FBC2 special_left:
500 FBC2 A6 55 ldx colcrs
501 FBC4 F0 05 beq slft_to_right
502 FBC6 CA dex
503 FBC7 E4 52 cpx lmargn
504 FBC9 B0 F4 bcs hmove_to_x
505
506 ;move to right margin
507 FBCB slft_to_right:
508 FBCB A6 53 ldx rmargn
509 FBCD 90 F0 bcc hmove_to_x
510
511 ;--------------------------------------------------------------------------
512 FBCF special_right:
513 FBCF A6 55 ldx colcrs
514 FBD1 E4 53 cpx rmargn
515 FBD3 B0 E8 bcs hmove_to_lmargn
516
517 ;right one char
518 FBD5 E6 55 inc colcrs
519 FBD7 60 rts
520
521 ;--------------------------------------------------------------------------
522 ; Delete line behavior:
523 ; - The entire logical line that the cursor is in is deleted.
524 ; - The cursor is positioned at the beginning of the next logical line.
525 ;
526 FBD8 special_delete_line:
527 ;delete current logical line
528 FBD8 20 85 FD jsr EditorGetCurLogicalRow
529 FBDB 4C CE FC jmp EditorDeleteLine
530
531 ;----------------
532 FBDE special_insert_line:
533 ;insert a new logical line at this point; note that this may split
534 ;the current line
535 FBDE 38 sec
536 FBDF 20 8E F8 jsr ScreenInsertLine
537 FBE2 4C BD FB jmp tab_adjust_left
538
539 ;--------------------------------------------------------------------------
540 ; Delete character behavior:
541 ; - Erases the current character and drags in characters from the
542 ; remainder of the logical line, excluding the margins.
543 ; - If the last physical line is blank and not the only physical line in
544 ; the logical line, it is deleted and the logical line is shortened.
545 ; Only one line is removed even if the last two lines are blank. The
546 ; cursor does not move when this happens and may be shifted into the
547 ; next logical line. This also does not change the input line!
548 ;
549 FBE5 special_delete_char:
550 ;compute base address of current row (not char)
551 FBE5 A4 54 ldy rowcrs
552 FBE7 84 51 sty hold1
553 FBE9 20 75 F9 jsr ScreenComputeToAddrX0
554
555 ;begin shifting in the first column at the current pos
556 FBEC A4 55 ldy colcrs
557
558 ;delete chars to end
559 FBEE 4C 7C FC jmp delete_shift_loop_entry
560
561 ;--------------------------------------------------------------------------
562 ; Insert character behavior:
563 ; - Inserts a blank at the current position and shifts characters forward
564 ; within the margins.
565 ; - If the character shifted out of the end of the logical line is non-
566 ; blank, the logical line will be extended if possible. This can cause
567 ; a scroll. If the logical line is already three rows, the last
568 ; character is lost.
569 ;
570 FBF1 special_insert_char:
571 ;get logical line start
572 FBF1 20 85 FD jsr EditorGetCurLogicalRow
573
574 ;compute line at which we cannot add another physical line
575 FBF4 18 69 03 add #3
576 FBF7 85 76 sta deltar
577
578 ;compute address of row
579 FBF9 A4 54 ldy rowcrs
580 FBFB 84 51 sty hold1
581 FBFD 20 75 F9 jsr ScreenComputeToAddrX0
582
583 FC00 A4 55 ldy colcrs ;end shift at current column
584 FC02 A2 00 ldx #0 ;insert blank character at start
585 FC04 F0 04 beq insert_line_loop_entry
586
587 FC06 insert_line_loop:
588 FC06 A4 52 ldy lmargn ;end shift at left column
589 FC08 A6 50 ldx tmpchr ;character to shift in (from last line)
590
591 FC0A insert_line_loop_entry:
592 FC0A 84 65 sty adress+1 ;stash shift origin
593 FC0C A4 53 ldy rmargn ;begin shift at right column
594 FC0E B1 66 lda (toadr),y ;get character being shifted out
595 FC10 85 50 sta tmpchr ;save it off to later shift in on the next row
596 FC12 insert_shift_loop:
597 FC12 88 dey
598 FC13 B1 66 lda (toadr),y
599 FC15 C8 iny
600 FC16 91 66 sta (toadr),y
601 FC18 88 dey
602 FC19 C4 65 cpy adress+1
603 FC1B D0 F5 bne insert_shift_loop
604
605 ;put character shifted out from previous line into beginning of this one
606 FC1D 8A txa
607 FC1E 91 66 sta (toadr),y
608
609 ;next row
610 FC20 E6 51 inc hold1
611
612 FC22 20 C5 FD jsr EditorNextLineAddr
613
614 ;check if we're at the end of the logical line
615 FC25 A5 51 lda hold1
616 FC27 CD BF 02 cmp botscr
617 FC2A B0 05 bcs insert_crossed_lline
618 FC2C 20 7E FD jsr EditorTestLogicalLineBit
619 FC2F F0 D5 beq insert_line_loop
620 FC31 insert_crossed_lline:
621
622 ;check if we shifted out a non-blank character
623 FC31 A5 50 lda tmpchr
624 FC33 F0 2D beq insert_done
625
626 ;save current row
627 FC35 A5 54 lda rowcrs
628 FC37 48 pha
629
630 ;check if the logical line is already 3 rows -- if so, we cannot extend and
631 ;the last char goes into the bit bucket, but we still must scroll (!)
632 FC38 A6 51 ldx hold1
633 FC3A E4 76 cpx deltar
634 FC3C 08 php
635
636 ;move to the bottom line +1; we use ROWCRS so it stays updated with the scrolling
637 FC3D 86 54 stx rowcrs
638
639 ;check if we are at the bottom of the screen; if so we must scroll
640 FC3F A9 00 lda #0
641 FC41 85 76 sta deltar
642
643 FC43 EC BF 02 cpx botscr
644 FC46 90 03 bcc insert_no_scroll
645
646 ;scroll the screen
647 FC48 20 CC FC jsr EditorDeleteLine0
648
649 FC4B insert_no_scroll:
650 ;if we can't extend, we are done
651 FC4B 28 plp
652 FC4C B0 0E bcs insert_cant_extend
653
654 ;just insert a blank line at the end of this logical row to extend it
655 FC4E 20 8D F8 jsr ScreenInsertPhysLine
656
657 ;restore shifted character and put it in place
658 FC51 A4 54 ldy rowcrs
659 FC53 20 75 F9 jsr ScreenComputeToAddrX0
660 FC56 A5 50 lda tmpchr
661 FC58 A4 52 ldy lmargn
662 FC5A 91 66 sta (toadr),y
663 FC5C insert_cant_extend:
664
665 ;restore cursor row, adjusting for any scroll
666 FC5C 68 pla
667 FC5D 38 sec
668 FC5E E5 76 sbc deltar
669 FC60 85 54 sta rowcrs
670
671 FC62 insert_done:
672 FC62 60 rts
673
674 ;---------------------------------
675 FC63 dispatch:
676 FC63 A9 FB lda #>special_escape
677 FC65 48 pha
678 FC66 BD 0C FB lda special_dispatch_lo_tab,x
679 FC69 48 pha
680 FC6A 60 rts
681
682 ;---------------------------------
683 FC6B delete_line_loop:
684 ;copy first character into right margin of previous row
685 FC6B A4 52 ldy lmargn
686 FC6D B1 66 lda (toadr),y
687 FC6F A4 53 ldy rmargn
688 FC71 91 68 sta (frmadr),y
689
690 ;start shifting new row at left margin
691 FC73 A4 52 ldy lmargn
692 FC75 delete_shift_loop:
693 FC75 C8 iny
694 FC76 B1 66 lda (toadr),y
695 FC78 88 dey
696 FC79 91 66 sta (toadr),y
697 FC7B C8 iny
698 FC7C delete_shift_loop_entry:
699 FC7C C4 53 cpy rmargn
700 FC7E D0 F5 bne delete_shift_loop
701
702 ;next line
703 FC80 20 C5 FD jsr EditorNextLineAddr
704
705 ;check if the next row is a logical line start
706 FC83 A6 51 ldx hold1
707 FC85 E8 inx
708 FC86 EC BF 02 cpx botscr
709 FC89 B0 08 bcs delete_stop_shifting
710 FC8B 86 51 stx hold1
711 FC8D 8A txa
712 FC8E 20 7E FD jsr EditorTestLogicalLineBit
713
714 ;keep going if not
715 FC91 F0 D8 beq delete_line_loop
716
717 FC93 delete_stop_shifting:
718 ;blank the last character of the last line
719 FC93 A4 53 ldy rmargn
720 FC95 A9 00 lda #0
721 FC97 91 68 sta (frmadr),y
722
723 ;check if the last line is blank
724 FC99 delete_blank_test_loop:
725 FC99 B1 68 lda (frmadr),y
726 FC9B D0 19 bne delete_not_blank
727 FC9D 88 dey
728 FC9E C4 52 cpy lmargn
729 FCA0 B0 F7 bcs delete_blank_test_loop
730
731 ;the last line is blank... check if it is a logical line start
732 FCA2 C6 51 dec hold1
733 FCA4 A5 51 lda hold1
734 FCA6 20 7E FD jsr EditorTestLogicalLineBit
735
736 ;skip if so -- we can't delete the entire logical line
737 FCA9 D0 0B bne delete_not_blank
738
739 ;delete this physical line... however, do not move the cursor and
740 ;do not change the read line even if the cursor hops to a new one
741 FCAB A5 55 lda colcrs
742 FCAD 48 pha
743 FCAE A5 51 lda hold1
744 FCB0 20 CE FC jsr EditorDeleteLine
745 FCB3 68 pla
746 FCB4 85 55 sta colcrs
747
748 FCB6 delete_not_blank:
749 ;re-show cursor and exit
750 FCB6 60 rts
751
752 .endp
753
754 ;==========================================================================
755 FCB7 .proc EditorIsSpecial
756 FCB7 special_binsearch:
757 FCB7 DD FB FA cmp EditorPutByte.special_code_tab,x
758 FCBA F0 03 beq special_found
759 FCBC CA dex
760 FCBD 10 F8 bpl special_binsearch
761 FCBF special_found:
762 FCBF 60 rts
763 .endp
764
765 ;==========================================================================
766 FCC0 .proc EditorRecomputeCursorAddr
767 FCC0 A6 55 ldx colcrs
768 FCC2 A4 54 ldy rowcrs
769 FCC4 20 5F F9 jsr ScreenComputeAddr
770 FCC7 86 5E stx oldadr
771 FCC9 85 5F sta oldadr+1
772 FCCB 60 rts
773 .endp
774
775 ;==========================================================================
776 ; Delete a logical line on screen, and scroll the remainder of the screen
777 ; upward.
778 ;
779 ; Inputs:
780 ; A = physical line row to delete
781 ;
782 ; Outputs:
783 ; DELTAR = number of lines scrolled
784 ;
785 = FCCE EditorDeleteLine = EditorDeleteLine0.use_line
786 FCCC .proc EditorDeleteLine0
787 FCCC A9 00 lda #0
788 FCCE use_line:
789 FCCE 85 51 sta hold1
790 FCD0 A2 00 ldx #0
791 FCD2 86 76 stx deltar
792
793 FCD4 scroll_loop:
794 ;compute base address and set that as destination
795 FCD4 A4 51 ldy hold1
796
797 .if _KERNEL_XLXE
798 FCD6 38 sec
799 FCD7 D0 21 bne nofine
800 FCD9 AE 6E 02 ldx fine
801 FCDC F0 1C beq nofine
802 FCDE A2 00 ldx #0
803 FCE0 xloop:
804 FCE0 A5 14 lda rtclok+2
805 FCE2 C5 14 F0 FC cmp:req rtclok+2
806 FCE6 E8 inx
807 FCE7 8E 05 D4 stx vscrol
808 FCEA E0 07 cpx #7
809 FCEC D0 F2 bne xloop
810 FCEE A9 10 lda #32/2
811 FCF0 CD 0B D4 90 FB cmp:rcc vcount
812 FCF5 CD 0B D4 B0 FB cmp:rcs vcount
813 FCFA nofine:
814 FCFA 08 php ;C=0 for fine scroll, C=1 for coarse scroll
815 .endif
816
817 ;set TOADR to the line to be deleted
818 FCFB 20 75 F9 jsr ScreenComputeToAddrX0
819
820 FCFE A6 51 ldx hold1
821 FD00 10 0C bpl line_loop_start
822
823 FD02 line_loop:
824 ;bump line: FRMADR <- TOADR, TOADR += 40
825 FD02 20 C5 FD jsr EditorNextLineAddr
826
827 ;move line -- note that we are copying backwards (TOADR to FRMADR)!
828 FD05 A0 27 ldy #39
829 FD07 B1 66 91 68 88 10 + mva:rpl (toadr),y (frmadr),y-
830
831 FD0E line_loop_start:
832 FD0E E8 inx
833 FD0F EC BF 02 cpx botscr
834 FD12 D0 EE bne line_loop
835
836 ;clear the last line
837 FD14 A0 27 ldy #39
838 FD16 A9 00 lda #0
839 FD18 91 66 88 10 FB sta:rpl (toadr),y-
840
841 .if _KERNEL_XLXE
842 FD1D 28 plp
843 FD1E B0 03 bcs nofinescroll2
844 FD20 8D 05 D4 sta vscrol
845 FD23 nofinescroll2:
846 .endif
847
848 FD23 20 58 FD jsr adjust_lines
849
850 ;delete bits out of the logical mask until we get to the next
851 ;logical line, computing the number of lines to scroll
852 FD26 A5 51 lda hold1
853 FD28 20 71 FD jsr EditorGetLogicalLineInfo
854 FD2B BE 55 FD ldx update_table,y ;get number of masks to shift
855 FD2E 38 sec ;setup to add a new logical line at the end
856 FD2F F0 09 beq do_mask ;jump to masking if we're on byte 2
857 FD31 2E B4 02 rol logmap+2 ;shift byte 2
858 FD34 CA dex ;
859 FD35 F0 03 beq do_mask ;jump to masking if we're on byte 1
860 FD37 2E B3 02 rol logmap+1 ;shift byte 1
861 FD3A do_mask:
862 FD3A 85 64 sta adress ;stash mask
863 FD3C 49 FF eor #$ff ;invert mask
864 FD3E 39 B2 02 and logmap,y ;kill target bit
865 FD41 85 65 sta adress+1 ;stash modified mask
866 FD43 C6 64 dec adress ;form mask for LSBs below bit
867 FD45 25 64 and adress ;isolate those bits
868 FD47 65 65 adc adress+1 ;shift those up and the bit from the next byte in
869 FD49 99 B2 02 sta logmap,y ;write to logmap
870
871 FD4C E6 76 inc deltar ;increment line count
872 FD4E E6 64 inc adress ;revert mask
873 FD50 24 64 bit adress ;test if we still have a logical line
874
875 ;loop back if we need to delete more physical lines
876 FD52 F0 80 beq scroll_loop
877
878 ;all done
879 FD54 60 rts
880
881 FD55 update_table:
882 FD55 02 01 00 dta 2,1,0
883
884 FD58 adjust_lines:
885 FD58 A5 52 lda lmargn ;prep for line adjustments
886
887 ;adjust the read row if it is affected by the deletion
888 FD5A A2 6C ldx #<bufstr
889 FD5C 20 61 FD jsr adjust_line
890
891 ;adjust the cursor row if it is affected by the deletion
892 FD5F A2 54 ldx #<rowcrs
893 FD61 adjust_line:
894 FD61 B4 00 ldy 0,x ;get row
895 FD63 C4 51 cpy hold1 ;compare against deletion pos
896 FD65 90 07 bcc adjust_line_above ;nothing to do if it's above del range
897 FD67 D0 03 bne adjust_line_below ;skip col adjust if it's below del range
898 FD69 95 01 sta 1,x ;within range - move cursor to left mgn
899 FD6B 60 rts
900 FD6C adjust_line_below:
901 FD6C D6 00 dec 0,x
902 FD6E adjust_line_above:
903 FD6E 60 rts
904 .endp
905
906 ;==========================================================================
907 = E4C9 EditorGetStatus = CIOExitSuccess
908 = E4CB EditorSpecial = CIOExitNotSupported
909 = E4CB EditorInit = CIOExitNotSupported
910
911 ;==========================================================================
912 ; Entry:
913 ; A = line
914 ;
915 ; Exit:
916 ; P = bit test status
917 ; A = bit mask
918 ; X = bit index
919 ; Y = mask index
920 ;
921 = FD6F EditorGetCurLogicalLineInfo = _EditorGetLogicalLineInfo
922 = FD71 EditorGetLogicalLineInfo = _EditorGetLogicalLineInfo.use_a
923 FD6F .proc _EditorGetLogicalLineInfo
924 FD6F A5 54 lda rowcrs
925 FD71 use_a:
926 FD71 48 pha
927 FD72 4A lsr
928 FD73 4A lsr
929 FD74 4A lsr
930 FD75 A8 tay
931 FD76 68 pla
932 FD77 29 07 and #7
933 FD79 AA tax
934 FD7A BD C1 E4 lda ReversedBitMasks,x
935 FD7D 60 rts
936 .endp
937
938 ;==========================================================================
939 ; Test whether a physical line is the start of a logical line.
940 ;
941 ; Entry:
942 ; A = line
943 ;
944 ; Exit:
945 ; Z = 1 if so, 0 if not
946 ;
947 ; Modified:
948 ; all registers
949 ;
950 FD7E .proc EditorTestLogicalLineBit
951 FD7E 20 71 FD jsr EditorGetLogicalLineInfo
952 FD81 39 B2 02 and logmap,y
953 FD84 60 rts
954 .endp
955
956 ;==========================================================================
957 ; Get the starting physical line for a logical line.
958 ;
959 ; Entry:
960 ; A = physical line
961 ;
962 ; Exit:
963 ; A = logical line start
964 ;
965 ; Modified:
966 ; ADRESS
967 ;
968 = FD87 EditorPhysToLogicalRow = EditorGetCurLogicalRow.use_line
969 FD85 .proc EditorGetCurLogicalRow
970 FD85 A5 54 lda rowcrs
971 FD87 use_line:
972 FD87 85 64 sta adress
973 FD89 test_loop:
974 FD89 A5 64 lda adress
975 FD8B 20 7E FD jsr EditorTestLogicalLineBit
976 FD8E D0 04 bne found
977 FD90 C6 64 dec adress
978 FD92 D0 F5 bne test_loop
979 FD94 found:
980 FD94 A5 64 lda adress
981 FD96 60 rts
982 .endp
983
984 ;==========================================================================
985 FD97 .proc EditorBell
986 FD97 A0 00 ldy #0
987 FD99 4C CC E4 jmp Bell
988 .endp
989
990 ;==========================================================================
991 FD9C .proc EditorSwapToScreen_Y1
992 FD9C A0 01 ldy #1
993 = FD9E .def :EditorSwapToScreen = *
994 FD9E 84 64 sty adress
995 FDA0 18 clc
996 FDA1 20 42 F9 jsr ScreenSwap
997 FDA4 A4 64 ldy adress
998 FDA6 60 rts
999 .endp
1000
1001 ;==========================================================================
1002 ; Compute the current logical column.
1003 ;
1004 ; Exit:
1005 ; A = column
1006 ; X = inverted row index (0-2 => $ff-$fd)
1007 ;
1008 FDA7 .proc EditorGetLogicalColumn
1009 ;get starting row of logical line
1010 FDA7 A5 54 lda rowcrs
1011 FDA9 20 87 FD jsr EditorPhysToLogicalRow
1012
1013 ;subtract off current row
1014 FDAC 18 clc
1015 FDAD E5 54 sbc rowcrs
1016 FDAF AA tax
1017
1018 ;multiply negated difference by 40
1019 FDB0 BD DB FC lda EditorLineLengthTab-$fc,x
1020
1021 ;add in physical column
1022 FDB3 65 55 adc colcrs
1023 FDB5 60 rts
1024 .endp
1025
1026 ;==========================================================================
1027 FDB6 .proc EditorSetupTabIndex
1028 FDB6 98 tya
1029 FDB7 29 07 and #7
1030 FDB9 AA tax
1031 FDBA BD C1 E4 lda ReversedBitMasks,x
1032 FDBD 48 pha
1033 FDBE 98 tya
1034 FDBF 4A lsr
1035 FDC0 4A lsr
1036 FDC1 4A lsr
1037 FDC2 AA tax
1038 FDC3 68 pla
1039 FDC4 60 rts
1040 .endp
1041
1042 ;==========================================================================
1043 ; Copy TOADR to FRMADR and add 40 to TOADR.
1044 ;
1045 FDC5 .proc EditorNextLineAddr
1046 FDC5 A5 66 lda toadr
1047 FDC7 85 68 sta frmadr
1048 FDC9 18 69 28 add #40
1049 FDCC 85 66 sta toadr
1050 FDCE A5 67 lda toadr+1
1051 FDD0 85 69 sta frmadr+1
1052 FDD2 69 00 adc #0
1053 FDD4 85 67 sta toadr+1
1054 FDD6 60 rts
1055 .endp
1056
1057 ;==========================================================================
1058 FDD7 .proc EditorLineLengthTab
1059 FDD7 78 50 28 00 dta 120, 80, 40, 0
1060 .endp
1061
271
272 .ifdef _KERNEL_816
273 icl 'screenext816.s'
274 .else
275 FDDB icl 'screenext.s'
Source: source/Shared/screenext.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Screen Handler extension routines
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 FDDB ScreenEncodingOffsetTable:
12 FDDB 00 dta $00 ;4-bit
13 FDDC 10 dta $10 ;2-bit
14 FDDD 14 dta $14 ;1-bit
15
16 .if !_KERNEL_XLXE
17 _SCREEN_TABLES_3
18 .endif
19
20 ;==========================================================================
21 ; ScreenFineScrollDLI
22 ;
23 ; This DLI routine is used to set the PF1 color to PF2 to kill junk that
24 ; would appear on the extra line added with vertical scrolling.
25 ;
26 .if _KERNEL_XLXE
27 FDDE .proc ScreenFineScrollDLI
28 FDDE 48 pha
29 FDDF AD C6 02 lda color2
30 FDE2 45 4F eor colrsh
31 FDE4 25 4E and drkmsk
32 FDE6 8D 17 D0 sta colpf1
33 FDE9 68 pla
34 FDEA 40 rti
35 .endp
36 .endif
37
38 ;==========================================================================
39 ; ScreenResetLogicalLineMap
40 ;
41 ; Marks all lines as the start of logical lines.
42 ;
43 ; Exit:
44 ; X = 0
45 ;
46 FDEB .proc ScreenResetLogicalLineMap
47 FDEB A2 FF ldx #$ff
48 FDED 8E B2 02 stx logmap
49 FDF0 8E B3 02 stx logmap+1
50 FDF3 8E B4 02 stx logmap+2
51
52 ;reset line read position
53 FDF6 E8 inx
54 FDF7 86 6C stx bufstr
55 FDF9 A5 52 lda lmargn
56 FDFB 85 6D sta bufstr+1
57
58 ;note - X=0 relied on here by EditorOpen
59 FDFD 60 rts
60 .endp
61
62 ;==========================================================================
63 ; ScreenSetLastPosition
64 ;
65 ; Copies COLCRS/ROWCRS to OLDCOL/OLDROW.
66 ;
67 FDFE .proc ScreenSetLastPosition
68 FDFE A2 02 ldx #2
69 FE00 loop:
70 FE00 B5 54 lda rowcrs,x
71 FE02 95 5A sta oldrow,x
72 FE04 CA dex
73 FE05 10 F9 bpl loop
74 FE07 60 rts
75 .endp
76
77 ;==========================================================================
78 ; ScreenAdvancePosMode0
79 ;
80 ; Advance to the next cursor position in reading order, for mode 0.
81 ;
82 ; Exit:
83 ; C = 1 if no wrap, 0 if wrapped
84 ;
85 ; Modified:
86 ; X
87 ;
88 ; Preserved:
89 ; A
90 ;
91 FE08 .proc ScreenAdvancePosMode0
92 FE08 E6 55 inc colcrs
93 FE0A A6 53 ldx rmargn
94 FE0C E4 55 cpx colcrs
95 FE0E B0 06 bcs post_wrap
96 FE10 A6 52 ldx lmargn
97 FE12 86 55 stx colcrs
98 FE14 E6 54 inc rowcrs
99 FE16 post_wrap:
100 FE16 60 rts
101 .endp
102
103
104 ;==========================================================================
105 ; Output:
106 ; Y=1 for convenience
107 ;
108 ; (OLDADR) must point to the cursor location with OLDCHR even if the cursor
109 ; is hidden. This is required by SDX QUICKED.SYS, which always restores the
110 ; cursor.
111 ;
112 FE17 .proc ScreenShowCursorAndXitOK
113 ;;##ASSERT dw(oldadr) >= dw(savmsc)
114 ;check if the cursor is enabled
115 FE17 A0 00 ldy #0
116 FE19 B1 5E lda (oldadr),y
117 FE1B 85 5D sta oldchr
118 FE1D AC F0 02 ldy crsinh
119 FE20 D0 04 bne cursor_inhibited
120 FE22 49 80 eor #$80
121 FE24 91 5E sta (oldadr),y
122 FE26 cursor_inhibited:
123 FE26 C8 iny
124 FE27 60 rts
125 .endp
126
127 ;==========================================================================
128 ; Close screen (S:).
129 ;
130 ; This is a no-op in OS-B mode. In XL/XE mode, it reopens the device in
131 ; Gr.0 if fine scrolling is on, since this is necessary to clear the DLI.
132 ; This happens even if S: doesn't correspond to the text window. Only
133 ; the high bit of FINE is checked.
134 ;
135 .if !_KERNEL_XLXE
136 ScreenClose = CIOExitSuccess
137 .else
138 FE28 .proc ScreenClose
139 FE28 2C 6E 02 bit fine
140 FE2B 30 03 bmi disable_fine_scrolling
141
142 FE2D A0 01 ldy #1
143 FE2F 60 rts
144
145 FE30 disable_fine_scrolling:
146 ;turn off DLI
147 FE30 A9 40 8D 0E D4 mva #$40 nmien
148
149 ;restore vdslst
150 FE35 A2 55 ldx #<IntExitHandler_None
151 FE37 A9 C0 lda #>IntExitHandler_None
152 FE39 20 A0 F5 jsr ScreenOpenGr0.write_vdslst
153
154 FE3C 4C EE F3 jmp ScreenOpenGr0
155 .endp
156 .endif
157
158 ;==========================================================================
159 .if !_KERNEL_XLXE
160 _SCREEN_TABLES_2
161 .endif
276 .endif
277
278 FE3F _KERNEL_REPORT_MODULE_SIZE 'Display routines', 0
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'Display routines'
1 $FE3F -> $0ADF($0000) Display routines
3 = FE3F .def ?@_kernel_lastpt = *
Source: source/main.xasm
279
280 .ifdef _KERNEL_816
281 icl 'keyboard816.s'
282 .else
283 FE3F icl 'keyboard.s'
Source: source/Shared/keyboard.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Keyboard Handler
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 ;==========================================================================
11 ; Oddly, the keyboard IRQs are not enabled from the keyboard init
12 ; routine. It's done by the Display Handler instead on open.
13 ;
14 FE3F .proc KeyboardInit
15 FE3F A2 FF ldx #$ff
16 FE41 8E FC 02 stx ch
17 FE44 8E F2 02 stx ch1
18 FE47 E8 inx
19 FE48 8E F1 02 stx keydel
20 FE4B 8E B6 02 stx invflg
21
22 ;turn on shift lock
23 FE4E A9 40 8D BE 02 mva #$40 shflok
24
25 ;set keyboard definition table pointer
26 .if _KERNEL_XLXE
27 FE53 A9 1D 85 79 A9 FF + mwa #KeyCodeToATASCIITable keydef
28 .endif
29 FE5B 60 rts
30 .endp
31
32 = E4C9 KeyboardOpen = CIOExitSuccess
33 = E4C9 KeyboardClose = CIOExitSuccess
34
35 ;==========================================================================
36 ; K: GET BYTE handler.
37 ;
38 ; Behavior:
39 ; - Exits with a Break error when break key is pressed.
40 ; - Ctrl-1 does not suspend input here (it is handled by S:/E:).
41 ; - Ctrl-3 returns an EOF error.
42 ; - Caps Lock sets caps mode on OS-A/B depending on Ctrl and Shift key
43 ; state. On the XL/XE OS, pressing Caps Lock alone will enable shift
44 ; lock if no lock is enabled and disable it otherwise.
45 ; - Shift/Control lock is applied by K:, but only on alpha keys.
46 ; - Inverse mode is also applied by K:. Control characters are excluded:
47 ; 1B-1F/7C-7F/9B-9F/FD-FF.
48 ; - Any Ctrl+Shift key code (>=$C0) produces a key click but is otherwise
49 ; ignored.
50 ;
51 FE5C .nowarn .proc _KeyboardGetByte
52 FE5C toggle_shift:
53 .if _KERNEL_XLXE
54 ;Caps Lock without Shift or Control is a toggle on the XL/XE line:
55 ; None -> Shifted
56 ; Shifted, Control -> None
57 FE5C AE BE 02 ldx shflok
58 FE5F D0 02 bne caps_off
59 FE61 A0 40 ldy #$40
60 .endif
61 FE63 shift_ctrl_on:
62 FE63 caps_off:
63 FE63 98 tya
64 FE64 29 C0 and #$c0
65 FE66 write_shflok:
66 FE66 8D BE 02 sta shflok
67
68 = FE69 .def :KeyboardGetByte
69 FE69 waitForChar:
70 FE69 A2 FF ldx #$ff
71 FE6B waitForChar2:
72 FE6B A5 11 lda brkkey
73 FE6D F0 57 beq isBreak
74 FE6F AD FC 02 lda ch
75 FE72 C9 FF cmp #$ff
76 FE74 F0 F5 beq waitForChar2
77
78 ;invalidate char
79 FE76 8E FC 02 stx ch
80
81 ;do keyboard click (we do this even for ignored ctrl+shift+keys)
82 FE79 A0 0C ldy #12
83 FE7B 20 CC E4 jsr Bell
84
85 ;ignore char if both ctrl and shift are pressed
86 FE7E C9 C0 cmp #$c0
87 FE80 B0 E7 bcs waitForChar
88
89 ;trap Ctrl-3 and return EOF
90 FE82 C9 9A cmp #$9a
91 FE84 F0 45 beq isCtrl3
92
93 ;translate char
94 FE86 A8 tay
95
96 .if _KERNEL_XLXE
97 FE87 B1 79 lda (keydef),y
98 .else
99 lda KeyCodeToATASCIITable,y
100 .endif
101
102 ;handle special keys (see keytable.s)
103 FE89 10 0E bpl valid_key
104 FE8B C9 81 cmp #$81
105 FE8D 90 DA bcc waitForChar ;$80 - invalid
106 FE8F F0 2B beq isInverse ;$81 - inverse video
107 FE91 C9 83 cmp #$83
108 FE93 90 C7 bcc toggle_shift ;$82 - caps lock
109 FE95 C9 85 cmp #$85
110 FE97 90 CA bcc shift_ctrl_on ;$83 - shift caps lock / $84 - ctrl caps lock
111
112 FE99 valid_key:
113 ;check for alpha key
114 FE99 C9 61 cmp #'a'
115 FE9B 90 0F bcc notAlpha
116 FE9D C9 7B cmp #'z'+1
117 FE9F B0 0B bcs notAlpha
118
119 ;check for shift/control lock
120 FEA1 2C BE 02 bit shflok
121 FEA4 70 04 bvs doShiftLock
122 FEA6 10 04 bpl notAlpha
123
124 ;do control lock logic
125 FEA8 29 1F and #$1f
126
127 FEAA doShiftLock:
128 FEAA 29 DF and #$df
129
130 FEAC notAlpha:
131 ;check if we should apply inverse flag -- special characters are excluded
132 FEAC A2 10 ldx #EditorPutByte.special_code_tab_end_2-EditorPutByte.special_code_tab-1
133 FEAE 20 B7 FC jsr EditorIsSpecial
134 FEB1 F0 03 beq skip_inverse
135
136 ;apply inverse flag
137 FEB3 4D B6 02 eor invflg
138 FEB6 skip_inverse:
139
140 ;return char
141 FEB6 8D FB 02 sta atachr ;required or CON.SYS (SDX 4.46) breaks
142 FEB9 A0 01 ldy #1
143 FEBB 60 rts
144
145 FEBC isInverse:
146 FEBC AD B6 02 lda invflg
147 FEBF 49 80 eor #$80
148 FEC1 8D B6 02 sta invflg
149 FEC4 B0 A3 bcs waitForChar ;!! - unconditional
150
151 FEC6 isBreak:
152 FEC6 86 11 stx brkkey
153 FEC8 A0 80 ldy #CIOStatBreak
154 FECA 60 rts
155
156 FECB isCtrl3:
157 FECB A0 88 ldy #CIOStatEndOfFile
158 FECD 60 rts
159 .endp
160
161 ;==============================================================================
162 = E4CB KeyboardPutByte = CIOExitNotSupported
163 = E4C9 KeyboardGetStatus = CIOExitSuccess
164 = E4CB KeyboardSpecial = CIOExitNotSupported
165
166 ;==============================================================================
167 ; Keyboard IRQ
168 ;
169 ; HELP button ($11, $51, and $91):
170 ; - Affects SRTIMR, ATRACT, KEYDEL, and HELPFG
171 ; - Does NOT affect CH, CH1
172 ;
173 FECE .proc KeyboardIRQ
174 ;reset software repeat timer
175 .if _KERNEL_XLXE
176 FECE AD D9 02 8D 2B 02 mva krpdel srtimr
177 .else
178 mva #$30 srtimr
179 .endif
180
181 ;read new key
182 FED4 AD 09 D2 lda kbcode
183
184 .if _KERNEL_XLXE
185 ;check for HELP
186 FED7 29 3F and #$3f
187 FED9 C9 11 cmp #$11
188 FEDB D0 05 bne not_help
189 FEDD 8D DC 02 sta helpfg
190 FEE0 F0 1E beq xit2
191
192 FEE2 not_help:
193 FEE2 AD 09 D2 lda kbcode
194 .endif
195
196 ;check if it is the same as the prev key
197 FEE5 CD F2 02 cmp ch1
198 FEE8 D0 08 bne debounced
199
200 ;reject key if debounce timer is still running
201 FEEA AD F1 02 lda keydel
202 FEED D0 16 bne xit
203 FEEF AD F2 02 lda ch1
204 FEF2 debounced:
205
206 ;check for Ctrl+1 to toggle display activity
207 FEF2 C9 9F cmp #$9f
208 FEF4 F0 11 beq is_suspend
209
210 ;store key
211 FEF6 8D FC 02 sta ch
212 FEF9 8D F2 02 sta ch1
213
214 ;reset attract
215 FEFC A9 00 85 4D mva #0 atract
216
217 FF00 xit2:
218 ;reset key delay
219 FF00 A9 03 8D F1 02 mva #3 keydel
220
221 FF05 xit:
222 ;all done
223 FF05 68 pla
224 FF06 40 rti
225
226 FF07 is_suspend:
227 ;toggle stop/start flag
228 FF07 AD FF 02 lda ssflag
229 FF0A 49 FF eor #$ff
230 FF0C 8D FF 02 sta ssflag
231 FF0F B0 EF bcs xit2 ;!! carry set from cmp #$9f!
232 .endp
233
234 ;==============================================================================
235 FF11 .proc KeyboardBreakIRQ
236 FF11 A9 00 85 11 mva #0 brkkey
237
238 ;need to clear the suspend flag as BREAK automatically nukes a pending Ctrl+1
239 FF15 8D FF 02 sta ssflag
240
241 ;interestingly, the default break handler forces the cursor back on.
242 FF18 8D F0 02 sta crsinh
243
244 FF1B 68 pla
245 FF1C 40 rti
246 .endp
284 .endif
285
286 FF1D icl 'keytable.s'
Source: source/Shared/keytable.s
1 ; Altirra - Atari 800/800XL/5200 emulator
2 ; Modular Kernel ROM - Keyboard Scan Code Table
3 ; Copyright (C) 2008-2016 Avery Lee
4 ;
5 ; Copying and distribution of this file, with or without modification,
6 ; are permitted in any medium without royalty provided the copyright
7 ; notice and this notice are preserved. This file is offered as-is,
8 ; without any warranty.
9
10 FF1D KeyCodeToATASCIITable:
11 ;Special codes in this table (values important for compat):
12 ; $80 - invalid key
13 ; $81 - inverse video
14 ; $82 - caps lock
15 ; $83 - shift caps lock
16 ; $84 - control caps lock
17
18 ;lowercase
19 FF1D 6C 6A 3B 80 80 6B + dta $6C, $6A, $3B, $80, $80, $6B, $2B, $2A
20 FF25 6F 80 70 75 9B 69 + dta $6F, $80, $70, $75, $9B, $69, $2D, $3D
21 FF2D 76 80 63 80 80 62 + dta $76, $80, $63, $80, $80, $62, $78, $7A
22 FF35 34 80 33 36 1B 35 + dta $34, $80, $33, $36, $1B, $35, $32, $31
23 FF3D 2C 20 2E 6E 80 6D + dta $2C, $20, $2E, $6E, $80, $6D, $2F, $81
24 FF45 72 80 65 79 7F 74 + dta $72, $80, $65, $79, $7F, $74, $77, $71
25 FF4D 39 80 30 37 7E 38 + dta $39, $80, $30, $37, $7E, $38, $3C, $3E
26 FF55 66 68 64 80 82 67 + dta $66, $68, $64, $80, $82, $67, $73, $61
27
28 ;SHIFT
29 FF5D 4C 4A 3A 80 80 4B + dta $4C, $4A, $3A, $80, $80, $4B, $5C, $5E
30 FF65 4F 80 50 55 9B 49 + dta $4F, $80, $50, $55, $9B, $49, $5F, $7C
31 FF6D 56 80 43 80 80 42 + dta $56, $80, $43, $80, $80, $42, $58, $5A
32 FF75 24 80 23 26 1B 25 + dta $24, $80, $23, $26, $1B, $25, $22, $21
33 FF7D 5B 20 5D 4E 80 4D + dta $5B, $20, $5D, $4E, $80, $4D, $3F, $80
34 FF85 52 80 45 59 9F 54 + dta $52, $80, $45, $59, $9F, $54, $57, $51
35 FF8D 28 80 29 27 9C 40 + dta $28, $80, $29, $27, $9C, $40, $7D, $9D
36 FF95 46 48 44 80 83 47 + dta $46, $48, $44, $80, $83, $47, $53, $41
37
38 ;CTRL
39 FF9D 0C 0A 7B 80 80 0B + dta $0C, $0A, $7B, $80, $80, $0B, $1E, $1F
40 FFA5 0F 80 10 15 9B 09 + dta $0F, $80, $10, $15, $9B, $09, $1C, $1D
41 FFAD 16 80 03 80 80 02 + dta $16, $80, $03, $80, $80, $02, $18, $1A
42 FFB5 80 80 9B 80 1B 80 + dta $80, $80, $9B, $80, $1B, $80, $FD, $80
43 FFBD 00 20 60 0E 80 0D + dta $00, $20, $60, $0E, $80, $0D, $80, $80
44 FFC5 12 80 05 19 9E 14 + dta $12, $80, $05, $19, $9E, $14, $17, $11
45 FFCD 80 80 80 80 FE 80 + dta $80, $80, $80, $80, $FE, $80, $7D, $FF
46 FFD5 06 08 04 80 84 07 + dta $06, $08, $04, $80, $84, $07, $13, $01
287 FFDD _KERNEL_REPORT_MODULE_SIZE 'Keyboard routines', 0
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'Keyboard routines'
1 $FFDD -> $019E($0000) Keyboard routines
3 = FFDD .def ?@_kernel_lastpt = *
Source: source/main.xasm
288
289 .if _KERNEL_XLXE
290 .echo 'Free space: ', $FFEE-*, ' bytes'
290 Free space: $0011 bytes
291 .else
292 .echo 'Free space: ', $FFFA-*, ' bytes'
293 .endif
294
295 ;==============================================================================
296 ; version block (XL/XE)
297 ;==============================================================================
298
299 .ifdef _KERNEL_816
300 org $ffe4
301 dta a(IntDispatchNativeCop) ;$FFE4
302 dta a(IntDispatchNativeBreak) ;$FFE6
303 dta a(IntDispatchNativeAbort) ;$FFE8
304 dta a(IntDispatchNativeNmi) ;$FFEA
305 dta a(0) ;$FFEC
306 dta a(IntDispatchNativeIrq) ;$FFEE
307 dta $13 ;$FFF0
308 dta $02 ;$FFF1 option byte - !!CHECKED BY ARCHON
309 dta 'CX' ;$FFF2
310 dta a(IntDispatchCop) ;$FFF4
311 dta a(0) ;$FFF6
312 dta a(IntDispatchAbort) ;$FFF8
313 .elif _KERNEL_XLXE
314 FFDD org $ffee
315 FFEE 01 01 13 dta $01,$01,$13
316 FFF1 02 dta $02 ;option byte - !!CHECKED BY ARCHON
317 FFF2 43 58 00 00 00 dta 'CX',$00,$00,$00
318 FFF7 00 dta $00
319 FFF8 00 00 dta a(0)
320 .endif
321
322 ;==============================================================================
323 ; reset vectors
324 ;==============================================================================
325 FFFA org $fffa
326 FFFA 81 C1 dta a(IntDispatchNMI)
327 FFFC B9 EE dta a(InitReset)
328 FFFE 95 C1 dta a(IntDispatchIRQ)
329
330 end