mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-28 23:49:20 +00:00
10525 lines
364 KiB
Plaintext
10525 lines
364 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 _KERNEL_PBI_SUPPORT = 1
|
|
14 _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 = 0000 _KERNEL_PBI_SUPPORT = 0
|
|
24 = 0000 _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 dta a(0)
|
|
49 dta $01,$01,$13
|
|
50 dta $02
|
|
51 dta 'CX',$00,$00,$00
|
|
52 dta $00
|
|
53
|
|
54 _KERNEL_REPORT_MODULE_MARK
|
|
55
|
|
56 .ifdef _KERNEL_816
|
|
57 icl 'vbi816.s'
|
|
58 .else
|
|
59 icl 'vbi.s'
|
|
60 .endif
|
|
61
|
|
62 _KERNEL_REPORT_MODULE_SIZE 'VBI routines', 0
|
|
63
|
|
64 .ifdef _KERNEL_816
|
|
65 icl 'interrupt816.s'
|
|
66 .else
|
|
67 icl 'interrupt.s'
|
|
68 .endif
|
|
69
|
|
70 _KERNEL_REPORT_MODULE_SIZE 'Base interrupt routines', 0
|
|
71
|
|
72 .ifdef _KERNEL_816
|
|
73 icl 'irq816.s'
|
|
74 .else
|
|
75 icl 'irq.s'
|
|
76 .endif
|
|
77
|
|
78 _KERNEL_REPORT_MODULE_SIZE 'IRQ routines', 0
|
|
79
|
|
80 icl 'pbi.s'
|
|
81 _KERNEL_REPORT_MODULE_SIZE 'PBI routines', 0
|
|
82 icl 'phandler.s'
|
|
83 _KERNEL_REPORT_MODULE_SIZE 'Peripheral Handler routines', 0
|
|
84
|
|
85 .ifdef _KERNEL_816
|
|
86 icl 'syscall816.s'
|
|
87 icl 'sysdev816.s'
|
|
88 .endif
|
|
89
|
|
90 org $cc00
|
|
91 icl 'atariifont.inc'
|
|
92
|
|
93 org $d000
|
|
94 icl 'bootscreen.s'
|
|
95
|
|
96 opt f+
|
|
97 .endif
|
|
98
|
|
99 org $d800
|
|
100
|
|
101 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 org $d800
|
|
117 = D800 _afp = afp
|
|
118 .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 E9 F9 editrv dta a(EditorOpen-1)
|
|
108 E402 C8 E4 dta a(EditorClose-1)
|
|
109 E404 F5 F9 dta a(EditorGetByte-1)
|
|
110 E406 A7 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 C8 E4 dta a(ScreenClose-1)
|
|
118 E414 9E F5 dta a(ScreenGetByte-1)
|
|
119 E416 DE F5 dta a(ScreenPutByte-1)
|
|
120 E418 C8 E4 dta a(ScreenGetStatus-1)
|
|
121 E41A C2 F6 dta a(ScreenSpecial-1)
|
|
122 E41C 20 91 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 65 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 4B FE jmp KeyboardInit
|
|
132 E42F 00 dta $00
|
|
133
|
|
134 E430 C5 ED printv dta a(PrinterOpen-1)
|
|
135 E432 DA ED dta a(PrinterClose-1)
|
|
136 E434 CA E4 dta a(PrinterGetByte-1)
|
|
137 E436 E1 ED dta a(PrinterPutByte-1)
|
|
138 E438 2F EE dta a(PrinterGetStatus-1)
|
|
139 E43A CA E4 dta a(PrinterSpecial-1)
|
|
140 E43C 20 C0 ED jsr PrinterInit
|
|
141 E43F 00 dta $00
|
|
142
|
|
143 E440 5B EE casetv dta a(CassetteOpen-1)
|
|
144 E442 B0 EE dta a(CassetteClose-1)
|
|
145 E444 D1 EE dta a(CassetteGetByte-1)
|
|
146 E446 11 EF dta a(CassettePutByte-1)
|
|
147 E448 C8 E4 dta a(CassetteGetStatus-1)
|
|
148 E44A CA E4 dta a(CassetteSpecial-1)
|
|
149 E44C 4C 51 EE jmp CassetteInit
|
|
150 E44F 00 dta $00
|
|
151
|
|
152 ;vector table
|
|
153 E450 org $e450
|
|
154 E450 4C 60 ED diskiv jmp DiskInit ;$E450
|
|
155 E453 4C 61 ED dskinv jmp DiskHandler ;$E453
|
|
156 E456 4C FC E4 ciov jmp CIO ;$E456
|
|
157 E459 4C 50 E9 siov jmp SIO ;$E459
|
|
158 E45C 4C 69 E8 setvbv jmp VBISetVector ;$E45C
|
|
159 E45F 4C 1D E7 sysvbv jmp VBIStage1 ;$E45F
|
|
160 E462 4C 61 E7 xitvbv jmp VBIExit ;$E462
|
|
161 E465 4C 45 E9 sioinv jmp SIOInit ;$E465
|
|
162 E468 4C 99 EA sendev jmp SIOSendEnable ;$E468
|
|
163 E46B 4C 7F E8 intinv jmp IntInitInterrupts ;$E46B
|
|
164 E46E 4C EA E4 cioinv jmp CIOInit ;$E46E
|
|
165
|
|
166 .if _KERNEL_XLXE
|
|
167 blkbdv jmp SelfTestEntry ;$E471
|
|
168 .else
|
|
169 E471 4C 80 E4 blkbdv jmp Blackboard ;$E471
|
|
170 .endif
|
|
171
|
|
172 E474 4C 49 F0 warmsv jmp InitWarmStart ;$E474
|
|
173 E477 4C FD EF coldsv jmp InitColdStart ;$E477
|
|
174 E47A 4C 52 EF rblokv jmp CassetteReadBlock ;$E47A
|
|
175 E47D 4C 6F EE csopiv jmp CassetteOpenRead ;$E47D
|
|
176
|
|
177 .if _KERNEL_XLXE
|
|
178 pupdiv jmp SelfTestEntry ;$E480 XL/XE: power-up display
|
|
179 slftsv jmp $5000 ;$E483 XL/XE: self-test entry
|
|
180 pentv jmp PHAddHandler ;$E486 XL/XE: peripheral handler add
|
|
181 phunlv jmp PHRemoveHandler ;$E489 XL/XE: peripheral handler remove
|
|
182 phiniv jmp PHInitHandler ;$E48C XL/XE: peripheral handler init
|
|
183 gpdvv PBI_VECTOR_TABLE ;$E48F XL/XE: Generic device vector
|
|
184 .endif
|
|
185
|
|
186 .if _KERNEL_XLXE
|
|
187 icl 'selftestentry.s'
|
|
188 .else
|
|
189 E480 icl 'blackboard.s'
|
|
Source: source/Shared/blackboard.s
|
|
1 ; Altirra - Atari 800/800XL emulator
|
|
2 ; Kernel ROM replacement - Blackboard
|
|
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 E480 .proc Blackboard
|
|
11 ;print banner
|
|
12 E480 A9 A6 8D 44 03 mva #<blackboard_banner icbal
|
|
13 E485 A9 E4 8D 45 03 mva #>blackboard_banner icbah
|
|
14 E48A 8D 48 03 sta icbll
|
|
15 E48D A2 00 ldx #0
|
|
16 E48F 8E 49 03 stx icblh
|
|
17 E492 A9 09 lda #CIOCmdPutRecord
|
|
18 E494 echoloop:
|
|
19 E494 8D 42 03 sta iccmd
|
|
20 E497 20 56 E4 jsr ciov
|
|
21
|
|
22 E49A 8E 48 03 stx icbll
|
|
23 E49D A9 07 lda #CIOCmdGetChars
|
|
24 E49F D0 F3 bne echoloop
|
|
25 .endp
|
|
26
|
|
27 .if *>$e480 && *<$e4c0
|
|
28 ;anchor version for emulator purposes
|
|
29 E4A1 org $e4a6
|
|
30 .endif
|
|
31 E4A6 blackboard_banner:
|
|
32 E4A6 41 6C 74 69 72 72 + dta 'AltirraOS '
|
|
33 E4B0 _KERNELSTR_VERSION
|
|
Macro: _KERNELSTR_VERSION [Source: source/Shared/version.inc]
|
|
1 E4B0 33 2E 32 36 dta '3.26'
|
|
Source: source/Shared/blackboard.s
|
|
34 E4B4 20 6D 65 6D 6F 20 + dta ' memo pad',$9B
|
|
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 E4BE 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 01 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 0E 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 mva #0 hndlod
|
|
62 .endif
|
|
63
|
|
64 E50A A5 2F lda ciochr
|
|
65 E50C 28 plp
|
|
66 E50D 60 rts
|
|
67
|
|
68 E50E process:
|
|
69 ;validate IOCB offset
|
|
70 E50E 8A txa
|
|
71 E50F 29 8F and #$8f
|
|
72 E511 F0 06 beq validIOCB
|
|
73
|
|
74 ;return invalid IOCB error
|
|
75 E513 A0 86 ldy #CIOStatInvalidIOCB
|
|
76 E515 60 rts
|
|
77
|
|
78 E516 cmdInvalid:
|
|
79 ;invalid command <$03
|
|
80 E516 A0 84 ldy #CIOStatInvalidCmd
|
|
81 E518 60 rts
|
|
82
|
|
83 E519 validIOCB:
|
|
84 E519 20 D1 E6 jsr CIOLoadZIOCB
|
|
85
|
|
86 ;check if we're handling the OPEN command
|
|
87 E51C A5 22 lda iccomz
|
|
88 E51E C9 03 cmp #CIOCmdOpen
|
|
89 E520 F0 66 beq cmdOpen
|
|
90 E522 90 F2 bcc cmdInvalid
|
|
91
|
|
92 ;check if the IOCB is open
|
|
93 E524 A4 20 ldy ichidz
|
|
94
|
|
95 .if !_KERNEL_XLXE
|
|
96 E526 10 1C bpl isOpen
|
|
97 .else
|
|
98 bmi not_open
|
|
99
|
|
100 ;check for a provisionally open IOCB
|
|
101 iny
|
|
102 bpl isOpen
|
|
103
|
|
104 ;okay, it's provisionally open... check if it's a close
|
|
105 cmp #CIOCmdClose
|
|
106 sne:jmp cmdCloseProvisional
|
|
107
|
|
108 ;check if we're allowed to load a handler
|
|
109 lda hndlod
|
|
110 beq not_open
|
|
111
|
|
112 ;try to load the handler
|
|
113 jsr CIOLoadHandler
|
|
114 bpl isOpen
|
|
115 rts
|
|
116 .endif
|
|
117
|
|
118 E528 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 E528 A0 01 ldy #1
|
|
129 E52A A5 22 lda iccomz
|
|
130 E52C C9 0C cmp #CIOCmdClose
|
|
131 E52E F0 06 beq ignoreOpen
|
|
132 E530 C9 0D cmp #CIOCmdGetStatus
|
|
133 E532 B0 03 bcs preOpen ;closed IOCB is OK for get status and special
|
|
134 E534 not_open_handler:
|
|
135 E534 A0 85 ldy #CIOStatNotOpen
|
|
136 E536 ignoreOpen:
|
|
137 E536 60 rts
|
|
138
|
|
139 E537 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 E537 20 E0 E6 jsr CIOParsePath
|
|
143
|
|
144 ;check for special command
|
|
145 E53A A5 22 lda iccomz
|
|
146 E53C C9 0D cmp #CIOCmdGetStatus
|
|
147 E53E F0 40 beq cmdGetStatusSoftOpen
|
|
148 E540 C9 0E cmp #CIOCmdSpecial
|
|
149 E542 B0 3F bcs cmdSpecialSoftOpen
|
|
150
|
|
151 E544 isOpen:
|
|
152 E544 A6 22 ldx iccomz
|
|
153 E546 E0 0E cpx #CIOCmdSpecial
|
|
154 E548 90 02 A2 0E scc:ldx #$0e
|
|
155
|
|
156 ;do permissions check
|
|
157 E54C BD 8F E6 lda perm_check_table-4,x
|
|
158 E54F 30 04 bmi skip_perm_check
|
|
159 E551 24 2A bit icax1z
|
|
160 E553 F0 26 beq perm_check_fail
|
|
161 E555 skip_perm_check:
|
|
162
|
|
163 ;load command table vector
|
|
164 E555 BD B0 E6 lda command_table_hi-4,x
|
|
165 E558 48 pha
|
|
166 E559 BD A5 E6 lda command_table_lo-4,x
|
|
167 E55C 48 pha
|
|
168
|
|
169 ;preload dispatch vector and dispatch to command
|
|
170 E55D BC 9A E6 ldy vector_preload_table-4,x
|
|
171 E560 load_vector:
|
|
172 E560 A6 20 ldx ichidz
|
|
173 E562 BD 1B 03 85 2C BD + mwa hatabs+1,x icax3z
|
|
174 E56C B1 2C lda (icax3z),y
|
|
175 E56E AA tax
|
|
176 E56F 88 dey
|
|
177 E570 B1 2C lda (icax3z),y
|
|
178 E572 85 2C sta icax3z
|
|
179 E574 86 2D stx icax3z+1
|
|
180
|
|
181 ;many commands want to check length=0 on entry
|
|
182 E576 A5 28 lda icbllz
|
|
183 E578 05 29 ora icblhz
|
|
184 E57A 60 rts
|
|
185
|
|
186 E57B 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 E57B 18 clc
|
|
191 E57C 69 7F adc #$7f
|
|
192 E57E A8 tay
|
|
193 E57F 60 rts
|
|
194
|
|
195 ;--------------------------------------------------------------------------
|
|
196 E580 cmdGetStatusSoftOpen:
|
|
197 E580 A0 09 ldy #9
|
|
198 E582 2C dta {bit $0100}
|
|
199 E583 cmdSpecialSoftOpen:
|
|
200 E583 A0 0B ldy #11
|
|
201 E585 invoke_and_soft_close_xit:
|
|
202 E585 4C BF E6 jmp CIOInvoke
|
|
203
|
|
204 ;--------------------------------------------------------------------------
|
|
205 ; Open command ($03).
|
|
206 ;
|
|
207 E588 cmdOpen:
|
|
208 ;check if the IOCB is already open
|
|
209 E588 A4 20 ldy ichidz
|
|
210 E58A C8 iny
|
|
211 E58B F0 03 beq notAlreadyOpen
|
|
212
|
|
213 ;IOCB is already open - error
|
|
214 E58D A0 81 ldy #CIOStatIOCBInUse
|
|
215 E58F 60 rts
|
|
216
|
|
217 E590 notAlreadyOpen:
|
|
218 ;attempt to parse and open -- note that this will fail out directly
|
|
219 ;on an unknown device or provisional open
|
|
220 E590 20 E0 E6 jsr CIOParsePath
|
|
221
|
|
222 E593 open_entry:
|
|
223 ;request open
|
|
224 E593 A0 01 ldy #1
|
|
225 E595 20 BF E6 jsr CIOInvoke
|
|
226
|
|
227 ;move handler ID and device number to IOCB
|
|
228 E598 A6 2E ldx icidno
|
|
229 E59A A5 20 9D 40 03 mva ichidz ichid,x
|
|
230 E59F A5 21 9D 41 03 mva icdnoz icdno,x
|
|
231
|
|
232 E5A4 98 tya
|
|
233 E5A5 10 01 bpl openOK
|
|
234 E5A7 60 rts
|
|
235
|
|
236 E5A8 openOK:
|
|
237
|
|
238 ;copy PUT BYTE vector for Atari Basic
|
|
239 E5A8 A6 20 ldx ichidz
|
|
240 E5AA BD 1B 03 85 2C BD + mwa hatabs+1,x icax3z
|
|
241 E5B4 A0 06 ldy #6
|
|
242 E5B6 B1 2C lda (icax3z),y
|
|
243 E5B8 A6 2E ldx icidno
|
|
244 E5BA 9D 46 03 sta icptl,x
|
|
245 E5BD C8 iny
|
|
246 E5BE B1 2C lda (icax3z),y
|
|
247 E5C0 9D 47 03 sta icpth,x
|
|
248 E5C3 A0 01 ldy #1
|
|
249 E5C5 60 rts
|
|
250
|
|
251 = E6C2 cmdGetStatus = CIOInvoke.invoke_vector
|
|
252 E5C6 cmdSpecial:
|
|
253 E5C6 20 C2 E6 jsr CIOInvoke.invoke_vector
|
|
254
|
|
255 ;need to copy AUX1/2 back for R:
|
|
256 E5C9 A6 2E ldx icidno
|
|
257 E5CB A5 2A 9D 4A 03 mva icax1z icax1,x
|
|
258 E5D0 A5 2B 9D 4B 03 mva icax2z icax2,x
|
|
259 E5D5 60 rts
|
|
260
|
|
261 ;--------------------------------------------------------------------------
|
|
262 E5D6 cmdGetRecord:
|
|
263 ;check if buffer is full on entry
|
|
264 E5D6 F0 16 beq cmdGetRecordBufferFull
|
|
265 E5D8 cmdGetRecordLoop:
|
|
266 E5D8 cmdGetRecordGetByte:
|
|
267 ;fetch byte
|
|
268 E5D8 20 C2 E6 jsr CIOInvoke.invoke_vector
|
|
269 E5DB C0 00 cpy #0
|
|
270 E5DD 30 1C bmi cmdGetRecordXit
|
|
271
|
|
272 ;store byte (even if EOL)
|
|
273 E5DF A2 00 ldx #0
|
|
274 E5E1 81 24 sta (icbalz,x)
|
|
275
|
|
276 ;check for EOL
|
|
277 E5E3 49 9B eor #$9b
|
|
278 E5E5 C9 01 cmp #1
|
|
279
|
|
280 ;increment buffer pointer and decrement length
|
|
281 E5E7 20 72 E6 jsr advance_pointers
|
|
282
|
|
283 ;skip buffer full check if we had an EOL
|
|
284 E5EA 90 0F bcc cmdGetRecordXit
|
|
285
|
|
286 ;loop back for more bytes if buffer not full
|
|
287 E5EC D0 EA bne cmdGetRecordLoop
|
|
288
|
|
289 E5EE cmdGetRecordBufferFull:
|
|
290 ;read byte to discard
|
|
291 E5EE 20 C2 E6 jsr CIOInvoke.invoke_vector
|
|
292 E5F1 C0 00 cpy #0
|
|
293 E5F3 30 06 bmi cmdGetRecordXit
|
|
294
|
|
295 ;continue if not EOL
|
|
296 E5F5 C9 9B cmp #$9b
|
|
297 E5F7 D0 F5 bne cmdGetRecordBufferFull
|
|
298
|
|
299 ;return truncated record
|
|
300 E5F9 A0 89 ldy #CIOStatTruncRecord
|
|
301
|
|
302 E5FB cmdGetRecordXit:
|
|
303 E5FB cmdGetPutDone:
|
|
304 ;update byte count in IOCB
|
|
305 E5FB A6 2E ldx icidno
|
|
306 E5FD 38 sec
|
|
307 E5FE BD 48 03 lda icbll,x
|
|
308 E601 E5 28 sbc icbllz
|
|
309 E603 85 28 sta icbllz ;required by Lightspeed DOS
|
|
310 E605 9D 48 03 sta icbll,x
|
|
311 E608 BD 49 03 lda icblh,x
|
|
312 E60B E5 29 sbc icblhz
|
|
313 E60D 85 29 sta icblhz
|
|
314 E60F 9D 49 03 sta icblh,x
|
|
315
|
|
316 ;NOMAM 2013 BASIC Ten-Liners disk requires ICBALZ to be untouched :P
|
|
317 E612 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 E61C 60 rts
|
|
322
|
|
323 ;--------------------------------------------------------------------------
|
|
324 E61D cmdGetChars:
|
|
325 E61D F0 15 beq cmdGetCharsSingle
|
|
326 E61F cmdGetCharsLoop:
|
|
327 E61F 20 C2 E6 jsr CIOInvoke.invoke_vector
|
|
328 E622 C0 00 cpy #0
|
|
329 E624 30 0B bmi cmdGetCharsError
|
|
330 E626 A2 00 ldx #0
|
|
331 E628 85 2F sta ciochr ;required by HOTEL title screen
|
|
332 E62A 81 24 sta (icbalz,x)
|
|
333 E62C 20 72 E6 jsr advance_pointers
|
|
334 E62F D0 EE bne cmdGetCharsLoop
|
|
335 E631 cmdGetCharsError:
|
|
336 E631 4C FB E5 jmp cmdGetPutDone
|
|
337
|
|
338 E634 cmdGetCharsSingle:
|
|
339 E634 20 C2 E6 jsr CIOInvoke.invoke_vector
|
|
340 E637 85 2F sta ciochr
|
|
341 E639 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 E63A cmdPutRecord:
|
|
358 E63A F0 33 beq cmdPutCharsSingle
|
|
359 E63C cmdPutRecordLoop:
|
|
360 E63C A0 00 ldy #0
|
|
361 E63E B1 24 lda (icbalz),y
|
|
362 E640 20 C2 E6 jsr CIOInvoke.invoke_vector
|
|
363 E643 98 tya
|
|
364 E644 30 12 bmi cmdPutRecordError
|
|
365 E646 20 72 E6 jsr advance_pointers
|
|
366 E649 F0 08 beq cmdPutRecordEOL
|
|
367 E64B A9 9B lda #$9b
|
|
368 E64D C5 2F cmp ciochr
|
|
369 E64F F0 07 beq cmdPutRecordDone
|
|
370 E651 D0 E7 bne cmdPutRecord
|
|
371
|
|
372 E653 cmdPutRecordEOL:
|
|
373 E653 A9 9B lda #$9b
|
|
374 E655 20 C2 E6 jsr CIOInvoke.invoke_vector
|
|
375 E658 cmdPutRecordError:
|
|
376 E658 cmdPutRecordDone:
|
|
377 E658 4C FB E5 jmp cmdGetPutDone
|
|
378
|
|
379 ;--------------------------------------------------------------------------
|
|
380 E65B cmdPutChars:
|
|
381 E65B F0 12 beq cmdPutCharsSingle
|
|
382 E65D cmdPutCharsLoop:
|
|
383 E65D A0 00 ldy #0
|
|
384 E65F B1 24 lda (icbalz),y
|
|
385 E661 20 C2 E6 jsr CIOInvoke.invoke_vector
|
|
386 E664 98 tya
|
|
387 E665 30 F1 bmi cmdPutRecordError
|
|
388 E667 20 72 E6 jsr advance_pointers
|
|
389 E66A D0 F1 bne cmdPutCharsLoop
|
|
390 E66C 4C FB E5 jmp cmdGetPutDone
|
|
391 E66F cmdPutCharsSingle:
|
|
392 E66F 4C C4 E6 jmp CIOInvoke.invoke_vector_ciochr
|
|
393
|
|
394 ;--------------------------------------------------------------------------
|
|
395
|
|
396 E672 advance_pointers:
|
|
397 E672 E6 24 D0 02 E6 25 inw icbalz
|
|
398 E678 A5 28 D0 02 C6 29 + dew icbllz
|
|
399 E680 D0 02 A5 29 sne:lda icblhz
|
|
400 E684 60 rts
|
|
401
|
|
402 ;--------------------------------------------------------------------------
|
|
403 E685 cmdClose:
|
|
404 E685 20 C2 E6 jsr CIOInvoke.invoke_vector
|
|
405 E688 cmdCloseProvisional:
|
|
406 E688 A6 2E ldx icidno
|
|
407 E68A 20 01 E7 jsr CIOSetPutByteClosed
|
|
408 E68D A9 FF 9D 40 03 mva #$ff ichid,x
|
|
409 E692 60 rts
|
|
410
|
|
411 E693 perm_check_table:
|
|
412 E693 04 dta $04 ;$04 (get record)
|
|
413 E694 04 dta $04 ;$05 (get record)
|
|
414 E695 04 dta $04 ;$06 (get chars)
|
|
415 E696 04 dta $04 ;$07 (get chars)
|
|
416 E697 08 dta $08 ;$08 (put record)
|
|
417 E698 08 dta $08 ;$09 (put record)
|
|
418 E699 08 dta $08 ;$0A (put chars)
|
|
419 E69A 08 dta $08 ;$0B (put chars)
|
|
420 E69B FF dta $ff ;$0C (close)
|
|
421 E69C FF dta $ff ;$0D (get status)
|
|
422 E69D FF dta $ff ;$0E (special)
|
|
423
|
|
424 E69E vector_preload_table:
|
|
425 E69E 05 dta $05 ;$04 (get record)
|
|
426 E69F 05 dta $05 ;$05 (get record)
|
|
427 E6A0 05 dta $05 ;$06 (get chars)
|
|
428 E6A1 05 dta $05 ;$07 (get chars)
|
|
429 E6A2 07 dta $07 ;$08 (put record)
|
|
430 E6A3 07 dta $07 ;$09 (put record)
|
|
431 E6A4 07 dta $07 ;$0A (put chars)
|
|
432 E6A5 07 dta $07 ;$0B (put chars)
|
|
433 E6A6 03 dta $03 ;$0C (close)
|
|
434 E6A7 09 dta $09 ;$0D (get status)
|
|
435 E6A8 0B dta $0b ;$0E (special)
|
|
436
|
|
437 E6A9 command_table_lo:
|
|
438 E6A9 D5 dta <(cmdGetRecord-1) ;$04
|
|
439 E6AA D5 dta <(cmdGetRecord-1) ;$05
|
|
440 E6AB 1C dta <(cmdGetChars-1) ;$06
|
|
441 E6AC 1C dta <(cmdGetChars-1) ;$07
|
|
442 E6AD 39 dta <(cmdPutRecord-1) ;$08
|
|
443 E6AE 39 dta <(cmdPutRecord-1) ;$09
|
|
444 E6AF 5A dta <(cmdPutChars-1) ;$0A
|
|
445 E6B0 5A dta <(cmdPutChars-1) ;$0B
|
|
446 E6B1 84 dta <(cmdClose-1) ;$0C
|
|
447 E6B2 C1 dta <(cmdGetStatus-1) ;$0D
|
|
448 E6B3 C5 dta <(cmdSpecial-1) ;$0E
|
|
449
|
|
450 E6B4 command_table_hi:
|
|
451 E6B4 E5 dta >(cmdGetRecord-1) ;$04
|
|
452 E6B5 E5 dta >(cmdGetRecord-1) ;$05
|
|
453 E6B6 E6 dta >(cmdGetChars-1) ;$06
|
|
454 E6B7 E6 dta >(cmdGetChars-1) ;$07
|
|
455 E6B8 E6 dta >(cmdPutRecord-1) ;$08
|
|
456 E6B9 E6 dta >(cmdPutRecord-1) ;$09
|
|
457 E6BA E6 dta >(cmdPutChars-1) ;$0A
|
|
458 E6BB E6 dta >(cmdPutChars-1) ;$0B
|
|
459 E6BC E6 dta >(cmdClose-1) ;$0C
|
|
460 E6BD E6 dta >(cmdGetStatus-1) ;$0D
|
|
461 E6BE 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 E6BF .proc CIOInvoke
|
|
480 E6BF 20 60 E5 jsr CIO.load_vector
|
|
481 E6C2 invoke_vector:
|
|
482 E6C2 85 2F sta ciochr
|
|
483 E6C4 invoke_vector_ciochr:
|
|
484 E6C4 A5 2D lda icax3z+1
|
|
485 E6C6 48 pha
|
|
486 E6C7 A5 2C lda icax3z
|
|
487 E6C9 48 pha
|
|
488 E6CA A0 92 ldy #CIOStatNotSupported
|
|
489 E6CC A6 2E ldx icidno
|
|
490 E6CE A5 2F lda ciochr
|
|
491 E6D0 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 E6D1 .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 E6D1 A0 00 ldy #0
|
|
510 E6D3 copyToZIOCB:
|
|
511 E6D3 BD 40 03 lda ichid,x
|
|
512 E6D6 99 20 00 sta ziocb,y
|
|
513 E6D9 E8 inx
|
|
514 E6DA C8 iny
|
|
515 E6DB C0 0C cpy #12
|
|
516 E6DD D0 F4 bne copyToZIOCB
|
|
517 E6DF 60 rts
|
|
518 .endp
|
|
519
|
|
520 ;==========================================================================
|
|
521 E6E0 .proc CIOParsePath
|
|
522 ;default to device #1
|
|
523 E6E0 A2 01 ldx #1
|
|
524
|
|
525 ;pull first character of filename and stash it
|
|
526 E6E2 A1 23 lda (icbalz-1,x)
|
|
527 E6E4 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 E6E6 A0 01 ldy #1
|
|
538 E6E8 B1 24 lda (icbalz),y
|
|
539 E6EA 38 sec
|
|
540 E6EB E9 30 sbc #'0'
|
|
541 E6ED F0 06 beq nodevnum
|
|
542 E6EF C9 0A cmp #10
|
|
543 E6F1 B0 02 bcs nodevnum
|
|
544 E6F3 AA tax
|
|
545
|
|
546 E6F4 C8 iny
|
|
547
|
|
548 E6F5 nodevnum:
|
|
549 E6F5 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 lda iccomz
|
|
554 cmp #CIOCmdOpen
|
|
555 bne skip_poll
|
|
556
|
|
557 ;clear DVSTAT+0/+1 to indicate no poll
|
|
558 lda #0
|
|
559 sta dvstat
|
|
560 sta dvstat+1
|
|
561
|
|
562 ;check if we should do an unconditional poll (HNDLOD nonzero).
|
|
563 lda hndlod
|
|
564 bne unconditional_poll
|
|
565
|
|
566 ;search handler table
|
|
567 jsr CIOFindHandler
|
|
568 beq found
|
|
569
|
|
570 unconditional_poll:
|
|
571 ;do type 4 poll
|
|
572 jsr CIOPollForDevice
|
|
573 bmi unknown_device
|
|
574
|
|
575 ;mark provisionally open
|
|
576 ldx icidno
|
|
577 mva #$7f ichid,x
|
|
578 mva icax4z icax3,x
|
|
579 mva dvstat+2 icax4,x
|
|
580 mwa #CIOPutByteLoadHandler-1 icptl,x
|
|
581 mva icdnoz icdno,x
|
|
582
|
|
583 ;do direct exit, bypassing regular open path
|
|
584 pla
|
|
585 pla
|
|
586 ldy #1
|
|
587 rts
|
|
588
|
|
589 skip_poll:
|
|
590 .endif
|
|
591
|
|
592 ;search handler table
|
|
593 E6F7 20 0C E7 jsr CIOFindHandler
|
|
594 E6FA F0 04 beq found
|
|
595
|
|
596 E6FC unknown_device:
|
|
597 ;return unknown device error
|
|
598 E6FC A0 82 ldy #CIOStatUnkDevice
|
|
599 E6FE 68 pla
|
|
600 E6FF 68 pla
|
|
601 E700 found:
|
|
602 E700 60 rts
|
|
603 .endp
|
|
604
|
|
605 ;==========================================================================
|
|
606 E701 .proc CIOSetPutByteClosed
|
|
607 E701 A9 33 lda #<[CIO.not_open_handler-1]
|
|
608 E703 9D 46 03 sta icptl,x
|
|
609 E706 A9 E5 lda #>[CIO.not_open_handler-1]
|
|
610 E708 9D 47 03 sta icpth,x
|
|
611 E70B 60 rts
|
|
612 .endp
|
|
613
|
|
614 ;==========================================================================
|
|
615 ; Attempt to find a handler entry in HATABS.
|
|
616 ;
|
|
617 E70C .proc CIOFindHandler
|
|
618 ;search for handler
|
|
619 E70C A5 2D lda icax4z
|
|
620 E70E A2 21 ldx #11*3
|
|
621 E710 findHandler:
|
|
622 E710 DD 1A 03 cmp hatabs,x
|
|
623 E713 F0 05 beq foundHandler
|
|
624 E715 CA dex
|
|
625 E716 CA dex
|
|
626 E717 CA dex
|
|
627 E718 10 F6 bpl findHandler
|
|
628 E71A foundHandler:
|
|
629 ;store handler ID
|
|
630 E71A 86 20 stx ichidz
|
|
631 E71C 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 .proc CIOPollForDevice
|
|
641 lda icax4z
|
|
642 sta daux1
|
|
643 lda icdnoz
|
|
644 sta daux2
|
|
645
|
|
646 ldx #9
|
|
647 mva:rpl cmd_tab,x ddevic,x-
|
|
648
|
|
649 jmp siov
|
|
650
|
|
651 cmd_tab:
|
|
652 dta $4f ;device
|
|
653 dta $01 ;unit
|
|
654 dta $40 ;command
|
|
655 dta $40 ;status (transfer flags)
|
|
656 dta <dvstat ;dbuflo
|
|
657 dta >dvstat ;dbufhi
|
|
658 dta $40 ;dtimlo
|
|
659 dta $00 ;unused
|
|
660 dta $04 ;dbytlo
|
|
661 dta $00 ;dbythi
|
|
662 .endp
|
|
663 .endif
|
|
664
|
|
665 ;==========================================================================
|
|
666 ; Load handler for a provisionally open IOCB.
|
|
667 ;
|
|
668 .if _KERNEL_XLXE
|
|
669 .proc CIOLoadHandler
|
|
670 ;load handler over SIO bus
|
|
671 mwa dvstat+2 loadad
|
|
672 ldx icidno
|
|
673 mva icax4,x ddevic
|
|
674 jsr PHLoadHandler
|
|
675 bcs fail
|
|
676
|
|
677 ;let's see if we can look up the handler now
|
|
678 ldx icidno
|
|
679 mva icax3,x icax4z
|
|
680 jsr CIOFindHandler
|
|
681 bne fail
|
|
682
|
|
683 ;follow through with open
|
|
684 jsr CIO.open_entry
|
|
685 bpl ok
|
|
686 fail:
|
|
687 ldy #CIOStatUnkDevice
|
|
688 ok:
|
|
689 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 .proc CIOPutByteLoadHandler
|
|
704 ;save off A/X
|
|
705 sta ciochr
|
|
706 stx icidno
|
|
707
|
|
708 ;check if we're allowed to load a handler and bail if not
|
|
709 lda hndlod
|
|
710 beq load_error
|
|
711
|
|
712 ;copy IOCB to ZIOCB
|
|
713 jsr CIOLoadZIOCB
|
|
714
|
|
715 ;try to load the handler
|
|
716 jsr CIOLoadHandler
|
|
717 bmi load_error
|
|
718
|
|
719 ;all good... let's invoke the standard handler
|
|
720 ldy #7
|
|
721 jsr CIOInvoke
|
|
722 jmp xit
|
|
723
|
|
724 load_error:
|
|
725 ldy #CIOStatUnkDevice
|
|
726 xit:
|
|
727 php
|
|
728 lda ciochr
|
|
729 ldx icidno
|
|
730 plp
|
|
731 rts
|
|
732 .endp
|
|
733 .endif
|
|
236 .endif
|
|
237
|
|
238 E71D _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 $E71D -> $0233($022F) Central Input/Output (CIO)
|
|
3 = E71D .def ?@_kernel_lastpt = *
|
|
Source: source/main.xasm
|
|
239
|
|
240 .if !_KERNEL_XLXE
|
|
241 E71D 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 = E761 VBIExit = VBIProcess.xit
|
|
16
|
|
17 ;==========================================================================
|
|
18 ; VBIProcess - Vertical Blank Processor
|
|
19 ;
|
|
20 = E71D VBIStage1 = VBIProcess.stage_1
|
|
21 = E772 VBIStage2 = VBIProcess.stage_2
|
|
22 E71D .proc VBIProcess
|
|
23 E71D stage_1:
|
|
24 ;increment real-time clock and do attract processing
|
|
25 E71D E6 14 inc rtclok+2
|
|
26 E71F D0 08 bne clock_done
|
|
27 E721 E6 4D inc atract
|
|
28 E723 E6 13 inc rtclok+1
|
|
29 E725 D0 02 bne clock_done
|
|
30 E727 E6 12 inc rtclok
|
|
31 E729 clock_done:
|
|
32
|
|
33 ;Pole Position depends on DRKMSK and COLRSH being reset from VBI as it
|
|
34 ;clears kernel vars after startup.
|
|
35 E729 A2 FE ldx #$fe ;default to no mask
|
|
36 E72B A9 00 lda #$00 ;default to no color alteration
|
|
37 E72D A4 4D ldy atract ;check attract counter
|
|
38 E72F 10 06 bpl attract_off ;skip if attract is off
|
|
39 E731 86 4D stx atract ;lock the attract counter
|
|
40 E733 A2 F6 ldx #$f6 ;set mask to dim colors
|
|
41 E735 A5 13 lda rtclok+1 ;use clock to randomize colors
|
|
42 E737 attract_off:
|
|
43 E737 86 4E stx drkmsk ;set color mask
|
|
44 E739 85 4F sta colrsh ;set color modifier
|
|
45
|
|
46 ;atract color 1 only
|
|
47 E73B 4D C5 02 eor color1
|
|
48 E73E 25 4E and drkmsk
|
|
49 E740 8D 17 D0 sta colpf1
|
|
50
|
|
51 ;decrement timer 1 and check for underflow
|
|
52 E743 AD 18 02 lda cdtmv1 ;check low byte
|
|
53 E746 D0 08 bne timer1_lobytezero ;if non-zero, decrement and check for fire
|
|
54 E748 AD 19 02 lda cdtmv1+1 ;check high byte
|
|
55 E74B F0 10 beq timer1_done ;if clear, timer's not running
|
|
56 E74D CE 19 02 dec cdtmv1+1 ;decrement high byte
|
|
57 E750 timer1_lobytezero:
|
|
58 E750 CE 18 02 dec cdtmv1 ;decrement low byte
|
|
59 E753 D0 08 bne timer1_done ;no underflow if non-zero
|
|
60 E755 AD 19 02 lda cdtmv1+1 ;low byte is zero... check if high byte is too
|
|
61 E758 D0 03 bne timer1_done ;if it's not, we're not done yet ($xx00 > 0)
|
|
62 E75A 20 67 E7 jsr timer1_dispatch ;jump through timer vector
|
|
63 E75D timer1_done:
|
|
64
|
|
65 ;check for critical operation
|
|
66 E75D A5 42 lda critic
|
|
67 E75F F0 09 beq no_critic
|
|
68 E761 xit:
|
|
69 E761 68 pla
|
|
70 E762 A8 tay
|
|
71 E763 68 pla
|
|
72 E764 AA tax
|
|
73 E765 exit_a:
|
|
74 E765 68 pla
|
|
75 E766 exit_none:
|
|
76 E766 40 rti
|
|
77
|
|
78 E767 timer1_dispatch:
|
|
79 E767 6C 26 02 jmp (cdtma1)
|
|
80
|
|
81 E76A no_critic:
|
|
82 E76A A9 04 lda #$04 ;I flag
|
|
83 E76C BA tsx
|
|
84 E76D 3D 04 01 and $0104,x ;I flag set on pushed stack?
|
|
85 E770 D0 EF bne xit ;exit if so
|
|
86
|
|
87 ;======== stage 2 processing
|
|
88
|
|
89 E772 stage_2:
|
|
90 ;re-enable interrupts
|
|
91 E772 58 cli
|
|
92
|
|
93 ;update shadow registers
|
|
94 E773 AD 31 02 8D 03 D4 mva sdlsth dlisth
|
|
95 E779 AD 30 02 8D 02 D4 mva sdlstl dlistl
|
|
96 E77F AD 2F 02 8D 00 D4 mva sdmctl dmactl
|
|
97 E785 AD F4 02 8D 09 D4 mva chbas chbase
|
|
98 E78B AD F3 02 8D 01 D4 mva chact chactl
|
|
99 E791 AD 6F 02 8D 1B D0 mva gprior prior
|
|
100
|
|
101 E797 A2 08 ldx #8
|
|
102 E799 8E 1F D0 stx consol ;sneak in speaker reset while we have an 8
|
|
103 E79C ColorLoop
|
|
104 E79C BD C0 02 lda pcolr0,x
|
|
105 E79F 45 4F eor colrsh
|
|
106 E7A1 25 4E and drkmsk
|
|
107 E7A3 9D 12 D0 sta colpm0,x
|
|
108 E7A6 CA dex
|
|
109 E7A7 10 F3 bpl ColorLoop
|
|
110
|
|
111 ;decrement timer 2 and check for underflow
|
|
112 E7A9 A2 03 ldx #3
|
|
113 E7AB 20 51 E8 jsr VBIDecrementTimer
|
|
114 E7AE D0 03 20 2F E8 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 E7B3 A2 09 ldx #9
|
|
124 E7B5 timer_n_loop:
|
|
125 E7B5 18 clc
|
|
126 E7B6 20 51 E8 jsr VBIDecrementTimer
|
|
127 E7B9 B0 07 bcs timer_n_not_running
|
|
128 E7BB F0 02 A9 FF seq:lda #$ff
|
|
129 E7BF timer_n_not_expired:
|
|
130 E7BF 9D 25 02 sta cdtmf3-5,x
|
|
131 E7C2 timer_n_not_running:
|
|
132 E7C2 CA dex
|
|
133 E7C3 CA dex
|
|
134 E7C4 E0 05 cpx #5
|
|
135 E7C6 B0 ED bcs timer_n_loop
|
|
136
|
|
137 ;Read POKEY keyboard register and handle auto-repeat
|
|
138 E7C8 AD 0F D2 lda skstat ;get key status
|
|
139 E7CB 29 04 and #$04 ;check if key is down
|
|
140 E7CD D0 12 bne no_repeat_key ;skip if not
|
|
141 E7CF CE 2B 02 dec srtimr ;decrement repeat timer
|
|
142 E7D2 D0 12 bne no_repeat ;skip if not time to repeat yet
|
|
143 E7D4 AD 09 D2 8D FC 02 mva kbcode ch ;repeat last key
|
|
144
|
|
145 .if _KERNEL_XLXE
|
|
146 mva keyrep srtimr ;reset repeat timer
|
|
147 .else
|
|
148 E7DA A9 06 8D 2B 02 mva #$06 srtimr ;reset repeat timer
|
|
149 .endif
|
|
150
|
|
151 E7DF D0 0D bne no_keydel ;skip debounce counter decrement
|
|
152
|
|
153 E7E1 no_repeat_key:
|
|
154 E7E1 A9 00 lda #0
|
|
155 E7E3 8D 2B 02 sta srtimr
|
|
156 E7E6 no_repeat:
|
|
157 ;decrement keyboard debounce counter
|
|
158 E7E6 AD F1 02 lda keydel
|
|
159 E7E9 F0 03 CE F1 02 seq:dec keydel
|
|
160 E7EE 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 lda porta
|
|
179 tax
|
|
180 and #$0f
|
|
181 sta stick0
|
|
182 sta stick2
|
|
183 txa
|
|
184 lsr ;shr1
|
|
185 lsr ;shr2
|
|
186 tax
|
|
187 lsr ;shr3
|
|
188 lsr ;shr4
|
|
189 sta stick1
|
|
190 sta stick3
|
|
191 lsr ;shr5
|
|
192 lsr ;shr6
|
|
193 tay
|
|
194 and #$01
|
|
195 sta ptrig2
|
|
196 tya
|
|
197 lsr
|
|
198 sta ptrig3
|
|
199 txa
|
|
200 and #$01
|
|
201 sta ptrig0
|
|
202 txa
|
|
203 lsr
|
|
204 and #$01
|
|
205 sta ptrig1
|
|
206
|
|
207 ldx #3
|
|
208 pot_loop:
|
|
209 lda pot0,x
|
|
210 sta paddl0,x
|
|
211 sta paddl4,x
|
|
212 lda ptrig0,x
|
|
213 sta ptrig4,x
|
|
214 dex
|
|
215 bpl pot_loop
|
|
216
|
|
217 ldx #1
|
|
218 port_loop:
|
|
219 lda trig0,x
|
|
220 sta strig0,x
|
|
221 sta strig2,x
|
|
222 dex
|
|
223 bpl port_loop
|
|
224
|
|
225 .else
|
|
226 E7EE A2 07 ldx #7
|
|
227 E7F0 pot_loop:
|
|
228 E7F0 BD 00 D2 lda pot0,x
|
|
229 E7F3 9D 70 02 sta paddl0,x
|
|
230 E7F6 A9 00 lda #0
|
|
231 E7F8 9D 7C 02 sta ptrig0,x
|
|
232 E7FB CA dex
|
|
233 E7FC 10 F2 bpl pot_loop
|
|
234
|
|
235 E7FE A2 03 ldx #3
|
|
236 E800 trig_loop:
|
|
237 E800 BD 10 D0 lda trig0,x
|
|
238 E803 9D 84 02 sta strig0,x
|
|
239 E806 CA dex
|
|
240 E807 10 F7 bpl trig_loop
|
|
241
|
|
242 E809 AD 00 D3 lda porta
|
|
243 E80C A2 00 ldx #0
|
|
244 E80E A0 00 ldy #0
|
|
245 E810 20 32 E8 jsr do_stick_ptrigs
|
|
246 E813 AD 01 D3 lda portb
|
|
247 E816 A2 04 ldx #4
|
|
248 E818 A0 02 ldy #2
|
|
249 E81A 20 32 E8 jsr do_stick_ptrigs
|
|
250 .endif
|
|
251
|
|
252 ;restart pots (required for SysInfo)
|
|
253 E81D 8D 0B D2 sta potgo
|
|
254
|
|
255 ;update light pen
|
|
256 E820 AD 0C D4 8D 34 02 mva penh lpenh
|
|
257 E826 AD 0D D4 8D 35 02 mva penv lpenv
|
|
258
|
|
259 E82C 6C 24 02 jmp (vvblkd) ;jump through vblank deferred vector
|
|
260
|
|
261 E82F Timer2Dispatch
|
|
262 E82F 6C 28 02 jmp (cdtma2)
|
|
263
|
|
264 .if !_KERNEL_XLXE
|
|
265 E832 do_stick_ptrigs:
|
|
266 E832 48 pha
|
|
267 E833 29 0F and #$0f
|
|
268 E835 99 78 02 sta stick0,y
|
|
269 E838 68 pla
|
|
270 E839 4A lsr
|
|
271 E83A 4A lsr
|
|
272 E83B 4A lsr
|
|
273 E83C 3E 7C 02 rol ptrig0,x
|
|
274 E83F 4A lsr
|
|
275 E840 3E 7D 02 rol ptrig1,x
|
|
276 E843 99 79 02 sta stick1,y
|
|
277 E846 4A lsr
|
|
278 E847 4A lsr
|
|
279 E848 4A lsr
|
|
280 E849 3E 7E 02 rol ptrig2,x
|
|
281 E84C 4A lsr
|
|
282 E84D 3E 7F 02 rol ptrig3,x
|
|
283 E850 60 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 E851 .proc VBIDecrementTimer
|
|
300 ;check low byte
|
|
301 E851 BD 17 02 lda cdtmv1-1,x
|
|
302 E854 D0 0A bne lononzero
|
|
303
|
|
304 ;check high byte; set C=1/Z=1 if zero, C=0/Z=0 otherwise
|
|
305 E856 DD 18 02 cmp cdtmv1,x
|
|
306 E859 D0 02 bne lozero_hinonzero
|
|
307
|
|
308 ;both bytes are zero, so timer's not running
|
|
309 E85B 8A txa
|
|
310 E85C 60 rts
|
|
311
|
|
312 E85D lozero_hinonzero:
|
|
313 ;decrement high byte
|
|
314 E85D DE 18 02 dec cdtmv1,x
|
|
315
|
|
316 E860 lononzero:
|
|
317 ;decrement low byte
|
|
318 E860 DE 17 02 dec cdtmv1-1,x
|
|
319 E863 D0 03 bne still_running
|
|
320
|
|
321 ;return high byte to set Z appropriately
|
|
322 E865 BD 18 02 lda cdtmv1,x
|
|
323 E868 still_running:
|
|
324 E868 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 E869 .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 E869 0A asl
|
|
356 E86A 8D 2D 02 sta intemp
|
|
357 E86D 08 php
|
|
358 E86E 78 sei
|
|
359 E86F 98 tya
|
|
360 E870 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 E873 EE 0A D4 inc wsync
|
|
402 E876 99 16 02 sta cdtmv1-2,y
|
|
403 E879 8A txa
|
|
404 E87A 99 17 02 sta cdtmv1-1,y
|
|
405 E87D 28 plp
|
|
406 E87E 60 rts
|
|
407 .endp
|
|
242 E87F 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 E87F .proc IntInitInterrupts
|
|
14 E87F 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 mva trig3 gintlk
|
|
20 .endif
|
|
21
|
|
22 E884 60 rts
|
|
23 .endp
|
|
24
|
|
25 ;==========================================================================
|
|
26 E885 .proc IntDispatchNMI
|
|
27 E885 2C 0F D4 bit nmist ;check nmi status
|
|
28 E888 10 06 bpl not_dli ;skip if not a DLI
|
|
29 E88A 6C 00 02 jmp (vdslst) ;jump to display list vector
|
|
30
|
|
31 .if !_KERNEL_XLXE
|
|
32 E88D is_system_reset:
|
|
33 E88D 4C 74 E4 jmp warmsv
|
|
34 .endif
|
|
35
|
|
36 E890 not_dli:
|
|
37 E890 48 pha
|
|
38
|
|
39 .if _KERNEL_XLXE
|
|
40 ;Only XL/XE OSes cleared the decimal bit.
|
|
41 cld
|
|
42 .else
|
|
43 ;The stock OS treats 'not RNMI' as VBI. We'd best follow its example.
|
|
44 E891 A9 20 lda #$20
|
|
45 E893 2C 0F D4 bit nmist
|
|
46 E896 D0 F5 bne is_system_reset
|
|
47 .endif
|
|
48
|
|
49 E898 8A txa
|
|
50 E899 48 pha
|
|
51 E89A 98 tya
|
|
52 E89B 48 pha
|
|
53 E89C 8D 0F D4 sta nmires ;reset VBI interrupt
|
|
54 E89F 6C 22 02 jmp (vvblki) ;jump through vblank immediate vector
|
|
55 .endp
|
|
56
|
|
57 E8A2 .proc IntDispatchIRQ
|
|
58 .if _KERNEL_XLXE
|
|
59 cld
|
|
60 .endif
|
|
61 E8A2 6C 16 02 jmp (vimirq)
|
|
62 .endp
|
|
63
|
|
64 ;==============================================================================
|
|
65 = E765 IntExitHandler_A = VBIProcess.exit_a
|
|
66 = E766 IntExitHandler_None = VBIProcess.exit_none
|
|
243 E8A5 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 = E8CD IRQHandler = _IRQHandler._entry
|
|
50 E8A5 .proc _IRQHandler
|
|
51 .if _KERNEL_PBI_SUPPORT
|
|
52 check_pbi:
|
|
53 ;check if a device interrupt is active
|
|
54 and $d1ff
|
|
55 beq no_pbi_interrupt
|
|
56
|
|
57 ;save X
|
|
58 sta jveck
|
|
59 txa
|
|
60 pha
|
|
61
|
|
62 ;jump through PBI interrupt vector
|
|
63 lda jveck
|
|
64 jmp (vpirq)
|
|
65 .endif
|
|
66
|
|
67 E8A5 dispatch_serout:
|
|
68 E8A5 A9 EF lda #$ef
|
|
69 E8A7 _ACK_IRQ
|
|
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
|
|
1 E8A7 20 3C E9 jsr IrqAcknowledge
|
|
Source: source/Shared/irq.s
|
|
70 E8AA 6C 0C 02 jmp (vseror)
|
|
71
|
|
72 E8AD check_seroc:
|
|
73 E8AD 2C 0E D2 bit irqst
|
|
74 E8B0 D0 3C bne not_seroc
|
|
75 E8B2 dispatch_seroc:
|
|
76 E8B2 6C 0E 02 jmp (vseroc)
|
|
77
|
|
78 E8B5 dispatch_timer1:
|
|
79 E8B5 A9 FE lda #$fe
|
|
80 E8B7 _ACK_IRQ
|
|
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
|
|
1 E8B7 20 3C E9 jsr IrqAcknowledge
|
|
Source: source/Shared/irq.s
|
|
81 E8BA 6C 10 02 jmp (vtimr1)
|
|
82
|
|
83 E8BD dispatch_timer2:
|
|
84 E8BD A9 FD lda #$fd
|
|
85 E8BF _ACK_IRQ
|
|
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
|
|
1 E8BF 20 3C E9 jsr IrqAcknowledge
|
|
Source: source/Shared/irq.s
|
|
86 E8C2 6C 12 02 jmp (vtimr2)
|
|
87
|
|
88 E8C5 dispatch_timer4:
|
|
89 E8C5 A9 FB lda #$fb
|
|
90 E8C7 _ACK_IRQ
|
|
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
|
|
1 E8C7 20 3C E9 jsr IrqAcknowledge
|
|
Source: source/Shared/irq.s
|
|
91 E8CA 6C 14 02 jmp (vtimr4)
|
|
92
|
|
93 E8CD _entry:
|
|
94 E8CD 48 pha
|
|
95
|
|
96 ;check for serial input ready IRQ
|
|
97 E8CE A9 20 lda #$20
|
|
98 E8D0 2C 0E D2 bit irqst
|
|
99 E8D3 D0 0D bne not_serin
|
|
100 E8D5 A9 DF lda #$df
|
|
101 E8D7 8D 0E D2 sta irqen
|
|
102 E8DA A5 10 lda pokmsk
|
|
103 E8DC 8D 0E D2 sta irqen
|
|
104 E8DF 6C 0A 02 jmp (vserin)
|
|
105 E8E2 not_serin:
|
|
106
|
|
107 .if _KERNEL_PBI_SUPPORT
|
|
108 ;check for PBI devices requiring interrupt handling
|
|
109 lda pdmsk
|
|
110 bne check_pbi
|
|
111 no_pbi_interrupt:
|
|
112 .endif
|
|
113
|
|
114 ;check for serial output ready IRQ
|
|
115 E8E2 A9 10 lda #$10
|
|
116 E8E4 2C 0E D2 bit irqst
|
|
117 E8E7 F0 BC beq dispatch_serout
|
|
118
|
|
119 ;check for serial output complete (not a latch, so must mask)
|
|
120 E8E9 4A lsr
|
|
121 E8EA 24 10 bit pokmsk
|
|
122 E8EC D0 BF bne check_seroc
|
|
123 E8EE not_seroc:
|
|
124
|
|
125 E8EE AD 0E D2 lda irqst
|
|
126 E8F1 4A lsr
|
|
127 E8F2 90 C1 bcc dispatch_timer1
|
|
128 E8F4 4A lsr
|
|
129 E8F5 90 C6 bcc dispatch_timer2
|
|
130 E8F7 4A lsr
|
|
131 E8F8 90 CB bcc dispatch_timer4
|
|
132 E8FA 2C 0E D2 bit irqst
|
|
133 E8FD 50 21 bvc dispatch_keyboard
|
|
134 E8FF 10 27 bpl dispatch_break
|
|
135
|
|
136 ;check for serial bus proceed line
|
|
137 E901 2C 02 D3 bit pactl
|
|
138 E904 30 2A bmi dispatch_pia_irqa
|
|
139
|
|
140 ;check for serial bus interrupt line
|
|
141 E906 2C 03 D3 bit pbctl
|
|
142 E909 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 E90B 68 pla
|
|
149 E90C 8D 8C 02 sta jveck
|
|
150 E90F 68 pla
|
|
151 E910 48 pha
|
|
152 E911 29 10 and #$10
|
|
153 E913 F0 07 beq not_brk
|
|
154 E915 AD 8C 02 lda jveck
|
|
155 E918 48 pha
|
|
156 E919 6C 06 02 jmp (vbreak)
|
|
157 E91C not_brk:
|
|
158 E91C AD 8C 02 lda jveck
|
|
159 E91F 40 rti
|
|
160
|
|
161
|
|
162 E920 dispatch_keyboard:
|
|
163 E920 A9 BF lda #$bf
|
|
164 E922 _ACK_IRQ
|
|
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
|
|
1 E922 20 3C E9 jsr IrqAcknowledge
|
|
Source: source/Shared/irq.s
|
|
165 E925 6C 08 02 jmp (vkeybd)
|
|
166
|
|
167 E928 dispatch_break:
|
|
168 E928 A9 7F lda #$7f
|
|
169 E92A _ACK_IRQ
|
|
Macro: _ACK_IRQ [Source: source/Shared/irq.s]
|
|
1 E92A 20 3C E9 jsr IrqAcknowledge
|
|
Source: source/Shared/irq.s
|
|
170 E92D 6C 36 02 jmp (brkky)
|
|
171
|
|
172 E930 dispatch_pia_irqa:
|
|
173 ;clear serial bus proceed interrupt
|
|
174 E930 AD 00 D3 lda porta
|
|
175 E933 6C 02 02 jmp (vprced)
|
|
176
|
|
177 E936 dispatch_pia_irqb:
|
|
178 ;clear serial bus interrupt interrupt
|
|
179 E936 AD 01 D3 lda portb
|
|
180 E939 6C 04 02 jmp (vinter)
|
|
181
|
|
182 .endp
|
|
183
|
|
184 ;==========================================================================
|
|
185 .if !_KERNEL_FAST_IRQ
|
|
186 E93C .proc IrqAcknowledge
|
|
187 E93C 8D 0E D2 sta irqen
|
|
188 E93F A5 10 lda pokmsk
|
|
189 E941 8D 0E D2 sta irqen
|
|
190 E944 60 rts
|
|
191 .endp
|
|
192 .endif
|
|
244 .endif
|
|
245 E945 _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 $E945 -> $0228($026F) Interrupt routines
|
|
3 = E945 .def ?@_kernel_lastpt = *
|
|
Source: source/main.xasm
|
|
246
|
|
247 E945 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 E945 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 E945 .proc SIOInit
|
|
11 ;turn off POKEY init mode so polynomial counters and audio run
|
|
12 E945 A9 03 8D 0F D2 mva #3 skctl
|
|
13 E94A 8D 32 02 sta sskctl
|
|
14
|
|
15 ;enable noisy sound (yes, this is actually documented as being inited to
|
|
16 ;3)
|
|
17 E94D 85 41 sta soundr
|
|
18 E94F 60 rts
|
|
19 .endp
|
|
20
|
|
21 ;==============================================================================
|
|
22 E950 .proc SIO
|
|
23 ;set retry counters
|
|
24 E950 A9 01 8D BD 02 mva #$01 dretry
|
|
25
|
|
26 ;enter critical section
|
|
27 E955 85 42 sta critic
|
|
28
|
|
29 .if _KERNEL_PBI_SUPPORT
|
|
30 ;attempt PBI transfer
|
|
31 jsr PBIAttemptSIO
|
|
32 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 E957 BA tsx
|
|
38 E958 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 E95B 20 65 EA jsr SIOSetTimeoutVector
|
|
44
|
|
45 ;check for cassette -- needs to match $60 or else Prisma: Alien Ambush
|
|
46 ;fails to load.
|
|
47 E95E A2 00 ldx #0
|
|
48 E960 AD 00 03 lda ddevic
|
|
49 E963 C9 60 cmp #$60
|
|
50 E965 D0 01 CA sne:dex
|
|
51 E968 8E 0F 03 stx casflg
|
|
52
|
|
53 ;init POKEY hardware
|
|
54 E96B 20 B8 EA jsr SIOInitHardware
|
|
55
|
|
56 ;go do cassette now
|
|
57 E96E 2C 0F 03 bit casflg
|
|
58 E971 10 03 bpl retry_command
|
|
59 E973 4C 2E EC jmp SIOCassette
|
|
60
|
|
61 E976 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 E976 A9 0D 8D 9C 02 mva #$0d cretry
|
|
65
|
|
66 E97B retry_command_2:
|
|
67 ;init command buffer
|
|
68 E97B AD 00 03 lda ddevic
|
|
69 E97E 18 clc
|
|
70 E97F 6D 01 03 adc dunit
|
|
71 E982 38 sec
|
|
72 E983 E9 01 sbc #1
|
|
73 E985 8D 3A 02 sta cdevic
|
|
74
|
|
75 E988 AD 02 03 8D 3B 02 mva dcomnd ccomnd
|
|
76 E98E AD 0A 03 8D 3C 02 mva daux1 caux1
|
|
77 E994 AD 0B 03 8D 3D 02 mva daux2 caux2
|
|
78
|
|
79 ;assert command line
|
|
80 E99A A9 34 8D 03 D3 mva #$34 pbctl
|
|
81
|
|
82 ;wait ~600us to ensure 750us minimum delay (~1k cycles or ~10 scanlines)
|
|
83 E99F A2 05 ldx #5
|
|
84 E9A1 AC 0B D4 ldy vcount
|
|
85 E9A4 cmddelay:
|
|
86 E9A4 CC 0B D4 F0 FB cpy:req vcount
|
|
87 E9A9 C8 iny
|
|
88 E9AA CA dex
|
|
89 E9AB D0 F7 bne cmddelay
|
|
90
|
|
91 ;send command frame
|
|
92 E9AD A9 00 85 3C mva #0 nocksm
|
|
93 E9B1 A9 02 lda #>cdevic
|
|
94 E9B3 85 33 sta bufrhi
|
|
95 E9B5 85 35 sta bfenhi
|
|
96 E9B7 A9 3A 85 32 mva #<cdevic bufrlo
|
|
97 E9BB A9 3E 85 34 mva #<caux2+1 bfenlo
|
|
98 E9BF 20 1D EB jsr SIOSend
|
|
99 E9C2 30 65 bmi xit
|
|
100
|
|
101 ;wait for the ACK
|
|
102 E9C4 20 70 EA jsr SIOWaitForACK
|
|
103 E9C7 10 0A bpl ackOK
|
|
104
|
|
105 E9C9 command_error:
|
|
106 E9C9 20 8A EB jsr SIOReceiveStop
|
|
107 E9CC CE 9C 02 dec cretry
|
|
108 E9CF 10 AA bpl retry_command_2
|
|
109 E9D1 30 4B bmi transfer_error
|
|
110
|
|
111 E9D3 ackOK:
|
|
112
|
|
113 ;check if we should send a data frame
|
|
114 E9D3 2C 03 03 bit dstats
|
|
115 E9D6 10 0D bpl no_send_frame
|
|
116
|
|
117 ;setup buffer pointers
|
|
118 E9D8 20 07 EB jsr SIOSetupBufferPointers
|
|
119
|
|
120 ;send data frame
|
|
121 E9DB 20 1D EB jsr SIOSend
|
|
122 E9DE 30 49 bmi xit
|
|
123
|
|
124 ;wait for ACK
|
|
125 E9E0 20 70 EA jsr SIOWaitForACK
|
|
126 E9E3 30 E4 bmi command_error
|
|
127
|
|
128 E9E5 no_send_frame:
|
|
129
|
|
130 ;setup for receiving complete
|
|
131 E9E5 A2 FF ldx #$ff
|
|
132 E9E7 8E 17 03 stx timflg
|
|
133 E9EA 86 3C stx nocksm
|
|
134
|
|
135 ;setup frame delay for complete
|
|
136 E9EC AD 06 03 lda dtimlo
|
|
137 E9EF 6A ror
|
|
138 E9F0 6A ror
|
|
139 E9F1 48 pha
|
|
140 E9F2 6A ror
|
|
141 E9F3 29 C0 and #$c0
|
|
142 E9F5 A8 tay
|
|
143 E9F6 68 pla
|
|
144 E9F7 29 3F and #$3f
|
|
145 E9F9 AA tax
|
|
146
|
|
147 E9FA A9 01 lda #1
|
|
148 E9FC 20 5C E4 jsr setvbv
|
|
149
|
|
150 E9FF A2 3E ldx #<temp
|
|
151 EA01 86 32 stx bufrlo
|
|
152 EA03 E8 inx
|
|
153 EA04 86 34 stx bfenlo
|
|
154 EA06 A2 02 ldx #>temp
|
|
155 EA08 86 33 stx bufrhi
|
|
156 EA0A 86 35 stx bfenhi
|
|
157 EA0C 20 4C EB jsr SIOReceive
|
|
158 EA0F 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 EA11 AD 3E 02 lda temp
|
|
164 EA14 C9 43 cmp #$43
|
|
165 EA16 F0 32 beq completeOK
|
|
166 EA18 C9 45 cmp #$45
|
|
167 EA1A F0 2E beq completeOK
|
|
168
|
|
169 ;we received crap... fail it now
|
|
170 EA1C device_error:
|
|
171 EA1C A0 90 ldy #SIOErrorDeviceError
|
|
172
|
|
173 EA1E transfer_error:
|
|
174 EA1E 20 8A EB jsr SIOReceiveStop
|
|
175
|
|
176 EA21 CE BD 02 dec dretry
|
|
177 EA24 30 03 bmi device_retries_exhausted
|
|
178 EA26 4C 76 E9 jmp retry_command
|
|
179
|
|
180 EA29 device_retries_exhausted:
|
|
181 EA29 xit:
|
|
182 EA29 AE 0F 03 ldx casflg
|
|
183 EA2C D0 0C bne leave_cassette_audio_on
|
|
184 EA2E 8E 01 D2 stx audc1
|
|
185 EA31 8E 03 D2 stx audc2
|
|
186 EA34 8E 05 D2 stx audc3
|
|
187 EA37 8E 07 D2 stx audc4
|
|
188 EA3A 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 EA3A AE 18 03 ldx stackp
|
|
198 EA3D 9A txs
|
|
199 .endif
|
|
200
|
|
201 EA3E xit_pbi:
|
|
202 EA3E A9 00 lda #0
|
|
203 EA40 85 42 sta critic
|
|
204
|
|
205 EA42 C0 00 cpy #0 ;!! - A=0 must be preserved for LiteDOS
|
|
206 EA44 8C 03 03 sty dstats
|
|
207 EA47 84 30 sty status
|
|
208 EA49 60 rts
|
|
209
|
|
210 EA4A completeOK:
|
|
211 ;check if we should read a data frame
|
|
212 EA4A 2C 03 03 bit dstats
|
|
213 EA4D 50 08 bvc no_receive_frame
|
|
214
|
|
215 ;setup buffer pointers
|
|
216 EA4F 20 07 EB jsr SIOSetupBufferPointers
|
|
217
|
|
218 ;receive the rest of the frame
|
|
219 EA52 20 4C EB jsr SIOReceive
|
|
220 EA55 30 C7 bmi transfer_error
|
|
221
|
|
222 EA57 no_receive_frame:
|
|
223 ;now we can finally shut off the receive IRQ
|
|
224 EA57 20 8A EB jsr SIOReceiveStop
|
|
225
|
|
226 ;Now check whether we got a device error earlier. If we did, return
|
|
227 ;that instead of success.
|
|
228 EA5A AD 3E 02 lda temp
|
|
229 EA5D C9 43 cmp #'C'
|
|
230 EA5F D0 BB bne device_error
|
|
231
|
|
232 ;nope, we're good... exit OK.
|
|
233 EA61 A0 01 ldy #SIOSuccess
|
|
234 EA63 D0 C4 bne xit
|
|
235 .endp
|
|
236
|
|
237 ;==============================================================================
|
|
238 EA65 .proc SIOSetTimeoutVector
|
|
239 EA65 A9 28 8D 26 02 A9 + mwa #SIOCountdown1Handler cdtma1
|
|
240 EA6F 60 rts
|
|
241 .endp
|
|
242
|
|
243 ;==============================================================================
|
|
244 EA70 .proc SIOWaitForACK
|
|
245 ;setup 2 frame delay for ack
|
|
246 EA70 A2 FF ldx #$ff
|
|
247 EA72 8E 17 03 stx timflg
|
|
248 EA75 86 3C stx nocksm
|
|
249 EA77 E8 inx ;X=0
|
|
250 EA78 A9 01 lda #1
|
|
251 EA7A A0 02 ldy #2
|
|
252 EA7C 84 33 sty bufrhi ;>temp = 2
|
|
253 EA7E 84 35 sty bfenhi ;>temp+1 = 2
|
|
254 EA80 20 5C E4 jsr setvbv
|
|
255
|
|
256 ;setup for receiving ACK
|
|
257 EA83 A2 3E ldx #<temp
|
|
258 EA85 86 32 stx bufrlo
|
|
259 EA87 E8 inx
|
|
260 EA88 86 34 stx bfenlo ;#<[temp+1]
|
|
261
|
|
262 EA8A 20 4C EB jsr SIOReceive
|
|
263
|
|
264 ;check if we had a receive error
|
|
265 EA8D 30 09 bmi xit
|
|
266
|
|
267 ;check if we got an ACK
|
|
268 EA8F AD 3E 02 lda temp
|
|
269 EA92 C9 41 cmp #'A'
|
|
270 EA94 F0 02 beq xit
|
|
271
|
|
272 ;doh
|
|
273 EA96 A0 8B ldy #SIOErrorNAK
|
|
274 EA98 xit:
|
|
275 EA98 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 = EAB8 SIOInitHardware = SIOSendEnable.init_hardware
|
|
294 EA99 .proc SIOSendEnable
|
|
295 ;enable serial output ready IRQ and suppress serial output complete IRQ
|
|
296 EA99 A5 10 lda pokmsk
|
|
297 EA9B 09 10 ora #$10
|
|
298 EA9D 29 F7 and #$f7
|
|
299 EA9F 85 10 sta pokmsk
|
|
300 EAA1 8D 0E D2 sta irqen
|
|
301
|
|
302 EAA4 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 EAA4 AD 32 02 lda sskctl
|
|
306 EAA7 29 0F and #$0f
|
|
307 EAA9 09 20 ora #$20
|
|
308 EAAB AE 0F 03 ldx casflg
|
|
309 EAAE F0 02 09 08 seq:ora #$08
|
|
310 EAB2 8D 32 02 sta sskctl
|
|
311 EAB5 8D 0F D2 sta skctl
|
|
312
|
|
313 EAB8 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 EAB8 A2 08 ldx #8
|
|
317
|
|
318 ;check if we are doing a cassette transfer; if so, use the cassette
|
|
319 ;register table instead
|
|
320 EABA AD 0F 03 lda casflg
|
|
321 EABD F0 02 beq not_cassette
|
|
322
|
|
323 EABF A2 11 ldx #17
|
|
324
|
|
325 EAC1 not_cassette:
|
|
326
|
|
327 = EAC1 .def :SIOInitPOKEYWithRegOffsetX
|
|
328 ;load POKEY audio registers
|
|
329 EAC1 A0 08 ldy #8
|
|
330 EAC3 BD EC EA CA 99 00 + mva:rpl regdata_normal,x- audf1,y-
|
|
331
|
|
332 ;go noisy audio if requested
|
|
333 EACD A5 41 lda soundr
|
|
334 EACF F0 17 beq no_noise
|
|
335
|
|
336 EAD1 A9 A8 lda #$a8
|
|
337 EAD3 8D 07 D2 sta audc4
|
|
338 EAD6 AE 0F 03 ldx casflg
|
|
339 EAD9 F0 0D beq no_noise
|
|
340 EADB A9 10 lda #$10
|
|
341 EADD 2C 32 02 bit sskctl
|
|
342 EAE0 D0 06 bne no_noise
|
|
343 EAE2 8D 01 D2 sta audc1
|
|
344 EAE5 8D 03 D2 sta audc2
|
|
345
|
|
346 EAE8 no_noise:
|
|
347
|
|
348 ;reset serial status
|
|
349 EAE8 8D 0A D2 sta skres
|
|
350 EAEB 60 rts
|
|
351
|
|
352 EAEC regdata:
|
|
353 EAEC regdata_normal:
|
|
354 EAEC 00 dta $00 ;audf1
|
|
355 EAED A0 dta $a0 ;audc1
|
|
356 EAEE 00 dta $00 ;audf2
|
|
357 EAEF A0 dta $a0 ;audc2
|
|
358 EAF0 28 dta $28 ;audf3
|
|
359 EAF1 A0 dta $a0 ;audc3
|
|
360 EAF2 00 dta $00 ;audf4
|
|
361 EAF3 A0 dta $a0 ;audc4
|
|
362 EAF4 28 dta $28 ;audctl
|
|
363
|
|
364 EAF5 regdata_cassette_write:
|
|
365 EAF5 05 dta $05 ;audf1
|
|
366 EAF6 A0 dta $a0 ;audc1
|
|
367 EAF7 07 dta $07 ;audf2
|
|
368 EAF8 A0 dta $a0 ;audc2
|
|
369 EAF9 CC dta $cc ;audf3
|
|
370 EAFA A0 dta $a0 ;audc3
|
|
371 EAFB 05 dta $05 ;audf4
|
|
372 EAFC A0 dta $a0 ;audc4
|
|
373 EAFD 28 dta $28 ;audctl
|
|
374
|
|
375 EAFE regdata_cassette_read:
|
|
376 EAFE 00 dta $00 ;audf1
|
|
377 EAFF A0 dta $a0 ;audc1
|
|
378 EB00 00 dta $00 ;audf2
|
|
379 EB01 A0 dta $a0 ;audc2
|
|
380 EB02 CC dta $cc ;audf3
|
|
381 EB03 A0 dta $a0 ;audc3
|
|
382 EB04 05 dta $05 ;audf4
|
|
383 EB05 A0 dta $a0 ;audc4
|
|
384 EB06 28 dta $28 ;audctl
|
|
385 .endp
|
|
386
|
|
387 ;==============================================================================
|
|
388 EB07 .proc SIOSetupBufferPointers
|
|
389 EB07 18 clc
|
|
390 EB08 AD 04 03 lda dbuflo
|
|
391 EB0B 85 32 sta bufrlo
|
|
392 EB0D 6D 08 03 adc dbytlo
|
|
393 EB10 85 34 sta bfenlo
|
|
394 EB12 AD 05 03 lda dbufhi
|
|
395 EB15 85 33 sta bufrhi
|
|
396 EB17 6D 09 03 adc dbythi
|
|
397 EB1A 85 35 sta bfenhi
|
|
398 EB1C 60 rts
|
|
399 .endp
|
|
400
|
|
401 ;==============================================================================
|
|
402 ;SIO send routine
|
|
403 ;
|
|
404 EB1D .proc SIOSend
|
|
405 ;configure serial port for synchronous transmission
|
|
406 ;enable transmission IRQs
|
|
407 EB1D 78 sei
|
|
408 EB1E 20 99 EA jsr SIOSendEnable
|
|
409
|
|
410 EB21 A0 00 ldy #0
|
|
411 EB23 84 3A sty xmtdon
|
|
412 EB25 84 30 sty status
|
|
413 EB27 84 3B sty chksnt
|
|
414
|
|
415 ;send first byte and set checksum (must be atomic)
|
|
416 EB29 B1 32 lda (bufrlo),y
|
|
417 EB2B 8D 0D D2 sta serout
|
|
418 EB2E 85 31 sta chksum
|
|
419
|
|
420 ;unmask IRQs
|
|
421 EB30 58 cli
|
|
422
|
|
423 ;wait for transmit to complete or Break to be pressed
|
|
424 EB31 wait:
|
|
425 EB31 A5 11 lda brkkey
|
|
426 EB33 F0 06 beq break_detected
|
|
427 EB35 A5 3A lda xmtdon
|
|
428 EB37 F0 F8 beq wait
|
|
429 EB39 D0 04 bne send_completed
|
|
430
|
|
431 EB3B break_detected:
|
|
432 EB3B A0 80 ldy #$80
|
|
433 EB3D 84 30 sty status
|
|
434
|
|
435 EB3F send_completed:
|
|
436 ;shut off transmission IRQs
|
|
437 EB3F 78 sei
|
|
438 EB40 A5 10 lda pokmsk
|
|
439 EB42 29 E7 and #$e7
|
|
440 EB44 85 10 sta pokmsk
|
|
441 EB46 8D 0E D2 sta irqen
|
|
442 EB49 58 cli
|
|
443
|
|
444 ;we're done
|
|
445 EB4A 98 tya
|
|
446 EB4B 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 EB4C .proc SIOReceive
|
|
459 EB4C A9 00 lda #0
|
|
460 EB4E use_checksum:
|
|
461 EB4E 85 31 sta chksum
|
|
462 EB50 A2 00 ldx #0
|
|
463 EB52 86 39 stx recvdn ;receive done flag = false
|
|
464 EB54 86 38 stx bufrfl ;buffer full flag = false
|
|
465 EB56 E8 inx
|
|
466 EB57 86 30 stx status ;set status to success (1)
|
|
467
|
|
468 ;configure serial port for asynchronous receive
|
|
469 ;enable receive IRQ
|
|
470 EB59 78 sei
|
|
471 EB5A AD 32 02 lda sskctl
|
|
472 EB5D 29 8F and #$8f
|
|
473 EB5F 09 10 ora #$10
|
|
474 EB61 8D 32 02 sta sskctl
|
|
475 EB64 8D 0F D2 sta skctl
|
|
476 EB67 A5 10 lda pokmsk
|
|
477 EB69 09 20 ora #$20
|
|
478 EB6B 85 10 sta pokmsk
|
|
479 EB6D 8D 0E D2 sta irqen
|
|
480 EB70 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 EB71 A9 3C 8D 03 D3 mva #$3c pbctl
|
|
487
|
|
488 ;wait for receive to complete
|
|
489 EB76 wait:
|
|
490 EB76 AD 17 03 lda timflg ;check for timeout
|
|
491 EB79 F0 0B beq timeout ;bail if so
|
|
492 EB7B A4 30 ldy status ;check for another error code
|
|
493 EB7D 30 05 bmi error ;bail if so
|
|
494 EB7F A5 39 lda recvdn ;check for receive complete
|
|
495 EB81 F0 F3 beq wait ;keep waiting if not
|
|
496 EB83 98 tya ;set flags from status
|
|
497
|
|
498 EB84 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 EB84 78 sei
|
|
507 EB85 60 rts
|
|
508
|
|
509 EB86 timeout:
|
|
510 EB86 A0 8A ldy #SIOErrorTimeout
|
|
511 EB88 78 sei
|
|
512 EB89 60 rts
|
|
513 .endp
|
|
514
|
|
515 ;==============================================================================
|
|
516 EB8A .proc SIOReceiveStop
|
|
517 ;shut off receive IRQs
|
|
518 EB8A A5 10 lda pokmsk
|
|
519 EB8C 29 D7 and #$d7
|
|
520 EB8E 85 10 sta pokmsk
|
|
521 EB90 8D 0E D2 sta irqen
|
|
522 EB93 58 cli
|
|
523 EB94 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 EB95 .proc SIOInputReadyHandler
|
|
540 EB95 A5 38 lda bufrfl
|
|
541 EB97 D0 2A bne receiveChecksum
|
|
542
|
|
543 ;receive data byte
|
|
544 EB99 98 tya
|
|
545 EB9A 48 pha
|
|
546 EB9B AD 0D D2 lda serin
|
|
547 EB9E A0 00 ldy #$00
|
|
548 EBA0 91 32 sta (bufrlo),y
|
|
549 EBA2 18 clc
|
|
550 EBA3 65 31 adc chksum
|
|
551 EBA5 69 00 adc #$00
|
|
552 EBA7 85 31 sta chksum
|
|
553
|
|
554 ;restore Y now
|
|
555 EBA9 68 pla
|
|
556 EBAA A8 tay
|
|
557
|
|
558 ;bump buffer pointer
|
|
559 EBAB E6 32 D0 02 E6 33 inw bufrlo
|
|
560
|
|
561 ;check for EOB
|
|
562 EBB1 A5 32 lda bufrlo
|
|
563 EBB3 C5 34 cmp bfenlo
|
|
564 EBB5 A5 33 lda bufrhi
|
|
565 EBB7 E5 35 sbc bfenhi
|
|
566 EBB9 90 06 bcc xit
|
|
567
|
|
568 EBBB C6 38 dec bufrfl ;!! - this was $00 coming in
|
|
569
|
|
570 ;should there be a checksum?
|
|
571 EBBD A5 3C lda nocksm
|
|
572 EBBF D0 15 bne skipChecksum
|
|
573 EBC1 xit:
|
|
574 EBC1 68 pla
|
|
575 EBC2 40 rti
|
|
576
|
|
577 EBC3 receiveChecksum:
|
|
578 ;read and compare checksum
|
|
579 EBC3 AD 0D D2 lda serin
|
|
580 EBC6 C5 31 cmp chksum
|
|
581 EBC8 D0 06 bne checksum_fail
|
|
582
|
|
583 EBCA signal_end:
|
|
584 ;set receive done flag
|
|
585 EBCA A9 FF 85 39 mva #$ff recvdn
|
|
586
|
|
587 ;exit
|
|
588 EBCE 68 pla
|
|
589 EBCF 40 rti
|
|
590
|
|
591 EBD0 checksum_fail:
|
|
592 EBD0 A9 8F lda #SIOErrorChecksum
|
|
593 EBD2 85 30 sta status
|
|
594 EBD4 D0 F4 bne signal_end ;!! - unconditional
|
|
595
|
|
596 EBD6 skipChecksum:
|
|
597 ;set receive done flag
|
|
598 EBD6 85 39 sta recvdn
|
|
599
|
|
600 ;clear no checksum flag
|
|
601 EBD8 A9 00 lda #0
|
|
602 EBDA 85 3C sta nocksm
|
|
603 EBDC 68 pla
|
|
604 EBDD 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 EBDE .proc SIOOutputReadyHandler
|
|
621 ;increment buffer pointer
|
|
622 EBDE E6 32 inc bufrlo
|
|
623 EBE0 D0 02 bne addrcc
|
|
624 EBE2 E6 33 inc bufrhi
|
|
625 EBE4 addrcc:
|
|
626
|
|
627 ;compare against buffer end
|
|
628 EBE4 A5 32 lda bufrlo
|
|
629 EBE6 C5 34 cmp bfenlo
|
|
630 EBE8 A5 33 lda bufrhi
|
|
631 EBEA E5 35 sbc bfenhi ;set flags according to (dst - end)
|
|
632 EBEC B0 13 bcs doChecksum
|
|
633
|
|
634 ;save Y
|
|
635 EBEE 98 tya
|
|
636 EBEF 48 pha
|
|
637
|
|
638 ;send out next byte
|
|
639 EBF0 A0 00 ldy #0
|
|
640 EBF2 B1 32 lda (bufrlo),y
|
|
641 EBF4 8D 0D D2 sta serout
|
|
642
|
|
643 ;update checksum
|
|
644 EBF7 65 31 adc chksum
|
|
645 EBF9 69 00 adc #0
|
|
646 EBFB 85 31 sta chksum
|
|
647
|
|
648 ;restore registers and exit
|
|
649 EBFD 68 pla
|
|
650 EBFE A8 tay
|
|
651 EBFF 68 pla
|
|
652 EC00 40 rti
|
|
653
|
|
654 EC01 doChecksum:
|
|
655 ;send checksum
|
|
656 EC01 A5 31 lda chksum
|
|
657 EC03 8D 0D D2 sta serout
|
|
658
|
|
659 ;set checksum sent flag
|
|
660 EC06 A9 FF 85 3B mva #$ff chksnt
|
|
661
|
|
662 ;enable output complete IRQ and disable serial output IRQ
|
|
663 EC0A A5 10 lda pokmsk
|
|
664 EC0C 09 08 ora #$08
|
|
665 EC0E 29 EF and #$ef
|
|
666 EC10 85 10 sta pokmsk
|
|
667 EC12 8D 0E D2 sta irqen
|
|
668
|
|
669 EC15 68 pla
|
|
670 EC16 40 rti
|
|
671 .endp
|
|
672
|
|
673 ;==============================================================================
|
|
674 EC17 .proc SIOOutputCompleteHandler
|
|
675 ;check that we've sent the checksum
|
|
676 EC17 A5 3B lda chksnt
|
|
677 EC19 F0 0B beq xit
|
|
678
|
|
679 ;we're done sending the checksum
|
|
680 EC1B 85 3A sta xmtdon
|
|
681
|
|
682 ;need to shut off this interrupt as it is not latched
|
|
683 EC1D A5 10 lda pokmsk
|
|
684 EC1F 29 F7 and #$f7
|
|
685 EC21 85 10 sta pokmsk
|
|
686 EC23 8D 0E D2 sta irqen
|
|
687
|
|
688 EC26 xit:
|
|
689 EC26 68 pla
|
|
690 EC27 40 rti
|
|
691 .endp
|
|
692
|
|
693 ;==============================================================================
|
|
694 EC28 .proc SIOCountdown1Handler
|
|
695 ;signal operation timeout
|
|
696 EC28 A9 00 8D 17 03 mva #0 timflg
|
|
697 EC2D 60 rts
|
|
698 .endp
|
|
699
|
|
700 ;==============================================================================
|
|
701 EC2E .proc SIOCassette
|
|
702 ;check if it's read sector
|
|
703 EC2E AD 02 03 lda dcomnd
|
|
704 EC31 C9 52 cmp #$52
|
|
705 EC33 F0 0F beq isread
|
|
706
|
|
707 ;check if it's put sector
|
|
708 EC35 C9 50 cmp #$50
|
|
709 EC37 F0 05 beq iswrite
|
|
710
|
|
711 ;nope, bail
|
|
712 EC39 A0 8B ldy #SIOErrorNAK
|
|
713 EC3B 4C 29 EA jmp SIO.xit
|
|
714
|
|
715 EC3E iswrite:
|
|
716 EC3E 20 4A EC jsr SIOCassetteWriteFrame
|
|
717 EC41 4C 29 EA jmp SIO.xit
|
|
718
|
|
719 EC44 isread:
|
|
720 EC44 20 5B EC jsr SIOCassetteReadFrame
|
|
721 EC47 4C 29 EA jmp SIO.xit
|
|
722 .endp
|
|
723
|
|
724 ;==============================================================================
|
|
725 EC4A .proc SIOCassetteWriteFrame
|
|
726 ;wait for pre-record write tone or IRG read delay
|
|
727 EC4A A2 02 ldx #2
|
|
728 EC4C 20 9D EF jsr CassetteWaitLongShortCheck
|
|
729
|
|
730 ;set up to transmit
|
|
731 EC4F 20 99 EA jsr SIOSendEnable
|
|
732
|
|
733 ;setup buffer pointers
|
|
734 EC52 20 07 EB jsr SIOSetupBufferPointers
|
|
735
|
|
736 ;send data frame
|
|
737 EC55 20 1D EB jsr SIOSend
|
|
738
|
|
739 ;all done
|
|
740 EC58 4C 29 EA 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 EC5B .proc SIOCassetteReadFrame
|
|
759 ;wait for pre-record write tone or IRG read delay
|
|
760 EC5B A2 04 ldx #4
|
|
761 EC5D 20 9D EF jsr CassetteWaitLongShortCheck
|
|
762
|
|
763 ;set to 600 baud, turn on async read to shut off annoying tone
|
|
764 EC60 A2 1A ldx #SIOSendEnable.regdata_cassette_read-SIOSendEnable.regdata+8
|
|
765 EC62 20 C1 EA jsr SIOInitPOKEYWithRegOffsetX
|
|
766
|
|
767 EC65 AD 32 02 lda sskctl
|
|
768 EC68 29 8F and #$8f
|
|
769 EC6A 09 10 ora #$10
|
|
770 EC6C 8D 32 02 sta sskctl
|
|
771
|
|
772 ;set timeout (approx; no NTSC/PAL switching yet)
|
|
773 EC6F A9 FF 8D 17 03 mva #$ff timflg
|
|
774 EC74 A9 01 lda #1
|
|
775 EC76 A2 0E ldx #>3600
|
|
776 EC78 A0 10 ldy #<3600
|
|
777 EC7A 20 69 E8 jsr VBISetVector
|
|
778
|
|
779 ;wait for beginning of frame
|
|
780 EC7D A9 10 lda #$10 ;test bit 4 of SKSTAT
|
|
781 EC7F waitzerostart:
|
|
782 EC7F 2C 17 03 bit timflg
|
|
783 EC82 10 2B bpl timeout
|
|
784 EC84 2C 0F D2 bit skstat
|
|
785 EC87 D0 F6 bne waitzerostart
|
|
786
|
|
787 ;take first time measurement
|
|
788 EC89 20 49 ED jsr readtimer
|
|
789 EC8C 8C 0D 03 sty timer1+1
|
|
790 EC8F 8D 0C 03 sta timer1
|
|
791
|
|
792 ;wait for 19 bit transitions
|
|
793 EC92 A9 10 lda #$10 ;test bit 4 of SKSTAT
|
|
794 EC94 A2 0A ldx #10 ;test 10 pairs of bits
|
|
795 EC96 waitone:
|
|
796 EC96 2C 17 03 bit timflg
|
|
797 EC99 10 14 bpl timeout
|
|
798 EC9B 2C 0F D2 bit skstat
|
|
799 EC9E F0 F6 beq waitone
|
|
800 ECA0 CA dex
|
|
801 ECA1 F0 11 beq waitdone
|
|
802 ECA3 waitzero:
|
|
803 ECA3 2C 17 03 bit timflg
|
|
804 ECA6 10 07 bpl timeout
|
|
805 ECA8 2C 0F D2 bit skstat
|
|
806 ECAB D0 F6 bne waitzero
|
|
807 ECAD F0 E7 beq waitone
|
|
808
|
|
809 ECAF timeout:
|
|
810 ECAF A0 8A ldy #SIOErrorTimeout
|
|
811 ECB1 4C 29 EA jmp SIO.xit
|
|
812
|
|
813 ECB4 waitdone:
|
|
814
|
|
815 ;take second time measurement
|
|
816 ECB4 20 49 ED jsr readtimer
|
|
817 ECB7 8D 10 03 sta timer2
|
|
818 ECBA 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 ECBD A2 83 ldx #131
|
|
839 ECBF AD 14 D0 lda pal
|
|
840 ECC2 4A lsr
|
|
841 ECC3 D0 02 A2 9C sne:ldx #156
|
|
842 ECC7 8E 15 03 stx temp3
|
|
843
|
|
844 ;compute line difference
|
|
845 ECCA AD 0C 03 lda timer1
|
|
846 ECCD 20 57 ED jsr correct_time
|
|
847 ECD0 85 34 sta bfenlo
|
|
848
|
|
849 ECD2 AD 10 03 lda timer2
|
|
850 ECD5 20 57 ED jsr correct_time
|
|
851 ECD8 18 clc ;!! this decrements one line from the line delta
|
|
852 ECD9 E5 34 sbc bfenlo
|
|
853 ECDB 85 34 sta bfenlo
|
|
854 ECDD A0 00 ldy #0
|
|
855 ECDF B0 01 88 scs:dey
|
|
856
|
|
857 ;compute frame difference
|
|
858 ECE2 AD 11 03 lda timer2+1
|
|
859 ECE5 38 ED 0D 03 sub timer1+1
|
|
860 ECE9 AA tax
|
|
861
|
|
862 ;accumulate frame difference
|
|
863 ECEA F0 0C beq no_frames
|
|
864 ECEC A5 34 lda bfenlo
|
|
865 ECEE add_frame_loop:
|
|
866 ECEE 18 clc
|
|
867 ECEF 6D 15 03 adc temp3
|
|
868 ECF2 90 01 C8 scc:iny
|
|
869 ECF5 CA dex
|
|
870 ECF6 D0 F6 bne add_frame_loop
|
|
871 ECF8 no_frames:
|
|
872 ECF8 84 35 sty bfenhi
|
|
873
|
|
874 ;compute lines*6 - 7 = (lines-1)*6 - 1
|
|
875 ECFA 0A asl ;(lines-1)*2 (lo)
|
|
876 ECFB 26 35 rol bfenhi ;(lines-1)*2 (hi)
|
|
877 ECFD 85 34 sta bfenlo
|
|
878 ECFF A4 35 ldy bfenhi ;
|
|
879 ED01 06 34 asl bfenlo ;(lines-1)*4 (lo)
|
|
880 ED03 26 35 rol bfenhi ;(lines-1)*4 (hi)
|
|
881 ED05 65 34 adc bfenlo ;(lines-1)*6 (lo)
|
|
882 ED07 AA tax ;
|
|
883 ED08 98 tya ;
|
|
884 ED09 65 35 adc bfenhi ;(lines-1)*6 (hi) (and c=0)
|
|
885 ED0B CA dex ;-1 line, bringing us to -7
|
|
886 ED0C 8E 04 D2 stx audf3
|
|
887 ED0F 8E EE 02 stx cbaudl
|
|
888 ED12 E8 inx
|
|
889 ED13 D0 02 E9 00 sne:sbc #0
|
|
890 ED17 8D 06 D2 sta audf4
|
|
891 ED1A 8D EF 02 sta cbaudh
|
|
892
|
|
893 ;kick pokey into init mode to reset serial input shift hw
|
|
894 ED1D AE 32 02 ldx sskctl
|
|
895 ED20 8A txa
|
|
896 ED21 29 FC and #$fc
|
|
897 ED23 8D 0F D2 sta skctl
|
|
898
|
|
899 ;reset serial port status
|
|
900 ED26 8D 0A D2 sta skres
|
|
901
|
|
902 ;re-enable serial input hw
|
|
903 ED29 8E 0F D2 stx skctl
|
|
904
|
|
905 ED2C 20 07 EB jsr SIOSetupBufferPointers
|
|
906
|
|
907 ;stuff two $55 bytes into the buffer, which we "read" above
|
|
908 ED2F A9 55 lda #$55
|
|
909 ED31 A0 00 ldy #0
|
|
910 ED33 A2 02 ldx #2
|
|
911 ED35 aaloop:
|
|
912 ED35 91 32 sta (bufrlo),y
|
|
913 ED37 E6 32 D0 02 E6 33 inw bufrlo
|
|
914 ED3D CA D0 F5 dex:bne aaloop
|
|
915
|
|
916 ;reset checksum for two $55 bytes and receive frame
|
|
917 ED40 0A asl
|
|
918 ED41 85 31 sta chksum
|
|
919
|
|
920 ED43 20 4E EB jsr SIOReceive.use_checksum
|
|
921 ED46 4C 8A EB 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 ED49 readtimer:
|
|
933 ED49 A4 14 ldy rtclok+2
|
|
934 ED4B AD 0B D4 lda vcount
|
|
935 ED4E C4 14 cpy rtclok+2
|
|
936 ED50 D0 F7 bne readtimer
|
|
937 ED52 C9 7C cmp #124
|
|
938 ED54 F0 F3 beq readtimer
|
|
939 ED56 60 rts
|
|
940
|
|
941 ED57 correct_time:
|
|
942 ED57 38 sec
|
|
943 ED58 E9 7C sbc #124
|
|
944 ED5A B0 03 bcs time_ok
|
|
945 ED5C 6D 15 03 adc temp3
|
|
946 ED5F time_ok:
|
|
947 ED5F 60 rts
|
|
948
|
|
949 .endp
|
|
950
|
|
249 ED60 _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 $ED60 -> $041B($04A6) Serial Input/Output (SIO)
|
|
3 = ED60 .def ?@_kernel_lastpt = *
|
|
Source: source/main.xasm
|
|
250
|
|
251 ED60 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 ED60 .proc DiskInit
|
|
11 .if _KERNEL_XLXE
|
|
12 ;set disk sector size to 128 bytes
|
|
13 mwa #$80 dsctln
|
|
14 .endif
|
|
15 ED60 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 ED61 .proc DiskHandler
|
|
28 ED61 A9 31 8D 00 03 mva #$31 ddevic
|
|
29 ED66 A9 0F 8D 06 03 mva #$0f dtimlo
|
|
30
|
|
31 ;check for status command
|
|
32 ED6B AD 02 03 lda dcomnd
|
|
33 ED6E 8D 3B 02 sta ccomnd
|
|
34 ED71 C9 53 cmp #$53
|
|
35 ED73 D0 20 bne notStatus
|
|
36
|
|
37 ED75 A9 EA lda #<dvstat
|
|
38 ED77 8D 04 03 sta dbuflo
|
|
39 ED7A A9 02 lda #>dvstat
|
|
40 ED7C 8D 05 03 sta dbufhi
|
|
41 ED7F 0A asl ;hack to save a byte to get $04 since >dvstat is $02
|
|
42 ED80 8D 08 03 sta dbytlo
|
|
43 ED83 A9 00 lda #0
|
|
44 ED85 8D 09 03 sta dbythi
|
|
45
|
|
46 ED88 20 AD ED jsr do_read
|
|
47 ED8B 30 07 bmi xit
|
|
48
|
|
49 ;update format timeout
|
|
50 ED8D AE EC 02 8E 46 02 mvx dvstat+2 dsktim
|
|
51 ED93 AA tax
|
|
52 ED94 xit:
|
|
53 ED94 60 rts
|
|
54
|
|
55 ED95 notStatus:
|
|
56
|
|
57 ;set disk sector length
|
|
58 .if _KERNEL_XLXE
|
|
59 mwy dsctln dbytlo
|
|
60 .else
|
|
61 ED95 A0 80 8C 08 03 A0 + mwy #$80 dbytlo
|
|
62 .endif
|
|
63
|
|
64 ;check for put/write
|
|
65 .if _KERNEL_XLXE
|
|
66 cmp #$50
|
|
67 beq do_write
|
|
68 .endif
|
|
69 ED9F C9 57 cmp #$57
|
|
70 EDA1 F0 19 beq do_write
|
|
71
|
|
72 ;check for format, or else assume it's a read command ($52) or similar
|
|
73 EDA3 C9 21 cmp #$21
|
|
74 EDA5 D0 06 bne do_read
|
|
75
|
|
76 ;it's format... use the format timeout
|
|
77 EDA7 AD 46 02 8D 06 03 mva dsktim dtimlo
|
|
78
|
|
79 EDAD do_read:
|
|
80 EDAD A9 40 lda #$40
|
|
81 EDAF do_io:
|
|
82 EDAF 8D 03 03 sta dstats
|
|
83 EDB2 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 EDB5 AD 02 03 lda dcomnd
|
|
89 EDB8 C0 00 cpy #0 ;!! Atari800WinPlus's SIO patch doesn't set STATUS
|
|
90 EDBA 38 sec
|
|
91 EDBB 60 rts
|
|
92
|
|
93 EDBC do_write:
|
|
94 EDBC A9 80 lda #$80
|
|
95 EDBE D0 EF bne do_io
|
|
96 .endp
|
|
252 EDC0 _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 $EDC0 -> $0060($008E) Disk Handler
|
|
3 = EDC0 .def ?@_kernel_lastpt = *
|
|
Source: source/main.xasm
|
|
253
|
|
254 EDC0 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 EDC0 .proc PrinterInit
|
|
12 ;set printer timeout to default
|
|
13 EDC0 A9 1E 8D 14 03 mva #30 ptimot
|
|
14 EDC5 60 rts
|
|
15 .endp
|
|
16
|
|
17 ;==========================================================================
|
|
18 EDC6 .proc PrinterOpen
|
|
19 ;check for sideways mode and compute line size
|
|
20 EDC6 A2 28 ldx #40
|
|
21 EDC8 A5 2B lda icax2z
|
|
22 EDCA C9 53 cmp #$53
|
|
23 EDCC D0 02 A2 1D sne:ldx #29
|
|
24 EDD0 8E DF 02 stx pbufsz
|
|
25
|
|
26 EDD3 A9 00 lda #0
|
|
27 EDD5 8D DE 02 sta pbpnt
|
|
28
|
|
29 EDD8 xit:
|
|
30 EDD8 A0 01 ldy #1
|
|
31 EDDA 60 rts
|
|
32 .endp
|
|
33
|
|
34 ;==========================================================================
|
|
35 = EDDB PrinterClose = _PrinterPutByte.close_entry
|
|
36 = EDE2 PrinterPutByte = _PrinterPutByte.put_entry
|
|
37
|
|
38 EDDB .proc _PrinterPutByte
|
|
39 EDDB close_entry:
|
|
40 ;check if we have anything in the buffer
|
|
41 EDDB AD DE 02 lda pbpnt
|
|
42
|
|
43 ;exit if buffer is empty
|
|
44 EDDE F0 F8 beq PrinterOpen.xit
|
|
45
|
|
46 ;fall through to put with EOL
|
|
47 EDE0 A9 9B lda #$9b
|
|
48
|
|
49 EDE2 put_entry:
|
|
50 ;preload buffer index (useful later)
|
|
51 EDE2 AE DE 02 ldx pbpnt
|
|
52
|
|
53 ;check for EOL
|
|
54 EDE5 C9 9B cmp #$9b
|
|
55 EDE7 F0 0E beq do_eol
|
|
56
|
|
57 ;mask off MSB
|
|
58 EDE9 29 7F and #$7f
|
|
59
|
|
60 ;put char and advance
|
|
61 EDEB 9D C0 03 sta prnbuf,x
|
|
62 EDEE E8 inx
|
|
63 EDEF 8E DE 02 stx pbpnt
|
|
64
|
|
65 ;check for end of line and exit if not
|
|
66 EDF2 EC DF 02 cpx pbufsz
|
|
67 EDF5 90 E1 bcc PrinterOpen.xit
|
|
68
|
|
69 ;fall through to EOL
|
|
70
|
|
71 EDF7 do_eol:
|
|
72 ;fill remainder of buffer with spaces
|
|
73 EDF7 A9 20 lda #$20
|
|
74 EDF9 fill_loop:
|
|
75 EDF9 EC DF 02 cpx pbufsz
|
|
76 EDFC B0 06 bcs fill_done
|
|
77 EDFE 9D C0 03 sta prnbuf,x
|
|
78 EE01 E8 inx
|
|
79 EE02 90 F5 bcc fill_loop
|
|
80 EE04 fill_done:
|
|
81
|
|
82 ;send line to printer
|
|
83 EE04 A0 0A ldy #10
|
|
84 EE06 B9 25 EE 99 FF 02 + mva:rne iocbdat-1,y ddevic-1,y-
|
|
85
|
|
86 ;empty buffer
|
|
87 EE0F 8C DE 02 sty pbpnt
|
|
88
|
|
89 ;set line length
|
|
90 EE12 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 EE15 8A txa
|
|
101 EE16 29 15 and #%00010101
|
|
102 EE18 49 4E eor #%01001110
|
|
103 EE1A 8D 0A 03 sta daux1 ;set AUX1 to indicate width to device
|
|
104
|
|
105 ;send to printer and exit
|
|
106 EE1D do_io:
|
|
107 EE1D AD 14 03 8D 06 03 mva ptimot dtimlo
|
|
108 EE23 4C 59 E4 jmp siov
|
|
109
|
|
110 EE26 iocbdat:
|
|
111 EE26 40 dta $40 ;device
|
|
112 EE27 01 dta $01 ;unit
|
|
113 EE28 57 dta $57 ;command 'W'
|
|
114 EE29 80 dta $80 ;input/output mode (write)
|
|
115 EE2A C0 03 dta a(prnbuf) ;buffer address
|
|
116 EE2C 00 00 dta a(0) ;timeout
|
|
117 EE2E 00 00 dta a(0) ;buffer length
|
|
118 .endp
|
|
119
|
|
120 ;==============================================================================
|
|
121 EE30 .proc PrinterGetStatus
|
|
122 ;setup parameter block
|
|
123 EE30 A2 09 ldx #9
|
|
124 EE32 BD 47 EE 9D 00 03 + mva:rpl iocbdat,x ddevic,x-
|
|
125
|
|
126 ;issue status call
|
|
127 EE3B 20 1D EE jsr _PrinterPutByte.do_io
|
|
128 EE3E 30 06 bmi error
|
|
129
|
|
130 ;update timeout
|
|
131 EE40 AD EC 02 8D 14 03 mva dvstat+2 ptimot
|
|
132
|
|
133 EE46 error:
|
|
134 EE46 60 rts
|
|
135
|
|
136 EE47 iocbdat:
|
|
137 EE47 40 dta $40 ;device
|
|
138 EE48 01 dta $01 ;unit
|
|
139 EE49 53 dta $53 ;command 'S'
|
|
140 EE4A 40 dta $40 ;input/output mode (read)
|
|
141 EE4B EA 02 dta a(dvstat) ;buffer address
|
|
142 EE4D 00 00 dta a(0) ;timeout
|
|
143 EE4F 04 00 dta a(4) ;buffer length
|
|
144 .endp
|
|
145
|
|
146 ;==============================================================================
|
|
147 = E4CB PrinterGetByte = CIOExitNotSupported
|
|
148 = E4CB PrinterSpecial = CIOExitNotSupported
|
|
255 EE51 _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 $EE51 -> $0091($00C9) Printer Handler
|
|
3 = EE51 .def ?@_kernel_lastpt = *
|
|
Source: source/main.xasm
|
|
256
|
|
257 EE51 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 EE51 .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 EE51 A9 CC 8D EE 02 A9 + mwa #$05CC cbaudl
|
|
16 EE5B 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 = EE6F CassetteOpenRead = CassetteOpen.do_open_read
|
|
36 EE5C .proc CassetteOpen
|
|
37 ;stash continuous mode flag
|
|
38 EE5C A5 2B lda icax2z ;!! FIRST TWO BYTES CHECKED BY ARCHON
|
|
39 EE5E 85 3E sta ftype
|
|
40
|
|
41 ;check mode byte for read/write modes
|
|
42 EE60 A2 80 ldx #$80
|
|
43 EE62 A5 2A lda icax1z
|
|
44 EE64 29 0C and #$0c
|
|
45 EE66 C9 04 cmp #$04 ;read?
|
|
46 EE68 F0 05 beq found_read_mode
|
|
47 EE6A C9 08 cmp #$08 ;write?
|
|
48 EE6C F0 03 beq found_write_mode
|
|
49
|
|
50 ;invalid mode -- return not supported
|
|
51 EE6E 60 rts
|
|
52
|
|
53 EE6F do_open_read:
|
|
54 EE6F found_read_mode:
|
|
55 EE6F A2 00 ldx #$00
|
|
56 EE71 found_write_mode:
|
|
57 EE71 8E 89 02 stx wmode
|
|
58
|
|
59 ;set cassette buffer size to 128 bytes and mark it empty
|
|
60 EE74 A9 80 lda #$80
|
|
61 EE76 85 3D sta bptr
|
|
62 EE78 8D 8A 02 sta blim
|
|
63
|
|
64 ;clear EOF flag
|
|
65 EE7B 0A asl
|
|
66 EE7C 85 3F sta feof
|
|
67
|
|
68 ;request one beep for read, or two for write
|
|
69 EE7E 2C 89 02 bit wmode
|
|
70 EE81 10 05 bpl one_ping_only
|
|
71
|
|
72 EE83 06 3D asl bptr ;!! - set bptr=0 when starting write
|
|
73
|
|
74 EE85 20 C9 EF jsr CassetteBell
|
|
75
|
|
76 EE88 one_ping_only:
|
|
77 EE88 20 C9 EF jsr CassetteBell
|
|
78
|
|
79 ;wait for a key press
|
|
80 EE8B 20 66 FE jsr KeyboardGetByte
|
|
81 EE8E 30 20 bmi aborted
|
|
82
|
|
83 ;need to set up POKEY for writes now to write leader
|
|
84 EE90 2C 89 02 bit wmode
|
|
85 EE93 10 08 bpl no_write_init
|
|
86 EE95 A9 FF lda #$ff
|
|
87 EE97 8D 0F 03 sta casflg
|
|
88 EE9A 20 A4 EA jsr SIOSendEnable.no_irq_setup
|
|
89 EE9D no_write_init:
|
|
90
|
|
91 ;turn on motor (continuous mode or not)
|
|
92 EE9D A9 34 lda #$34
|
|
93 EE9F 8D 02 D3 sta pactl
|
|
94
|
|
95 ;wait for leader (9.6 seconds read, 19.2s write)
|
|
96 EEA2 A2 00 ldx #0
|
|
97 EEA4 2C 89 02 bit wmode
|
|
98 EEA7 30 02 A2 01 smi:ldx #1
|
|
99 EEAB 20 A3 EF jsr CassetteWait
|
|
100
|
|
101 ;all done
|
|
102 EEAE A0 01 ldy #1
|
|
103 EEB0 aborted:
|
|
104 EEB0 60 rts
|
|
105 .endp
|
|
106
|
|
107 ;==========================================================================
|
|
108 EEB1 .proc CassetteClose
|
|
109 ;check if we are in write mode
|
|
110 EEB1 AD 89 02 lda wmode ;!! FIRST TWO BYTES CHECKED BY ARCHON
|
|
111 EEB4 10 0A bpl notwrite
|
|
112
|
|
113 ;check if we have data to write
|
|
114 EEB6 A5 3D lda bptr
|
|
115 EEB8 F0 03 beq nopartial
|
|
116
|
|
117 ;flush partial record ($FA)
|
|
118 EEBA 20 22 EF jsr CassetteFlush
|
|
119
|
|
120 EEBD nopartial:
|
|
121 ;write EOF record ($FE)
|
|
122 EEBD 20 22 EF jsr CassetteFlush
|
|
123
|
|
124 EEC0 notwrite:
|
|
125 ;stop the motor
|
|
126 EEC0 A9 3C lda #$3c
|
|
127 EEC2 8D 02 D3 sta pactl
|
|
128
|
|
129 ;kill audio
|
|
130 EEC5 A0 00 ldy #0
|
|
131 EEC7 8C 01 D2 sty audc1
|
|
132 EECA 8C 03 D2 sty audc2
|
|
133 EECD 8C 07 D2 sty audc4
|
|
134
|
|
135 ;all done
|
|
136 EED0 C8 iny
|
|
137 EED1 60 rts
|
|
138 .endp
|
|
139
|
|
140 ;==========================================================================
|
|
141 EED2 .proc CassetteGetByte
|
|
142 ;check if we have an EOF condition
|
|
143 EED2 A5 3F lda feof ;!! FIRST TWO BYTES CHECKED BY ARCHON
|
|
144 EED4 D0 1D bne xit_eof
|
|
145
|
|
146 EED6 fetchbyte:
|
|
147 ;check if we can still fetch a byte
|
|
148 EED6 A6 3D ldx bptr
|
|
149 EED8 EC 8A 02 cpx blim
|
|
150 EEDB F0 08 beq nobytes
|
|
151
|
|
152 EEDD BD 00 04 lda casbuf+3,x
|
|
153 EEE0 E6 3D inc bptr
|
|
154 EEE2 A0 01 ldy #1
|
|
155 EEE4 60 rts
|
|
156
|
|
157 EEE5 nobytes:
|
|
158 ;fetch more bytes
|
|
159 EEE5 20 52 EF jsr CassetteReadBlock
|
|
160 EEE8 30 0B bmi error
|
|
161
|
|
162 ;check control byte
|
|
163 EEEA AD FF 03 lda casbuf+2
|
|
164 EEED C9 FE cmp #$fe
|
|
165 EEEF D0 05 bne noteofbyte
|
|
166
|
|
167 ;found $FE (EOF) - set flag and return EOF
|
|
168 EEF1 85 3F sta feof
|
|
169 EEF3 xit_eof:
|
|
170 EEF3 A0 88 ldy #CIOStatEndOfFile
|
|
171 EEF5 error:
|
|
172 EEF5 60 rts
|
|
173
|
|
174 EEF6 noteofbyte:
|
|
175 ;reset buffer ptr
|
|
176 EEF6 A2 00 86 3D mvx #0 bptr
|
|
177
|
|
178 ;assume full block first (128 bytes)
|
|
179 EEFA A2 80 ldx #$80
|
|
180
|
|
181 ;check if it actually is one
|
|
182 EEFC C9 FC cmp #$fc
|
|
183 EEFE D0 06 bne not_full_block
|
|
184
|
|
185 EF00 init_new_block:
|
|
186 ;reset block length and loop back
|
|
187 EF00 8E 8A 02 stx blim
|
|
188 EF03 4C D6 EE jmp fetchbyte
|
|
189
|
|
190 EF06 not_full_block:
|
|
191 ;check if we have a partial block
|
|
192 EF06 C9 FA cmp #$fa
|
|
193 EF08 D0 05 bne not_partial_block
|
|
194
|
|
195 ;set length of partial block and the jump to init+loop
|
|
196 EF0A AE 7F 04 ldx casbuf+130
|
|
197 EF0D B0 F1 bcs init_new_block
|
|
198
|
|
199 EF0F not_partial_block:
|
|
200 ;uh oh... bad control byte.
|
|
201 EF0F A0 A3 ldy #CIOStatFatalDiskIO
|
|
202 EF11 60 rts
|
|
203 .endp
|
|
204
|
|
205 ;==========================================================================
|
|
206 EF12 .proc CassettePutByte
|
|
207 ;put a byte into the buffer
|
|
208 EF12 A6 3D ldx bptr ;!! FIRST TWO BYTES CHECKED BY ARCHON
|
|
209 EF14 9D 00 04 sta casbuf+3,x
|
|
210
|
|
211 ;bump and check if it's time to write
|
|
212 EF17 E8 inx
|
|
213 EF18 86 3D stx bptr
|
|
214 EF1A EC 8A 02 cpx blim
|
|
215 EF1D B0 03 bcs CassetteFlush
|
|
216
|
|
217 ;all done
|
|
218 EF1F A0 01 ldy #1
|
|
219 EF21 60 rts
|
|
220 .endp
|
|
221
|
|
222 ;==========================================================================
|
|
223 EF22 .proc CassetteFlush
|
|
224 EF22 A9 00 lda #0
|
|
225
|
|
226 ;set control byte based on buffer level
|
|
227 EF24 A2 FE ldx #$fe ;empty -> EOF
|
|
228 EF26 A4 3D ldy bptr ;get buffer level
|
|
229 EF28 D0 08 bne not_empty ;skip not empty
|
|
230
|
|
231 ;clear buffer for EOF
|
|
232 EF2A 99 00 04 C8 10 FA sta:rpl casbuf+3,y+
|
|
233 EF30 30 0C bmi is_empty ;!! - unconditional
|
|
234
|
|
235 EF32 not_empty:
|
|
236 EF32 A2 FC ldx #$fc ;load complete code
|
|
237 EF34 CC 8A 02 cpy blim ;check if buffer is full
|
|
238 EF37 B0 05 bcs is_complete ;skip if so
|
|
239 EF39 A2 FA ldx #$fa ;load partial code
|
|
240 EF3B 8C 7F 04 sty casbuf+130 ;store level in last byte
|
|
241 EF3E is_complete:
|
|
242 EF3E is_empty:
|
|
243
|
|
244 ;store code
|
|
245 EF3E 8E FF 03 stx casbuf+2
|
|
246
|
|
247 ;reset buffer level
|
|
248 EF41 85 3D sta bptr
|
|
249
|
|
250 ;setup sync bytes
|
|
251 EF43 A9 55 lda #$55
|
|
252 EF45 8D FD 03 sta casbuf
|
|
253 EF48 8D FE 03 sta casbuf+1
|
|
254
|
|
255 ;issue write request and exit
|
|
256 EF4B A2 80 ldx #$80
|
|
257 EF4D A0 50 ldy #'P'
|
|
258 EF4F 4C 56 EF 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 = EF56 CassetteDoIO = _CassetteDoIO.do_io
|
|
275 = EF52 CassetteReadBlock = _CassetteDoIO.read_block
|
|
276
|
|
277 EF52 .proc _CassetteDoIO
|
|
278 EF52 read_block:
|
|
279 EF52 A2 40 ldx #$40
|
|
280 EF54 A0 52 ldy #'R'
|
|
281 EF56 do_io:
|
|
282 ;start the motor if not already running
|
|
283 EF56 A9 34 lda #$34
|
|
284 EF58 8D 02 D3 sta pactl
|
|
285
|
|
286 ;set up SIO read/write
|
|
287 EF5B 8E 03 03 stx dstats
|
|
288 EF5E 8C 02 03 sty dcomnd
|
|
289 EF61 A9 FD 8D 04 03 A9 + mwa #casbuf dbuflo
|
|
290 EF6B A9 83 8D 08 03 A9 + mwa #131 dbytlo
|
|
291 EF75 A9 60 8D 00 03 mva #$60 ddevic
|
|
292 EF7A A9 00 8D 01 03 mva #0 dunit
|
|
293 EF7F A5 3E 8D 0B 03 mva ftype daux2
|
|
294
|
|
295 ;do it
|
|
296 EF84 20 59 E4 jsr siov
|
|
297
|
|
298 ;check if we are in continuous mode (again)
|
|
299 EF87 A5 3E lda ftype
|
|
300 EF89 30 0F bmi rolling_stop
|
|
301
|
|
302 ;not in continuous mode -- wait for post-write tone if writing
|
|
303 EF8B 2C 89 02 bit wmode
|
|
304 EF8E 10 05 bpl no_pwt
|
|
305 EF90 A2 06 ldx #6
|
|
306 EF92 20 A3 EF jsr CassetteWait
|
|
307 EF95 no_pwt:
|
|
308
|
|
309 ;stop the motor
|
|
310 EF95 A9 3C lda #$3c
|
|
311 EF97 8D 02 D3 sta pactl
|
|
312
|
|
313 EF9A rolling_stop:
|
|
314 EF9A A4 30 ldy status
|
|
315 EF9C 60 rts
|
|
316 .endp
|
|
317
|
|
318 ;==========================================================================
|
|
319 ;Entry:
|
|
320 ; X = delay type
|
|
321 ;
|
|
322 = EFA3 CassetteWait = CassetteWaitLongShortCheck.normal_entry
|
|
323 EF9D .proc CassetteWaitLongShortCheck
|
|
324 EF9D 2C 0B 03 bit daux2
|
|
325 EFA0 10 01 E8 spl:inx
|
|
326 EFA3 normal_entry:
|
|
327 EFA3 20 65 EA jsr SIOSetTimeoutVector
|
|
328 EFA6 BC BB EF ldy wait_table_lo,x
|
|
329 EFA9 BD C2 EF lda wait_table_hi,x
|
|
330 EFAC AA tax
|
|
331 EFAD A9 01 lda #1
|
|
332 EFAF 8D 17 03 sta timflg
|
|
333 EFB2 20 69 E8 jsr VBISetVector
|
|
334 EFB5 AD 17 03 D0 FB lda:rne timflg
|
|
335 EFBA 60 rts
|
|
336
|
|
337 EFBB wait_table_lo:
|
|
338 EFBB 80 dta <$0480 ;$00 - write file leader (19.2 seconds NTSC)
|
|
339 EFBC 40 dta <$0240 ;$01 - read leader delay (9.6 seconds NTSC)
|
|
340 EFBD B4 dta <$00B4 ;$02 - long pre-record write tone (3.0s NTSC)
|
|
341 EFBE 0F dta <$000F ;$03 - short pre-record write tone (0.25s NTSC)
|
|
342 EFBF 78 dta <$0078 ;$04 - long read IRG (2.0s NTSC)
|
|
343 EFC0 0A dta <$000A ;$05 - short read IRG (0.16s NTSC)
|
|
344 EFC1 3C dta <$003C ;$06 - post record gap (1s NTSC)
|
|
345
|
|
346 EFC2 wait_table_hi:
|
|
347 EFC2 04 dta >$0480 ;$00 - write file leader (19.2 seconds NTSC)
|
|
348 EFC3 02 dta >$0240 ;$01 - read leader delay (9.6 seconds NTSC)
|
|
349 EFC4 00 dta >$00B4 ;$02 - long pre-record write tone (3.0s NTSC)
|
|
350 EFC5 00 dta >$000F ;$03 - short pre-record write tone (0.25s NTSC)
|
|
351 EFC6 00 dta >$0078 ;$04 - long read IRG (2.0s NTSC)
|
|
352 EFC7 00 dta >$000A ;$05 - short read IRG (0.16s NTSC)
|
|
353 EFC8 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 EFC9 .proc CassetteBell
|
|
363 EFC9 A0 00 ldy #0
|
|
364 EFCB 98 tya
|
|
365 EFCC soundloop:
|
|
366 EFCC A2 0A ldx #10
|
|
367 EFCE 48 pha
|
|
368 EFCF delay:
|
|
369 EFCF AD 0B D4 lda vcount
|
|
370 EFD2 CD 0B D4 F0 FB cmp:req vcount
|
|
371 EFD7 CA dex
|
|
372 EFD8 D0 F5 bne delay
|
|
373 EFDA 68 pla
|
|
374 EFDB 49 08 eor #$08
|
|
375 EFDD 8D 1F D0 sta consol
|
|
376 EFE0 D0 EA bne soundloop
|
|
377 EFE2 88 dey
|
|
378 EFE3 D0 E7 bne soundloop
|
|
379 EFE5 60 rts
|
|
380 .endp
|
|
258 EFE6 _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 $EFE6 -> $0195($01A2) Cassette Handler
|
|
3 = EFE6 .def ?@_kernel_lastpt = *
|
|
Source: source/main.xasm
|
|
259
|
|
260 .ifdef _KERNEL_816
|
|
261 icl 'init816.s'
|
|
262 .else
|
|
263 EFE6 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 .proc InitBootSignature
|
|
12 dta $5C,$93,$25
|
|
13 .endp
|
|
14 .endif
|
|
15
|
|
16 EFE6 .proc InitHandlerTable
|
|
17 EFE6 50 30 E4 dta c'P',a(printv)
|
|
18 EFE9 43 40 E4 dta c'C',a(casetv)
|
|
19 EFEC 45 00 E4 dta c'E',a(editrv)
|
|
20 EFEF 53 10 E4 dta c'S',a(screnv)
|
|
21 EFF2 4B 20 E4 dta c'K',a(keybdv)
|
|
22 .endp
|
|
23
|
|
24 EFF5 .nowarn .proc _InitReset
|
|
25 EFF5 run_diag:
|
|
26 ; start diagnostic cartridge
|
|
27 EFF5 6C FE BF jmp ($bffe)
|
|
28
|
|
29 = EFF8 .def :InitReset
|
|
30 ;mask interrupts and initialize CPU
|
|
31 EFF8 78 sei
|
|
32 EFF9 D8 cld
|
|
33 EFFA A2 FF ldx #$ff
|
|
34 EFFC 9A txs
|
|
35
|
|
36 .if _KERNEL_XLXE
|
|
37 ;wait for everything to stabilize (0.1s) (XL/XE only)
|
|
38 ldy #140
|
|
39 stabilize_loop:
|
|
40 dex:rne
|
|
41 dey
|
|
42 bne stabilize_loop
|
|
43
|
|
44 ;check for warmstart signature (XL/XE)
|
|
45 ldx #2
|
|
46 warm_check:
|
|
47 lda pupbt1,x
|
|
48 cmp InitBootSignature,x
|
|
49 bne cold_boot
|
|
50 dex
|
|
51 bpl warm_check
|
|
52
|
|
53 jmp InitWarmStart
|
|
54 .endif
|
|
55
|
|
56 = EFFD .def :InitColdStart
|
|
57 EFFD cold_boot:
|
|
58 ; 1. initialize CPU
|
|
59 EFFD 78 sei
|
|
60 EFFE D8 cld
|
|
61 EFFF A2 FF ldx #$ff
|
|
62 F001 9A txs
|
|
63
|
|
64 ; 2. clear warmstart flag
|
|
65 F002 E8 inx
|
|
66 F003 86 08 stx warmst
|
|
67
|
|
68 ; 3. test for diagnostic cartridge
|
|
69 F005 AD FC BF lda $bffc
|
|
70 F008 D0 17 bne not_diag
|
|
71 F00A A2 FF ldx #$ff
|
|
72 F00C EC FF BF cpx $bfff ;prevent diagnostic cart from activating if addr is $FFxx
|
|
73 F00F F0 10 beq not_diag
|
|
74 F011 8E FC BF stx $bffc
|
|
75 F014 CD FC BF cmp $bffc
|
|
76 F017 8D FC BF sta $bffc
|
|
77 F01A D0 05 bne not_diag
|
|
78
|
|
79 ; is it enabled?
|
|
80 F01C 2C FD BF bit $bffd
|
|
81 F01F 30 D4 bmi run_diag
|
|
82
|
|
83 F021 not_diag:
|
|
84
|
|
85 F021 20 70 F0 jsr InitHardwareReset
|
|
86
|
|
87 .if _KERNEL_XLXE
|
|
88 ;check for OPTION and enable BASIC (note that we do NOT set BASICF just yet)
|
|
89 lda #4
|
|
90 bit consol
|
|
91 beq no_basic
|
|
92
|
|
93 .ifdef _KERNEL_SOFTKICK
|
|
94 ldx #$fc
|
|
95 .else
|
|
96 ldx #$fd
|
|
97 .endif
|
|
98
|
|
99 ;check for keyboard present + SELECT or no keyboard + no SELECT and enable game if so
|
|
100 lda trig2 ;check keyboard present (1 = present)
|
|
101 asl
|
|
102 eor consol ;XOR against select (0 = pressed)
|
|
103 and #$02
|
|
104
|
|
105 .ifdef _KERNEL_SOFTKICK
|
|
106 seq:ldx #$be
|
|
107 .else
|
|
108 seq:ldx #$bf
|
|
109 .endif
|
|
110
|
|
111 stx portb ;enable GAME or BASIC
|
|
112
|
|
113 no_basic:
|
|
114 .endif
|
|
115
|
|
116 ; 4. measure memory -> tramsz
|
|
117 F024 20 9C F0 jsr InitMemory
|
|
118
|
|
119 ; 6. clear memory from $0008 up to [tramsz,0]
|
|
120 .ifdef _KERNEL_SOFTKICK
|
|
121 ldx #$50
|
|
122 .else
|
|
123 F027 A6 06 ldx tramsz
|
|
124 .endif
|
|
125 F029 A0 08 ldy #8
|
|
126 F02B A9 00 85 66 mva #0 a1
|
|
127 F02F 85 67 sta a1+1
|
|
128 F031 clearloop:
|
|
129 F031 91 66 C8 D0 FB sta:rne (a1),y+
|
|
130 F036 E6 67 inc a1+1
|
|
131 F038 CA dex
|
|
132 F039 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 ldx portb
|
|
139 txa
|
|
140 and #$7f
|
|
141 sta portb
|
|
142 stx portb
|
|
143 .endif
|
|
144
|
|
145 ; 7. set dosvec to blackboard routine
|
|
146 .if _KERNEL_USE_BOOT_SCREEN
|
|
147 mwa #SelfTestEntry dosvec
|
|
148 .else
|
|
149 F03B A9 80 85 0A A9 E4 + mwa #Blackboard dosvec
|
|
150 .endif
|
|
151
|
|
152 ; 8. set coldstart flag
|
|
153 F043 CE 44 02 dec coldst ;!! coldst=0 from clear loop above, now $ff
|
|
154
|
|
155 .if _KERNEL_XLXE
|
|
156 ; set BASIC flag
|
|
157 lda portb
|
|
158 and #$02
|
|
159 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 F046 4C DA F0 jmp InitEnvironment
|
|
175 .endp
|
|
176
|
|
177 ;==============================================================================
|
|
178 F049 .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 F049 78 sei ;!! FIRST TWO BYTES CHECKED BY ARCHON
|
|
187 F04A AD 44 02 lda coldst
|
|
188 F04D D0 AE bne InitColdStart
|
|
189 F04F D8 cld
|
|
190 F050 A2 FF ldx #$ff
|
|
191 F052 9A txs
|
|
192
|
|
193 ; B. set warmstart flag
|
|
194 F053 86 08 stx warmst
|
|
195
|
|
196 ; reinitialize hardware without doing a full clear
|
|
197 F055 20 70 F0 jsr InitHardwareReset
|
|
198
|
|
199 .if _KERNEL_XLXE
|
|
200 ; reinitialize BASIC
|
|
201 lda basicf
|
|
202 sne:mva #$fd portb
|
|
203 .endif
|
|
204
|
|
205 ; C. check for diag, measure memory, clear hw registers
|
|
206 F058 20 9C F0 jsr InitMemory
|
|
207
|
|
208 ; D. zero 0010-007F and 0200-03EC (must not clear BASICF).
|
|
209 F05B A2 60 ldx #$60
|
|
210 F05D A9 00 lda #0
|
|
211 F05F 95 0F CA D0 FB sta:rne $0f,x-
|
|
212
|
|
213 F064 dbclear:
|
|
214 F064 9D 00 02 sta $0200,x
|
|
215 F067 9D ED 02 sta $02ed,x
|
|
216 F06A E8 inx
|
|
217 F06B 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 F06D 4C DA F0 jmp InitEnvironment
|
|
224 .endp
|
|
225
|
|
226 ;==============================================================================
|
|
227 F070 .proc InitHardwareReset
|
|
228 ; clear all hardware registers
|
|
229 F070 A0 00 ldy #0
|
|
230 F072 98 tya
|
|
231 F073 hwclear:
|
|
232 F073 99 00 D0 sta $d000,y
|
|
233 F076 99 00 D2 sta $d200,y
|
|
234 F079 99 00 D4 sta $d400,y
|
|
235 F07C C8 iny
|
|
236 F07D D0 F4 bne hwclear
|
|
237
|
|
238 ;initialize PIA
|
|
239 F07F A9 3C lda #$3c
|
|
240 F081 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 stx pactl ;switch to DDRA
|
|
257 sty porta ;portA -> input
|
|
258 sta pactl ;switch to IORA
|
|
259 sty porta ;portA -> $00
|
|
260 sta pbctl ;switch to IORB
|
|
261 dey
|
|
262 sty portb ;portB -> $FF
|
|
263 stx pbctl ;switch to DDRB
|
|
264 sty portb ;portB -> all output
|
|
265 sta pbctl ;switch to IORB
|
|
266 .else
|
|
267 F083 8E 02 D3 stx pactl ;switch to DDRA
|
|
268 F086 8E 03 D3 stx pbctl ;switch to DDRB
|
|
269 F089 8C 00 D3 sty porta ;portA -> input
|
|
270 F08C 8C 01 D3 sty portb ;portB -> input
|
|
271 F08F 8D 02 D3 sta pactl ;switch to IORA
|
|
272 F092 8D 03 D3 sta pbctl ;switch to IORB
|
|
273 F095 8C 00 D3 sty porta ;portA -> $00
|
|
274 F098 8C 01 D3 sty portb ;portB -> $00
|
|
275 .endif
|
|
276 F09B 60 rts
|
|
277 .endp
|
|
278
|
|
279 ;==============================================================================
|
|
280 F09C .proc InitMemory
|
|
281 ; 4. measure memory -> tramsz
|
|
282 F09C A0 00 ldy #$00
|
|
283 F09E 84 64 sty adress
|
|
284 F0A0 A2 02 ldx #$02
|
|
285 F0A2 pageloop:
|
|
286 F0A2 86 65 stx adress+1
|
|
287 F0A4 B1 64 lda (adress),y
|
|
288 F0A6 49 FF eor #$ff
|
|
289 F0A8 91 64 sta (adress),y
|
|
290 F0AA D1 64 cmp (adress),y
|
|
291 F0AC D0 09 bne notRAM
|
|
292 F0AE 49 FF eor #$ff
|
|
293 F0B0 91 64 sta (adress),y
|
|
294 F0B2 E8 inx
|
|
295
|
|
296 .if _KERNEL_XLXE
|
|
297 cpx #$c0
|
|
298 .else
|
|
299 F0B3 E0 D0 cpx #$d0
|
|
300 .endif
|
|
301
|
|
302 F0B5 D0 EB bne pageloop
|
|
303 F0B7 notRAM:
|
|
304 F0B7 86 06 stx tramsz
|
|
305
|
|
306 F0B9 60 rts
|
|
307 .endp
|
|
308
|
|
309 ;==============================================================================
|
|
310 F0BA .proc InitVectorTable1
|
|
311 F0BA 66 E7 dta a(IntExitHandler_None) ;$0200 VDSLST
|
|
312 F0BC 65 E7 dta a(IntExitHandler_A) ;$0202 VPRCED
|
|
313 F0BE 65 E7 dta a(IntExitHandler_A) ;$0204 VINTER
|
|
314 F0C0 65 E7 dta a(IntExitHandler_A) ;$0206 VBREAK
|
|
315 F0C2 CC FE dta a(KeyboardIRQ) ;$0208 VKEYBD
|
|
316 F0C4 95 EB dta a(SIOInputReadyHandler) ;$020A VSERIN
|
|
317 F0C6 DE EB dta a(SIOOutputReadyHandler) ;$020C VSEROR
|
|
318 F0C8 17 EC dta a(SIOOutputCompleteHandler) ;$020E VSEROC
|
|
319 F0CA 65 E7 dta a(IntExitHandler_A) ;$0210 VTIMR1
|
|
320 F0CC 65 E7 dta a(IntExitHandler_A) ;$0212 VTIMR2
|
|
321 F0CE 65 E7 dta a(IntExitHandler_A) ;$0214 VTIMR4
|
|
322 F0D0 CD E8 dta a(IrqHandler) ;$0216 VIMIRQ
|
|
323 F0D2 end:
|
|
324 .endp
|
|
325
|
|
326 F0D2 .proc InitVectorTable2
|
|
327 F0D2 1D E7 dta a(VBIStage1) ;$0222 VVBLKI
|
|
328 F0D4 61 E7 dta a(VBIExit) ;$0224 VVBLKD
|
|
329 F0D6 00 00 dta a(0) ;$0226 CDTMA1
|
|
330 .endp
|
|
331
|
|
332 F0D8 krpdel_table:
|
|
333 F0D8 30 28 dta 48,40
|
|
334
|
|
335 ;==============================================================================
|
|
336 F0DA .proc InitEnvironment
|
|
337 F0DA 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 ldx #3
|
|
343 mva:rne InitBootSignature-1,x pupbt1-1,x-
|
|
344 .endif
|
|
345
|
|
346 ; 9. set screen margins
|
|
347 F0DF A9 02 85 52 mva #2 lmargn
|
|
348 F0E3 A9 27 85 53 mva #39 rmargn
|
|
349
|
|
350 ;set PAL/NTSC flag (XL/XE only)
|
|
351 .if _KERNEL_XLXE
|
|
352 ldx #0
|
|
353 lda pal
|
|
354 ldy #6
|
|
355 and #$0e
|
|
356 bne is_ntsc
|
|
357 sne:inx
|
|
358 dey
|
|
359 is_ntsc:
|
|
360 stx palnts
|
|
361 sty keyrep
|
|
362 mva krpdel_table,x krpdel
|
|
363 .endif
|
|
364
|
|
365 ; 10. initialize RAM vectors
|
|
366
|
|
367 ;VDSLST-VIMIRQ
|
|
368 F0E7 A2 17 ldx #[.len InitVectorTable1]-1
|
|
369 F0E9 BD BA F0 9D 00 02 + mva:rpl InitVectorTable1,x vdslst,x-
|
|
370
|
|
371 ;VVBLKI-CDTMA1
|
|
372 F0F2 A2 05 ldx #[.len InitVectorTable2]-1
|
|
373 F0F4 BD D2 F0 9D 22 02 + mva:rpl InitVectorTable2,x vvblki,x-
|
|
374
|
|
375 F0FD A9 00 8D 36 02 A9 + mwa #KeyboardBreakIRQ brkky
|
|
376
|
|
377 ; 11. set misc database values
|
|
378 F107 A2 FF ldx #$ff
|
|
379 F109 86 11 stx brkkey
|
|
380 F10B E8 inx
|
|
381 F10C 8E E5 02 stx memtop
|
|
382 F10F 8E E7 02 stx memlo
|
|
383 F112 A5 06 8D E6 02 mva tramsz memtop+1
|
|
384 F117 A2 07 8E E8 02 mvx #$07 memlo+1
|
|
385
|
|
386 F11C 20 60 ED jsr DiskInit
|
|
387 F11F 20 91 F5 jsr ScreenInit
|
|
388 ;jsr DisplayInit
|
|
389 F122 20 4B FE jsr KeyboardInit
|
|
390
|
|
391 .if _KERNEL_PRINTER_SUPPORT
|
|
392 F125 20 C0 ED 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 F128 A2 0E ldx #14
|
|
398 F12A BD E6 EF 9D 1A 03 + mva:rpl InitHandlerTable,x hatabs,x-
|
|
399
|
|
400 ;jsr CassetteInit
|
|
401 F133 20 6E E4 jsr cioinv
|
|
402 F136 20 45 E9 jsr SIOInit
|
|
403 F139 20 7F E8 jsr IntInitInterrupts
|
|
404
|
|
405 ; check for START key, and if so, set cassette boot flag
|
|
406 F13C AD 1F D0 lda consol
|
|
407 F13F 29 01 and #1
|
|
408 F141 49 01 eor #1
|
|
409 F143 8D E9 03 sta ckey
|
|
410
|
|
411 .if _KERNEL_PBI_SUPPORT
|
|
412 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 F146 58 cli
|
|
423
|
|
424 ; 14. initialize cartridges
|
|
425 F147 A9 00 85 07 mva #0 tstdat
|
|
426
|
|
427 .if !_KERNEL_XLXE
|
|
428 F14B AD FC 9F lda $9ffc
|
|
429 F14E D0 18 bne skipCartBInit
|
|
430 F150 AD FB 9F lda $9ffb
|
|
431 F153 AA tax
|
|
432 F154 49 FF eor #$ff
|
|
433 F156 8D FB 9F sta $9ffb
|
|
434 F159 CD FB 9F cmp $9ffb
|
|
435 F15C 8E FB 9F stx $9ffb
|
|
436 F15F F0 07 beq skipCartBInit
|
|
437 F161 20 11 F2 jsr InitCartB
|
|
438 F164 A9 01 85 07 mva #1 tstdat
|
|
439 F168 skipCartBInit:
|
|
440 .endif
|
|
441
|
|
442 F168 A9 00 85 06 mva #0 tramsz
|
|
443 F16C AD FC BF lda $bffc
|
|
444 F16F D0 18 bne skipCartAInit
|
|
445 F171 AD FB BF lda $bffb
|
|
446 F174 AA tax
|
|
447 F175 49 FF eor #$ff
|
|
448 F177 8D FB BF sta $bffb
|
|
449 F17A CD FB BF cmp $bffb
|
|
450 F17D 8E FB BF stx $bffb
|
|
451 F180 F0 07 beq skipCartAInit
|
|
452 F182 20 0E F2 jsr InitCartA
|
|
453 F185 A9 01 85 06 mva #1 tramsz
|
|
454 F189 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 F189 A9 03 8D 42 03 mva #$03 iccmd ;OPEN
|
|
463 F18E A9 14 8D 44 03 A9 + mwa #ScreenEditorName icbal
|
|
464 F198 A9 0C 8D 4A 03 mva #$0c icax1 ;read/write, no forced read
|
|
465 F19D A2 00 ldx #0
|
|
466 F19F 8E 4B 03 stx icax2 ;mode 0
|
|
467 F1A2 20 56 E4 jsr ciov
|
|
468
|
|
469 ; 16. wait for VBLANK so screen is initialized
|
|
470 F1A5 A5 14 lda rtclok+2
|
|
471 F1A7 waitvbl:
|
|
472 F1A7 C5 14 cmp rtclok+2
|
|
473 F1A9 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 F1AB A5 08 lda warmst
|
|
502 F1AD D0 0B bne reinitcas
|
|
503
|
|
504 F1AF AD E9 03 lda ckey
|
|
505 F1B2 F0 0F beq postcasboot
|
|
506 F1B4 20 7B F2 jsr BootCassette
|
|
507 F1B7 4C C3 F1 jmp postcasboot
|
|
508
|
|
509 F1BA reinitcas:
|
|
510 F1BA A9 02 lda #2
|
|
511 F1BC 24 09 bit boot?
|
|
512 F1BE F0 03 beq postcasboot
|
|
513 F1C0 20 18 F2 jsr InitCassetteBoot
|
|
514 F1C3 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 F1C3 A5 08 lda warmst
|
|
527 F1C5 D0 1D bne reinitDisk
|
|
528
|
|
529 .if !_KERNEL_XLXE
|
|
530
|
|
531 ;check if we have cart B
|
|
532 F1C7 A5 07 lda tstdat
|
|
533 F1C9 D0 06 bne have_cart_b
|
|
534
|
|
535 ;no cart B -- if no cart A either, do disk boot
|
|
536 F1CB A6 06 ldx tramsz ;cart A
|
|
537 F1CD F0 0F beq boot_disk
|
|
538 F1CF D0 07 bne have_cart_a
|
|
539
|
|
540 F1D1 have_cart_b:
|
|
541 ;have cart B - grab boot disk flag (bit 0)
|
|
542 F1D1 AD FD 9F lda $9ffd
|
|
543
|
|
544 ;merge cart A's flags if it is present
|
|
545 F1D4 A6 06 ldx tramsz
|
|
546 F1D6 F0 03 beq no_cart_a
|
|
547
|
|
548 F1D8 have_cart_a:
|
|
549 F1D8 0D FD BF ora $bffd
|
|
550
|
|
551 F1DB no_cart_a:
|
|
552 ;skip disk boot if neither cart requested it
|
|
553 F1DB 4A lsr
|
|
554 F1DC 90 0E bcc skip_disk_boot
|
|
555
|
|
556 .else
|
|
557
|
|
558 ;check for cart A requesting boot
|
|
559 lda tramsz
|
|
560 beq boot_disk
|
|
561
|
|
562 ;have cart A - boot disk if requested
|
|
563 lda $bffd
|
|
564 lsr
|
|
565 bcc skip_disk_boot
|
|
566
|
|
567 .endif
|
|
568
|
|
569 F1DE boot_disk:
|
|
570 F1DE 20 1C F2 jsr BootDisk
|
|
571 F1E1 4C EC F1 jmp post_disk_boot
|
|
572
|
|
573 F1E4 reinitDisk:
|
|
574 F1E4 A5 09 lda boot?
|
|
575 F1E6 4A lsr
|
|
576 F1E7 90 03 bcc skip_disk_boot
|
|
577 F1E9 20 15 F2 jsr InitDiskBoot
|
|
578
|
|
579 F1EC 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 lda warmst
|
|
585 bne reinit_handlers
|
|
586 jsr PHStartupPoll
|
|
587 jmp post_reinit
|
|
588 reinit_handlers:
|
|
589 jsr PHReinitHandlers
|
|
590 post_reinit:
|
|
591 .endif
|
|
592
|
|
593 F1EC skip_disk_boot:
|
|
594
|
|
595 ;-------------------------------------------------------------------------
|
|
596 ; H. same as steps 19 and 20
|
|
597 ; 19. reset coldstart flag
|
|
598
|
|
599 F1EC A2 00 ldx #0
|
|
600 F1EE 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 F1F1 A9 04 lda #$04
|
|
615 F1F3 A6 06 ldx tramsz
|
|
616 F1F5 F0 08 beq NoBootCartA
|
|
617 F1F7 2C FD BF bit $bffd
|
|
618 F1FA F0 03 6C FA BF seq:jmp ($bffa)
|
|
619 F1FF NoBootCartA:
|
|
620
|
|
621 ; try to boot cart B
|
|
622 F1FF A6 07 ldx tstdat
|
|
623 F201 F0 08 beq NoBootCartB
|
|
624 F203 2C FD 9F bit $9ffd
|
|
625 F206 F0 03 6C FA 9F seq:jmp ($9ffa)
|
|
626 F20B NoBootCartB:
|
|
627
|
|
628 ; run blackboard
|
|
629 F20B 6C 0A 00 jmp (dosvec)
|
|
630
|
|
631 F20E InitCartA:
|
|
632 F20E 6C FE BF jmp ($bffe)
|
|
633
|
|
634 F211 InitCartB:
|
|
635 F211 6C FE 9F jmp ($9ffe)
|
|
636
|
|
637 F214 ScreenEditorName:
|
|
638 F214 45 dta c"E"
|
|
639
|
|
640 .endp
|
|
641
|
|
642 ;==============================================================================
|
|
643 F215 .proc InitDiskBoot
|
|
644 F215 6C 0C 00 jmp (dosini)
|
|
645 .endp
|
|
646
|
|
647 F218 .proc InitCassetteBoot
|
|
648 .endp
|
|
649 F218 6C 02 00 jmp (casini)
|
|
650
|
|
651 ;==============================================================================
|
|
652
|
|
653 F21B EA nop
|
|
264 .endif
|
|
265
|
|
266 F21C 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 F21C .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 F21C A9 53 lda #$53
|
|
21 F21E 8D 02 03 sta dcomnd
|
|
22 F221 A2 01 ldx #1
|
|
23 F223 8E 01 03 stx dunit
|
|
24 F226 20 53 E4 jsr dskinv
|
|
25 F229 30 3C bmi xit
|
|
26
|
|
27 ;read first sector to $0400
|
|
28 F22B A2 01 ldx #1
|
|
29 F22D 8E 01 03 stx dunit
|
|
30 F230 8E 0A 03 stx daux1
|
|
31 F233 CA dex
|
|
32 F234 8E 04 03 stx dbuflo
|
|
33 F237 8E 0B 03 stx daux2
|
|
34 F23A A9 52 8D 02 03 mva #$52 dcomnd
|
|
35 F23F A9 04 8D 05 03 mva #$04 dbufhi
|
|
36 F244 20 53 E4 jsr dskinv
|
|
37 F247 30 1A bmi fail
|
|
38
|
|
39 F249 sector1_ok:
|
|
40 F249 A2 0C ldx #dosini
|
|
41 F24B 20 B6 F2 jsr BootInitHeaders
|
|
42
|
|
43 ;load remaining sectors
|
|
44 F24E sectorloop:
|
|
45 ;copy sector from $0400 to destination (required by Ankh; see above)
|
|
46 ;bump destination address for next sector copy
|
|
47 F24E 20 E3 F2 jsr BootCopyBlock
|
|
48
|
|
49 ;exit if this was the last sector (note that 0 means to load 256 sectors!)
|
|
50 F251 CE 41 02 dec dbsect
|
|
51 F254 F0 18 beq loaddone
|
|
52
|
|
53 ;increment sector (yes, this can overflow to 256)
|
|
54 F256 EE 0A 03 D0 03 EE + inw daux1
|
|
55
|
|
56 ;read next sector
|
|
57 F25E 20 53 E4 jsr dskinv
|
|
58
|
|
59 ;keep going if we succeeded
|
|
60 F261 10 EB bpl sectorloop
|
|
61
|
|
62 ;read failed
|
|
63 F263 fail:
|
|
64 F263 C0 8A cpy #SIOErrorTimeout
|
|
65 F265 D0 01 bne failmsg
|
|
66 F267 xit:
|
|
67 F267 60 rts
|
|
68
|
|
69 F268 failmsg:
|
|
70 .if _KERNEL_USE_BOOT_SCREEN
|
|
71 st_loop:
|
|
72 lda portb
|
|
73 eor #$80
|
|
74 sta portb
|
|
75 bmi sector1_ok
|
|
76 jsr BootScreen.boot_entry
|
|
77 jmp st_loop
|
|
78 .else
|
|
79 F268 20 F8 F2 jsr BootShowError
|
|
80 F26B 4C 1C F2 jmp BootDisk
|
|
81 .endif
|
|
82
|
|
83 F26E loaddone:
|
|
84 F26E 20 D3 F2 jsr BootRunLoader
|
|
85 F271 B0 F5 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 F273 20 15 F2 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 F276 A9 01 85 09 mva #1 boot?
|
|
97 F27A 60 rts
|
|
98 .endp
|
|
99
|
|
100
|
|
101 ;============================================================================
|
|
102
|
|
103 F27B .proc BootCassette
|
|
104 ;set continuous mode -- must do this as CSOPIV doesn't
|
|
105 F27B A9 80 lda #$80
|
|
106 F27D 85 3E sta ftype
|
|
107
|
|
108 ;open cassette device
|
|
109 F27F 20 7D E4 jsr csopiv
|
|
110
|
|
111 ;read first block
|
|
112 F282 20 7A E4 jsr rblokv
|
|
113 F285 30 24 bmi load_failure
|
|
114
|
|
115 F287 A2 02 ldx #casini
|
|
116 F289 20 B6 F2 jsr BootInitHeaders
|
|
117
|
|
118 F28C block_loop:
|
|
119 ;copy 128 bytes from CASBUF+3 ($0400) to destination
|
|
120 ;update destination pointer
|
|
121 F28C 20 E3 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 F28F 20 7A E4 jsr rblokv
|
|
127 F292 30 17 bmi load_failure
|
|
128
|
|
129 F294 CE 41 02 dec dbsect
|
|
130 F297 D0 F3 bne block_loop
|
|
131
|
|
132 ;run loader
|
|
133 F299 20 D3 F2 jsr BootRunLoader
|
|
134
|
|
135 ;run cassette init routine
|
|
136 F29C 20 18 F2 jsr InitCassetteBoot
|
|
137
|
|
138 ;clear cassette boot key flag
|
|
139 F29F A9 00 lda #0
|
|
140 F2A1 8D E9 03 sta ckey
|
|
141
|
|
142 ;set cassette boot flag
|
|
143 F2A4 A9 02 85 09 mva #2 boot?
|
|
144
|
|
145 ;run application
|
|
146 F2A8 6C 0A 00 jmp (dosvec)
|
|
147
|
|
148 F2AB load_failure:
|
|
149 F2AB A9 00 lda #0
|
|
150 F2AD 8D E9 03 sta ckey
|
|
151 F2B0 20 B1 EE jsr CassetteClose
|
|
152 F2B3 4C F8 F2 jmp BootShowError
|
|
153 .endp
|
|
154
|
|
155 ;============================================================================
|
|
156 F2B6 .proc BootInitHeaders
|
|
157 ;copy the first four bytes to DFLAGS, DBSECT, and BOOTAD
|
|
158 F2B6 A0 FC ldy #$fc
|
|
159 F2B8 B9 04 03 99 44 01 + mva:rne $0400-$fc,y dflags-$fc,y+
|
|
160
|
|
161 ;copy boot address in BOOTAD to BUFADR
|
|
162 F2C1 85 16 sta bufadr+1
|
|
163 F2C3 AD 42 02 lda bootad
|
|
164 F2C6 85 15 sta bufadr
|
|
165
|
|
166 ;copy init vector
|
|
167 F2C8 AD 04 04 95 00 AD + mwa $0404 0,x
|
|
168 F2D2 60 rts
|
|
169 .endp
|
|
170
|
|
171 ;============================================================================
|
|
172 F2D3 .proc BootRunLoader
|
|
173 ;loader is at load address + 6
|
|
174 F2D3 AD 42 02 lda bootad
|
|
175 F2D6 18 69 05 add #$05
|
|
176 F2D9 AA tax
|
|
177 F2DA AD 43 02 lda bootad+1
|
|
178 F2DD 69 00 adc #0
|
|
179 F2DF 48 pha
|
|
180 F2E0 8A txa
|
|
181 F2E1 48 pha
|
|
182 F2E2 60 rts
|
|
183 .endp
|
|
184
|
|
185 ;============================================================================
|
|
186 F2E3 .proc BootCopyBlock
|
|
187 F2E3 A0 7F ldy #$7f
|
|
188 F2E5 B9 00 04 91 15 88 + mva:rpl $0400,y (bufadr),y-
|
|
189
|
|
190 F2ED A5 15 lda bufadr
|
|
191 F2EF 49 80 eor #$80
|
|
192 F2F1 85 15 sta bufadr
|
|
193 F2F3 30 02 E6 16 smi:inc bufadr+1
|
|
194 F2F7 60 rts
|
|
195 .endp
|
|
196
|
|
197 ;============================================================================
|
|
198
|
|
199 F2F8 .proc BootShowError
|
|
200 F2F8 A2 F5 ldx #$f5
|
|
201 F2FA msgloop:
|
|
202 F2FA 8A txa
|
|
203 F2FB 48 pha
|
|
204 F2FC BD 13 F2 lda errormsg-$f5,x
|
|
205 F2FF 20 A8 FA jsr EditorPutByte
|
|
206 F302 68 pla
|
|
207 F303 AA tax
|
|
208 F304 E8 inx
|
|
209 F305 D0 F3 bne msgloop
|
|
210 F307 60 rts
|
|
211
|
|
212 F308 errormsg:
|
|
213 F308 42 4F 4F 54 20 45 + dta 'BOOT ERROR',$9B
|
|
214 .endp
|
|
267 F313 _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 $F313 -> $032D($0301) Monitor routines
|
|
3 = F313 .def ?@_kernel_lastpt = *
|
|
Source: source/main.xasm
|
|
268
|
|
269 F313 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 = F9C7 ScreenHeightsSplit = ScreenWidths
|
|
178 ; dta 10, 20, 40, 80, 160
|
|
179
|
|
180 = F9C8 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 _SCREEN_TABLES_3
|
|
235 _SCREEN_TABLES_2
|
|
236 _SCREEN_TABLES_1
|
|
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 F313 _KERNEL_REPORT_MODULE_PAD_ADJUST [$f3f6-8]-*
|
|
Macro: _KERNEL_REPORT_MODULE_PAD_ADJUST [Source: source/main.xasm]
|
|
1 = F3EE .def ?@_kernel_lastpt = ?@_kernel_lastpt + [$F3F6-8]-*
|
|
Source: source/Shared/screen.s
|
|
250 .endif
|
|
251
|
|
252 F313 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 16 FE 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 26 FE ldy ScreenHeightShifts,x
|
|
342 F437 BE 36 FE ldx ScreenHeights,y
|
|
343 F43A 0A asl
|
|
344 F43B 10 03 BE C7 F9 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 06 FE 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 F6 FD 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 16 FE 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 ldy #1
|
|
409 cpy fine ;clear carry to alloc +1 byte if fine scrolling is enabled
|
|
410 .endif
|
|
411
|
|
412 F482 65 70 adc rowac ;allocate dl bytes (note that carry is set!)
|
|
413 F484 8D E5 02 sta memtop
|
|
414 F487 85 70 sta rowac
|
|
415 F489 8D 30 02 sta sdlstl
|
|
416
|
|
417 ;check if we're below APPMHI
|
|
418 F48C E4 0F cpx appmhi+1
|
|
419 F48E 90 BC bcc alloc_fail
|
|
420 F490 D0 04 bne alloc_ok
|
|
421 F492 C5 0E cmp appmhi
|
|
422 F494 90 B6 bcc alloc_fail
|
|
423
|
|
424 F496 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 F496 CE E5 02 dec memtop
|
|
428
|
|
429 ;set up text window address (-160 from top)
|
|
430 F499 A6 6A ldx ramtop
|
|
431 F49B CA dex
|
|
432 F49C 8E 95 02 stx txtmsc+1
|
|
433 F49F 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 F4A4 08 php
|
|
438 F4A5 78 sei
|
|
439 F4A6 0A asl ;!! - A = $C0
|
|
440 F4A7 05 10 ora pokmsk
|
|
441 F4A9 85 10 sta pokmsk
|
|
442 F4AB 8D 0E D2 sta irqen
|
|
443 F4AE 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 F4AF A0 18 ldy #24
|
|
451 F4B1 8C BF 02 sty botscr
|
|
452
|
|
453 ;init colors -- note that we do NOT overwrite pcolr0-3!
|
|
454 F4B4 A0 05 ldy #5
|
|
455 F4B6 B9 88 F5 99 C3 02 + mva:rne standard_colors-1,y color0-1,y-
|
|
456
|
|
457 F4BF 8C F0 02 sty crsinh ;!! - Y=0 for this and for write index
|
|
458
|
|
459 ;add 24 blank lines
|
|
460 F4C2 A9 70 lda #$70
|
|
461 F4C4 A2 03 ldx #3
|
|
462 F4C6 20 6D F5 jsr write_repeat
|
|
463
|
|
464 ;override COLOR4 (background) to $06 for GR.11 so it isn't dark
|
|
465 F4C9 A5 57 lda dindex
|
|
466 F4CB C9 0B cmp #11
|
|
467 F4CD D0 05 bne not_gr11
|
|
468 F4CF A9 06 lda #$06
|
|
469 F4D1 8D C8 02 sta color4
|
|
470 F4D4 not_gr11:
|
|
471
|
|
472 ;add in the main screen
|
|
473 F4D4 20 32 F5 jsr setup_display
|
|
474
|
|
475 ;save off the DL ptr
|
|
476 F4D7 84 7E sty countr
|
|
477
|
|
478 ;clear it if necessary
|
|
479 F4D9 20 82 F5 jsr try_clear
|
|
480
|
|
481 ;check if we are doing a split
|
|
482 F4DC 24 68 bit frmadr
|
|
483 F4DE 50 12 bvc nosplit
|
|
484
|
|
485 ;change text screen height to four lines
|
|
486 F4E0 A2 04 ldx #4
|
|
487 F4E2 8E BF 02 stx botscr
|
|
488
|
|
489 ;swap to the text screen
|
|
490 F4E5 20 0A F9 jsr EditorSwapToText
|
|
491
|
|
492 ;add text screen dlist
|
|
493 F4E8 A4 7E ldy countr
|
|
494 F4EA 20 32 F5 jsr setup_display
|
|
495 F4ED 84 7E sty countr
|
|
496
|
|
497 ;clear the split screen
|
|
498 F4EF 20 82 F5 jsr try_clear
|
|
499
|
|
500 F4F2 nosplit:
|
|
501 F4F2 A9 02 8D F3 02 mva #2 chact
|
|
502
|
|
503 ;init tab map to every 8 columns
|
|
504 F4F7 A2 0F ldx #15
|
|
505 F4F9 4A lsr ;!! A=1
|
|
506 F4FA 9D A2 02 CA D0 FA sta:rne tabmap-1,x-
|
|
507
|
|
508 ;reset line status
|
|
509 F500 86 6B stx bufcnt
|
|
510
|
|
511 ;init character set
|
|
512 F502 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 bit frmadr
|
|
517 sne:ldx #$40
|
|
518 .else
|
|
519 F507 A2 40 ldx #$40
|
|
520 .endif
|
|
521 F509 8E 0E D4 stx nmien
|
|
522
|
|
523 ;terminate display list with jvb
|
|
524 F50C A4 7E ldy countr
|
|
525 F50E A2 70 ldx #rowac
|
|
526 F510 A9 41 lda #$41
|
|
527 F512 20 74 F5 jsr write_with_zp_address
|
|
528
|
|
529 ;init display list and playfield dma
|
|
530 F515 AD 2F 02 lda sdmctl
|
|
531 F518 09 22 ora #$22
|
|
532 F51A 8D 2F 02 sta sdmctl
|
|
533
|
|
534 ;wait for screen to establish (necessary for Timewise splash screen to render)
|
|
535 F51D A5 14 lda rtclok+2
|
|
536 F51F 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 F523 A5 2B lda icax2z
|
|
544 F525 29 0F and #$0f
|
|
545 F527 D0 03 bne no_cursor
|
|
546
|
|
547 ;show cursor
|
|
548 F529 20 82 F6 jsr ScreenPutByte.recompute_show_cursor_exit
|
|
549 F52C no_cursor:
|
|
550 ;swap back to main context
|
|
551 F52C 20 61 FD jsr EditorSwapToScreen_Y1
|
|
552
|
|
553 ;exit
|
|
554 F52F A2 00 ldx #0 ;required by Qix (v3)
|
|
555 F531 60 rts
|
|
556
|
|
557
|
|
558 ;--------------------------------------------------------
|
|
559 F532 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 F532 A6 57 ldx dindex
|
|
564 F534 BD 16 FE lda ScreenModeTable,x
|
|
565 F537 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 ldx dindex
|
|
570 bne nofine
|
|
571 ldx fine
|
|
572 beq nofine
|
|
573 ora #$20
|
|
574 nofine:
|
|
575 .endif
|
|
576
|
|
577 F539 48 pha
|
|
578 F53A 09 40 ora #$40
|
|
579 F53C A2 58 ldx #savmsc
|
|
580 F53E 20 74 F5 jsr write_with_zp_address
|
|
581
|
|
582 ;retrieve row count
|
|
583 F541 A6 69 ldx frmadr+1
|
|
584 F543 A5 57 lda dindex
|
|
585 F545 D0 03 AE BF 02 sne:ldx botscr
|
|
586
|
|
587 ;dec row count since we already did the LMS
|
|
588 F54A CA dex
|
|
589 F54B 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 cmp #$22
|
|
595 beq dofine
|
|
596 .endif
|
|
597
|
|
598 ;check if this is a split mode
|
|
599 F54C C9 0E cmp #$0e
|
|
600 F54E 90 1D bcc no_lms_split
|
|
601
|
|
602 ;yes it is -- write 93 lines
|
|
603 F550 A2 5D ldx #93
|
|
604 F552 20 6D F5 jsr write_repeat
|
|
605
|
|
606 ;write LMS to jump over 4K boundary
|
|
607 F555 48 pha
|
|
608 F556 09 40 ora #$40
|
|
609 F558 91 70 C8 sta (rowac),y+
|
|
610 F55B A9 00 lda #0
|
|
611 F55D 91 70 C8 sta (rowac),y+
|
|
612 F560 A5 59 lda savmsc+1
|
|
613 F562 69 0E adc #$0f-1 ;!! - C=1 from bcc above
|
|
614 F564 91 70 C8 sta (rowac),y+
|
|
615
|
|
616 ;set up to write 95 fewer lines (note that carry is cleared)
|
|
617 F567 A5 69 lda frmadr+1
|
|
618 F569 E9 5E sbc #94
|
|
619 F56B AA tax
|
|
620 F56C 68 pla
|
|
621
|
|
622 ;write mode lines and return
|
|
623 F56D no_lms_split:
|
|
624 F56D write_repeat:
|
|
625 F56D 91 70 C8 sta (rowac),y+
|
|
626 F570 CA dex
|
|
627 F571 D0 FA bne write_repeat
|
|
628 F573 no_clear:
|
|
629 F573 60 rts
|
|
630
|
|
631 .if _KERNEL_XLXE
|
|
632 dofine:
|
|
633 ;write the regular lines (22 or 2)
|
|
634 dex
|
|
635 jsr write_repeat
|
|
636
|
|
637 ;write DLI line
|
|
638 ora #$80
|
|
639 sta (rowac),y+
|
|
640
|
|
641 ;write non-scrolled line
|
|
642 and #$5f
|
|
643 sta (rowac),y+
|
|
644
|
|
645 ;indicate to mainline that DLIs should be turned on
|
|
646 inc frmadr
|
|
647
|
|
648 ;set up DLI routine
|
|
649 ldx #<ScreenFineScrollDLI
|
|
650 lda #>ScreenFineScrollDLI
|
|
651 write_vdslst:
|
|
652 stx vdslst
|
|
653 sta vdslst+1
|
|
654 rts
|
|
655 .endif
|
|
656
|
|
657 ;--------------------------------------------------------
|
|
658 F574 write_with_zp_address:
|
|
659 F574 91 70 C8 sta (rowac),y+
|
|
660 F577 B5 00 lda 0,x
|
|
661 F579 91 70 C8 sta (rowac),y+
|
|
662 F57C B5 01 lda 1,x
|
|
663 F57E A2 01 ldx #1
|
|
664 F580 D0 EB bne write_repeat ;!! - unconditional
|
|
665
|
|
666 F582 try_clear:
|
|
667 F582 24 68 bit frmadr
|
|
668 F584 30 ED bmi no_clear
|
|
669 F586 4C 17 F8 jmp ScreenClear
|
|
670
|
|
671 ;--------------------------------------------------------
|
|
672 F589 standard_colors:
|
|
673 F589 28 dta $28
|
|
674 F58A CA dta $ca
|
|
675 F58B 94 dta $94
|
|
676 F58C 46 dta $46
|
|
677 = F58D .def :ScreenBitposFlipTab
|
|
678 F58D 00 dta $00 ;!! - shared value between tables
|
|
679 F58E 01 dta $01
|
|
680 F58F 03 dta $03
|
|
681 F590 07 dta $07
|
|
682
|
|
683 .endp
|
|
684
|
|
685 ;==========================================================================
|
|
686 F591 .proc ScreenInit
|
|
687 F591 AD E6 02 85 6A mva memtop+1 ramtop
|
|
688
|
|
689 .ifdef _KERNEL_816
|
|
690 stz colrsh
|
|
691 .else
|
|
692 F596 A9 00 85 4F mva #0 colrsh
|
|
693 .endif
|
|
694
|
|
695 F59A A9 FE 85 4E mva #$FE drkmsk
|
|
696 F59E 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 F59F .proc ScreenGetByte
|
|
711 F59F 20 C7 F8 jsr ScreenCheckPosition
|
|
712 F5A2 30 3A bmi xit
|
|
713
|
|
714 ;compute addressing
|
|
715 F5A4 A4 54 ldy rowcrs
|
|
716 F5A6 20 42 F9 jsr ScreenComputeToAddrX0
|
|
717 F5A9 A5 55 lda colcrs
|
|
718 F5AB A6 57 ldx dindex
|
|
719 F5AD BC D2 F9 ldy ScreenEncodingTab,x
|
|
720 F5B0 59 8D F5 eor ScreenBitposFlipTab,y
|
|
721 F5B3 AA tax
|
|
722 F5B4 A5 56 lda colcrs+1
|
|
723 F5B6 20 8B F9 jsr ScreenSetupPixelAddr.phase2
|
|
724
|
|
725 ;retrieve byte containing pixel
|
|
726 F5B9 A4 6F ldy shfamt
|
|
727 F5BB B1 66 lda (toadr),y
|
|
728
|
|
729 ;shift down
|
|
730 F5BD 20 78 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 F5C0 0A asl
|
|
739 F5C1 08 php
|
|
740 F5C2 10 02 49 40 spl:eor #$40 ;00>20, 20>40, 40>60, 60>40
|
|
741 F5C6 69 40 adc #$40 ;00>20, 20>40, 40>00, 60>60
|
|
742 F5C8 28 plp
|
|
743 F5C9 6A ror
|
|
744
|
|
745 ;mask using right-justified pixel mask for mode
|
|
746 F5CA A6 57 ldx dindex
|
|
747 F5CC BC D2 F9 ldy ScreenEncodingTab,x
|
|
748 F5CF 39 E2 F9 and ScreenPixelMasks,y
|
|
749
|
|
750 ;advance to next position
|
|
751 F5D2 A6 57 ldx dindex
|
|
752 F5D4 F0 03 beq mode0
|
|
753 F5D6 4C A3 F9 jmp ScreenAdvancePosNonMode0
|
|
754 F5D9 mode0:
|
|
755 F5D9 20 D6 FD jsr ScreenAdvancePosMode0
|
|
756 F5DC A0 01 ldy #1
|
|
757 F5DE xit:
|
|
758 F5DE 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 F5DF .proc ScreenPutByte
|
|
785 F5DF 8D FB 02 sta atachr
|
|
786 F5E2 20 C7 F8 jsr ScreenCheckPosition
|
|
787 F5E5 30 0C bmi error
|
|
788
|
|
789 ;check for screen clear
|
|
790 F5E7 AD FB 02 lda atachr
|
|
791 F5EA C9 7D cmp #$7d
|
|
792 F5EC D0 0E bne not_clear_2
|
|
793 F5EE 20 17 F8 jsr ScreenClear
|
|
794 F5F1 A0 01 ldy #1
|
|
795 F5F3 error:
|
|
796 F5F3 60 rts
|
|
797
|
|
798 F5F4 graphics_eol:
|
|
799 F5F4 4C BC F9 jmp ScreenAdvancePosNonMode0.graphics_eol
|
|
800
|
|
801 ;*** ENTRY POINT FROM EDITOR FOR ESC HANDLING ***
|
|
802 F5F7 not_clear:
|
|
803 F5F7 20 C7 F8 jsr ScreenCheckPosition
|
|
804 F5FA 30 F7 bmi error
|
|
805
|
|
806 F5FC not_clear_2:
|
|
807 ;set old position now (used by setup code for plot pixel)
|
|
808 F5FC 20 CC FD jsr ScreenSetLastPosition
|
|
809
|
|
810 ;restore char
|
|
811 F5FF AD FB 02 lda atachr
|
|
812
|
|
813 ;check if we're in gr.0
|
|
814 F602 A6 57 ldx dindex
|
|
815 F604 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 F606 C9 9B cmp #$9b
|
|
820 F608 F0 EA beq graphics_eol
|
|
821
|
|
822 ;check for display suspend (ctrl+1) and wait until it is cleared
|
|
823 F60A AE FF 02 D0 FB ldx:rne ssflag
|
|
824
|
|
825 ;fold the pixel, compute masks, and convert ATASCII to Internal
|
|
826 F60F 20 9B F6 jsr ScreenFoldColor
|
|
827 F612 48 pha
|
|
828
|
|
829 ;compute addressing and shift mask
|
|
830 F613 20 73 F9 jsr ScreenSetupPlotPixel
|
|
831
|
|
832 F616 68 pla
|
|
833 F617 A4 6F ldy shfamt
|
|
834 F619 51 66 eor (toadr),y
|
|
835 F61B 25 6E and bitmsk
|
|
836 F61D 51 66 eor (toadr),y
|
|
837 F61F 91 66 sta (toadr),y
|
|
838
|
|
839 ;advance cursor position and exit
|
|
840 F621 4C A3 F9 jmp ScreenAdvancePosNonMode0
|
|
841
|
|
842 F624 mode_0:
|
|
843 ;check for EOL, which bypasses the ESC check
|
|
844 F624 C9 9B cmp #$9b
|
|
845 F626 D0 18 bne not_eol
|
|
846
|
|
847 ;it's an EOL
|
|
848 F628 A5 52 lda lmargn
|
|
849 F62A 85 55 sta colcrs
|
|
850 F62C E6 54 inc rowcrs
|
|
851 F62E A5 54 lda rowcrs
|
|
852 F630 CD BF 02 cmp botscr
|
|
853 F633 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 F635 AE BF 02 ldx botscr
|
|
859 F638 86 54 stx rowcrs
|
|
860
|
|
861 F63A 20 BC FC jsr EditorDeleteLine0
|
|
862 F63D noywrap:
|
|
863 F63D 4C 82 F6 jmp recompute_show_cursor_exit
|
|
864
|
|
865 F640 not_eol:
|
|
866 ;check for display suspend (ctrl+1) and wait until it is cleared
|
|
867 F640 AE FF 02 D0 FB ldx:rne ssflag
|
|
868
|
|
869 F645 48 pha
|
|
870 F646 20 B0 FC jsr EditorRecomputeCursorAddr
|
|
871 F649 68 pla
|
|
872 F64A 20 B8 F6 jsr ScreenConvertATASCIIToInternal
|
|
873
|
|
874 ;plot character
|
|
875 F64D A0 00 ldy #0
|
|
876 F64F 91 5E sta (oldadr),y
|
|
877
|
|
878 ;inc pos
|
|
879 F651 E6 5E D0 02 E6 5F inw oldadr
|
|
880 F657 20 D6 FD jsr ScreenAdvancePosMode0
|
|
881
|
|
882 ;check if we've gone beyond the right margin
|
|
883 F65A B0 29 bcs nowrap
|
|
884
|
|
885 ;check if we're beyond the bottom of the screen
|
|
886 F65C A5 54 lda rowcrs
|
|
887 F65E CD BF 02 cmp botscr
|
|
888 F661 90 12 bcc no_scroll
|
|
889
|
|
890 ;yes -- scroll up
|
|
891 F663 20 BC FC jsr EditorDeleteLine0
|
|
892
|
|
893 ;check if we can extend the current logical line -- 3 rows max.
|
|
894 F666 20 88 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 F669 20 34 FD jsr EditorGetCurLogicalLineInfo
|
|
902 F66C 59 B2 02 eor logmap,y
|
|
903 F66F 99 B2 02 sta logmap,y
|
|
904
|
|
905 F672 4C 82 F6 jmp post_scroll
|
|
906
|
|
907 F675 no_scroll:
|
|
908 ;check if we can extend the current logical line -- 3 rows max.
|
|
909 F675 20 88 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 F678 A5 54 lda rowcrs
|
|
915 F67A 20 43 FD jsr EditorTestLogicalLineBit
|
|
916 F67D F0 03 beq post_scroll
|
|
917
|
|
918 ;yup, insert a physical line
|
|
919 F67F 20 5A F8 jsr ScreenInsertPhysLine
|
|
920
|
|
921 F682 recompute_show_cursor_exit:
|
|
922 F682 post_scroll:
|
|
923 F682 20 B0 FC jsr EditorRecomputeCursorAddr
|
|
924 F685 nowrap:
|
|
925 F685 4C E5 FD jmp ScreenShowCursorAndXitOK
|
|
926
|
|
927 F688 check_extend:
|
|
928 F688 A6 54 ldx rowcrs
|
|
929 F68A CA dex
|
|
930 F68B 8A txa
|
|
931 F68C 20 4C FD jsr EditorPhysToLogicalRow
|
|
932
|
|
933 .ifdef _KERNEL_816
|
|
934 inc
|
|
935 inc
|
|
936 .else
|
|
937 F68F 18 clc
|
|
938 F690 69 02 adc #2
|
|
939 .endif
|
|
940
|
|
941 F692 C5 54 cmp rowcrs
|
|
942 F694 90 01 60 scc:rts
|
|
943 F697 68 pla
|
|
944 F698 68 pla
|
|
945 F699 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 F69B .proc ScreenFoldColor
|
|
969 F69B A6 57 ldx dindex
|
|
970 F69D BC D2 F9 ldy ScreenEncodingTab,x ;0 = 8-bit, 1 = 4-bit, 2 = 2-bit, 3 = 1-bit
|
|
971 F6A0 BE E6 F9 86 77 mvx ScreenPixelMasks+4,y deltac
|
|
972 F6A5 BE E2 F9 8E A0 02 mvx ScreenPixelMasks,y dmask
|
|
973 F6AB 30 0B bmi fold_byte
|
|
974 F6AD 2D A0 02 and dmask
|
|
975 F6B0 19 9F FD ora ScreenEncodingOffsetTable-1,y
|
|
976 F6B3 AA tax
|
|
977 F6B4 BD A3 FD lda ScreenEncodingTable,x
|
|
978 F6B7 60 rts
|
|
979
|
|
980 F6B8 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 = F6B8 .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 F6B8 0A asl
|
|
1001 F6B9 08 php
|
|
1002 F6BA E9 3F sbc #$3f ;00>60, 20>00, 40>20, 60>40
|
|
1003 F6BC 10 02 49 40 spl:eor #$40 ;00>40, 20>00, 40>20, 60>60
|
|
1004 F6C0 28 plp
|
|
1005 F6C1 6A ror
|
|
1006 F6C2 60 rts
|
|
1007 .endp
|
|
1008
|
|
1009
|
|
1010 ;==========================================================================
|
|
1011 F6C3 .proc ScreenSpecial
|
|
1012 F6C3 A5 22 lda iccomz
|
|
1013 F6C5 C9 11 cmp #$11
|
|
1014 F6C7 F0 05 beq ScreenDrawLineFill ;draw line
|
|
1015 F6C9 C9 12 cmp #$12
|
|
1016 F6CB F0 01 beq ScreenDrawLineFill ;fill
|
|
1017 F6CD 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 F6CE .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 F6CE AD FD 02 lda fildat
|
|
1067 F6D1 20 9B F6 jsr ScreenFoldColor
|
|
1068 F6D4 8D BC 02 sta hold4
|
|
1069 F6D7 AD FB 02 lda atachr
|
|
1070 F6DA 20 9B F6 jsr ScreenFoldColor
|
|
1071 F6DD 85 51 sta hold1
|
|
1072
|
|
1073 F6DF 20 73 F9 jsr ScreenSetupPlotPixel
|
|
1074
|
|
1075 ;compute screen pitch
|
|
1076 F6E2 A0 01 ldy #1
|
|
1077 F6E4 20 4C F9 jsr ScreenComputeRangeSize
|
|
1078 F6E7 85 78 sta deltac+1
|
|
1079 F6E9 AA tax
|
|
1080 F6EA A0 00 ldy #0
|
|
1081
|
|
1082 ;compute abs(dy) and sign(dy)
|
|
1083 F6EC A5 54 lda rowcrs
|
|
1084 F6EE 38 E5 5A sub oldrow
|
|
1085 F6F1 B0 0C bcs going_down
|
|
1086 F6F3 49 FF eor #$ff ;take abs(dy)
|
|
1087 F6F5 69 01 adc #1 ;
|
|
1088 ;negate screen pitch
|
|
1089 F6F7 48 pha
|
|
1090 F6F8 8A txa
|
|
1091 F6F9 49 FF eor #$ff
|
|
1092 F6FB AA tax
|
|
1093 F6FC E8 inx
|
|
1094 F6FD 88 dey
|
|
1095 F6FE 68 pla
|
|
1096 F6FF going_down:
|
|
1097 F6FF 86 70 stx rowac
|
|
1098 F701 85 76 sta deltar
|
|
1099 F703 84 71 sty rowac+1
|
|
1100
|
|
1101 ;;##TRACE "dy = %d" db(deltar)
|
|
1102
|
|
1103 ;compute abs(dx) and sign(dx)
|
|
1104 F705 A2 00 ldx #0
|
|
1105 F707 A5 55 lda colcrs
|
|
1106 F709 38 E5 5B sub oldcol
|
|
1107 F70C 85 72 sta colac
|
|
1108 F70E A5 56 lda colcrs+1
|
|
1109 F710 E5 5C sbc oldcol+1
|
|
1110 F712 B0 10 bcs going_right
|
|
1111 F714 49 FF eor #$ff
|
|
1112 F716 A8 tay
|
|
1113 F717 A5 72 lda colac
|
|
1114 F719 49 FF eor #$ff
|
|
1115 F71B 69 01 adc #1
|
|
1116 F71D 85 72 sta colac
|
|
1117 F71F 98 tya
|
|
1118 F720 69 00 adc #0
|
|
1119 F722 A2 CC ldx #left_shift_8-right_shift_8
|
|
1120 F724 going_right:
|
|
1121 F724 85 73 sta colac+1
|
|
1122
|
|
1123 ;;##TRACE "dx = %d" dw(colac)
|
|
1124
|
|
1125 ;set up x shift routine
|
|
1126 F726 8A txa
|
|
1127 F727 A6 57 ldx dindex
|
|
1128 F729 BC D2 F9 ldy ScreenEncodingTab,x
|
|
1129 F72C 18 clc
|
|
1130 F72D 79 7A F7 adc shift_lo_tab,y
|
|
1131 F730 85 64 sta adress
|
|
1132 F732 A9 F7 lda #>left_shift_8
|
|
1133 F734 85 65 sta adress+1
|
|
1134 F736 85 75 sta endpt+1
|
|
1135
|
|
1136 ;set up x fill shift routine
|
|
1137 F738 B9 7A F7 lda shift_lo_tab,y
|
|
1138 F73B 18 clc
|
|
1139 F73C 69 D9 adc #fill_right_8-right_shift_8
|
|
1140 F73E 85 74 sta endpt
|
|
1141
|
|
1142 ;compute initial error accumulator in frmadr (dx-dy)
|
|
1143 F740 A6 72 ldx colac
|
|
1144 F742 8A txa
|
|
1145 F743 38 E5 76 sub deltar
|
|
1146 F746 85 68 sta frmadr
|
|
1147 F748 A4 73 ldy colac+1 ;leave dx in y:x for max() below
|
|
1148 F74A 98 tya
|
|
1149 F74B E9 00 sbc #0
|
|
1150 F74D 85 69 sta frmadr+1
|
|
1151
|
|
1152 ;compute max(dx, dy) based on sign of (dx - dy)
|
|
1153 F74F B0 04 bcs dx_larger
|
|
1154 F751 A0 00 ldy #0
|
|
1155 F753 A6 76 ldx deltar
|
|
1156 F755 dx_larger:
|
|
1157 F755 86 7E stx countr
|
|
1158 F757 84 7F sty countr+1
|
|
1159
|
|
1160 F759 98 tya
|
|
1161 F75A D0 03 bne not_empty
|
|
1162 F75C 8A txa
|
|
1163 F75D F0 0D beq skip_showcursor
|
|
1164 F75F not_empty:
|
|
1165
|
|
1166 ;;##TRACE "Pixel count = %d" dw(countr)
|
|
1167
|
|
1168 ;enter pixel loop (this will do a decrement for us)
|
|
1169 F75F 4C CF F7 jmp next_pixel
|
|
1170
|
|
1171 ;----------------------------------------------
|
|
1172 F762 done:
|
|
1173 F762 20 CC 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 F765 A4 57 ldy dindex
|
|
1179 F767 D0 03 bne skip_showcursor
|
|
1180 F769 20 B0 FC jsr EditorRecomputeCursorAddr
|
|
1181 F76C skip_showcursor:
|
|
1182 F76C A0 01 ldy #1
|
|
1183 F76E 60 rts
|
|
1184
|
|
1185 ;----------------------------------------------
|
|
1186 F76F fill_done:
|
|
1187 F76F 86 6E stx bitmsk
|
|
1188 F771 4C CF F7 jmp next_pixel
|
|
1189
|
|
1190 ;----------------------------------------------
|
|
1191 F774 do_fill:
|
|
1192 F774 A4 6F ldy shfamt ;load current byte offset
|
|
1193 F776 A6 6E ldx bitmsk ;save current bitmask
|
|
1194 F778 D0 33 bne fill_start ;!! - unconditional
|
|
1195
|
|
1196 ;----------------------------------------------
|
|
1197 F77A shift_lo_tab:
|
|
1198 F77A B8 dta <right_shift_8
|
|
1199 F77B B2 dta <right_shift_4
|
|
1200 F77C B4 dta <right_shift_2
|
|
1201 F77D B5 dta <right_shift_1
|
|
1202
|
|
1203 ;----------------------------------------------
|
|
1204 F77E left_shift_4:
|
|
1205 F77E 0A asl
|
|
1206 F77F 0A asl
|
|
1207 F780 left_shift_2:
|
|
1208 F780 0A asl
|
|
1209 F781 left_shift_1:
|
|
1210 F781 0A asl
|
|
1211 F782 90 05 bcc left_shift_ok
|
|
1212 F784 left_shift_8:
|
|
1213 F784 C6 6F dec shfamt
|
|
1214 F786 AD A0 02 lda dmask
|
|
1215 F789 left_shift_ok:
|
|
1216 F789 D0 31 bne post_xinc ;!! - unconditional
|
|
1217
|
|
1218 ;----------------------------------------------
|
|
1219 F78B fill_right_4:
|
|
1220 F78B 4A lsr
|
|
1221 F78C 4A lsr
|
|
1222 F78D fill_right_2:
|
|
1223 F78D 4A lsr
|
|
1224 F78E fill_right_1:
|
|
1225 F78E 4A lsr
|
|
1226 F78F 90 09 bcc fill_right_ok
|
|
1227 F791 fill_right_8:
|
|
1228 F791 A5 77 lda deltac
|
|
1229 F793 C8 iny
|
|
1230 F794 C4 78 cpy deltac+1
|
|
1231 F796 90 02 A0 00 scc:ldy #0
|
|
1232 F79A fill_right_ok:
|
|
1233 F79A 85 6E sta bitmsk
|
|
1234 F79C F0 D1 beq fill_done
|
|
1235 F79E fill_loop:
|
|
1236 F79E B1 66 lda (toadr),y ;load screen byte
|
|
1237 F7A0 24 6E bit bitmsk ;mask to current pixel
|
|
1238 F7A2 D0 CB bne fill_done ;exit loop if non-zero
|
|
1239 F7A4 4D BC 02 eor hold4 ;XOR with fill color
|
|
1240 F7A7 25 6E and bitmsk ;mask change bits to current pixel
|
|
1241 F7A9 51 66 eor (toadr),y ;merge with screen byte
|
|
1242 F7AB 91 66 sta (toadr),y ;save screen byte
|
|
1243 F7AD fill_start:
|
|
1244 F7AD A5 6E lda bitmsk
|
|
1245 F7AF 6C 74 00 jmp (endpt)
|
|
1246
|
|
1247 ;----------------------------------------------
|
|
1248 F7B2 right_shift_4:
|
|
1249 F7B2 4A lsr
|
|
1250 F7B3 4A lsr
|
|
1251 F7B4 right_shift_2:
|
|
1252 F7B4 4A lsr
|
|
1253 F7B5 right_shift_1:
|
|
1254 F7B5 4A lsr
|
|
1255 F7B6 90 04 bcc right_shift_ok
|
|
1256 F7B8 right_shift_8:
|
|
1257 F7B8 E6 6F inc shfamt
|
|
1258 F7BA A5 77 lda deltac
|
|
1259 F7BC right_shift_ok:
|
|
1260 ;fall through to post_xinc
|
|
1261 F7BC post_xinc:
|
|
1262 F7BC 85 6E sta bitmsk
|
|
1263 F7BE no_xinc:
|
|
1264
|
|
1265 ;plot pixel
|
|
1266 ;;##TRACE "Plotting at $%04X+%d with mask $%02X" dw(toadr) db(shfamt) db(bitmsk)
|
|
1267 F7BE A4 6F ldy shfamt
|
|
1268 F7C0 A5 51 lda hold1
|
|
1269 F7C2 51 66 eor (toadr),y
|
|
1270 F7C4 25 6E and bitmsk
|
|
1271 F7C6 51 66 eor (toadr),y
|
|
1272 F7C8 91 66 sta (toadr),y
|
|
1273
|
|
1274 ;do fill if needed
|
|
1275 F7CA A5 22 lda iccomz
|
|
1276 F7CC 4A lsr
|
|
1277 F7CD 90 A5 bcc do_fill
|
|
1278
|
|
1279 F7CF next_pixel:
|
|
1280 ;loop back for next pixel
|
|
1281 F7CF A5 7E lda countr
|
|
1282 F7D1 D0 04 bne next_pixel_2
|
|
1283 F7D3 C6 7F dec countr+1
|
|
1284 F7D5 30 8B bmi done
|
|
1285 F7D7 next_pixel_2:
|
|
1286 F7D7 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 F7D9 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 F7D9 A5 68 lda frmadr
|
|
1306 F7DB 0A asl
|
|
1307 F7DC A8 tay
|
|
1308 F7DD A5 69 lda frmadr+1
|
|
1309 F7DF 2A rol
|
|
1310 F7E0 AA tax
|
|
1311
|
|
1312 ;check for y increment (2*e < dx, or A:Y < colac)
|
|
1313 F7E1 98 tya
|
|
1314 F7E2 18 clc
|
|
1315 F7E3 E5 72 sbc colac
|
|
1316 F7E5 8A txa
|
|
1317 F7E6 48 pha
|
|
1318 F7E7 E5 73 sbc colac+1
|
|
1319 F7E9 10 13 bpl no_yinc
|
|
1320
|
|
1321 F7EB do_yinc:
|
|
1322 ;bump y (add/subtract pitch, e += dx)
|
|
1323 F7EB A2 02 ldx #2
|
|
1324 F7ED yinc_loop:
|
|
1325 F7ED B5 70 lda rowac,x
|
|
1326 F7EF 18 clc
|
|
1327 F7F0 75 66 adc toadr,x
|
|
1328 F7F2 95 66 sta toadr,x
|
|
1329 F7F4 B5 71 lda rowac+1,x
|
|
1330 F7F6 75 67 adc toadr+1,x
|
|
1331 F7F8 95 67 sta toadr+1,x
|
|
1332 F7FA CA dex
|
|
1333 F7FB CA dex
|
|
1334 F7FC 10 EF bpl yinc_loop
|
|
1335 F7FE no_yinc:
|
|
1336
|
|
1337 ;check for x increment (2*e + dy > 0, or Y:[S] + deltar > 0)
|
|
1338 F7FE 98 tya
|
|
1339 F7FF 18 clc
|
|
1340 F800 65 76 adc deltar
|
|
1341 F802 68 pla
|
|
1342 F803 69 00 adc #0
|
|
1343 F805 30 B7 bmi no_xinc
|
|
1344
|
|
1345 ;update error accumulator
|
|
1346 F807 A5 68 lda frmadr
|
|
1347 F809 38 E5 76 sub deltar
|
|
1348 F80C 85 68 sta frmadr
|
|
1349 F80E B0 02 C6 69 scs:dec frmadr+1
|
|
1350
|
|
1351 ;bump x
|
|
1352 F812 A5 6E lda bitmsk
|
|
1353 F814 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 F817 .proc ScreenClear
|
|
1387 ;first, set up for clearing the split-screen window (4*40 bytes main)
|
|
1388 F817 A0 04 ldy #4
|
|
1389
|
|
1390 ;check if we are in the split screen text window
|
|
1391 F819 A6 7B ldx swpflg
|
|
1392 F81B D0 08 bne is_text_window
|
|
1393
|
|
1394 ;nope, it's the main screen... compute size
|
|
1395 F81D A4 57 ldy dindex
|
|
1396 F81F BE 26 FE ldx ScreenHeightShifts,y
|
|
1397 F822 BC 36 FE ldy ScreenHeights,x
|
|
1398 F825 is_text_window:
|
|
1399 F825 20 4C 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 F828 18 clc
|
|
1404 F829 A6 57 ldx dindex
|
|
1405 F82B F0 02 beq is_gr0
|
|
1406 F82D 69 A0 adc #160
|
|
1407 F82F is_gr0:
|
|
1408 F82F A8 tay
|
|
1409 F830 A5 65 lda adress+1
|
|
1410 F832 69 00 adc #0
|
|
1411
|
|
1412 F834 AA tax
|
|
1413 F835 65 59 adc savmsc+1
|
|
1414 F837 85 67 sta toadr+1
|
|
1415 F839 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 F83D A9 00 lda #0
|
|
1421 F83F loop:
|
|
1422 F83F 88 dey
|
|
1423 F840 91 66 sta (toadr),y
|
|
1424 F842 D0 FB bne loop
|
|
1425 F844 C6 67 dec toadr+1
|
|
1426 F846 CA dex
|
|
1427 F847 10 F6 bpl loop
|
|
1428
|
|
1429 ;reset coordinates and cursor (we're going to wipe the cursor)
|
|
1430 F849 85 56 sta colcrs+1
|
|
1431 F84B 85 54 sta rowcrs
|
|
1432 F84D 85 5D sta oldchr
|
|
1433
|
|
1434 ;always reset the logical line map
|
|
1435 F84F A6 57 ldx dindex
|
|
1436 F851 D0 02 bne is_graphic_screen
|
|
1437 F853 A5 52 lda lmargn
|
|
1438 F855 is_graphic_screen:
|
|
1439 F855 85 55 sta colcrs
|
|
1440
|
|
1441 ;always reset the logical line map and exit
|
|
1442 F857 4C B9 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 = F85B ScreenInsertLine = ScreenInsertPhysLine.use_c
|
|
1456 F85A .proc ScreenInsertPhysLine
|
|
1457 F85A 18 clc
|
|
1458 F85B use_c:
|
|
1459 ;save new logline flag
|
|
1460 F85B 08 php
|
|
1461
|
|
1462 ;compute addresses
|
|
1463 F85C AC BF 02 ldy botscr
|
|
1464 F85F 88 dey
|
|
1465 F860 20 42 F9 jsr ScreenComputeToAddrX0
|
|
1466 F863 20 8A FD jsr EditorNextLineAddr
|
|
1467
|
|
1468 ;copy lines
|
|
1469 F866 AE BF 02 ldx botscr
|
|
1470 F869 D0 09 bne line_loop_start
|
|
1471 F86B line_loop:
|
|
1472 F86B A0 27 ldy #39
|
|
1473 F86D char_loop:
|
|
1474 F86D B1 68 lda (frmadr),y
|
|
1475 F86F 91 66 sta (toadr),y
|
|
1476 F871 88 dey
|
|
1477 F872 10 F9 bpl char_loop
|
|
1478 F874 line_loop_start:
|
|
1479 F874 A5 68 lda frmadr
|
|
1480 F876 85 66 sta toadr
|
|
1481 F878 38 sec
|
|
1482 F879 E9 28 sbc #40
|
|
1483 F87B 85 68 sta frmadr
|
|
1484 F87D A5 69 lda frmadr+1
|
|
1485 F87F 85 67 sta toadr+1
|
|
1486 F881 E9 00 sbc #0
|
|
1487 F883 85 69 sta frmadr+1
|
|
1488
|
|
1489 F885 CA dex
|
|
1490 F886 E4 54 cpx rowcrs
|
|
1491 F888 D0 E1 bne line_loop
|
|
1492
|
|
1493 F88A no_copy:
|
|
1494 ;clear the current line
|
|
1495 F88A A0 27 ldy #39
|
|
1496 F88C A9 00 lda #0
|
|
1497 F88E clear_loop:
|
|
1498 F88E 91 66 sta (toadr),y
|
|
1499 F890 88 dey
|
|
1500 F891 10 FB bpl clear_loop
|
|
1501
|
|
1502 ;insert bit into logical line mask
|
|
1503 F893 20 34 FD jsr EditorGetCurLogicalLineInfo
|
|
1504
|
|
1505 F896 28 plp
|
|
1506 F897 B0 02 A9 00 scs:lda #0
|
|
1507 F89B 85 51 sta hold1
|
|
1508
|
|
1509 F89D A9 00 lda #0
|
|
1510 F89F 38 sec
|
|
1511 F8A0 FD C1 E4 sbc ReversedBitMasks,x ;-bit
|
|
1512 F8A3 0A asl
|
|
1513 F8A4 39 B2 02 and logmap,y
|
|
1514 F8A7 18 clc
|
|
1515 F8A8 79 B2 02 adc logmap,y
|
|
1516 F8AB 6A ror
|
|
1517 F8AC 05 51 ora hold1
|
|
1518 F8AE 99 B2 02 sta logmap,y
|
|
1519
|
|
1520 F8B1 88 dey
|
|
1521 F8B2 10 03 6E B3 02 spl:ror logmap+1
|
|
1522 F8B7 88 dey
|
|
1523 F8B8 10 03 6E B4 02 spl:ror logmap+2
|
|
1524 F8BD 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 F8BE .proc ScreenHideCursor
|
|
1537 ;erase the cursor
|
|
1538 F8BE 48 pha
|
|
1539 F8BF A0 00 ldy #0
|
|
1540 F8C1 A5 5D lda oldchr
|
|
1541 F8C3 91 5E sta (oldadr),y
|
|
1542 F8C5 68 pla
|
|
1543 F8C6 no_cursor:
|
|
1544 F8C6 60 rts
|
|
1545 .endp
|
|
1546
|
|
1547 ;==========================================================================
|
|
1548 F8C7 .proc ScreenCheckPosition
|
|
1549 ;Check for ROWCRS out of range. Note that for split screen modes we still
|
|
1550 ;check against the full height!
|
|
1551 F8C7 AD BF 02 lda botscr
|
|
1552 F8CA A6 57 ldx dindex
|
|
1553 F8CC F0 06 beq rowcheck_gr0
|
|
1554 F8CE BC 26 FE ldy ScreenHeightShifts,x
|
|
1555 F8D1 B9 36 FE lda ScreenHeights,y
|
|
1556 F8D4 rowcheck_gr0:
|
|
1557 ;while we know it's GR.0, clamp RMARGN to 39 (required for ARTILLERY.BAS)
|
|
1558 F8D4 A0 27 ldy #39
|
|
1559 F8D6 C4 53 cpy rmargn
|
|
1560 F8D8 B0 02 bcs rmargn_ok
|
|
1561 F8DA 84 53 sty rmargn
|
|
1562 F8DC rmargn_ok:
|
|
1563 F8DC 18 clc
|
|
1564 F8DD E5 54 sbc rowcrs
|
|
1565 F8DF B0 0E bcs rowcheck_pass
|
|
1566 F8E1 invalid_position:
|
|
1567
|
|
1568 ;If the cursor is out of range, reset it within bounds.
|
|
1569 F8E1 A0 00 ldy #0
|
|
1570 F8E3 84 56 sty colcrs+1 ;X high = 0
|
|
1571 F8E5 8A txa
|
|
1572 F8E6 D0 02 A4 52 sne:ldy lmargn
|
|
1573 F8EA 84 55 sty colcrs ;X low = X origin
|
|
1574
|
|
1575 F8EC A0 8D ldy #CIOStatCursorRange
|
|
1576 F8EE 60 rts
|
|
1577
|
|
1578 F8EF rowcheck_pass:
|
|
1579 ;check width
|
|
1580 F8EF BC 3B FE ldy ScreenPixelWidthIds,x
|
|
1581 F8F2 A5 55 lda colcrs
|
|
1582 F8F4 D9 C8 F9 cmp ScreenPixelWidthsLo,y
|
|
1583 F8F7 A5 56 lda colcrs+1
|
|
1584 F8F9 F9 CD F9 sbc ScreenPixelWidthsHi,y
|
|
1585 F8FC B0 E3 bcs invalid_position
|
|
1586
|
|
1587 ;check for BREAK
|
|
1588 F8FE A0 FF ldy #$ff
|
|
1589 F900 A5 11 lda brkkey
|
|
1590 F902 D0 04 bne no_break
|
|
1591 F904 84 11 sty brkkey
|
|
1592 F906 A0 7F ldy #CIOStatBreak-1
|
|
1593 F908 no_break:
|
|
1594 F908 C8 iny
|
|
1595 F909 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 F90A .proc EditorSwapToText
|
|
1618 ;set C=0 (main) if gr.0, C=1 (split) otherwise
|
|
1619 F90A A0 17 ldy #23
|
|
1620 F90C CC BF 02 cpy botscr
|
|
1621
|
|
1622 = F90F .def :ScreenSwap = *
|
|
1623 ;check if the correct set is in place
|
|
1624 F90F 48 pha
|
|
1625 F910 A9 00 lda #0
|
|
1626 F912 65 7B adc swpflg
|
|
1627 F914 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 F916 A2 0B ldx #11
|
|
1642 F918 swap_loop:
|
|
1643 F918 B5 54 lda rowcrs,x
|
|
1644 F91A BC 90 02 ldy txtrow,x
|
|
1645 F91D 94 54 sty rowcrs,x
|
|
1646 F91F 9D 90 02 sta txtrow,x
|
|
1647 F922 CA dex
|
|
1648 F923 10 F3 bpl swap_loop
|
|
1649
|
|
1650 ;invert swap flag
|
|
1651 F925 8A txa
|
|
1652 F926 45 7B eor swpflg
|
|
1653 F928 85 7B sta swpflg
|
|
1654
|
|
1655 F92A already_there:
|
|
1656 F92A 68 pla
|
|
1657 F92B 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 F92C .proc ScreenComputeAddr
|
|
1674 F92C 20 4C F9 jsr ScreenComputeRangeSize
|
|
1675 F92F 85 64 sta adress
|
|
1676 F931 8A txa
|
|
1677 F932 18 clc
|
|
1678 F933 65 64 adc adress ;row*10,20,40+col
|
|
1679 F935 90 02 E6 65 scc:inc adress+1
|
|
1680 F939 18 clc
|
|
1681 F93A 65 58 adc savmsc
|
|
1682 F93C AA tax
|
|
1683 F93D A5 65 lda adress+1
|
|
1684 F93F 65 59 adc savmsc+1
|
|
1685 F941 60 rts
|
|
1686 .endp
|
|
1687
|
|
1688 ;==========================================================================
|
|
1689 = F944 ScreenComputeToAddr = ScreenComputeToAddrX0.with_x
|
|
1690 F942 .proc ScreenComputeToAddrX0
|
|
1691 F942 A2 00 ldx #0
|
|
1692 F944 with_x:
|
|
1693 F944 20 2C F9 jsr ScreenComputeAddr
|
|
1694 F947 86 66 stx toadr
|
|
1695 F949 85 67 sta toadr+1
|
|
1696 F94B 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 F94C .proc ScreenComputeRangeSize
|
|
1716 F94C A9 00 85 65 mva #0 adress+1
|
|
1717 F950 84 64 sty adress
|
|
1718 F952 A4 57 ldy dindex
|
|
1719 F954 B9 3B FE lda ScreenPixelWidthIds,y
|
|
1720 F957 38 sec
|
|
1721 F958 F9 D2 F9 sbc ScreenEncodingTab,y
|
|
1722 F95B A8 tay
|
|
1723 F95C C8 iny
|
|
1724 F95D A5 64 lda adress
|
|
1725 F95F 0A asl
|
|
1726 F960 26 65 rol adress+1 ;row*2
|
|
1727 F962 0A asl
|
|
1728 F963 26 65 rol adress+1 ;row*4
|
|
1729 F965 18 clc
|
|
1730 F966 65 64 adc adress ;row*5
|
|
1731 F968 90 02 E6 65 scc:inc adress+1
|
|
1732 F96C shift_loop:
|
|
1733 F96C 0A asl
|
|
1734 F96D 26 65 rol adress+1 ;row*10,20,40
|
|
1735 F96F 88 dey
|
|
1736 F970 10 FA bpl shift_loop
|
|
1737 F972 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 = F978 ScreenAlignPixel = ScreenSetupPlotPixel.rshift_mask
|
|
1756 F973 .proc ScreenSetupPlotPixel
|
|
1757 ;;##TRACE "Folded pixel = $%02X" db(hold1)
|
|
1758 F973 20 82 F9 jsr ScreenSetupPixelAddr
|
|
1759
|
|
1760 ;preshift bit mask
|
|
1761 F976 A5 77 lda deltac
|
|
1762 F978 rshift_mask:
|
|
1763 F978 CA dex
|
|
1764 F979 30 04 bmi xmaskshift_done
|
|
1765 F97B xmaskshift_loop:
|
|
1766 F97B 4A lsr
|
|
1767 F97C CA dex
|
|
1768 F97D 10 FC bpl xmaskshift_loop
|
|
1769 F97F xmaskshift_done:
|
|
1770 F97F 85 6E sta bitmsk
|
|
1771
|
|
1772 ;;##TRACE "Initial bitmasks = $%02X $%02X" db(bitmsk) db(dmask)
|
|
1773 F981 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 F982 .proc ScreenSetupPixelAddr
|
|
1789 ;compute initial address
|
|
1790 F982 A4 5A ldy oldrow
|
|
1791 F984 20 42 F9 jsr ScreenComputeToAddrX0
|
|
1792
|
|
1793 ;;##TRACE "Initial row address = $%04X" dw(toadr)
|
|
1794
|
|
1795 ;compute initial byte offset
|
|
1796 F987 A5 5C lda oldcol+1
|
|
1797 F989 A6 5B ldx oldcol
|
|
1798 F98B phase2:
|
|
1799 F98B 6A ror
|
|
1800 F98C 86 6F stx shfamt
|
|
1801 F98E A9 00 lda #0
|
|
1802 F990 A6 57 ldx dindex
|
|
1803 F992 BC D2 F9 ldy ScreenEncodingTab,x
|
|
1804 F995 F0 06 beq no_xshift
|
|
1805 F997 xshift_loop:
|
|
1806 F997 66 6F ror shfamt
|
|
1807 F999 6A ror
|
|
1808 F99A 88 dey
|
|
1809 F99B D0 FA bne xshift_loop
|
|
1810 F99D no_xshift:
|
|
1811 F99D 2A rol
|
|
1812 F99E 2A rol
|
|
1813 F99F 2A rol
|
|
1814 F9A0 2A rol
|
|
1815 F9A1 AA tax
|
|
1816
|
|
1817 ;;##TRACE "Initial row offset = $%02X" db(shfamt)
|
|
1818 F9A2 60 rts
|
|
1819 .endp
|
|
1820
|
|
1821 ;==========================================================================
|
|
1822 ; ScreenAdvancePosNonMode0
|
|
1823 ;
|
|
1824 F9A3 .proc ScreenAdvancePosNonMode0
|
|
1825 ;advance position
|
|
1826 F9A3 E6 55 inc colcrs
|
|
1827 F9A5 D0 02 E6 56 sne:inc colcrs+1
|
|
1828 F9A9 A6 57 ldx dindex
|
|
1829 F9AB BC 3B FE ldy ScreenPixelWidthIds,x
|
|
1830 F9AE BE CD F9 ldx ScreenPixelWidthsHi,y
|
|
1831 F9B1 E4 56 cpx colcrs+1
|
|
1832 F9B3 D0 0F bne graphics_no_wrap
|
|
1833 F9B5 BE C8 F9 ldx ScreenPixelWidthsLo,y
|
|
1834 F9B8 E4 55 cpx colcrs
|
|
1835 F9BA D0 08 bne graphics_no_wrap
|
|
1836
|
|
1837 F9BC 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 F9BC A0 00 ldy #0
|
|
1842 F9BE 84 55 sty colcrs
|
|
1843 F9C0 84 56 sty colcrs+1
|
|
1844 F9C2 E6 54 inc rowcrs
|
|
1845 F9C4 graphics_no_wrap:
|
|
1846 F9C4 A0 01 ldy #1
|
|
1847 F9C6 60 rts
|
|
1848 .endp
|
|
1849
|
|
1850 ;==========================================================================
|
|
1851 .if !_KERNEL_XLXE
|
|
1852 F9C7 _SCREEN_TABLES_1
|
|
Macro: _SCREEN_TABLES_1 [Source: source/Shared/screen.s]
|
|
3 F9C7 0A dta <10
|
|
4 F9C8 14 dta <20
|
|
5 F9C9 28 dta <40
|
|
6 F9CA 50 dta <80
|
|
7 F9CB A0 dta <160
|
|
8 F9CC 40 dta <320
|
|
12 F9CD 00 dta >20
|
|
13 F9CE 00 dta >40
|
|
14 F9CF 00 dta >80
|
|
15 F9D0 00 dta >160
|
|
16 F9D1 01 dta >320
|
|
20 F9D2 00 dta 0 ;gr.0 direct bytes
|
|
21 F9D3 00 dta 0 ;gr.1 direct bytes
|
|
22 F9D4 00 dta 0 ;gr.2 direct bytes
|
|
23 F9D5 02 dta 2 ;gr.3 two bits per pixel
|
|
24 F9D6 03 dta 3 ;gr.4 one bit per pixel
|
|
25 F9D7 02 dta 2 ;gr.5 two bits per pixel
|
|
26 F9D8 03 dta 3 ;gr.6 one bit per pixel
|
|
27 F9D9 02 dta 2 ;gr.7 two bits per pixel
|
|
28 F9DA 03 dta 3 ;gr.8 one bit per pixel
|
|
29 F9DB 01 dta 1 ;gr.9 four bits per pixel
|
|
30 F9DC 01 dta 1 ;gr.10 four bits per pixel
|
|
31 F9DD 01 dta 1 ;gr.11 four bits per pixel
|
|
32 F9DE 00 dta 0 ;gr.12 direct bytes
|
|
33 F9DF 00 dta 0 ;gr.13 direct bytes
|
|
34 F9E0 03 dta 3 ;gr.14 one bit per pixel
|
|
35 F9E1 02 dta 2 ;gr.15 two bits per pixel
|
|
39 F9E2 FF 0F 03 01 FF F0 + dta $ff, $0f, $03, $01, $ff, $f0, $c0, $80
|
|
Source: source/Shared/screen.s
|
|
1853 .endif
|
|
270 F9EA 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 F9EA .proc EditorOpen
|
|
12 F9EA 20 B9 FD jsr ScreenResetLogicalLineMap
|
|
13 F9ED 8E FE 02 stx dspflg ;!! relies on X=0 from ScreenResetLogicalLineMap
|
|
14 F9F0 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 F9F3 4C F2 F3 jmp ScreenOpenMode0
|
|
19 .endp
|
|
20
|
|
21 ;==========================================================================
|
|
22 = E4C9 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 F9F6 .proc EditorGetByte
|
|
36 ;check if we have anything left in the current line
|
|
37 F9F6 A5 6B lda bufcnt
|
|
38 F9F8 D0 06 bne have_line
|
|
39
|
|
40 ;nope, fetch a line
|
|
41 F9FA 20 16 FA jsr EditorGetLine
|
|
42 F9FD 10 01 bpl have_line
|
|
43 F9FF 60 rts
|
|
44
|
|
45 FA00 have_line:
|
|
46 ;swap to text context
|
|
47 FA00 20 0A F9 jsr EditorSwapToText
|
|
48
|
|
49 ;subtract off a char
|
|
50 FA03 C6 6B dec bufcnt
|
|
51
|
|
52 ;check if we're at the EOL
|
|
53 FA05 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 FA07 A9 9B lda #$9b
|
|
58 FA09 20 DF F5 jsr ScreenPutByte
|
|
59
|
|
60 FA0C A9 9B lda #$9b
|
|
61 FA0E D0 03 bne done
|
|
62
|
|
63 FA10 have_char:
|
|
64 ;read a char from the screen
|
|
65 FA10 20 9F F5 jsr ScreenGetByte
|
|
66 FA13 done:
|
|
67 FA13 4C 63 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 FA16 .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 FA16 20 0A F9 jsr EditorSwapToText
|
|
123 FA19 A5 55 85 6D mva colcrs _start_x
|
|
124 FA1D A5 54 85 6C mva rowcrs _start_y
|
|
125 FA21 20 63 FD jsr EditorSwapToScreen
|
|
126
|
|
127 ;check if forced read is enabled on the IOCB -- if so, assume we've gotten
|
|
128 ;an EOL
|
|
129 FA24 A5 2A lda icax1z
|
|
130 FA26 4A lsr
|
|
131 FA27 B0 25 bcs do_eol
|
|
132
|
|
133 FA29 read_loop:
|
|
134 ;get a character
|
|
135 FA29 20 66 FE jsr KeyboardGetByte
|
|
136 FA2C 10 01 bpl read_ok
|
|
137 FA2E read_error:
|
|
138 FA2E 60 rts
|
|
139
|
|
140 FA2F read_ok:
|
|
141 FA2F C9 9B cmp #$9b
|
|
142 FA31 F0 1D beq is_eol
|
|
143
|
|
144 ;echo the character
|
|
145 FA33 20 A8 FA jsr EditorPutByte
|
|
146 FA36 30 F6 bmi read_error
|
|
147
|
|
148 ;check if we've hit the warning point (logical pos 113)
|
|
149 FA38 A5 55 lda colcrs
|
|
150 FA3A C9 21 cmp #33
|
|
151 FA3C D0 EB bne read_loop
|
|
152
|
|
153 ;convert current row to logical start row
|
|
154 FA3E 20 4A FD jsr EditorGetCurLogicalRow
|
|
155
|
|
156 ;check if we're on the third row
|
|
157 FA41 18 clc
|
|
158 FA42 69 02 adc #2
|
|
159 FA44 C5 54 cmp rowcrs
|
|
160
|
|
161 ;if so, sound the bell
|
|
162 FA46 D0 E1 bne read_loop
|
|
163 FA48 20 5C FD jsr EditorBell
|
|
164
|
|
165 FA4B 4C 29 FA jmp read_loop
|
|
166
|
|
167 FA4E do_eol:
|
|
168 FA4E A9 9B lda #$9b
|
|
169 FA50 is_eol:
|
|
170 ;echo the character
|
|
171 FA50 20 A8 FA jsr EditorPutByte
|
|
172 FA53 30 D9 bmi read_error
|
|
173
|
|
174 ;swap to text screen context
|
|
175 FA55 20 0A F9 jsr EditorSwapToText
|
|
176
|
|
177 ;hide the cursor so we can scan text properly
|
|
178 FA58 20 BE F8 jsr ScreenHideCursor
|
|
179
|
|
180 ;compute address
|
|
181 FA5B A2 00 ldx #0
|
|
182 FA5D 86 63 stx logcol
|
|
183 FA5F A4 6C ldy _start_y
|
|
184 FA61 84 54 sty rowcrs
|
|
185 FA63 20 44 F9 jsr ScreenComputeToAddr
|
|
186
|
|
187 FA66 A4 6D ldy _start_x
|
|
188 FA68 char_loop:
|
|
189 FA68 E6 63 inc logcol
|
|
190 FA6A B1 66 lda (toadr),y
|
|
191 FA6C F0 04 beq blank
|
|
192 FA6E A5 63 85 6B mva logcol bufcnt
|
|
193 FA72 blank:
|
|
194 FA72 C4 53 cpy rmargn
|
|
195 FA74 C8 iny
|
|
196 FA75 90 F1 bcc char_loop
|
|
197 FA77 20 8A FD jsr EditorNextLineAddr
|
|
198
|
|
199 ;check if we're at the bottom of the screen
|
|
200 FA7A E6 54 inc rowcrs
|
|
201 FA7C A5 54 lda rowcrs
|
|
202 FA7E CD BF 02 cmp botscr
|
|
203 FA81 B0 0A bcs scan_scroll
|
|
204
|
|
205 ;check if we're at the end of the logical line
|
|
206 FA83 20 43 FD jsr EditorTestLogicalLineBit
|
|
207 FA86 D0 08 bne scan_done
|
|
208
|
|
209 FA88 A4 52 ldy lmargn
|
|
210 FA8A 4C 68 FA jmp char_loop
|
|
211
|
|
212 FA8D scan_scroll:
|
|
213 ;we're below the screen... need to scroll up
|
|
214 FA8D 20 BC FC jsr EditorDeleteLine0
|
|
215
|
|
216 FA90 scan_done:
|
|
217 ;adjust BUFCNT so it is the number of chars to read (scanned + EOL)
|
|
218 FA90 E6 6B inc bufcnt
|
|
219
|
|
220 ;mark this as the start of a new logical line, trimming off any extra
|
|
221 ;blank lines
|
|
222 FA92 A5 54 lda rowcrs
|
|
223 FA94 20 36 FD jsr EditorGetLogicalLineInfo
|
|
224 FA97 19 B2 02 ora logmap,y
|
|
225 FA9A 99 B2 02 sta logmap,y
|
|
226
|
|
227 ;reset cursor to line start, but leave the cursor off
|
|
228 FA9D A6 6D 86 55 mvx _start_x colcrs
|
|
229 FAA1 A4 6C 84 54 mvy _start_y rowcrs
|
|
230
|
|
231 ;swap back to main context and exit successfully
|
|
232 FAA5 4C 61 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 FAA8 .proc EditorPutByte
|
|
245 ;open the text screen if it is not open already
|
|
246 FAA8 A4 57 ldy dindex
|
|
247 FAAA F0 0C beq screenok
|
|
248 FAAC AC BF 02 ldy botscr
|
|
249 FAAF C0 04 cpy #4
|
|
250 FAB1 F0 05 beq screenok
|
|
251
|
|
252 FAB3 48 pha
|
|
253 FAB4 20 EE F3 jsr ScreenOpenGr0
|
|
254 FAB7 68 pla
|
|
255 FAB8 screenok:
|
|
256
|
|
257 ;swap to text context
|
|
258 FAB8 20 0A F9 jsr EditorSwapToText
|
|
259
|
|
260 ;hide the cursor -- this must be done before we suspend display on
|
|
261 ;Ctrl+1.
|
|
262 FABB 20 BE F8 jsr ScreenHideCursor
|
|
263
|
|
264 ;save off character to free up acc
|
|
265 FABE 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 FABF 0E A2 02 asl escflg ;test and clear escape flag
|
|
273 FAC2 B0 1E bcs not_special
|
|
274
|
|
275 ;check if this might be a special character
|
|
276 FAC4 29 1F and #$1f
|
|
277 FAC6 C9 1B cmp #$1b
|
|
278 FAC8 90 18 bcc not_special
|
|
279
|
|
280 ;might be special, but not EOL... search the special char table
|
|
281 FACA A2 0E ldx #special_code_tab_end-special_code_tab-1
|
|
282 FACC 98 tya
|
|
283 FACD 20 A7 FC jsr EditorIsSpecial
|
|
284 FAD0 D0 10 bne not_special
|
|
285
|
|
286 FAD2 special_found:
|
|
287 ;check if display of control codes is desired; if so, we need to ignore this
|
|
288 FAD2 AD FE 02 lda dspflg
|
|
289 FAD5 D0 0B bne not_special
|
|
290
|
|
291 ;jump to routine
|
|
292 FAD7 20 53 FC jsr dispatch
|
|
293 FADA 20 B0 FC jsr EditorRecomputeCursorAddr
|
|
294 FADD 20 E5 FD jsr ScreenShowCursorAndXitOK
|
|
295 FAE0 10 06 bpl xit2 ;!! - unconditional jump
|
|
296
|
|
297 FAE2 not_special:
|
|
298 ;ok, just put the char to the screen
|
|
299 FAE2 8C FB 02 sty atachr
|
|
300 FAE5 20 F7 F5 jsr ScreenPutByte.not_clear
|
|
301 FAE8 xit2:
|
|
302 ;swap back to main context and exit
|
|
303 FAE8 4C 63 FD jmp EditorSwapToScreen
|
|
304
|
|
305 ;---------------
|
|
306 FAEB special_code_tab:
|
|
307 FAEB 1B dta $1b
|
|
308 FAEC 1C dta $1c
|
|
309 FAED 1D dta $1d
|
|
310 FAEE 1E dta $1e
|
|
311 FAEF 1F dta $1f
|
|
312 FAF0 7D dta $7d
|
|
313 FAF1 7E dta $7e
|
|
314 FAF2 7F dta $7f
|
|
315 FAF3 9C dta $9c
|
|
316 FAF4 9D dta $9d
|
|
317 FAF5 9E dta $9e
|
|
318 FAF6 9F dta $9f
|
|
319 FAF7 FD dta $fd
|
|
320 FAF8 FE dta $fe
|
|
321 FAF9 FF dta $ff
|
|
322 FAFA special_code_tab_end:
|
|
323 FAFA 9B dta $9b ;these are only for the K: check
|
|
324 FAFB 7C dta $7c
|
|
325 FAFC special_code_tab_end_2:
|
|
326
|
|
327 ;----------------
|
|
328
|
|
329 FAFC special_dispatch_lo_tab:
|
|
330 FAFC 0A dta <(special_escape-1)
|
|
331 FAFD 13 dta <(special_up-1)
|
|
332 FAFE 1D dta <(special_down-1)
|
|
333 FAFF B1 dta <(special_left-1)
|
|
334 FB00 BE dta <(special_right-1)
|
|
335 FB01 10 dta <(special_clear-1)
|
|
336 FB02 38 dta <(special_backspace-1)
|
|
337 FB03 77 dta <(special_tab-1)
|
|
338 FB04 C7 dta <(special_delete_line-1)
|
|
339 FB05 CD dta <(special_insert_line-1)
|
|
340 FB06 64 dta <(special_clear_tab-1)
|
|
341 FB07 5C dta <(special_set_tab-1)
|
|
342 FB08 59 dta <(special_bell-1)
|
|
343 FB09 D4 dta <(special_delete_char-1)
|
|
344 FB0A E0 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 FB0B special_escape:
|
|
352 FB0B A9 80 8D A2 02 mva #$80 escflg
|
|
353 FB10 60 rts
|
|
354
|
|
355 ;---------------
|
|
356 FB11 special_clear:
|
|
357 FB11 4C 17 F8 jmp ScreenClear
|
|
358
|
|
359 ;---------------
|
|
360 FB14 special_up:
|
|
361 FB14 A6 54 ldx rowcrs
|
|
362 FB16 D0 03 bne isup2
|
|
363 FB18 AE BF 02 ldx botscr
|
|
364 FB1B isup2:
|
|
365 FB1B CA dex
|
|
366 FB1C 10 0A bpl vmoveexit
|
|
367
|
|
368 ;---------------
|
|
369 FB1E special_down:
|
|
370 FB1E A6 54 ldx rowcrs
|
|
371 FB20 E8 inx
|
|
372 FB21 EC BF 02 cpx botscr
|
|
373 FB24 90 02 A2 00 scc:ldx #0
|
|
374
|
|
375 FB28 vmoveexit:
|
|
376 FB28 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 FB2A 8A txa
|
|
381 FB2B 20 4C FD jsr EditorPhysToLogicalRow
|
|
382 FB2E C5 6C cmp bufstr
|
|
383 FB30 F0 06 beq moveexit
|
|
384
|
|
385 ;we switched rows -- reset read row
|
|
386 FB32 85 6C sta bufstr
|
|
387 FB34 A5 52 85 6D mva lmargn bufstr+1
|
|
388
|
|
389 FB38 moveexit:
|
|
390 FB38 60 rts
|
|
391
|
|
392 ;---------------
|
|
393 FB39 special_backspace:
|
|
394 ;check if we are at the left column
|
|
395 FB39 A5 52 lda lmargn
|
|
396 FB3B C5 55 cmp colcrs
|
|
397 FB3D B0 0B bcs sbks_wrap
|
|
398
|
|
399 ;nope, we can just back up
|
|
400 FB3F C6 55 dec colcrs
|
|
401
|
|
402 ;recompute pos and clear character
|
|
403 FB41 sbks_recomp:
|
|
404 FB41 20 B0 FC jsr EditorRecomputeCursorAddr
|
|
405 FB44 A0 00 ldy #0
|
|
406 FB46 98 tya
|
|
407 FB47 91 5E sta (oldadr),y
|
|
408 FB49 sbks_xit:
|
|
409 FB49 60 rts
|
|
410
|
|
411 FB4A sbks_wrap:
|
|
412 ;check if we're at the start of the logical line
|
|
413 FB4A A5 54 lda rowcrs
|
|
414 FB4C 20 43 FD jsr EditorTestLogicalLineBit
|
|
415 FB4F D0 F8 bne sbks_xit
|
|
416
|
|
417 ;no, so we need to wrap to the right column of the prev line...
|
|
418 FB51 C6 54 dec rowcrs
|
|
419 FB53 A5 53 lda rmargn
|
|
420 FB55 85 55 sta colcrs
|
|
421
|
|
422 ;recompute everything and exit
|
|
423 FB57 4C 41 FB jmp sbks_recomp
|
|
424
|
|
425 ;----------------
|
|
426 FB5A special_bell:
|
|
427 FB5A 4C 5C FD jmp EditorBell
|
|
428
|
|
429 ;----------------
|
|
430 FB5D special_set_tab:
|
|
431 FB5D 20 71 FB jsr special_common_tab
|
|
432 FB60 1D A3 02 ora tabmap,x
|
|
433 FB63 D0 08 bne special_common_exit_tab
|
|
434
|
|
435 FB65 special_clear_tab:
|
|
436 FB65 20 71 FB jsr special_common_tab
|
|
437 FB68 49 FF eor #$ff
|
|
438 FB6A 3D A3 02 and tabmap,x
|
|
439 FB6D special_common_exit_tab:
|
|
440 FB6D 9D A3 02 sta tabmap,x
|
|
441 FB70 60 rts
|
|
442
|
|
443 FB71 special_common_tab:
|
|
444 FB71 20 6C FD jsr EditorGetLogicalColumn
|
|
445 FB74 A8 tay
|
|
446 FB75 4C 7B 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 FB78 special_tab:
|
|
456 FB78 20 6C FD jsr EditorGetLogicalColumn
|
|
457 FB7B A8 tay
|
|
458 FB7C 8A txa
|
|
459 FB7D 38 sec
|
|
460 FB7E 65 54 adc rowcrs
|
|
461 FB80 85 54 sta rowcrs
|
|
462
|
|
463 ;scan forward until we find the next bit set, or we hit position 120
|
|
464 FB82 tab_scan_loop:
|
|
465 FB82 C8 iny
|
|
466 FB83 C0 78 cpy #120
|
|
467 FB85 B0 08 bcs tab_found
|
|
468 FB87 20 7B FD jsr EditorSetupTabIndex
|
|
469 FB8A 3D A3 02 and tabmap,x
|
|
470 FB8D F0 F3 beq tab_scan_loop
|
|
471 FB8F tab_found:
|
|
472 FB8F 84 55 sty colcrs
|
|
473 FB91 tab_adjust_row:
|
|
474 FB91 A5 55 lda colcrs
|
|
475 FB93 38 sec
|
|
476 FB94 E9 28 sbc #40 ;subtract a row worth of columns
|
|
477 FB96 90 19 bcc tab_adjust_done ;exit if <40
|
|
478 FB98 85 55 sta colcrs
|
|
479 FB9A E6 54 inc rowcrs ;next row
|
|
480 FB9C A5 54 lda rowcrs ;
|
|
481 FB9E CD BF 02 cmp botscr ;check if we're below the screen
|
|
482 FBA1 B0 07 bcs tab_adjust_scroll ;if so, do a scroll
|
|
483 FBA3 20 43 FD jsr EditorTestLogicalLineBit ;check if we're on a new log line
|
|
484 FBA6 F0 E9 beq tab_adjust_row ;if not, keep adjusting
|
|
485 FBA8 10 03 bpl tab_adjust_left ;position at beginning of new line
|
|
486
|
|
487 FBAA tab_adjust_scroll:
|
|
488 FBAA 20 BC FC jsr EditorDeleteLine0
|
|
489 FBAD tab_adjust_left:
|
|
490 FBAD hmove_to_lmargn:
|
|
491 ;move to left margin
|
|
492 FBAD A6 52 ldx lmargn
|
|
493 FBAF hmove_to_x:
|
|
494 FBAF 86 55 stx colcrs
|
|
495 FBB1 tab_adjust_done:
|
|
496 FBB1 60 rts
|
|
497
|
|
498 ;--------------------------------------------------------------------------
|
|
499 FBB2 special_left:
|
|
500 FBB2 A6 55 ldx colcrs
|
|
501 FBB4 F0 05 beq slft_to_right
|
|
502 FBB6 CA dex
|
|
503 FBB7 E4 52 cpx lmargn
|
|
504 FBB9 B0 F4 bcs hmove_to_x
|
|
505
|
|
506 ;move to right margin
|
|
507 FBBB slft_to_right:
|
|
508 FBBB A6 53 ldx rmargn
|
|
509 FBBD 90 F0 bcc hmove_to_x
|
|
510
|
|
511 ;--------------------------------------------------------------------------
|
|
512 FBBF special_right:
|
|
513 FBBF A6 55 ldx colcrs
|
|
514 FBC1 E4 53 cpx rmargn
|
|
515 FBC3 B0 E8 bcs hmove_to_lmargn
|
|
516
|
|
517 ;right one char
|
|
518 FBC5 E6 55 inc colcrs
|
|
519 FBC7 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 FBC8 special_delete_line:
|
|
527 ;delete current logical line
|
|
528 FBC8 20 4A FD jsr EditorGetCurLogicalRow
|
|
529 FBCB 4C BE FC jmp EditorDeleteLine
|
|
530
|
|
531 ;----------------
|
|
532 FBCE special_insert_line:
|
|
533 ;insert a new logical line at this point; note that this may split
|
|
534 ;the current line
|
|
535 FBCE 38 sec
|
|
536 FBCF 20 5B F8 jsr ScreenInsertLine
|
|
537 FBD2 4C AD 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 FBD5 special_delete_char:
|
|
550 ;compute base address of current row (not char)
|
|
551 FBD5 A4 54 ldy rowcrs
|
|
552 FBD7 84 51 sty hold1
|
|
553 FBD9 20 42 F9 jsr ScreenComputeToAddrX0
|
|
554
|
|
555 ;begin shifting in the first column at the current pos
|
|
556 FBDC A4 55 ldy colcrs
|
|
557
|
|
558 ;delete chars to end
|
|
559 FBDE 4C 6C 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 FBE1 special_insert_char:
|
|
571 ;get logical line start
|
|
572 FBE1 20 4A FD jsr EditorGetCurLogicalRow
|
|
573
|
|
574 ;compute line at which we cannot add another physical line
|
|
575 FBE4 18 69 03 add #3
|
|
576 FBE7 85 76 sta deltar
|
|
577
|
|
578 ;compute address of row
|
|
579 FBE9 A4 54 ldy rowcrs
|
|
580 FBEB 84 51 sty hold1
|
|
581 FBED 20 42 F9 jsr ScreenComputeToAddrX0
|
|
582
|
|
583 FBF0 A4 55 ldy colcrs ;end shift at current column
|
|
584 FBF2 A2 00 ldx #0 ;insert blank character at start
|
|
585 FBF4 F0 04 beq insert_line_loop_entry
|
|
586
|
|
587 FBF6 insert_line_loop:
|
|
588 FBF6 A4 52 ldy lmargn ;end shift at left column
|
|
589 FBF8 A6 50 ldx tmpchr ;character to shift in (from last line)
|
|
590
|
|
591 FBFA insert_line_loop_entry:
|
|
592 FBFA 84 65 sty adress+1 ;stash shift origin
|
|
593 FBFC A4 53 ldy rmargn ;begin shift at right column
|
|
594 FBFE B1 66 lda (toadr),y ;get character being shifted out
|
|
595 FC00 85 50 sta tmpchr ;save it off to later shift in on the next row
|
|
596 FC02 insert_shift_loop:
|
|
597 FC02 88 dey
|
|
598 FC03 B1 66 lda (toadr),y
|
|
599 FC05 C8 iny
|
|
600 FC06 91 66 sta (toadr),y
|
|
601 FC08 88 dey
|
|
602 FC09 C4 65 cpy adress+1
|
|
603 FC0B D0 F5 bne insert_shift_loop
|
|
604
|
|
605 ;put character shifted out from previous line into beginning of this one
|
|
606 FC0D 8A txa
|
|
607 FC0E 91 66 sta (toadr),y
|
|
608
|
|
609 ;next row
|
|
610 FC10 E6 51 inc hold1
|
|
611
|
|
612 FC12 20 8A FD jsr EditorNextLineAddr
|
|
613
|
|
614 ;check if we're at the end of the logical line
|
|
615 FC15 A5 51 lda hold1
|
|
616 FC17 CD BF 02 cmp botscr
|
|
617 FC1A B0 05 bcs insert_crossed_lline
|
|
618 FC1C 20 43 FD jsr EditorTestLogicalLineBit
|
|
619 FC1F F0 D5 beq insert_line_loop
|
|
620 FC21 insert_crossed_lline:
|
|
621
|
|
622 ;check if we shifted out a non-blank character
|
|
623 FC21 A5 50 lda tmpchr
|
|
624 FC23 F0 2D beq insert_done
|
|
625
|
|
626 ;save current row
|
|
627 FC25 A5 54 lda rowcrs
|
|
628 FC27 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 FC28 A6 51 ldx hold1
|
|
633 FC2A E4 76 cpx deltar
|
|
634 FC2C 08 php
|
|
635
|
|
636 ;move to the bottom line +1; we use ROWCRS so it stays updated with the scrolling
|
|
637 FC2D 86 54 stx rowcrs
|
|
638
|
|
639 ;check if we are at the bottom of the screen; if so we must scroll
|
|
640 FC2F A9 00 lda #0
|
|
641 FC31 85 76 sta deltar
|
|
642
|
|
643 FC33 EC BF 02 cpx botscr
|
|
644 FC36 90 03 bcc insert_no_scroll
|
|
645
|
|
646 ;scroll the screen
|
|
647 FC38 20 BC FC jsr EditorDeleteLine0
|
|
648
|
|
649 FC3B insert_no_scroll:
|
|
650 ;if we can't extend, we are done
|
|
651 FC3B 28 plp
|
|
652 FC3C B0 0E bcs insert_cant_extend
|
|
653
|
|
654 ;just insert a blank line at the end of this logical row to extend it
|
|
655 FC3E 20 5A F8 jsr ScreenInsertPhysLine
|
|
656
|
|
657 ;restore shifted character and put it in place
|
|
658 FC41 A4 54 ldy rowcrs
|
|
659 FC43 20 42 F9 jsr ScreenComputeToAddrX0
|
|
660 FC46 A5 50 lda tmpchr
|
|
661 FC48 A4 52 ldy lmargn
|
|
662 FC4A 91 66 sta (toadr),y
|
|
663 FC4C insert_cant_extend:
|
|
664
|
|
665 ;restore cursor row, adjusting for any scroll
|
|
666 FC4C 68 pla
|
|
667 FC4D 38 sec
|
|
668 FC4E E5 76 sbc deltar
|
|
669 FC50 85 54 sta rowcrs
|
|
670
|
|
671 FC52 insert_done:
|
|
672 FC52 60 rts
|
|
673
|
|
674 ;---------------------------------
|
|
675 FC53 dispatch:
|
|
676 FC53 A9 FB lda #>special_escape
|
|
677 FC55 48 pha
|
|
678 FC56 BD FC FA lda special_dispatch_lo_tab,x
|
|
679 FC59 48 pha
|
|
680 FC5A 60 rts
|
|
681
|
|
682 ;---------------------------------
|
|
683 FC5B delete_line_loop:
|
|
684 ;copy first character into right margin of previous row
|
|
685 FC5B A4 52 ldy lmargn
|
|
686 FC5D B1 66 lda (toadr),y
|
|
687 FC5F A4 53 ldy rmargn
|
|
688 FC61 91 68 sta (frmadr),y
|
|
689
|
|
690 ;start shifting new row at left margin
|
|
691 FC63 A4 52 ldy lmargn
|
|
692 FC65 delete_shift_loop:
|
|
693 FC65 C8 iny
|
|
694 FC66 B1 66 lda (toadr),y
|
|
695 FC68 88 dey
|
|
696 FC69 91 66 sta (toadr),y
|
|
697 FC6B C8 iny
|
|
698 FC6C delete_shift_loop_entry:
|
|
699 FC6C C4 53 cpy rmargn
|
|
700 FC6E D0 F5 bne delete_shift_loop
|
|
701
|
|
702 ;next line
|
|
703 FC70 20 8A FD jsr EditorNextLineAddr
|
|
704
|
|
705 ;check if the next row is a logical line start
|
|
706 FC73 A6 51 ldx hold1
|
|
707 FC75 E8 inx
|
|
708 FC76 EC BF 02 cpx botscr
|
|
709 FC79 B0 08 bcs delete_stop_shifting
|
|
710 FC7B 86 51 stx hold1
|
|
711 FC7D 8A txa
|
|
712 FC7E 20 43 FD jsr EditorTestLogicalLineBit
|
|
713
|
|
714 ;keep going if not
|
|
715 FC81 F0 D8 beq delete_line_loop
|
|
716
|
|
717 FC83 delete_stop_shifting:
|
|
718 ;blank the last character of the last line
|
|
719 FC83 A4 53 ldy rmargn
|
|
720 FC85 A9 00 lda #0
|
|
721 FC87 91 68 sta (frmadr),y
|
|
722
|
|
723 ;check if the last line is blank
|
|
724 FC89 delete_blank_test_loop:
|
|
725 FC89 B1 68 lda (frmadr),y
|
|
726 FC8B D0 19 bne delete_not_blank
|
|
727 FC8D 88 dey
|
|
728 FC8E C4 52 cpy lmargn
|
|
729 FC90 B0 F7 bcs delete_blank_test_loop
|
|
730
|
|
731 ;the last line is blank... check if it is a logical line start
|
|
732 FC92 C6 51 dec hold1
|
|
733 FC94 A5 51 lda hold1
|
|
734 FC96 20 43 FD jsr EditorTestLogicalLineBit
|
|
735
|
|
736 ;skip if so -- we can't delete the entire logical line
|
|
737 FC99 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 FC9B A5 55 lda colcrs
|
|
742 FC9D 48 pha
|
|
743 FC9E A5 51 lda hold1
|
|
744 FCA0 20 BE FC jsr EditorDeleteLine
|
|
745 FCA3 68 pla
|
|
746 FCA4 85 55 sta colcrs
|
|
747
|
|
748 FCA6 delete_not_blank:
|
|
749 ;re-show cursor and exit
|
|
750 FCA6 60 rts
|
|
751
|
|
752 .endp
|
|
753
|
|
754 ;==========================================================================
|
|
755 FCA7 .proc EditorIsSpecial
|
|
756 FCA7 special_binsearch:
|
|
757 FCA7 DD EB FA cmp EditorPutByte.special_code_tab,x
|
|
758 FCAA F0 03 beq special_found
|
|
759 FCAC CA dex
|
|
760 FCAD 10 F8 bpl special_binsearch
|
|
761 FCAF special_found:
|
|
762 FCAF 60 rts
|
|
763 .endp
|
|
764
|
|
765 ;==========================================================================
|
|
766 FCB0 .proc EditorRecomputeCursorAddr
|
|
767 FCB0 A6 55 ldx colcrs
|
|
768 FCB2 A4 54 ldy rowcrs
|
|
769 FCB4 20 2C F9 jsr ScreenComputeAddr
|
|
770 FCB7 86 5E stx oldadr
|
|
771 FCB9 85 5F sta oldadr+1
|
|
772 FCBB 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 = FCBE EditorDeleteLine = EditorDeleteLine0.use_line
|
|
786 FCBC .proc EditorDeleteLine0
|
|
787 FCBC A9 00 lda #0
|
|
788 FCBE use_line:
|
|
789 FCBE 85 51 sta hold1
|
|
790 FCC0 A2 00 ldx #0
|
|
791 FCC2 86 76 stx deltar
|
|
792
|
|
793 FCC4 scroll_loop:
|
|
794 ;compute base address and set that as destination
|
|
795 FCC4 A4 51 ldy hold1
|
|
796
|
|
797 .if _KERNEL_XLXE
|
|
798 sec
|
|
799 bne nofine
|
|
800 ldx fine
|
|
801 beq nofine
|
|
802 ldx #0
|
|
803 xloop:
|
|
804 lda rtclok+2
|
|
805 cmp:req rtclok+2
|
|
806 inx
|
|
807 stx vscrol
|
|
808 cpx #7
|
|
809 bne xloop
|
|
810 lda #32/2
|
|
811 cmp:rcc vcount
|
|
812 cmp:rcs vcount
|
|
813 nofine:
|
|
814 php ;C=0 for fine scroll, C=1 for coarse scroll
|
|
815 .endif
|
|
816
|
|
817 ;set TOADR to the line to be deleted
|
|
818 FCC6 20 42 F9 jsr ScreenComputeToAddrX0
|
|
819
|
|
820 FCC9 A6 51 ldx hold1
|
|
821 FCCB 10 0C bpl line_loop_start
|
|
822
|
|
823 FCCD line_loop:
|
|
824 ;bump line: FRMADR <- TOADR, TOADR += 40
|
|
825 FCCD 20 8A FD jsr EditorNextLineAddr
|
|
826
|
|
827 ;move line -- note that we are copying backwards (TOADR to FRMADR)!
|
|
828 FCD0 A0 27 ldy #39
|
|
829 FCD2 B1 66 91 68 88 10 + mva:rpl (toadr),y (frmadr),y-
|
|
830
|
|
831 FCD9 line_loop_start:
|
|
832 FCD9 E8 inx
|
|
833 FCDA EC BF 02 cpx botscr
|
|
834 FCDD D0 EE bne line_loop
|
|
835
|
|
836 ;clear the last line
|
|
837 FCDF A0 27 ldy #39
|
|
838 FCE1 A9 00 lda #0
|
|
839 FCE3 91 66 88 10 FB sta:rpl (toadr),y-
|
|
840
|
|
841 .if _KERNEL_XLXE
|
|
842 plp
|
|
843 bcs nofinescroll2
|
|
844 sta vscrol
|
|
845 nofinescroll2:
|
|
846 .endif
|
|
847
|
|
848 FCE8 20 1D 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 FCEB A5 51 lda hold1
|
|
853 FCED 20 36 FD jsr EditorGetLogicalLineInfo
|
|
854 FCF0 BE 1A FD ldx update_table,y ;get number of masks to shift
|
|
855 FCF3 38 sec ;setup to add a new logical line at the end
|
|
856 FCF4 F0 09 beq do_mask ;jump to masking if we're on byte 2
|
|
857 FCF6 2E B4 02 rol logmap+2 ;shift byte 2
|
|
858 FCF9 CA dex ;
|
|
859 FCFA F0 03 beq do_mask ;jump to masking if we're on byte 1
|
|
860 FCFC 2E B3 02 rol logmap+1 ;shift byte 1
|
|
861 FCFF do_mask:
|
|
862 FCFF 85 64 sta adress ;stash mask
|
|
863 FD01 49 FF eor #$ff ;invert mask
|
|
864 FD03 39 B2 02 and logmap,y ;kill target bit
|
|
865 FD06 85 65 sta adress+1 ;stash modified mask
|
|
866 FD08 C6 64 dec adress ;form mask for LSBs below bit
|
|
867 FD0A 25 64 and adress ;isolate those bits
|
|
868 FD0C 65 65 adc adress+1 ;shift those up and the bit from the next byte in
|
|
869 FD0E 99 B2 02 sta logmap,y ;write to logmap
|
|
870
|
|
871 FD11 E6 76 inc deltar ;increment line count
|
|
872 FD13 E6 64 inc adress ;revert mask
|
|
873 FD15 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 FD17 F0 AB beq scroll_loop
|
|
877
|
|
878 ;all done
|
|
879 FD19 60 rts
|
|
880
|
|
881 FD1A update_table:
|
|
882 FD1A 02 01 00 dta 2,1,0
|
|
883
|
|
884 FD1D adjust_lines:
|
|
885 FD1D A5 52 lda lmargn ;prep for line adjustments
|
|
886
|
|
887 ;adjust the read row if it is affected by the deletion
|
|
888 FD1F A2 6C ldx #<bufstr
|
|
889 FD21 20 26 FD jsr adjust_line
|
|
890
|
|
891 ;adjust the cursor row if it is affected by the deletion
|
|
892 FD24 A2 54 ldx #<rowcrs
|
|
893 FD26 adjust_line:
|
|
894 FD26 B4 00 ldy 0,x ;get row
|
|
895 FD28 C4 51 cpy hold1 ;compare against deletion pos
|
|
896 FD2A 90 07 bcc adjust_line_above ;nothing to do if it's above del range
|
|
897 FD2C D0 03 bne adjust_line_below ;skip col adjust if it's below del range
|
|
898 FD2E 95 01 sta 1,x ;within range - move cursor to left mgn
|
|
899 FD30 60 rts
|
|
900 FD31 adjust_line_below:
|
|
901 FD31 D6 00 dec 0,x
|
|
902 FD33 adjust_line_above:
|
|
903 FD33 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 = FD34 EditorGetCurLogicalLineInfo = _EditorGetLogicalLineInfo
|
|
922 = FD36 EditorGetLogicalLineInfo = _EditorGetLogicalLineInfo.use_a
|
|
923 FD34 .proc _EditorGetLogicalLineInfo
|
|
924 FD34 A5 54 lda rowcrs
|
|
925 FD36 use_a:
|
|
926 FD36 48 pha
|
|
927 FD37 4A lsr
|
|
928 FD38 4A lsr
|
|
929 FD39 4A lsr
|
|
930 FD3A A8 tay
|
|
931 FD3B 68 pla
|
|
932 FD3C 29 07 and #7
|
|
933 FD3E AA tax
|
|
934 FD3F BD C1 E4 lda ReversedBitMasks,x
|
|
935 FD42 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 FD43 .proc EditorTestLogicalLineBit
|
|
951 FD43 20 36 FD jsr EditorGetLogicalLineInfo
|
|
952 FD46 39 B2 02 and logmap,y
|
|
953 FD49 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 = FD4C EditorPhysToLogicalRow = EditorGetCurLogicalRow.use_line
|
|
969 FD4A .proc EditorGetCurLogicalRow
|
|
970 FD4A A5 54 lda rowcrs
|
|
971 FD4C use_line:
|
|
972 FD4C 85 64 sta adress
|
|
973 FD4E test_loop:
|
|
974 FD4E A5 64 lda adress
|
|
975 FD50 20 43 FD jsr EditorTestLogicalLineBit
|
|
976 FD53 D0 04 bne found
|
|
977 FD55 C6 64 dec adress
|
|
978 FD57 D0 F5 bne test_loop
|
|
979 FD59 found:
|
|
980 FD59 A5 64 lda adress
|
|
981 FD5B 60 rts
|
|
982 .endp
|
|
983
|
|
984 ;==========================================================================
|
|
985 FD5C .proc EditorBell
|
|
986 FD5C A0 00 ldy #0
|
|
987 FD5E 4C CC E4 jmp Bell
|
|
988 .endp
|
|
989
|
|
990 ;==========================================================================
|
|
991 FD61 .proc EditorSwapToScreen_Y1
|
|
992 FD61 A0 01 ldy #1
|
|
993 = FD63 .def :EditorSwapToScreen = *
|
|
994 FD63 84 64 sty adress
|
|
995 FD65 18 clc
|
|
996 FD66 20 0F F9 jsr ScreenSwap
|
|
997 FD69 A4 64 ldy adress
|
|
998 FD6B 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 FD6C .proc EditorGetLogicalColumn
|
|
1009 ;get starting row of logical line
|
|
1010 FD6C A5 54 lda rowcrs
|
|
1011 FD6E 20 4C FD jsr EditorPhysToLogicalRow
|
|
1012
|
|
1013 ;subtract off current row
|
|
1014 FD71 18 clc
|
|
1015 FD72 E5 54 sbc rowcrs
|
|
1016 FD74 AA tax
|
|
1017
|
|
1018 ;multiply negated difference by 40
|
|
1019 FD75 BD A0 FC lda EditorLineLengthTab-$fc,x
|
|
1020
|
|
1021 ;add in physical column
|
|
1022 FD78 65 55 adc colcrs
|
|
1023 FD7A 60 rts
|
|
1024 .endp
|
|
1025
|
|
1026 ;==========================================================================
|
|
1027 FD7B .proc EditorSetupTabIndex
|
|
1028 FD7B 98 tya
|
|
1029 FD7C 29 07 and #7
|
|
1030 FD7E AA tax
|
|
1031 FD7F BD C1 E4 lda ReversedBitMasks,x
|
|
1032 FD82 48 pha
|
|
1033 FD83 98 tya
|
|
1034 FD84 4A lsr
|
|
1035 FD85 4A lsr
|
|
1036 FD86 4A lsr
|
|
1037 FD87 AA tax
|
|
1038 FD88 68 pla
|
|
1039 FD89 60 rts
|
|
1040 .endp
|
|
1041
|
|
1042 ;==========================================================================
|
|
1043 ; Copy TOADR to FRMADR and add 40 to TOADR.
|
|
1044 ;
|
|
1045 FD8A .proc EditorNextLineAddr
|
|
1046 FD8A A5 66 lda toadr
|
|
1047 FD8C 85 68 sta frmadr
|
|
1048 FD8E 18 69 28 add #40
|
|
1049 FD91 85 66 sta toadr
|
|
1050 FD93 A5 67 lda toadr+1
|
|
1051 FD95 85 69 sta frmadr+1
|
|
1052 FD97 69 00 adc #0
|
|
1053 FD99 85 67 sta toadr+1
|
|
1054 FD9B 60 rts
|
|
1055 .endp
|
|
1056
|
|
1057 ;==========================================================================
|
|
1058 FD9C .proc EditorLineLengthTab
|
|
1059 FD9C 78 50 28 00 dta 120, 80, 40, 0
|
|
1060 .endp
|
|
1061
|
|
271
|
|
272 .ifdef _KERNEL_816
|
|
273 icl 'screenext816.s'
|
|
274 .else
|
|
275 FDA0 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 FDA0 ScreenEncodingOffsetTable:
|
|
12 FDA0 00 dta $00 ;4-bit
|
|
13 FDA1 10 dta $10 ;2-bit
|
|
14 FDA2 14 dta $14 ;1-bit
|
|
15
|
|
16 .if !_KERNEL_XLXE
|
|
17 FDA3 _SCREEN_TABLES_3
|
|
Macro: _SCREEN_TABLES_3 [Source: source/Shared/screen.s]
|
|
2 FDA3 00 11 22 33 44 55 + dta $00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$aa,$bb,$cc,$dd,$ee,$ff
|
|
3 FDB3 00 55 AA FF dta $00,$55,$aa,$ff
|
|
4 FDB7 00 FF dta $00,$ff
|
|
Source: source/Shared/screenext.s
|
|
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 .proc ScreenFineScrollDLI
|
|
28 pha
|
|
29 lda color2
|
|
30 eor colrsh
|
|
31 and drkmsk
|
|
32 sta colpf1
|
|
33 pla
|
|
34 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 FDB9 .proc ScreenResetLogicalLineMap
|
|
47 FDB9 A2 FF ldx #$ff
|
|
48 FDBB 8E B2 02 stx logmap
|
|
49 FDBE 8E B3 02 stx logmap+1
|
|
50 FDC1 8E B4 02 stx logmap+2
|
|
51
|
|
52 ;reset line read position
|
|
53 FDC4 E8 inx
|
|
54 FDC5 86 6C stx bufstr
|
|
55 FDC7 A5 52 lda lmargn
|
|
56 FDC9 85 6D sta bufstr+1
|
|
57
|
|
58 ;note - X=0 relied on here by EditorOpen
|
|
59 FDCB 60 rts
|
|
60 .endp
|
|
61
|
|
62 ;==========================================================================
|
|
63 ; ScreenSetLastPosition
|
|
64 ;
|
|
65 ; Copies COLCRS/ROWCRS to OLDCOL/OLDROW.
|
|
66 ;
|
|
67 FDCC .proc ScreenSetLastPosition
|
|
68 FDCC A2 02 ldx #2
|
|
69 FDCE loop:
|
|
70 FDCE B5 54 lda rowcrs,x
|
|
71 FDD0 95 5A sta oldrow,x
|
|
72 FDD2 CA dex
|
|
73 FDD3 10 F9 bpl loop
|
|
74 FDD5 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 FDD6 .proc ScreenAdvancePosMode0
|
|
92 FDD6 E6 55 inc colcrs
|
|
93 FDD8 A6 53 ldx rmargn
|
|
94 FDDA E4 55 cpx colcrs
|
|
95 FDDC B0 06 bcs post_wrap
|
|
96 FDDE A6 52 ldx lmargn
|
|
97 FDE0 86 55 stx colcrs
|
|
98 FDE2 E6 54 inc rowcrs
|
|
99 FDE4 post_wrap:
|
|
100 FDE4 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 FDE5 .proc ScreenShowCursorAndXitOK
|
|
113 ;;##ASSERT dw(oldadr) >= dw(savmsc)
|
|
114 ;check if the cursor is enabled
|
|
115 FDE5 A0 00 ldy #0
|
|
116 FDE7 B1 5E lda (oldadr),y
|
|
117 FDE9 85 5D sta oldchr
|
|
118 FDEB AC F0 02 ldy crsinh
|
|
119 FDEE D0 04 bne cursor_inhibited
|
|
120 FDF0 49 80 eor #$80
|
|
121 FDF2 91 5E sta (oldadr),y
|
|
122 FDF4 cursor_inhibited:
|
|
123 FDF4 C8 iny
|
|
124 FDF5 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 = E4C9 ScreenClose = CIOExitSuccess
|
|
137 .else
|
|
138 .proc ScreenClose
|
|
139 bit fine
|
|
140 bmi disable_fine_scrolling
|
|
141
|
|
142 ldy #1
|
|
143 rts
|
|
144
|
|
145 disable_fine_scrolling:
|
|
146 ;turn off DLI
|
|
147 mva #$40 nmien
|
|
148
|
|
149 ;restore vdslst
|
|
150 ldx #<IntExitHandler_None
|
|
151 lda #>IntExitHandler_None
|
|
152 jsr ScreenOpenGr0.write_vdslst
|
|
153
|
|
154 jmp ScreenOpenGr0
|
|
155 .endp
|
|
156 .endif
|
|
157
|
|
158 ;==========================================================================
|
|
159 .if !_KERNEL_XLXE
|
|
160 FDF6 _SCREEN_TABLES_2
|
|
Macro: _SCREEN_TABLES_2 [Source: source/Shared/screen.s]
|
|
23 FDF6 40 dta <($10000-$03C0) ;gr.0 960 bytes = 40*24 = 40*24
|
|
24 FDF7 80 dta <($10000-$0280) ;gr.1 640 bytes = 20*24 + 40*4 = 40*12 + 40*4
|
|
25 FDF8 70 dta <($10000-$0190) ;gr.2 400 bytes = 10*24 + 40*4 = 40*6 + 40*4
|
|
26 FDF9 70 dta <($10000-$0190) ;gr.3 400 bytes = 10*24 + 40*4 = 40*6 + 40*4
|
|
27 FDFA 80 dta <($10000-$0280) ;gr.4 640 bytes = 10*48 + 40*4 = 40*12 + 40*4
|
|
28 FDFB A0 dta <($10000-$0460) ;gr.5 1120 bytes = 20*48 + 40*4 = 40*24 + 40*4
|
|
29 FDFC E0 dta <($10000-$0820) ;gr.6 2080 bytes = 20*96 + 40*4 = 40*48 + 40*4
|
|
30 FDFD 60 dta <($10000-$0FA0) ;gr.7 4000 bytes = 40*96 + 40*4 = 40*96 + 40*4
|
|
31 FDFE 50 dta <($10000-$1EB0) ;gr.8 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
|
|
32 FDFF 50 dta <($10000-$1EB0) ;gr.9 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
|
|
33 FE00 50 dta <($10000-$1EB0) ;gr.10 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
|
|
34 FE01 50 dta <($10000-$1EB0) ;gr.11 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
|
|
35 FE02 A0 dta <($10000-$0460) ;gr.12 1120 bytes = 40*24 + 40*4 = 40*24 + 40*4
|
|
36 FE03 80 dta <($10000-$0280) ;gr.13 640 bytes = 40*12 + 40*4 = 40*12 + 40*4
|
|
37 FE04 60 dta <($10000-$0FA0) ;gr.14 4000 bytes = 20*192 + 40*4 = 40*96 + 40*4
|
|
38 FE05 50 dta <($10000-$1EB0) ;gr.15 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16
|
|
42 FE06 FC dta >($10000-$03C0) ;gr.0
|
|
43 FE07 FD dta >($10000-$0280) ;gr.1
|
|
44 FE08 FE dta >($10000-$0190) ;gr.2
|
|
45 FE09 FE dta >($10000-$0190) ;gr.3
|
|
46 FE0A FD dta >($10000-$0280) ;gr.4
|
|
47 FE0B FB dta >($10000-$0460) ;gr.5
|
|
48 FE0C F7 dta >($10000-$0820) ;gr.6
|
|
49 FE0D F0 dta >($10000-$0FA0) ;gr.7
|
|
50 FE0E E1 dta >($10000-$1EB0) ;gr.8
|
|
51 FE0F E1 dta >($10000-$1EB0) ;gr.9
|
|
52 FE10 E1 dta >($10000-$1EB0) ;gr.10
|
|
53 FE11 E1 dta >($10000-$1EB0) ;gr.11
|
|
54 FE12 FB dta >($10000-$0460) ;gr.12
|
|
55 FE13 FD dta >($10000-$0280) ;gr.13
|
|
56 FE14 F0 dta >($10000-$0FA0) ;gr.14
|
|
57 FE15 E1 dta >($10000-$1EB0) ;gr.15
|
|
66 FE16 02 06 07 08 09 0A + dta $02,$06,$07,$08,$09,$0A,$0B,$1D,$3F,$7F,$BF,$FF,$04,$05,$1C,$3E
|
|
72 FE26 01 dta 1
|
|
73 FE27 01 dta 1
|
|
74 FE28 00 dta 0
|
|
75 FE29 01 dta 1
|
|
76 FE2A 02 dta 2
|
|
77 FE2B 02 dta 2
|
|
78 FE2C 03 dta 3
|
|
79 FE2D 03 dta 3
|
|
80 FE2E 04 dta 4
|
|
81 FE2F 04 dta 4
|
|
82 FE30 04 dta 4
|
|
83 FE31 04 dta 4
|
|
84 FE32 01 dta 1
|
|
85 FE33 00 dta 0
|
|
86 FE34 04 dta 4
|
|
87 FE35 04 dta 4
|
|
91 FE36 0C 18 30 60 C0 dta 12, 24, 48, 96, 192
|
|
95 FE3B 01 dta 1 ;gr.0 40 pixels
|
|
96 FE3C 00 dta 0 ;gr.1 20 pixels
|
|
97 FE3D 00 dta 0 ;gr.2 20 pixels
|
|
98 FE3E 01 dta 1 ;gr.3 40 pixels
|
|
99 FE3F 02 dta 2 ;gr.4 80 pixels
|
|
100 FE40 02 dta 2 ;gr.5 80 pixels
|
|
101 FE41 03 dta 3 ;gr.6 160 pixels
|
|
102 FE42 03 dta 3 ;gr.7 160 pixels
|
|
103 FE43 04 dta 4 ;gr.8 320 pixels
|
|
104 FE44 02 dta 2 ;gr.9 80 pixels
|
|
105 FE45 02 dta 2 ;gr.10 80 pixels
|
|
106 FE46 02 dta 2 ;gr.11 80 pixels
|
|
107 FE47 01 dta 1 ;gr.12 40 pixels
|
|
108 FE48 01 dta 1 ;gr.13 40 pixels
|
|
109 FE49 03 dta 3 ;gr.14 160 pixels
|
|
110 FE4A 03 dta 3 ;gr.15 160 pixels
|
|
Source: source/Shared/screenext.s
|
|
161 .endif
|
|
276 .endif
|
|
277
|
|
278 FE4B _KERNEL_REPORT_MODULE_SIZE 'Display routines', 0
|
|
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
|
|
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'Display routines'
|
|
1 $FE4B -> $0A5D($0000) Display routines
|
|
3 = FE4B .def ?@_kernel_lastpt = *
|
|
Source: source/main.xasm
|
|
279
|
|
280 .ifdef _KERNEL_816
|
|
281 icl 'keyboard816.s'
|
|
282 .else
|
|
283 FE4B 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 FE4B .proc KeyboardInit
|
|
15 FE4B A2 FF ldx #$ff
|
|
16 FE4D 8E FC 02 stx ch
|
|
17 FE50 8E F2 02 stx ch1
|
|
18 FE53 E8 inx
|
|
19 FE54 8E F1 02 stx keydel
|
|
20 FE57 8E B6 02 stx invflg
|
|
21
|
|
22 ;turn on shift lock
|
|
23 FE5A A9 40 8D BE 02 mva #$40 shflok
|
|
24
|
|
25 ;set keyboard definition table pointer
|
|
26 .if _KERNEL_XLXE
|
|
27 mwa #KeyCodeToATASCIITable keydef
|
|
28 .endif
|
|
29 FE5F 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 FE60 .nowarn .proc _KeyboardGetByte
|
|
52 FE60 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 ldx shflok
|
|
58 bne caps_off
|
|
59 ldy #$40
|
|
60 .endif
|
|
61 FE60 shift_ctrl_on:
|
|
62 FE60 caps_off:
|
|
63 FE60 98 tya
|
|
64 FE61 29 C0 and #$c0
|
|
65 FE63 write_shflok:
|
|
66 FE63 8D BE 02 sta shflok
|
|
67
|
|
68 = FE66 .def :KeyboardGetByte
|
|
69 FE66 waitForChar:
|
|
70 FE66 A2 FF ldx #$ff
|
|
71 FE68 waitForChar2:
|
|
72 FE68 A5 11 lda brkkey
|
|
73 FE6A F0 58 beq isBreak
|
|
74 FE6C AD FC 02 lda ch
|
|
75 FE6F C9 FF cmp #$ff
|
|
76 FE71 F0 F5 beq waitForChar2
|
|
77
|
|
78 ;invalidate char
|
|
79 FE73 8E FC 02 stx ch
|
|
80
|
|
81 ;do keyboard click (we do this even for ignored ctrl+shift+keys)
|
|
82 FE76 A0 0C ldy #12
|
|
83 FE78 20 CC E4 jsr Bell
|
|
84
|
|
85 ;ignore char if both ctrl and shift are pressed
|
|
86 FE7B C9 C0 cmp #$c0
|
|
87 FE7D B0 E7 bcs waitForChar
|
|
88
|
|
89 ;trap Ctrl-3 and return EOF
|
|
90 FE7F C9 9A cmp #$9a
|
|
91 FE81 F0 46 beq isCtrl3
|
|
92
|
|
93 ;translate char
|
|
94 FE83 A8 tay
|
|
95
|
|
96 .if _KERNEL_XLXE
|
|
97 lda (keydef),y
|
|
98 .else
|
|
99 FE84 B9 0C FF lda KeyCodeToATASCIITable,y
|
|
100 .endif
|
|
101
|
|
102 ;handle special keys (see keytable.s)
|
|
103 FE87 10 0E bpl valid_key
|
|
104 FE89 C9 81 cmp #$81
|
|
105 FE8B 90 D9 bcc waitForChar ;$80 - invalid
|
|
106 FE8D F0 2B beq isInverse ;$81 - inverse video
|
|
107 FE8F C9 83 cmp #$83
|
|
108 FE91 90 CD bcc toggle_shift ;$82 - caps lock
|
|
109 FE93 C9 85 cmp #$85
|
|
110 FE95 90 C9 bcc shift_ctrl_on ;$83 - shift caps lock / $84 - ctrl caps lock
|
|
111
|
|
112 FE97 valid_key:
|
|
113 ;check for alpha key
|
|
114 FE97 C9 61 cmp #'a'
|
|
115 FE99 90 0F bcc notAlpha
|
|
116 FE9B C9 7B cmp #'z'+1
|
|
117 FE9D B0 0B bcs notAlpha
|
|
118
|
|
119 ;check for shift/control lock
|
|
120 FE9F 2C BE 02 bit shflok
|
|
121 FEA2 70 04 bvs doShiftLock
|
|
122 FEA4 10 04 bpl notAlpha
|
|
123
|
|
124 ;do control lock logic
|
|
125 FEA6 29 1F and #$1f
|
|
126
|
|
127 FEA8 doShiftLock:
|
|
128 FEA8 29 DF and #$df
|
|
129
|
|
130 FEAA notAlpha:
|
|
131 ;check if we should apply inverse flag -- special characters are excluded
|
|
132 FEAA A2 10 ldx #EditorPutByte.special_code_tab_end_2-EditorPutByte.special_code_tab-1
|
|
133 FEAC 20 A7 FC jsr EditorIsSpecial
|
|
134 FEAF F0 03 beq skip_inverse
|
|
135
|
|
136 ;apply inverse flag
|
|
137 FEB1 4D B6 02 eor invflg
|
|
138 FEB4 skip_inverse:
|
|
139
|
|
140 ;return char
|
|
141 FEB4 8D FB 02 sta atachr ;required or CON.SYS (SDX 4.46) breaks
|
|
142 FEB7 A0 01 ldy #1
|
|
143 FEB9 60 rts
|
|
144
|
|
145 FEBA isInverse:
|
|
146 FEBA AD B6 02 lda invflg
|
|
147 FEBD 49 80 eor #$80
|
|
148 FEBF 8D B6 02 sta invflg
|
|
149 FEC2 B0 A2 bcs waitForChar ;!! - unconditional
|
|
150
|
|
151 FEC4 isBreak:
|
|
152 FEC4 86 11 stx brkkey
|
|
153 FEC6 A0 80 ldy #CIOStatBreak
|
|
154 FEC8 60 rts
|
|
155
|
|
156 FEC9 isCtrl3:
|
|
157 FEC9 A0 88 ldy #CIOStatEndOfFile
|
|
158 FECB 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 FECC .proc KeyboardIRQ
|
|
174 ;reset software repeat timer
|
|
175 .if _KERNEL_XLXE
|
|
176 mva krpdel srtimr
|
|
177 .else
|
|
178 FECC A9 30 8D 2B 02 mva #$30 srtimr
|
|
179 .endif
|
|
180
|
|
181 ;read new key
|
|
182 FED1 AD 09 D2 lda kbcode
|
|
183
|
|
184 .if _KERNEL_XLXE
|
|
185 ;check for HELP
|
|
186 and #$3f
|
|
187 cmp #$11
|
|
188 bne not_help
|
|
189 sta helpfg
|
|
190 beq xit2
|
|
191
|
|
192 not_help:
|
|
193 lda kbcode
|
|
194 .endif
|
|
195
|
|
196 ;check if it is the same as the prev key
|
|
197 FED4 CD F2 02 cmp ch1
|
|
198 FED7 D0 08 bne debounced
|
|
199
|
|
200 ;reject key if debounce timer is still running
|
|
201 FED9 AD F1 02 lda keydel
|
|
202 FEDC D0 16 bne xit
|
|
203 FEDE AD F2 02 lda ch1
|
|
204 FEE1 debounced:
|
|
205
|
|
206 ;check for Ctrl+1 to toggle display activity
|
|
207 FEE1 C9 9F cmp #$9f
|
|
208 FEE3 F0 11 beq is_suspend
|
|
209
|
|
210 ;store key
|
|
211 FEE5 8D FC 02 sta ch
|
|
212 FEE8 8D F2 02 sta ch1
|
|
213
|
|
214 ;reset attract
|
|
215 FEEB A9 00 85 4D mva #0 atract
|
|
216
|
|
217 FEEF xit2:
|
|
218 ;reset key delay
|
|
219 FEEF A9 03 8D F1 02 mva #3 keydel
|
|
220
|
|
221 FEF4 xit:
|
|
222 ;all done
|
|
223 FEF4 68 pla
|
|
224 FEF5 40 rti
|
|
225
|
|
226 FEF6 is_suspend:
|
|
227 ;toggle stop/start flag
|
|
228 FEF6 AD FF 02 lda ssflag
|
|
229 FEF9 49 FF eor #$ff
|
|
230 FEFB 8D FF 02 sta ssflag
|
|
231 FEFE B0 EF bcs xit2 ;!! carry set from cmp #$9f!
|
|
232 .endp
|
|
233
|
|
234 ;==============================================================================
|
|
235 FF00 .proc KeyboardBreakIRQ
|
|
236 FF00 A9 00 85 11 mva #0 brkkey
|
|
237
|
|
238 ;need to clear the suspend flag as BREAK automatically nukes a pending Ctrl+1
|
|
239 FF04 8D FF 02 sta ssflag
|
|
240
|
|
241 ;interestingly, the default break handler forces the cursor back on.
|
|
242 FF07 8D F0 02 sta crsinh
|
|
243
|
|
244 FF0A 68 pla
|
|
245 FF0B 40 rti
|
|
246 .endp
|
|
284 .endif
|
|
285
|
|
286 FF0C 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 FF0C 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 FF0C 6C 6A 3B 80 80 6B + dta $6C, $6A, $3B, $80, $80, $6B, $2B, $2A
|
|
20 FF14 6F 80 70 75 9B 69 + dta $6F, $80, $70, $75, $9B, $69, $2D, $3D
|
|
21 FF1C 76 80 63 80 80 62 + dta $76, $80, $63, $80, $80, $62, $78, $7A
|
|
22 FF24 34 80 33 36 1B 35 + dta $34, $80, $33, $36, $1B, $35, $32, $31
|
|
23 FF2C 2C 20 2E 6E 80 6D + dta $2C, $20, $2E, $6E, $80, $6D, $2F, $81
|
|
24 FF34 72 80 65 79 7F 74 + dta $72, $80, $65, $79, $7F, $74, $77, $71
|
|
25 FF3C 39 80 30 37 7E 38 + dta $39, $80, $30, $37, $7E, $38, $3C, $3E
|
|
26 FF44 66 68 64 80 82 67 + dta $66, $68, $64, $80, $82, $67, $73, $61
|
|
27
|
|
28 ;SHIFT
|
|
29 FF4C 4C 4A 3A 80 80 4B + dta $4C, $4A, $3A, $80, $80, $4B, $5C, $5E
|
|
30 FF54 4F 80 50 55 9B 49 + dta $4F, $80, $50, $55, $9B, $49, $5F, $7C
|
|
31 FF5C 56 80 43 80 80 42 + dta $56, $80, $43, $80, $80, $42, $58, $5A
|
|
32 FF64 24 80 23 26 1B 25 + dta $24, $80, $23, $26, $1B, $25, $22, $21
|
|
33 FF6C 5B 20 5D 4E 80 4D + dta $5B, $20, $5D, $4E, $80, $4D, $3F, $80
|
|
34 FF74 52 80 45 59 9F 54 + dta $52, $80, $45, $59, $9F, $54, $57, $51
|
|
35 FF7C 28 80 29 27 9C 40 + dta $28, $80, $29, $27, $9C, $40, $7D, $9D
|
|
36 FF84 46 48 44 80 83 47 + dta $46, $48, $44, $80, $83, $47, $53, $41
|
|
37
|
|
38 ;CTRL
|
|
39 FF8C 0C 0A 7B 80 80 0B + dta $0C, $0A, $7B, $80, $80, $0B, $1E, $1F
|
|
40 FF94 0F 80 10 15 9B 09 + dta $0F, $80, $10, $15, $9B, $09, $1C, $1D
|
|
41 FF9C 16 80 03 80 80 02 + dta $16, $80, $03, $80, $80, $02, $18, $1A
|
|
42 FFA4 80 80 9B 80 1B 80 + dta $80, $80, $9B, $80, $1B, $80, $FD, $80
|
|
43 FFAC 00 20 60 0E 80 0D + dta $00, $20, $60, $0E, $80, $0D, $80, $80
|
|
44 FFB4 12 80 05 19 9E 14 + dta $12, $80, $05, $19, $9E, $14, $17, $11
|
|
45 FFBC 80 80 80 80 FE 80 + dta $80, $80, $80, $80, $FE, $80, $7D, $FF
|
|
46 FFC4 06 08 04 80 84 07 + dta $06, $08, $04, $80, $84, $07, $13, $01
|
|
287 FFCC _KERNEL_REPORT_MODULE_SIZE 'Keyboard routines', 0
|
|
Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm]
|
|
1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'Keyboard routines'
|
|
1 $FFCC -> $0181($0000) Keyboard routines
|
|
3 = FFCC .def ?@_kernel_lastpt = *
|
|
Source: source/main.xasm
|
|
288
|
|
289 .if _KERNEL_XLXE
|
|
290 .echo 'Free space: ', $FFEE-*, ' bytes'
|
|
291 .else
|
|
292 .echo 'Free space: ', $FFFA-*, ' bytes'
|
|
292 Free space: $002E 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 org $ffee
|
|
315 dta $01,$01,$13
|
|
316 dta $02 ;option byte - !!CHECKED BY ARCHON
|
|
317 dta 'CX',$00,$00,$00
|
|
318 dta $00
|
|
319 dta a(0)
|
|
320 .endif
|
|
321
|
|
322 ;==============================================================================
|
|
323 ; reset vectors
|
|
324 ;==============================================================================
|
|
325 FFCC org $fffa
|
|
326 FFFA 85 E8 dta a(IntDispatchNMI)
|
|
327 FFFC F8 EF dta a(InitReset)
|
|
328 FFFE A2 E8 dta a(IntDispatchIRQ)
|
|
329
|
|
330 end
|