mads 2.1.0 Source: source/main.xasm 1 ; Altirra - Atari 800/800XL emulator 2 ; Kernel ROM replacement 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 12 .if _KERNEL_XLXE 13 = 0001 _KERNEL_PBI_SUPPORT = 1 14 = 0001 _KERNEL_USE_BOOT_SCREEN = 1 15 .macro _KERNELSTR_BIOS_NAME_INTERNAL 16 .ifdef _KERNEL_816 17 dta d" for 65C816" 18 .else 19 dta d" for XL/XE/XEGS" 20 .endif 21 .endm 22 .else 23 _KERNEL_PBI_SUPPORT = 0 24 _KERNEL_USE_BOOT_SCREEN = 0 25 .endif 26 27 = 0001 _KERNEL_PRINTER_SUPPORT = 1 28 29 ;========================================================================== 30 31 icl 'version.inc' Source: source/Shared/version.inc 1 ; Altirra - Atari 800/800XL emulator 2 ; Kernel ROM replacement - version info 3 ; Copyright (C) 2008-2020 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 .macro _KERNELSTR_VERSION 11 dta '3.26' 12 .endm 13 14 .macro _KERNELSTR_VERSION_INTERNAL 15 dta "3.26" 16 .endm 32 icl 'hardware.inc' Source: source/Shared/hardware.inc 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Hardware register definitions 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 .ifndef f_HARDWARE_INC 11 .def f_HARDWARE_INC 12 13 ;========================================================================== 14 ; GTIA 15 ; 16 m0pf equ $d000 17 m1pf equ $d001 18 m2pf equ $d002 19 m3pf equ $d003 20 p0pf equ $d004 21 p1pf equ $d005 22 p2pf equ $d006 23 p3pf equ $d007 24 m0pl equ $d008 25 m1pl equ $d009 26 m2pl equ $d00a 27 m3pl equ $d00b 28 p0pl equ $d00c 29 p1pl equ $d00d 30 p2pl equ $d00e 31 p3pl equ $d00f 32 33 hposp0 equ $d000 34 hposp1 equ $d001 35 hposp2 equ $d002 36 hposp3 equ $d003 37 hposm0 equ $d004 38 hposm1 equ $d005 39 hposm2 equ $d006 40 hposm3 equ $d007 41 sizep0 equ $d008 42 sizep1 equ $d009 43 sizep2 equ $d00a 44 sizep3 equ $d00b 45 sizem equ $d00c 46 grafp0 equ $d00d 47 grafp1 equ $d00e 48 grafp2 equ $d00f 49 grafp3 equ $d010 50 grafm equ $d011 51 trig0 equ $d010 52 trig1 equ $d011 53 trig2 equ $d012 54 colpm0 equ $d012 55 trig3 equ $d013 56 colpm1 equ $d013 57 pal equ $d014 58 colpm2 equ $d014 59 colpm3 equ $d015 60 colpf0 equ $d016 61 colpf1 equ $d017 62 colpf2 equ $d018 63 colpf3 equ $d019 64 colbk equ $d01a 65 prior equ $d01b 66 vdelay equ $d01c 67 gractl equ $d01d 68 hitclr equ $d01e 69 consol equ $d01f 70 71 ;========================================================================== 72 ; POKEY 73 ; 74 pot0 equ $d200 75 audf1 equ $d200 76 pot1 equ $d201 77 audc1 equ $d201 78 pot2 equ $d202 79 audf2 equ $d202 80 pot3 equ $d203 81 audc2 equ $d203 82 pot4 equ $d204 83 audf3 equ $d204 84 pot5 equ $d205 85 audc3 equ $d205 86 pot6 equ $d206 87 audf4 equ $d206 88 pot7 equ $d207 89 audc4 equ $d207 90 audctl equ $d208 91 kbcode equ $d209 92 skres equ $d20a 93 potgo equ $d20b 94 serin equ $d20d 95 serout equ $d20d 96 irqen equ $d20e 97 irqst equ $d20e 98 skctl equ $d20f 99 skstat equ $d20f 100 101 ;========================================================================== 102 ; PIA 103 ; 104 porta equ $d300 105 portb equ $d301 106 pactl equ $d302 107 pbctl equ $d303 108 109 ;========================================================================== 110 ; ANTIC 111 ; 112 dmactl equ $d400 113 chactl equ $d401 114 dlistl equ $d402 115 dlisth equ $d403 116 hscrol equ $d404 117 vscrol equ $d405 118 pmbase equ $d407 119 chbase equ $d409 120 wsync equ $d40a 121 vcount equ $d40b 122 penh equ $d40c 123 penv equ $d40d 124 nmien equ $d40e 125 nmist equ $d40f 126 nmires equ $d40f 127 128 ;========================================================================== 129 ; 6502 130 ; 131 nmivec equ $fffa 132 resvec equ $fffc 133 irqvec equ $fffe 134 135 .endif 33 icl 'kerneldb.inc' Source: source/Shared/kerneldb.inc 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Kernel Database Definitions 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 .ifndef f_KERNELDB_INC 11 .def f_KERNELDB_INC 12 13 casini = $0002 ;cassette initialization vector 14 ramlo = $0004 ; 15 tramsz = $0006 ;temporary ram size / cart A flag 16 tstdat = $0007 ;RAM test data register / cart B flag 17 ;(also CMCMD for T:) 18 warmst = $0008 ;warmstart flag 19 boot? = $0009 ;boot flag; 0 if none, 1 for disk, 2 for cassette 20 dosvec = $000a 21 dosini = $000c 22 appmhi = $000e 23 pokmsk = $0010 24 brkkey = $0011 ;set on [BREAK] 25 rtclok = $0012 26 bufadr = $0015 ;indirect buffer address pointer (temp for disk buffer) 27 ; $0016 28 iccomt = $0017 ;CIO: command byte 29 ziocb = $0020 ;zero-page IOCB 30 ichidz = $0020 ;Zero page IOCB: device index ($FF = not open) 31 icdnoz = $0021 ;Zero page IOCB: device number 32 iccomz = $0022 ;Zero page IOCB: command byte 33 icstaz = $0023 ;Zero page IOCB: status byte 34 icbalz = $0024 ;Zero page IOCB: address of device/filename spec lo 35 icbahz = $0025 ;Zero page IOCB: address of device/filename spec hi 36 icptlz = $0026 ;Zero page IOCB: put byte address lo (-1) 37 icpthz = $0027 ;Zero page IOCB: put byte address hi (-1) 38 icbllz = $0028 ;Zero page IOCB: buffer length/byte count lo (-1) 39 icblhz = $0029 ;Zero page IOCB: buffer length/byte count hi (-1) 40 icax1z = $002a ;Zero page IOCB: device-specific information 1 41 icax2z = $002b ;Zero page IOCB: device-specific information 2 42 icax3z = $002c ;Zero page IOCB: device-specific information 3 43 icax4z = $002d ;Zero page IOCB: device-specific information 4 44 icax5z = $002e ;Zero page IOCB: device-specific information 5 45 icidno = $002e ;CIO: call X register save/restore 46 icax6z = $002f ;Zero page IOCB: device-specific information 6 47 ciochr = $002f ;CIO: call A register save/restore 48 status = $0030 ;SIO: temporay status byte 49 chksum = $0031 ;SIO: temporary checksum byte (used by IRQ routines) 50 bufrlo = $0032 ;SIO: buffer pointer lo (incremented by IRQ routines) 51 bufrhi = $0033 ;SIO: buffer pointer hi (incremented by IRQ routines) 52 bfenlo = $0034 ;SIO: buffer end lo 53 bfenhi = $0035 ;SIO: buffer end hi 54 ltemp = $0036 ;Relocating loader: loader temp address (XL/XE) 55 ; $0037 56 bufrfl = $0038 ;SIO: buffer full flag 57 recvdn = $0039 ;SIO: receive completed flag 58 xmtdon = $003a ;SIO: transmit completed flag 59 chksnt = $003b ;SIO: checksum sent flag 60 nocksm = $003c ;SIO: no-checksum flag 61 bptr = $003d ;Cassette: Buffer pointer 62 ftype = $003e ;Cassette: Interrecord gap (IRG) type; bit7=1 means continuous mode 63 feof = $003f ;Cassette: EOF flag 64 soundr = $0041 ;SIO: noisy audio flag 65 critic = $0042 ;critical flag for vbi 66 zchain = $004a ;Peripheral Handler: zero-page chain address 67 ; $004b 68 atract = $004d ;screen attract counter 69 drkmsk = $004e ;screen attract mask 70 colrsh = $004f ;screen attract color shift 71 tmpchr = $0050 ;Screen Editor 72 hold1 = $0051 ;Display/Editor: temporary storage 73 lmargn = $0052 ;left margin column 74 rmargn = $0053 ;right margin column 75 rowcrs = $0054 ;cursor row 76 colcrs = $0055 ;cursor column 77 ; $0056 78 dindex = $0057 ;display mode index 79 savmsc = $0058 ;lowest address of screen region 80 oldrow = $005a ; 81 oldcol = $005b ; 82 oldchr = $005d ;cursor character save/restore 83 oldadr = $005e ;cursor memory address 84 ; $005f 85 palnts = $0062 ;PAL/NTSC flag 86 logcol = $0063 ;Display/Editor: Logical column (0-119) 87 adress = $0064 ;temporary storage (display code) 88 ; $0065 89 toadr = $0066 ;temporary storage (display code) 90 a1 = toadr 91 ; $0067 92 frmadr = $0068 ;temporary storage (display code) 93 ; $0069 94 ramtop = $006a ;ram size 95 bufcnt = $006b 96 bufstr = $006c ;row/column of start of logical line 97 bitmsk = $006e ;Screen Editor 98 shfamt = $006f ;Screen Editor 99 rowac = $0070 ;Screen Editor: line drawing 100 ; $0071 ; 101 colac = $0072 ;Screen Editor: line drawing 102 ; $0073 ; 103 endpt = $0074 ;Screen Editor: line drawing 104 ; $0075 ; 105 deltar = $0076 ;Screen Editor: delta row (line drawing) 106 deltac = $0077 ;Screen Editor: delta column (line drawing) 107 ; $0078 ; 108 keydef = $0079 ;XL/XE: Keyboard definition table 109 ; $007a 110 swpflg = $007b ;current display var state ($00 = main, $FF = split screen) 111 holdch = $007c ;temporary key hold area prior to shift/control lock logic 112 countr = $007e ;Screen Editor: line length 113 ; $007f 114 fr0 = $00d4 ;FP: Accumulator 0 115 _fr3 = $00da ;FP: Accumulator 3 (officially FRE) 116 fr1 = $00e0 ;FP: Accumulator 1 117 fr2 = $00e6 ;FP: Accumulator 2 118 _fpcocnt= $00ec ;FP: temporary storage - polynomial coefficient counter 119 _fptemp0= $00ed ;FP: temporary storage - transcendental temporary (officially EEXP) 120 _fptemp1= $00ee ;FP: temporary storage - transcendental temporary (officially NSIGN) 121 ;esign $00ef ;BASIC: Used in sqr() routine -- must not be touched by FP elementary functions 122 ;fchrflg $00f0 ;BASIC: Used in sin() routine -- must not be touched by any FP functions 123 cix = $00f2 ;FP: Character index 124 inbuff = $00f3 ;FP: ASCII conversion buffer 125 ; $00f4 126 ; $00f5 ;FP: temporary storage -- also temporarily used by BASIC power routine 127 ; $00f6 ;FP: temporary storage 128 ztemp4 = $00f7 ;FP: temporary storage -- also temporarily used by BASIC power routine 129 ; $00f8 ;FP: temporary storage 130 ; $00f9 ;FP: temporary storage 131 ; $00fa ;FP: temporary storage 132 degflg = $00fb ;FP: degree/radian flag (0=radians, 6=degrees) 133 flptr = $00fc ;FP: pointer for floating-point loads and stores 134 fptr2 = $00fe ;FP: pointer for polynomial evaluation 135 136 vdslst = $0200 ;display list interrupt vector 137 vprced = $0202 ;serial bus proceed interrupt vector 138 vinter = $0204 ;serial bus interrupt vector 139 vbreak = $0206 ;BRK instruction vector 140 vkeybd = $0208 ;keyboard interrupt vector 141 vserin = $020a ;serial input ready interrupt vector 142 vseror = $020c ;serial output ready interrupt vector 143 vseroc = $020e ;serial output completed interrupt vector 144 vtimr1 = $0210 ;pokey timer 1 interrupt vector 145 vtimr2 = $0212 ;pokey timer 2 interrupt vector 146 vtimr4 = $0214 ;pokey timer 4 interrupt vector 147 vimirq = $0216 ;immediate IRQ vector 148 cdtmv1 = $0218 ;countdown timer 1 149 cdtmv2 = $021a ;countdown timer 2 150 cdtmv3 = $021c ;countdown timer 3 151 cdtmv4 = $021e ;countdown timer 4 152 cdtmv5 = $0220 ;countdown timer 5 153 vvblki = $0222 ;vertical blank immediate vector 154 vvblkd = $0224 ;vertical blank deferred vector 155 cdtma1 = $0226 ;timer 1 vector 156 cdtma2 = $0228 ;timer 2 vector 157 cdtmf3 = $022a ;timer 3 flag 158 srtimr = $022b ;autorepeat timer 159 cdtmf4 = $022c ;timer 4 flag 160 intemp = $022d ;temp value used by SETVBV 161 cdtmf5 = $022e ;timer 5 flag 162 sdmctl = $022f ;shadow for DMACTL ($D400) 163 sdlstl = $0230 ;shadow for DLISTL ($D402) 164 sdlsth = $0231 ;shadow for DLISTH ($D403) 165 sskctl = $0232 ;shadow for SKCTL ($D20F) 166 lcount = $0233 ;Relocating loader: (XL/XE) 167 lpenh = $0234 ;light pen horizontal pos 168 lpenv = $0235 ;light pen vertical pos 169 brkky = $0236 ;break key interrupt vector (OS B+ only) 170 vpirq = $0238 ;PBI device interrupt vector (XL/XE) 171 ; $0239 172 cdevic = $023a ;SIO: command frame device ID 173 ccomnd = $023b ;SIO: command frame command ID 174 caux1 = $023c ;SIO: command aux byte 1 175 caux2 = $023d ;SIO: command aux byte 2 176 temp = $023e ;SIO: temp space 177 errflg = $023f ;SIO: error flag 178 dflags = $0240 ;disk boot flags 179 dbsect = $0241 ;disk boot sector count 180 bootad = $0242 ;disk boot address 181 coldst = $0244 ;cold start flag 182 reclen = $0245 ;Relocating loader: record length (XL/XE) 183 dsktim = $0246 ;Disk Handler: Disk operation timeout 184 pdvmsk = $0247 ;PBI device mask (XL/XE) 185 shpdvs = $0248 ;PBI device selection register shadow ($D1FF) (XL/XE) 186 pdmsk = $0249 ;PBI device interrupt mask (XL/XE) 187 reladr = $024a ;Relocating loader: temp address (XL/XE) 188 ; $024b 189 190 .if _KERNEL_816 191 vabte = $024f ;(816) Emulation ABORT vector 192 ; $0250 193 vcope = $0251 ;(816) Emulation COP vector 194 ; $0252 195 vabtn = $0253 ;(816) Native ABORT vector 196 ; $0254 197 ; $0255 198 vcopn = $0256 ;(816) Native COP vector 199 ; $0257 200 ; $0258 201 vnmin = $0259 ;(816) Native NMI vector 202 ; $025a 203 ; $025b 204 virqn = $025c ;(816) Native IRQ vector 205 ; $025d 206 ; $025e 207 vbrkn = $025f ;(816) Native BREAK vector 208 ; $0260 209 ; $0261 210 vcop0 = $0262 ;(816) Native COP #0 vector 211 ; $0263 212 ; $0264 213 vcopu = $0265 ;(816) Native COP #1-127 vector 214 ; $0266 215 ; $0267 216 vcopc = $0268 ;(816) Native COP #128-255 vector 217 ; $0269 218 ; $026a 219 .endif 220 221 fine = $026e ;fine scrolling flag (XL/XE) 222 gprior = $026f ;shadow for PRIOR ($D01B) 223 paddl0 = $0270 ;shadow for POT0 ($D200) 224 paddl1 = $0271 ;shadow for POT1 ($D201) 225 paddl2 = $0272 ;shadow for POT2 ($D202) 226 paddl3 = $0273 ;shadow for POT3 ($D203) 227 paddl4 = $0274 ;shadow for POT4 ($D204) 228 paddl5 = $0275 ;shadow for POT5 ($D205) 229 paddl6 = $0276 ;shadow for POT6 ($D206) 230 paddl7 = $0277 ;shadow for POT7 ($D207) 231 stick0 = $0278 ;shadow for PORTA lo ($D300) 232 stick1 = $0279 ;shadow for PORTA hi ($D300) 233 stick2 = $027A ;shadow for PORTB lo ($D302) 234 stick3 = $027B ;shadow for PORTB hih ($D302) 235 ptrig0 = $027c ;paddle trigger 0 236 ptrig1 = $027d ;paddle trigger 1 237 ptrig2 = $027e ;paddle trigger 2 238 ptrig3 = $027f ;paddle trigger 3 239 ptrig4 = $0280 ;paddle trigger 4 240 ptrig5 = $0281 ;paddle trigger 5 241 ptrig6 = $0282 ;paddle trigger 6 242 ptrig7 = $0283 ;paddle trigger 7 243 strig0 = $0284 ;shadow for TRIG0 ($D001) 244 strig1 = $0285 ;shadow for TRIG1 ($D002) 245 strig2 = $0286 ;shadow for TRIG2 ($D003) 246 strig3 = $0287 ;shadow for TRIG3 ($D004) 247 hibyte = $0288 ;Relocating loader (XL/XE) 248 wmode = $0289 ;Cassette: Write mode (00 = read, 80 = write) 249 blim = $028a ;Cassette: Buffer limit 250 jveck = $028c ;XL/XE: IRQ jump vector 251 newadr = $028e ;Relocating loader (XL/XE) 252 txtrow = $0290 253 txtcol = $0291 254 ; $0292 255 tindex = $0293 ;text mode index 256 txtmsc = $0294 ;text window pointer 257 ; $0295 258 cretry = $029c ;SIO: command retries (XL/XE) 259 hold3 = $029d ;Screen Editor 260 hold2 = $029f ;Screen Editor 261 dmask = $02a0 ;Display/Editor: Graphics merge mask 262 tmplbt = $02a1 263 escflg = $02a2 ;Display/Editor: Escape next character 264 tabmap = $02a3 ;Display/Editor: Bitfield indicating tabs (note reversed bit positions) 265 logmap = $02b2 ;Display/Editor: Logical line start map (4 bytes) 266 invflg = $02b6 ;Keyboard Handler: inverse flag ($00/$80) 267 tmprow = $02b8 ;Screen Editor 268 tmpcol = $02b9 ;Screen Editor 269 ; $02ba 270 scrflg = $02bb ;Display/Editor: Scroll counter 271 hold4 = $02bc ;Screen Editor 272 dretry = $02bd ;SIO: device retries (XL/XE) 273 shflok = $02be ;shift/control lock flags 274 botscr = $02bf ;number of text rows in text window 275 pcolr0 = $02c0 ;shadow for COLPM0 ($D012) 276 pcolr1 = $02c1 ;shadow for COLPM1 ($D013) 277 pcolr2 = $02c2 ;shadow for COLPM2 ($D014) 278 pcolr3 = $02c3 ;shadow for COLPM3 ($D015) 279 color0 = $02c4 ;shadow for COLPF0 ($D016) 280 color1 = $02c5 ;shadow for COLPF1 ($D017) 281 color2 = $02c6 ;shadow for COLPF2 ($D018) 282 color3 = $02c7 ;shadow for COLPF3 ($D019) 283 color4 = $02c8 ;shadow for COLBK ($D01A) 284 runadr = $02c9 ;Relocating loader: run address (XL/XE) 285 ; $02ca 286 hiused = $02cb ;Relocating loader: Next available memory location (out) (XL/XE) 287 ; $02cc 288 zhiuse = $02cd ;Relocating loader: Next available zero-page address (out) (XL/XE) 289 ; $02ce 290 gbytea = $02cf ;Relocating loader: GET BYTE address (XL/XE) 291 ; $02d0 292 loadad = $02d1 ;Relocating loader: Load address (XL/XE) 293 ; $02d2 294 zloada = $02d3 ;Relocating loader: Zero-page load address (XL/XE) 295 ; $02d4 296 dsctln = $02d5 ;Disk sector size (XL/XE) 297 krpdel = $02d9 ;Keyboard repeat delay (XL/XE) 298 keyrep = $02da ;Keyboard repeat rate (XL/XE) 299 helpfg = $02dc ;Help flag (XL/XE) 300 pbpnt = $02de ;Printer: Buffer index (XL/XE location) 301 pbufsz = $02df ;Printer: Record size (XL/XE location) 302 ramsiz = $02e4 ;ram size in pages 303 memtop = $02e5 ;highest location for programs and data 304 memlo = $02e7 ;base of application memory 305 hndlod = $02e9 ;CIO: Handler load flag (XL/XE) 306 dvstat = $02ea ;DISK: Status request buffer area (4 bytes) 307 ; $02eb 308 ; $02ec 309 ; $02ed 310 cbaudl = $02ee ;Cassette baud rate as POKEY divisor. Set to nominal ($05CC) by C: init. 311 cbaudh = $02ef ; 312 crsinh = $02f0 ;Display/Editor: cursor inhibit flag 313 keydel = $02f1 ;keyboard debounce delay (set to 3 vblanks per key) 314 ch1 = $02f2 ;last keyboard code read 315 chact = $02f3 ;shadow for CHACTL ($D401) 316 chbas = $02f4 ;shadow for CHBASE ($D409) 317 rowinc = $02f8 ;Screen Editor: row direction (XL/XE location) 318 colinc = $02f9 ;Screen Editor: col direction (XL/XE location) 319 atachr = $02fb ;Screen Editor 320 ch = $02fc ;keyboard FIFO byte 321 fildat = $02fd ;Screen Editor: fill color 322 dspflg = $02fe ;enable/disable of control codes by screen editor (E:) 323 ssflag = $02ff ;display/screen editor suspend flag 324 ddevic = $0300 ;serial bus ID 325 dunit = $0301 ;device number 326 dcomnd = $0302 ;command byte 327 dstats = $0303 ;status byte 328 dbuflo = $0304 ;buffer address lo 329 dbufhi = $0305 ;buffer address hi 330 dtimlo = $0306 ;disk timeout value 331 dbytlo = $0308 ;byte count lo 332 dbythi = $0309 ;byte count hi 333 daux1 = $030a ;sector number lo 334 daux2 = $030b ;sector number hi 335 timer1 = $030c ;SIO: baud rate determination - first timer value 336 addcor = $030e ;SIO: baud rate determination - correction value 337 casflg = $030f ;SIO: cassette I/O flag (0=normal, nonzero=cassette) 338 timer2 = $0310 ;SIO: baud rate determination - second timer value 339 temp1 = $0312 ;SIO: baud rate determination - temp 340 ; $0313 341 ptimot = $0314 ;Printer: Timeout (XL/XE location) 342 temp3 = $0315 ;SIO: baud rate determination - temp 343 timflg = $0317 ;SIO: operation timeout flag (set by countdown timer 1 IRQ) 344 stackp = $0318 ;SIO: stack pointer save 345 hatabs = $031a ;handler table 346 pupbt1 = $033d ;(XL/XE) Power-up boot flag #1 - $5C 347 pupbt2 = $033e ;(XL/XE) Power-up boot flag #2 - $93 348 pupbt3 = $033f ;(XL/XE) Power-up boot flag #3 - $25 349 ichid = $0340 ;IOCB #0 handler ID 350 icdno = $0341 ;IOCB #0 device number 351 iccmd = $0342 ;IOCB #0 command byte 352 icsta = $0343 ;IOCB #0 status 353 icbal = $0344 ;IOCB #0 buffer address lo 354 icbah = $0345 ;IOCB #0 buffer address hi 355 icptl = $0346 ;IOCB #0 PUT address lo 356 icpth = $0347 ;IOCB #0 PUT address hi 357 icbll = $0348 ;IOCB #0 buffer length/byte count lo 358 icblh = $0349 ;IOCB #0 buffer length/byte count hi 359 icax1 = $034a ;IOCB #0 auxiliary information lo 360 icax2 = $034b ;IOCB #0 auxiliary information hi 361 icax3 = $034c ; 362 icax4 = $034d ; 363 icax5 = $034e ; 364 icax6 = $034f ; 365 prnbuf = $03c0 ;printer buffer 366 ckey = $03e9 ;cassette boot key 367 basicf = $03f8 ;XL/XE: ROM BASIC flag. 0 = enabled 368 gintlk = $03fa ;XL/XE: Cartridge interlock (clone of TRIG3). 369 chlink = $03fb ;XL/XE: Relocated loader chain 370 casbuf = $03fd ;Cassette buffer (03FD-047F) 371 lbuff = $0580 ; 372 plyarg = $05e0 ;FP: Polynomial evaluation temp register 373 fpscr = $05e6 ;FP: Temp evaluation register (used by LOG/LOG10) 374 375 .endif 34 35 opt h-o+f+ 36 37 .ifdef _KERNEL_816 38 opt c+ 39 .endif 40 41 .if _KERNEL_XLXE 42 org $c000 43 44 ;============================================================================== 45 ; lower ROM identification block (XL/XE) 46 ;============================================================================== 47 48 C000 00 00 dta a(0) 49 C002 01 01 13 dta $01,$01,$13 50 C005 02 dta $02 51 C006 43 58 00 00 00 dta 'CX',$00,$00,$00 52 C00B 00 dta $00 53 54 C00C _KERNEL_REPORT_MODULE_MARK Macro: _KERNEL_REPORT_MODULE_MARK [Source: source/main.xasm] 1 = C00C .def ?@_kernel_lastpt = * Source: source/main.xasm 55 56 .ifdef _KERNEL_816 57 icl 'vbi816.s' 58 .else 59 C00C icl 'vbi.s' Source: source/Shared/vbi.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Vertical Blank Interrupt Services 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 ; VBIExit - Vertical Blank Interrupt Exit Routine 12 ; 13 ; This is a drop-in replacement for XITVBV. 14 ; 15 = C050 VBIExit = VBIProcess.xit 16 17 ;========================================================================== 18 ; VBIProcess - Vertical Blank Processor 19 ; 20 = C00C VBIStage1 = VBIProcess.stage_1 21 = C061 VBIStage2 = VBIProcess.stage_2 22 C00C .proc VBIProcess 23 C00C stage_1: 24 ;increment real-time clock and do attract processing 25 C00C E6 14 inc rtclok+2 26 C00E D0 08 bne clock_done 27 C010 E6 4D inc atract 28 C012 E6 13 inc rtclok+1 29 C014 D0 02 bne clock_done 30 C016 E6 12 inc rtclok 31 C018 clock_done: 32 33 ;Pole Position depends on DRKMSK and COLRSH being reset from VBI as it 34 ;clears kernel vars after startup. 35 C018 A2 FE ldx #$fe ;default to no mask 36 C01A A9 00 lda #$00 ;default to no color alteration 37 C01C A4 4D ldy atract ;check attract counter 38 C01E 10 06 bpl attract_off ;skip if attract is off 39 C020 86 4D stx atract ;lock the attract counter 40 C022 A2 F6 ldx #$f6 ;set mask to dim colors 41 C024 A5 13 lda rtclok+1 ;use clock to randomize colors 42 C026 attract_off: 43 C026 86 4E stx drkmsk ;set color mask 44 C028 85 4F sta colrsh ;set color modifier 45 46 ;atract color 1 only 47 C02A 4D C5 02 eor color1 48 C02D 25 4E and drkmsk 49 C02F 8D 17 D0 sta colpf1 50 51 ;decrement timer 1 and check for underflow 52 C032 AD 18 02 lda cdtmv1 ;check low byte 53 C035 D0 08 bne timer1_lobytezero ;if non-zero, decrement and check for fire 54 C037 AD 19 02 lda cdtmv1+1 ;check high byte 55 C03A F0 10 beq timer1_done ;if clear, timer's not running 56 C03C CE 19 02 dec cdtmv1+1 ;decrement high byte 57 C03F timer1_lobytezero: 58 C03F CE 18 02 dec cdtmv1 ;decrement low byte 59 C042 D0 08 bne timer1_done ;no underflow if non-zero 60 C044 AD 19 02 lda cdtmv1+1 ;low byte is zero... check if high byte is too 61 C047 D0 03 bne timer1_done ;if it's not, we're not done yet ($xx00 > 0) 62 C049 20 56 C0 jsr timer1_dispatch ;jump through timer vector 63 C04C timer1_done: 64 65 ;check for critical operation 66 C04C A5 42 lda critic 67 C04E F0 09 beq no_critic 68 C050 xit: 69 C050 68 pla 70 C051 A8 tay 71 C052 68 pla 72 C053 AA tax 73 C054 exit_a: 74 C054 68 pla 75 C055 exit_none: 76 C055 40 rti 77 78 C056 timer1_dispatch: 79 C056 6C 26 02 jmp (cdtma1) 80 81 C059 no_critic: 82 C059 A9 04 lda #$04 ;I flag 83 C05B BA tsx 84 C05C 3D 04 01 and $0104,x ;I flag set on pushed stack? 85 C05F D0 EF bne xit ;exit if so 86 87 ;======== stage 2 processing 88 89 C061 stage_2: 90 ;re-enable interrupts 91 C061 58 cli 92 93 ;update shadow registers 94 C062 AD 31 02 8D 03 D4 mva sdlsth dlisth 95 C068 AD 30 02 8D 02 D4 mva sdlstl dlistl 96 C06E AD 2F 02 8D 00 D4 mva sdmctl dmactl 97 C074 AD F4 02 8D 09 D4 mva chbas chbase 98 C07A AD F3 02 8D 01 D4 mva chact chactl 99 C080 AD 6F 02 8D 1B D0 mva gprior prior 100 101 C086 A2 08 ldx #8 102 C088 8E 1F D0 stx consol ;sneak in speaker reset while we have an 8 103 C08B ColorLoop 104 C08B BD C0 02 lda pcolr0,x 105 C08E 45 4F eor colrsh 106 C090 25 4E and drkmsk 107 C092 9D 12 D0 sta colpm0,x 108 C095 CA dex 109 C096 10 F3 bpl ColorLoop 110 111 ;decrement timer 2 and check for underflow 112 C098 A2 03 ldx #3 113 C09A 20 47 C1 jsr VBIDecrementTimer 114 C09D D0 03 20 44 C1 sne:jsr Timer2Dispatch 115 116 ;Decrement timers 3-5 and set flags 117 ; 118 ;[OS Manual] Appendix L, page 254 says that the OS never modifies CDTMF3-5 119 ;except to set them to zero on timeout at init. This is a LIE. It also sets 120 ;the flags to $FF when they are running. It does not write the flags when 121 ;the timer is idle. Spider Quake depends on this. 122 ; 123 C0A2 A2 09 ldx #9 124 C0A4 timer_n_loop: 125 C0A4 18 clc 126 C0A5 20 47 C1 jsr VBIDecrementTimer 127 C0A8 B0 07 bcs timer_n_not_running 128 C0AA F0 02 A9 FF seq:lda #$ff 129 C0AE timer_n_not_expired: 130 C0AE 9D 25 02 sta cdtmf3-5,x 131 C0B1 timer_n_not_running: 132 C0B1 CA dex 133 C0B2 CA dex 134 C0B3 E0 05 cpx #5 135 C0B5 B0 ED bcs timer_n_loop 136 137 ;Read POKEY keyboard register and handle auto-repeat 138 C0B7 AD 0F D2 lda skstat ;get key status 139 C0BA 29 04 and #$04 ;check if key is down 140 C0BC D0 13 bne no_repeat_key ;skip if not 141 C0BE CE 2B 02 dec srtimr ;decrement repeat timer 142 C0C1 D0 13 bne no_repeat ;skip if not time to repeat yet 143 C0C3 AD 09 D2 8D FC 02 mva kbcode ch ;repeat last key 144 145 .if _KERNEL_XLXE 146 C0C9 AD DA 02 8D 2B 02 mva keyrep srtimr ;reset repeat timer 147 .else 148 mva #$06 srtimr ;reset repeat timer 149 .endif 150 151 C0CF D0 0D bne no_keydel ;skip debounce counter decrement 152 153 C0D1 no_repeat_key: 154 C0D1 A9 00 lda #0 155 C0D3 8D 2B 02 sta srtimr 156 C0D6 no_repeat: 157 ;decrement keyboard debounce counter 158 C0D6 AD F1 02 lda keydel 159 C0D9 F0 03 CE F1 02 seq:dec keydel 160 C0DE no_keydel: 161 162 ;Update controller shadows. 163 ; 164 ;The PORTA/PORTB decoding is a bit complex: 165 ; 166 ; bits 0-3 -> STICK0/4 (and no, we cannot leave junk in the high bits) 167 ; bits 4-7 -> STICK1/5 168 ; bit 2 -> PTRIG0/4 169 ; bit 3 -> PTRIG1/5 170 ; bit 6 -> PTRIG2/6 171 ; bit 7 -> PTRIG3/7 172 ; 173 ;XL/XE machines only have two joystick ports, so the results of ports 0-1 174 ;are mapped onto ports 2-3. 175 ; 176 177 .if _KERNEL_XLXE 178 C0DE AD 00 D3 lda porta 179 C0E1 AA tax 180 C0E2 29 0F and #$0f 181 C0E4 8D 78 02 sta stick0 182 C0E7 8D 7A 02 sta stick2 183 C0EA 8A txa 184 C0EB 4A lsr ;shr1 185 C0EC 4A lsr ;shr2 186 C0ED AA tax 187 C0EE 4A lsr ;shr3 188 C0EF 4A lsr ;shr4 189 C0F0 8D 79 02 sta stick1 190 C0F3 8D 7B 02 sta stick3 191 C0F6 4A lsr ;shr5 192 C0F7 4A lsr ;shr6 193 C0F8 A8 tay 194 C0F9 29 01 and #$01 195 C0FB 8D 7E 02 sta ptrig2 196 C0FE 98 tya 197 C0FF 4A lsr 198 C100 8D 7F 02 sta ptrig3 199 C103 8A txa 200 C104 29 01 and #$01 201 C106 8D 7C 02 sta ptrig0 202 C109 8A txa 203 C10A 4A lsr 204 C10B 29 01 and #$01 205 C10D 8D 7D 02 sta ptrig1 206 207 C110 A2 03 ldx #3 208 C112 pot_loop: 209 C112 BD 00 D2 lda pot0,x 210 C115 9D 70 02 sta paddl0,x 211 C118 9D 74 02 sta paddl4,x 212 C11B BD 7C 02 lda ptrig0,x 213 C11E 9D 80 02 sta ptrig4,x 214 C121 CA dex 215 C122 10 EE bpl pot_loop 216 217 C124 A2 01 ldx #1 218 C126 port_loop: 219 C126 BD 10 D0 lda trig0,x 220 C129 9D 84 02 sta strig0,x 221 C12C 9D 86 02 sta strig2,x 222 C12F CA dex 223 C130 10 F4 bpl port_loop 224 225 .else 226 ldx #7 227 pot_loop: 228 lda pot0,x 229 sta paddl0,x 230 lda #0 231 sta ptrig0,x 232 dex 233 bpl pot_loop 234 235 ldx #3 236 trig_loop: 237 lda trig0,x 238 sta strig0,x 239 dex 240 bpl trig_loop 241 242 lda porta 243 ldx #0 244 ldy #0 245 jsr do_stick_ptrigs 246 lda portb 247 ldx #4 248 ldy #2 249 jsr do_stick_ptrigs 250 .endif 251 252 ;restart pots (required for SysInfo) 253 C132 8D 0B D2 sta potgo 254 255 ;update light pen 256 C135 AD 0C D4 8D 34 02 mva penh lpenh 257 C13B AD 0D D4 8D 35 02 mva penv lpenv 258 259 C141 6C 24 02 jmp (vvblkd) ;jump through vblank deferred vector 260 261 C144 Timer2Dispatch 262 C144 6C 28 02 jmp (cdtma2) 263 264 .if !_KERNEL_XLXE 265 do_stick_ptrigs: 266 pha 267 and #$0f 268 sta stick0,y 269 pla 270 lsr 271 lsr 272 lsr 273 rol ptrig0,x 274 lsr 275 rol ptrig1,x 276 sta stick1,y 277 lsr 278 lsr 279 lsr 280 rol ptrig2,x 281 lsr 282 rol ptrig3,x 283 rts 284 .endif 285 286 .endp 287 288 ;========================================================================== 289 ; VBIDecrementTimer 290 ; 291 ; Entry: 292 ; X = timer index *2+1 (1-9) 293 ; 294 ; Exit: 295 ; C=1, Z=0, A!0 timer not running 296 ; C=0/same, Z=1, A=0 timer just expired 297 ; C=0/same, Z=0, A=? timer still running 298 ; 299 C147 .proc VBIDecrementTimer 300 ;check low byte 301 C147 BD 17 02 lda cdtmv1-1,x 302 C14A D0 0A bne lononzero 303 304 ;check high byte; set C=1/Z=1 if zero, C=0/Z=0 otherwise 305 C14C DD 18 02 cmp cdtmv1,x 306 C14F D0 02 bne lozero_hinonzero 307 308 ;both bytes are zero, so timer's not running 309 C151 8A txa 310 C152 60 rts 311 312 C153 lozero_hinonzero: 313 ;decrement high byte 314 C153 DE 18 02 dec cdtmv1,x 315 316 C156 lononzero: 317 ;decrement low byte 318 C156 DE 17 02 dec cdtmv1-1,x 319 C159 D0 03 bne still_running 320 321 ;return high byte to set Z appropriately 322 C15B BD 18 02 lda cdtmv1,x 323 C15E still_running: 324 C15E 60 rts 325 .endp 326 327 ;========================================================================== 328 ; VBISetVector - set vertical blank vector or counter 329 ; 330 ; This is a drop-in replacement for SETVBV. 331 ; 332 ; A = item to update 333 ; 1-5 timer 1-5 counter value 334 ; 6 VVBLKI 335 ; 7 VVBLKD 336 ; X = MSB 337 ; Y = LSB 338 ; 339 C15F .proc VBISetVector 340 ;A = item to update 341 ; 1-5 timer 1-5 counter value 342 ; 6 VVBLKI 343 ; 7 VVBLKD 344 ;X = MSB 345 ;Y = LSB 346 ; 347 ;NOTE: 348 ;The Atari OS Manual says that DLIs will be disabled after SETVBV is called. 349 ;This is a lie -- neither the OS-B nor XL kernels do this, and the Bewesoft 350 ;8-players demo depends on it being left enabled. 351 ; 352 ;IRQ mask state must be saved across this proc. DOSDISKA.ATR breaks if IRQs 353 ;are unmasked. 354 355 C15F 0A asl 356 C160 8D 2D 02 sta intemp 357 C163 08 php 358 C164 78 sei 359 C165 98 tya 360 C166 AC 2D 02 ldy intemp 361 362 ;We're relying on a rather tight window here. We can't touch NMIEN, so we have 363 ;to wing it with DLIs enabled. Problem is, in certain conditions we can be under 364 ;very tight timing constraints. In order to do this safely we have to finish 365 ;before a DLI can execute. The worst case is a wide mode 2 line at the end of 366 ;a vertically scrolled region with P/M graphics enabled and an LMS on the next 367 ;mode line. In that case we only have 7 cycles before we hit the P/M graphics 368 ;and another two cycles after that until the DLI fires. The exact cycle timing 369 ;looks like this: 370 ; 371 ;* inc wsync 372 ;ANTIC halts CPU until cycle 105 373 ;105 playfield DMA 374 ;106 refresh DMA 375 ;107 sta abs,y (1/5) 376 ;108 sta abs,y (2/5) 377 ;109 sta abs,y (3/5) 378 ;110 sta abs,y (4/5) 379 ;111 sta abs,y (5/5) 380 ;112 txa (1/2) 381 ;113 txa (2/2) 382 ;0 missiles 383 ;1 display list 384 ;2 player 0 385 ;3 player 1 386 ;4 player 2 387 ;5 player 3 388 ;6 display list address low 389 ;7 display list address high 390 ;8 sta abs,y (1/5) 391 ;9 sta abs,y (2/5) 392 ;10 sta abs,y (3/5) 393 ;11 sta abs,y (4/5) 394 ;12 sta abs,y (5/5) 395 ; 396 ;We rely on the 6502 not being able to service interrupts until the end of an 397 ;instruction for this to work. The INC WSYNC is necessary to combat the case 398 ;where the NMI is triggered across the WSYNC wait; without it, the VBI could 399 ;fire immediately after the first STA. 400 401 C169 EE 0A D4 inc wsync 402 C16C 99 16 02 sta cdtmv1-2,y 403 C16F 8A txa 404 C170 99 17 02 sta cdtmv1-1,y 405 C173 28 plp 406 C174 60 rts 407 .endp 60 .endif 61 62 C175 _KERNEL_REPORT_MODULE_SIZE 'VBI routines', 0 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'VBI routines' 1 $C175 -> $0169($0000) VBI routines 3 = C175 .def ?@_kernel_lastpt = * Source: source/main.xasm 63 64 .ifdef _KERNEL_816 65 icl 'interrupt816.s' 66 .else 67 C175 icl 'interrupt.s' Source: source/Shared/interrupt.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Interrupt Handlers 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 ; Dispatched from INTINV. Used by SpartaDOS X. 12 ; 13 C175 .proc IntInitInterrupts 14 C175 A9 40 8D 0E D4 mva #$40 nmien 15 16 .if _KERNEL_XLXE 17 ;Required by XEGS carts to run since they have a clone of the XL/XE 18 ;OS in them. 19 C17A AD 13 D0 8D FA 03 mva trig3 gintlk 20 .endif 21 22 C180 60 rts 23 .endp 24 25 ;========================================================================== 26 C181 .proc IntDispatchNMI 27 C181 2C 0F D4 bit nmist ;check nmi status 28 C184 10 03 bpl not_dli ;skip if not a DLI 29 C186 6C 00 02 jmp (vdslst) ;jump to display list vector 30 31 .if !_KERNEL_XLXE 32 is_system_reset: 33 jmp warmsv 34 .endif 35 36 C189 not_dli: 37 C189 48 pha 38 39 .if _KERNEL_XLXE 40 ;Only XL/XE OSes cleared the decimal bit. 41 C18A D8 cld 42 .else 43 ;The stock OS treats 'not RNMI' as VBI. We'd best follow its example. 44 lda #$20 45 bit nmist 46 bne is_system_reset 47 .endif 48 49 C18B 8A txa 50 C18C 48 pha 51 C18D 98 tya 52 C18E 48 pha 53 C18F 8D 0F D4 sta nmires ;reset VBI interrupt 54 C192 6C 22 02 jmp (vvblki) ;jump through vblank immediate vector 55 .endp 56 57 C195 .proc IntDispatchIRQ 58 .if _KERNEL_XLXE 59 C195 D8 cld 60 .endif 61 C196 6C 16 02 jmp (vimirq) 62 .endp 63 64 ;============================================================================== 65 = C054 IntExitHandler_A = VBIProcess.exit_a 66 = C055 IntExitHandler_None = VBIProcess.exit_none 68 .endif 69 70 C199 _KERNEL_REPORT_MODULE_SIZE 'Base interrupt routines', 0 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'Base interrupt routines' 1 $C199 -> $0024($0000) Base interrupt routines 3 = C199 .def ?@_kernel_lastpt = * Source: source/main.xasm 71 72 .ifdef _KERNEL_816 73 icl 'irq816.s' 74 .else 75 C199 icl 'irq.s' Source: source/Shared/irq.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - IRQ routines 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 ; _KERNEL_FAST_IRQ 12 ; 13 ; If set, expands the IRQ module slightly to save 12 cycles when ack'ing 14 ; POKEY IRQs. This is still faster than the stock XL/XE OS. If cleared, 15 ; an additional subroutine call is used to reduce code size. 16 ; 17 .ifndef _KERNEL_FAST_IRQ 18 _KERNEL_FAST_IRQ = 0 19 .endif 20 21 ;========================================================================== 22 .if _KERNEL_FAST_IRQ 23 _ACK_IRQ .macro 24 sta irqen 25 lda pokmsk 26 sta irqen 27 .endm 28 .else 29 _ACK_IRQ .macro 30 jsr IrqAcknowledge 31 .endm 32 .endif 33 34 ;========================================================================== 35 ; The canonical IRQ priority order for the XL/XE is: 36 ; - Serial input ready ($20) 37 ; - PBI devices 38 ; - Serial output ready ($10) 39 ; - Serial output complete ($08) 40 ; - Timer 1 ($01) 41 ; - Timer 2 ($02) 42 ; - Timer 4 ($04) 43 ; - Keyboard ($80) 44 ; - Break ($40) 45 ; - PIA proceed 46 ; - PIA interrupt 47 ; - BRK instruction 48 ; 49 = C1D1 IRQHandler = _IRQHandler._entry 50 C199 .proc _IRQHandler 51 .if _KERNEL_PBI_SUPPORT 52 C199 check_pbi: 53 ;check if a device interrupt is active 54 C199 2D FF D1 and $d1ff 55 C19C F0 4D beq no_pbi_interrupt 56 57 ;save X 58 C19E 8D 8C 02 sta jveck 59 C1A1 8A txa 60 C1A2 48 pha 61 62 ;jump through PBI interrupt vector 63 C1A3 AD 8C 02 lda jveck 64 C1A6 6C 38 02 jmp (vpirq) 65 .endif 66 67 C1A9 dispatch_serout: 68 C1A9 A9 EF lda #$ef 69 C1AB _ACK_IRQ Macro: _ACK_IRQ [Source: source/Shared/irq.s] 1 C1AB 20 45 C2 jsr IrqAcknowledge Source: source/Shared/irq.s 70 C1AE 6C 0C 02 jmp (vseror) 71 72 C1B1 check_seroc: 73 C1B1 2C 0E D2 bit irqst 74 C1B4 D0 41 bne not_seroc 75 C1B6 dispatch_seroc: 76 C1B6 6C 0E 02 jmp (vseroc) 77 78 C1B9 dispatch_timer1: 79 C1B9 A9 FE lda #$fe 80 C1BB _ACK_IRQ Macro: _ACK_IRQ [Source: source/Shared/irq.s] 1 C1BB 20 45 C2 jsr IrqAcknowledge Source: source/Shared/irq.s 81 C1BE 6C 10 02 jmp (vtimr1) 82 83 C1C1 dispatch_timer2: 84 C1C1 A9 FD lda #$fd 85 C1C3 _ACK_IRQ Macro: _ACK_IRQ [Source: source/Shared/irq.s] 1 C1C3 20 45 C2 jsr IrqAcknowledge Source: source/Shared/irq.s 86 C1C6 6C 12 02 jmp (vtimr2) 87 88 C1C9 dispatch_timer4: 89 C1C9 A9 FB lda #$fb 90 C1CB _ACK_IRQ Macro: _ACK_IRQ [Source: source/Shared/irq.s] 1 C1CB 20 45 C2 jsr IrqAcknowledge Source: source/Shared/irq.s 91 C1CE 6C 14 02 jmp (vtimr4) 92 93 C1D1 _entry: 94 C1D1 48 pha 95 96 ;check for serial input ready IRQ 97 C1D2 A9 20 lda #$20 98 C1D4 2C 0E D2 bit irqst 99 C1D7 D0 0D bne not_serin 100 C1D9 A9 DF lda #$df 101 C1DB 8D 0E D2 sta irqen 102 C1DE A5 10 lda pokmsk 103 C1E0 8D 0E D2 sta irqen 104 C1E3 6C 0A 02 jmp (vserin) 105 C1E6 not_serin: 106 107 .if _KERNEL_PBI_SUPPORT 108 ;check for PBI devices requiring interrupt handling 109 C1E6 AD 49 02 lda pdmsk 110 C1E9 D0 AE bne check_pbi 111 C1EB no_pbi_interrupt: 112 .endif 113 114 ;check for serial output ready IRQ 115 C1EB A9 10 lda #$10 116 C1ED 2C 0E D2 bit irqst 117 C1F0 F0 B7 beq dispatch_serout 118 119 ;check for serial output complete (not a latch, so must mask) 120 C1F2 4A lsr 121 C1F3 24 10 bit pokmsk 122 C1F5 D0 BA bne check_seroc 123 C1F7 not_seroc: 124 125 C1F7 AD 0E D2 lda irqst 126 C1FA 4A lsr 127 C1FB 90 BC bcc dispatch_timer1 128 C1FD 4A lsr 129 C1FE 90 C1 bcc dispatch_timer2 130 C200 4A lsr 131 C201 90 C6 bcc dispatch_timer4 132 C203 2C 0E D2 bit irqst 133 C206 50 21 bvc dispatch_keyboard 134 C208 10 27 bpl dispatch_break 135 136 ;check for serial bus proceed line 137 C20A 2C 02 D3 bit pactl 138 C20D 30 2A bmi dispatch_pia_irqa 139 140 ;check for serial bus interrupt line 141 C20F 2C 03 D3 bit pbctl 142 C212 30 2B bmi dispatch_pia_irqb 143 144 ;check for break instruction 145 ; 146 ;we used to use TSX here, but this takes too many insns to 147 ;handle stack wrapping properly 148 C214 68 pla 149 C215 8D 8C 02 sta jveck 150 C218 68 pla 151 C219 48 pha 152 C21A 29 10 and #$10 153 C21C F0 07 beq not_brk 154 C21E AD 8C 02 lda jveck 155 C221 48 pha 156 C222 6C 06 02 jmp (vbreak) 157 C225 not_brk: 158 C225 AD 8C 02 lda jveck 159 C228 40 rti 160 161 162 C229 dispatch_keyboard: 163 C229 A9 BF lda #$bf 164 C22B _ACK_IRQ Macro: _ACK_IRQ [Source: source/Shared/irq.s] 1 C22B 20 45 C2 jsr IrqAcknowledge Source: source/Shared/irq.s 165 C22E 6C 08 02 jmp (vkeybd) 166 167 C231 dispatch_break: 168 C231 A9 7F lda #$7f 169 C233 _ACK_IRQ Macro: _ACK_IRQ [Source: source/Shared/irq.s] 1 C233 20 45 C2 jsr IrqAcknowledge Source: source/Shared/irq.s 170 C236 6C 36 02 jmp (brkky) 171 172 C239 dispatch_pia_irqa: 173 ;clear serial bus proceed interrupt 174 C239 AD 00 D3 lda porta 175 C23C 6C 02 02 jmp (vprced) 176 177 C23F dispatch_pia_irqb: 178 ;clear serial bus interrupt interrupt 179 C23F AD 01 D3 lda portb 180 C242 6C 04 02 jmp (vinter) 181 182 .endp 183 184 ;========================================================================== 185 .if !_KERNEL_FAST_IRQ 186 C245 .proc IrqAcknowledge 187 C245 8D 0E D2 sta irqen 188 C248 A5 10 lda pokmsk 189 C24A 8D 0E D2 sta irqen 190 C24D 60 rts 191 .endp 192 .endif 76 .endif 77 78 C24E _KERNEL_REPORT_MODULE_SIZE 'IRQ routines', 0 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'IRQ routines' 1 $C24E -> $00B5($0000) IRQ routines 3 = C24E .def ?@_kernel_lastpt = * Source: source/main.xasm 79 80 C24E icl 'pbi.s' Source: source/Shared/pbi.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Parallel Bus Interface routines 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 .if _KERNEL_PBI_SUPPORT 11 12 C24E icl 'cio.inc' Source: source/Shared/cio.inc 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Character Input/Output Definitions 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 .ifndef f_CIO_INC 11 .def f_CIO_INC 12 13 CIOStatBreak = $80 ;break key abort 14 CIOStatIOCBInUse = $81 ;IOCB in use 15 CIOStatUnkDevice = $82 ;unknown device 16 CIOStatWriteOnly = $83 ;opened for write only 17 CIOStatInvalidCmd = $84 ;invalid command 18 CIOStatNotOpen = $85 ;device or file not open 19 CIOStatInvalidIOCB = $86 ;invalid IOCB number 20 CIOStatReadOnly = $87 ;opened for read only 21 CIOStatEndOfFile = $88 ;end of file reached 22 CIOStatTruncRecord = $89 ;record truncated 23 CIOStatTimeout = $8A ;device timeout 24 CIOStatNAK = $8B ;device NAK 25 CIOStatSerFrameErr = $8C ;serial bus framing error 26 CIOStatCursorRange = $8D ;cursor out of range 27 CIOStatSerOverrun = $8E ;serial frame overrun error 28 CIOStatSerChecksum = $8F ;serial checksum error 29 CIOStatDeviceDone = $90 ;device done error 30 CIOStatBadScrnMode = $91 ;bad screen mode 31 CIOStatNotSupported = $92 ;function not supported by handler 32 CIOStatOutOfMemory = $93 ;not enough memory 33 CIOStatDriveNumErr = $A0 ;disk drive # error 34 CIOStatTooManyFiles = $A1 ;too many open disk files 35 CIOStatDiskFull = $A2 ;disk full 36 CIOStatFatalDiskIO = $A3 ;fatal disk I/O error 37 CIOStatFileNumDiff = $A4 ;internal file # mismatch 38 CIOStatFileNameErr = $A5 ;filename error 39 CIOStatPointDLen = $A6 ;point data length error 40 CIOStatFileLocked = $A7 ;file locked 41 CIOStatInvDiskCmd = $A8 ;invalid command for disk 42 CIOStatDirFull = $A9 ;directory full (64 files) 43 CIOStatFileNotFound = $AA ;file not found 44 CIOStatInvPoint = $AB ;invalid point 45 46 CIOCmdOpen = $03 47 CIOCmdGetRecord = $05 48 CIOCmdGetChars = $07 49 CIOCmdPutRecord = $09 50 ; $0A ;PUT CHARS alias (required by K-Razy Shoot Out) 51 CIOCmdPutChars = $0B 52 CIOCmdClose = $0C 53 CIOCmdGetStatus = $0D 54 CIOCmdSpecial = $0E ;$0E and up is escape 55 56 .endif 13 14 ;========================================================================== 15 ; PBI device ROM entry points: 16 ; $D800 Checksum low (unused) 17 ; $D801 Checksum high (unused) 18 ; $D802 Revision (unused) 19 ; $D803 ID byte; must be $80. 20 ; $D804 Device type (unused) 21 ; $D805 JMP sio_vector 22 ; $D806 (cont.) 23 ; $D807 (cont.) 24 ; $D808 JMP irq_vector 25 ; $D809 (cont.) 26 ; $D80A (cont.) 27 ; $D80B ID byte; must be $91 28 ; $D80C Device name (unused) 29 ; $D80D CIO open vector - 1 30 ; $D80E (cont.) 31 ; $D80F CIO close vector - 1 32 ; $D810 (cont.) 33 ; $D811 CIO get byte vector - 1 34 ; $D812 (cont.) 35 ; $D813 CIO put byte vector - 1 36 ; $D814 (cont.) 37 ; $D815 CIO get status vector - 1 38 ; $D816 (cont.) 39 ; $D817 CIO special vector - 1 40 ; $D818 (cont.) 41 ; $D819 JMP init_vector 42 ; $D81A (cont.) 43 ; $D81B (cont.) 44 ; 45 46 ;========================================================================== 47 ; Scan for PBI devices. 48 ; 49 ; The details: 50 ; - $D1FF is the PBI device select register; 1 selects a device. 51 ; - A selected device, if it exists, maps its ROM into $D800-DFFF, on 52 ; top of the math pack. 53 ; - ID bytes are checked to ensure that a device ROM is actually present. 54 ; (This means that the math pack must not match those bytes!) 55 ; - SHPDVS is the device selection shadow variable. It must match the 56 ; value written to $D1FF whenever the PBI ROM is invoked so that the 57 ; PBI device code can detect its ID. 58 ; - PDVMSK is the device enable mask and is used by SIO to call into 59 ; PBI devices. Each bit in this mask indicates that a PBI device is 60 ; available to possibly service requests. It is NOT set by this 61 ; routine, but by the PBI device init code. 62 ; 63 C24E .proc PBIScan 64 ;set up interrupt handler 65 C24E A9 7E 8D 38 02 A9 + mwa #PBIHandleIRQ vpirq 66 67 ;begin scan 68 C258 A9 01 lda #$01 69 C25A loop: 70 ;select next device 71 C25A 8D 48 02 sta shpdvs 72 C25D 8D FF D1 sta $d1ff 73 74 ;check ID bytes 75 C260 AC 03 D8 ldy $d803 76 C263 C0 80 cpy #$80 77 C265 D0 0A bne invalid 78 79 C267 AC 0B D8 ldy $d80b 80 C26A C0 91 cpy #$91 81 C26C D0 03 bne invalid 82 83 ;init PBI device 84 C26E 20 19 D8 jsr $d819 85 C271 invalid: 86 87 ;next device 88 C271 AD 48 02 lda shpdvs 89 C274 0A asl 90 C275 D0 E3 bne loop 91 92 ;deselect last device 93 C277 8D 48 02 sta shpdvs 94 C27A 8D FF D1 sta $d1ff 95 C27D 60 rts 96 .endp 97 98 ;========================================================================== 99 ; Entry: 100 ; A, X saved on stack 101 ; A = active PBI IRQ mask ($D1FF AND PDMSK) 102 ; 103 ; Exit: 104 ; A, X restored 105 ; Interrupt exit 106 ; 107 C27E .proc PBIHandleIRQ 108 ;isolate lowest bit (ID of highest priority device) 109 C27E 8D 8C 02 sta jveck 110 C281 49 FF eor #$ff 111 C283 18 clc 112 C284 69 01 adc #1 113 C286 2D 8C 02 and jveck 114 115 ;save off the current device mask and select interrupting device 116 C289 AE 48 02 ldx shpdvs 117 C28C 8D 48 02 sta shpdvs 118 C28F 8D FF D1 sta $d1ff 119 C292 8A txa 120 C293 48 pha 121 122 ;call through interrupt vector 123 C294 20 08 D8 jsr $d808 124 125 ;restore previously (un)selected device 126 C297 68 pla 127 C298 8D 48 02 sta shpdvs 128 C29B 8D FF D1 sta $d1ff 129 130 ;restore X, A and exit 131 C29E 68 pla 132 C29F AA tax 133 C2A0 68 pla 134 C2A1 40 rti 135 .endp 136 137 ;========================================================================== 138 C2A2 .proc PBIAttemptSIO 139 C2A2 AD 47 02 lda pdvmsk 140 C2A5 D0 08 bne begin_scan 141 C2A7 fail: 142 C2A7 8D 48 02 sta shpdvs 143 C2AA 8D FF D1 sta $d1ff 144 C2AD 18 clc 145 C2AE 60 rts 146 147 C2AF begin_scan: 148 C2AF A9 00 lda #0 149 C2B1 38 sec 150 C2B2 loop: 151 ;advance to next device bit 152 C2B2 2A rol 153 154 ;check if we've scanned all 8 IDs 155 C2B3 B0 F2 bcs fail 156 157 ;check if device exists 158 C2B5 2C 47 02 bit pdvmsk 159 160 ;keep scanning if not 161 C2B8 F0 F8 beq loop 162 163 ;select the device 164 C2BA 8D 48 02 sta shpdvs 165 C2BD 8D FF D1 sta $d1ff 166 167 ;attempt I/O 168 C2C0 48 pha 169 C2C1 20 05 D8 jsr $d805 170 C2C4 68 pla 171 172 ;loop back if PBI handler didn't claim the I/O 173 C2C5 90 EB bcc loop 174 175 ;deselect last device 176 C2C7 A9 00 lda #0 177 C2C9 8D 48 02 sta shpdvs 178 C2CC 8D FF D1 sta $d1ff 179 180 ;all done 181 C2CF 60 rts 182 .endp 183 184 ;========================================================================== 185 C2D0 .proc PBIGenericDeviceOpen 186 C2D0 A0 00 ldy #0 187 C2D2 10 0A bpl PBIGenericDevicePutByte.vector_entry 188 .endp 189 190 ;========================================================================== 191 C2D4 .proc PBIGenericDeviceClose 192 C2D4 A0 02 ldy #2 193 C2D6 10 06 bpl PBIGenericDevicePutByte.vector_entry 194 .endp 195 196 ;========================================================================== 197 C2D8 .proc PBIGenericDeviceGetByte 198 C2D8 A0 04 ldy #4 199 C2DA 10 02 bpl PBIGenericDevicePutByte.vector_entry 200 .endp 201 202 ;========================================================================== 203 C2DC .proc PBIGenericDevicePutByte 204 C2DC A0 06 ldy #6 205 C2DE vector_entry: 206 C2DE 8C 4A 02 sty reladr 207 C2E1 8D 4B 02 sta reladr+1 208 C2E4 A9 00 lda #0 209 C2E6 38 sec 210 C2E7 loop: 211 ;advance to next device bit 212 C2E7 2A rol 213 214 ;check if we've scanned all 8 IDs 215 C2E8 B0 1B bcs fail 216 217 ;check if device exists and keep scanning if not 218 C2EA 2C 47 02 bit pdvmsk 219 C2ED F0 F8 beq loop 220 221 ;select the device -- note that the write to SHPDVS *MUST* come 222 ;first, in case a PBI IRQ happens, since we do *NOT* have IRQs 223 ;masked here! 224 C2EF 8D 48 02 sta shpdvs 225 C2F2 8D FF D1 sta $d1ff 226 227 ;attempt I/O 228 C2F5 A5 2F lda ciochr 229 C2F7 20 09 C3 jsr dispatch 230 231 ;loop back if PBI handler didn't claim the I/O 232 C2FA 90 EB bcc loop 233 234 ;all done 235 C2FC done: 236 C2FC A2 00 ldx #0 237 C2FE 8E 48 02 stx shpdvs 238 C301 8E FF D1 stx $d1ff 239 C304 60 rts 240 241 C305 fail: 242 C305 A0 82 ldy #CIOStatUnkDevice 243 C307 D0 F3 bne done 244 245 C309 dispatch: 246 C309 AC 4A 02 ldy reladr 247 C30C B9 0E D8 lda $d80e,y 248 C30F 48 pha 249 C310 B9 0D D8 lda $d80d,y 250 C313 48 pha 251 C314 AD 4B 02 lda reladr+1 252 C317 A0 92 ldy #CIOStatNotSupported 253 C319 60 rts 254 255 .endp 256 257 ;========================================================================== 258 C31A .proc PBIGenericDeviceGetStatus 259 C31A A0 08 ldy #8 260 C31C 10 C0 bpl PBIGenericDevicePutByte.vector_entry 261 .endp 262 263 ;========================================================================== 264 C31E .proc PBIGenericDeviceSpecial 265 C31E A0 0A ldy #10 266 C320 10 BC bpl PBIGenericDevicePutByte.vector_entry 267 .endp 268 269 ;========================================================================== 270 .macro PBI_VECTOR_TABLE 271 dta a(PBIGenericDeviceOpen-1) 272 dta a(PBIGenericDeviceClose-1) 273 dta a(PBIGenericDeviceGetByte-1) 274 dta a(PBIGenericDevicePutByte-1) 275 dta a(PBIGenericDeviceGetStatus-1) 276 dta a(PBIGenericDeviceSpecial-1) 277 .endm 278 279 .endif 81 C322 _KERNEL_REPORT_MODULE_SIZE 'PBI routines', 0 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'PBI routines' 1 $C322 -> $00D4($0000) PBI routines 3 = C322 .def ?@_kernel_lastpt = * Source: source/main.xasm 82 C322 icl 'phandler.s' Source: source/Shared/phandler.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Peripheral Handler routines 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 ; Add handler to HATABS. 12 ; 13 ; Input: 14 ; X Name of device 15 ; A:Y CIO handler table address 16 ; 17 ; Returns: 18 ; N=1 HATABS is full. 19 ; C=0 Handler added successfully. 20 ; C=1 Handler already exists; X points to address entry 21 ; A:Y preserved (required by SDX 4.43rc) 22 ; 23 C322 .proc PHAddHandler 24 C322 48 pha 25 C323 98 tya 26 C324 48 pha 27 C325 8A txa 28 C326 A2 21 ldx #33 29 C328 search_loop: 30 C328 DD 1A 03 cmp hatabs,x 31 C32B F0 17 beq found_existing 32 C32D CA dex 33 C32E CA dex 34 C32F CA dex 35 C330 10 F6 bpl search_loop 36 37 C332 insert_loop: 38 C332 E8 inx 39 C333 E8 inx 40 C334 E8 inx 41 C335 BC 1A 03 ldy hatabs,x 42 C338 F0 10 beq found_empty 43 C33A E0 24 cpx #36 44 C33C D0 F4 bne insert_loop 45 46 ;oops... table is full! 47 C33E 68 pla 48 C33F 68 pla 49 C340 A9 FF lda #$ff 50 C342 38 sec 51 C343 60 rts 52 53 C344 found_existing: 54 C344 68 pla 55 C345 A8 tay 56 C346 68 pla 57 C347 E8 inx ;X=address offset, N=0 (not full) 58 C348 38 sec ;C=1 (already exists) 59 C349 60 rts 60 61 C34A found_empty: 62 C34A 9D 1A 03 sta hatabs,x 63 C34D 68 pla 64 C34E 9D 1B 03 sta hatabs+1,x 65 C351 68 pla 66 C352 9D 1C 03 sta hatabs+2,x 67 C355 0A asl ;N=0 (not full) 68 C356 18 clc ;C=0 (added successfully) 69 C357 60 rts 70 .endp 71 72 ;========================================================================== 73 ; Remove peripheral handler. 74 ; 75 ; Entry: 76 ; A:Y Address of handler to remove 77 ; 78 ; Exit: 79 ; C=0 Removal was successful 80 ; C=1 Removal failed (not found, broken chain or handler size was 81 ; non-zero) 82 ; 83 ; This routine unlinks a peripheral handler from the CHLINK chain. It fails 84 ; if the handler size in the handler table is non-zero, which means that it 85 ; was loaded on power-up. 86 ; 87 ; Note that this routine does NOT remove any handler entries in HATABS. 88 ; 89 C358 .proc PHRemoveHandler 90 ;stash handler address 91 C358 8C 4A 02 sty reladr 92 C35B 8D 4B 02 sta reladr+1 93 94 ;load "chain head" by pretending the chain address is in a handler 95 ;entry 96 C35E A2 E9 ldx #<(chlink-$12) 97 C360 A9 03 lda #>(chlink-$12) 98 99 C362 search_loop: 100 ;check if we're at the end 101 C362 A8 tay 102 C363 D0 04 bne not_end 103 C365 E0 00 cpx #0 104 C367 F0 23 beq epic_fail 105 106 C369 not_end: 107 ;save off the prev pointer 108 C369 86 36 stx ltemp 109 C36B 85 37 sta ltemp+1 110 111 ;load the next pointer 112 C36D A0 12 ldy #$12 113 C36F B1 36 lda (ltemp),y 114 C371 AA tax 115 C372 C8 iny 116 C373 B1 36 lda (ltemp),y 117 C375 CD 4B 02 cmp reladr+1 118 C378 D0 E8 bne search_loop 119 C37A EC 4A 02 cpx reladr 120 C37D D0 E3 bne search_loop 121 122 ;we've found it -- move it into a pointer var 123 C37F 86 4A stx zchain 124 C381 85 4B sta zchain+1 125 126 ;check if the handler size is zero 127 C383 A0 10 ldy #$10 128 C385 B1 4A lda (zchain),y 129 C387 C8 iny 130 C388 11 4A ora (zchain),y 131 C38A F0 02 beq size_ok 132 133 ;whoops... we can't remove this handler. 134 C38C epic_fail: 135 C38C 38 sec 136 C38D 60 rts 137 138 C38E size_ok: 139 ;unlink the handler 140 C38E A0 12 ldy #$12 141 C390 B1 4A lda (zchain),y ;load low byte 142 C392 AA tax ;stash it 143 C393 C8 iny 144 C394 B1 4A lda (zchain),y ;load high byte 145 C396 91 36 sta (ltemp),y ;prev->link_hi = next->link_hi 146 C398 88 dey 147 C399 8A txa 148 C39A 91 36 sta (ltemp),y ;prev->link_lo = next->link_lo 149 150 ;all done 151 C39C 18 clc 152 C39D 60 rts 153 .endp 154 155 156 ;========================================================================== 157 ; Init peripheral handler. 158 ; 159 ; Entry: 160 ; A:Y Address of handler table 161 ; C Set if MEMLO should be adjusted, cleared otherwise 162 ; 163 ; Exit: 164 ; C Cleared on success, set on failure 165 ; 166 ; Modified: 167 ; DVSTAT+2, DVSTAT+3 168 ; 169 ; See also: Sweet 16 OS Supplement part 3, Handler Loader 170 ; 171 C39E .proc PHInitHandler 172 ;save off the table pointer; we use DVSTAT+2/3 per the Sweet16 spec 173 C39E 8C EC 02 sty dvstat+2 174 C3A1 8D ED 02 sta dvstat+3 175 176 ;save off MEMLO adjust flag 177 C3A4 08 php 178 179 ;move chain to zero page pointer 180 C3A5 A2 E9 ldx #<(chlink-$12) 181 C3A7 A9 03 lda #>(chlink-$11) 182 183 ;find zero link 184 C3A9 end_search_loop: 185 ;move to next link 186 C3A9 86 4A stx zchain 187 C3AB 85 4B sta zchain+1 188 189 ;load low byte 190 C3AD A0 12 ldy #$12 191 C3AF B1 4A lda (zchain),y 192 C3B1 AA tax 193 C3B2 C8 iny 194 195 ;load high byte and check if it is zero 196 C3B3 B1 4A lda (zchain),y 197 C3B5 D0 F2 bne end_search_loop 198 199 ;check if low byte is zero too 200 C3B7 E0 00 cpx #0 201 C3B9 D0 EE bne end_search_loop 202 203 ;alright, we've found the end of the chain -- link in the table 204 C3BB AD ED 02 lda dvstat+3 205 C3BE 91 4A sta (zchain),y 206 C3C0 AA tax 207 C3C1 88 dey 208 C3C2 AD EC 02 lda dvstat+2 209 C3C5 91 4A sta (zchain),y 210 211 ;switch to the new link 212 C3C7 86 4B stx zchain+1 213 C3C9 85 4A sta zchain 214 215 ;zero the forward pointer 216 C3CB A0 13 ldy #$13 217 C3CD A9 00 lda #0 218 C3CF 91 4A sta (zchain),y 219 C3D1 88 dey 220 C3D2 91 4A sta (zchain),y 221 222 ;jump to handler init 223 C3D4 20 20 C4 jsr PHCallHandlerInit 224 C3D7 90 0A bcc init_ok 225 226 ;remove handler and return with error (C=1) 227 C3D9 A5 4A lda zchain 228 C3DB A4 4B ldy zchain+1 229 C3DD 20 58 C3 jsr PHRemoveHandler 230 C3E0 28 plp 231 C3E1 38 sec 232 C3E2 60 rts 233 234 C3E3 init_ok: 235 ;retrieve the MEMLO adjust flag 236 C3E3 28 plp 237 238 ;zero out the handler size if we aren't adjusting MEMLO 239 C3E4 B0 0A bcs adjust_memlo 240 241 C3E6 A0 10 ldy #$10 242 C3E8 A9 00 lda #0 243 C3EA AA tax 244 C3EB 91 4A sta (zchain),y 245 C3ED C8 iny 246 C3EE 91 4A sta (zchain),y 247 248 C3F0 adjust_memlo: 249 C3F0 20 09 C4 jsr PHAdjustMemlo 250 251 ;zero checksum 252 C3F3 A0 0F ldy #$0f 253 C3F5 A9 00 lda #0 254 C3F7 91 4A sta (zchain),y 255 256 ;compute checksum 257 C3F9 A0 11 ldy #$11 258 C3FB 18 clc 259 C3FC checksum_loop: 260 C3FC 71 4A adc (zchain),y 261 C3FE 88 dey 262 C3FF 10 FB bpl checksum_loop 263 C401 69 00 adc #0 264 265 ;store checksum 266 C403 A0 0F ldy #$0f 267 C405 91 4A sta (zchain),y 268 269 ;all done - return success 270 C407 18 clc 271 C408 60 rts 272 .endp 273 274 ;========================================================================== 275 C409 .proc PHAdjustMemlo 276 ;load handler size 277 C409 A0 11 ldy #$11 278 C40B B1 4A lda (zchain),y 279 C40D AA tax 280 C40E 88 dey 281 C40F B1 4A lda (zchain),y 282 283 ;adjust MEMLO by handler size 284 C411 18 clc 285 C412 6D E7 02 adc memlo 286 C415 8D E7 02 sta memlo 287 C418 8A txa 288 C419 6D E8 02 adc memlo+1 289 C41C 8D E8 02 sta memlo+1 290 C41F 60 rts 291 .endp 292 293 ;========================================================================== 294 ; Initializes a single handler pointed to by ZCHAIN. 295 ; 296 C420 .proc PHCallHandlerInit 297 C420 A5 4A lda zchain 298 C422 18 clc 299 C423 69 0B adc #$0b 300 C425 AA tax 301 C426 A5 4B lda zchain+1 302 C428 69 00 adc #0 303 C42A 48 pha 304 C42B 8A txa 305 C42C 48 pha 306 C42D 60 rts 307 .endp 308 309 ;========================================================================== 310 ; Reinitialize all handlers in the handler chain. 311 ; 312 C42E .proc PHReinitHandlers 313 ;move chain to zero page pointer 314 C42E AE FB 03 ldx chlink 315 C431 AD FC 03 lda chlink+1 316 317 ;find zero link 318 C434 init_loop: 319 ;move to next link 320 C434 86 4A stx zchain 321 C436 85 4B sta zchain+1 322 C438 05 4A ora zchain 323 C43A F0 2D beq init_done 324 325 ;recompute checksum (except for checksum byte) 326 C43C A0 11 ldy #$11 327 C43E 18 clc 328 C43F B1 4A 88 lda (zchain),y- 329 C442 71 4A 88 adc (zchain),y- 330 C445 88 dey 331 C446 71 4A 88 10 FB adc:rpl (zchain),y- 332 C44B 69 00 adc #0 333 334 ;check if the checksum matches 335 C44D A0 0F ldy #$0f 336 C44F D1 4A cmp (zchain),y 337 C451 D0 16 bne init_done 338 339 ;reinitialize the handler 340 C453 20 20 C4 jsr PHCallHandlerInit 341 C456 B0 11 bcs init_done 342 343 ;adjust MEMLO 344 C458 20 09 C4 jsr PHAdjustMemlo 345 346 ;check for a next link 347 C45B A0 13 ldy #$13 348 C45D B1 4A lda (zchain),y 349 C45F AA tax 350 C460 C8 iny 351 C461 B1 4A lda (zchain),y 352 C463 D0 CF bne init_loop 353 354 ;load high byte and check if it is zero 355 C465 E0 00 cpx #0 356 C467 D0 CB bne init_loop 357 358 C469 init_done: 359 C469 60 rts 360 .endp 361 362 ;========================================================================== 363 ; Startup poll for peripheral handlers. 364 ; 365 ; The protocol for initing handlers from the SIO bus is as follows: 366 ; 367 ; 1. Issue type 3 poll reset (4F/40/4F/4F). 368 ; 2. Issue type 3 poll (4F/40/00/00), reading 4 bytes. 369 ; 2a. If this poll fails with a timeout, we're done. 370 ; 2b. If the poll fails for any other reason, issue a type 3 null poll 371 ; (4F/40/4E/4E) and go back to step 2. 372 ; 3. Compare the size in DVSTAT+0/1 against the amount of memory between 373 ; MEMTOP and MEMLO. If there isn't enough, issue a type 3 null poll 374 ; and go to step 2. 375 ; 4. Call the relocating loader to load the handler. The handler is 376 ; loaded 128 bytes at a time using command $26 (&), AUX1=block, where 377 ; block 0 is the first block. 378 ; 5. Go back to step 2. 379 ; 380 C46A .proc PHStartupPoll 381 ;issue type 3 poll reset (address $4F, command $40, aux $4F4F, no data) 382 C46A A2 4F ldx #$4F 383 C46C 20 E4 C4 jsr do_simple_poll 384 385 ;issue type 3 poll (address $4F, command $40, aux $0000, read 4 bytes) 386 C46F poll_loop: 387 C46F A9 00 lda #$00 388 C471 8D 0A 03 sta daux1 389 C474 8D 0B 03 sta daux2 390 C477 8D 09 03 sta dbythi 391 C47A A9 EA 8D 04 03 A9 + mwa #dvstat dbuflo 392 C484 A9 04 8D 08 03 mva #4 dbytlo 393 C489 A9 40 8D 03 03 mva #$40 dstats 394 C48E 20 59 E4 jsr siov 395 C491 10 11 bpl poll_ok 396 C493 C0 8A cpy #SIOErrorTimeout 397 C495 D0 01 bne poll_fail 398 C497 exit: 399 C497 60 rts 400 C498 poll_fail: 401 ;!! - Black Box 2.16 firmware intercepts type 3 polls and forces 402 ;a user abort error (Y=$80), which we must exit on to avoid an infinite 403 ;loop. 404 C498 C0 80 cpy #$80 405 C49A F0 FB beq exit 406 407 ;we had a failure -- issue a null poll before trying another device 408 C49C A2 4E ldx #$4e 409 C49E 20 E4 C4 jsr do_simple_poll 410 C4A1 4C 6F C4 jmp poll_loop 411 412 C4A4 poll_ok: 413 ;DVSTAT now contains the following frame: 414 ; 415 ; DVSTAT+0 handler size, low byte (should be even) 416 ; DVSTAT+1 handler size, high byte 417 ; DVSTAT+2 device address 418 ; DVSTAT+3 peripheral revision number 419 420 ;Check whether we have enough room between MEMLO and MEMTOP to load 421 ;this handler -- remember that MEMTOP is inclusive. Also, we need to 422 ;alloc an additional byte if MEMLO is odd. 423 C4A4 AD E7 02 lda memlo 424 C4A7 AA tax 425 C4A8 6A ror 426 C4A9 8A txa 427 C4AA 6D EA 02 adc dvstat 428 C4AD AA tax 429 C4AE AD E8 02 lda memlo+1 430 C4B1 6D EB 02 adc dvstat+1 431 C4B4 CD E6 02 cmp memtop+1 432 C4B7 90 09 bcc mem_ok 433 C4B9 D0 DD bne poll_fail 434 C4BB EC E5 02 cpx memtop 435 C4BE B0 02 bcs mem_ok 436 C4C0 D0 D6 bne poll_fail 437 C4C2 mem_ok: 438 439 ;set up for handler load 440 C4C2 AD E7 02 lda memlo 441 C4C5 AA tax 442 C4C6 6A ror 443 C4C7 8A txa 444 C4C8 69 00 adc #0 445 C4CA 8D D1 02 sta loadad 446 C4CD AD E8 02 lda memlo+1 447 C4D0 69 00 adc #0 448 C4D2 8D D2 02 sta loadad+1 449 450 C4D5 AD EC 02 8D 00 03 mva dvstat+2 ddevic 451 452 C4DB 38 sec 453 C4DC 20 01 C5 jsr PHLoadHandler 454 C4DF B0 B7 bcs poll_fail 455 456 ;look for another device 457 C4E1 4C 6F C4 jmp poll_loop 458 459 ;-------------------------------------------------------------------------- 460 C4E4 do_simple_poll: 461 C4E4 A9 4F lda #$4f 462 C4E6 8D 00 03 sta ddevic 463 C4E9 8E 0A 03 stx daux1 464 C4EC 8E 0B 03 stx daux2 465 C4EF A9 40 lda #$40 466 C4F1 8D 02 03 sta dcomnd 467 C4F4 A9 01 lda #$01 468 C4F6 8D 01 03 sta dunit 469 C4F9 A9 00 lda #$00 470 C4FB 8D 03 03 sta dstats 471 C4FE 4C 59 E4 jmp siov 472 473 .endp 474 475 ;========================================================================== 476 ; Load peripheral handler over the SIO bus. 477 ; 478 ; Entry: 479 ; C Set to adjust MEMLO, clear to not 480 ; DDEVIC SIO address to load for loading 481 ; LOADAD Handler load address 482 ; 483 ; Modified: 484 ; All relocatable handler variables 485 ; DCB 486 ; DVSTAT 487 ; 488 C501 .proc PHLoadHandler 489 ;save MEMLO adjustment flag 490 C501 08 php 491 492 ;set zero-page relocation destination to $80 (should never be used) 493 C502 A9 80 8D D3 02 mva #$80 zloada 494 495 ;set up relocator get byte handler 496 C507 A9 40 8D CF 02 A9 + mwa #PHGetByte gbytea 497 498 ;set up for get byte, using command $26 and the cassette buffer 499 C511 A9 26 8D 02 03 mva #$26 dcomnd 500 C516 A2 00 8E 0A 03 mvx #0 daux1 501 C51B 8E 09 03 stx dbythi 502 C51E 8E 04 03 stx dbuflo 503 C521 CA dex 504 C522 86 3D stx bptr 505 C524 A9 04 8D 05 03 mva #$04 dbufhi 506 C529 A9 80 8D 08 03 mva #$80 dbytlo 507 508 ;load the handler 509 C52E 20 5A C5 jsr PHRelocateHandler 510 C531 B0 0B bcs reloc_fail 511 512 ;try to init handler, adjusting MEMLO as necessary 513 C533 AC D1 02 ldy loadad 514 C536 AD D2 02 lda loadad+1 515 C539 28 plp 516 C53A 20 9E C3 jsr PHInitHandler 517 C53D failed: 518 C53D 60 rts 519 C53E reloc_fail: 520 C53E 68 pla 521 C53F 60 rts 522 .endp 523 524 ;========================================================================== 525 ; Get byte handler used with relocating loader when loading handlers over 526 ; the SIO bus. 527 ; 528 C540 .proc PHGetByte 529 ;try to grab a byte 530 C540 A6 3D ldx bptr 531 C542 10 0C bpl fetch 532 533 ;issue SIO call to fetch next block 534 C544 A9 40 8D 03 03 mva #$40 dstats 535 C549 20 59 E4 jsr siov 536 C54C 30 0A bmi get_byte_fail 537 C54E A2 00 ldx #0 538 539 C550 fetch: 540 ;read next byte from cassette buffer 541 C550 BD 00 04 lda $0400,x 542 C553 E8 inx 543 C554 86 3D stx bptr 544 545 ;all clear 546 C556 18 clc 547 C557 60 rts 548 549 C558 get_byte_fail: 550 C558 38 sec 551 C559 60 rts 552 553 .endp 554 555 ;========================================================================== 556 ; Relocating loader. 557 ; 558 ; Modified: 559 ; LTEMP (word) 560 ; LCOUNT 561 ; RELADR 562 ; RECLEN 563 ; HIBYTE 564 ; RUNADR (word) 565 ; HIUSED (word) 566 ; ZHIUSE 567 ; 568 ; Record types: 569 ; Non-zp text $00 len { offset-lo offset-hi data* } 570 ; Zero-page text $01 len { offset-lo offset-hi data* } 571 ; Non-zp ref to non-zp $08 len { {offset lo-byte}* } 578 ; Zp >ref to non-zp $09 len { {offset lo-byte}* } 579 ; Absolute text $0A len { addr-lo addr-hi data* } 580 ; End record $0B self-start addr-lo addr-hi 581 ; 582 ; The references need some explanation: 583 ; - The program is split into two sections, a zero-page section and a 584 ; non-zero page section. The two sections are each contiguous. 585 ; - Both the zero-page and non-zero-page sections can reference each 586 ; other. 587 ; - Low-byte references include only the low byte of an address. 588 ; - High-byte references include only the high byte of an address. A 589 ; low byte offset is included in the relocation to enable this. 590 ; - Relocation records are always applied to the last text record 591 ; that was loaded. 592 ; 593 C55A .proc PHRelocateHandler 594 ;make the zero-page load address 16-bit 595 C55A A9 00 lda #0 596 C55C 8D D4 02 sta zloada+1 597 598 C55F reloc_loop: 599 ;get a control byte and stash it 600 C55F 20 58 C6 jsr PHRelocateGetByte 601 C562 8D 33 02 sta lcount 602 603 ;get the length or self-start byte 604 C565 20 58 C6 jsr PHRelocateGetByte 605 C568 8D 45 02 sta reclen 606 607 ;dispatch to handler 608 C56B 20 71 C5 jsr dispatch 609 610 ;process more records 611 C56E 4C 5F C5 jmp reloc_loop 612 613 C571 dispatch: 614 C571 AE 33 02 ldx lcount 615 C574 BC 80 C5 ldy cmd_table_ind_tab,x 616 C577 B9 90 C5 lda cmd_table_hi,y 617 C57A 48 pha 618 C57B B9 8C C5 lda cmd_table_lo,y 619 C57E 48 pha 620 C57F 60 rts 621 622 ;--------------------------------------------------------- 623 C580 cmd_table_ind_tab: 624 C580 00 00 01 01 01 01 + dta 0,0,1,1,1,1,1,1,2,2,0,3 625 626 C58C cmd_table_lo: 627 C58C 93 dta <(PHRelocateLoadText-1) 628 C58D D0 dta <(PHRelocateApplyFixups-1) 629 C58E 01 dta <(PHRelocateApplyHiFixups-1) 630 C58F 1F dta <(PHRelocateEnd-1) 631 632 C590 cmd_table_hi: 633 C590 C5 dta >(PHRelocateLoadText-1) 634 C591 C5 dta >(PHRelocateApplyFixups-1) 635 C592 C6 dta >(PHRelocateApplyHiFixups-1) 636 C593 C6 dta >(PHRelocateEnd-1) 637 .endp 638 639 ;========================================================================== 640 C594 .proc PHRelocateLoadText 641 ;retrieve the address into LTEMP 642 C594 20 58 C6 jsr PHRelocateGetByte 643 C597 85 36 sta ltemp 644 C599 20 58 C6 jsr PHRelocateGetByte 645 C59C 85 37 sta ltemp+1 646 647 ;check if we are doing an absolute load ($0A) 648 C59E AD 33 02 lda lcount 649 C5A1 C9 0A cmp #$0a 650 C5A3 F0 11 beq is_absolute 651 652 ;check whether we should use zero-page ($01) or non-zero-page ($00), 653 ;and adjust LTEMP 654 C5A5 0A asl 655 C5A6 AA tax 656 C5A7 18 BD D1 02 65 36 + adw loadad,x ltemp ltemp 657 658 C5B6 is_absolute: 659 ;init counter 660 C5B6 A9 00 lda #0 661 C5B8 8D 33 02 sta lcount 662 663 ;load reclen-2 bytes 664 C5BB CE 45 02 dec reclen 665 C5BE D0 0B bne load_loop_start 666 667 C5C0 load_loop: 668 C5C0 20 58 C6 jsr PHRelocateGetByte 669 C5C3 AC 33 02 ldy lcount 670 C5C6 EE 33 02 inc lcount 671 C5C9 91 36 sta (ltemp),y 672 C5CB load_loop_start: 673 C5CB CE 45 02 dec reclen 674 C5CE D0 F0 bne load_loop 675 C5D0 60 rts 676 .endp 677 678 ;========================================================================== 679 C5D1 .proc PHRelocateApplyFixups 680 ;get command byte and copy the appropriate reloc target into zchain 681 C5D1 AD 33 02 lda lcount 682 C5D4 4A lsr 683 C5D5 AE D1 02 ldx loadad 684 C5D8 C9 02 cmp #2 685 C5DA D0 03 sne 686 C5DC AE D3 02 ldx zloada 687 C5DF 86 4A stx zchain 688 689 ;set flag if we are doing a word reloc (types $06, $07) 690 C5E1 C9 03 cmp #3 691 C5E3 66 4B ror zchain+1 692 693 C5E5 reloc_loop: 694 ;fetch offset byte 695 C5E5 20 58 C6 jsr PHRelocateGetByte 696 C5E8 A8 tay 697 698 ;fixup low byte 699 C5E9 B1 36 lda (ltemp),y 700 C5EB 18 clc 701 C5EC 65 4A adc zchain 702 C5EE 91 36 sta (ltemp),y 703 704 ;check if we're doing a high byte reloc 705 C5F0 24 4B bit zchain+1 706 C5F2 10 08 bpl low_byte_only 707 708 ;fixup high byte 709 C5F4 C8 iny 710 C5F5 B1 36 lda (ltemp),y 711 C5F7 6D D2 02 adc loadad+1 712 C5FA 91 36 sta (ltemp),y 713 714 C5FC low_byte_only: 715 ;loop back if there is more fixup data 716 C5FC CE 45 02 dec reclen 717 C5FF D0 E4 bne reloc_loop 718 C601 60 rts 719 .endp 720 721 ;========================================================================== 722 C602 .proc PHRelocateApplyHiFixups 723 C602 reloc_loop: 724 ;fetch offset byte 725 C602 20 58 C6 jsr PHRelocateGetByte 726 C605 85 4A sta zchain 727 728 ;fetch low fixup byte 729 C607 20 58 C6 jsr PHRelocateGetByte 730 731 ;add low byte to base 732 C60A 18 clc 733 C60B 6D D1 02 adc loadad 734 735 ;fixup high byte 736 C60E A4 4A ldy zchain 737 C610 AD D2 02 lda loadad+1 738 C613 71 36 adc (ltemp),y 739 C615 91 36 sta (ltemp),y 740 741 ;loop back if there is more fixup data 742 C617 CE 45 02 dec reclen 743 C61A CE 45 02 dec reclen 744 C61D D0 E3 bne reloc_loop 745 C61F 60 rts 746 .endp 747 748 ;========================================================================== 749 C620 .proc PHRelocateEnd 750 ;read in the address to RUNADR 751 C620 20 58 C6 jsr PHRelocateGetByte 752 C623 8D C9 02 sta runadr 753 C626 20 58 C6 jsr PHRelocateGetByte 754 C629 8D CA 02 sta runadr+1 755 756 ;check the self-start byte 757 C62C AE 33 02 ldx lcount 758 C62F D0 0E bne do_self_start 759 760 ;no self-start... zero the addr and exit 761 C631 A9 00 lda #0 762 C633 8D C9 02 sta runadr 763 C636 8D CA 02 sta runadr+1 764 C639 xit: 765 C639 18 clc 766 C63A 68 pla 767 C63B 68 pla 768 C63C A0 01 ldy #1 769 C63E 60 rts 770 771 C63F do_self_start: 772 ;check if we need to relocate the address... if it 773 ;is absolute ($01), we're done 774 C63F CA dex 775 C640 F0 F7 beq xit 776 777 ;add the non-zp base address and exit 778 C642 18 AD C9 02 6D D1 + adw runadr loadad runadr 779 C655 4C 39 C6 jmp xit 780 .endp 781 782 ;========================================================================== 783 C658 .proc PHRelocateGetByte 784 C658 20 60 C6 jsr call_get_byte 785 C65B 90 02 bcc get_byte_ok 786 C65D 68 pla 787 C65E 68 pla 788 C65F get_byte_ok: 789 C65F 60 rts 790 791 C660 call_get_byte: 792 C660 6C CF 02 jmp (gbytea) 793 .endp 83 C663 _KERNEL_REPORT_MODULE_SIZE 'Peripheral Handler routines', 0 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'Peripheral Handler routines' 1 $C663 -> $0341($0000) Peripheral Handler routines 3 = C663 .def ?@_kernel_lastpt = * Source: source/main.xasm 84 85 .ifdef _KERNEL_816 86 icl 'syscall816.s' 87 icl 'sysdev816.s' 88 .endif 89 90 C663 org $cc00 91 CC00 icl 'atariifont.inc' Source: source/Shared/atariifont.inc 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Character Font 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 CC00 00 00 00 00 00 00 + ins 'atariifont.bin',$0,$400 92 93 D000 org $d000 94 D000 icl 'bootscreen.s' Source: source/Shared/bootscreen.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Boot Screen 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 37 opt l+ 38 39 009B org $5000,$d000 40 opt o+f+ 41 42 5000 .proc BootScreen 43 D000 18 clc 44 5001 24 dta {bit $00} 45 5002 boot_entry: 46 5002 38 sec 47 5003 08 php 48 49 5004 20 6C 52 jsr BootClearRam 50 51 5007 28 plp 52 5008 66 80 ror canboot 53 54 ;relocate data down to RAM 55 500A A9 D0 85 8A A9 56 + mwa #[.adr BootRamDataStart]+$5000-$D000 scrnad1 56 5012 A9 00 85 8C A9 30 + mwa #BootRamDataStart scrnad2 57 58 .if >[BootRamDataEnd-BootRamDataStart] 59 ldx #>[BootRamDataEnd-BootRamDataStart] 60 ldy #0 61 page_copy: 62 mva:rne (scrnad1),y (scrnad2),y+ 63 inc scrnad1+1 64 inc scrnad2+1 65 dex 66 bne page_copy 67 .endif 68 69 .if <[BootRamDataEnd-BootRamDataStart] 70 501A byte_copy: 71 501A B1 8A 91 8C C8 mva (scrnad1),y (scrnad2),y+ 72 501F C0 7A cpy #<[BootRamDataEnd-BootRamDataStart] 73 5021 D0 F7 bne byte_copy 74 .endif 75 76 ;copy down bitmap graphics 77 5023 A9 13 85 8C A9 32 + mwa #playfield3+19 scrnad2 78 502B A9 C8 85 8A A9 54 + mwa #BootDriveImage scrnad1 79 5033 A2 28 ldx #40 80 5035 blit_loop: 81 5035 A0 0C ldy #12 82 5037 B1 8A 91 8C 88 10 + mva:rpl (scrnad1),y (scrnad2),y- 83 503E 18 clc 84 503F A5 8C lda scrnad2 85 5041 69 20 adc #$20 86 5043 85 8C sta scrnad2 87 5045 90 02 E6 8D scc:inc scrnad2+1 88 5049 A5 8A lda scrnad1 89 504B 18 clc 90 504C 69 0D adc #13 91 504E 85 8A sta scrnad1 92 5050 90 02 E6 8B scc:inc scrnad1+1 93 5054 CA dex 94 5055 D0 DE bne blit_loop 95 96 ;set up display and interrupts 97 5057 78 sei 98 5058 20 9D 54 jsr BootSwapVectors 99 505B A9 00 8D 0E D4 mva #0 nmien 100 5060 A9 C0 8D 0E D4 mva #$c0 nmien 101 5065 A9 2C 8D 07 D4 mva #>player0 pmbase 102 103 506A A2 0C ldx #$0c 104 506C BD 16 52 9D 00 D0 + mva:rpl gtia_data,x hposp0,x- 105 106 5075 A9 03 8D 1D D0 mva #$03 gractl 107 507A 58 cli 108 109 ;init sprites 0,1 110 507B A2 00 ldx #0 111 507D A0 20 ldy #32 112 507F sprinit: 113 507F BD 3F 54 99 00 2C mva spr0dat,x player0,y 114 5085 BD 47 54 99 00 2D + mva spr1dat,x player1,y+ 115 508C 98 tya 116 508D 29 0F and #$0f 117 508F D0 EE bne sprinit 118 5091 E8 inx 119 5092 E0 08 cpx #8 120 5094 D0 E9 bne sprinit 121 122 5096 A9 00 lda #0 123 5098 85 88 sta char_x 124 509A 85 89 sta char_y 125 126 509C 85 8E sta msgadr 127 509E imloop: 128 509E A4 8E ldy msgadr 129 50A0 E6 8E inc msgadr 130 50A2 B9 D6 52 lda BootMessage,y 131 50A5 C9 FF cmp #$ff 132 50A7 F0 06 beq imdone 133 50A9 20 A9 53 jsr PlotChar 134 50AC 4C 9E 50 jmp imloop 135 50AF imdone: 136 137 50AF A9 00 lda #0 138 50B1 85 9A sta phase 139 50B3 loop1: 140 50B3 A2 00 ldx #0 141 50B5 8A txa 142 50B6 sprclr: 143 50B6 9D 00 2E sta player2,x 144 50B9 9D 00 2F sta player3,x 145 50BC CA dex 146 50BD D0 F7 bne sprclr 147 148 ;save off the current RTCLOK 149 50BF AD 0B D4 D0 FB lda:rne vcount 150 50C4 A2 02 ldx #2 151 50C6 B5 12 95 94 CA 10 + mva:rpl rtclok,x rtcsav,x- 152 153 ;clear the break key in case it was pressed to interrupt the last read 154 50CD 86 11 stx brkkey 155 156 ;issue status request to D1: 157 50CF A9 01 lda #1 158 50D1 8D 01 03 sta dunit 159 50D4 A9 53 8D 02 03 mva #$53 dcomnd 160 50D9 20 53 E4 jsr dskinv 161 50DC 30 21 bmi loop2 162 163 ;try to read sector #1 on D1: 164 50DE A9 52 8D 02 03 mva #$52 dcomnd 165 50E3 A9 00 8D 04 03 A9 + mwa #$0400 dbuflo 166 50ED A9 01 8D 0A 03 A9 + mwa #1 daux1 167 50F7 20 53 E4 jsr dskinv 168 50FA 30 03 bmi loop2 169 50FC 4C 23 52 jmp BootScreenExit 170 50FF loop2: 171 50FF A5 14 lda rtclok+2 172 5101 C5 14 F0 FC cmp:req rtclok+2 173 5105 A5 14 lda rtclok+2 174 5107 C5 14 F0 FC cmp:req rtclok+2 175 176 510B A6 9A ldx phase 177 510D BD 87 51 85 92 BD + mwa phasetab+1,x spricl 178 179 5117 BC 86 51 ldy phasetab,x 180 511A A9 00 lda #0 181 511C 85 90 sta spracl 182 511E 85 91 sta sprach 183 5120 clloop: 184 5120 99 00 2B sta missiles,y 185 5123 99 00 2E sta player2,y 186 5126 99 00 2F sta player3,y 187 5129 88 dey 188 512A 30 F4 bmi clloop 189 190 512C BC 86 51 ldy phasetab,x 191 512F A9 FF lda #$ff 192 5131 blitloop: 193 5131 A6 91 ldx sprach 194 5133 BD 4F 54 lda sprdat2,x 195 5136 99 00 2E sta player2,y 196 5139 BD 6F 54 lda sprdat3,x 197 513C 99 00 2F sta player3,y 198 199 513F C8 iny 200 5140 18 A5 90 65 92 85 + adw spracl spricl spracl 201 514D A5 91 lda sprach 202 514F C9 20 cmp #$20 203 5151 90 DE bcc blitloop 204 5153 A9 00 lda #0 205 5155 blitloop2: 206 5155 99 00 2B sta missiles,y 207 5158 99 00 2E sta player2,y 208 515B 99 00 2F sta player3,y 209 515E C8 iny 210 515F C0 40 cpy #$40 211 5161 D0 F2 bne blitloop2 212 213 ;if this is the first animation frame, wait a bit after it 214 5163 A5 9A lda phase 215 5165 D0 0C bne no_wait 216 217 5167 A2 19 ldx #25 218 5169 waitloop: 219 5169 A5 14 lda rtclok+2 220 516B C5 14 F0 FC cmp:req rtclok+2 221 516F CA dex 222 5170 D0 F7 bne waitloop 223 5172 8A txa 224 225 5173 no_wait: 226 5173 18 clc 227 5174 69 03 adc #3 228 5176 85 9A sta phase 229 5178 C9 90 cmp #phasetab_end-phasetab 230 517A B0 03 4C FF 50 scs:jmp loop2 231 232 517F A9 00 lda #0 233 5181 85 9A sta phase 234 5183 4C B3 50 jmp loop1 235 236 5186 phasetab: 237 5186 8A AA 00 89 AB 00 + :48 dta $7a+[48-#]/3, a([$200+#*#*3]/3) 238 5216 phasetab_end: 239 240 5216 gtia_data: 241 5216 40 60 A4 98 68 60 + dta $40,$60,$a4,$98,$68,$60,$00,$00 242 521E 03 03 00 03 0F dta $03,$03,$00,$03,$0f 243 .endp 244 245 ;========================================================================== 246 5223 .proc BootScreenExit 247 5223 78 sei 248 5224 A9 00 lda #0 249 5226 8D 0E D4 sta nmien 250 251 ;wait for vertical blank 252 5229 A2 7C ldx #248/2 253 522B EC 0B D4 D0 FB cpx:rne vcount 254 255 ;shut off display 256 5230 8D 00 D4 sta dmactl 257 5233 8D 2F 02 sta sdmctl 258 259 ;reset GTIA (but not VBXE) 260 5236 9D 00 D0 E8 10 FA sta:rpl $d000,x+ 261 262 ;check if we can continue the initial boot process 263 523C 24 80 bit canboot 264 523E 30 03 bmi continue_boot 265 266 ;invoke cold start 267 5240 4C 77 E4 jmp coldsv 268 269 5243 continue_boot: 270 ;swap interrupt handler registers back 271 5243 20 9D 54 jsr BootSwapVectors 272 273 ;re-wipe RAM areas we used 274 5246 20 6C 52 jsr BootClearRam 275 276 ;re-enable IRQs (but VBI is still disabled) 277 5249 58 cli 278 279 ;print a clear screen character to clear any latent BOOT ERRORs 280 524A A9 7D lda #$7d 281 524C A2 00 ldx #0 282 524E 8E 48 03 stx icbll 283 5251 8E 49 03 stx icblh 284 5254 A0 0B ldy #CIOCmdPutChars 285 5256 8C 42 03 sty iccmd 286 5259 20 56 E4 jsr ciov 287 288 ;re-enable VBI and wait for VBI stage 2 to run once 289 525C A9 40 8D 0E D4 mva #$40 nmien 290 291 5261 A9 FF lda #$ff 292 5263 8D 83 02 sta ptrig7 293 5266 2C 83 02 30 FB bit:rmi ptrig7 294 295 ;all done, return to boot code with sector 1 loaded at $0400 296 526B 60 rts 297 .endp 298 299 ;========================================================================== 300 526C .proc BootClearRam 301 ;clear $2000-$37FF 302 526C A9 00 lda #0 303 526E A8 tay 304 526F 85 84 sta charadr 305 5271 A2 20 ldx #$20 306 5273 86 85 stx charadr+1 307 5275 A2 18 ldx #$18 308 5277 clear_loop: 309 5277 91 84 C8 D0 FB sta:rne (charadr),y+ 310 527C E6 85 inc charadr+1 311 527E CA dex 312 527F D0 F6 bne clear_loop 313 314 ;clear user page zero 315 5281 95 80 E8 10 FB sta:rpl $80,x+ 316 317 ;all done 318 5286 60 rts 319 .endp 320 321 ;========================================================================== 322 5287 .proc BootScreenVbi 323 5287 AD 4E 30 lda pfadr+1 324 528A 49 05 eor #$05 325 528C 8D 4E 30 sta pfadr+1 326 528F AD C5 02 lda color1 327 5292 8D 17 D0 sta colpf1 328 5295 AD C6 02 lda color2 329 5298 8D 18 D0 sta colpf2 330 529B 6C 00 30 jmp (BootVecVbi) 331 .endp 332 333 ;========================================================================== 334 529E .proc BootScreenIrq 335 529E 2C 0F D4 bit nmist 336 52A1 10 20 bpl do_irq 337 = 52A3 .def :BootScreenDli 338 52A3 48 pha 339 52A4 8A txa 340 52A5 48 pha 341 52A6 AD 0B D4 lda vcount 342 52A9 C9 48 cmp #72 343 52AB B0 19 bcs split 344 52AD 4A lsr 345 52AE 4A lsr 346 52AF AA tax 347 52B0 BD 8A 54 lda coltab-5,x 348 52B3 8D 0A D4 sta wsync 349 52B6 8D 12 D0 sta colpm0 350 52B9 8D 13 D0 sta colpm1 351 52BC xit: 352 52BC 8D 0F D4 sta nmires 353 52BF 68 pla 354 52C0 AA tax 355 52C1 68 pla 356 52C2 40 rti 357 52C3 do_irq: 358 52C3 6C 02 30 jmp (BootVecIrq) 359 52C6 split: 360 52C6 A9 50 lda #$50 361 52C8 A2 5C ldx #$5c 362 52CA 8D 0A D4 sta wsync 363 52CD 8D 18 D0 sta colpf2 364 52D0 8E 17 D0 stx colpf1 365 366 52D3 4C BC 52 jmp xit 367 .endp 368 369 ;========================================================================== 370 52D6 .local BootMessage 371 ; 0123456789012345678901234567890123456789012345678901234567890123 372 52D6 21 6C 74 69 72 72 + dta d"AltirraOS" 373 52DF _KERNELSTR_BIOS_NAME_INTERNAL Macro: _KERNELSTR_BIOS_NAME_INTERNAL [Source: source/main.xasm] 4 52DF 00 66 6F 72 00 38 + dta d" for XL/XE/XEGS" Source: source/Shared/bootscreen.s 374 52EE 00 dta d" " 375 52EF _KERNELSTR_VERSION_INTERNAL Macro: _KERNELSTR_VERSION_INTERNAL [Source: source/Shared/version.inc] 1 52EF 13 0E 12 16 dta "3.26" Source: source/Shared/bootscreen.s 376 377 52F3 9B dta $9b 378 379 .ifdef _KERNEL_816 380 dta d"Copyright (C) 2018-2019 Avery Lee",$9b 381 .else 382 52F4 23 6F 70 79 72 69 + dta d"Copyright (C) 2012-2019 Avery Lee",$9b 383 .endif 384 385 5316 21 6C 6C 00 32 69 + dta d"All Rights Reserved",$9b 386 532A 34 68 69 73 00 69 + dta d"This is a substitute for the standard OS ROM. See the help file",$9b 387 536A 66 6F 72 00 68 6F + dta d"for how to use real Atari ROM images for higher compatibility." 388 53A8 FF dta $ff 389 .endl 390 391 ;========================================================================== 392 53A9 plotchar: 393 53A9 C9 9B cmp #$9b 394 53AB D0 07 bne not_eol 395 53AD A9 00 85 88 mva #0 char_x 396 53B1 E6 89 inc char_y 397 53B3 60 rts 398 53B4 not_eol: 399 53B4 85 84 sta charadr 400 401 53B6 A9 00 lda #0 402 53B8 85 8A sta scrnad1 403 53BA 85 8C sta scrnad2 404 53BC A5 89 lda char_y 405 53BE 09 20 ora #>playfield 406 53C0 85 8B sta scrnad1+1 407 53C2 18 clc 408 53C3 69 05 adc #$05 409 53C5 85 8D sta scrnad2+1 410 411 53C7 A5 88 lda char_x 412 53C9 4A lsr 413 53CA 85 83 sta charpos 414 53CC 6A ror 415 53CD 85 87 sta charodd 416 417 53CF A9 1C lda #$e0/8 418 53D1 A2 03 ldx #3 419 53D3 shlloop: 420 53D3 06 84 asl charadr 421 53D5 2A rol 422 53D6 CA dex 423 53D7 D0 FA bne shlloop 424 53D9 85 85 sta charadr+1 425 426 53DB 18 clc 427 53DC rowloop: 428 53DC A2 04 ldx #4 429 53DE A0 00 ldy #0 430 53E0 B1 84 lda (charadr),y 431 53E2 4A lsr 432 53E3 bitloop: 433 53E3 4A lsr 434 53E4 66 81 ror chardt1 435 53E6 4A lsr 436 53E7 66 82 ror chardt2 437 53E9 CA dex 438 53EA D0 F7 bne bitloop 439 440 53EC A4 83 ldy charpos 441 53EE 24 87 bit charodd 442 53F0 30 12 bmi odd 443 53F2 A5 82 lda chardt2 444 53F4 51 8C eor (scrnad2),y 445 53F6 29 0F and #$0f 446 53F8 45 82 eor chardt2 447 53FA 91 8C sta (scrnad2),y 448 449 53FC A5 81 lda chardt1 450 53FE 51 8A eor (scrnad1),y 451 5400 29 0F and #$0f 452 453 5402 10 1E bpl even 454 5404 odd: 455 5404 A5 81 lda chardt1 456 5406 4A lsr 457 5407 4A lsr 458 5408 4A lsr 459 5409 4A lsr 460 540A 85 81 sta chardt1 461 540C A5 82 lda chardt2 462 540E 4A lsr 463 540F 4A lsr 464 5410 4A lsr 465 5411 4A lsr 466 5412 85 82 sta chardt2 467 5414 51 8C eor (scrnad2),y 468 5416 29 F0 and #$f0 469 5418 45 82 eor chardt2 470 541A 91 8C sta (scrnad2),y 471 541C A5 81 lda chardt1 472 541E 51 8A eor (scrnad1),y 473 5420 29 F0 and #$f0 474 5422 even: 475 5422 45 81 eor chardt1 476 5424 91 8A sta (scrnad1),y 477 5426 E6 84 inc charadr 478 5428 98 tya 479 5429 18 clc 480 542A 69 20 adc #$20 481 542C 85 83 sta charpos 482 542E 90 AC bcc rowloop 483 484 ;update position 485 5430 E6 88 inc char_x 486 5432 A6 88 ldx char_x 487 5434 E0 40 cpx #64 488 5436 90 06 bcc done 489 5438 A9 00 85 88 mva #0 char_x 490 543C E6 89 inc char_y 491 543E done: 492 543E 60 rts 493 494 ;========================================================================== 495 543F spr0dat: 496 543F 00 dta %00000000 497 5440 03 dta %00000011 498 5441 0F dta %00001111 499 5442 3C dta %00111100 500 5443 3C dta %00111100 501 5444 3F dta %00111111 502 5445 3C dta %00111100 503 5446 00 dta %00000000 504 505 5447 spr1dat: 506 5447 00 dta %00000000 507 5448 C0 dta %11000000 508 5449 F0 dta %11110000 509 544A 3C dta %00111100 510 544B 3C dta %00111100 511 544C FC dta %11111100 512 544D 3C dta %00111100 513 544E 00 dta %00000000 514 515 544F sprdat2: 516 544F 00 dta %00000000 517 5450 00 dta %00000000 518 5451 18 dta %00011000 519 5452 3C dta %00111100 520 5453 3C dta %00111100 521 5454 3C dta %00111100 522 5455 3C dta %00111100 523 5456 3C dta %00111100 524 5457 3C dta %00111100 525 5458 18 dta %00011000 526 5459 00 dta %00000000 527 545A 00 dta %00000000 528 545B E7 dta %11100111 529 545C 81 dta %10000001 530 545D 81 dta %10000001 531 545E 00 dta %00000000 532 545F 00 dta %00000000 533 5460 81 dta %10000001 534 5461 81 dta %10000001 535 5462 E7 dta %11100111 536 5463 00 dta %00000000 537 5464 00 dta %00000000 538 5465 00 dta %00000000 539 5466 00 dta %00000000 540 5467 00 dta %00000000 541 5468 00 dta %00000000 542 5469 00 dta %00000000 543 546A 00 dta %00000000 544 546B 00 dta %00000000 545 546C 00 dta %00000000 546 546D 00 dta %00000000 547 546E 00 dta %00000000 548 549 546F sprdat3: 550 546F FF dta %11111111 551 5470 FF dta %11111111 552 5471 FF dta %11111111 553 5472 FF dta %11111111 554 5473 FF dta %11111111 555 5474 FF dta %11111111 556 5475 FF dta %11111111 557 5476 FF dta %11111111 558 5477 FF dta %11111111 559 5478 FF dta %11111111 560 5479 FF dta %11111111 561 547A FF dta %11111111 562 547B E7 dta %11100111 563 547C E7 dta %11100111 564 547D E7 dta %11100111 565 547E E7 dta %11100111 566 547F E7 dta %11100111 567 5480 E7 dta %11100111 568 5481 E7 dta %11100111 569 5482 E7 dta %11100111 570 5483 FF dta %11111111 571 5484 FF dta %11111111 572 5485 FF dta %11111111 573 5486 FF dta %11111111 574 5487 FF dta %11111111 575 5488 FF dta %11111111 576 5489 7F dta %01111111 577 548A FF dta %11111111 578 548B FF dta %11111111 579 548C FF dta %11111111 580 548D FF dta %11111111 581 548E FF dta %11111111 582 583 ;========================================================================== 584 585 ;========================================================================== 586 548F coltab: 587 548F 1A dta $1a 588 5490 FA dta $fa 589 5491 EA dta $ea 590 5492 DA dta $da 591 5493 CA dta $ca 592 5494 BA dta $ba 593 5495 AA dta $aa 594 5496 9A dta $9a 595 5497 8A dta $8a 596 5498 7A dta $7a 597 5499 6A dta $6a 598 549A 5A dta $5a 599 600 549B 0E 50 dta $0E,$50 601 602 ;========================================================================== 603 549D .proc BootSwapVectors 604 549D A2 13 ldx #vec_offsets_end-vec_offsets-1 605 549F loop: 606 549F BC B4 54 ldy vec_offsets,x 607 54A2 B9 00 02 lda $0200,y 608 54A5 48 pha 609 54A6 BD 00 30 lda BootVectors,x 610 54A9 99 00 02 sta $0200,y 611 54AC 68 pla 612 54AD 9D 00 30 sta BootVectors,x 613 54B0 CA dex 614 54B1 10 EC bpl loop 615 54B3 60 rts 616 617 54B4 vec_offsets: 618 54B4 22 dta vvblki-$0200 619 54B5 23 dta vvblki-$0200+1 620 54B6 16 dta vimirq-$0200 621 54B7 17 dta vimirq-$0200+1 622 54B8 00 dta vdslst-$0200 623 54B9 01 dta vdslst-$0200+1 624 54BA 30 dta sdlstl-$0200 625 54BB 31 dta sdlsth-$0200 626 54BC C0 dta pcolr0-$0200 627 54BD C1 dta pcolr1-$0200 628 54BE C2 dta pcolr2-$0200 629 54BF C3 dta pcolr3-$0200 630 54C0 C4 dta color0-$0200 631 54C1 C5 dta color1-$0200 632 54C2 C6 dta color2-$0200 633 54C3 C7 dta color3-$0200 634 54C4 C8 dta color4-$0200 635 54C5 2F dta sdmctl-$0200 636 54C6 6F dta gprior-$0200 637 54C7 44 dta coldst-$0200 638 54C8 vec_offsets_end: 639 .endp 640 641 ;========================================================================== 642 54C8 .proc BootDriveImage 643 54C8 icl 'driveimage.inc' Source: source/Shared/driveimage.inc 1 ;Made from driveimage.bmp using driveimageconv.cpp 2 54C8 00 00 00 0A AA AA + dta %00000000,%00000000,%00000000,%00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000,%00000000,%00000000,%00000000 3 54D5 02 AA AA AA AA AA + dta %00000010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101000,%00000000 4 54E2 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000 5 54EF 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000 6 54FC 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000 7 5509 0A 55 55 55 55 55 + dta %00001010,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01011010,%00000000 8 5516 2A 55 55 55 55 55 + dta %00101010,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01011010,%10000000 9 5523 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10000000 10 5530 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10000000 11 553D 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10000000 12 554A 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10000000 13 5557 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000 14 5564 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000 15 5571 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000 16 557E A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000 17 558B A5 55 55 55 55 55 + dta %10100101,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010101,%10100000 18 5598 A5 55 55 55 55 55 + dta %10100101,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010101,%10100000 19 55A5 A5 55 57 FF FF FF + dta %10100101,%01010101,%01010111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11010101,%10100000 20 55B2 A5 55 57 FF FF FF + dta %10100101,%01010101,%01010111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11010101,%10100000 21 55BF A5 55 57 FF FF FF + dta %10100101,%01010101,%01010111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11010101,%10100000 22 55CC A5 55 55 55 55 55 + dta %10100101,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010101,%10100000 23 55D9 A5 55 55 55 55 55 + dta %10100101,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010101,%10100000 24 55E6 A5 55 55 55 55 55 + dta %10100101,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010101,%10100000 25 55F3 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000 26 5600 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000 27 560D A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000 28 561A A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000 29 5627 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000 30 5634 A9 55 55 55 55 55 + dta %10101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10100000 31 5641 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%11111111,%11111111,%01010101,%01010101,%01010101,%01010110,%10000000 32 564E 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010110,%10000000 33 565B 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010110,%10000000 34 5668 29 55 55 55 55 55 + dta %00101001,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010110,%10000000 35 5675 2A 55 55 55 55 55 + dta %00101010,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01011010,%10000000 36 5682 0A 55 55 55 55 55 + dta %00001010,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01010101,%01011010,%00000000 37 568F 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000 38 569C 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000 39 56A9 0A AA AA AA AA AA + dta %00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000 40 56B6 02 AA AA AA AA AA + dta %00000010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101010,%10101000,%00000000 41 56C3 00 00 00 0A AA AA + dta %00000000,%00000000,%00000000,%00001010,%10101010,%10101010,%10101010,%10101010,%10101010,%00000000,%00000000,%00000000,%00000000 644 .endp 645 646 ;========================================================================== 647 ; Data relocated to RAM 648 ; 649 56D0 org $3000,*-$5000+$d000 650 651 = 3000 BootRamDataStart = * 652 653 3000 BootVectors: 654 3000 87 52 BootVecVbi dta a(BootScreenVbi) 655 3002 9E 52 BootVecIrq dta a(BootScreenIrq) 656 3004 A3 52 BootVecDli dta a(BootScreenDli) 657 3006 14 30 BootVecDlist dta a(BootDlist) 658 3008 color_table: 659 3008 00 dta $00 660 3009 00 dta $00 661 300A 02 dta $02 662 300B 00 dta $00 663 300C 08 dta $08 664 300D 0C dta $0C 665 300E 02 dta $02 666 300F 14 dta $14 667 3010 50 dta $50 668 3011 3D dta $3d ;sdmctl 669 3012 01 dta $01 ;gprior 670 3013 FF dta $ff ;coldst, to force cold reboot if RESET pressed 671 672 3014 BootDlist: 673 3014 70 70 70 70 :4 dta $70 674 3018 F0 F0 F0 F0 F0 F0 + :8 dta $F0 675 676 ;drive image (40 lines x 32 bytes = $500 bytes 677 3020 4E 00 32 dta $4E,a(playfield3) 678 3023 0E 0E 0E 0E 0E 0E :6 dta $0E 679 3029 8E dta $8E 680 302A 0E 0E 0E 0E 0E 0E + :4 dta $0E,$0E,$0E,$0E,$0E,$0E,$0E,$8E 681 682 304A F0 dta $F0 683 304B 70 dta $70 684 685 ;80-col text screen (2x 40 rows) 686 304C 4F 00 20 dta $4F,a(playfield) 687 = 304D pfadr = *-2 688 304F 0F 0F 0F 0F 0F 0F + :7 dta $0F 689 3056 0F 0F 0F 0F 0F 0F + :8 dta $0F 690 305E 0F 0F 0F 0F 0F 0F + :8 dta $0F 691 3066 70 dta $70 692 3067 0F 0F 0F 0F 0F 0F + :8 dta $0F 693 306F 0F 0F 0F 0F 0F 0F + :8 dta $0F 694 3077 41 14 30 dta $41,a(BootDlist) 695 696 = 307A BootRamDataEnd = * 697 698 ;========================================================================== 699 ; Version block for emulator 700 ; 701 307A org $d7f8 702 D7F8 _KERNELSTR_VERSION Macro: _KERNELSTR_VERSION [Source: source/Shared/version.inc] 1 D7F8 33 2E 32 36 dta '3.26' Source: source/Shared/bootscreen.s 703 D7FC 00 dta 0 704 705 706 D7FD org $d7ff 707 D7FF 00 dta 0 708 729 opt l+ 730 3200 org $d800 95 96 opt f+ 97 .endif 98 99 D800 org $d800 100 101 D800 icl 'mathpack.s' Source: source/Shared/mathpack.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Decimal Floating-Point Math Pack 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 ; 12 ; Known problems: 13 ; Currently incompatible with BASIC XE due to it relying on $DE-DF not 14 ; being modified by FADD/FSUB. 15 ; 16 ;========================================================================== 17 ; 18 ; Notes 19 ; 20 ; AFP FMUL 21 ; |FASC.FDIV 22 ; |.IPF.|PLYEVL 23 ; |.|FPI|.EXP 24 ; |.|.FADD|REDRNG 25 ; |.|.|.|.|.LOG 26 ; vvvvvvvvvvv 27 ; $D4 FR0 M MMM. 28 ; $D5 | M MMM. 29 ; $D6 | M MMM. 30 ; $D7 | M MMM. 31 ; $D8 | M MMM. 32 ; $D9 v M MMM. 33 ; $DA FR2 {FRE} TTTTTTT. 34 ; $DB | TT TTTT. 35 ; $DC | TT TTTT. 36 ; $DD | TT TTTT. 37 ; $DE | T TTT. [1,2] 38 ; $DF v TTT. [1,2] 39 ; $E0 FR1 MM . [3] 40 ; $E1 | MM . [3] 41 ; $E2 | MM . [3] 42 ; $E3 | MM . [3] 43 ; $E4 | MM . [3] 44 ; $E5 v MM . [3] 45 ; $E6 FR3 {FR2} . . 46 ; $E7 . . 47 ; $E8 . . 48 ; $E9 . . 49 ; $EA . . 50 ; $EB . . 51 ; $EC {FRX} . . 52 ; $ED {EEXP} . . 53 ; $EE {NSIGN} . . 54 ; $EF {ESIGN} . . 55 ; $F0 {FCHRFLG} . . 56 ; $F1 {DIGRT} . . 57 ; $F2 CIX . . 58 ; $F3 INBUFF . . 59 ; $F4 v . . 60 ; $F5 {ZTEMP1} . . 61 ; $F6 v . . 62 ; $F7 {ZTEMP4} . . 63 ; $F8 v . . 64 ; $F9 {ZTEMP3} . . 65 ; $FA v . . 66 ; $FB DEGFLG/RADFLG . . 67 ; $FC FLPTR . . 68 ; $FD v . . 69 ; $FE FPTR2 . . 70 ; $FF v . . 71 ; $05E0 PLYARG T T 72 ; $05E1 | T T 73 ; $05E2 | T T 74 ; $05E3 | T T 75 ; $05E4 | T T 76 ; $05E5 v T T 77 ; $05E6 FPSCR TT 78 ; $05E7 | TT 79 ; $05E8 | TT 80 ; $05E9 | TT 81 ; $05EA | TT 82 ; $05EB v TT 83 ; $05EC FPSCR1 84 ; $05ED | 85 ; $05EE | 86 ; $05EF | 87 ; $05F0 | 88 ; $05F1 v 89 ; 90 ; Notes: 91 ; [1] BASIC XE relies on $DE/DF not being touched by FADD, or FOR/NEXT 92 ; breaks. 93 ; [2] MAC/65 relies on $DE/DF not being touched by IPF. 94 ; [3] DARG relies on FPI not touching FR1. 95 ; [4] ACTris 1.2 relies on FASC not touching lower parts of FR2. 96 ; 97 98 .macro ckaddr 99 .if * <> %%1 100 .error 'Incorrect address: ',*,' != ',%%1 101 .endif 102 .endm 103 104 .macro fixadr 105 .if * < %%1 106 .print (%%1-*),' bytes free before ',%%1 107 org %%1 108 .elif * > %%1 109 .error 'Out of space: ',*,' > ',%%1,' (',*-%%1,' bytes over)' 110 .endif 111 .endm 112 113 ;========================================================================== 114 ; AFP [D800] Convert ASCII string at INBUFF[CIX] to FR0 115 ; 116 D800 org $d800 117 = D800 _afp = afp 118 D800 .proc afp 119 = 00E6 dotflag = fr2 120 = 00E7 xinvert = fr2+1 121 = 00E8 cix0 = fr2+2 122 = 00E9 sign = fr2+3 123 = 00EA digit2 = fr2+4 124 125 ;skip initial spaces 126 D800 20 A1 DB jsr skpspc 127 128 ;init FR0 and one extra mantissa byte 129 D803 A9 7F lda #$7f 130 D805 85 D4 sta fr0 131 D807 85 EA sta digit2 132 133 D809 A2 D5 ldx #fr0+1 134 D80B 20 46 DA jsr zf1 135 136 ;clear decimal flag 137 D80E 85 E6 sta dotflag 138 D810 85 E9 sta sign 139 140 ;check for sign 141 D812 A4 F2 ldy cix 142 D814 B1 F3 lda (inbuff),y 143 D816 C9 2B cmp #'+' 144 D818 F0 06 beq isplus 145 D81A C9 2D cmp #'-' 146 D81C D0 03 bne postsign 147 D81E 66 E9 ror sign 148 D820 isplus: 149 D820 C8 iny 150 D821 postsign: 151 D821 84 E8 sty cix0 152 153 ;skip leading zeroes 154 D823 A9 30 lda #'0' 155 D825 20 A5 DB jsr fp_skipchar 156 157 ;check if next char is a dot, indicating mantissa <1 158 D828 B1 F3 lda (inbuff),y 159 D82A C9 2E cmp #'.' 160 D82C D0 10 bne not_tiny 161 D82E C8 iny 162 163 ;set dot flag 164 D82F 66 E6 ror dotflag 165 166 ;increment anchor so we don't count the dot as a digit for purposes 167 ;of seeing if we got any digits 168 D831 E6 E8 inc cix0 169 170 ;skip zeroes and adjust exponent 171 D833 A9 30 lda #'0' 172 D835 tiny_denorm_loop: 173 D835 D1 F3 cmp (inbuff),y 174 D837 D0 05 bne tiny_denorm_loop_exit 175 D839 C6 D4 dec fr0 176 D83B C8 iny 177 D83C D0 F7 bne tiny_denorm_loop 178 D83E tiny_denorm_loop_exit: 179 180 D83E not_tiny: 181 182 ;grab digits left of decimal point 183 D83E A2 01 ldx #1 184 D840 nextdigit: 185 D840 B1 F3 lda (inbuff),y 186 D842 C9 45 cmp #'E' 187 D844 F0 55 beq isexp 188 D846 C8 iny 189 D847 C9 2E cmp #'.' 190 D849 F0 28 beq isdot 191 D84B 49 30 eor #'0' 192 D84D C9 0A cmp #10 193 D84F B0 2A bcs termcheck 194 195 ;write digit if we haven't exceeded digit count 196 D851 E0 06 cpx #6 197 D853 B0 15 bcs afterwrite 198 199 D855 24 EA bit digit2 200 D857 10 09 bpl writehi 201 202 ;clear second digit flag 203 D859 C6 EA dec digit2 204 205 ;merge in low digit 206 D85B 15 D4 ora fr0,x 207 D85D 95 D4 sta fr0,x 208 209 ;advance to next byte 210 D85F E8 inx 211 D860 D0 08 bne afterwrite 212 213 D862 writehi: 214 ;set second digit flag 215 D862 E6 EA inc digit2 216 217 ;shift digit to high nibble and write 218 D864 0A asl 219 D865 0A asl 220 D866 0A asl 221 D867 0A asl 222 D868 95 D4 sta fr0,x 223 224 D86A afterwrite: 225 ;adjust digit exponent if we haven't seen a dot yet 226 D86A 24 E6 bit dotflag 227 D86C 30 02 E6 D4 smi:inc fr0 228 229 ;go back for more 230 D870 4C 40 D8 jmp nextdigit 231 232 D873 isdot: 233 D873 A5 E6 lda dotflag 234 D875 D0 04 bne termcheck 235 236 ;set the dot flag and loop back for more 237 D877 66 E6 ror dotflag 238 D879 D0 C5 bne nextdigit 239 240 D87B termcheck: 241 D87B 88 dey 242 D87C C4 E8 cpy cix0 243 D87E F0 1A beq err_carryset 244 D880 term: 245 ;stash offset 246 D880 84 F2 sty cix 247 248 D882 term_rollback_exp: 249 ;divide digit exponent by two and merge in sign 250 D882 26 E9 rol sign 251 D884 66 D4 ror fr0 252 253 ;check if we need a one digit shift 254 D886 B0 0F bcs nodigitshift 255 256 ;shift right one digit 257 D888 A2 04 ldx #4 258 D88A digitshift: 259 D88A 46 D5 lsr fr0+1 260 D88C 66 D6 ror fr0+2 261 D88E 66 D7 ror fr0+3 262 D890 66 D8 ror fr0+4 263 D892 66 D9 ror fr0+5 264 D894 CA dex 265 D895 D0 F3 bne digitshift 266 267 D897 nodigitshift: 268 D897 4C 00 DC jmp fp_normalize 269 270 D89A err_carryset: 271 D89A 60 rts 272 273 D89B isexp: 274 D89B C4 E8 cpy cix0 275 D89D F0 FB beq err_carryset 276 277 ;save off this point as a fallback in case we don't actually have 278 ;exponential notation 279 D89F 84 F2 sty cix 280 281 ;check for sign 282 D8A1 A2 00 ldx #0 283 D8A3 C8 iny 284 D8A4 B1 F3 lda (inbuff),y 285 D8A6 C9 2B cmp #'+' 286 D8A8 F0 05 beq isexpplus 287 D8AA C9 2D cmp #'-' 288 D8AC D0 02 bne postexpsign 289 D8AE CA dex ;x=$ff 290 D8AF isexpplus: 291 D8AF C8 iny 292 D8B0 postexpsign: 293 D8B0 86 E7 stx xinvert 294 295 ;pull up to two exponent digits -- check first digit 296 D8B2 20 B1 DB jsr fp_isdigit_y 297 D8B5 C8 iny 298 D8B6 B0 CA bcs term_rollback_exp 299 300 ;stash first digit 301 D8B8 AA tax 302 303 ;check for another digit 304 D8B9 20 B1 DB jsr fp_isdigit_y 305 D8BC B0 05 bcs notexpzero2 306 D8BE C8 iny 307 308 D8BF 7D 39 DA adc fp_mul10,x 309 D8C2 AA tax 310 D8C3 notexpzero2: 311 D8C3 8A txa 312 313 ;zero is not a valid exponent 314 D8C4 F0 BC beq term_rollback_exp 315 316 ;check if mantissa is zero -- if so, don't bias 317 ; ldx fr0+1 318 ; beq term 319 320 ;apply sign to exponent 321 D8C6 45 E7 eor xinvert 322 D8C8 26 E7 rol xinvert 323 324 ;bias digit exponent 325 D8CA 65 D4 adc fr0 326 D8CC 85 D4 sta fr0 327 D8CE expterm: 328 D8CE 4C 80 D8 jmp term 329 330 .endp 331 332 ;========================================================================== 333 D8D1 .proc fp_fmul_carryup 334 D8D1 round_loop: 335 D8D1 75 D4 adc fr0,x 336 D8D3 95 D4 sta fr0,x 337 D8D5 dec_entry: 338 D8D5 CA dex 339 D8D6 A9 00 lda #0 340 D8D8 B0 F7 bcs round_loop 341 D8DA 60 rts 342 .endp 343 344 ;========================================================================== 345 D8DB .proc fp_tab_lo_100 346 D8DB 00 64 C8 2C 90 F4 + :10 dta <[100*#] 347 .endp 348 349 ;========================================================================== 350 D8E5 fixadr $d8e6 Macro: FIXADR [Source: source/Shared/mathpack.s] 2 .print ($D8E6-*),' bytes free before ',$D8E6 2 $0001 bytes free before $D8E6 3 D8E5 org $D8E6 Source: source/Shared/mathpack.s 351 = D8E6 _fasc = fasc 352 D8E6 .proc fasc 353 = 00F7 dotcntr = ztemp4 354 = 00F8 expval = ztemp4+1 355 = 00F9 trimbase = ztemp4+2 356 D8E6 20 51 DA jsr ldbufa 357 D8E9 A0 00 ldy #0 358 359 ;read exponent and check if number is zero 360 D8EB A5 D4 lda fr0 361 D8ED D0 05 bne notzero 362 363 D8EF A9 B0 lda #$b0 364 D8F1 91 F3 sta (inbuff),y 365 D8F3 60 rts 366 367 D8F4 notzero: 368 D8F4 84 F8 sty expval 369 D8F6 84 F9 sty trimbase 370 371 ;insert sixth mantissa byte 372 D8F8 84 D4 sty fr0 373 374 ;check if number is negative 375 D8FA 10 0A bpl ispos 376 D8FC A2 2D ldx #'-' 377 D8FE C6 F3 dec inbuff 378 D900 8E 7F 05 stx lbuff-1 379 D903 E6 F9 inc trimbase 380 D905 C8 iny 381 D906 ispos: 382 383 ;set up for 5 mantissa bytes 384 D906 A2 FB ldx #-5 385 386 ;compute digit offset to place dot 387 ; 0.001 (10.0E-04) = 3E 10 00 00 00 00 -> -1 388 ; 0.01 ( 1.0E-02) = 3F 01 00 00 00 00 -> 1 389 ; 0.1 (10.0E-02) = 3F 10 00 00 00 00 -> 1 390 ; 1.0 ( 1.0E+00) = 40 01 00 00 00 00 -> 3 391 ; 10.0 (10.0E+00) = 40 10 00 00 00 00 -> 3 392 ; 100.0 ( 1.0E+02) = 40 01 00 00 00 00 -> 5 393 ; 1000.0 (10.0E+02) = 40 10 00 00 00 00 -> 5 394 395 D908 0A asl 396 D909 38 sec 397 D90A E9 7D sbc #125 398 399 ;check if we should go to exponential form (exp >= 10 or <=-3) 400 D90C C9 0C cmp #12 401 D90E 90 0A bcc noexp 402 403 ;yes - compute and stash explicit exponent 404 D910 E9 02 sbc #2 ;!! - carry set from BCC fail 405 D912 85 F8 sta expval ;$0A <= expval < $FE 406 407 ;reset dot counter 408 D914 A9 02 lda #2 409 410 ;exclude first two digits from zero trim 411 D916 E6 F9 inc trimbase 412 D918 E6 F9 inc trimbase 413 414 D91A noexp: 415 ;check if number is less than 1.0 and init dot counter 416 D91A C9 02 cmp #2 417 D91C B0 03 bcs not_tiny 418 419 ;use sixth mantissa byte 420 D91E 69 02 adc #2 421 D920 CA dex 422 D921 not_tiny: 423 D921 85 F7 sta dotcntr ;$02 <= dotcntr < $0C 424 425 ;check if number begins with a leading zero 426 D923 B5 DA lda fr0+6,x 427 D925 C9 10 cmp #$10 428 D927 B0 0C bcs digitloop 429 430 D929 C6 F9 dec trimbase 431 432 ;yes - skip the high digit 433 D92B 46 F8 lsr expval 434 D92D 06 F8 asl expval 435 D92F D0 18 bne writelow 436 D931 C6 F7 dec dotcntr 437 D933 90 14 bcc writelow 438 439 ;write out mantissa digits 440 D935 digitloop: 441 D935 C6 F7 dec dotcntr 442 D937 D0 05 bne no_hidot 443 D939 A9 2E lda #'.' 444 D93B 91 F3 sta (inbuff),y 445 D93D C8 iny 446 D93E no_hidot: 447 448 ;write out high digit 449 D93E B5 DA lda fr0+6,x 450 D940 4A lsr 451 D941 4A lsr 452 D942 4A lsr 453 D943 4A lsr 454 D944 09 30 ora #$30 455 D946 91 F3 sta (inbuff),y 456 D948 C8 iny 457 458 D949 writelow: 459 ;write out low digit 460 D949 C6 F7 dec dotcntr 461 D94B D0 05 bne no_lodot 462 D94D A9 2E lda #'.' 463 D94F 91 F3 sta (inbuff),y 464 D951 C8 iny 465 D952 no_lodot: 466 467 D952 B5 DA lda fr0+6,x 468 D954 29 0F and #$0f 469 D956 09 30 ora #$30 470 D958 91 F3 sta (inbuff),y 471 D95A C8 iny 472 473 ;next digit 474 D95B E8 inx 475 D95C D0 D7 bne digitloop 476 477 ;skip trim if dot hasn't been written 478 D95E A5 F7 lda dotcntr 479 D960 10 11 bpl skip_zero_trim 480 481 ;trim off leading zeroes 482 D962 A9 30 lda #'0' 483 D964 lzloop: 484 D964 C4 F9 cpy trimbase 485 D966 F0 05 beq stop_zero_trim 486 D968 88 dey 487 D969 D1 F3 cmp (inbuff),y 488 D96B F0 F7 beq lzloop 489 490 ;trim off dot 491 D96D stop_zero_trim: 492 D96D B1 F3 lda (inbuff),y 493 D96F C9 2E cmp #'.' 494 D971 D0 03 bne no_trailing_dot 495 496 D973 skip_zero_trim: 497 D973 88 dey 498 D974 B1 F3 lda (inbuff),y 499 D976 no_trailing_dot: 500 501 ;check if we have an exponent to deal with 502 D976 A6 F8 ldx expval 503 D978 F0 26 beq noexp2 504 505 ;print an 'E' 506 D97A A9 45 lda #'E' 507 D97C C8 iny 508 D97D 91 F3 sta (inbuff),y 509 510 ;check for a negative exponent 511 D97F 8A txa 512 D980 10 07 bpl exppos 513 D982 49 FF eor #$ff 514 D984 AA tax 515 D985 E8 inx 516 D986 A9 2D lda #'-' 517 D988 2C dta {bit $0100} 518 D989 exppos: 519 D989 A9 2B lda #'+' 520 D98B expneg: 521 D98B C8 iny 522 D98C 91 F3 sta (inbuff),y 523 524 ;print tens digit, if any 525 D98E 8A txa 526 D98F 38 sec 527 D990 A2 2F ldx #$2f 528 D992 tensloop: 529 D992 E8 inx 530 D993 E9 0A sbc #10 531 D995 B0 FB bcs tensloop 532 D997 48 pha 533 D998 8A txa 534 D999 C8 iny 535 D99A 91 F3 sta (inbuff),y 536 D99C 68 pla 537 D99D 69 3A adc #$3a 538 D99F C8 iny 539 D9A0 noexp2: 540 ;set high bit on last char 541 D9A0 09 80 ora #$80 542 D9A2 91 F3 sta (inbuff),y 543 D9A4 60 rts 544 .endp 545 546 ;========================================================================== 547 ; IPF [D9AA] Convert 16-bit integer at FR0 to FP 548 ; 549 ; !NOTE! Cannot use FR2/FR3 -- MAC/65 requires that $DE-DF be preserved. 550 ; 551 D9A5 fixadr $d9aa Macro: FIXADR [Source: source/Shared/mathpack.s] 2 .print ($D9AA-*),' bytes free before ',$D9AA 2 $0005 bytes free before $D9AA 3 D9A5 org $D9AA Source: source/Shared/mathpack.s 552 D9AA .proc ipf 553 D9AA F8 sed 554 555 D9AB A2 D6 ldx #fr0+2 556 D9AD A0 05 ldy #5 557 D9AF 20 48 DA jsr zfl 558 559 D9B2 A0 10 ldy #16 560 D9B4 byteloop: 561 ;shift out binary bit 562 D9B4 06 D4 asl fr0 563 D9B6 26 D5 rol fr0+1 564 565 ;shift in BCD bit 566 D9B8 A5 D8 lda fr0+4 567 D9BA 65 D8 adc fr0+4 568 D9BC 85 D8 sta fr0+4 569 D9BE A5 D7 lda fr0+3 570 D9C0 65 D7 adc fr0+3 571 D9C2 85 D7 sta fr0+3 572 D9C4 26 D6 rol fr0+2 573 574 D9C6 88 dey 575 D9C7 D0 EB bne byteloop 576 577 D9C9 A9 43 lda #$43 578 D9CB 85 D4 sta fr0 579 580 D9CD 4C FF DB jmp fp_normalize_cld 581 .endp 582 583 ;========================================================================== 584 ; FPI [D9D2] Convert FR0 to 16-bit integer at FR0 with rounding 585 ; 586 ; This cannot overwrite FR1. Darg relies on being able to stash a value 587 ; there across a call to FPI in its startup. 588 ; 589 D9D0 fixadr $d9d2 Macro: FIXADR [Source: source/Shared/mathpack.s] 2 .print ($D9D2-*),' bytes free before ',$D9D2 2 $0002 bytes free before $D9D2 3 D9D0 org $D9D2 Source: source/Shared/mathpack.s 590 D9D2 .nowarn .proc fpi 591 = 00E6 _acc0 = fr2 592 = 00E7 _acc1 = fr2+1 593 594 ;error out if it's guaranteed to be too big or negative (>999999) 595 D9D2 A5 D4 lda fr0 596 D9D4 C9 43 cmp #$43 597 D9D6 B0 60 bcs err 598 599 ;zero number if it's guaranteed to be too small (<0.01) 600 D9D8 E9 3E sbc #$3f-1 ;!!- carry is clear 601 D9DA 90 68 bcc zfr0 602 603 D9DC AA tax 604 605 ;clear temp accum and set up rounding 606 D9DD A9 00 lda #0 607 D9DF B4 D5 ldy fr0+1,x 608 D9E1 C0 50 cpy #$50 609 D9E3 2A rol ;!! - clears carry too 610 D9E4 85 D4 sta fr0 611 D9E6 A9 00 lda #0 612 613 ;check for [0.01, 1) 614 D9E8 CA dex 615 D9E9 30 4B bmi done 616 617 ;convert ones/tens digit pair to binary (one result byte: 0-100) 618 D9EB B5 D5 lda fr0+1,x 619 D9ED 20 CD DA jsr fp_dectobin 620 D9F0 65 D4 adc fr0 621 D9F2 79 F6 DF adc fp_dectobin_tab,y 622 D9F5 18 clc 623 D9F6 85 D4 sta fr0 624 D9F8 A9 00 lda #0 625 626 ;check if we're done 627 D9FA CA dex 628 D9FB 30 39 bmi done 629 630 ;convert hundreds/thousands digit pair to binary (two result bytes: 0-10000) 631 D9FD B5 D5 lda fr0+1,x 632 D9FF 20 CD DA jsr fp_dectobin 633 DA02 A5 D4 lda fr0 634 DA04 79 48 DF adc fp_tab_lo_1000,y 635 DA07 85 D4 sta fr0 636 DA09 B9 52 DF lda fp_tab_hi_1000,y 637 DA0C 69 00 adc #0 638 DA0E 48 pha 639 DA0F B5 D5 lda fr0+1,x 640 DA11 29 0F and #$0f 641 DA13 A8 tay 642 DA14 A5 D4 lda fr0 643 DA16 79 DB D8 adc fp_tab_lo_100,y 644 DA19 85 D4 sta fr0 645 DA1B 68 pla 646 DA1C 79 5C DF adc fp_tab_hi_100,y 647 648 ;check if we're done 649 DA1F CA dex 650 DA20 30 14 bmi done 651 652 ;convert ten thousands digit pair to binary (two result bytes: 0-100000, overflow possible) 653 DA22 B4 D5 ldy fr0+1,x 654 DA24 C0 07 cpy #$07 655 DA26 B0 10 bcs err 656 DA28 AA tax 657 DA29 98 tya 658 DA2A 0A asl 659 DA2B 0A asl 660 DA2C 0A asl 661 DA2D 0A asl 662 DA2E 65 D4 adc fr0 663 DA30 85 D4 sta fr0 664 DA32 8A txa 665 DA33 79 65 DF adc fp_tab_hi_10000-1,y 666 667 DA36 done: 668 ;move result back to FR0, with rounding 669 DA36 85 D5 sta fr0+1 670 DA38 err: 671 DA38 60 rts 672 .endp 673 674 ;========================================================================== 675 DA39 fp_mul10: 676 DA39 00 0A 14 1E 28 32 + dta 0,10,20,30,40,50,60,70,80,90 677 678 ;========================================================================== 679 ; ZFR0 [DA44] Zero FR0 680 ; ZF1 [DA46] Zero float at (X) 681 ; ZFL [DA48] Zero float at (X) with length Y (UNDOCUMENTED) 682 ; 683 DA43 fixadr $da44 Macro: FIXADR [Source: source/Shared/mathpack.s] 2 .print ($DA44-*),' bytes free before ',$DA44 2 $0001 bytes free before $DA44 3 DA43 org $DA44 Source: source/Shared/mathpack.s 684 DA44 zfr0: 685 DA44 A2 D4 ldx #fr0 686 DA46 ckaddr $da46 Macro: CKADDR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 687 DA46 zf1: 688 DA46 A0 06 ldy #6 689 DA48 ckaddr $da48 Macro: CKADDR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 690 DA48 zfl: 691 DA48 A9 00 lda #0 692 DA4A zflloop: 693 DA4A 95 00 sta 0,x 694 DA4C E8 inx 695 DA4D 88 dey 696 DA4E D0 FA bne zflloop 697 DA50 60 rts 698 699 ;========================================================================== 700 ; LDBUFA [DA51] Set LBUFF to #INBUFF (UNDOCUMENTED) 701 ; 702 DA51 fixadr $da51 Macro: FIXADR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 703 DA51 ldbufa: 704 DA51 A9 80 85 F3 A9 05 + mwa #lbuff inbuff 705 DA59 60 rts 706 707 ;========================================================================== 708 ; FPILL_SHL16 [DA5A] Shift left 16-bit word at $F7:F8 (UNDOCUMENTED) 709 ; 710 ; Illegal entry point used by MAC/65 when doing hex conversion. 711 ; 712 ; Yes, even the byte ordering is wrong. 713 ; 714 DA5A fixadr $da5a Macro: FIXADR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 715 716 DA5A .nowarn .proc fpill_shl16 717 DA5A 06 F8 asl $f8 718 DA5C 26 F7 rol $f7 719 DA5E 60 rts 720 .endp 721 722 ;** 1 byte free** 723 724 ;========================================================================== 725 ; FSUB [DA60] Subtract FR1 from FR0; FR1 is altered 726 ; FADD [DA66] Add FR1 to FR0; FR1 is altered 727 DA5F fixadr $da60 Macro: FIXADR [Source: source/Shared/mathpack.s] 2 .print ($DA60-*),' bytes free before ',$DA60 2 $0001 bytes free before $DA60 3 DA5F org $DA60 Source: source/Shared/mathpack.s 728 = DA66 fadd = fsub._fadd 729 DA60 .proc fsub 730 731 = 00E0 _diffmode = fr1 732 733 ;toggle sign on FR1 734 DA60 A5 E0 lda fr1 735 DA62 49 80 eor #$80 736 DA64 85 E0 sta fr1 737 738 ;fall through to FADD 739 740 DA66 ckaddr $da66 Macro: CKADDR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 741 DA66 _fadd: 742 ;if fr1 is zero, we're done 743 DA66 A5 E0 lda fr1 744 DA68 F0 4E beq sum_xit 745 746 ;if fr0 is zero, swap 747 DA6A A5 D4 lda fr0 748 DA6C F0 0E beq swap 749 750 ;compute difference in exponents, ignoring sign 751 DA6E A5 E0 lda fr1 ;load fr1 sign 752 DA70 45 D4 eor fr0 ;compute fr0 ^ fr1 signs 753 DA72 29 80 and #$80 ;mask to just sign 754 DA74 AA tax 755 DA75 45 E0 eor fr1 ;flip fr1 sign to match fr0 756 DA77 18 clc 757 DA78 E5 D4 sbc fr0 ;compute difference in exponents - 1 758 DA7A 90 05 bcc noswap 759 760 ;swap FR0 and FR1 761 DA7C swap: 762 DA7C 20 74 DD jsr fp_swap 763 764 ;loop back and retry 765 DA7F 30 E5 bmi _fadd 766 767 DA81 noswap: 768 ;A = FR1 - FR0 - 1 769 ;X = add/sub flag 770 771 ;compute positions for add/subtract 772 DA81 69 06 adc #6 ;A = (FR1) - (FR0) + 6 !! carry is clear coming in 773 DA83 A8 tay 774 775 ;check if FR1 is too small in magnitude to matter 776 DA84 30 32 bmi sum_xit 777 778 ;jump to decimal mode and prepare for add/sub loops 779 DA86 F8 sed 780 781 ;check if we are doing a sum or a difference 782 DA87 E0 80 cpx #$80 783 DA89 A2 05 ldx #5 784 DA8B B0 2E bcs do_subtract 785 786 ;set up rounding 787 DA8D A9 00 lda #0 788 DA8F C0 05 cpy #5 789 DA91 B0 03 bcs add_no_round 790 DA93 B9 E1 00 lda fr1+1,y 791 DA96 add_no_round: 792 DA96 C9 50 cmp #$50 793 794 ;add mantissas 795 DA98 98 tya 796 DA99 F0 0B beq post_add_loop 797 DA9B add_loop: 798 DA9B B9 E0 00 lda fr1,y 799 DA9E 75 D4 adc fr0,x 800 DAA0 95 D4 sta fr0,x 801 DAA2 CA dex 802 DAA3 88 dey 803 DAA4 D0 F5 bne add_loop 804 DAA6 post_add_loop: 805 806 ;check if we had a carry out 807 DAA6 90 10 bcc sum_xit 808 809 ;carry it up 810 DAA8 B0 08 bcs sum_carryloop_start 811 DAAA sum_carryloop: 812 DAAA B5 D5 lda fr0+1,x 813 DAAC 69 00 adc #0 814 DAAE 95 D5 sta fr0+1,x 815 DAB0 90 06 bcc sum_xit 816 DAB2 sum_carryloop_start: 817 DAB2 CA dex 818 DAB3 10 F5 bpl sum_carryloop 819 820 DAB5 20 6A DE jsr fp_carry_expup 821 822 DAB8 sum_xit: 823 ;exit decimal mode 824 ;normalize if necessary and exit (needed for borrow, as well to check over/underflow) 825 DAB8 4C FF DB jmp fp_normalize_cld 826 827 DABB do_subtract: 828 ;subtract FR0 and FR1 mantissas (!! carry is set coming in) 829 DABB 84 E0 sty fr1 830 DABD B0 08 bcs sub_loop_entry 831 DABF sub_loop: 832 DABF B5 D4 lda fr0,x 833 DAC1 F9 E1 00 sbc fr1+1,y 834 DAC4 95 D4 sta fr0,x 835 DAC6 CA dex 836 DAC7 sub_loop_entry: 837 DAC7 88 dey 838 DAC8 10 F5 bpl sub_loop 839 DACA 4C 5E DC jmp fp_fsub_cont 840 .endp 841 842 ;========================================================================== 843 ; Entry: 844 ; A = BCD value 845 ; P.D = clear 846 ; 847 ; Exit: 848 ; A = binary value 849 ; Y = modified 850 ; 851 DACD .proc fp_dectobin 852 DACD 48 pha 853 DACE 4A lsr 854 DACF 4A lsr 855 DAD0 4A lsr 856 DAD1 4A lsr 857 DAD2 A8 tay 858 DAD3 68 pla 859 = DAD4 .def :fp_exit_success 860 DAD4 18 clc 861 DAD5 60 rts 862 .endp 863 864 ;========================================================================== 865 ; FMUL [DADB]: Multiply FR0 * FR1 -> FR0 866 ; 867 DAD6 fixadr $dad6 Macro: FIXADR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 868 DAD6 fp_fld1r_const_fmul: 869 DAD6 A0 DB ldy #>fpconst_ten 870 DAD8 fp_fld1r_fmul: 871 DAD8 20 98 DD jsr fld1r 872 DADB ckaddr $dadb Macro: CKADDR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 873 DADB .proc fmul 874 875 ;We use FR0:FR3 as a double-precision accumulator, and copy the 876 ;original multiplicand value in FR0 to FR1. The multiplier in 877 ;FR1 is converted to binary digit pairs into FR2. 878 879 = 00DF _offset = _fr3+5 880 = 00E6 _offset2 = fr2 881 882 ;if FR0 is zero, we're done 883 DADB A5 D4 lda fr0 884 DADD F0 F5 beq fp_exit_success 885 886 ;if FR1 is zero, zero FR0 and exit 887 DADF A5 E0 lda fr1 888 DAE1 18 clc 889 DAE2 F0 17 beq fp_exit_zero 890 891 ;move fr0 to fr2 892 DAE4 20 79 DE jsr fp_fmul_fr0_to_binfr2 893 894 ;compute new exponent and stash 895 DAE7 A5 E0 lda fr1 896 DAE9 18 clc 897 DAEA 20 03 DB jsr fp_adjust_exponent.fmul_entry 898 899 DAED 85 D4 sta fr0 900 DAEF E6 D4 inc fr0 901 902 ;clear accumulator through to exponent byte of fr1 903 DAF1 A2 D5 ldx #fr0+1 904 DAF3 A0 0C ldy #12 905 DAF5 F8 sed 906 907 DAF6 4C C3 DC jmp fp_fmul_innerloop 908 .endp 909 910 DAF9 underflow_overflow: 911 DAF9 68 pla 912 DAFA 68 pla 913 DAFB fp_exit_zero: 914 DAFB 4C 44 DA jmp zfr0 915 916 DAFE .proc fp_adjust_exponent 917 DAFE fdiv_entry: 918 DAFE A5 E0 lda fr1 919 DB00 49 7F eor #$7f 920 DB02 38 sec 921 DB03 fmul_entry: 922 ;stash modified exp1 923 DB03 AA tax 924 925 ;compute new sign 926 DB04 45 D4 eor fr0 927 DB06 29 80 and #$80 928 DB08 85 E0 sta fr1 929 930 ;merge exponents 931 DB0A 8A txa 932 DB0B 65 D4 adc fr0 933 DB0D AA tax 934 DB0E 45 E0 eor fr1 935 936 ;check for underflow/overflow 937 DB10 C9 4F cmp #128-49 938 DB12 90 E5 bcc underflow_overflow 939 940 DB14 C9 B1 cmp #128+49 941 DB16 B0 E1 bcs underflow_overflow 942 943 ;rebias exponent 944 DB18 8A txa 945 DB19 E9 3F sbc #$40-1 ;!! - C=0 from bcs fail 946 DB1B 60 rts 947 .endp 948 949 ;========================================================================== 950 DB1C .pages 1 ;optimized by fp_fld1r_const_fmul 951 952 DB1C fpconst_ten: 953 DB1C 40 10 00 00 00 00 .fl 10 954 955 DB22 fpconst_ln10: 956 DB22 40 02 30 25 85 09 .fl 2.3025850929940456840179914546844 957 958 DB28 .endpg 959 ;========================================================================== 960 ; FDIV [DB28] Divide FR0 / FR1 -> FR0 961 ; 962 ; Compatibility: 963 ; - It is important that FDIV rounds if FADD/FMUL do. Otherwise, some 964 ; forms of square root computation can have a slight error on integers, 965 ; which breaks TICKTOCK.BAS. 966 ; 967 DB28 fixadr $db28 Macro: FIXADR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 968 DB28 .proc fdiv 969 = 00DB _digit = _fr3+1 970 = 00DC _index = _fr3+2 971 ;check if divisor is zero 972 DB28 A5 E0 lda fr1 973 DB2A F0 72 beq err 974 975 ;check if dividend is zero 976 DB2C A5 D4 lda fr0 977 DB2E F0 6C beq ok 978 979 ;compute new exponent 980 DB30 20 FE DA jsr fp_adjust_exponent.fdiv_entry 981 982 DB33 20 2D DC jsr fp_fdiv_init 983 984 DB36 digitloop: 985 ;just keep going if we're accurate 986 DB36 A5 D4 lda fr0 987 DB38 05 D5 ora fr0+1 988 DB3A F0 3D beq nextdigit 989 990 ;check if we should either divide or add based on current sign (stored in carry) 991 DB3C 90 05 bcc incloop 992 993 DB3E 20 B9 DB jsr fp_fdiv_decloop 994 DB41 90 36 bcc nextdigit 995 996 DB43 incloop: 997 ;decrement quotient mantissa byte 998 DB43 A9 00 lda #0 999 DB45 E5 DB sbc _digit 1000 DB47 A6 DC ldx _index 1001 DB49 downloop: 1002 DB49 75 ED adc fr2+7,x 1003 DB4B 95 ED sta fr2+7,x 1004 DB4D A9 99 lda #$99 1005 DB4F CA dex 1006 DB50 90 F7 bcc downloop 1007 1008 ;add mantissas 1009 DB52 18 clc 1010 .rept 6 1011 LDA FR0+(5-#) 1012 ADC FR1+(5-#) 1013 STA FR0+(5-#) 1014 .ENDR 1014 .endr Source: REPT 1011 DB53 A5 D9 LDA FR0+(5-#) 1011 DB55 65 E5 ADC FR1+(5-#) 1011 DB57 85 D9 STA FR0+(5-#) 1011 DB59 A5 D8 LDA FR0+(5-#) 1011 DB5B 65 E4 ADC FR1+(5-#) 1011 DB5D 85 D8 STA FR0+(5-#) 1011 DB5F A5 D7 LDA FR0+(5-#) 1011 DB61 65 E3 ADC FR1+(5-#) 1011 DB63 85 D7 STA FR0+(5-#) 1011 DB65 A5 D6 LDA FR0+(5-#) 1011 DB67 65 E2 ADC FR1+(5-#) 1011 DB69 85 D6 STA FR0+(5-#) 1011 DB6B A5 D5 LDA FR0+(5-#) 1011 DB6D 65 E1 ADC FR1+(5-#) 1011 DB6F 85 D5 STA FR0+(5-#) 1011 DB71 A5 D4 LDA FR0+(5-#) 1011 DB73 65 E0 ADC FR1+(5-#) 1011 DB75 85 D4 STA FR0+(5-#) Source: source/Shared/mathpack.s 1015 1016 ;keep going until we overflow 1017 DB77 90 CA bcc incloop 1018 1019 DB79 nextdigit: 1020 ;shift dividend (make sure to save carry state) 1021 DB79 08 php 1022 DB7A A2 04 ldx #4 1023 DB7C bitloop: 1024 DB7C 06 D9 asl fr0+5 1025 DB7E 26 D8 rol fr0+4 1026 DB80 26 D7 rol fr0+3 1027 DB82 26 D6 rol fr0+2 1028 DB84 26 D5 rol fr0+1 1029 DB86 26 D4 rol fr0 1030 DB88 CA dex 1031 DB89 D0 F1 bne bitloop 1032 DB8B 28 plp 1033 1034 ;next digit 1035 DB8C A5 DB lda _digit 1036 DB8E 49 09 eor #$09 1037 DB90 85 DB sta _digit 1038 DB92 F0 A2 beq digitloop 1039 1040 ;next quo byte 1041 DB94 E6 DC inc _index 1042 DB96 D0 9E bne digitloop 1043 1044 ;move back to fr0 1045 DB98 20 EE DB jsr fp_fdiv_complete 1046 DB9B D8 cld 1047 DB9C ok: 1048 DB9C 18 clc 1049 DB9D 60 rts 1050 DB9E err: 1051 DB9E 38 sec 1052 DB9F 60 rts 1053 .endp 1054 1055 ;========================================================================== 1056 ; SKPSPC [DBA1] Increment CIX while INBUFF[CIX] is a space 1057 DBA0 fixadr $dba1 Macro: FIXADR [Source: source/Shared/mathpack.s] 2 .print ($DBA1-*),' bytes free before ',$DBA1 2 $0001 bytes free before $DBA1 3 DBA0 org $DBA1 Source: source/Shared/mathpack.s 1058 DBA1 skpspc: 1059 DBA1 A9 20 lda #' ' 1060 DBA3 A4 F2 ldy cix 1061 DBA5 fp_skipchar: 1062 DBA5 skpspc_loop: 1063 DBA5 D1 F3 cmp (inbuff),y 1064 DBA7 D0 03 bne skpspc_xit 1065 DBA9 C8 iny 1066 DBAA D0 F9 bne skpspc_loop 1067 DBAC skpspc_xit: 1068 DBAC 84 F2 sty cix 1069 DBAE 60 rts 1070 1071 ;========================================================================== 1072 ; ISDIGT [DBAF] Check if INBUFF[CIX] is a digit (UNDOCUMENTED) 1073 DBAF fixadr $dbaf Macro: FIXADR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 1074 = DBAF isdigt = _isdigt 1075 DBAF .proc _isdigt 1076 DBAF A4 F2 ldy cix 1077 = DBB1 .def :fp_isdigit_y = * 1078 DBB1 B1 F3 lda (inbuff),y 1079 DBB3 38 sec 1080 DBB4 E9 30 sbc #'0' 1081 DBB6 C9 0A cmp #10 1082 DBB8 60 rts 1083 .endp 1084 1085 ;========================================================================== 1086 DBB9 .proc fp_fdiv_decloop 1087 DBB9 decloop: 1088 ;increment quotient mantissa byte 1089 DBB9 A5 DB lda fdiv._digit 1090 DBBB A6 DC ldx fdiv._index 1091 DBBD uploop: 1092 DBBD 75 ED adc fr2+7,x 1093 DBBF 95 ED sta fr2+7,x 1094 DBC1 A9 00 lda #0 1095 DBC3 CA dex 1096 DBC4 B0 F7 bcs uploop 1097 1098 ;subtract mantissas 1099 DBC6 38 sec 1100 DBC7 A5 D9 lda fr0+5 1101 DBC9 E5 E5 sbc fr1+5 1102 DBCB 85 D9 sta fr0+5 1103 DBCD A5 D8 lda fr0+4 1104 DBCF E5 E4 sbc fr1+4 1105 DBD1 85 D8 sta fr0+4 1106 DBD3 A5 D7 lda fr0+3 1107 DBD5 E5 E3 sbc fr1+3 1108 DBD7 85 D7 sta fr0+3 1109 DBD9 A5 D6 lda fr0+2 1110 DBDB E5 E2 sbc fr1+2 1111 DBDD 85 D6 sta fr0+2 1112 DBDF A5 D5 lda fr0+1 1113 DBE1 E5 E1 sbc fr1+1 1114 DBE3 85 D5 sta fr0+1 1115 DBE5 A5 D4 lda fr0 1116 DBE7 E9 00 sbc #0 1117 DBE9 85 D4 sta fr0 1118 1119 ;keep going until we underflow 1120 DBEB B0 CC bcs decloop 1121 DBED 60 rts 1122 .endp 1123 1124 DBEE .proc fp_fdiv_complete 1125 DBEE A2 E5 ldx #fr2-1 1126 DBF0 A4 DA ldy _fr3 1127 DBF2 A5 E6 lda fr2 1128 DBF4 D0 02 bne no_normstep 1129 DBF6 E8 inx 1130 DBF7 88 dey 1131 DBF8 no_normstep: 1132 DBF8 94 00 sty 0,x 1133 DBFA 4C 87 DD jmp fld0r_zp 1134 .endp 1135 1136 ;========================================================================== 1137 ; NORMALIZE [DC00] Normalize FR0 (UNDOCUMENTED) 1138 DBFD fixadr $dc00-1 Macro: FIXADR [Source: source/Shared/mathpack.s] 2 .print ($DC00-1-*),' bytes free before ',$DC00-1 2 $0002 bytes free before $DBFF 3 DBFD org $DC00-1 Source: source/Shared/mathpack.s 1139 DBFF fp_normalize_cld: 1140 DBFF D8 cld 1141 DC00 ckaddr $dc00 Macro: CKADDR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 1142 DC00 fp_normalize: 1143 DC00 .nowarn .proc normalize 1144 DC00 A0 05 ldy #5 1145 DC02 normloop: 1146 DC02 A5 D4 lda fr0 1147 DC04 29 7F and #$7f 1148 DC06 F0 21 beq underflow2 1149 1150 DC08 A6 D5 ldx fr0+1 1151 DC0A F0 07 beq need_norm 1152 1153 ;Okay, we're done normalizing... check if the exponent is in bounds. 1154 ;It needs to be within +/-48 to be valid. If the exponent is <-49, 1155 ;we set it to zero; otherwise, we mark overflow. 1156 1157 DC0C C9 0F cmp #64-49 1158 DC0E 90 1A bcc underflow 1159 DC10 C9 71 cmp #64+49 1160 DC12 60 rts 1161 1162 DC13 need_norm: 1163 DC13 C6 D4 dec fr0 1164 DC15 A2 FB ldx #-5 1165 DC17 normloop2: 1166 DC17 B5 DB 95 DA mva fr0+7,x fr0+6,x 1167 DC1B E8 inx 1168 DC1C D0 F9 bne normloop2 1169 DC1E 86 DA stx fr0+6 1170 DC20 88 dey 1171 DC21 D0 DF bne normloop 1172 1173 ;Hmm, we shifted out everything... must be zero; reset exponent. This 1174 ;is critical since Atari Basic depends on the exponent being zero for 1175 ;a zero result. 1176 DC23 84 D4 sty fr0 1177 DC25 84 D5 sty fr0+1 1178 DC27 xit: 1179 DC27 18 clc 1180 DC28 60 rts 1181 1182 DC29 underflow2: 1183 DC29 18 clc 1184 DC2A underflow: 1185 DC2A 4C 44 DA jmp zfr0 1186 1187 .endp 1188 1189 ;========================================================================== 1190 ; HELPER ROUTINES 1191 ;========================================================================== 1192 1193 DC2D .proc fp_fdiv_init 1194 DC2D 85 DA sta _fr3 1195 1196 DC2F A2 E6 ldx #fr2 1197 DC31 20 46 DA jsr zf1 1198 DC34 A9 50 lda #$50 1199 DC36 85 EC sta fr2+6 1200 1201 DC38 A2 00 ldx #0 1202 DC3A 86 D4 stx fr0 1203 DC3C 86 E0 stx fr1 1204 1205 ;check if dividend begins with a leading zero digit -- if so, shift it left 4 1206 ;and begin with the tens digit 1207 DC3E A5 E1 lda fr1+1 1208 DC40 C9 10 cmp #$10 1209 DC42 B0 11 bcs start_with_ones 1210 1211 DC44 A0 04 ldy #4 1212 DC46 bitloop: 1213 DC46 06 E5 asl fr1+5 1214 DC48 26 E4 rol fr1+4 1215 DC4A 26 E3 rol fr1+3 1216 DC4C 26 E2 rol fr1+2 1217 DC4E 26 E1 rol fr1+1 1218 DC50 88 dey 1219 DC51 D0 F3 bne bitloop 1220 1221 DC53 A2 09 ldx #$09 1222 1223 DC55 start_with_ones: 1224 1225 DC55 86 DB stx fdiv._digit 1226 DC57 F8 sed 1227 1228 DC58 A2 F9 ldx #0-7 1229 DC5A 86 DC stx fdiv._index 1230 DC5C 38 sec 1231 DC5D 60 rts 1232 .endp 1233 1234 ;-------------------------------------------------------------------------- 1235 DC5E .proc fp_fsub_cont 1236 ;check if we had a borrow 1237 DC5E B0 1F bcs sub_xit 1238 DC60 90 08 bcc borrow_loop_start 1239 1240 ;propagate borrow up 1241 DC62 borrow_loop: 1242 DC62 B5 D5 lda fr0+1,x 1243 DC64 E9 00 sbc #0 1244 DC66 95 D5 sta fr0+1,x 1245 DC68 B0 15 bcs sub_xit 1246 DC6A borrow_loop_start: 1247 DC6A CA dex 1248 DC6B 10 F5 bpl borrow_loop 1249 1250 DC6D A2 05 ldx #5 1251 DC6F 38 sec 1252 DC70 diff_borrow: 1253 DC70 A9 00 lda #0 1254 DC72 F5 D4 sbc fr0,x 1255 DC74 95 D4 sta fr0,x 1256 DC76 CA dex 1257 DC77 D0 F7 bne diff_borrow 1258 DC79 A9 80 lda #$80 1259 DC7B 45 D4 eor fr0 1260 DC7D 85 D4 sta fr0 1261 DC7F sub_xit: 1262 1263 DC7F norm_loop: 1264 ;Check if the exponent is in bounds. 1265 ;It needs to be within +/-48 to be valid. If the exponent is <-49, 1266 ;we set it to zero. Overflow isn't possible as this is the mantissa 1267 ;subtraction path. 1268 DC7F A5 D4 lda fr0 1269 DC81 29 7F and #$7f 1270 DC83 C9 0F cmp #64-49 1271 DC85 90 1F bcc underflow 1272 1273 DC87 A6 D5 ldx fr0+1 1274 DC89 F0 0F beq need_norm 1275 1276 ;check if we need to round, i.e.: 1277 ; 2.00000000 1278 ;-0.000000005 1279 ;load rounding byte offset 1280 DC8B A6 E0 ldx fr1 1281 DC8D E0 04 cpx #4 1282 DC8F B0 06 bcs no_round 1283 DC91 B5 E2 lda fr1+2,x 1284 DC93 C9 50 cmp #$50 1285 DC95 B0 27 bcs round_up 1286 DC97 no_round: 1287 1288 DC97 18 clc 1289 DC98 D8 cld 1290 DC99 60 rts 1291 1292 DC9A need_norm: 1293 DC9A A2 FC ldx #-4 1294 DC9C scan_loop: 1295 DC9C C6 D4 dec fr0 1296 DC9E B4 DA ldy fr0+6,x 1297 DCA0 D0 08 bne found_pos 1298 DCA2 E8 inx 1299 DCA3 D0 F7 bne scan_loop 1300 1301 ;hmm... mantissa is all zero. 1302 DCA5 underflow2: 1303 DCA5 18 clc 1304 DCA6 underflow: 1305 DCA6 D8 cld 1306 DCA7 4C 44 DA jmp zfr0 1307 1308 DCAA found_pos: 1309 ;shift up mantissa 1310 DCAA A0 00 ldy #0 1311 DCAC shift_loop: 1312 DCAC B5 DA 99 D5 00 mva fr0+6,x fr0+1,y 1313 DCB1 C8 iny 1314 DCB2 E8 inx 1315 DCB3 D0 F7 bne shift_loop 1316 1317 ;clear remaining mantissa bytes 1318 DCB5 clear_loop: 1319 DCB5 96 D5 C8 stx fr0+1,y+ 1320 DCB8 C0 06 cpy #6 1321 DCBA D0 F9 bne clear_loop 1322 1323 ;check if we need to round 1324 1325 1326 ;if not, loop back to check the exponent and exit 1327 ; bcc norm_loop 1328 DCBC F0 C1 beq norm_loop 1329 1330 DCBE round_up: 1331 ;jump back into fadd code to carry up and exit 1332 DCBE A2 05 ldx #5 1333 DCC0 4C AA DA jmp fsub.sum_carryloop 1334 .endp 1335 1336 ;-------------------------------------------------------------------------- 1337 DCC3 .proc fp_fmul_innerloop 1338 = 00DF _offset = _fr3+5 1339 = 00E6 _offset2 = fr2 1340 1341 DCC3 20 48 DA jsr zfl 1342 1343 ;set up for 7 bits per digit pair (0-99 in 0-127) 1344 DCC6 A0 07 ldy #7 1345 1346 ;set rounding byte, assuming renormalize needed (fr0+2 through fr0+6) 1347 DCC8 A9 50 lda #$50 1348 DCCA 85 DB sta fr0+7 1349 1350 ;begin outer loop -- this is where we process one _bit_ out of each 1351 ;multiplier byte in FR2's mantissa (note that this is inverted in that 1352 ;it is bytes-in-bits instead of bits-in-bytes) 1353 DCCC offloop: 1354 1355 ;begin inner loop -- here we process the same bit in each multiplier 1356 ;byte, going from byte 5 down to byte 1 1357 DCCC A2 05 ldx #5 1358 DCCE offloop2: 1359 ;shift an inverted bit out of fr1 mantissa 1360 DCCE 56 E6 lsr fr2,x 1361 DCD0 B0 2D bcs noadd 1362 1363 ;add fr1 to fr0 at offset 1364 .rept 6 1365 LDA FR0+(5-#),X 1366 ADC FR1+(5-#) 1367 STA FR0+(5-#),X 1368 .ENDR 1368 .endr Source: REPT 1365 DCD2 B5 D9 LDA FR0+(5-#),X 1365 DCD4 65 E5 ADC FR1+(5-#) 1365 DCD6 95 D9 STA FR0+(5-#),X 1365 DCD8 B5 D8 LDA FR0+(5-#),X 1365 DCDA 65 E4 ADC FR1+(5-#) 1365 DCDC 95 D8 STA FR0+(5-#),X 1365 DCDE B5 D7 LDA FR0+(5-#),X 1365 DCE0 65 E3 ADC FR1+(5-#) 1365 DCE2 95 D7 STA FR0+(5-#),X 1365 DCE4 B5 D6 LDA FR0+(5-#),X 1365 DCE6 65 E2 ADC FR1+(5-#) 1365 DCE8 95 D6 STA FR0+(5-#),X 1365 DCEA B5 D5 LDA FR0+(5-#),X 1365 DCEC 65 E1 ADC FR1+(5-#) 1365 DCEE 95 D5 STA FR0+(5-#),X 1365 DCF0 B5 D4 LDA FR0+(5-#),X 1365 DCF2 65 E0 ADC FR1+(5-#) 1365 DCF4 95 D4 STA FR0+(5-#),X Source: source/Shared/mathpack.s 1369 1370 ;check if we have a carry out to the upper bytes 1371 DCF6 90 07 bcc no_carry 1372 DCF8 86 E6 stx _offset2 1373 DCFA 20 D5 D8 jsr fp_fmul_carryup.dec_entry 1374 DCFD A6 E6 ldx _offset2 1375 DCFF no_carry: 1376 1377 DCFF noadd: 1378 ;go back for next byte 1379 DCFF CA dex 1380 DD00 D0 CC bne offloop2 1381 1382 ;double fr1 1383 DD02 18 clc 1384 DD03 A5 E5 lda fr1+5 1385 DD05 65 E5 adc fr1+5 1386 DD07 85 E5 sta fr1+5 1387 DD09 A5 E4 lda fr1+4 1388 DD0B 65 E4 adc fr1+4 1389 DD0D 85 E4 sta fr1+4 1390 DD0F A5 E3 lda fr1+3 1391 DD11 65 E3 adc fr1+3 1392 DD13 85 E3 sta fr1+3 1393 DD15 A5 E2 lda fr1+2 1394 DD17 65 E2 adc fr1+2 1395 DD19 85 E2 sta fr1+2 1396 DD1B A5 E1 lda fr1+1 1397 DD1D 65 E1 adc fr1+1 1398 DD1F 85 E1 sta fr1+1 1399 DD21 A5 E0 lda fr1+0 1400 DD23 65 E0 adc fr1+0 1401 DD25 85 E0 sta fr1+0 1402 1403 ;loop back until all mantissa bytes finished 1404 DD27 88 dey 1405 DD28 D0 A2 bne offloop 1406 1407 ;check if no renormalize is needed, and if so, re-add new rounding 1408 DD2A A5 D5 lda fr0+1 1409 DD2C F0 07 beq renorm_needed 1410 1411 DD2E A9 50 lda #$50 1412 DD30 A2 06 ldx #6 1413 DD32 20 D1 D8 jsr fp_fmul_carryup 1414 1415 DD35 renorm_needed: 1416 ;all done 1417 DD35 4C FF DB jmp fp_normalize_cld 1418 .endp 1419 1420 ;========================================================================== 1421 ; PLYEVL [DD40] Eval polynomial at (X:Y) with A coefficients using FR0 1422 ; 1423 DD38 fixadr $dd3e Macro: FIXADR [Source: source/Shared/mathpack.s] 2 .print ($DD3E-*),' bytes free before ',$DD3E 2 $0006 bytes free before $DD3E 3 DD38 org $DD3E Source: source/Shared/mathpack.s 1424 DD3E fp_plyevl_10: 1425 DD3E A9 0A lda #10 1426 DD40 .nowarn .proc plyevl 1427 ;stash arguments 1428 DD40 86 FE stx fptr2 1429 DD42 84 FF sty fptr2+1 1430 DD44 85 EC sta _fpcocnt 1431 1432 ;copy FR0 -> PLYARG 1433 DD46 A2 E0 ldx #plyarg 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 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 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 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 #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 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 1713 DEAC 20 A7 DD jsr fst0r 1714 DEAF A2 E6 ldx #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 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 #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 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 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 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 #[1000*#] 1858 .endp 1859 1860 DF5C .proc fp_tab_hi_100 1861 DF5C 00 00 00 01 01 01 + :10 dta >[100*#] 1862 .endp 1863 1864 DF66 .proc fp_tab_hi_10000 1865 DF66 27 4E 75 9C C3 EA :6 dta >[10000*[#+1]] 1866 .endp 1867 1868 ;========================================================================== 1869 ; HALF (used by Atari BASIC) 1870 ; 1871 DF6C fixadr $df6c Macro: FIXADR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 1872 DF6C fpconst_half: 1873 DF6C 3F 50 00 00 00 00 .fl 0.5 1874 1875 ;========================================================================== 1876 ; log10(x) coefficients 1877 ; 1878 ; LOG10 computes: 1879 ; -0.30 <= z <= 3.0 1880 ; y = (z-1)/(z+1) -0.54 <= y <= 0.5 1881 ; x = y^2 0 <= x <= 0.29 1882 ; log10(z) = f(x)*y 1883 ; 1884 ; Therefore: 1885 ; f(x) = log10((1+y)/(1-y))/y 1886 ; 1887 DF72 fpconst_log10coeff: ;Maclaurin series expansion for log10((z-1)/(z+1)) 1888 DF72 3F 20 26 22 71 53 .fl 0.2026227154 1889 DF78 BF 07 32 04 49 21 .fl -0.0732044921 1890 DF7E 3F 10 60 98 35 64 .fl 0.1060983564 1891 DF84 3F 05 60 41 73 29 .fl 0.0560417329 1892 DF8A 3F 08 04 18 84 06 .fl 0.0804188407 1893 DF90 3F 09 63 91 60 14 .fl 0.0963916015 1894 DF96 3F 12 40 89 61 35 .fl 0.1240896135 1895 DF9C 3F 17 37 17 66 45 .fl 0.1737176646 1896 DFA2 3F 28 95 29 65 58 .fl 0.2895296558 1897 DFA8 3F 86 85 88 96 37 .fl 0.8685889638 1898 1899 ;========================================================================== 1900 ; Arctangent coefficients 1901 ; 1902 ; The 11 coefficients here form a power series approximation 1903 ; f(x^2) ~= atn(x)/x. This is not an official feature of the math pack but 1904 ; is relied upon by BASIC. 1905 ; 1906 ; We used to use the coefficients from Abramowitz & Stegun 4.4.49 here, but 1907 ; there seems to be an error there such that the result falls far short 1908 ; of the specified 2x10^-8 accuracy over 0<=x<=1 at x=1. Instead, we now 1909 ; use a custom minimax polynomial for f(y)=atn(sqrt(y))/sqrt(y) where y=x^2. 1910 ; 1911 DFAE fixadr $dfae Macro: FIXADR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 1912 DFAE atncoef: ;coefficients for atn(x)/x ~= f(x^2) 1913 ;see Abramowitz & Stegun 4.4.49 1914 1915 DFAE 3E 11 12 07 58 81 .fl 0.001112075881 ;x**10*1.11207588057982e-3 1916 DFB4 BE 73 04 08 75 20 .fl -0.007304087520 ;x**9*-7.30408751951452e-3 1917 DFBA 3F 02 24 96 55 73 .fl 0.0224965573 ;x**8*2.24965572957342e-2 1918 DFC0 BF 04 46 18 51 71 .fl -0.0446185172 ;x**7*-4.46185172165888e-2 1919 DFC6 3F 06 73 46 32 44 .fl 0.0673463245 ;x**6*6.73463245104305e-2 1920 DFCC BF 08 80 69 06 64 .fl -0.0880690664 ;x**5*-8.80690663570546e-2 1921 DFD2 3F 11 05 66 74 99 .fl 0.1105667499 ;x**4*1.10566749879313e-1 1922 DFD8 BF 14 27 94 93 12 .fl -0.1427949312 ;x**3*-1.42794931245212e-1 1923 DFDE 3F 19 99 96 30 60 .fl 0.1999963060 ;x**2*1.99996306023439e-1 1924 DFE4 BF 33 33 33 24 72 .fl -0.3333332472 ;x**1*-3.33333247188074e-1 1925 ;x**0*9.99999999667198e-1 1926 DFEA fp_one: 1927 DFEA 40 01 00 00 00 00 .fl 1.0 ;also an arctan coeff 1928 DFF0 fixadr $dff0 Macro: FIXADR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 1929 DFF0 fp_pi4: ;pi/4 - needed by Atari Basic ATN() 1930 DFF0 3F 78 53 98 16 34 .fl 0.78539816339744830961566084581988 1931 1932 DFF6 fp_dectobin_tab: 1933 DFF6 00 FA F4 EE E8 E2 + :10 dta <[-6*#] 1934 1935 E000 ckaddr $e000 Macro: CKADDR [Source: source/Shared/mathpack.s] Source: source/Shared/mathpack.s 102 103 E000 org $e000 104 E000 icl 'atarifont.inc' Source: source/Shared/atarifont.inc 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Character Font 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 E000 00 00 00 00 00 00 + ins 'atarifont.bin',$0,$400 105 106 E400 org $e400 107 E400 F9 F9 editrv dta a(EditorOpen-1) 108 E402 27 FE dta a(EditorClose-1) 109 E404 05 FA dta a(EditorGetByte-1) 110 E406 B7 FA dta a(EditorPutByte-1) 111 E408 C8 E4 dta a(EditorGetStatus-1) 112 E40A CA E4 dta a(EditorSpecial-1) 113 E40C 4C CB E4 jmp EditorInit 114 E40F 00 dta $00 115 116 E410 F5 F3 screnv dta a(ScreenOpen-1) 117 E412 27 FE dta a(ScreenClose-1) 118 E414 D1 F5 dta a(ScreenGetByte-1) 119 E416 11 F6 dta a(ScreenPutByte-1) 120 E418 C8 E4 dta a(ScreenGetStatus-1) 121 E41A F5 F6 dta a(ScreenSpecial-1) 122 E41C 20 C4 F5 jsr ScreenInit 123 E41F 00 dta $00 124 125 E420 C8 E4 keybdv dta a(KeyboardOpen-1) 126 E422 C8 E4 dta a(KeyboardClose-1) 127 E424 68 FE dta a(KeyboardGetByte-1) 128 E426 CA E4 dta a(KeyboardPutByte-1) 129 E428 C8 E4 dta a(KeyboardGetStatus-1) 130 E42A CA E4 dta a(KeyboardSpecial-1) 131 E42C 4C 3F FE jmp KeyboardInit 132 E42F 00 dta $00 133 134 E430 83 EC printv dta a(PrinterOpen-1) 135 E432 98 EC dta a(PrinterClose-1) 136 E434 CA E4 dta a(PrinterGetByte-1) 137 E436 9F EC dta a(PrinterPutByte-1) 138 E438 ED EC dta a(PrinterGetStatus-1) 139 E43A CA E4 dta a(PrinterSpecial-1) 140 E43C 20 7E EC jsr PrinterInit 141 E43F 00 dta $00 142 143 E440 19 ED casetv dta a(CassetteOpen-1) 144 E442 6E ED dta a(CassetteClose-1) 145 E444 8F ED dta a(CassetteGetByte-1) 146 E446 CF ED dta a(CassettePutByte-1) 147 E448 C8 E4 dta a(CassetteGetStatus-1) 148 E44A CA E4 dta a(CassetteSpecial-1) 149 E44C 4C 0F ED jmp CassetteInit 150 E44F 00 dta $00 151 152 ;vector table 153 E450 org $e450 154 E450 4C 0E EC diskiv jmp DiskInit ;$E450 155 E453 4C 19 EC dskinv jmp DiskHandler ;$E453 156 E456 4C FC E4 ciov jmp CIO ;$E456 157 E459 4C F6 E7 siov jmp SIO ;$E459 158 E45C 4C 5F C1 setvbv jmp VBISetVector ;$E45C 159 E45F 4C 0C C0 sysvbv jmp VBIStage1 ;$E45F 160 E462 4C 50 C0 xitvbv jmp VBIExit ;$E462 161 E465 4C EB E7 sioinv jmp SIOInit ;$E465 162 E468 4C 47 E9 sendev jmp SIOSendEnable ;$E468 163 E46B 4C 75 C1 intinv jmp IntInitInterrupts ;$E46B 164 E46E 4C EA E4 cioinv jmp CIOInit ;$E46E 165 166 .if _KERNEL_XLXE 167 E471 4C 9B E4 blkbdv jmp SelfTestEntry ;$E471 168 .else 169 blkbdv jmp Blackboard ;$E471 170 .endif 171 172 E474 4C 4F EF warmsv jmp InitWarmStart ;$E474 173 E477 4C D6 EE coldsv jmp InitColdStart ;$E477 174 E47A 4C 10 EE rblokv jmp CassetteReadBlock ;$E47A 175 E47D 4C 2D ED csopiv jmp CassetteOpenRead ;$E47D 176 177 .if _KERNEL_XLXE 178 E480 4C 9B E4 pupdiv jmp SelfTestEntry ;$E480 XL/XE: power-up display 179 E483 4C 00 50 slftsv jmp $5000 ;$E483 XL/XE: self-test entry 180 E486 4C 22 C3 pentv jmp PHAddHandler ;$E486 XL/XE: peripheral handler add 181 E489 4C 58 C3 phunlv jmp PHRemoveHandler ;$E489 XL/XE: peripheral handler remove 182 E48C 4C 9E C3 phiniv jmp PHInitHandler ;$E48C XL/XE: peripheral handler init 183 E48F gpdvv PBI_VECTOR_TABLE ;$E48F XL/XE: Generic device vector Macro: PBI_VECTOR_TABLE [Source: source/Shared/pbi.s] 1 E48F CF C2 dta a(PBIGenericDeviceOpen-1) 2 E491 D3 C2 dta a(PBIGenericDeviceClose-1) 3 E493 D7 C2 dta a(PBIGenericDeviceGetByte-1) 4 E495 DB C2 dta a(PBIGenericDevicePutByte-1) 5 E497 19 C3 dta a(PBIGenericDeviceGetStatus-1) 6 E499 1D C3 dta a(PBIGenericDeviceSpecial-1) Source: source/main.xasm 184 .endif 185 186 .if _KERNEL_XLXE 187 E49B icl 'selftestentry.s' Source: source/Shared/selftestentry.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Self Test Entry Trampoline 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 E49B .proc SelfTestEntry 11 E49B AD 01 D3 lda portb 12 E49E 29 7F and #$7f 13 E4A0 8D 01 D3 sta portb 14 E4A3 4C 00 50 jmp BootScreen 15 .endp 188 .else 189 icl 'blackboard.s' 190 .endif 191 192 ;============================================================================== 193 ; $E4C0 Known RTS instruction 194 ; 195 ; The Atari 850 handler uses this as a "known RTS" instruction, as does 196 ; Altirra's internal R: handler emulation. 197 ; 198 E4A6 org $e4c0 199 200 E4C0 .nowarn .proc KnownRTS 201 E4C0 60 rts 202 .endp 203 204 ;============================================================================== 205 ; Main modules. 206 ; 207 ; We report the sizes here as well as reference sizes. The reference sizes for 208 ; OS-B come from Mapping the Atari. 209 ; 210 211 .echo 'Module sizes:' 211 Module sizes: 212 213 .macro _KERNEL_REPORT_MODULE_MARK 214 .def ?@_kernel_lastpt = * 215 .endm 216 217 .macro _KERNEL_REPORT_MODULE_PAD_ADJUST 218 .def ?@_kernel_lastpt = ?@_kernel_lastpt + :1 219 .endm 220 221 .macro _KERNEL_REPORT_MODULE_SIZE 222 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', :2, ')', ' ', :1 223 224 .def ?@_kernel_lastpt = * 225 .endm 226 227 E4C1 icl 'misc.s' Source: source/Shared/misc.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Miscellaneous data 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 ;Used by PBI and display/editor. 12 ; 13 E4C1 .proc ReversedBitMasks 14 E4C1 80 40 20 10 08 04 + dta $80,$40,$20,$10,$08,$04,$02,$01 15 .endp 16 17 ;========================================================================== 18 ;Used by CIO devices 19 E4C9 .proc CIOExitSuccess 20 E4C9 A0 01 ldy #1 21 E4CB exit_not_supported: 22 E4CB 60 rts 23 .endp 24 25 = E4CB CIOExitNotSupported = CIOExitSuccess.exit_not_supported 26 27 ;========================================================================== 28 ; Sound a bell using the console speaker. 29 ; 30 ; Entry: 31 ; Y = duration 32 ; 33 ; Modified: 34 ; X 35 ; 36 ; Preserved: 37 ; A 38 ; 39 E4CC .proc Bell 40 E4CC 48 pha 41 E4CD A9 08 lda #$08 42 E4CF soundloop: 43 E4CF A2 04 ldx #4 44 E4D1 48 pha 45 E4D2 delay: 46 E4D2 AD 0B D4 lda vcount 47 E4D5 CD 0B D4 F0 FB cmp:req vcount 48 E4DA CA dex 49 E4DB D0 F5 bne delay 50 E4DD 68 pla 51 E4DE 49 08 eor #$08 52 E4E0 8D 1F D0 sta consol 53 E4E3 D0 EA bne soundloop 54 E4E5 88 dey 55 E4E6 D0 E7 bne soundloop 56 E4E8 68 pla 57 E4E9 60 rts 58 .endp 228 E4EA _KERNEL_REPORT_MODULE_MARK Macro: _KERNEL_REPORT_MODULE_MARK [Source: source/main.xasm] 1 = E4EA .def ?@_kernel_lastpt = * Source: source/main.xasm 229 230 E4EA icl 'cio.inc' Source: source/Shared/cio.inc 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Character Input/Output Definitions 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 .ifndef f_CIO_INC 11 .def f_CIO_INC 12 13 CIOStatBreak = $80 ;break key abort 14 CIOStatIOCBInUse = $81 ;IOCB in use 15 CIOStatUnkDevice = $82 ;unknown device 16 CIOStatWriteOnly = $83 ;opened for write only 17 CIOStatInvalidCmd = $84 ;invalid command 18 CIOStatNotOpen = $85 ;device or file not open 19 CIOStatInvalidIOCB = $86 ;invalid IOCB number 20 CIOStatReadOnly = $87 ;opened for read only 21 CIOStatEndOfFile = $88 ;end of file reached 22 CIOStatTruncRecord = $89 ;record truncated 23 CIOStatTimeout = $8A ;device timeout 24 CIOStatNAK = $8B ;device NAK 25 CIOStatSerFrameErr = $8C ;serial bus framing error 26 CIOStatCursorRange = $8D ;cursor out of range 27 CIOStatSerOverrun = $8E ;serial frame overrun error 28 CIOStatSerChecksum = $8F ;serial checksum error 29 CIOStatDeviceDone = $90 ;device done error 30 CIOStatBadScrnMode = $91 ;bad screen mode 31 CIOStatNotSupported = $92 ;function not supported by handler 32 CIOStatOutOfMemory = $93 ;not enough memory 33 CIOStatDriveNumErr = $A0 ;disk drive # error 34 CIOStatTooManyFiles = $A1 ;too many open disk files 35 CIOStatDiskFull = $A2 ;disk full 36 CIOStatFatalDiskIO = $A3 ;fatal disk I/O error 37 CIOStatFileNumDiff = $A4 ;internal file # mismatch 38 CIOStatFileNameErr = $A5 ;filename error 39 CIOStatPointDLen = $A6 ;point data length error 40 CIOStatFileLocked = $A7 ;file locked 41 CIOStatInvDiskCmd = $A8 ;invalid command for disk 42 CIOStatDirFull = $A9 ;directory full (64 files) 43 CIOStatFileNotFound = $AA ;file not found 44 CIOStatInvPoint = $AB ;invalid point 45 46 CIOCmdOpen = $03 47 CIOCmdGetRecord = $05 48 CIOCmdGetChars = $07 49 CIOCmdPutRecord = $09 50 ; $0A ;PUT CHARS alias (required by K-Razy Shoot Out) 51 CIOCmdPutChars = $0B 52 CIOCmdClose = $0C 53 CIOCmdGetStatus = $0D 54 CIOCmdSpecial = $0E ;$0E and up is escape 55 56 .endif 231 232 .ifdef _KERNEL_816 233 icl 'cio816.s' 234 .else 235 E4EA icl 'cio.s' Source: source/Shared/cio.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Character Input/Output Facility 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 E4EA .proc CIOInit 11 E4EA 38 sec 12 E4EB A2 70 ldx #$70 13 E4ED iocb_loop: 14 E4ED A9 FF lda #$ff 15 E4EF 9D 40 03 sta ichid,x 16 E4F2 20 5E E7 jsr CIOSetPutByteClosed 17 E4F5 8A txa 18 E4F6 E9 10 sbc #$10 19 E4F8 AA tax 20 E4F9 10 F2 bpl iocb_loop 21 E4FB 60 rts 22 .endp 23 24 ;============================================================================== 25 ; Character I/O entry vector 26 ; 27 ; On entry: 28 ; X = IOCB offset (# x 16) 29 ; 30 ; Returns: 31 ; A = depends on operation 32 ; X = IOCB offset (# x 16) 33 ; Y = status (reflected in P) 34 ; 35 ; Notes: 36 ; BUFADR must not be touched from CIO. DOS XE relies on this for 37 ; temporary storage and breaks if it is modified. 38 ; 39 ; XL/XE mode notes: 40 ; HNDLOD is always set to $00 afterward, per Sweet 16 supplement 3. 41 ; 42 ; CIO can optionally attempt a provisional open by doing a type 4 poll 43 ; over the SIO bus. This happens unconditionally if HNDLOD is non-zero 44 ; and only after the device is not found in HATABS if HNDLOD is zero. 45 ; If this succeeds, the IOCB is provisionally opened. Type 4 polling 46 ; ONLY happens for direct opens -- it does not happen for a soft open. 47 ; 48 E4FC .proc CIO 49 ;stash IOCB offset (X) and acc (A) 50 E4FC 85 2F sta ciochr 51 E4FE 86 2E stx icidno 52 E500 20 13 E5 jsr process 53 E503 xit: 54 ;copy status back to IOCB 55 E503 A6 2E ldx icidno 56 E505 98 tya 57 E506 9D 43 03 sta icsta,x 58 E509 08 php 59 60 .if _KERNEL_XLXE 61 E50A A9 00 8D E9 02 mva #0 hndlod 62 .endif 63 64 E50F A5 2F lda ciochr 65 E511 28 plp 66 E512 60 rts 67 68 E513 process: 69 ;validate IOCB offset 70 E513 8A txa 71 E514 29 8F and #$8f 72 E516 F0 06 beq validIOCB 73 74 ;return invalid IOCB error 75 E518 A0 86 ldy #CIOStatInvalidIOCB 76 E51A 60 rts 77 78 E51B cmdInvalid: 79 ;invalid command <$03 80 E51B A0 84 ldy #CIOStatInvalidCmd 81 E51D 60 rts 82 83 E51E validIOCB: 84 E51E 20 EB E6 jsr CIOLoadZIOCB 85 86 ;check if we're handling the OPEN command 87 E521 A5 22 lda iccomz 88 E523 C9 03 cmp #CIOCmdOpen 89 E525 F0 7B beq cmdOpen 90 E527 90 F2 bcc cmdInvalid 91 92 ;check if the IOCB is open 93 E529 A4 20 ldy ichidz 94 95 .if !_KERNEL_XLXE 96 bpl isOpen 97 .else 98 E52B 30 15 bmi not_open 99 100 ;check for a provisionally open IOCB 101 E52D C8 iny 102 E52E 10 2E bpl isOpen 103 104 ;okay, it's provisionally open... check if it's a close 105 E530 C9 0C cmp #CIOCmdClose 106 E532 D0 03 4C A2 E6 sne:jmp cmdCloseProvisional 107 108 ;check if we're allowed to load a handler 109 E537 AD E9 02 lda hndlod 110 E53A F0 06 beq not_open 111 112 ;try to load the handler 113 E53C 20 9C E7 jsr CIOLoadHandler 114 E53F 10 1D bpl isOpen 115 E541 60 rts 116 .endif 117 118 E542 not_open: 119 ;IOCB isn't open - issue error 120 ; 121 ;Special cases; 122 ; - No error issued for close ($0C). This is needed so that extra CLOSE 123 ; commands from BASIC don't trip errors. 124 ; - Get status ($0D) and special ($0E+) do soft open and close if needed. 125 ; $0D case is required for Top Dos 1.5a to boot; $0E+ case is encountered 126 ; with R: device XIO commands. 127 ; 128 E542 A0 01 ldy #1 129 E544 A5 22 lda iccomz 130 E546 C9 0C cmp #CIOCmdClose 131 E548 F0 06 beq ignoreOpen 132 E54A C9 0D cmp #CIOCmdGetStatus 133 E54C B0 03 bcs preOpen ;closed IOCB is OK for get status and special 134 E54E not_open_handler: 135 E54E A0 85 ldy #CIOStatNotOpen 136 E550 ignoreOpen: 137 E550 60 rts 138 139 E551 preOpen: 140 ;If the device is not open when a SPECIAL command is issued, parse the path 141 ;and soft-open the device in the zero page IOCB. 142 E551 20 FA E6 jsr CIOParsePath 143 144 ;check for special command 145 E554 A5 22 lda iccomz 146 E556 C9 0D cmp #CIOCmdGetStatus 147 E558 F0 40 beq cmdGetStatusSoftOpen 148 E55A C9 0E cmp #CIOCmdSpecial 149 E55C B0 3F bcs cmdSpecialSoftOpen 150 151 E55E isOpen: 152 E55E A6 22 ldx iccomz 153 E560 E0 0E cpx #CIOCmdSpecial 154 E562 90 02 A2 0E scc:ldx #$0e 155 156 ;do permissions check 157 E566 BD A9 E6 lda perm_check_table-4,x 158 E569 30 04 bmi skip_perm_check 159 E56B 24 2A bit icax1z 160 E56D F0 26 beq perm_check_fail 161 E56F skip_perm_check: 162 163 ;load command table vector 164 E56F BD CA E6 lda command_table_hi-4,x 165 E572 48 pha 166 E573 BD BF E6 lda command_table_lo-4,x 167 E576 48 pha 168 169 ;preload dispatch vector and dispatch to command 170 E577 BC B4 E6 ldy vector_preload_table-4,x 171 E57A load_vector: 172 E57A A6 20 ldx ichidz 173 E57C BD 1B 03 85 2C BD + mwa hatabs+1,x icax3z 174 E586 B1 2C lda (icax3z),y 175 E588 AA tax 176 E589 88 dey 177 E58A B1 2C lda (icax3z),y 178 E58C 85 2C sta icax3z 179 E58E 86 2D stx icax3z+1 180 181 ;many commands want to check length=0 on entry 182 E590 A5 28 lda icbllz 183 E592 05 29 ora icblhz 184 E594 60 rts 185 186 E595 perm_check_fail: 187 ;at this point we have A=$04 if we failed a get perm check, and A=$08 188 ;if we failed a put perm check -- these need to be translated to Y=$83 189 ;and Y=$87. 190 E595 18 clc 191 E596 69 7F adc #$7f 192 E598 A8 tay 193 E599 60 rts 194 195 ;-------------------------------------------------------------------------- 196 E59A cmdGetStatusSoftOpen: 197 E59A A0 09 ldy #9 198 E59C 2C dta {bit $0100} 199 E59D cmdSpecialSoftOpen: 200 E59D A0 0B ldy #11 201 E59F invoke_and_soft_close_xit: 202 E59F 4C D9 E6 jmp CIOInvoke 203 204 ;-------------------------------------------------------------------------- 205 ; Open command ($03). 206 ; 207 E5A2 cmdOpen: 208 ;check if the IOCB is already open 209 E5A2 A4 20 ldy ichidz 210 E5A4 C8 iny 211 E5A5 F0 03 beq notAlreadyOpen 212 213 ;IOCB is already open - error 214 E5A7 A0 81 ldy #CIOStatIOCBInUse 215 E5A9 60 rts 216 217 E5AA notAlreadyOpen: 218 ;attempt to parse and open -- note that this will fail out directly 219 ;on an unknown device or provisional open 220 E5AA 20 FA E6 jsr CIOParsePath 221 222 E5AD open_entry: 223 ;request open 224 E5AD A0 01 ldy #1 225 E5AF 20 D9 E6 jsr CIOInvoke 226 227 ;move handler ID and device number to IOCB 228 E5B2 A6 2E ldx icidno 229 E5B4 A5 20 9D 40 03 mva ichidz ichid,x 230 E5B9 A5 21 9D 41 03 mva icdnoz icdno,x 231 232 E5BE 98 tya 233 E5BF 10 01 bpl openOK 234 E5C1 60 rts 235 236 E5C2 openOK: 237 238 ;copy PUT BYTE vector for Atari Basic 239 E5C2 A6 20 ldx ichidz 240 E5C4 BD 1B 03 85 2C BD + mwa hatabs+1,x icax3z 241 E5CE A0 06 ldy #6 242 E5D0 B1 2C lda (icax3z),y 243 E5D2 A6 2E ldx icidno 244 E5D4 9D 46 03 sta icptl,x 245 E5D7 C8 iny 246 E5D8 B1 2C lda (icax3z),y 247 E5DA 9D 47 03 sta icpth,x 248 E5DD A0 01 ldy #1 249 E5DF 60 rts 250 251 = E6DC cmdGetStatus = CIOInvoke.invoke_vector 252 E5E0 cmdSpecial: 253 E5E0 20 DC E6 jsr CIOInvoke.invoke_vector 254 255 ;need to copy AUX1/2 back for R: 256 E5E3 A6 2E ldx icidno 257 E5E5 A5 2A 9D 4A 03 mva icax1z icax1,x 258 E5EA A5 2B 9D 4B 03 mva icax2z icax2,x 259 E5EF 60 rts 260 261 ;-------------------------------------------------------------------------- 262 E5F0 cmdGetRecord: 263 ;check if buffer is full on entry 264 E5F0 F0 16 beq cmdGetRecordBufferFull 265 E5F2 cmdGetRecordLoop: 266 E5F2 cmdGetRecordGetByte: 267 ;fetch byte 268 E5F2 20 DC E6 jsr CIOInvoke.invoke_vector 269 E5F5 C0 00 cpy #0 270 E5F7 30 1C bmi cmdGetRecordXit 271 272 ;store byte (even if EOL) 273 E5F9 A2 00 ldx #0 274 E5FB 81 24 sta (icbalz,x) 275 276 ;check for EOL 277 E5FD 49 9B eor #$9b 278 E5FF C9 01 cmp #1 279 280 ;increment buffer pointer and decrement length 281 E601 20 8C E6 jsr advance_pointers 282 283 ;skip buffer full check if we had an EOL 284 E604 90 0F bcc cmdGetRecordXit 285 286 ;loop back for more bytes if buffer not full 287 E606 D0 EA bne cmdGetRecordLoop 288 289 E608 cmdGetRecordBufferFull: 290 ;read byte to discard 291 E608 20 DC E6 jsr CIOInvoke.invoke_vector 292 E60B C0 00 cpy #0 293 E60D 30 06 bmi cmdGetRecordXit 294 295 ;continue if not EOL 296 E60F C9 9B cmp #$9b 297 E611 D0 F5 bne cmdGetRecordBufferFull 298 299 ;return truncated record 300 E613 A0 89 ldy #CIOStatTruncRecord 301 302 E615 cmdGetRecordXit: 303 E615 cmdGetPutDone: 304 ;update byte count in IOCB 305 E615 A6 2E ldx icidno 306 E617 38 sec 307 E618 BD 48 03 lda icbll,x 308 E61B E5 28 sbc icbllz 309 E61D 85 28 sta icbllz ;required by Lightspeed DOS 310 E61F 9D 48 03 sta icbll,x 311 E622 BD 49 03 lda icblh,x 312 E625 E5 29 sbc icblhz 313 E627 85 29 sta icblhz 314 E629 9D 49 03 sta icblh,x 315 316 ;NOMAM 2013 BASIC Ten-Liners disk requires ICBALZ to be untouched :P 317 E62C BD 44 03 85 24 BD + mwa icbal,x icbalz 318 319 ;Pacem in Terris requires Y=1 exit. 320 ;DOS 3.0 with 128K/XE mode requires Y=3 for EOF imminent. 321 E636 60 rts 322 323 ;-------------------------------------------------------------------------- 324 E637 cmdGetChars: 325 E637 F0 15 beq cmdGetCharsSingle 326 E639 cmdGetCharsLoop: 327 E639 20 DC E6 jsr CIOInvoke.invoke_vector 328 E63C C0 00 cpy #0 329 E63E 30 0B bmi cmdGetCharsError 330 E640 A2 00 ldx #0 331 E642 85 2F sta ciochr ;required by HOTEL title screen 332 E644 81 24 sta (icbalz,x) 333 E646 20 8C E6 jsr advance_pointers 334 E649 D0 EE bne cmdGetCharsLoop 335 E64B cmdGetCharsError: 336 E64B 4C 15 E6 jmp cmdGetPutDone 337 338 E64E cmdGetCharsSingle: 339 E64E 20 DC E6 jsr CIOInvoke.invoke_vector 340 E651 85 2F sta ciochr 341 E653 60 rts 342 343 ;-------------------------------------------------------------------------- 344 ; PUT RECORD handler ($09) 345 ; 346 ; Exit: 347 ; ICBAL/ICBAH: Not changed 348 ; ICBLL/ICBLH: Number of bytes processed 349 ; 350 ; If the string does not contain an EOL character, one is printed at the 351 ; end. Also, in this case CIOCHR must reflect the last character in the 352 ; buffer and not the EOL. (Required by Atari DOS 2.5 RAMDISK banner) 353 ; 354 ; If length=0, the character in the A register is output without an EOL. 355 ; This behavior is required by the graphics library for Mad Pascal. 356 ; 357 E654 cmdPutRecord: 358 E654 F0 33 beq cmdPutCharsSingle 359 E656 cmdPutRecordLoop: 360 E656 A0 00 ldy #0 361 E658 B1 24 lda (icbalz),y 362 E65A 20 DC E6 jsr CIOInvoke.invoke_vector 363 E65D 98 tya 364 E65E 30 12 bmi cmdPutRecordError 365 E660 20 8C E6 jsr advance_pointers 366 E663 F0 08 beq cmdPutRecordEOL 367 E665 A9 9B lda #$9b 368 E667 C5 2F cmp ciochr 369 E669 F0 07 beq cmdPutRecordDone 370 E66B D0 E7 bne cmdPutRecord 371 372 E66D cmdPutRecordEOL: 373 E66D A9 9B lda #$9b 374 E66F 20 DC E6 jsr CIOInvoke.invoke_vector 375 E672 cmdPutRecordError: 376 E672 cmdPutRecordDone: 377 E672 4C 15 E6 jmp cmdGetPutDone 378 379 ;-------------------------------------------------------------------------- 380 E675 cmdPutChars: 381 E675 F0 12 beq cmdPutCharsSingle 382 E677 cmdPutCharsLoop: 383 E677 A0 00 ldy #0 384 E679 B1 24 lda (icbalz),y 385 E67B 20 DC E6 jsr CIOInvoke.invoke_vector 386 E67E 98 tya 387 E67F 30 F1 bmi cmdPutRecordError 388 E681 20 8C E6 jsr advance_pointers 389 E684 D0 F1 bne cmdPutCharsLoop 390 E686 4C 15 E6 jmp cmdGetPutDone 391 E689 cmdPutCharsSingle: 392 E689 4C DE E6 jmp CIOInvoke.invoke_vector_ciochr 393 394 ;-------------------------------------------------------------------------- 395 396 E68C advance_pointers: 397 E68C E6 24 D0 02 E6 25 inw icbalz 398 E692 A5 28 D0 02 C6 29 + dew icbllz 399 E69A D0 02 A5 29 sne:lda icblhz 400 E69E 60 rts 401 402 ;-------------------------------------------------------------------------- 403 E69F cmdClose: 404 E69F 20 DC E6 jsr CIOInvoke.invoke_vector 405 E6A2 cmdCloseProvisional: 406 E6A2 A6 2E ldx icidno 407 E6A4 20 5E E7 jsr CIOSetPutByteClosed 408 E6A7 A9 FF 9D 40 03 mva #$ff ichid,x 409 E6AC 60 rts 410 411 E6AD perm_check_table: 412 E6AD 04 dta $04 ;$04 (get record) 413 E6AE 04 dta $04 ;$05 (get record) 414 E6AF 04 dta $04 ;$06 (get chars) 415 E6B0 04 dta $04 ;$07 (get chars) 416 E6B1 08 dta $08 ;$08 (put record) 417 E6B2 08 dta $08 ;$09 (put record) 418 E6B3 08 dta $08 ;$0A (put chars) 419 E6B4 08 dta $08 ;$0B (put chars) 420 E6B5 FF dta $ff ;$0C (close) 421 E6B6 FF dta $ff ;$0D (get status) 422 E6B7 FF dta $ff ;$0E (special) 423 424 E6B8 vector_preload_table: 425 E6B8 05 dta $05 ;$04 (get record) 426 E6B9 05 dta $05 ;$05 (get record) 427 E6BA 05 dta $05 ;$06 (get chars) 428 E6BB 05 dta $05 ;$07 (get chars) 429 E6BC 07 dta $07 ;$08 (put record) 430 E6BD 07 dta $07 ;$09 (put record) 431 E6BE 07 dta $07 ;$0A (put chars) 432 E6BF 07 dta $07 ;$0B (put chars) 433 E6C0 03 dta $03 ;$0C (close) 434 E6C1 09 dta $09 ;$0D (get status) 435 E6C2 0B dta $0b ;$0E (special) 436 437 E6C3 command_table_lo: 438 E6C3 EF dta <(cmdGetRecord-1) ;$04 439 E6C4 EF dta <(cmdGetRecord-1) ;$05 440 E6C5 36 dta <(cmdGetChars-1) ;$06 441 E6C6 36 dta <(cmdGetChars-1) ;$07 442 E6C7 53 dta <(cmdPutRecord-1) ;$08 443 E6C8 53 dta <(cmdPutRecord-1) ;$09 444 E6C9 74 dta <(cmdPutChars-1) ;$0A 445 E6CA 74 dta <(cmdPutChars-1) ;$0B 446 E6CB 9E dta <(cmdClose-1) ;$0C 447 E6CC DB dta <(cmdGetStatus-1) ;$0D 448 E6CD DF dta <(cmdSpecial-1) ;$0E 449 450 E6CE command_table_hi: 451 E6CE E5 dta >(cmdGetRecord-1) ;$04 452 E6CF E5 dta >(cmdGetRecord-1) ;$05 453 E6D0 E6 dta >(cmdGetChars-1) ;$06 454 E6D1 E6 dta >(cmdGetChars-1) ;$07 455 E6D2 E6 dta >(cmdPutRecord-1) ;$08 456 E6D3 E6 dta >(cmdPutRecord-1) ;$09 457 E6D4 E6 dta >(cmdPutChars-1) ;$0A 458 E6D5 E6 dta >(cmdPutChars-1) ;$0B 459 E6D6 E6 dta >(cmdClose-1) ;$0C 460 E6D7 E6 dta >(cmdGetStatus-1) ;$0D 461 E6D8 E5 dta >(cmdSpecial-1) ;$0E 462 .endp 463 464 ;========================================================================== 465 ; Invoke device vector. 466 ; 467 ; Entry (standard): 468 ; A, X = ignored 469 ; Y = offset to high vector byte in device table 470 ; 471 ; Entry (invoke_vector): 472 ; A = byte to pass to PUT CHAR vector 473 ; X, Y = ignored 474 ; 475 ; Exit: 476 ; A = byte returned from GET CHAR vector 477 ; Y = status 478 ; 479 E6D9 .proc CIOInvoke 480 E6D9 20 7A E5 jsr CIO.load_vector 481 E6DC invoke_vector: 482 E6DC 85 2F sta ciochr 483 E6DE invoke_vector_ciochr: 484 E6DE A5 2D lda icax3z+1 485 E6E0 48 pha 486 E6E1 A5 2C lda icax3z 487 E6E3 48 pha 488 E6E4 A0 92 ldy #CIOStatNotSupported 489 E6E6 A6 2E ldx icidno 490 E6E8 A5 2F lda ciochr 491 E6EA 60 rts 492 .endp 493 494 ;========================================================================== 495 ; Copy IOCB to ZIOCB. 496 ; 497 ; Entry: 498 ; X = IOCB 499 ; 500 ; [OSManual p236] "Although both the outer level IOCB and the Zero-page 501 ; IOCB are defined to be 16 bytes in size, only the first 12 bytes are 502 ; moved by CIO." 503 ; 504 E6EB .proc CIOLoadZIOCB 505 ;We used to do a trick here where we would count Y from $F4 to $00... 506 ;but we can't do that because the 65C816 doesn't wrap abs,Y within 507 ;bank 0 even in emulation mode. Argh! 508 509 E6EB A0 00 ldy #0 510 E6ED copyToZIOCB: 511 E6ED BD 40 03 lda ichid,x 512 E6F0 99 20 00 sta ziocb,y 513 E6F3 E8 inx 514 E6F4 C8 iny 515 E6F5 C0 0C cpy #12 516 E6F7 D0 F4 bne copyToZIOCB 517 E6F9 60 rts 518 .endp 519 520 ;========================================================================== 521 E6FA .proc CIOParsePath 522 ;default to device #1 523 E6FA A2 01 ldx #1 524 525 ;pull first character of filename and stash it 526 E6FC A1 23 lda (icbalz-1,x) 527 E6FE 85 2D sta icax4z 528 529 ;Check for a device number. 530 ; 531 ; - D1:-D9: is supported. D0: also gives unit 1, and any digits beyond 532 ; the first are ignored. 533 ; 534 ; We don't validate the colon anymore -- Atari OS allows opening just "C" to get 535 ; to the cassette. 536 ; 537 E700 A0 01 ldy #1 538 E702 B1 24 lda (icbalz),y 539 E704 38 sec 540 E705 E9 30 sbc #'0' 541 E707 F0 06 beq nodevnum 542 E709 C9 0A cmp #10 543 E70B B0 02 bcs nodevnum 544 E70D AA tax 545 546 E70E C8 iny 547 548 E70F nodevnum: 549 E70F 86 21 stx icdnoz 550 551 .if _KERNEL_XLXE 552 ;check if we are doing a true open and if we should do a type 4 poll 553 E711 A5 22 lda iccomz 554 E713 C9 03 cmp #CIOCmdOpen 555 E715 D0 3D bne skip_poll 556 557 ;clear DVSTAT+0/+1 to indicate no poll 558 E717 A9 00 lda #0 559 E719 8D EA 02 sta dvstat 560 E71C 8D EB 02 sta dvstat+1 561 562 ;check if we should do an unconditional poll (HNDLOD nonzero). 563 E71F AD E9 02 lda hndlod 564 E722 D0 05 bne unconditional_poll 565 566 ;search handler table 567 E724 20 69 E7 jsr CIOFindHandler 568 E727 F0 34 beq found 569 570 E729 unconditional_poll: 571 ;do type 4 poll 572 E729 20 7A E7 jsr CIOPollForDevice 573 E72C 30 2B bmi unknown_device 574 575 ;mark provisionally open 576 E72E A6 2E ldx icidno 577 E730 A9 7F 9D 40 03 mva #$7f ichid,x 578 E735 A5 2D 9D 4C 03 mva icax4z icax3,x 579 E73A AD EC 02 9D 4D 03 mva dvstat+2 icax4,x 580 E740 A9 C8 9D 46 03 A9 + mwa #CIOPutByteLoadHandler-1 icptl,x 581 E74A A5 21 9D 41 03 mva icdnoz icdno,x 582 583 ;do direct exit, bypassing regular open path 584 E74F 68 pla 585 E750 68 pla 586 E751 A0 01 ldy #1 587 E753 60 rts 588 589 E754 skip_poll: 590 .endif 591 592 ;search handler table 593 E754 20 69 E7 jsr CIOFindHandler 594 E757 F0 04 beq found 595 596 E759 unknown_device: 597 ;return unknown device error 598 E759 A0 82 ldy #CIOStatUnkDevice 599 E75B 68 pla 600 E75C 68 pla 601 E75D found: 602 E75D 60 rts 603 .endp 604 605 ;========================================================================== 606 E75E .proc CIOSetPutByteClosed 607 E75E A9 4D lda #<[CIO.not_open_handler-1] 608 E760 9D 46 03 sta icptl,x 609 E763 A9 E5 lda #>[CIO.not_open_handler-1] 610 E765 9D 47 03 sta icpth,x 611 E768 60 rts 612 .endp 613 614 ;========================================================================== 615 ; Attempt to find a handler entry in HATABS. 616 ; 617 E769 .proc CIOFindHandler 618 ;search for handler 619 E769 A5 2D lda icax4z 620 E76B A2 21 ldx #11*3 621 E76D findHandler: 622 E76D DD 1A 03 cmp hatabs,x 623 E770 F0 05 beq foundHandler 624 E772 CA dex 625 E773 CA dex 626 E774 CA dex 627 E775 10 F6 bpl findHandler 628 E777 foundHandler: 629 ;store handler ID 630 E777 86 20 stx ichidz 631 E779 60 rts 632 .endp 633 634 ;========================================================================== 635 ; Poll SIO bus for CIO device 636 ; 637 ; Issues a type 4 poll ($4F/$40/devname/devnumber). 638 ; 639 .if _KERNEL_XLXE 640 E77A .proc CIOPollForDevice 641 E77A A5 2D lda icax4z 642 E77C 8D 0A 03 sta daux1 643 E77F A5 21 lda icdnoz 644 E781 8D 0B 03 sta daux2 645 646 E784 A2 09 ldx #9 647 E786 BD 92 E7 9D 00 03 + mva:rpl cmd_tab,x ddevic,x- 648 649 E78F 4C 59 E4 jmp siov 650 651 E792 cmd_tab: 652 E792 4F dta $4f ;device 653 E793 01 dta $01 ;unit 654 E794 40 dta $40 ;command 655 E795 40 dta $40 ;status (transfer flags) 656 E796 EA dta dvstat ;dbufhi 658 E798 40 dta $40 ;dtimlo 659 E799 00 dta $00 ;unused 660 E79A 04 dta $04 ;dbytlo 661 E79B 00 dta $00 ;dbythi 662 .endp 663 .endif 664 665 ;========================================================================== 666 ; Load handler for a provisionally open IOCB. 667 ; 668 .if _KERNEL_XLXE 669 E79C .proc CIOLoadHandler 670 ;load handler over SIO bus 671 E79C AD EC 02 8D D1 02 + mwa dvstat+2 loadad 672 E7A8 A6 2E ldx icidno 673 E7AA BD 4D 03 8D 00 03 mva icax4,x ddevic 674 E7B0 20 01 C5 jsr PHLoadHandler 675 E7B3 B0 11 bcs fail 676 677 ;let's see if we can look up the handler now 678 E7B5 A6 2E ldx icidno 679 E7B7 BD 4C 03 85 2D mva icax3,x icax4z 680 E7BC 20 69 E7 jsr CIOFindHandler 681 E7BF D0 05 bne fail 682 683 ;follow through with open 684 E7C1 20 AD E5 jsr CIO.open_entry 685 E7C4 10 02 bpl ok 686 E7C6 fail: 687 E7C6 A0 82 ldy #CIOStatUnkDevice 688 E7C8 ok: 689 E7C8 60 rts 690 .endp 691 .endif 692 693 ;========================================================================== 694 ; PUT BYTE handler for provisionally open IOCBs. 695 ; 696 ; This handler is used when an IOCB has been provisionally opened pending 697 ; a handler load over the SIO bus. It is used when a direct call is made 698 ; through ICPTL/ICPTH. If HNDLOD=0, the call fails as handler loading is 699 ; not set up; if it is nonzero, the handler is loaded over the SIO bus and 700 ; then the PUT BYTE call continues if everything is good. 701 ; 702 .if _KERNEL_XLXE 703 E7C9 .proc CIOPutByteLoadHandler 704 ;save off A/X 705 E7C9 85 2F sta ciochr 706 E7CB 86 2E stx icidno 707 708 ;check if we're allowed to load a handler and bail if not 709 E7CD AD E9 02 lda hndlod 710 E7D0 F0 10 beq load_error 711 712 ;copy IOCB to ZIOCB 713 E7D2 20 EB E6 jsr CIOLoadZIOCB 714 715 ;try to load the handler 716 E7D5 20 9C E7 jsr CIOLoadHandler 717 E7D8 30 08 bmi load_error 718 719 ;all good... let's invoke the standard handler 720 E7DA A0 07 ldy #7 721 E7DC 20 D9 E6 jsr CIOInvoke 722 E7DF 4C E4 E7 jmp xit 723 724 E7E2 load_error: 725 E7E2 A0 82 ldy #CIOStatUnkDevice 726 E7E4 xit: 727 E7E4 08 php 728 E7E5 A5 2F lda ciochr 729 E7E7 A6 2E ldx icidno 730 E7E9 28 plp 731 E7EA 60 rts 732 .endp 733 .endif 236 .endif 237 238 E7EB _KERNEL_REPORT_MODULE_SIZE 'Central Input/Output (CIO)', $E6D5-$E4A6 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $E6D5-$E4A6, ')', ' ', 'Central Input/Output (CIO)' 1 $E7EB -> $0301($022F) Central Input/Output (CIO) 3 = E7EB .def ?@_kernel_lastpt = * Source: source/main.xasm 239 240 .if !_KERNEL_XLXE 241 icl 'vbi.s' 242 icl 'interrupt.s' 243 icl 'irq.s' 244 .endif 245 E7EB _KERNEL_REPORT_MODULE_SIZE 'Interrupt routines', $E944-$E6D5 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $E944-$E6D5, ')', ' ', 'Interrupt routines' 1 $E7EB -> $0000($026F) Interrupt routines 3 = E7EB .def ?@_kernel_lastpt = * Source: source/main.xasm 246 247 E7EB icl 'sio.inc' Source: source/Shared/sio.inc 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - SIO definitions 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 .ifndef f_SIO_INC 11 .def f_SIO_INC 12 13 SIOSuccess = $01 14 SIOErrorTimeout = $8A 15 SIOErrorNAK = $8B 16 SIOErrorBadFrame = $8C 17 SIOErrorOverrun = $8E 18 SIOErrorChecksum = $8F 19 SIOErrorDeviceError = $90 20 21 .endif 248 E7EB icl 'sio.s' Source: source/Shared/sio.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; AltirraOS modular Kernel ROM - Serial Input/Output (SIO) routines 3 ; Copyright (C) 2008-2019 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 E7EB .proc SIOInit 11 ;turn off POKEY init mode so polynomial counters and audio run 12 E7EB A9 03 8D 0F D2 mva #3 skctl 13 E7F0 8D 32 02 sta sskctl 14 15 ;enable noisy sound (yes, this is actually documented as being inited to 16 ;3) 17 E7F3 85 41 sta soundr 18 E7F5 60 rts 19 .endp 20 21 ;============================================================================== 22 E7F6 .proc SIO 23 ;set retry counters 24 E7F6 A9 01 8D BD 02 mva #$01 dretry 25 26 ;enter critical section 27 E7FB 85 42 sta critic 28 29 .if _KERNEL_PBI_SUPPORT 30 ;attempt PBI transfer 31 E7FD 20 A2 C2 jsr PBIAttemptSIO 32 E800 90 03 4C EC E8 scc:jmp xit_pbi 33 .endif 34 35 ;we must not save STACKP until after PBI devices are polled -- the 36 ;BlackBox PBI routines depend on being able to reuse this location 37 E805 BA tsx 38 E806 8E 18 03 stx stackp 39 40 ;Set timeout timer address -- MUST be done on each call to SIO, or 41 ;Cross-Town Crazy Eight hangs on load due to taking over this vector 42 ;previously. This is guaranteed by the OS Manual in Appendix L, H27. 43 E809 20 13 E9 jsr SIOSetTimeoutVector 44 45 ;check for cassette -- needs to match $60 or else Prisma: Alien Ambush 46 ;fails to load. 47 E80C A2 00 ldx #0 48 E80E AD 00 03 lda ddevic 49 E811 C9 60 cmp #$60 50 E813 D0 01 CA sne:dex 51 E816 8E 0F 03 stx casflg 52 53 ;init POKEY hardware 54 E819 20 66 E9 jsr SIOInitHardware 55 56 ;go do cassette now 57 E81C 2C 0F 03 bit casflg 58 E81F 10 03 bpl retry_command 59 E821 4C DC EA jmp SIOCassette 60 61 E824 retry_command: 62 ;We try 13 times to get a command accepted by a device; after that it 63 ;counts as a device failure and we try one more round of 13 tries. 64 E824 A9 0D 8D 9C 02 mva #$0d cretry 65 66 E829 retry_command_2: 67 ;init command buffer 68 E829 AD 00 03 lda ddevic 69 E82C 18 clc 70 E82D 6D 01 03 adc dunit 71 E830 38 sec 72 E831 E9 01 sbc #1 73 E833 8D 3A 02 sta cdevic 74 75 E836 AD 02 03 8D 3B 02 mva dcomnd ccomnd 76 E83C AD 0A 03 8D 3C 02 mva daux1 caux1 77 E842 AD 0B 03 8D 3D 02 mva daux2 caux2 78 79 ;assert command line 80 E848 A9 34 8D 03 D3 mva #$34 pbctl 81 82 ;wait ~600us to ensure 750us minimum delay (~1k cycles or ~10 scanlines) 83 E84D A2 05 ldx #5 84 E84F AC 0B D4 ldy vcount 85 E852 cmddelay: 86 E852 CC 0B D4 F0 FB cpy:req vcount 87 E857 C8 iny 88 E858 CA dex 89 E859 D0 F7 bne cmddelay 90 91 ;send command frame 92 E85B A9 00 85 3C mva #0 nocksm 93 E85F A9 02 lda #>cdevic 94 E861 85 33 sta bufrhi 95 E863 85 35 sta bfenhi 96 E865 A9 3A 85 32 mva #temp 155 E8B6 86 33 stx bufrhi 156 E8B8 86 35 stx bfenhi 157 E8BA 20 FA E9 jsr SIOReceive 158 E8BD 30 0D bmi transfer_error 159 160 ;Check if we received a C ($43) or E ($45) -- we must NOT abort immediately 161 ;on a device error, as the device still sends back data we need to read, and 162 ;Music Studio relies on the data coming back from a CRC error. 163 E8BF AD 3E 02 lda temp 164 E8C2 C9 43 cmp #$43 165 E8C4 F0 32 beq completeOK 166 E8C6 C9 45 cmp #$45 167 E8C8 F0 2E beq completeOK 168 169 ;we received crap... fail it now 170 E8CA device_error: 171 E8CA A0 90 ldy #SIOErrorDeviceError 172 173 E8CC transfer_error: 174 E8CC 20 38 EA jsr SIOReceiveStop 175 176 E8CF CE BD 02 dec dretry 177 E8D2 30 03 bmi device_retries_exhausted 178 E8D4 4C 24 E8 jmp retry_command 179 180 E8D7 device_retries_exhausted: 181 E8D7 xit: 182 E8D7 AE 0F 03 ldx casflg 183 E8DA D0 0C bne leave_cassette_audio_on 184 E8DC 8E 01 D2 stx audc1 185 E8DF 8E 03 D2 stx audc2 186 E8E2 8E 05 D2 stx audc3 187 E8E5 8E 07 D2 stx audc4 188 E8E8 leave_cassette_audio_on: 189 190 .ifdef _KERNEL_816 191 ;we may be in native mode, so we can't f-up the high byte of the stack pointer 192 lda #1 193 xba 194 lda stackp 195 tcs 196 .else 197 E8E8 AE 18 03 ldx stackp 198 E8EB 9A txs 199 .endif 200 201 E8EC xit_pbi: 202 E8EC A9 00 lda #0 203 E8EE 85 42 sta critic 204 205 E8F0 C0 00 cpy #0 ;!! - A=0 must be preserved for LiteDOS 206 E8F2 8C 03 03 sty dstats 207 E8F5 84 30 sty status 208 E8F7 60 rts 209 210 E8F8 completeOK: 211 ;check if we should read a data frame 212 E8F8 2C 03 03 bit dstats 213 E8FB 50 08 bvc no_receive_frame 214 215 ;setup buffer pointers 216 E8FD 20 B5 E9 jsr SIOSetupBufferPointers 217 218 ;receive the rest of the frame 219 E900 20 FA E9 jsr SIOReceive 220 E903 30 C7 bmi transfer_error 221 222 E905 no_receive_frame: 223 ;now we can finally shut off the receive IRQ 224 E905 20 38 EA jsr SIOReceiveStop 225 226 ;Now check whether we got a device error earlier. If we did, return 227 ;that instead of success. 228 E908 AD 3E 02 lda temp 229 E90B C9 43 cmp #'C' 230 E90D D0 BB bne device_error 231 232 ;nope, we're good... exit OK. 233 E90F A0 01 ldy #SIOSuccess 234 E911 D0 C4 bne xit 235 .endp 236 237 ;============================================================================== 238 E913 .proc SIOSetTimeoutVector 239 E913 A9 D6 8D 26 02 A9 + mwa #SIOCountdown1Handler cdtma1 240 E91D 60 rts 241 .endp 242 243 ;============================================================================== 244 E91E .proc SIOWaitForACK 245 ;setup 2 frame delay for ack 246 E91E A2 FF ldx #$ff 247 E920 8E 17 03 stx timflg 248 E923 86 3C stx nocksm 249 E925 E8 inx ;X=0 250 E926 A9 01 lda #1 251 E928 A0 02 ldy #2 252 E92A 84 33 sty bufrhi ;>temp = 2 253 E92C 84 35 sty bfenhi ;>temp+1 = 2 254 E92E 20 5C E4 jsr setvbv 255 256 ;setup for receiving ACK 257 E931 A2 3E ldx #3600 776 EB26 A0 10 ldy #<3600 777 EB28 20 5F C1 jsr VBISetVector 778 779 ;wait for beginning of frame 780 EB2B A9 10 lda #$10 ;test bit 4 of SKSTAT 781 EB2D waitzerostart: 782 EB2D 2C 17 03 bit timflg 783 EB30 10 2B bpl timeout 784 EB32 2C 0F D2 bit skstat 785 EB35 D0 F6 bne waitzerostart 786 787 ;take first time measurement 788 EB37 20 F7 EB jsr readtimer 789 EB3A 8C 0D 03 sty timer1+1 790 EB3D 8D 0C 03 sta timer1 791 792 ;wait for 19 bit transitions 793 EB40 A9 10 lda #$10 ;test bit 4 of SKSTAT 794 EB42 A2 0A ldx #10 ;test 10 pairs of bits 795 EB44 waitone: 796 EB44 2C 17 03 bit timflg 797 EB47 10 14 bpl timeout 798 EB49 2C 0F D2 bit skstat 799 EB4C F0 F6 beq waitone 800 EB4E CA dex 801 EB4F F0 11 beq waitdone 802 EB51 waitzero: 803 EB51 2C 17 03 bit timflg 804 EB54 10 07 bpl timeout 805 EB56 2C 0F D2 bit skstat 806 EB59 D0 F6 bne waitzero 807 EB5B F0 E7 beq waitone 808 809 EB5D timeout: 810 EB5D A0 8A ldy #SIOErrorTimeout 811 EB5F 4C D7 E8 jmp SIO.xit 812 813 EB62 waitdone: 814 815 ;take second time measurement 816 EB62 20 F7 EB jsr readtimer 817 EB65 8D 10 03 sta timer2 818 EB68 8C 11 03 sty timer2+1 819 820 ;compute baud rate and adjust pokey divisor 821 ; 822 ; counts = (pal ? 156 : 131)*rtdelta + vdelta; 823 ; lines = counts * 2 824 ; lines_per_bit = lines / 19 825 ; cycles_per_bit = lines_per_bit * 114 826 ; pokey_divisor = cycles_per_bit / 2 - 7 827 ; 828 ; -or- 829 ; 830 ; pokey_divisor = counts * 2 * 114 / 19 / 2 - 7 831 ; = counts * 6 - 7 832 ; 833 ;16 bits at 600 baud is nominally 209 scanline pairs. This means that we 834 ;don't have to worry about more than two frames, which is at least 262 835 ;scanline pairs or less than 480 baud. 836 837 ;set frame height - 262 scanlines for NTSC, 312 for PAL 838 EB6B A2 83 ldx #131 839 EB6D AD 14 D0 lda pal 840 EB70 4A lsr 841 EB71 D0 02 A2 9C sne:ldx #156 842 EB75 8E 15 03 stx temp3 843 844 ;compute line difference 845 EB78 AD 0C 03 lda timer1 846 EB7B 20 05 EC jsr correct_time 847 EB7E 85 34 sta bfenlo 848 849 EB80 AD 10 03 lda timer2 850 EB83 20 05 EC jsr correct_time 851 EB86 18 clc ;!! this decrements one line from the line delta 852 EB87 E5 34 sbc bfenlo 853 EB89 85 34 sta bfenlo 854 EB8B A0 00 ldy #0 855 EB8D B0 01 88 scs:dey 856 857 ;compute frame difference 858 EB90 AD 11 03 lda timer2+1 859 EB93 38 ED 0D 03 sub timer1+1 860 EB97 AA tax 861 862 ;accumulate frame difference 863 EB98 F0 0C beq no_frames 864 EB9A A5 34 lda bfenlo 865 EB9C add_frame_loop: 866 EB9C 18 clc 867 EB9D 6D 15 03 adc temp3 868 EBA0 90 01 C8 scc:iny 869 EBA3 CA dex 870 EBA4 D0 F6 bne add_frame_loop 871 EBA6 no_frames: 872 EBA6 84 35 sty bfenhi 873 874 ;compute lines*6 - 7 = (lines-1)*6 - 1 875 EBA8 0A asl ;(lines-1)*2 (lo) 876 EBA9 26 35 rol bfenhi ;(lines-1)*2 (hi) 877 EBAB 85 34 sta bfenlo 878 EBAD A4 35 ldy bfenhi ; 879 EBAF 06 34 asl bfenlo ;(lines-1)*4 (lo) 880 EBB1 26 35 rol bfenhi ;(lines-1)*4 (hi) 881 EBB3 65 34 adc bfenlo ;(lines-1)*6 (lo) 882 EBB5 AA tax ; 883 EBB6 98 tya ; 884 EBB7 65 35 adc bfenhi ;(lines-1)*6 (hi) (and c=0) 885 EBB9 CA dex ;-1 line, bringing us to -7 886 EBBA 8E 04 D2 stx audf3 887 EBBD 8E EE 02 stx cbaudl 888 EBC0 E8 inx 889 EBC1 D0 02 E9 00 sne:sbc #0 890 EBC5 8D 06 D2 sta audf4 891 EBC8 8D EF 02 sta cbaudh 892 893 ;kick pokey into init mode to reset serial input shift hw 894 EBCB AE 32 02 ldx sskctl 895 EBCE 8A txa 896 EBCF 29 FC and #$fc 897 EBD1 8D 0F D2 sta skctl 898 899 ;reset serial port status 900 EBD4 8D 0A D2 sta skres 901 902 ;re-enable serial input hw 903 EBD7 8E 0F D2 stx skctl 904 905 EBDA 20 B5 E9 jsr SIOSetupBufferPointers 906 907 ;stuff two $55 bytes into the buffer, which we "read" above 908 EBDD A9 55 lda #$55 909 EBDF A0 00 ldy #0 910 EBE1 A2 02 ldx #2 911 EBE3 aaloop: 912 EBE3 91 32 sta (bufrlo),y 913 EBE5 E6 32 D0 02 E6 33 inw bufrlo 914 EBEB CA D0 F5 dex:bne aaloop 915 916 ;reset checksum for two $55 bytes and receive frame 917 EBEE 0A asl 918 EBEF 85 31 sta chksum 919 920 EBF1 20 FC E9 jsr SIOReceive.use_checksum 921 EBF4 4C 38 EA jmp SIOReceiveStop 922 923 ;------------------------------------------------------------------------- 924 ; We have to be VERY careful when reading (RTCLOK+2, VCOUNT), because 925 ; the VBI can strike in between. First, we double-check RTCLOK+2 to see 926 ; if it has changed. If so, we retry the read. Second, we check if 927 ; VCOUNT=124, which corresponds to lines 248/249. This can correspond to 928 ; either before or after the VBI -- with CRITIC off the VBI ends around 929 ; (249, 20-50) -- so we don't know which side of the frame boundary we're 930 ; on. 931 ; 932 EBF7 readtimer: 933 EBF7 A4 14 ldy rtclok+2 934 EBF9 AD 0B D4 lda vcount 935 EBFC C4 14 cpy rtclok+2 936 EBFE D0 F7 bne readtimer 937 EC00 C9 7C cmp #124 938 EC02 F0 F3 beq readtimer 939 EC04 60 rts 940 941 EC05 correct_time: 942 EC05 38 sec 943 EC06 E9 7C sbc #124 944 EC08 B0 03 bcs time_ok 945 EC0A 6D 15 03 adc temp3 946 EC0D time_ok: 947 EC0D 60 rts 948 949 .endp 950 249 EC0E _KERNEL_REPORT_MODULE_SIZE 'Serial Input/Output (SIO)', $EDEA-$E944 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $EDEA-$E944, ')', ' ', 'Serial Input/Output (SIO)' 1 $EC0E -> $0423($04A6) Serial Input/Output (SIO) 3 = EC0E .def ?@_kernel_lastpt = * Source: source/main.xasm 250 251 EC0E icl 'disk.s' Source: source/Shared/disk.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Disk Routines 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 EC0E .proc DiskInit 11 .if _KERNEL_XLXE 12 ;set disk sector size to 128 bytes 13 EC0E A9 80 8D D5 02 A9 + mwa #$80 dsctln 14 .endif 15 EC18 60 rts 16 .endp 17 18 ;========================================================================== 19 ; Disk handler routine (pointed to by DSKINV) 20 ; 21 ; Exit: 22 ; A = command byte (undocumented; required by Pooyan) 23 ; Y = status 24 ; N = 1 if error, 0 if success (high bit of Y) 25 ; C = 1 if command is >=$21 (undocumented; required by Arcade Machine) 26 ; 27 EC19 .proc DiskHandler 28 EC19 A9 31 8D 00 03 mva #$31 ddevic 29 EC1E A9 0F 8D 06 03 mva #$0f dtimlo 30 31 ;check for status command 32 EC23 AD 02 03 lda dcomnd 33 EC26 8D 3B 02 sta ccomnd 34 EC29 C9 53 cmp #$53 35 EC2B D0 20 bne notStatus 36 37 EC2D A9 EA lda #dvstat 40 EC34 8D 05 03 sta dbufhi 41 EC37 0A asl ;hack to save a byte to get $04 since >dvstat is $02 42 EC38 8D 08 03 sta dbytlo 43 EC3B A9 00 lda #0 44 EC3D 8D 09 03 sta dbythi 45 46 EC40 20 6B EC jsr do_read 47 EC43 30 07 bmi xit 48 49 ;update format timeout 50 EC45 AE EC 02 8E 46 02 mvx dvstat+2 dsktim 51 EC4B AA tax 52 EC4C xit: 53 EC4C 60 rts 54 55 EC4D notStatus: 56 57 ;set disk sector length 58 .if _KERNEL_XLXE 59 EC4D AC D5 02 8C 08 03 + mwy dsctln dbytlo 60 .else 61 mwy #$80 dbytlo 62 .endif 63 64 ;check for put/write 65 .if _KERNEL_XLXE 66 EC59 C9 50 cmp #$50 67 EC5B F0 1D beq do_write 68 .endif 69 EC5D C9 57 cmp #$57 70 EC5F F0 19 beq do_write 71 72 ;check for format, or else assume it's a read command ($52) or similar 73 EC61 C9 21 cmp #$21 74 EC63 D0 06 bne do_read 75 76 ;it's format... use the format timeout 77 EC65 AD 46 02 8D 06 03 mva dsktim dtimlo 78 79 EC6B do_read: 80 EC6B A9 40 lda #$40 81 EC6D do_io: 82 EC6D 8D 03 03 sta dstats 83 EC70 20 59 E4 jsr siov 84 85 ;load disk command back into A (required by Pooyan) 86 ;emulate compare against format command (required by Arcade Machine) 87 ;sort-of emulate compare against status (required by Micropainter) 88 EC73 AD 02 03 lda dcomnd 89 EC76 C0 00 cpy #0 ;!! Atari800WinPlus's SIO patch doesn't set STATUS 90 EC78 38 sec 91 EC79 60 rts 92 93 EC7A do_write: 94 EC7A A9 80 lda #$80 95 EC7C D0 EF bne do_io 96 .endp 252 EC7E _KERNEL_REPORT_MODULE_SIZE 'Disk Handler', $EE78-$EDEA Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $EE78-$EDEA, ')', ' ', 'Disk Handler' 1 $EC7E -> $0070($008E) Disk Handler 3 = EC7E .def ?@_kernel_lastpt = * Source: source/main.xasm 253 254 EC7E icl 'printer.s' Source: source/Shared/printer.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Printer Handler 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 EC7E .proc PrinterInit 12 ;set printer timeout to default 13 EC7E A9 1E 8D 14 03 mva #30 ptimot 14 EC83 60 rts 15 .endp 16 17 ;========================================================================== 18 EC84 .proc PrinterOpen 19 ;check for sideways mode and compute line size 20 EC84 A2 28 ldx #40 21 EC86 A5 2B lda icax2z 22 EC88 C9 53 cmp #$53 23 EC8A D0 02 A2 1D sne:ldx #29 24 EC8E 8E DF 02 stx pbufsz 25 26 EC91 A9 00 lda #0 27 EC93 8D DE 02 sta pbpnt 28 29 EC96 xit: 30 EC96 A0 01 ldy #1 31 EC98 60 rts 32 .endp 33 34 ;========================================================================== 35 = EC99 PrinterClose = _PrinterPutByte.close_entry 36 = ECA0 PrinterPutByte = _PrinterPutByte.put_entry 37 38 EC99 .proc _PrinterPutByte 39 EC99 close_entry: 40 ;check if we have anything in the buffer 41 EC99 AD DE 02 lda pbpnt 42 43 ;exit if buffer is empty 44 EC9C F0 F8 beq PrinterOpen.xit 45 46 ;fall through to put with EOL 47 EC9E A9 9B lda #$9b 48 49 ECA0 put_entry: 50 ;preload buffer index (useful later) 51 ECA0 AE DE 02 ldx pbpnt 52 53 ;check for EOL 54 ECA3 C9 9B cmp #$9b 55 ECA5 F0 0E beq do_eol 56 57 ;mask off MSB 58 ECA7 29 7F and #$7f 59 60 ;put char and advance 61 ECA9 9D C0 03 sta prnbuf,x 62 ECAC E8 inx 63 ECAD 8E DE 02 stx pbpnt 64 65 ;check for end of line and exit if not 66 ECB0 EC DF 02 cpx pbufsz 67 ECB3 90 E1 bcc PrinterOpen.xit 68 69 ;fall through to EOL 70 71 ECB5 do_eol: 72 ;fill remainder of buffer with spaces 73 ECB5 A9 20 lda #$20 74 ECB7 fill_loop: 75 ECB7 EC DF 02 cpx pbufsz 76 ECBA B0 06 bcs fill_done 77 ECBC 9D C0 03 sta prnbuf,x 78 ECBF E8 inx 79 ECC0 90 F5 bcc fill_loop 80 ECC2 fill_done: 81 82 ;send line to printer 83 ECC2 A0 0A ldy #10 84 ECC4 B9 E3 EC 99 FF 02 + mva:rne iocbdat-1,y ddevic-1,y- 85 86 ;empty buffer 87 ECCD 8C DE 02 sty pbpnt 88 89 ;set line length 90 ECD0 8E 08 03 stx dbytlo 91 92 ;Compute AUX1 byte from length. 93 ; 94 ;Note that the OS manual is wrong -- this byte needs to go into AUX1 and 95 ;not AUX2 as the manual says. 96 ; 97 ; normal (40): 00101000 -> 01001110 ($4E 'N') 98 ; sideways (29): 00011101 -> 01010011 ($53 'S') 99 ; 010_1I1_ 100 ECD3 8A txa 101 ECD4 29 15 and #%00010101 102 ECD6 49 4E eor #%01001110 103 ECD8 8D 0A 03 sta daux1 ;set AUX1 to indicate width to device 104 105 ;send to printer and exit 106 ECDB do_io: 107 ECDB AD 14 03 8D 06 03 mva ptimot dtimlo 108 ECE1 4C 59 E4 jmp siov 109 110 ECE4 iocbdat: 111 ECE4 40 dta $40 ;device 112 ECE5 01 dta $01 ;unit 113 ECE6 57 dta $57 ;command 'W' 114 ECE7 80 dta $80 ;input/output mode (write) 115 ECE8 C0 03 dta a(prnbuf) ;buffer address 116 ECEA 00 00 dta a(0) ;timeout 117 ECEC 00 00 dta a(0) ;buffer length 118 .endp 119 120 ;============================================================================== 121 ECEE .proc PrinterGetStatus 122 ;setup parameter block 123 ECEE A2 09 ldx #9 124 ECF0 BD 05 ED 9D 00 03 + mva:rpl iocbdat,x ddevic,x- 125 126 ;issue status call 127 ECF9 20 DB EC jsr _PrinterPutByte.do_io 128 ECFC 30 06 bmi error 129 130 ;update timeout 131 ECFE AD EC 02 8D 14 03 mva dvstat+2 ptimot 132 133 ED04 error: 134 ED04 60 rts 135 136 ED05 iocbdat: 137 ED05 40 dta $40 ;device 138 ED06 01 dta $01 ;unit 139 ED07 53 dta $53 ;command 'S' 140 ED08 40 dta $40 ;input/output mode (read) 141 ED09 EA 02 dta a(dvstat) ;buffer address 142 ED0B 00 00 dta a(0) ;timeout 143 ED0D 04 00 dta a(4) ;buffer length 144 .endp 145 146 ;============================================================================== 147 = E4CB PrinterGetByte = CIOExitNotSupported 148 = E4CB PrinterSpecial = CIOExitNotSupported 255 ED0F _KERNEL_REPORT_MODULE_SIZE 'Printer Handler', $EF41-$EE78 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $EF41-$EE78, ')', ' ', 'Printer Handler' 1 $ED0F -> $0091($00C9) Printer Handler 3 = ED0F .def ?@_kernel_lastpt = * Source: source/main.xasm 256 257 ED0F icl 'cassette.s' Source: source/Shared/cassette.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Cassette tape support 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 ED0F .proc CassetteInit 12 ;Set CBAUDL/CBAUDH to $05CC, the nominal POKEY divisor for 600 13 ;baud. We don't care about this, but it's documented in the OS 14 ;Manual. 15 ED0F A9 CC 8D EE 02 A9 + mwa #$05CC cbaudl 16 ED19 60 rts 17 .endp 18 19 ;========================================================================== 20 ; Cassette open routine. 21 ; 22 ; XL/XE OS behavior notes: 23 ; - Attempting to open for none (AUX1=$00) or read/write (AUX1=$0C) 24 ; results in a Not Supported error (146). 25 ; - Open for read gives one beep, while open for write gives two beeps. 26 ; - Break will break out of the wait. 27 ; - Ctrl+3 during the keypress causes an EOF error (!). This is a side 28 ; effect of reusing the keyboard handler. 29 ; 30 ; CSOPIV behavior: 31 ; - Does NOT set FTYPE (continuous mode flag). 32 ; - Sets read mode (WMODE). 33 ; - Does NOT require ICAX1Z or ICAX2Z to be set. 34 ; 35 = ED2D CassetteOpenRead = CassetteOpen.do_open_read 36 ED1A .proc CassetteOpen 37 ;stash continuous mode flag 38 ED1A A5 2B lda icax2z ;!! FIRST TWO BYTES CHECKED BY ARCHON 39 ED1C 85 3E sta ftype 40 41 ;check mode byte for read/write modes 42 ED1E A2 80 ldx #$80 43 ED20 A5 2A lda icax1z 44 ED22 29 0C and #$0c 45 ED24 C9 04 cmp #$04 ;read? 46 ED26 F0 05 beq found_read_mode 47 ED28 C9 08 cmp #$08 ;write? 48 ED2A F0 03 beq found_write_mode 49 50 ;invalid mode -- return not supported 51 ED2C 60 rts 52 53 ED2D do_open_read: 54 ED2D found_read_mode: 55 ED2D A2 00 ldx #$00 56 ED2F found_write_mode: 57 ED2F 8E 89 02 stx wmode 58 59 ;set cassette buffer size to 128 bytes and mark it empty 60 ED32 A9 80 lda #$80 61 ED34 85 3D sta bptr 62 ED36 8D 8A 02 sta blim 63 64 ;clear EOF flag 65 ED39 0A asl 66 ED3A 85 3F sta feof 67 68 ;request one beep for read, or two for write 69 ED3C 2C 89 02 bit wmode 70 ED3F 10 05 bpl one_ping_only 71 72 ED41 06 3D asl bptr ;!! - set bptr=0 when starting write 73 74 ED43 20 87 EE jsr CassetteBell 75 76 ED46 one_ping_only: 77 ED46 20 87 EE jsr CassetteBell 78 79 ;wait for a key press 80 ED49 20 69 FE jsr KeyboardGetByte 81 ED4C 30 20 bmi aborted 82 83 ;need to set up POKEY for writes now to write leader 84 ED4E 2C 89 02 bit wmode 85 ED51 10 08 bpl no_write_init 86 ED53 A9 FF lda #$ff 87 ED55 8D 0F 03 sta casflg 88 ED58 20 52 E9 jsr SIOSendEnable.no_irq_setup 89 ED5B no_write_init: 90 91 ;turn on motor (continuous mode or not) 92 ED5B A9 34 lda #$34 93 ED5D 8D 02 D3 sta pactl 94 95 ;wait for leader (9.6 seconds read, 19.2s write) 96 ED60 A2 00 ldx #0 97 ED62 2C 89 02 bit wmode 98 ED65 30 02 A2 01 smi:ldx #1 99 ED69 20 61 EE jsr CassetteWait 100 101 ;all done 102 ED6C A0 01 ldy #1 103 ED6E aborted: 104 ED6E 60 rts 105 .endp 106 107 ;========================================================================== 108 ED6F .proc CassetteClose 109 ;check if we are in write mode 110 ED6F AD 89 02 lda wmode ;!! FIRST TWO BYTES CHECKED BY ARCHON 111 ED72 10 0A bpl notwrite 112 113 ;check if we have data to write 114 ED74 A5 3D lda bptr 115 ED76 F0 03 beq nopartial 116 117 ;flush partial record ($FA) 118 ED78 20 E0 ED jsr CassetteFlush 119 120 ED7B nopartial: 121 ;write EOF record ($FE) 122 ED7B 20 E0 ED jsr CassetteFlush 123 124 ED7E notwrite: 125 ;stop the motor 126 ED7E A9 3C lda #$3c 127 ED80 8D 02 D3 sta pactl 128 129 ;kill audio 130 ED83 A0 00 ldy #0 131 ED85 8C 01 D2 sty audc1 132 ED88 8C 03 D2 sty audc2 133 ED8B 8C 07 D2 sty audc4 134 135 ;all done 136 ED8E C8 iny 137 ED8F 60 rts 138 .endp 139 140 ;========================================================================== 141 ED90 .proc CassetteGetByte 142 ;check if we have an EOF condition 143 ED90 A5 3F lda feof ;!! FIRST TWO BYTES CHECKED BY ARCHON 144 ED92 D0 1D bne xit_eof 145 146 ED94 fetchbyte: 147 ;check if we can still fetch a byte 148 ED94 A6 3D ldx bptr 149 ED96 EC 8A 02 cpx blim 150 ED99 F0 08 beq nobytes 151 152 ED9B BD 00 04 lda casbuf+3,x 153 ED9E E6 3D inc bptr 154 EDA0 A0 01 ldy #1 155 EDA2 60 rts 156 157 EDA3 nobytes: 158 ;fetch more bytes 159 EDA3 20 10 EE jsr CassetteReadBlock 160 EDA6 30 0B bmi error 161 162 ;check control byte 163 EDA8 AD FF 03 lda casbuf+2 164 EDAB C9 FE cmp #$fe 165 EDAD D0 05 bne noteofbyte 166 167 ;found $FE (EOF) - set flag and return EOF 168 EDAF 85 3F sta feof 169 EDB1 xit_eof: 170 EDB1 A0 88 ldy #CIOStatEndOfFile 171 EDB3 error: 172 EDB3 60 rts 173 174 EDB4 noteofbyte: 175 ;reset buffer ptr 176 EDB4 A2 00 86 3D mvx #0 bptr 177 178 ;assume full block first (128 bytes) 179 EDB8 A2 80 ldx #$80 180 181 ;check if it actually is one 182 EDBA C9 FC cmp #$fc 183 EDBC D0 06 bne not_full_block 184 185 EDBE init_new_block: 186 ;reset block length and loop back 187 EDBE 8E 8A 02 stx blim 188 EDC1 4C 94 ED jmp fetchbyte 189 190 EDC4 not_full_block: 191 ;check if we have a partial block 192 EDC4 C9 FA cmp #$fa 193 EDC6 D0 05 bne not_partial_block 194 195 ;set length of partial block and the jump to init+loop 196 EDC8 AE 7F 04 ldx casbuf+130 197 EDCB B0 F1 bcs init_new_block 198 199 EDCD not_partial_block: 200 ;uh oh... bad control byte. 201 EDCD A0 A3 ldy #CIOStatFatalDiskIO 202 EDCF 60 rts 203 .endp 204 205 ;========================================================================== 206 EDD0 .proc CassettePutByte 207 ;put a byte into the buffer 208 EDD0 A6 3D ldx bptr ;!! FIRST TWO BYTES CHECKED BY ARCHON 209 EDD2 9D 00 04 sta casbuf+3,x 210 211 ;bump and check if it's time to write 212 EDD5 E8 inx 213 EDD6 86 3D stx bptr 214 EDD8 EC 8A 02 cpx blim 215 EDDB B0 03 bcs CassetteFlush 216 217 ;all done 218 EDDD A0 01 ldy #1 219 EDDF 60 rts 220 .endp 221 222 ;========================================================================== 223 EDE0 .proc CassetteFlush 224 EDE0 A9 00 lda #0 225 226 ;set control byte based on buffer level 227 EDE2 A2 FE ldx #$fe ;empty -> EOF 228 EDE4 A4 3D ldy bptr ;get buffer level 229 EDE6 D0 08 bne not_empty ;skip not empty 230 231 ;clear buffer for EOF 232 EDE8 99 00 04 C8 10 FA sta:rpl casbuf+3,y+ 233 EDEE 30 0C bmi is_empty ;!! - unconditional 234 235 EDF0 not_empty: 236 EDF0 A2 FC ldx #$fc ;load complete code 237 EDF2 CC 8A 02 cpy blim ;check if buffer is full 238 EDF5 B0 05 bcs is_complete ;skip if so 239 EDF7 A2 FA ldx #$fa ;load partial code 240 EDF9 8C 7F 04 sty casbuf+130 ;store level in last byte 241 EDFC is_complete: 242 EDFC is_empty: 243 244 ;store code 245 EDFC 8E FF 03 stx casbuf+2 246 247 ;reset buffer level 248 EDFF 85 3D sta bptr 249 250 ;setup sync bytes 251 EE01 A9 55 lda #$55 252 EE03 8D FD 03 sta casbuf 253 EE06 8D FE 03 sta casbuf+1 254 255 ;issue write request and exit 256 EE09 A2 80 ldx #$80 257 EE0B A0 50 ldy #'P' 258 EE0D 4C 14 EE jmp CassetteDoIO 259 .endp 260 261 ;========================================================================== 262 = E4C9 CassetteGetStatus = CIOExitSuccess 263 = E4CB CassetteSpecial = CIOExitNotSupported 264 265 ;========================================================================== 266 ; CassetteDoIO 267 ; 268 ; X = DSTATS value 269 ; Y = SIO command byte 270 ; 271 ; Note that SOUNDR must take effect each time a cassette I/O operation 272 ; occurs. 273 ; 274 = EE14 CassetteDoIO = _CassetteDoIO.do_io 275 = EE10 CassetteReadBlock = _CassetteDoIO.read_block 276 277 EE10 .proc _CassetteDoIO 278 EE10 read_block: 279 EE10 A2 40 ldx #$40 280 EE12 A0 52 ldy #'R' 281 EE14 do_io: 282 ;start the motor if not already running 283 EE14 A9 34 lda #$34 284 EE16 8D 02 D3 sta pactl 285 286 ;set up SIO read/write 287 EE19 8E 03 03 stx dstats 288 EE1C 8C 02 03 sty dcomnd 289 EE1F A9 FD 8D 04 03 A9 + mwa #casbuf dbuflo 290 EE29 A9 83 8D 08 03 A9 + mwa #131 dbytlo 291 EE33 A9 60 8D 00 03 mva #$60 ddevic 292 EE38 A9 00 8D 01 03 mva #0 dunit 293 EE3D A5 3E 8D 0B 03 mva ftype daux2 294 295 ;do it 296 EE42 20 59 E4 jsr siov 297 298 ;check if we are in continuous mode (again) 299 EE45 A5 3E lda ftype 300 EE47 30 0F bmi rolling_stop 301 302 ;not in continuous mode -- wait for post-write tone if writing 303 EE49 2C 89 02 bit wmode 304 EE4C 10 05 bpl no_pwt 305 EE4E A2 06 ldx #6 306 EE50 20 61 EE jsr CassetteWait 307 EE53 no_pwt: 308 309 ;stop the motor 310 EE53 A9 3C lda #$3c 311 EE55 8D 02 D3 sta pactl 312 313 EE58 rolling_stop: 314 EE58 A4 30 ldy status 315 EE5A 60 rts 316 .endp 317 318 ;========================================================================== 319 ;Entry: 320 ; X = delay type 321 ; 322 = EE61 CassetteWait = CassetteWaitLongShortCheck.normal_entry 323 EE5B .proc CassetteWaitLongShortCheck 324 EE5B 2C 0B 03 bit daux2 325 EE5E 10 01 E8 spl:inx 326 EE61 normal_entry: 327 EE61 20 13 E9 jsr SIOSetTimeoutVector 328 EE64 BC 79 EE ldy wait_table_lo,x 329 EE67 BD 80 EE lda wait_table_hi,x 330 EE6A AA tax 331 EE6B A9 01 lda #1 332 EE6D 8D 17 03 sta timflg 333 EE70 20 5F C1 jsr VBISetVector 334 EE73 AD 17 03 D0 FB lda:rne timflg 335 EE78 60 rts 336 337 EE79 wait_table_lo: 338 EE79 80 dta <$0480 ;$00 - write file leader (19.2 seconds NTSC) 339 EE7A 40 dta <$0240 ;$01 - read leader delay (9.6 seconds NTSC) 340 EE7B B4 dta <$00B4 ;$02 - long pre-record write tone (3.0s NTSC) 341 EE7C 0F dta <$000F ;$03 - short pre-record write tone (0.25s NTSC) 342 EE7D 78 dta <$0078 ;$04 - long read IRG (2.0s NTSC) 343 EE7E 0A dta <$000A ;$05 - short read IRG (0.16s NTSC) 344 EE7F 3C dta <$003C ;$06 - post record gap (1s NTSC) 345 346 EE80 wait_table_hi: 347 EE80 04 dta >$0480 ;$00 - write file leader (19.2 seconds NTSC) 348 EE81 02 dta >$0240 ;$01 - read leader delay (9.6 seconds NTSC) 349 EE82 00 dta >$00B4 ;$02 - long pre-record write tone (3.0s NTSC) 350 EE83 00 dta >$000F ;$03 - short pre-record write tone (0.25s NTSC) 351 EE84 00 dta >$0078 ;$04 - long read IRG (2.0s NTSC) 352 EE85 00 dta >$000A ;$05 - short read IRG (0.16s NTSC) 353 EE86 00 dta >$003C ;$06 - post record gap (1s NTSC) 354 .endp 355 356 ;========================================================================== 357 ; Sound a bell using the console speaker (cassette version) 358 ; 359 ; Modified: 360 ; A, X, Y 361 ; 362 EE87 .proc CassetteBell 363 EE87 A0 00 ldy #0 364 EE89 98 tya 365 EE8A soundloop: 366 EE8A A2 0A ldx #10 367 EE8C 48 pha 368 EE8D delay: 369 EE8D AD 0B D4 lda vcount 370 EE90 CD 0B D4 F0 FB cmp:req vcount 371 EE95 CA dex 372 EE96 D0 F5 bne delay 373 EE98 68 pla 374 EE99 49 08 eor #$08 375 EE9B 8D 1F D0 sta consol 376 EE9E D0 EA bne soundloop 377 EEA0 88 dey 378 EEA1 D0 E7 bne soundloop 379 EEA3 60 rts 380 .endp 258 EEA4 _KERNEL_REPORT_MODULE_SIZE 'Cassette Handler', $F0E3-$EF41 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $F0E3-$EF41, ')', ' ', 'Cassette Handler' 1 $EEA4 -> $0195($01A2) Cassette Handler 3 = EEA4 .def ?@_kernel_lastpt = * Source: source/main.xasm 259 260 .ifdef _KERNEL_816 261 icl 'init816.s' 262 .else 263 EEA4 icl 'init.s' Source: source/Shared/init.s 1 ; Altirra - Atari 800/800XL emulator 2 ; Kernel ROM replacement - Initialization 3 ; Copyright (C) 2008-2019 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 .if _KERNEL_XLXE 11 EEA4 .proc InitBootSignature 12 EEA4 5C 93 25 dta $5C,$93,$25 13 .endp 14 .endif 15 16 EEA7 .proc InitHandlerTable 17 EEA7 50 30 E4 dta c'P',a(printv) 18 EEAA 43 40 E4 dta c'C',a(casetv) 19 EEAD 45 00 E4 dta c'E',a(editrv) 20 EEB0 53 10 E4 dta c'S',a(screnv) 21 EEB3 4B 20 E4 dta c'K',a(keybdv) 22 .endp 23 24 EEB6 .nowarn .proc _InitReset 25 EEB6 run_diag: 26 ; start diagnostic cartridge 27 EEB6 6C FE BF jmp ($bffe) 28 29 = EEB9 .def :InitReset 30 ;mask interrupts and initialize CPU 31 EEB9 78 sei 32 EEBA D8 cld 33 EEBB A2 FF ldx #$ff 34 EEBD 9A txs 35 36 .if _KERNEL_XLXE 37 ;wait for everything to stabilize (0.1s) (XL/XE only) 38 EEBE A0 8C ldy #140 39 EEC0 stabilize_loop: 40 EEC0 CA D0 FD dex:rne 41 EEC3 88 dey 42 EEC4 D0 FA bne stabilize_loop 43 44 ;check for warmstart signature (XL/XE) 45 EEC6 A2 02 ldx #2 46 EEC8 warm_check: 47 EEC8 BD 3D 03 lda pupbt1,x 48 EECB DD A4 EE cmp InitBootSignature,x 49 EECE D0 06 bne cold_boot 50 EED0 CA dex 51 EED1 10 F5 bpl warm_check 52 53 EED3 4C 4F EF jmp InitWarmStart 54 .endif 55 56 = EED6 .def :InitColdStart 57 EED6 cold_boot: 58 ; 1. initialize CPU 59 EED6 78 sei 60 EED7 D8 cld 61 EED8 A2 FF ldx #$ff 62 EEDA 9A txs 63 64 ; 2. clear warmstart flag 65 EEDB E8 inx 66 EEDC 86 08 stx warmst 67 68 ; 3. test for diagnostic cartridge 69 EEDE AD FC BF lda $bffc 70 EEE1 D0 17 bne not_diag 71 EEE3 A2 FF ldx #$ff 72 EEE5 EC FF BF cpx $bfff ;prevent diagnostic cart from activating if addr is $FFxx 73 EEE8 F0 10 beq not_diag 74 EEEA 8E FC BF stx $bffc 75 EEED CD FC BF cmp $bffc 76 EEF0 8D FC BF sta $bffc 77 EEF3 D0 05 bne not_diag 78 79 ; is it enabled? 80 EEF5 2C FD BF bit $bffd 81 EEF8 30 BC bmi run_diag 82 83 EEFA not_diag: 84 85 EEFA 20 80 EF jsr InitHardwareReset 86 87 .if _KERNEL_XLXE 88 ;check for OPTION and enable BASIC (note that we do NOT set BASICF just yet) 89 EEFD A9 04 lda #4 90 EEFF 2C 1F D0 bit consol 91 EF02 F0 12 beq no_basic 92 93 .ifdef _KERNEL_SOFTKICK 94 ldx #$fc 95 .else 96 EF04 A2 FD ldx #$fd 97 .endif 98 99 ;check for keyboard present + SELECT or no keyboard + no SELECT and enable game if so 100 EF06 AD 12 D0 lda trig2 ;check keyboard present (1 = present) 101 EF09 0A asl 102 EF0A 4D 1F D0 eor consol ;XOR against select (0 = pressed) 103 EF0D 29 02 and #$02 104 105 .ifdef _KERNEL_SOFTKICK 106 seq:ldx #$be 107 .else 108 EF0F F0 02 A2 BF seq:ldx #$bf 109 .endif 110 111 EF13 8E 01 D3 stx portb ;enable GAME or BASIC 112 113 EF16 no_basic: 114 .endif 115 116 ; 4. measure memory -> tramsz 117 EF16 20 B0 EF jsr InitMemory 118 119 ; 6. clear memory from $0008 up to [tramsz,0] 120 .ifdef _KERNEL_SOFTKICK 121 ldx #$50 122 .else 123 EF19 A6 06 ldx tramsz 124 .endif 125 EF1B A0 08 ldy #8 126 EF1D A9 00 85 66 mva #0 a1 127 EF21 85 67 sta a1+1 128 EF23 clearloop: 129 EF23 91 66 C8 D0 FB sta:rne (a1),y+ 130 EF28 E6 67 inc a1+1 131 EF2A CA dex 132 EF2B D0 F6 bne clearloop 133 134 .if _KERNEL_XLXE 135 ;Blip the self test ROM for a second -- this is one way that Altirra detects 136 ;that Option has been used by the OS. The XL/XE OS does this as part of its 137 ;ROM checksum routine (which we don't bother with). 138 EF2D AE 01 D3 ldx portb 139 EF30 8A txa 140 EF31 29 7F and #$7f 141 EF33 8D 01 D3 sta portb 142 EF36 8E 01 D3 stx portb 143 .endif 144 145 ; 7. set dosvec to blackboard routine 146 .if _KERNEL_USE_BOOT_SCREEN 147 EF39 A9 9B 85 0A A9 E4 + mwa #SelfTestEntry dosvec 148 .else 149 mwa #Blackboard dosvec 150 .endif 151 152 ; 8. set coldstart flag 153 EF41 CE 44 02 dec coldst ;!! coldst=0 from clear loop above, now $ff 154 155 .if _KERNEL_XLXE 156 ; set BASIC flag 157 EF44 AD 01 D3 lda portb 158 EF47 29 02 and #$02 159 EF49 8D F8 03 sta basicf 160 .endif 161 162 ; 9. set screen margins 163 ; 10. initialize RAM vectors 164 ; 11. set misc database values 165 ; 12. enable IRQ interrupts 166 ; 13. initialize device table 167 ; 14. initialize cartridges 168 ; 15. use IOCB #0 to open screen editor (E) 169 ; 16. wait for VBLANK so screen is initialized 170 ; 17. do cassette boot, if it was requested 171 ; 18. do disk boot 172 ; 19. reset coldstart flag 173 ; 20. run cartridges or blackboard 174 EF4C 4C EE EF jmp InitEnvironment 175 .endp 176 177 ;============================================================================== 178 EF4F .proc InitWarmStart 179 ; A. initialize CPU 180 ; 181 ; Undocumented: Check if cold start completed (COLDST=0); if not, force 182 ; a cold start. ACTris 2.1 relies on this since its boot doesn't reset 183 ; COLDST. This is also required to work on Atari800WinPLus, which doesn't 184 ; clear memory on a cold start. 185 ; 186 EF4F 78 sei ;!! FIRST TWO BYTES CHECKED BY ARCHON 187 EF50 AD 44 02 lda coldst 188 EF53 D0 81 bne InitColdStart 189 EF55 D8 cld 190 EF56 A2 FF ldx #$ff 191 EF58 9A txs 192 193 ; B. set warmstart flag 194 EF59 86 08 stx warmst 195 196 ; reinitialize hardware without doing a full clear 197 EF5B 20 80 EF jsr InitHardwareReset 198 199 .if _KERNEL_XLXE 200 ; reinitialize BASIC 201 EF5E AD F8 03 lda basicf 202 EF61 D0 05 A9 FD 8D 01 + sne:mva #$fd portb 203 .endif 204 205 ; C. check for diag, measure memory, clear hw registers 206 EF68 20 B0 EF jsr InitMemory 207 208 ; D. zero 0010-007F and 0200-03EC (must not clear BASICF). 209 EF6B A2 60 ldx #$60 210 EF6D A9 00 lda #0 211 EF6F 95 0F CA D0 FB sta:rne $0f,x- 212 213 EF74 dbclear: 214 EF74 9D 00 02 sta $0200,x 215 EF77 9D ED 02 sta $02ed,x 216 EF7A E8 inx 217 EF7B D0 F7 bne dbclear 218 219 ; E. steps 9-16 above 220 ; F. if cassette boot was successful on cold boot, execute cassette init 221 ; G. if disk boot was successful on cold boot, execute disk init 222 ; H. same as steps 19 and 20 223 EF7D 4C EE EF jmp InitEnvironment 224 .endp 225 226 ;============================================================================== 227 EF80 .proc InitHardwareReset 228 ; clear all hardware registers 229 EF80 A0 00 ldy #0 230 EF82 98 tya 231 EF83 hwclear: 232 EF83 99 00 D0 sta $d000,y 233 EF86 99 00 D2 sta $d200,y 234 EF89 99 00 D4 sta $d400,y 235 EF8C C8 iny 236 EF8D D0 F4 bne hwclear 237 238 ;initialize PIA 239 EF8F A9 3C lda #$3c 240 EF91 A2 38 ldx #$38 241 242 .ifdef _KERNEL_SOFTKICK 243 stx pactl ;switch to DDRA 244 sty porta ;portA -> input 245 sta pactl ;switch to IORA 246 sty porta ;portA -> $00 247 sta pbctl ;switch to IORB 248 dey 249 dey 250 sty portb ;portB -> $FE 251 stx pbctl ;switch to DDRB 252 iny 253 sty portb ;portB -> all output 254 sta pbctl ;switch to IORB 255 .elseif _KERNEL_XLXE 256 EF93 8E 02 D3 stx pactl ;switch to DDRA 257 EF96 8C 00 D3 sty porta ;portA -> input 258 EF99 8D 02 D3 sta pactl ;switch to IORA 259 EF9C 8C 00 D3 sty porta ;portA -> $00 260 EF9F 8D 03 D3 sta pbctl ;switch to IORB 261 EFA2 88 dey 262 EFA3 8C 01 D3 sty portb ;portB -> $FF 263 EFA6 8E 03 D3 stx pbctl ;switch to DDRB 264 EFA9 8C 01 D3 sty portb ;portB -> all output 265 EFAC 8D 03 D3 sta pbctl ;switch to IORB 266 .else 267 stx pactl ;switch to DDRA 268 stx pbctl ;switch to DDRB 269 sty porta ;portA -> input 270 sty portb ;portB -> input 271 sta pactl ;switch to IORA 272 sta pbctl ;switch to IORB 273 sty porta ;portA -> $00 274 sty portb ;portB -> $00 275 .endif 276 EFAF 60 rts 277 .endp 278 279 ;============================================================================== 280 EFB0 .proc InitMemory 281 ; 4. measure memory -> tramsz 282 EFB0 A0 00 ldy #$00 283 EFB2 84 64 sty adress 284 EFB4 A2 02 ldx #$02 285 EFB6 pageloop: 286 EFB6 86 65 stx adress+1 287 EFB8 B1 64 lda (adress),y 288 EFBA 49 FF eor #$ff 289 EFBC 91 64 sta (adress),y 290 EFBE D1 64 cmp (adress),y 291 EFC0 D0 09 bne notRAM 292 EFC2 49 FF eor #$ff 293 EFC4 91 64 sta (adress),y 294 EFC6 E8 inx 295 296 .if _KERNEL_XLXE 297 EFC7 E0 C0 cpx #$c0 298 .else 299 cpx #$d0 300 .endif 301 302 EFC9 D0 EB bne pageloop 303 EFCB notRAM: 304 EFCB 86 06 stx tramsz 305 306 EFCD 60 rts 307 .endp 308 309 ;============================================================================== 310 EFCE .proc InitVectorTable1 311 EFCE 55 C0 dta a(IntExitHandler_None) ;$0200 VDSLST 312 EFD0 54 C0 dta a(IntExitHandler_A) ;$0202 VPRCED 313 EFD2 54 C0 dta a(IntExitHandler_A) ;$0204 VINTER 314 EFD4 54 C0 dta a(IntExitHandler_A) ;$0206 VBREAK 315 EFD6 CE FE dta a(KeyboardIRQ) ;$0208 VKEYBD 316 EFD8 43 EA dta a(SIOInputReadyHandler) ;$020A VSERIN 317 EFDA 8C EA dta a(SIOOutputReadyHandler) ;$020C VSEROR 318 EFDC C5 EA dta a(SIOOutputCompleteHandler) ;$020E VSEROC 319 EFDE 54 C0 dta a(IntExitHandler_A) ;$0210 VTIMR1 320 EFE0 54 C0 dta a(IntExitHandler_A) ;$0212 VTIMR2 321 EFE2 54 C0 dta a(IntExitHandler_A) ;$0214 VTIMR4 322 EFE4 D1 C1 dta a(IrqHandler) ;$0216 VIMIRQ 323 EFE6 end: 324 .endp 325 326 EFE6 .proc InitVectorTable2 327 EFE6 0C C0 dta a(VBIStage1) ;$0222 VVBLKI 328 EFE8 50 C0 dta a(VBIExit) ;$0224 VVBLKD 329 EFEA 00 00 dta a(0) ;$0226 CDTMA1 330 .endp 331 332 EFEC krpdel_table: 333 EFEC 30 28 dta 48,40 334 335 ;============================================================================== 336 EFEE .proc InitEnvironment 337 EFEE A5 06 8D E4 02 mva tramsz ramsiz 338 339 .if _KERNEL_XLXE 340 ; set warmstart signature -- must be done before cart init, because 341 ; SDX doesn't return. 342 EFF3 A2 03 ldx #3 343 EFF5 BD A3 EE 9D 3C 03 + mva:rne InitBootSignature-1,x pupbt1-1,x- 344 .endif 345 346 ; 9. set screen margins 347 EFFE A9 02 85 52 mva #2 lmargn 348 F002 A9 27 85 53 mva #39 rmargn 349 350 ;set PAL/NTSC flag (XL/XE only) 351 .if _KERNEL_XLXE 352 F006 A2 00 ldx #0 353 F008 AD 14 D0 lda pal 354 F00B A0 06 ldy #6 355 F00D 29 0E and #$0e 356 F00F D0 04 bne is_ntsc 357 F011 D0 01 E8 sne:inx 358 F014 88 dey 359 F015 is_ntsc: 360 F015 86 62 stx palnts 361 F017 8C DA 02 sty keyrep 362 F01A BD EC EF 8D D9 02 mva krpdel_table,x krpdel 363 .endif 364 365 ; 10. initialize RAM vectors 366 367 ;VDSLST-VIMIRQ 368 F020 A2 17 ldx #[.len InitVectorTable1]-1 369 F022 BD CE EF 9D 00 02 + mva:rpl InitVectorTable1,x vdslst,x- 370 371 ;VVBLKI-CDTMA1 372 F02B A2 05 ldx #[.len InitVectorTable2]-1 373 F02D BD E6 EF 9D 22 02 + mva:rpl InitVectorTable2,x vvblki,x- 374 375 F036 A9 11 8D 36 02 A9 + mwa #KeyboardBreakIRQ brkky 376 377 ; 11. set misc database values 378 F040 A2 FF ldx #$ff 379 F042 86 11 stx brkkey 380 F044 E8 inx 381 F045 8E E5 02 stx memtop 382 F048 8E E7 02 stx memlo 383 F04B A5 06 8D E6 02 mva tramsz memtop+1 384 F050 A2 07 8E E8 02 mvx #$07 memlo+1 385 386 F055 20 0E EC jsr DiskInit 387 F058 20 C4 F5 jsr ScreenInit 388 ;jsr DisplayInit 389 F05B 20 3F FE jsr KeyboardInit 390 391 .if _KERNEL_PRINTER_SUPPORT 392 F05E 20 7E EC jsr PrinterInit 393 .endif 394 395 ; 13. initialize device table (HATABS has already been cleared) 396 ; NOTE: The R: emulation relies on this being before CIOINV is invoked. 397 F061 A2 0E ldx #14 398 F063 BD A7 EE 9D 1A 03 + mva:rpl InitHandlerTable,x hatabs,x- 399 400 ;jsr CassetteInit 401 F06C 20 6E E4 jsr cioinv 402 F06F 20 EB E7 jsr SIOInit 403 F072 20 75 C1 jsr IntInitInterrupts 404 405 ; check for START key, and if so, set cassette boot flag 406 F075 AD 1F D0 lda consol 407 F078 29 01 and #1 408 F07A 49 01 eor #1 409 F07C 8D E9 03 sta ckey 410 411 .if _KERNEL_PBI_SUPPORT 412 F07F 20 4E C2 jsr PBIScan 413 .endif 414 415 ; 12. enable IRQ interrupts 416 ; 417 ; We do this later than the original OS specification because the PBI scan needs 418 ; to happen with IRQs disabled (a PBI device with interrupts may not have been 419 ; inited yet) and that PBI scan in turn needs to happen after HATABS has been 420 ; set up. There's no harm in initing HATABS with interrupts masked, so we do so. 421 422 F082 58 cli 423 424 ; 14. initialize cartridges 425 F083 A9 00 85 07 mva #0 tstdat 426 427 .if !_KERNEL_XLXE 428 lda $9ffc 429 bne skipCartBInit 430 lda $9ffb 431 tax 432 eor #$ff 433 sta $9ffb 434 cmp $9ffb 435 stx $9ffb 436 beq skipCartBInit 437 jsr InitCartB 438 mva #1 tstdat 439 skipCartBInit: 440 .endif 441 442 F087 A9 00 85 06 mva #0 tramsz 443 F08B AD FC BF lda $bffc 444 F08E D0 18 bne skipCartAInit 445 F090 AD FB BF lda $bffb 446 F093 AA tax 447 F094 49 FF eor #$ff 448 F096 8D FB BF sta $bffb 449 F099 CD FB BF cmp $bffb 450 F09C 8E FB BF stx $bffb 451 F09F F0 07 beq skipCartAInit 452 F0A1 20 2D F1 jsr InitCartA 453 F0A4 A9 01 85 06 mva #1 tramsz 454 F0A8 skipCartAInit: 455 456 ; 15. use IOCB #0 ($0340) to open screen editor (E) 457 ; 458 ; NOTE: We _must_ leave $0C in the A register when invoking CIO. Pooyan 459 ; relies on $0C being left in CIOCHR after the last call to CIO before 460 ; disk boot! 461 462 F0A8 A9 03 8D 42 03 mva #$03 iccmd ;OPEN 463 F0AD A9 33 8D 44 03 A9 + mwa #ScreenEditorName icbal 464 F0B7 A9 0C 8D 4A 03 mva #$0c icax1 ;read/write, no forced read 465 F0BC A2 00 ldx #0 466 F0BE 8E 4B 03 stx icax2 ;mode 0 467 F0C1 20 56 E4 jsr ciov 468 469 ; 16. wait for VBLANK so screen is initialized 470 F0C4 A5 14 lda rtclok+2 471 F0C6 waitvbl: 472 F0C6 C5 14 cmp rtclok+2 473 F0C8 F0 FC beq waitvbl 474 475 ;------------------------------------------------------------------------- 476 ; Pre-boot hook (AltirraOS-specific) 477 ; 478 479 .ifdef _KERNEL_PRE_BOOT_HOOK 480 jsr InitPreBootHook 481 .endif 482 483 ;------------------------------------------------------------------------- 484 ; Run cartridge/cassette/disk 485 ; 486 487 ; 17. do cassette boot, if it was requested 488 ; F. if cassette boot was successful on cold boot, execute cassette init 489 490 ; The cold boot path must check the warm start flag and switch paths if 491 ; necessary. SpartaDOS X relies on being able to set the warm start 492 ; flag from its cart init handler. 493 ; 494 ; Disk boot must be attempted after cassette boot. Besides support for 495 ; using DOS from tape-based software, this is also required by the tape 496 ; version of Fun With Spelling (featuring Heathcliff), which depends on 497 ; the SIO request causing the tape start vector to be invoked shortly 498 ; after VBI so it can do an unsafe screen swap. 499 ; 500 501 F0CA A5 08 lda warmst 502 F0CC D0 0B bne reinitcas 503 504 F0CE AD E9 03 lda ckey 505 F0D1 F0 0F beq postcasboot 506 F0D3 20 A4 F1 jsr BootCassette 507 F0D6 4C E2 F0 jmp postcasboot 508 509 F0D9 reinitcas: 510 F0D9 A9 02 lda #2 511 F0DB 24 09 bit boot? 512 F0DD F0 03 beq postcasboot 513 F0DF 20 37 F1 jsr InitCassetteBoot 514 F0E2 postcasboot: 515 516 ;------------------------------------------------------------------------- 517 ; 18. do disk boot 518 ; G. if disk boot was successful on cold boot, execute disk init 519 ; 520 ; For 800 mode, we must check if either cart A or cart B is present, 521 ; doing a disk boot if either there are no carts or one of the carts 522 ; requests disk boot. For the XL/XE case, cart B doesn't exist and we 523 ; can simplify the logic. 524 ; 525 526 F0E2 A5 08 lda warmst 527 F0E4 D0 10 bne reinitDisk 528 529 .if !_KERNEL_XLXE 530 531 ;check if we have cart B 532 lda tstdat 533 bne have_cart_b 534 535 ;no cart B -- if no cart A either, do disk boot 536 ldx tramsz ;cart A 537 beq boot_disk 538 bne have_cart_a 539 540 have_cart_b: 541 ;have cart B - grab boot disk flag (bit 0) 542 lda $9ffd 543 544 ;merge cart A's flags if it is present 545 ldx tramsz 546 beq no_cart_a 547 548 have_cart_a: 549 ora $bffd 550 551 no_cart_a: 552 ;skip disk boot if neither cart requested it 553 lsr 554 bcc skip_disk_boot 555 556 .else 557 558 ;check for cart A requesting boot 559 F0E6 A5 06 lda tramsz 560 F0E8 F0 06 beq boot_disk 561 562 ;have cart A - boot disk if requested 563 F0EA AD FD BF lda $bffd 564 F0ED 4A lsr 565 F0EE 90 1B bcc skip_disk_boot 566 567 .endif 568 569 F0F0 boot_disk: 570 F0F0 20 3B F1 jsr BootDisk 571 F0F3 4C FE F0 jmp post_disk_boot 572 573 F0F6 reinitDisk: 574 F0F6 A5 09 lda boot? 575 F0F8 4A lsr 576 F0F9 90 10 bcc skip_disk_boot 577 F0FB 20 34 F1 jsr InitDiskBoot 578 579 F0FE post_disk_boot: 580 .if _KERNEL_XLXE 581 ; (XL/XE only) do type 3 poll or reinit handlers 582 ; !! - must only do this if a disk boot occurs; Pole Position audio breaks if 583 ; we do this and hit SKCTL before booting the cart 584 F0FE A5 08 lda warmst 585 F100 D0 06 bne reinit_handlers 586 F102 20 6A C4 jsr PHStartupPoll 587 F105 4C 0B F1 jmp post_reinit 588 F108 reinit_handlers: 589 F108 20 2E C4 jsr PHReinitHandlers 590 F10B post_reinit: 591 .endif 592 593 F10B skip_disk_boot: 594 595 ;------------------------------------------------------------------------- 596 ; H. same as steps 19 and 20 597 ; 19. reset coldstart flag 598 599 F10B A2 00 ldx #0 600 F10D 8E 44 02 stx coldst 601 602 ;------------------------------------------------------------------------- 603 ; 20. run cartridges or blackboard 604 ; 605 ; Weird quirk here: if the left cart is absent or doesn't request 606 ; cart start, and the right cart is present and also doesn't request 607 ; cart start, OS-B endlessly does disk boots instead of running (DOSVEC). 608 ; We don't emulate this behavior for now since in practice it just seems 609 ; useless, boot looping until DOS crashes. It is moot starting with the 610 ; 1200XL DOS due to support for cart B being dropped. 611 ; 612 613 ; try to boot cart A 614 F110 A9 04 lda #$04 615 F112 A6 06 ldx tramsz 616 F114 F0 08 beq NoBootCartA 617 F116 2C FD BF bit $bffd 618 F119 F0 03 6C FA BF seq:jmp ($bffa) 619 F11E NoBootCartA: 620 621 ; try to boot cart B 622 F11E A6 07 ldx tstdat 623 F120 F0 08 beq NoBootCartB 624 F122 2C FD 9F bit $9ffd 625 F125 F0 03 6C FA 9F seq:jmp ($9ffa) 626 F12A NoBootCartB: 627 628 ; run blackboard 629 F12A 6C 0A 00 jmp (dosvec) 630 631 F12D InitCartA: 632 F12D 6C FE BF jmp ($bffe) 633 634 F130 InitCartB: 635 F130 6C FE 9F jmp ($9ffe) 636 637 F133 ScreenEditorName: 638 F133 45 dta c"E" 639 640 .endp 641 642 ;============================================================================== 643 F134 .proc InitDiskBoot 644 F134 6C 0C 00 jmp (dosini) 645 .endp 646 647 F137 .proc InitCassetteBoot 648 .endp 649 F137 6C 02 00 jmp (casini) 650 651 ;============================================================================== 652 653 F13A EA nop 264 .endif 265 266 F13B icl 'boot.s' Source: source/Shared/boot.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Boot Code 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 ; Disk boot routine. 12 ; 13 ; Exit: 14 ; DBUFLO/DBUFHI = $0400 (Undoc; required by Ankh and the 1.atr SMB demo) 15 ; Last sector in $0400 (Undoc; required by Ankh) 16 ; 17 F13B .proc BootDisk 18 ;issue a status request first to see if the disk is active; if this 19 ;doesn't come back, don't bother trying to read 20 F13B A9 53 lda #$53 21 F13D 8D 02 03 sta dcomnd 22 F140 A2 01 ldx #1 23 F142 8E 01 03 stx dunit 24 F145 20 53 E4 jsr dskinv 25 F148 30 3C bmi xit 26 27 ;read first sector to $0400 28 F14A A2 01 ldx #1 29 F14C 8E 01 03 stx dunit 30 F14F 8E 0A 03 stx daux1 31 F152 CA dex 32 F153 8E 04 03 stx dbuflo 33 F156 8E 0B 03 stx daux2 34 F159 A9 52 8D 02 03 mva #$52 dcomnd 35 F15E A9 04 8D 05 03 mva #$04 dbufhi 36 F163 20 53 E4 jsr dskinv 37 F166 30 1A bmi fail 38 39 F168 sector1_ok: 40 F168 A2 0C ldx #dosini 41 F16A 20 DF F1 jsr BootInitHeaders 42 43 ;load remaining sectors 44 F16D sectorloop: 45 ;copy sector from $0400 to destination (required by Ankh; see above) 46 ;bump destination address for next sector copy 47 F16D 20 0C F2 jsr BootCopyBlock 48 49 ;exit if this was the last sector (note that 0 means to load 256 sectors!) 50 F170 CE 41 02 dec dbsect 51 F173 F0 22 beq loaddone 52 53 ;increment sector (yes, this can overflow to 256) 54 F175 EE 0A 03 D0 03 EE + inw daux1 55 56 ;read next sector 57 F17D 20 53 E4 jsr dskinv 58 59 ;keep going if we succeeded 60 F180 10 EB bpl sectorloop 61 62 ;read failed 63 F182 fail: 64 F182 C0 8A cpy #SIOErrorTimeout 65 F184 D0 01 bne failmsg 66 F186 xit: 67 F186 60 rts 68 69 F187 failmsg: 70 .if _KERNEL_USE_BOOT_SCREEN 71 F187 st_loop: 72 F187 AD 01 D3 lda portb 73 F18A 49 80 eor #$80 74 F18C 8D 01 D3 sta portb 75 F18F 30 D7 bmi sector1_ok 76 F191 20 02 50 jsr BootScreen.boot_entry 77 F194 4C 87 F1 jmp st_loop 78 .else 79 jsr BootShowError 80 jmp BootDisk 81 .endif 82 83 F197 loaddone: 84 F197 20 FC F1 jsr BootRunLoader 85 F19A B0 EB bcs failmsg 86 87 ;Diskette Boot Process, step 7 (p.161 of the OS Manual) is misleading. It 88 ;says that DOSVEC is invoked after DOSINI, but actually that should NOT 89 ;happen here -- it happens AFTER cartridges have had a chance to run. 90 ;This is necessary for BASIC to gain control before DOS goes to load 91 ;DUP.SYS. 92 F19C 20 34 F1 jsr InitDiskBoot 93 94 ;Must not occur until after init routine is called -- SpartaDOS 3.2 does 95 ;an INC on this flag and never exits. 96 F19F A9 01 85 09 mva #1 boot? 97 F1A3 60 rts 98 .endp 99 100 101 ;============================================================================ 102 103 F1A4 .proc BootCassette 104 ;set continuous mode -- must do this as CSOPIV doesn't 105 F1A4 A9 80 lda #$80 106 F1A6 85 3E sta ftype 107 108 ;open cassette device 109 F1A8 20 7D E4 jsr csopiv 110 111 ;read first block 112 F1AB 20 7A E4 jsr rblokv 113 F1AE 30 24 bmi load_failure 114 115 F1B0 A2 02 ldx #casini 116 F1B2 20 DF F1 jsr BootInitHeaders 117 118 F1B5 block_loop: 119 ;copy 128 bytes from CASBUF+3 ($0400) to destination 120 ;update destination pointer 121 F1B5 20 0C F2 jsr BootCopyBlock 122 123 ;read next block 124 ;we always need to do one more to catch the EOF block, which is 125 ;required by STDBLOAD2 126 F1B8 20 7A E4 jsr rblokv 127 F1BB 30 17 bmi load_failure 128 129 F1BD CE 41 02 dec dbsect 130 F1C0 D0 F3 bne block_loop 131 132 ;run loader 133 F1C2 20 FC F1 jsr BootRunLoader 134 135 ;run cassette init routine 136 F1C5 20 37 F1 jsr InitCassetteBoot 137 138 ;clear cassette boot key flag 139 F1C8 A9 00 lda #0 140 F1CA 8D E9 03 sta ckey 141 142 ;set cassette boot flag 143 F1CD A9 02 85 09 mva #2 boot? 144 145 ;run application 146 F1D1 6C 0A 00 jmp (dosvec) 147 148 F1D4 load_failure: 149 F1D4 A9 00 lda #0 150 F1D6 8D E9 03 sta ckey 151 F1D9 20 6F ED jsr CassetteClose 152 F1DC 4C 21 F2 jmp BootShowError 153 .endp 154 155 ;============================================================================ 156 F1DF .proc BootInitHeaders 157 ;copy the first four bytes to DFLAGS, DBSECT, and BOOTAD 158 F1DF A0 FC ldy #$fc 159 F1E1 B9 04 03 99 44 01 + mva:rne $0400-$fc,y dflags-$fc,y+ 160 161 ;copy boot address in BOOTAD to BUFADR 162 F1EA 85 16 sta bufadr+1 163 F1EC AD 42 02 lda bootad 164 F1EF 85 15 sta bufadr 165 166 ;copy init vector 167 F1F1 AD 04 04 95 00 AD + mwa $0404 0,x 168 F1FB 60 rts 169 .endp 170 171 ;============================================================================ 172 F1FC .proc BootRunLoader 173 ;loader is at load address + 6 174 F1FC AD 42 02 lda bootad 175 F1FF 18 69 05 add #$05 176 F202 AA tax 177 F203 AD 43 02 lda bootad+1 178 F206 69 00 adc #0 179 F208 48 pha 180 F209 8A txa 181 F20A 48 pha 182 F20B 60 rts 183 .endp 184 185 ;============================================================================ 186 F20C .proc BootCopyBlock 187 F20C A0 7F ldy #$7f 188 F20E B9 00 04 91 15 88 + mva:rpl $0400,y (bufadr),y- 189 190 F216 A5 15 lda bufadr 191 F218 49 80 eor #$80 192 F21A 85 15 sta bufadr 193 F21C 30 02 E6 16 smi:inc bufadr+1 194 F220 60 rts 195 .endp 196 197 ;============================================================================ 198 199 F221 .proc BootShowError 200 F221 A2 F5 ldx #$f5 201 F223 msgloop: 202 F223 8A txa 203 F224 48 pha 204 F225 BD 3C F1 lda errormsg-$f5,x 205 F228 20 B8 FA jsr EditorPutByte 206 F22B 68 pla 207 F22C AA tax 208 F22D E8 inx 209 F22E D0 F3 bne msgloop 210 F230 60 rts 211 212 F231 errormsg: 213 F231 42 4F 4F 54 20 45 + dta 'BOOT ERROR',$9B 214 .endp 267 F23C _KERNEL_REPORT_MODULE_SIZE 'Monitor routines', $F3E4-$F0E3 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', $F3E4-$F0E3, ')', ' ', 'Monitor routines' 1 $F23C -> $0398($0301) Monitor routines 3 = F23C .def ?@_kernel_lastpt = * Source: source/main.xasm 268 269 F23C icl 'screen.s' Source: source/Shared/screen.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Screen Handler 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;Display list: 11 ; 24 blank lines (3 bytes) 12 ; initial mode line with LMS (3 bytes) 13 ; mode lines 14 ; LMS for modes >4 pages 15 ; wait VBL (3 bytes) 16 ; 17 ; total is 8-10 bytes + mode lines 18 19 ; These are the addresses produced by the normal XL/XE OS: 20 ; 21 ; Normal Split, coarse Split, fine 22 ; Mode DL PF TX DL PF TX DL PF TX 23 ; 0 9C20 9C40 9F60 9C20 9C40 9F60 9C1F 9C40 9F60 24 ; 1 9D60 9D80 9F60 9D5E 9D80 9F60 9D5D 9D80 9F60 25 ; 2 9E5C 9E70 9F60 9E58 9E70 9F60 9E57 9E70 9F60 26 ; 3 9E50 9E70 9F60 9E4E 9E70 9F60 9E4D 9E70 9F60 27 ; 4 9D48 9D80 9F60 9D4A 9D80 9F60 9D49 9D80 9F60 28 ; 5 9B68 9BA0 9F60 9B6A 9BA0 9F60 9B69 9BA0 9F60 29 ; 6 9778 97E0 9F60 9782 97E0 9F60 9781 97E0 9F60 30 ; 7 8F98 9060 9F60 8FA2 9060 9F60 8FA1 9060 9F60 31 ; 8 8036 8150 9F60 8050 8150 9F60 804F 8150 9F60 32 ; 9 8036 8150 9F60 8036 8150 9F60 8036 8150 9F60 33 ; 10 8036 8150 9F60 8036 8150 9F60 8036 8150 9F60 34 ; 11 8036 8150 9F60 8036 8150 9F60 8036 8150 9F60 35 ; 12 9B80 9BA0 9F60 9B7E 9BA0 9F60 9B7D 9BA0 9F60 36 ; 13 9D6C 9D80 9F60 9D68 9D80 9F60 9D67 9D80 9F60 37 ; 14 8F38 9060 9F60 8F52 9060 9F60 8F51 9060 9F60 38 ; 15 8036 8150 9F60 8050 8150 9F60 804F 8150 9F60 39 ; 40 ; *DL = display list (SDLSTL/SDLSTH) 41 ; *PF = playfield (SAVMSC) 42 ; *TX = text window (TXTMSC) 43 ; 44 ; From this, we can derive a few things: 45 ; - The text window is always 160 ($A0) bytes below the ceiling. 46 ; - The playfield is always positioned to have enough room for 47 ; the text window, even though this wastes a little bit of 48 ; memory for modes 1, 2, 3, 4, and 13. This means that the 49 ; PF address does not have to be adjusted for split mode. 50 ; - The display list and playfield addresses are sometimes 51 ; adjusted in order to avoid crossing 1K boundaries for the 52 ; display list (gr.7) and 4K boundaries for the playfield (gr.8). 53 ; However, these are fixed offsets -- adjusting RAMTOP to $9F 54 ; does not remove the DL padding in GR.7 and breaks GR.7/8. 55 ; - Fine-scrolled modes take one additional byte for the extra 56 ; mode 2 line. In fact, it displays garbage that is masked by 57 ; a DLI that sets COLPF1 equal to COLPF2. (!) 58 ; 59 ; You might ask, why bother replicating these? Well, there are a 60 ; number of programs that rely on the layout of the default screen 61 ; and break if the memory addressing is different, such as ForemXEP. 62 63 .macro _SCREEN_TABLES_2 64 65 ;Mode Type Res Colors ANTIC Mem(unsplit) Mem(split) 66 ; 0 Text 40x24 1.5 2 960+32 (4) 960+32 (4) 67 ; 1 Text 20x24 5 6 480+32 (2) 560+32 (3) 68 ; 2 Text 20x12 5 7 240+20 (2) 360+22 (2) 69 ; 3 Bitmap 40x24 4 8 240+32 (2) 360+32 (2) 70 ; 4 Bitmap 80x48 2 9 480+56 (3) 560+52 (3) 71 ; 5 Bitmap 80x48 4 A 960+56 (4) 960+52 (4) 72 ; 6 Bitmap 160x96 2 B 1920+104 (8) 1760+92 (8) 73 ; 7 Bitmap 160x96 4 D 3840+104 (16) 3360+92 (14) 74 ; 8 Bitmap 320x192 1.5 F 7680+202 (32) 6560+174 (27) 75 ; 9 Bitmap 80x192 16 F 7680+202 (32) 6560+174 (27) 76 ; 10 Bitmap 80x192 9 F 7680+202 (32) 6560+174 (27) 77 ; 11 Bitmap 80x192 16 F 7680+202 (32) 6560+174 (27) 78 ; 12 Text 40x24 5 4 960+32 (4) 960+32 (4) 79 ; 13 Text 40x12 5 5 480+20 (2) 560+24 (3) 80 ; 14 Bitmap 160x192 2 C 3840+200 (16) 3360+172 (14) 81 ; 15 Bitmap 160x192 4 E 7680+202 (32) 6560+172 (27) 82 83 ;========================================================================== 84 ; 85 .proc ScreenPlayfieldSizesLo 86 dta <($10000-$03C0) ;gr.0 960 bytes = 40*24 = 40*24 87 dta <($10000-$0280) ;gr.1 640 bytes = 20*24 + 40*4 = 40*12 + 40*4 88 dta <($10000-$0190) ;gr.2 400 bytes = 10*24 + 40*4 = 40*6 + 40*4 89 dta <($10000-$0190) ;gr.3 400 bytes = 10*24 + 40*4 = 40*6 + 40*4 90 dta <($10000-$0280) ;gr.4 640 bytes = 10*48 + 40*4 = 40*12 + 40*4 91 dta <($10000-$0460) ;gr.5 1120 bytes = 20*48 + 40*4 = 40*24 + 40*4 92 dta <($10000-$0820) ;gr.6 2080 bytes = 20*96 + 40*4 = 40*48 + 40*4 93 dta <($10000-$0FA0) ;gr.7 4000 bytes = 40*96 + 40*4 = 40*96 + 40*4 94 dta <($10000-$1EB0) ;gr.8 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16 95 dta <($10000-$1EB0) ;gr.9 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16 96 dta <($10000-$1EB0) ;gr.10 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16 97 dta <($10000-$1EB0) ;gr.11 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16 98 dta <($10000-$0460) ;gr.12 1120 bytes = 40*24 + 40*4 = 40*24 + 40*4 99 dta <($10000-$0280) ;gr.13 640 bytes = 40*12 + 40*4 = 40*12 + 40*4 100 dta <($10000-$0FA0) ;gr.14 4000 bytes = 20*192 + 40*4 = 40*96 + 40*4 101 dta <($10000-$1EB0) ;gr.15 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16 102 .endp 103 104 .proc ScreenPlayfieldSizesHi 105 dta >($10000-$03C0) ;gr.0 106 dta >($10000-$0280) ;gr.1 107 dta >($10000-$0190) ;gr.2 108 dta >($10000-$0190) ;gr.3 109 dta >($10000-$0280) ;gr.4 110 dta >($10000-$0460) ;gr.5 111 dta >($10000-$0820) ;gr.6 112 dta >($10000-$0FA0) ;gr.7 113 dta >($10000-$1EB0) ;gr.8 114 dta >($10000-$1EB0) ;gr.9 115 dta >($10000-$1EB0) ;gr.10 116 dta >($10000-$1EB0) ;gr.11 117 dta >($10000-$0460) ;gr.12 118 dta >($10000-$0280) ;gr.13 119 dta >($10000-$0FA0) ;gr.14 120 dta >($10000-$1EB0) ;gr.15 121 .endp 122 123 ;========================================================================== 124 ; ANTIC mode is in bits 0-3, PRIOR bits in 6-7. 125 ; DL 1K hop: bit 4 126 ; playfield 4K hop: bit 5 127 ; 128 .proc ScreenModeTable 129 dta $02,$06,$07,$08,$09,$0A,$0B,$1D,$3F,$7F,$BF,$FF,$04,$05,$1C,$3E 130 .endp 131 132 ;========================================================================== 133 ; 134 .proc ScreenHeightShifts 135 dta 1 136 dta 1 137 dta 0 138 dta 1 139 dta 2 140 dta 2 141 dta 3 142 dta 3 143 dta 4 144 dta 4 145 dta 4 146 dta 4 147 dta 1 148 dta 0 149 dta 4 150 dta 4 151 .endp 152 153 .proc ScreenHeights 154 dta 12, 24, 48, 96, 192 155 .endp 156 157 .proc ScreenPixelWidthIds 158 dta 1 ;gr.0 40 pixels 159 dta 0 ;gr.1 20 pixels 160 dta 0 ;gr.2 20 pixels 161 dta 1 ;gr.3 40 pixels 162 dta 2 ;gr.4 80 pixels 163 dta 2 ;gr.5 80 pixels 164 dta 3 ;gr.6 160 pixels 165 dta 3 ;gr.7 160 pixels 166 dta 4 ;gr.8 320 pixels 167 dta 2 ;gr.9 80 pixels 168 dta 2 ;gr.10 80 pixels 169 dta 2 ;gr.11 80 pixels 170 dta 1 ;gr.12 40 pixels 171 dta 1 ;gr.13 40 pixels 172 dta 3 ;gr.14 160 pixels 173 dta 3 ;gr.15 160 pixels 174 .endp 175 .endm 176 177 = F2A7 ScreenHeightsSplit = ScreenWidths 178 ; dta 10, 20, 40, 80, 160 179 180 = F2A8 ScreenPixelWidthsLo = ScreenWidths + 1 181 182 .macro _SCREEN_TABLES_1 183 184 .proc ScreenWidths 185 dta <10 186 dta <20 187 dta <40 188 dta <80 189 dta <160 190 dta <320 191 .endp 192 193 .proc ScreenPixelWidthsHi 194 dta >20 195 dta >40 196 dta >80 197 dta >160 198 dta >320 199 .endp 200 201 .proc ScreenEncodingTab 202 dta 0 ;gr.0 direct bytes 203 dta 0 ;gr.1 direct bytes 204 dta 0 ;gr.2 direct bytes 205 dta 2 ;gr.3 two bits per pixel 206 dta 3 ;gr.4 one bit per pixel 207 dta 2 ;gr.5 two bits per pixel 208 dta 3 ;gr.6 one bit per pixel 209 dta 2 ;gr.7 two bits per pixel 210 dta 3 ;gr.8 one bit per pixel 211 dta 1 ;gr.9 four bits per pixel 212 dta 1 ;gr.10 four bits per pixel 213 dta 1 ;gr.11 four bits per pixel 214 dta 0 ;gr.12 direct bytes 215 dta 0 ;gr.13 direct bytes 216 dta 3 ;gr.14 one bit per pixel 217 dta 2 ;gr.15 two bits per pixel 218 .endp 219 220 .proc ScreenPixelMasks 221 dta $ff, $0f, $03, $01, $ff, $f0, $c0, $80 222 .endp 223 .endm 224 225 .macro _SCREEN_TABLES_3 226 .proc ScreenEncodingTable 227 dta $00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$aa,$bb,$cc,$dd,$ee,$ff 228 dta $00,$55,$aa,$ff 229 dta $00,$ff 230 .endp 231 .endm 232 233 .if _KERNEL_XLXE 234 F23C _SCREEN_TABLES_3 Macro: _SCREEN_TABLES_3 [Source: source/Shared/screen.s] 2 F23C 00 11 22 33 44 55 + dta $00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$aa,$bb,$cc,$dd,$ee,$ff 3 F24C 00 55 AA FF dta $00,$55,$aa,$ff 4 F250 00 FF dta $00,$ff Source: source/Shared/screen.s 235 F252 _SCREEN_TABLES_2 Macro: _SCREEN_TABLES_2 [Source: source/Shared/screen.s] 23 F252 40 dta <($10000-$03C0) ;gr.0 960 bytes = 40*24 = 40*24 24 F253 80 dta <($10000-$0280) ;gr.1 640 bytes = 20*24 + 40*4 = 40*12 + 40*4 25 F254 70 dta <($10000-$0190) ;gr.2 400 bytes = 10*24 + 40*4 = 40*6 + 40*4 26 F255 70 dta <($10000-$0190) ;gr.3 400 bytes = 10*24 + 40*4 = 40*6 + 40*4 27 F256 80 dta <($10000-$0280) ;gr.4 640 bytes = 10*48 + 40*4 = 40*12 + 40*4 28 F257 A0 dta <($10000-$0460) ;gr.5 1120 bytes = 20*48 + 40*4 = 40*24 + 40*4 29 F258 E0 dta <($10000-$0820) ;gr.6 2080 bytes = 20*96 + 40*4 = 40*48 + 40*4 30 F259 60 dta <($10000-$0FA0) ;gr.7 4000 bytes = 40*96 + 40*4 = 40*96 + 40*4 31 F25A 50 dta <($10000-$1EB0) ;gr.8 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16 32 F25B 50 dta <($10000-$1EB0) ;gr.9 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16 33 F25C 50 dta <($10000-$1EB0) ;gr.10 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16 34 F25D 50 dta <($10000-$1EB0) ;gr.11 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16 35 F25E A0 dta <($10000-$0460) ;gr.12 1120 bytes = 40*24 + 40*4 = 40*24 + 40*4 36 F25F 80 dta <($10000-$0280) ;gr.13 640 bytes = 40*12 + 40*4 = 40*12 + 40*4 37 F260 60 dta <($10000-$0FA0) ;gr.14 4000 bytes = 20*192 + 40*4 = 40*96 + 40*4 38 F261 50 dta <($10000-$1EB0) ;gr.15 7856 bytes = 40*192 + 40*4 + 16 = 40*192 + 40*4 + 16 42 F262 FC dta >($10000-$03C0) ;gr.0 43 F263 FD dta >($10000-$0280) ;gr.1 44 F264 FE dta >($10000-$0190) ;gr.2 45 F265 FE dta >($10000-$0190) ;gr.3 46 F266 FD dta >($10000-$0280) ;gr.4 47 F267 FB dta >($10000-$0460) ;gr.5 48 F268 F7 dta >($10000-$0820) ;gr.6 49 F269 F0 dta >($10000-$0FA0) ;gr.7 50 F26A E1 dta >($10000-$1EB0) ;gr.8 51 F26B E1 dta >($10000-$1EB0) ;gr.9 52 F26C E1 dta >($10000-$1EB0) ;gr.10 53 F26D E1 dta >($10000-$1EB0) ;gr.11 54 F26E FB dta >($10000-$0460) ;gr.12 55 F26F FD dta >($10000-$0280) ;gr.13 56 F270 F0 dta >($10000-$0FA0) ;gr.14 57 F271 E1 dta >($10000-$1EB0) ;gr.15 66 F272 02 06 07 08 09 0A + dta $02,$06,$07,$08,$09,$0A,$0B,$1D,$3F,$7F,$BF,$FF,$04,$05,$1C,$3E 72 F282 01 dta 1 73 F283 01 dta 1 74 F284 00 dta 0 75 F285 01 dta 1 76 F286 02 dta 2 77 F287 02 dta 2 78 F288 03 dta 3 79 F289 03 dta 3 80 F28A 04 dta 4 81 F28B 04 dta 4 82 F28C 04 dta 4 83 F28D 04 dta 4 84 F28E 01 dta 1 85 F28F 00 dta 0 86 F290 04 dta 4 87 F291 04 dta 4 91 F292 0C 18 30 60 C0 dta 12, 24, 48, 96, 192 95 F297 01 dta 1 ;gr.0 40 pixels 96 F298 00 dta 0 ;gr.1 20 pixels 97 F299 00 dta 0 ;gr.2 20 pixels 98 F29A 01 dta 1 ;gr.3 40 pixels 99 F29B 02 dta 2 ;gr.4 80 pixels 100 F29C 02 dta 2 ;gr.5 80 pixels 101 F29D 03 dta 3 ;gr.6 160 pixels 102 F29E 03 dta 3 ;gr.7 160 pixels 103 F29F 04 dta 4 ;gr.8 320 pixels 104 F2A0 02 dta 2 ;gr.9 80 pixels 105 F2A1 02 dta 2 ;gr.10 80 pixels 106 F2A2 02 dta 2 ;gr.11 80 pixels 107 F2A3 01 dta 1 ;gr.12 40 pixels 108 F2A4 01 dta 1 ;gr.13 40 pixels 109 F2A5 03 dta 3 ;gr.14 160 pixels 110 F2A6 03 dta 3 ;gr.15 160 pixels Source: source/Shared/screen.s 236 F2A7 _SCREEN_TABLES_1 Macro: _SCREEN_TABLES_1 [Source: source/Shared/screen.s] 3 F2A7 0A dta <10 4 F2A8 14 dta <20 5 F2A9 28 dta <40 6 F2AA 50 dta <80 7 F2AB A0 dta <160 8 F2AC 40 dta <320 12 F2AD 00 dta >20 13 F2AE 00 dta >40 14 F2AF 00 dta >80 15 F2B0 00 dta >160 16 F2B1 01 dta >320 20 F2B2 00 dta 0 ;gr.0 direct bytes 21 F2B3 00 dta 0 ;gr.1 direct bytes 22 F2B4 00 dta 0 ;gr.2 direct bytes 23 F2B5 02 dta 2 ;gr.3 two bits per pixel 24 F2B6 03 dta 3 ;gr.4 one bit per pixel 25 F2B7 02 dta 2 ;gr.5 two bits per pixel 26 F2B8 03 dta 3 ;gr.6 one bit per pixel 27 F2B9 02 dta 2 ;gr.7 two bits per pixel 28 F2BA 03 dta 3 ;gr.8 one bit per pixel 29 F2BB 01 dta 1 ;gr.9 four bits per pixel 30 F2BC 01 dta 1 ;gr.10 four bits per pixel 31 F2BD 01 dta 1 ;gr.11 four bits per pixel 32 F2BE 00 dta 0 ;gr.12 direct bytes 33 F2BF 00 dta 0 ;gr.13 direct bytes 34 F2C0 03 dta 3 ;gr.14 one bit per pixel 35 F2C1 02 dta 2 ;gr.15 two bits per pixel 39 F2C2 FF 0F 03 01 FF F0 + dta $ff, $0f, $03, $01, $ff, $f0, $c0, $80 Source: source/Shared/screen.s 237 .endif 238 239 ;========================================================================== 240 ;========================================================================== 241 242 ;Many compilation disks rely on ScreenOpen being at $F3F6. 243 244 .if *>$f3f6-8 245 .error 'ROM overflow into Screen Handler region: ',*,' > $F3EE.' 246 .endif 247 248 .ifdef _KERNEL_REPORT_MODULE_PAD_ADJUST 249 F2CA _KERNEL_REPORT_MODULE_PAD_ADJUST [$f3f6-8]-* Macro: _KERNEL_REPORT_MODULE_PAD_ADJUST [Source: source/main.xasm] 1 = F360 .def ?@_kernel_lastpt = ?@_kernel_lastpt + [$F3F6-8]-* Source: source/Shared/screen.s 250 .endif 251 252 F2CA org $f3f6-8 253 254 ;========================================================================== 255 ;========================================================================== 256 257 ;========================================================================== 258 ; 259 ; Return: 260 ; MEMTOP = first byte used by display 261 ; 262 ; Errors: 263 ; - If there is not enough memory (MEMTOP > APPMHI), GR.0 is reopened 264 ; automatically and an error is returned. 265 ; 266 ; Notes: 267 ; - Resets character base (CHBAS). 268 ; - Resets character attributes (CHACT). 269 ; - Resets playfield colors (COLOR0-COLOR4). 270 ; - Resets tab map, even if the mode does not have a text window. 271 ; - Resets logical line map, even if the mode does not have a text window. 272 ; - Does NOT reset P/M colors (PCOLR0-PCOLR3). 273 ; - Does NOT reset margins (LMARGN/RMARGN). 274 ; - Sets up fine scrolling if FINE bit 7 is set. Note that this is 275 ; different than the scroll logic itself, which tests the whole byte. 276 ; - Returns error $80 if BREAK has been pressed. 277 ; - If clear is bypassed, ROWCRS and COLCRS are preserved. 278 ; 279 ; Modified: 280 ; - FRMADR: used for bitflags 281 ; bit 7 = skip clear 282 ; bit 6 = split screen 283 ; bit 0 = fine scrolling (XL/XE only) 284 ; - ADRESS: temporary addressing 285 ; 286 = F3F6 ScreenOpen = ScreenOpenGr0.use_iocb 287 = F3F2 ScreenOpenMode0 = ScreenOpenGr0.use_mode0 288 F3EE .proc ScreenOpenGr0 289 F3EE A9 0C 85 2A mva #12 icax1z 290 F3F2 use_mode0: 291 F3F2 A9 00 85 2B mva #0 icax2z 292 F3F6 use_iocb: 293 ;shut off ANTIC playfield and instruction DMA 294 F3F6 AD 2F 02 lda sdmctl 295 F3F9 29 DC and #$dc 296 F3FB 8D 2F 02 sta sdmctl 297 F3FE 8D 00 D4 sta dmactl 298 299 ;reset cursor parameters 300 F401 A2 0B ldx #11 301 F403 A9 00 lda #0 302 F405 clear_parms: 303 F405 95 54 sta rowcrs,x 304 F407 9D 90 02 sta txtrow,x 305 F40A CA dex 306 F40B D0 F8 bne clear_parms 307 308 ;mark us as being in main screen context 309 F40D 86 7B stx swpflg 310 311 ;copy mode value to dindex 312 F40F A5 2B lda icax2z 313 F411 29 0F and #15 314 F413 85 57 sta dindex 315 F415 AA tax 316 317 ;poke PRIOR value (saves us some time to do it now) 318 ;note that we must preserve bits 0-5 of GPRIOR or else Wayout shows logo artifacts 319 F416 BD 72 F2 lda ScreenModeTable,x 320 F419 4D 6F 02 eor gprior 321 F41C 29 C0 and #$c0 322 F41E 4D 6F 02 eor gprior 323 F421 8D 6F 02 sta gprior 324 325 ;if a GTIA mode is active or we're in mode 0, force off split mode 326 F424 C9 40 cmp #$40 327 F426 A5 2A lda icax1z 328 F428 B0 04 bcs kill_split 329 F42A E0 00 cpx #0 330 F42C D0 02 bne not_gtia_mode_or_gr0 331 F42E kill_split: 332 F42E 29 EF and #$ef 333 F430 not_gtia_mode_or_gr0: 334 335 ;save off the split screen and clear flags in a more convenient form 336 F430 0A asl 337 F431 0A asl 338 F432 85 68 sta frmadr 339 340 ;compute number of mode lines that we're going to have and save it off 341 F434 BC 82 F2 ldy ScreenHeightShifts,x 342 F437 BE 92 F2 ldx ScreenHeights,y 343 F43A 0A asl 344 F43B 10 03 BE A7 F2 spl:ldx ScreenHeightsSplit,y 345 F440 86 69 stx frmadr+1 346 347 ;attempt to allocate playfield memory 348 F442 A5 6A lda ramtop 349 F444 A6 57 ldx dindex 350 F446 18 clc 351 F447 7D 62 F2 adc ScreenPlayfieldSizesHi,x 352 F44A B0 09 bcs pf_alloc_ok 353 354 F44C alloc_fail: 355 ;we ran out of memory -- attempt to reopen with gr.0 if we aren't 356 ;already (to prevent recursion), and exit with an error 357 F44C 8A txa 358 F44D F0 03 beq cant_reopen_gr0 359 360 F44F 20 EE F3 jsr ScreenOpenGr0 361 F452 cant_reopen_gr0: 362 F452 A0 93 ldy #CIOStatOutOfMemory 363 F454 60 rts 364 365 F455 pf_alloc_ok: 366 F455 85 59 sta savmsc+1 367 F457 BC 52 F2 ldy ScreenPlayfieldSizesLo,x 368 F45A 84 58 sty savmsc 369 370 ;Gr. modes 7 and 14 consume enough space for the playfield that there 371 ;is not enough space left between the playfield and the next 1K 372 ;boundary to contain the display list. In these cases, we preallocate 373 ;to the 1K boundary to prevent a DL crossing error. Gr.8-11 and 15 374 ;do this too -- I have no idea why, as it's not like the OS correctly 375 ;handles moving the 4K page split for those modes if RAMTOP is 376 ;misaligned. 377 F45C BD 72 F2 lda ScreenModeTable,x 378 F45F A6 59 ldx savmsc+1 379 F461 29 30 and #$30 380 F463 F0 03 beq no_dlist_page_crossing 381 F465 A0 00 ldy #0 382 F467 CA dex 383 F468 no_dlist_page_crossing: 384 F468 84 70 sty rowac 385 F46A 8E E6 02 stx memtop+1 386 F46D 86 71 stx rowac+1 387 F46F 8E 31 02 stx sdlsth 388 389 ;Compute display list size. 390 ; 391 ; We need: 392 ; - 8 fixed bytes (24 blank lines, LMS address, JVB) 393 ; - N bytes for mode lines 394 ; - 2 bytes for LMS split address (ANTIC modes E-F only) 395 ; - 6 bytes for split 396 ; 397 ;Note that the display list never crosses a page boundary. This is 398 ;conservative, as the display list only can't cross 1K boundaries. 399 400 F472 C9 20 cmp #$20 ;test 4K hop bit (bit 5) 401 F474 A9 F8 lda #$f8 ;start with -8 (if carry is clear after test) 402 F476 90 02 A9 F5 scc:lda #$f5 ;use -11 if so (carry is set) 403 F47A E5 69 sbc frmadr+1 ;subtract mode line count 404 F47C 24 68 bit frmadr 405 F47E 50 02 E9 06 svc:sbc #6 ;subtract 6 bytes for a split 406 407 .if _KERNEL_XLXE 408 F482 A0 01 ldy #1 409 F484 CC 6E 02 cpy fine ;clear carry to alloc +1 byte if fine scrolling is enabled 410 .endif 411 412 F487 65 70 adc rowac ;allocate dl bytes (note that carry is set!) 413 F489 8D E5 02 sta memtop 414 F48C 85 70 sta rowac 415 F48E 8D 30 02 sta sdlstl 416 417 ;check if we're below APPMHI 418 F491 E4 0F cpx appmhi+1 419 F493 90 B7 bcc alloc_fail 420 F495 D0 04 bne alloc_ok 421 F497 C5 0E cmp appmhi 422 F499 90 B1 bcc alloc_fail 423 424 F49B alloc_ok: 425 ;MEMTOP is -1 from first used byte; we cheat here with the knowledge that 426 ;the low byte of MEMTOP is never $00 427 F49B CE E5 02 dec memtop 428 429 ;set up text window address (-160 from top) 430 F49E A6 6A ldx ramtop 431 F4A0 CA dex 432 F4A1 8E 95 02 stx txtmsc+1 433 F4A4 A9 60 8D 94 02 mva #$60 txtmsc 434 435 ;Turn on keyboard and break interrupts; note that this is done both for S: 436 ;and E: opens. Close does not do this. 437 F4A9 08 php 438 F4AA 78 sei 439 F4AB 0A asl ;!! - A = $C0 440 F4AC 05 10 ora pokmsk 441 F4AE 85 10 sta pokmsk 442 F4B0 8D 0E D2 sta irqen 443 F4B3 28 plp 444 445 ;Set row count: 24 for full-screen. We will fix up the split case to 4 later 446 ;while we are writing the display list. Mapping the Atari incorrectly states 447 ;that this value is set to 0 when no text window is present; this is wrong 448 ;and in fact BAYPILOT.BAS relies on this being set to 24 for a GR.7+16 449 ;screen since it later aliases it to GR.0. 450 F4B4 A0 18 ldy #24 451 F4B6 8C BF 02 sty botscr 452 453 ;init colors -- note that we do NOT overwrite pcolr0-3! 454 F4B9 A0 05 ldy #5 455 F4BB B9 BB F5 99 C3 02 + mva:rne standard_colors-1,y color0-1,y- 456 457 F4C4 8C F0 02 sty crsinh ;!! - Y=0 for this and for write index 458 459 ;add 24 blank lines 460 F4C7 A9 70 lda #$70 461 F4C9 A2 03 ldx #3 462 F4CB 20 85 F5 jsr write_repeat 463 464 ;override COLOR4 (background) to $06 for GR.11 so it isn't dark 465 F4CE A5 57 lda dindex 466 F4D0 C9 0B cmp #11 467 F4D2 D0 05 bne not_gr11 468 F4D4 A9 06 lda #$06 469 F4D6 8D C8 02 sta color4 470 F4D9 not_gr11: 471 472 ;add in the main screen 473 F4D9 20 3B F5 jsr setup_display 474 475 ;save off the DL ptr 476 F4DC 84 7E sty countr 477 478 ;clear it if necessary 479 F4DE 20 B5 F5 jsr try_clear 480 481 ;check if we are doing a split 482 F4E1 24 68 bit frmadr 483 F4E3 50 12 bvc nosplit 484 485 ;change text screen height to four lines 486 F4E5 A2 04 ldx #4 487 F4E7 8E BF 02 stx botscr 488 489 ;swap to the text screen 490 F4EA 20 3D F9 jsr EditorSwapToText 491 492 ;add text screen dlist 493 F4ED A4 7E ldy countr 494 F4EF 20 3B F5 jsr setup_display 495 F4F2 84 7E sty countr 496 497 ;clear the split screen 498 F4F4 20 B5 F5 jsr try_clear 499 500 F4F7 nosplit: 501 F4F7 A9 02 8D F3 02 mva #2 chact 502 503 ;init tab map to every 8 columns 504 F4FC A2 0F ldx #15 505 F4FE 4A lsr ;!! A=1 506 F4FF 9D A2 02 CA D0 FA sta:rne tabmap-1,x- 507 508 ;reset line status 509 F505 86 6B stx bufcnt 510 511 ;init character set 512 F507 A2 E0 8E F4 02 mvx #$e0 chbas ;!! - also used for NMIEN 513 514 ;enable VBI; note that we have not yet enabled display DMA 515 .if _KERNEL_XLXE 516 F50C 24 68 bit frmadr 517 F50E D0 02 A2 40 sne:ldx #$40 518 .else 519 ldx #$40 520 .endif 521 F512 8E 0E D4 stx nmien 522 523 ;terminate display list with jvb 524 F515 A4 7E ldy countr 525 F517 A2 70 ldx #rowac 526 F519 A9 41 lda #$41 527 F51B 20 A7 F5 jsr write_with_zp_address 528 529 ;init display list and playfield dma 530 F51E AD 2F 02 lda sdmctl 531 F521 09 22 ora #$22 532 F523 8D 2F 02 sta sdmctl 533 534 ;wait for screen to establish (necessary for Timewise splash screen to render) 535 F526 A5 14 lda rtclok+2 536 F528 C5 14 F0 FC cmp:req rtclok+2 537 538 ;If we're in screen mode 0, show the cursor; otherwise, skip it and wait for 539 ;E: to do so. We need to skip this even if a split screen is present, or else 540 ;ACTris 2.1 displays a bogus cursor. Unfortunately we may have swapped to the 541 ;split screen, so the mode we need may be in either DINDEX or TINDEX; it's 542 ;easier for us just to re-check AUX2 bits 0-3. 543 F52C A5 2B lda icax2z 544 F52E 29 0F and #$0f 545 F530 D0 03 bne no_cursor 546 547 ;show cursor 548 F532 20 B5 F6 jsr ScreenPutByte.recompute_show_cursor_exit 549 F535 no_cursor: 550 ;swap back to main context 551 F535 20 9C FD jsr EditorSwapToScreen_Y1 552 553 ;exit 554 F538 A2 00 ldx #0 ;required by Qix (v3) 555 F53A 60 rts 556 557 558 ;-------------------------------------------------------- 559 F53B setup_display: 560 ;Add initial mode line with LMS, and check if we need to do an LMS 561 ;split (playfield exceeds 4K). As it turns out, this only happens if 562 ;we're using ANTIC mode E or F. 563 F53B A6 57 ldx dindex 564 F53D BD 72 F2 lda ScreenModeTable,x 565 F540 29 0F and #$0f 566 567 .if _KERNEL_XLXE 568 ;check if we are doing fine scrolling and set the vscrol bit if so 569 F542 A6 57 ldx dindex 570 F544 D0 07 bne nofine 571 F546 AE 6E 02 ldx fine 572 F549 F0 02 beq nofine 573 F54B 09 20 ora #$20 574 F54D nofine: 575 .endif 576 577 F54D 48 pha 578 F54E 09 40 ora #$40 579 F550 A2 58 ldx #savmsc 580 F552 20 A7 F5 jsr write_with_zp_address 581 582 ;retrieve row count 583 F555 A6 69 ldx frmadr+1 584 F557 A5 57 lda dindex 585 F559 D0 03 AE BF 02 sne:ldx botscr 586 587 ;dec row count since we already did the LMS 588 F55E CA dex 589 F55F 68 pla 590 591 .if _KERNEL_XLXE 592 ;subtract two rows if we are fine scrolling, as we need to do DLI 593 ;and non-vscrolled row 594 F560 C9 22 cmp #$22 595 F562 F0 28 beq dofine 596 .endif 597 598 ;check if this is a split mode 599 F564 C9 0E cmp #$0e 600 F566 90 1D bcc no_lms_split 601 602 ;yes it is -- write 93 lines 603 F568 A2 5D ldx #93 604 F56A 20 85 F5 jsr write_repeat 605 606 ;write LMS to jump over 4K boundary 607 F56D 48 pha 608 F56E 09 40 ora #$40 609 F570 91 70 C8 sta (rowac),y+ 610 F573 A9 00 lda #0 611 F575 91 70 C8 sta (rowac),y+ 612 F578 A5 59 lda savmsc+1 613 F57A 69 0E adc #$0f-1 ;!! - C=1 from bcc above 614 F57C 91 70 C8 sta (rowac),y+ 615 616 ;set up to write 95 fewer lines (note that carry is cleared) 617 F57F A5 69 lda frmadr+1 618 F581 E9 5E sbc #94 619 F583 AA tax 620 F584 68 pla 621 622 ;write mode lines and return 623 F585 no_lms_split: 624 F585 write_repeat: 625 F585 91 70 C8 sta (rowac),y+ 626 F588 CA dex 627 F589 D0 FA bne write_repeat 628 F58B no_clear: 629 F58B 60 rts 630 631 .if _KERNEL_XLXE 632 F58C dofine: 633 ;write the regular lines (22 or 2) 634 F58C CA dex 635 F58D 20 85 F5 jsr write_repeat 636 637 ;write DLI line 638 F590 09 80 ora #$80 639 F592 91 70 C8 sta (rowac),y+ 640 641 ;write non-scrolled line 642 F595 29 5F and #$5f 643 F597 91 70 C8 sta (rowac),y+ 644 645 ;indicate to mainline that DLIs should be turned on 646 F59A E6 68 inc frmadr 647 648 ;set up DLI routine 649 F59C A2 DE ldx #ScreenFineScrollDLI 651 F5A0 write_vdslst: 652 F5A0 8E 00 02 stx vdslst 653 F5A3 8D 01 02 sta vdslst+1 654 F5A6 60 rts 655 .endif 656 657 ;-------------------------------------------------------- 658 F5A7 write_with_zp_address: 659 F5A7 91 70 C8 sta (rowac),y+ 660 F5AA B5 00 lda 0,x 661 F5AC 91 70 C8 sta (rowac),y+ 662 F5AF B5 01 lda 1,x 663 F5B1 A2 01 ldx #1 664 F5B3 D0 D0 bne write_repeat ;!! - unconditional 665 666 F5B5 try_clear: 667 F5B5 24 68 bit frmadr 668 F5B7 30 D2 bmi no_clear 669 F5B9 4C 4A F8 jmp ScreenClear 670 671 ;-------------------------------------------------------- 672 F5BC standard_colors: 673 F5BC 28 dta $28 674 F5BD CA dta $ca 675 F5BE 94 dta $94 676 F5BF 46 dta $46 677 = F5C0 .def :ScreenBitposFlipTab 678 F5C0 00 dta $00 ;!! - shared value between tables 679 F5C1 01 dta $01 680 F5C2 03 dta $03 681 F5C3 07 dta $07 682 683 .endp 684 685 ;========================================================================== 686 F5C4 .proc ScreenInit 687 F5C4 AD E6 02 85 6A mva memtop+1 ramtop 688 689 .ifdef _KERNEL_816 690 stz colrsh 691 .else 692 F5C9 A9 00 85 4F mva #0 colrsh 693 .endif 694 695 F5CD A9 FE 85 4E mva #$FE drkmsk 696 F5D1 60 rts 697 .endp 698 699 ;========================================================================== 700 ; Behavior in gr.0: 701 ; - Reading char advances to next position, but cursor is not moved 702 ; - Cursor is picked up ($A0) 703 ; - Wrapping from end goes to left margin on next row 704 ; - Cursor may be outside of horizontal margins 705 ; - Error 141 (cursor out of range) if out of range 706 ; - Cursor will wrap to out of range if at end of screen (no automatic 707 ; vertical wrap) 708 ; - Does NOT update OLDROW/OLDCOL 709 ; 710 F5D2 .proc ScreenGetByte 711 F5D2 20 FA F8 jsr ScreenCheckPosition 712 F5D5 30 3A bmi xit 713 714 ;compute addressing 715 F5D7 A4 54 ldy rowcrs 716 F5D9 20 75 F9 jsr ScreenComputeToAddrX0 717 F5DC A5 55 lda colcrs 718 F5DE A6 57 ldx dindex 719 F5E0 BC B2 F2 ldy ScreenEncodingTab,x 720 F5E3 59 C0 F5 eor ScreenBitposFlipTab,y 721 F5E6 AA tax 722 F5E7 A5 56 lda colcrs+1 723 F5E9 20 BE F9 jsr ScreenSetupPixelAddr.phase2 724 725 ;retrieve byte containing pixel 726 F5EC A4 6F ldy shfamt 727 F5EE B1 66 lda (toadr),y 728 729 ;shift down 730 F5F0 20 AB F9 jsr ScreenAlignPixel 731 732 ;convert from Internal to ATASCII - must be done before we mask 733 ;Internal ATASCII 734 ;00-1F 20-3F 735 ;20-3F 40-5F 736 ;40-5F 00-1F 737 ;60-7F 60-7F 738 F5F3 0A asl 739 F5F4 08 php 740 F5F5 10 02 49 40 spl:eor #$40 ;00>20, 20>40, 40>60, 60>40 741 F5F9 69 40 adc #$40 ;00>20, 20>40, 40>00, 60>60 742 F5FB 28 plp 743 F5FC 6A ror 744 745 ;mask using right-justified pixel mask for mode 746 F5FD A6 57 ldx dindex 747 F5FF BC B2 F2 ldy ScreenEncodingTab,x 748 F602 39 C2 F2 and ScreenPixelMasks,y 749 750 ;advance to next position 751 F605 A6 57 ldx dindex 752 F607 F0 03 beq mode0 753 F609 4C D6 F9 jmp ScreenAdvancePosNonMode0 754 F60C mode0: 755 F60C 20 08 FE jsr ScreenAdvancePosMode0 756 F60F A0 01 ldy #1 757 F611 xit: 758 F611 60 rts 759 .endp 760 761 ;========================================================================== 762 ; Common behavior: 763 ; - Output is suspended if SSFLAG is set for non-clear and non-EOL chars 764 ; - Clear screen ($7D) and EOL ($9B) are always handled 765 ; - ESCFLG and DSPFLG are ignored (they are E: features) 766 ; 767 ; Behavior in gr.0: 768 ; - Logical lines are extended 769 ; - Scrolling occurs if bottom is hit 770 ; - Control chars other than clear and EOL are NOT handled by S: 771 ; - ROWCRS or COLCRS out of range results in an error. 772 ; - COLCRS in left margin is ignored and prints within margin. 773 ; - COLCRS in right margin prints one char and then does EOL. 774 ; - Previous cursor is not erased by S:, regardless of CRSINH state 775 ; - New cursor is drawn if CRSINH=0 776 ; 777 ; Behavior in gr.1+: 778 ; - No cursor is displayed 779 ; - LMARGN/RMARGN are ignored 780 ; - Cursor wraps from right side to next line 781 ; - ROWCRS may be below split screen boundary as long as it is within the 782 ; full screen size. 783 ; 784 F612 .proc ScreenPutByte 785 F612 8D FB 02 sta atachr 786 F615 20 FA F8 jsr ScreenCheckPosition 787 F618 30 0C bmi error 788 789 ;check for screen clear 790 F61A AD FB 02 lda atachr 791 F61D C9 7D cmp #$7d 792 F61F D0 0E bne not_clear_2 793 F621 20 4A F8 jsr ScreenClear 794 F624 A0 01 ldy #1 795 F626 error: 796 F626 60 rts 797 798 F627 graphics_eol: 799 F627 4C EF F9 jmp ScreenAdvancePosNonMode0.graphics_eol 800 801 ;*** ENTRY POINT FROM EDITOR FOR ESC HANDLING *** 802 F62A not_clear: 803 F62A 20 FA F8 jsr ScreenCheckPosition 804 F62D 30 F7 bmi error 805 806 F62F not_clear_2: 807 ;set old position now (used by setup code for plot pixel) 808 F62F 20 FE FD jsr ScreenSetLastPosition 809 810 ;restore char 811 F632 AD FB 02 lda atachr 812 813 ;check if we're in gr.0 814 F635 A6 57 ldx dindex 815 F637 F0 1E beq mode_0 816 817 ;nope, we're in a graphics mode... that makes this easier. 818 ;check if it's an EOL 819 F639 C9 9B cmp #$9b 820 F63B F0 EA beq graphics_eol 821 822 ;check for display suspend (ctrl+1) and wait until it is cleared 823 F63D AE FF 02 D0 FB ldx:rne ssflag 824 825 ;fold the pixel, compute masks, and convert ATASCII to Internal 826 F642 20 CE F6 jsr ScreenFoldColor 827 F645 48 pha 828 829 ;compute addressing and shift mask 830 F646 20 A6 F9 jsr ScreenSetupPlotPixel 831 832 F649 68 pla 833 F64A A4 6F ldy shfamt 834 F64C 51 66 eor (toadr),y 835 F64E 25 6E and bitmsk 836 F650 51 66 eor (toadr),y 837 F652 91 66 sta (toadr),y 838 839 ;advance cursor position and exit 840 F654 4C D6 F9 jmp ScreenAdvancePosNonMode0 841 842 F657 mode_0: 843 ;check for EOL, which bypasses the ESC check 844 F657 C9 9B cmp #$9b 845 F659 D0 18 bne not_eol 846 847 ;it's an EOL 848 F65B A5 52 lda lmargn 849 F65D 85 55 sta colcrs 850 F65F E6 54 inc rowcrs 851 F661 A5 54 lda rowcrs 852 F663 CD BF 02 cmp botscr 853 F666 90 08 bcc noywrap 854 855 ;We've gone over -- delete logical line 0 to make room. 856 ;Note that we need to set ROWCRS here first because the scroll may 857 ;delete more than one physical line. 858 F668 AE BF 02 ldx botscr 859 F66B 86 54 stx rowcrs 860 861 F66D 20 CC FC jsr EditorDeleteLine0 862 F670 noywrap: 863 F670 4C B5 F6 jmp recompute_show_cursor_exit 864 865 F673 not_eol: 866 ;check for display suspend (ctrl+1) and wait until it is cleared 867 F673 AE FF 02 D0 FB ldx:rne ssflag 868 869 F678 48 pha 870 F679 20 C0 FC jsr EditorRecomputeCursorAddr 871 F67C 68 pla 872 F67D 20 EB F6 jsr ScreenConvertATASCIIToInternal 873 874 ;plot character 875 F680 A0 00 ldy #0 876 F682 91 5E sta (oldadr),y 877 878 ;inc pos 879 F684 E6 5E D0 02 E6 5F inw oldadr 880 F68A 20 08 FE jsr ScreenAdvancePosMode0 881 882 ;check if we've gone beyond the right margin 883 F68D B0 29 bcs nowrap 884 885 ;check if we're beyond the bottom of the screen 886 F68F A5 54 lda rowcrs 887 F691 CD BF 02 cmp botscr 888 F694 90 12 bcc no_scroll 889 890 ;yes -- scroll up 891 F696 20 CC FC jsr EditorDeleteLine0 892 893 ;check if we can extend the current logical line -- 3 rows max. 894 F699 20 BB F6 jsr check_extend 895 896 ;Mark the current physical line as part of the last logical line. 897 ; 898 ;NOTE: There is a subtlety here in that we may delete multiple physical 899 ; lines if the top logical line is more than one line long, but we 900 ; only want to add one physical line onto our current logical line. 901 F69C 20 6F FD jsr EditorGetCurLogicalLineInfo 902 F69F 59 B2 02 eor logmap,y 903 F6A2 99 B2 02 sta logmap,y 904 905 F6A5 4C B5 F6 jmp post_scroll 906 907 F6A8 no_scroll: 908 ;check if we can extend the current logical line -- 3 rows max. 909 F6A8 20 BB F6 jsr check_extend 910 911 ;okay, here's the fun part -- we didn't scroll beyond, but we might 912 ;be on another logical line, in which case we need to scroll everything 913 ;down to extend it. 914 F6AB A5 54 lda rowcrs 915 F6AD 20 7E FD jsr EditorTestLogicalLineBit 916 F6B0 F0 03 beq post_scroll 917 918 ;yup, insert a physical line 919 F6B2 20 8D F8 jsr ScreenInsertPhysLine 920 921 F6B5 recompute_show_cursor_exit: 922 F6B5 post_scroll: 923 F6B5 20 C0 FC jsr EditorRecomputeCursorAddr 924 F6B8 nowrap: 925 F6B8 4C 17 FE jmp ScreenShowCursorAndXitOK 926 927 F6BB check_extend: 928 F6BB A6 54 ldx rowcrs 929 F6BD CA dex 930 F6BE 8A txa 931 F6BF 20 87 FD jsr EditorPhysToLogicalRow 932 933 .ifdef _KERNEL_816 934 inc 935 inc 936 .else 937 F6C2 18 clc 938 F6C3 69 02 adc #2 939 .endif 940 941 F6C5 C5 54 cmp rowcrs 942 F6C7 90 01 60 scc:rts 943 F6CA 68 pla 944 F6CB 68 pla 945 F6CC 90 E7 bcc post_scroll 946 .endp 947 948 ;========================================================================== 949 = E4C9 ScreenGetStatus = CIOExitSuccess 950 951 ;========================================================================== 952 ; Given a color byte, mask it off to the pertinent bits and reflect it 953 ; throughout a byte. The byte is converted from ATASCII to Internal 954 ; if the mode uses byte encoding. 955 ; 956 ; Entry: 957 ; A = color value 958 ; 959 ; Exit: 960 ; A = folded color byte 961 ; Y = encoding mode 962 ; DMASK = right-justified bit mask 963 ; DELTAC = left-justified bit mask 964 ; 965 ; Modified: 966 ; HOLD1, ADRESS 967 ; 968 F6CE .proc ScreenFoldColor 969 F6CE A6 57 ldx dindex 970 F6D0 BC B2 F2 ldy ScreenEncodingTab,x ;0 = 8-bit, 1 = 4-bit, 2 = 2-bit, 3 = 1-bit 971 F6D3 BE C6 F2 86 77 mvx ScreenPixelMasks+4,y deltac 972 F6D8 BE C2 F2 8E A0 02 mvx ScreenPixelMasks,y dmask 973 F6DE 30 0B bmi fold_byte 974 F6E0 2D A0 02 and dmask 975 F6E3 19 DA FD ora ScreenEncodingOffsetTable-1,y 976 F6E6 AA tax 977 F6E7 BD 3C F2 lda ScreenEncodingTable,x 978 F6EA 60 rts 979 980 F6EB fold_byte: 981 ;convert byte from ATASCII to Internal -- this is required for gr.1 982 ;and gr.2 to work correctly, and harmless for other modes 983 984 ;========================================================================== 985 ; Convert an ATASCII character to displayable INTERNAL format. 986 ; 987 ; Entry: 988 ; A = ATASCII char 989 ; 990 ; Exit: 991 ; A = INTERNAL char 992 ; 993 = F6EB .def :ScreenConvertATASCIIToInternal 994 ;ATASCII Internal 995 ;00-1F 40-5F 996 ;20-3F 00-1F 997 ;40-5F 20-3F 998 ;60-7F 60-7F 999 1000 F6EB 0A asl 1001 F6EC 08 php 1002 F6ED E9 3F sbc #$3f ;00>60, 20>00, 40>20, 60>40 1003 F6EF 10 02 49 40 spl:eor #$40 ;00>40, 20>00, 40>20, 60>60 1004 F6F3 28 plp 1005 F6F4 6A ror 1006 F6F5 60 rts 1007 .endp 1008 1009 1010 ;========================================================================== 1011 F6F6 .proc ScreenSpecial 1012 F6F6 A5 22 lda iccomz 1013 F6F8 C9 11 cmp #$11 1014 F6FA F0 05 beq ScreenDrawLineFill ;draw line 1015 F6FC C9 12 cmp #$12 1016 F6FE F0 01 beq ScreenDrawLineFill ;fill 1017 F700 60 rts 1018 .endp 1019 1020 ;========================================================================== 1021 ; 1022 ; Inputs: 1023 ; COLCRS,ROWCRS = next point 1024 ; OLDCOL,OLDROW = previous point 1025 ; ATACHR = color/character to use 1026 ; 1027 ; Outputs: 1028 ; OLDCOL,OLDROW = next point 1029 ; 1030 ; Behavior: 1031 ; - In GR.0: 1032 ; - Cursor is not drawn, even with CRSINH=0 1033 ; - OLDADR is updated to ending location, but not OLDCHR. If CRSINH=0, 1034 ; this can lead to a subsequent E: write stomping the last line draw 1035 ; cell with the under-cursor char from the last time the cursor was 1036 ; drawn elsewhere. 1037 ; 1038 ; Some test cases: 1039 ; - Ryba Pila 1040 ; - SPACEWAY.BAS 1041 ; - Worm of Bemer 1042 ; 1043 ; The Bresenham algorithm we use (from Wikipedia): 1044 ; dx = |x2 - x1| 1045 ; dy = |y2 - y1| 1046 ; e = dx - dy 1047 ; 1048 ; loop 1049 ; plot(x1, y1) 1050 ; if x1 == x2 and y1 == y2 then exit 1051 ; e2 = 2*e 1052 ; if e2 + dy > 0 then 1053 ; err = err - dy 1054 ; x0 = x0 + sign(dx) 1055 ; endif 1056 ; if e2 < dx then 1057 ; err = err + dx 1058 ; y0 = y0 + sign(dy) 1059 ; endif 1060 ; end 1061 ; 1062 F701 .proc ScreenDrawLineFill 1063 ;;##TRACE "Drawing line (%d,%d)-(%d,%d) in mode %d" dw(oldcol) db(oldrow) dw(colcrs) db(rowcrs) db(dindex) 1064 1065 ;initialize bit mask and repeat pertinent pixel bits throughout byte 1066 F701 AD FD 02 lda fildat 1067 F704 20 CE F6 jsr ScreenFoldColor 1068 F707 8D BC 02 sta hold4 1069 F70A AD FB 02 lda atachr 1070 F70D 20 CE F6 jsr ScreenFoldColor 1071 F710 85 51 sta hold1 1072 1073 F712 20 A6 F9 jsr ScreenSetupPlotPixel 1074 1075 ;compute screen pitch 1076 F715 A0 01 ldy #1 1077 F717 20 7F F9 jsr ScreenComputeRangeSize 1078 F71A 85 78 sta deltac+1 1079 F71C AA tax 1080 F71D A0 00 ldy #0 1081 1082 ;compute abs(dy) and sign(dy) 1083 F71F A5 54 lda rowcrs 1084 F721 38 E5 5A sub oldrow 1085 F724 B0 0C bcs going_down 1086 F726 49 FF eor #$ff ;take abs(dy) 1087 F728 69 01 adc #1 ; 1088 ;negate screen pitch 1089 F72A 48 pha 1090 F72B 8A txa 1091 F72C 49 FF eor #$ff 1092 F72E AA tax 1093 F72F E8 inx 1094 F730 88 dey 1095 F731 68 pla 1096 F732 going_down: 1097 F732 86 70 stx rowac 1098 F734 85 76 sta deltar 1099 F736 84 71 sty rowac+1 1100 1101 ;;##TRACE "dy = %d" db(deltar) 1102 1103 ;compute abs(dx) and sign(dx) 1104 F738 A2 00 ldx #0 1105 F73A A5 55 lda colcrs 1106 F73C 38 E5 5B sub oldcol 1107 F73F 85 72 sta colac 1108 F741 A5 56 lda colcrs+1 1109 F743 E5 5C sbc oldcol+1 1110 F745 B0 10 bcs going_right 1111 F747 49 FF eor #$ff 1112 F749 A8 tay 1113 F74A A5 72 lda colac 1114 F74C 49 FF eor #$ff 1115 F74E 69 01 adc #1 1116 F750 85 72 sta colac 1117 F752 98 tya 1118 F753 69 00 adc #0 1119 F755 A2 CC ldx #left_shift_8-right_shift_8 1120 F757 going_right: 1121 F757 85 73 sta colac+1 1122 1123 ;;##TRACE "dx = %d" dw(colac) 1124 1125 ;set up x shift routine 1126 F759 8A txa 1127 F75A A6 57 ldx dindex 1128 F75C BC B2 F2 ldy ScreenEncodingTab,x 1129 F75F 18 clc 1130 F760 79 AD F7 adc shift_lo_tab,y 1131 F763 85 64 sta adress 1132 F765 A9 F7 lda #>left_shift_8 1133 F767 85 65 sta adress+1 1134 F769 85 75 sta endpt+1 1135 1136 ;set up x fill shift routine 1137 F76B B9 AD F7 lda shift_lo_tab,y 1138 F76E 18 clc 1139 F76F 69 D9 adc #fill_right_8-right_shift_8 1140 F771 85 74 sta endpt 1141 1142 ;compute initial error accumulator in frmadr (dx-dy) 1143 F773 A6 72 ldx colac 1144 F775 8A txa 1145 F776 38 E5 76 sub deltar 1146 F779 85 68 sta frmadr 1147 F77B A4 73 ldy colac+1 ;leave dx in y:x for max() below 1148 F77D 98 tya 1149 F77E E9 00 sbc #0 1150 F780 85 69 sta frmadr+1 1151 1152 ;compute max(dx, dy) based on sign of (dx - dy) 1153 F782 B0 04 bcs dx_larger 1154 F784 A0 00 ldy #0 1155 F786 A6 76 ldx deltar 1156 F788 dx_larger: 1157 F788 86 7E stx countr 1158 F78A 84 7F sty countr+1 1159 1160 F78C 98 tya 1161 F78D D0 03 bne not_empty 1162 F78F 8A txa 1163 F790 F0 0D beq skip_showcursor 1164 F792 not_empty: 1165 1166 ;;##TRACE "Pixel count = %d" dw(countr) 1167 1168 ;enter pixel loop (this will do a decrement for us) 1169 F792 4C 02 F8 jmp next_pixel 1170 1171 ;---------------------------------------------- 1172 F795 done: 1173 F795 20 FE FD jsr ScreenSetLastPosition 1174 1175 ;RYBA PILA requires the quirky behavior of the last character of a non-zero length 1176 ;DRAWTO being stomped by the character saved from the cursor draw of the last PLOT 1177 ;(write to S:). Note that we must NOT do this for length 0 or it breaks SPACEWAY. 1178 F798 A4 57 ldy dindex 1179 F79A D0 03 bne skip_showcursor 1180 F79C 20 C0 FC jsr EditorRecomputeCursorAddr 1181 F79F skip_showcursor: 1182 F79F A0 01 ldy #1 1183 F7A1 60 rts 1184 1185 ;---------------------------------------------- 1186 F7A2 fill_done: 1187 F7A2 86 6E stx bitmsk 1188 F7A4 4C 02 F8 jmp next_pixel 1189 1190 ;---------------------------------------------- 1191 F7A7 do_fill: 1192 F7A7 A4 6F ldy shfamt ;load current byte offset 1193 F7A9 A6 6E ldx bitmsk ;save current bitmask 1194 F7AB D0 33 bne fill_start ;!! - unconditional 1195 1196 ;---------------------------------------------- 1197 F7AD shift_lo_tab: 1198 F7AD EB dta 0, or Y:[S] + deltar > 0) 1338 F831 98 tya 1339 F832 18 clc 1340 F833 65 76 adc deltar 1341 F835 68 pla 1342 F836 69 00 adc #0 1343 F838 30 B7 bmi no_xinc 1344 1345 ;update error accumulator 1346 F83A A5 68 lda frmadr 1347 F83C 38 E5 76 sub deltar 1348 F83F 85 68 sta frmadr 1349 F841 B0 02 C6 69 scs:dec frmadr+1 1350 1351 ;bump x 1352 F845 A5 6E lda bitmsk 1353 F847 6C 64 00 jmp (adress) 1354 1355 .if [right_shift_4 ^ right_shift_8]&$ff00 1356 .error "Right draw routines cross page: ",right_shift_4,"-",right_shift_8 1357 .endif 1358 .if [left_shift_4 ^ left_shift_8]&$ff00 1359 .error "Left draw routines cross page: ",left_shift_4,"-",left_shift_8 1360 .endif 1361 .if [fill_right_4 ^ fill_right_8]&$ff00 1362 .error "Fill routines cross page: ",fill_right_4,"-",fill_right_8 1363 .endif 1364 .if [[right_shift_4^left_shift_4]|[left_shift_4^fill_right_4]]&$ff00 1365 .error "Line/fill routines cross page: ",left_shift_4,',',right_shift_4,',',fill_right_4 1366 .endif 1367 1368 .endp 1369 1370 ;========================================================================== 1371 ; Clear the screen. 1372 ; 1373 ; Used: 1374 ; ADRESS 1375 ; TOADR 1376 ; 1377 ; Quirks: 1378 ; Clears the split-screen text area even if the main screen (S:) receives 1379 ; the clear. The In-Store Demonstration Cart depends on this. The cursor 1380 ; state of the split screen is NOT reset, so if the cursor was over a 1381 ; non-blank character, that character will be restored when the cursor 1382 ; moves. 1383 ; 1384 ; The logical line map is always reset. 1385 ; 1386 F84A .proc ScreenClear 1387 ;first, set up for clearing the split-screen window (4*40 bytes main) 1388 F84A A0 04 ldy #4 1389 1390 ;check if we are in the split screen text window 1391 F84C A6 7B ldx swpflg 1392 F84E D0 08 bne is_text_window 1393 1394 ;nope, it's the main screen... compute size 1395 F850 A4 57 ldy dindex 1396 F852 BE 82 F2 ldx ScreenHeightShifts,y 1397 F855 BC 92 F2 ldy ScreenHeights,x 1398 F858 is_text_window: 1399 F858 20 7F F9 jsr ScreenComputeRangeSize 1400 1401 ;add 160 bytes to size if not GR.0 -- important to avoid clearing 1402 ;beyond GR.0 screen (the font breaks in BIKERDAV.BAS otherwise!) 1403 F85B 18 clc 1404 F85C A6 57 ldx dindex 1405 F85E F0 02 beq is_gr0 1406 F860 69 A0 adc #160 1407 F862 is_gr0: 1408 F862 A8 tay 1409 F863 A5 65 lda adress+1 1410 F865 69 00 adc #0 1411 1412 F867 AA tax 1413 F868 65 59 adc savmsc+1 1414 F86A 85 67 sta toadr+1 1415 F86C A5 58 85 66 mva savmsc toadr 1416 1417 ;As it turns out, there are no cases where the main screen 1418 ;is an exact number of pages... so we can simply plow into 1419 ;the clear loop. 1420 F870 A9 00 lda #0 1421 F872 loop: 1422 F872 88 dey 1423 F873 91 66 sta (toadr),y 1424 F875 D0 FB bne loop 1425 F877 C6 67 dec toadr+1 1426 F879 CA dex 1427 F87A 10 F6 bpl loop 1428 1429 ;reset coordinates and cursor (we're going to wipe the cursor) 1430 F87C 85 56 sta colcrs+1 1431 F87E 85 54 sta rowcrs 1432 F880 85 5D sta oldchr 1433 1434 ;always reset the logical line map 1435 F882 A6 57 ldx dindex 1436 F884 D0 02 bne is_graphic_screen 1437 F886 A5 52 lda lmargn 1438 F888 is_graphic_screen: 1439 F888 85 55 sta colcrs 1440 1441 ;always reset the logical line map and exit 1442 F88A 4C EB FD jmp ScreenResetLogicalLineMap 1443 .endp 1444 1445 ;========================================================================== 1446 ; Insert a physical line at the current location. 1447 ; 1448 ; Entry: 1449 ; ROWCRS = row before which to insert new line 1450 ; C = 0 if physical line only, C = 1 if should start new logical line 1451 ; 1452 ; Modified: 1453 ; HOLD1, ADRESS 1454 ; 1455 = F88E ScreenInsertLine = ScreenInsertPhysLine.use_c 1456 F88D .proc ScreenInsertPhysLine 1457 F88D 18 clc 1458 F88E use_c: 1459 ;save new logline flag 1460 F88E 08 php 1461 1462 ;compute addresses 1463 F88F AC BF 02 ldy botscr 1464 F892 88 dey 1465 F893 20 75 F9 jsr ScreenComputeToAddrX0 1466 F896 20 C5 FD jsr EditorNextLineAddr 1467 1468 ;copy lines 1469 F899 AE BF 02 ldx botscr 1470 F89C D0 09 bne line_loop_start 1471 F89E line_loop: 1472 F89E A0 27 ldy #39 1473 F8A0 char_loop: 1474 F8A0 B1 68 lda (frmadr),y 1475 F8A2 91 66 sta (toadr),y 1476 F8A4 88 dey 1477 F8A5 10 F9 bpl char_loop 1478 F8A7 line_loop_start: 1479 F8A7 A5 68 lda frmadr 1480 F8A9 85 66 sta toadr 1481 F8AB 38 sec 1482 F8AC E9 28 sbc #40 1483 F8AE 85 68 sta frmadr 1484 F8B0 A5 69 lda frmadr+1 1485 F8B2 85 67 sta toadr+1 1486 F8B4 E9 00 sbc #0 1487 F8B6 85 69 sta frmadr+1 1488 1489 F8B8 CA dex 1490 F8B9 E4 54 cpx rowcrs 1491 F8BB D0 E1 bne line_loop 1492 1493 F8BD no_copy: 1494 ;clear the current line 1495 F8BD A0 27 ldy #39 1496 F8BF A9 00 lda #0 1497 F8C1 clear_loop: 1498 F8C1 91 66 sta (toadr),y 1499 F8C3 88 dey 1500 F8C4 10 FB bpl clear_loop 1501 1502 ;insert bit into logical line mask 1503 F8C6 20 6F FD jsr EditorGetCurLogicalLineInfo 1504 1505 F8C9 28 plp 1506 F8CA B0 02 A9 00 scs:lda #0 1507 F8CE 85 51 sta hold1 1508 1509 F8D0 A9 00 lda #0 1510 F8D2 38 sec 1511 F8D3 FD C1 E4 sbc ReversedBitMasks,x ;-bit 1512 F8D6 0A asl 1513 F8D7 39 B2 02 and logmap,y 1514 F8DA 18 clc 1515 F8DB 79 B2 02 adc logmap,y 1516 F8DE 6A ror 1517 F8DF 05 51 ora hold1 1518 F8E1 99 B2 02 sta logmap,y 1519 1520 F8E4 88 dey 1521 F8E5 10 03 6E B3 02 spl:ror logmap+1 1522 F8EA 88 dey 1523 F8EB 10 03 6E B4 02 spl:ror logmap+2 1524 F8F0 60 rts 1525 .endp 1526 1527 ;========================================================================== 1528 ; Hide the screen cursor, if it is present. 1529 ; 1530 ; Modified: 1531 ; Y 1532 ; 1533 ; Preserved: 1534 ; A 1535 ; 1536 F8F1 .proc ScreenHideCursor 1537 ;erase the cursor 1538 F8F1 48 pha 1539 F8F2 A0 00 ldy #0 1540 F8F4 A5 5D lda oldchr 1541 F8F6 91 5E sta (oldadr),y 1542 F8F8 68 pla 1543 F8F9 no_cursor: 1544 F8F9 60 rts 1545 .endp 1546 1547 ;========================================================================== 1548 F8FA .proc ScreenCheckPosition 1549 ;Check for ROWCRS out of range. Note that for split screen modes we still 1550 ;check against the full height! 1551 F8FA AD BF 02 lda botscr 1552 F8FD A6 57 ldx dindex 1553 F8FF F0 06 beq rowcheck_gr0 1554 F901 BC 82 F2 ldy ScreenHeightShifts,x 1555 F904 B9 92 F2 lda ScreenHeights,y 1556 F907 rowcheck_gr0: 1557 ;while we know it's GR.0, clamp RMARGN to 39 (required for ARTILLERY.BAS) 1558 F907 A0 27 ldy #39 1559 F909 C4 53 cpy rmargn 1560 F90B B0 02 bcs rmargn_ok 1561 F90D 84 53 sty rmargn 1562 F90F rmargn_ok: 1563 F90F 18 clc 1564 F910 E5 54 sbc rowcrs 1565 F912 B0 0E bcs rowcheck_pass 1566 F914 invalid_position: 1567 1568 ;If the cursor is out of range, reset it within bounds. 1569 F914 A0 00 ldy #0 1570 F916 84 56 sty colcrs+1 ;X high = 0 1571 F918 8A txa 1572 F919 D0 02 A4 52 sne:ldy lmargn 1573 F91D 84 55 sty colcrs ;X low = X origin 1574 1575 F91F A0 8D ldy #CIOStatCursorRange 1576 F921 60 rts 1577 1578 F922 rowcheck_pass: 1579 ;check width 1580 F922 BC 97 F2 ldy ScreenPixelWidthIds,x 1581 F925 A5 55 lda colcrs 1582 F927 D9 A8 F2 cmp ScreenPixelWidthsLo,y 1583 F92A A5 56 lda colcrs+1 1584 F92C F9 AD F2 sbc ScreenPixelWidthsHi,y 1585 F92F B0 E3 bcs invalid_position 1586 1587 ;check for BREAK 1588 F931 A0 FF ldy #$ff 1589 F933 A5 11 lda brkkey 1590 F935 D0 04 bne no_break 1591 F937 84 11 sty brkkey 1592 F939 A0 7F ldy #CIOStatBreak-1 1593 F93B no_break: 1594 F93B C8 iny 1595 F93C 60 rts 1596 .endp 1597 1598 ;========================================================================== 1599 ; Swap between the main screen and the split screen. 1600 ; 1601 ; Conventionally, the main screen is left as the selected context when 1602 ; the display handler is not active. 1603 ; 1604 ; Inputs: 1605 ; C = 0 for main screen 1606 ; C = 1 for split screen 1607 ; 1608 ; Modified: 1609 ; X 1610 ; 1611 ; Preserved: 1612 ; A 1613 ; 1614 ;========================================================================== 1615 ; Swap in the text screen (main if gr.0, split otherwise). 1616 ; 1617 F93D .proc EditorSwapToText 1618 ;set C=0 (main) if gr.0, C=1 (split) otherwise 1619 F93D A0 17 ldy #23 1620 F93F CC BF 02 cpy botscr 1621 1622 = F942 .def :ScreenSwap = * 1623 ;check if the correct set is in place 1624 F942 48 pha 1625 F943 A9 00 lda #0 1626 F945 65 7B adc swpflg 1627 F947 F0 14 beq already_there 1628 1629 ;Nope, we need to swap. Conveniently, the data to be swapped 1630 ;is in a 12 byte block: 1631 ; 1632 ; ROWCRS ($0054) TXTROW ($0290) 1633 ; COLCRS ($0055) TXTCOL ($0291) 1634 ; DINDEX ($0057) TINDEX ($0293) 1635 ; SAVMSC ($0058) TXTMSC ($0294) 1636 ; OLDROW ($005A) TXTOLD ($0296) 1637 ; OLDCOL ($005B) TXTOLD ($0297) 1638 ; OLDCHR ($005D) TXTOLD ($0299) 1639 ; OLDADR ($005E) TXTOLD ($029A) 1640 1641 F949 A2 0B ldx #11 1642 F94B swap_loop: 1643 F94B B5 54 lda rowcrs,x 1644 F94D BC 90 02 ldy txtrow,x 1645 F950 94 54 sty rowcrs,x 1646 F952 9D 90 02 sta txtrow,x 1647 F955 CA dex 1648 F956 10 F3 bpl swap_loop 1649 1650 ;invert swap flag 1651 F958 8A txa 1652 F959 45 7B eor swpflg 1653 F95B 85 7B sta swpflg 1654 1655 F95D already_there: 1656 F95D 68 pla 1657 F95E 60 rts 1658 .endp 1659 1660 ;========================================================================== 1661 ; Compute character address. 1662 ; 1663 ; Entry: 1664 ; X = byte index 1665 ; Y = line index 1666 ; 1667 ; Exit: 1668 ; A:X = address 1669 ; 1670 ; Used: 1671 ; ADRESS 1672 ; 1673 F95F .proc ScreenComputeAddr 1674 F95F 20 7F F9 jsr ScreenComputeRangeSize 1675 F962 85 64 sta adress 1676 F964 8A txa 1677 F965 18 clc 1678 F966 65 64 adc adress ;row*10,20,40+col 1679 F968 90 02 E6 65 scc:inc adress+1 1680 F96C 18 clc 1681 F96D 65 58 adc savmsc 1682 F96F AA tax 1683 F970 A5 65 lda adress+1 1684 F972 65 59 adc savmsc+1 1685 F974 60 rts 1686 .endp 1687 1688 ;========================================================================== 1689 = F977 ScreenComputeToAddr = ScreenComputeToAddrX0.with_x 1690 F975 .proc ScreenComputeToAddrX0 1691 F975 A2 00 ldx #0 1692 F977 with_x: 1693 F977 20 5F F9 jsr ScreenComputeAddr 1694 F97A 86 66 stx toadr 1695 F97C 85 67 sta toadr+1 1696 F97E 60 rts 1697 .endp 1698 1699 ;========================================================================== 1700 ; Compute size, in bytes, of a series of lines. 1701 ; 1702 ; Entry: 1703 ; Y = line count 1704 ; 1705 ; Exit: 1706 ; ADRESS+1 High byte of size 1707 ; A Low byte of size 1708 ; 1709 ; Preserved: 1710 ; X 1711 ; 1712 ; Modified: 1713 ; Y 1714 ; 1715 F97F .proc ScreenComputeRangeSize 1716 F97F A9 00 85 65 mva #0 adress+1 1717 F983 84 64 sty adress 1718 F985 A4 57 ldy dindex 1719 F987 B9 97 F2 lda ScreenPixelWidthIds,y 1720 F98A 38 sec 1721 F98B F9 B2 F2 sbc ScreenEncodingTab,y 1722 F98E A8 tay 1723 F98F C8 iny 1724 F990 A5 64 lda adress 1725 F992 0A asl 1726 F993 26 65 rol adress+1 ;row*2 1727 F995 0A asl 1728 F996 26 65 rol adress+1 ;row*4 1729 F998 18 clc 1730 F999 65 64 adc adress ;row*5 1731 F99B 90 02 E6 65 scc:inc adress+1 1732 F99F shift_loop: 1733 F99F 0A asl 1734 F9A0 26 65 rol adress+1 ;row*10,20,40 1735 F9A2 88 dey 1736 F9A3 10 FA bpl shift_loop 1737 F9A5 60 rts 1738 .endp 1739 1740 ;========================================================================== 1741 ; Setup for pixel plot. 1742 ; 1743 ; Entry: 1744 ; OLDCOL, OLDROW = position 1745 ; DELTAC = left-justified pixel mask 1746 ; 1747 ; Exit: 1748 ; TOADR = screen row 1749 ; SHFAMT = byte offset within row 1750 ; BITMSK = shifted bit mask for pixel 1751 ; 1752 ; Modified: 1753 ; ADRESS 1754 ; 1755 = F9AB ScreenAlignPixel = ScreenSetupPlotPixel.rshift_mask 1756 F9A6 .proc ScreenSetupPlotPixel 1757 ;;##TRACE "Folded pixel = $%02X" db(hold1) 1758 F9A6 20 B5 F9 jsr ScreenSetupPixelAddr 1759 1760 ;preshift bit mask 1761 F9A9 A5 77 lda deltac 1762 F9AB rshift_mask: 1763 F9AB CA dex 1764 F9AC 30 04 bmi xmaskshift_done 1765 F9AE xmaskshift_loop: 1766 F9AE 4A lsr 1767 F9AF CA dex 1768 F9B0 10 FC bpl xmaskshift_loop 1769 F9B2 xmaskshift_done: 1770 F9B2 85 6E sta bitmsk 1771 1772 ;;##TRACE "Initial bitmasks = $%02X $%02X" db(bitmsk) db(dmask) 1773 F9B4 60 rts 1774 .endp 1775 1776 ;========================================================================== 1777 ; Setup for pixel addressing. 1778 ; 1779 ; Entry: 1780 ; COLCRS, ROWCRS = position (ScreenSetupPixelAddr) 1781 ; OLDCOL, OLDROW = position (ScreenSetupPixelAddrOld) 1782 ; 1783 ; Exit: 1784 ; TOADR = screen row 1785 ; SHFAMT = byte offset within row 1786 ; X = number of bits from left side of byte to left side of pixel 1787 ; 1788 F9B5 .proc ScreenSetupPixelAddr 1789 ;compute initial address 1790 F9B5 A4 5A ldy oldrow 1791 F9B7 20 75 F9 jsr ScreenComputeToAddrX0 1792 1793 ;;##TRACE "Initial row address = $%04X" dw(toadr) 1794 1795 ;compute initial byte offset 1796 F9BA A5 5C lda oldcol+1 1797 F9BC A6 5B ldx oldcol 1798 F9BE phase2: 1799 F9BE 6A ror 1800 F9BF 86 6F stx shfamt 1801 F9C1 A9 00 lda #0 1802 F9C3 A6 57 ldx dindex 1803 F9C5 BC B2 F2 ldy ScreenEncodingTab,x 1804 F9C8 F0 06 beq no_xshift 1805 F9CA xshift_loop: 1806 F9CA 66 6F ror shfamt 1807 F9CC 6A ror 1808 F9CD 88 dey 1809 F9CE D0 FA bne xshift_loop 1810 F9D0 no_xshift: 1811 F9D0 2A rol 1812 F9D1 2A rol 1813 F9D2 2A rol 1814 F9D3 2A rol 1815 F9D4 AA tax 1816 1817 ;;##TRACE "Initial row offset = $%02X" db(shfamt) 1818 F9D5 60 rts 1819 .endp 1820 1821 ;========================================================================== 1822 ; ScreenAdvancePosNonMode0 1823 ; 1824 F9D6 .proc ScreenAdvancePosNonMode0 1825 ;advance position 1826 F9D6 E6 55 inc colcrs 1827 F9D8 D0 02 E6 56 sne:inc colcrs+1 1828 F9DC A6 57 ldx dindex 1829 F9DE BC 97 F2 ldy ScreenPixelWidthIds,x 1830 F9E1 BE AD F2 ldx ScreenPixelWidthsHi,y 1831 F9E4 E4 56 cpx colcrs+1 1832 F9E6 D0 0F bne graphics_no_wrap 1833 F9E8 BE A8 F2 ldx ScreenPixelWidthsLo,y 1834 F9EB E4 55 cpx colcrs 1835 F9ED D0 08 bne graphics_no_wrap 1836 1837 F9EF graphics_eol: 1838 ;move to left side and then one row down -- note that this may 1839 ;push us into an invalid coordinate, which will result on an error 1840 ;on the next call if not corrected 1841 F9EF A0 00 ldy #0 1842 F9F1 84 55 sty colcrs 1843 F9F3 84 56 sty colcrs+1 1844 F9F5 E6 54 inc rowcrs 1845 F9F7 graphics_no_wrap: 1846 F9F7 A0 01 ldy #1 1847 F9F9 60 rts 1848 .endp 1849 1850 ;========================================================================== 1851 .if !_KERNEL_XLXE 1852 _SCREEN_TABLES_1 1853 .endif 270 F9FA icl 'editor.s' Source: source/Shared/editor.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Editor Handler 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 F9FA .proc EditorOpen 12 F9FA 20 EB FD jsr ScreenResetLogicalLineMap 13 F9FD 8E FE 02 stx dspflg ;!! relies on X=0 from ScreenResetLogicalLineMap 14 FA00 8E A2 02 stx escflg 15 16 ;we must force mode 0 here -- ACTION calls this with $0C in AUX2 and 17 ;expects mode 0 to be set 18 FA03 4C F2 F3 jmp ScreenOpenMode0 19 .endp 20 21 ;========================================================================== 22 = FE28 EditorClose = ScreenClose 23 24 ;========================================================================== 25 ; 26 ; === Forced read mode === 27 ; 28 ; If bit 0 if AUX1 is set on the IOCB, it means to read in forced read 29 ; mode. In forced read mode, no keyboard input is fetched and instead 30 ; line read immediately commences, as if ENTER were pressed. 31 ; 32 ; Note that since AUX1 is tested on the IOCB used, it is possible to have 33 ; E: open on more than one IOCB with different forced read modes. 34 ; 35 FA06 .proc EditorGetByte 36 ;check if we have anything left in the current line 37 FA06 A5 6B lda bufcnt 38 FA08 D0 06 bne have_line 39 40 ;nope, fetch a line 41 FA0A 20 26 FA jsr EditorGetLine 42 FA0D 10 01 bpl have_line 43 FA0F 60 rts 44 45 FA10 have_line: 46 ;swap to text context 47 FA10 20 3D F9 jsr EditorSwapToText 48 49 ;subtract off a char 50 FA13 C6 6B dec bufcnt 51 52 ;check if we're at the EOL 53 FA15 D0 09 bne have_char 54 55 ;yes, we're at the EOL -- print it and return it (this will re-enable 56 ;the cursor, too) 57 FA17 A9 9B lda #$9b 58 FA19 20 12 F6 jsr ScreenPutByte 59 60 FA1C A9 9B lda #$9b 61 FA1E D0 03 bne done 62 63 FA20 have_char: 64 ;read a char from the screen 65 FA20 20 D2 F5 jsr ScreenGetByte 66 FA23 done: 67 FA23 4C 9E FD jmp EditorSwapToScreen 68 .endp 69 70 ;========================================================================== 71 ; This behavior is quite complex: 72 ; - The editor remembers the cursor position within the initial logical 73 ; line. Only contents beyond the initial position are returned. This 74 ; is true even if the cursor is moved out of the logical line and back 75 ; in again. 76 ; - Margins are not included. 77 ; - Trailing spaces at the end of a logical line are not returned even 78 ; if the cursor is after them. 79 ; - If the cursor is moved to another logical line, that logical line is 80 ; read instead. There is no memory of the line start for previous 81 ; logical lines, so if there was a prompt on that line it will be 82 ; picked up too. 83 ; - If the logical line length is exceeded, a beep sounds near the end 84 ; and after three lines (120ch) the logical line is terminated and a 85 ; new logical line is started. However, the previous logical line that 86 ; was overflowed is still returned. This still happens if the new 87 ; logical line extends to more than one physical line or even if 88 ; itself overflows (!). If the physical line is changed with up/down, 89 ; this memory is lost, but left/right don't do this. 90 ; - If a logical line extends exactly to the end of a physical line, an 91 ; extra blank line is printed on EOL. 92 ; - If a logical line extends exactly to the end of the screen, a cursor 93 ; out of bounds error results. (We currently do not implement this... 94 ; feature.) 95 ; 96 ; === The BUFSTR variable === 97 ; 98 ; The BUFSTR variable is critical to the way that the get line algorithm 99 ; works. It actually consists of two bytes, the row followed by the column 100 ; of the origin of the line to be read. This is updated whenever a read 101 ; request arrives that starts a new line or whenever the cursor is moved 102 ; to a different logical line. This is how the screen editor knows to 103 ; read at the end of a prompt or from a different line that you have moved 104 ; to, and how it tracks that when scrolling occurs. It does not, however, 105 ; get updated when regular characters are typed, even when spilling to a 106 ; new logical line. 107 ; 108 ; === BUFCNT === 109 ; 110 ; BUFCNT contains the number of characters left to return before we have 111 ; to get a new line: $00 means we will wait for keys, $01 is the EOL, and 112 ; >$01 returns a typed character. We need to follow this convention or 113 ; else the combination of S_VBXE.SYS + CON.SYS /E from SDX 4.46 acts 114 ; strangely on launch. 115 ; 116 FA26 .proc EditorGetLine 117 = 006D _start_x equ bufstr+1 118 = 006C _start_y equ bufstr 119 120 ;Set line buffer start to current position (NOT the start of the logical 121 ;line -- this is a special case). 122 FA26 20 3D F9 jsr EditorSwapToText 123 FA29 A5 55 85 6D mva colcrs _start_x 124 FA2D A5 54 85 6C mva rowcrs _start_y 125 FA31 20 9E FD jsr EditorSwapToScreen 126 127 ;check if forced read is enabled on the IOCB -- if so, assume we've gotten 128 ;an EOL 129 FA34 A5 2A lda icax1z 130 FA36 4A lsr 131 FA37 B0 25 bcs do_eol 132 133 FA39 read_loop: 134 ;get a character 135 FA39 20 69 FE jsr KeyboardGetByte 136 FA3C 10 01 bpl read_ok 137 FA3E read_error: 138 FA3E 60 rts 139 140 FA3F read_ok: 141 FA3F C9 9B cmp #$9b 142 FA41 F0 1D beq is_eol 143 144 ;echo the character 145 FA43 20 B8 FA jsr EditorPutByte 146 FA46 30 F6 bmi read_error 147 148 ;check if we've hit the warning point (logical pos 113) 149 FA48 A5 55 lda colcrs 150 FA4A C9 21 cmp #33 151 FA4C D0 EB bne read_loop 152 153 ;convert current row to logical start row 154 FA4E 20 85 FD jsr EditorGetCurLogicalRow 155 156 ;check if we're on the third row 157 FA51 18 clc 158 FA52 69 02 adc #2 159 FA54 C5 54 cmp rowcrs 160 161 ;if so, sound the bell 162 FA56 D0 E1 bne read_loop 163 FA58 20 97 FD jsr EditorBell 164 165 FA5B 4C 39 FA jmp read_loop 166 167 FA5E do_eol: 168 FA5E A9 9B lda #$9b 169 FA60 is_eol: 170 ;echo the character 171 FA60 20 B8 FA jsr EditorPutByte 172 FA63 30 D9 bmi read_error 173 174 ;swap to text screen context 175 FA65 20 3D F9 jsr EditorSwapToText 176 177 ;hide the cursor so we can scan text properly 178 FA68 20 F1 F8 jsr ScreenHideCursor 179 180 ;compute address 181 FA6B A2 00 ldx #0 182 FA6D 86 63 stx logcol 183 FA6F A4 6C ldy _start_y 184 FA71 84 54 sty rowcrs 185 FA73 20 77 F9 jsr ScreenComputeToAddr 186 187 FA76 A4 6D ldy _start_x 188 FA78 char_loop: 189 FA78 E6 63 inc logcol 190 FA7A B1 66 lda (toadr),y 191 FA7C F0 04 beq blank 192 FA7E A5 63 85 6B mva logcol bufcnt 193 FA82 blank: 194 FA82 C4 53 cpy rmargn 195 FA84 C8 iny 196 FA85 90 F1 bcc char_loop 197 FA87 20 C5 FD jsr EditorNextLineAddr 198 199 ;check if we're at the bottom of the screen 200 FA8A E6 54 inc rowcrs 201 FA8C A5 54 lda rowcrs 202 FA8E CD BF 02 cmp botscr 203 FA91 B0 0A bcs scan_scroll 204 205 ;check if we're at the end of the logical line 206 FA93 20 7E FD jsr EditorTestLogicalLineBit 207 FA96 D0 08 bne scan_done 208 209 FA98 A4 52 ldy lmargn 210 FA9A 4C 78 FA jmp char_loop 211 212 FA9D scan_scroll: 213 ;we're below the screen... need to scroll up 214 FA9D 20 CC FC jsr EditorDeleteLine0 215 216 FAA0 scan_done: 217 ;adjust BUFCNT so it is the number of chars to read (scanned + EOL) 218 FAA0 E6 6B inc bufcnt 219 220 ;mark this as the start of a new logical line, trimming off any extra 221 ;blank lines 222 FAA2 A5 54 lda rowcrs 223 FAA4 20 71 FD jsr EditorGetLogicalLineInfo 224 FAA7 19 B2 02 ora logmap,y 225 FAAA 99 B2 02 sta logmap,y 226 227 ;reset cursor to line start, but leave the cursor off 228 FAAD A6 6D 86 55 mvx _start_x colcrs 229 FAB1 A4 6C 84 54 mvy _start_y rowcrs 230 231 ;swap back to main context and exit successfully 232 FAB5 4C 9C FD jmp EditorSwapToScreen_Y1 233 .endp 234 235 ;========================================================================== 236 ; This routine must NOT write BUFADR -- doing so breaks the DLT flasher. 237 ; 238 ; Behavior notes: 239 ; - Ctrl+1 (suspend display) does not affect control codes handled only 240 ; by E:. In particular, EOL, move up/down/left/right, ESC, insert, and 241 ; delete are not affected by it. CLEAR on the other hand, is, because 242 ; it's handled by S:. 243 ; 244 FAB8 .proc EditorPutByte 245 ;open the text screen if it is not open already 246 FAB8 A4 57 ldy dindex 247 FABA F0 0C beq screenok 248 FABC AC BF 02 ldy botscr 249 FABF C0 04 cpy #4 250 FAC1 F0 05 beq screenok 251 252 FAC3 48 pha 253 FAC4 20 EE F3 jsr ScreenOpenGr0 254 FAC7 68 pla 255 FAC8 screenok: 256 257 ;swap to text context 258 FAC8 20 3D F9 jsr EditorSwapToText 259 260 ;hide the cursor -- this must be done before we suspend display on 261 ;Ctrl+1. 262 FACB 20 F1 F8 jsr ScreenHideCursor 263 264 ;save off character to free up acc 265 FACE A8 tay 266 267 ;Check if [esc] is active 268 ; 269 ;Note that the ASL trick relies on ESCFLG being $80 when set; this 270 ;is in fact guaranteed by the spec in the OS Manual, Appendix L, B26. 271 ; 272 FACF 0E A2 02 asl escflg ;test and clear escape flag 273 FAD2 B0 1E bcs not_special 274 275 ;check if this might be a special character 276 FAD4 29 1F and #$1f 277 FAD6 C9 1B cmp #$1b 278 FAD8 90 18 bcc not_special 279 280 ;might be special, but not EOL... search the special char table 281 FADA A2 0E ldx #special_code_tab_end-special_code_tab-1 282 FADC 98 tya 283 FADD 20 B7 FC jsr EditorIsSpecial 284 FAE0 D0 10 bne not_special 285 286 FAE2 special_found: 287 ;check if display of control codes is desired; if so, we need to ignore this 288 FAE2 AD FE 02 lda dspflg 289 FAE5 D0 0B bne not_special 290 291 ;jump to routine 292 FAE7 20 63 FC jsr dispatch 293 FAEA 20 C0 FC jsr EditorRecomputeCursorAddr 294 FAED 20 17 FE jsr ScreenShowCursorAndXitOK 295 FAF0 10 06 bpl xit2 ;!! - unconditional jump 296 297 FAF2 not_special: 298 ;ok, just put the char to the screen 299 FAF2 8C FB 02 sty atachr 300 FAF5 20 2A F6 jsr ScreenPutByte.not_clear 301 FAF8 xit2: 302 ;swap back to main context and exit 303 FAF8 4C 9E FD jmp EditorSwapToScreen 304 305 ;--------------- 306 FAFB special_code_tab: 307 FAFB 1B dta $1b 308 FAFC 1C dta $1c 309 FAFD 1D dta $1d 310 FAFE 1E dta $1e 311 FAFF 1F dta $1f 312 FB00 7D dta $7d 313 FB01 7E dta $7e 314 FB02 7F dta $7f 315 FB03 9C dta $9c 316 FB04 9D dta $9d 317 FB05 9E dta $9e 318 FB06 9F dta $9f 319 FB07 FD dta $fd 320 FB08 FE dta $fe 321 FB09 FF dta $ff 322 FB0A special_code_tab_end: 323 FB0A 9B dta $9b ;these are only for the K: check 324 FB0B 7C dta $7c 325 FB0C special_code_tab_end_2: 326 327 ;---------------- 328 329 FB0C special_dispatch_lo_tab: 330 FB0C 1A dta <(special_escape-1) 331 FB0D 23 dta <(special_up-1) 332 FB0E 2D dta <(special_down-1) 333 FB0F C1 dta <(special_left-1) 334 FB10 CE dta <(special_right-1) 335 FB11 20 dta <(special_clear-1) 336 FB12 48 dta <(special_backspace-1) 337 FB13 87 dta <(special_tab-1) 338 FB14 D7 dta <(special_delete_line-1) 339 FB15 DD dta <(special_insert_line-1) 340 FB16 74 dta <(special_clear_tab-1) 341 FB17 6C dta <(special_set_tab-1) 342 FB18 69 dta <(special_bell-1) 343 FB19 E4 dta <(special_delete_char-1) 344 FB1A F0 dta <(special_insert_char-1) 345 346 .if [((special_escape-1)^(special_insert_char-1))&$ff00] 347 .error 'Special character routines cross a page boundary: ',special_escape,'-',special_insert_char 348 .endif 349 350 ;--------------- 351 FB1B special_escape: 352 FB1B A9 80 8D A2 02 mva #$80 escflg 353 FB20 60 rts 354 355 ;--------------- 356 FB21 special_clear: 357 FB21 4C 4A F8 jmp ScreenClear 358 359 ;--------------- 360 FB24 special_up: 361 FB24 A6 54 ldx rowcrs 362 FB26 D0 03 bne isup2 363 FB28 AE BF 02 ldx botscr 364 FB2B isup2: 365 FB2B CA dex 366 FB2C 10 0A bpl vmoveexit 367 368 ;--------------- 369 FB2E special_down: 370 FB2E A6 54 ldx rowcrs 371 FB30 E8 inx 372 FB31 EC BF 02 cpx botscr 373 FB34 90 02 A2 00 scc:ldx #0 374 375 FB38 vmoveexit: 376 FB38 86 54 stx rowcrs 377 378 ;check if we have moved into a different logical line -- if so, 379 ;we need to reset the read row 380 FB3A 8A txa 381 FB3B 20 87 FD jsr EditorPhysToLogicalRow 382 FB3E C5 6C cmp bufstr 383 FB40 F0 06 beq moveexit 384 385 ;we switched rows -- reset read row 386 FB42 85 6C sta bufstr 387 FB44 A5 52 85 6D mva lmargn bufstr+1 388 389 FB48 moveexit: 390 FB48 60 rts 391 392 ;--------------- 393 FB49 special_backspace: 394 ;check if we are at the left column 395 FB49 A5 52 lda lmargn 396 FB4B C5 55 cmp colcrs 397 FB4D B0 0B bcs sbks_wrap 398 399 ;nope, we can just back up 400 FB4F C6 55 dec colcrs 401 402 ;recompute pos and clear character 403 FB51 sbks_recomp: 404 FB51 20 C0 FC jsr EditorRecomputeCursorAddr 405 FB54 A0 00 ldy #0 406 FB56 98 tya 407 FB57 91 5E sta (oldadr),y 408 FB59 sbks_xit: 409 FB59 60 rts 410 411 FB5A sbks_wrap: 412 ;check if we're at the start of the logical line 413 FB5A A5 54 lda rowcrs 414 FB5C 20 7E FD jsr EditorTestLogicalLineBit 415 FB5F D0 F8 bne sbks_xit 416 417 ;no, so we need to wrap to the right column of the prev line... 418 FB61 C6 54 dec rowcrs 419 FB63 A5 53 lda rmargn 420 FB65 85 55 sta colcrs 421 422 ;recompute everything and exit 423 FB67 4C 51 FB jmp sbks_recomp 424 425 ;---------------- 426 FB6A special_bell: 427 FB6A 4C 97 FD jmp EditorBell 428 429 ;---------------- 430 FB6D special_set_tab: 431 FB6D 20 81 FB jsr special_common_tab 432 FB70 1D A3 02 ora tabmap,x 433 FB73 D0 08 bne special_common_exit_tab 434 435 FB75 special_clear_tab: 436 FB75 20 81 FB jsr special_common_tab 437 FB78 49 FF eor #$ff 438 FB7A 3D A3 02 and tabmap,x 439 FB7D special_common_exit_tab: 440 FB7D 9D A3 02 sta tabmap,x 441 FB80 60 rts 442 443 FB81 special_common_tab: 444 FB81 20 A7 FD jsr EditorGetLogicalColumn 445 FB84 A8 tay 446 FB85 4C B6 FD jmp EditorSetupTabIndex 447 448 ;-------------------------------------------------------------------------- 449 ; Tab behavior: 450 ; - Moves cursor to the next tab position within the logical line. 451 ; - If there are no more tabs, moves cursor to beginning of next line. 452 ; This may cause a scroll. 453 ; - Tab does NOT adjust the read row. 454 ; 455 FB88 special_tab: 456 FB88 20 A7 FD jsr EditorGetLogicalColumn 457 FB8B A8 tay 458 FB8C 8A txa 459 FB8D 38 sec 460 FB8E 65 54 adc rowcrs 461 FB90 85 54 sta rowcrs 462 463 ;scan forward until we find the next bit set, or we hit position 120 464 FB92 tab_scan_loop: 465 FB92 C8 iny 466 FB93 C0 78 cpy #120 467 FB95 B0 08 bcs tab_found 468 FB97 20 B6 FD jsr EditorSetupTabIndex 469 FB9A 3D A3 02 and tabmap,x 470 FB9D F0 F3 beq tab_scan_loop 471 FB9F tab_found: 472 FB9F 84 55 sty colcrs 473 FBA1 tab_adjust_row: 474 FBA1 A5 55 lda colcrs 475 FBA3 38 sec 476 FBA4 E9 28 sbc #40 ;subtract a row worth of columns 477 FBA6 90 19 bcc tab_adjust_done ;exit if <40 478 FBA8 85 55 sta colcrs 479 FBAA E6 54 inc rowcrs ;next row 480 FBAC A5 54 lda rowcrs ; 481 FBAE CD BF 02 cmp botscr ;check if we're below the screen 482 FBB1 B0 07 bcs tab_adjust_scroll ;if so, do a scroll 483 FBB3 20 7E FD jsr EditorTestLogicalLineBit ;check if we're on a new log line 484 FBB6 F0 E9 beq tab_adjust_row ;if not, keep adjusting 485 FBB8 10 03 bpl tab_adjust_left ;position at beginning of new line 486 487 FBBA tab_adjust_scroll: 488 FBBA 20 CC FC jsr EditorDeleteLine0 489 FBBD tab_adjust_left: 490 FBBD hmove_to_lmargn: 491 ;move to left margin 492 FBBD A6 52 ldx lmargn 493 FBBF hmove_to_x: 494 FBBF 86 55 stx colcrs 495 FBC1 tab_adjust_done: 496 FBC1 60 rts 497 498 ;-------------------------------------------------------------------------- 499 FBC2 special_left: 500 FBC2 A6 55 ldx colcrs 501 FBC4 F0 05 beq slft_to_right 502 FBC6 CA dex 503 FBC7 E4 52 cpx lmargn 504 FBC9 B0 F4 bcs hmove_to_x 505 506 ;move to right margin 507 FBCB slft_to_right: 508 FBCB A6 53 ldx rmargn 509 FBCD 90 F0 bcc hmove_to_x 510 511 ;-------------------------------------------------------------------------- 512 FBCF special_right: 513 FBCF A6 55 ldx colcrs 514 FBD1 E4 53 cpx rmargn 515 FBD3 B0 E8 bcs hmove_to_lmargn 516 517 ;right one char 518 FBD5 E6 55 inc colcrs 519 FBD7 60 rts 520 521 ;-------------------------------------------------------------------------- 522 ; Delete line behavior: 523 ; - The entire logical line that the cursor is in is deleted. 524 ; - The cursor is positioned at the beginning of the next logical line. 525 ; 526 FBD8 special_delete_line: 527 ;delete current logical line 528 FBD8 20 85 FD jsr EditorGetCurLogicalRow 529 FBDB 4C CE FC jmp EditorDeleteLine 530 531 ;---------------- 532 FBDE special_insert_line: 533 ;insert a new logical line at this point; note that this may split 534 ;the current line 535 FBDE 38 sec 536 FBDF 20 8E F8 jsr ScreenInsertLine 537 FBE2 4C BD FB jmp tab_adjust_left 538 539 ;-------------------------------------------------------------------------- 540 ; Delete character behavior: 541 ; - Erases the current character and drags in characters from the 542 ; remainder of the logical line, excluding the margins. 543 ; - If the last physical line is blank and not the only physical line in 544 ; the logical line, it is deleted and the logical line is shortened. 545 ; Only one line is removed even if the last two lines are blank. The 546 ; cursor does not move when this happens and may be shifted into the 547 ; next logical line. This also does not change the input line! 548 ; 549 FBE5 special_delete_char: 550 ;compute base address of current row (not char) 551 FBE5 A4 54 ldy rowcrs 552 FBE7 84 51 sty hold1 553 FBE9 20 75 F9 jsr ScreenComputeToAddrX0 554 555 ;begin shifting in the first column at the current pos 556 FBEC A4 55 ldy colcrs 557 558 ;delete chars to end 559 FBEE 4C 7C FC jmp delete_shift_loop_entry 560 561 ;-------------------------------------------------------------------------- 562 ; Insert character behavior: 563 ; - Inserts a blank at the current position and shifts characters forward 564 ; within the margins. 565 ; - If the character shifted out of the end of the logical line is non- 566 ; blank, the logical line will be extended if possible. This can cause 567 ; a scroll. If the logical line is already three rows, the last 568 ; character is lost. 569 ; 570 FBF1 special_insert_char: 571 ;get logical line start 572 FBF1 20 85 FD jsr EditorGetCurLogicalRow 573 574 ;compute line at which we cannot add another physical line 575 FBF4 18 69 03 add #3 576 FBF7 85 76 sta deltar 577 578 ;compute address of row 579 FBF9 A4 54 ldy rowcrs 580 FBFB 84 51 sty hold1 581 FBFD 20 75 F9 jsr ScreenComputeToAddrX0 582 583 FC00 A4 55 ldy colcrs ;end shift at current column 584 FC02 A2 00 ldx #0 ;insert blank character at start 585 FC04 F0 04 beq insert_line_loop_entry 586 587 FC06 insert_line_loop: 588 FC06 A4 52 ldy lmargn ;end shift at left column 589 FC08 A6 50 ldx tmpchr ;character to shift in (from last line) 590 591 FC0A insert_line_loop_entry: 592 FC0A 84 65 sty adress+1 ;stash shift origin 593 FC0C A4 53 ldy rmargn ;begin shift at right column 594 FC0E B1 66 lda (toadr),y ;get character being shifted out 595 FC10 85 50 sta tmpchr ;save it off to later shift in on the next row 596 FC12 insert_shift_loop: 597 FC12 88 dey 598 FC13 B1 66 lda (toadr),y 599 FC15 C8 iny 600 FC16 91 66 sta (toadr),y 601 FC18 88 dey 602 FC19 C4 65 cpy adress+1 603 FC1B D0 F5 bne insert_shift_loop 604 605 ;put character shifted out from previous line into beginning of this one 606 FC1D 8A txa 607 FC1E 91 66 sta (toadr),y 608 609 ;next row 610 FC20 E6 51 inc hold1 611 612 FC22 20 C5 FD jsr EditorNextLineAddr 613 614 ;check if we're at the end of the logical line 615 FC25 A5 51 lda hold1 616 FC27 CD BF 02 cmp botscr 617 FC2A B0 05 bcs insert_crossed_lline 618 FC2C 20 7E FD jsr EditorTestLogicalLineBit 619 FC2F F0 D5 beq insert_line_loop 620 FC31 insert_crossed_lline: 621 622 ;check if we shifted out a non-blank character 623 FC31 A5 50 lda tmpchr 624 FC33 F0 2D beq insert_done 625 626 ;save current row 627 FC35 A5 54 lda rowcrs 628 FC37 48 pha 629 630 ;check if the logical line is already 3 rows -- if so, we cannot extend and 631 ;the last char goes into the bit bucket, but we still must scroll (!) 632 FC38 A6 51 ldx hold1 633 FC3A E4 76 cpx deltar 634 FC3C 08 php 635 636 ;move to the bottom line +1; we use ROWCRS so it stays updated with the scrolling 637 FC3D 86 54 stx rowcrs 638 639 ;check if we are at the bottom of the screen; if so we must scroll 640 FC3F A9 00 lda #0 641 FC41 85 76 sta deltar 642 643 FC43 EC BF 02 cpx botscr 644 FC46 90 03 bcc insert_no_scroll 645 646 ;scroll the screen 647 FC48 20 CC FC jsr EditorDeleteLine0 648 649 FC4B insert_no_scroll: 650 ;if we can't extend, we are done 651 FC4B 28 plp 652 FC4C B0 0E bcs insert_cant_extend 653 654 ;just insert a blank line at the end of this logical row to extend it 655 FC4E 20 8D F8 jsr ScreenInsertPhysLine 656 657 ;restore shifted character and put it in place 658 FC51 A4 54 ldy rowcrs 659 FC53 20 75 F9 jsr ScreenComputeToAddrX0 660 FC56 A5 50 lda tmpchr 661 FC58 A4 52 ldy lmargn 662 FC5A 91 66 sta (toadr),y 663 FC5C insert_cant_extend: 664 665 ;restore cursor row, adjusting for any scroll 666 FC5C 68 pla 667 FC5D 38 sec 668 FC5E E5 76 sbc deltar 669 FC60 85 54 sta rowcrs 670 671 FC62 insert_done: 672 FC62 60 rts 673 674 ;--------------------------------- 675 FC63 dispatch: 676 FC63 A9 FB lda #>special_escape 677 FC65 48 pha 678 FC66 BD 0C FB lda special_dispatch_lo_tab,x 679 FC69 48 pha 680 FC6A 60 rts 681 682 ;--------------------------------- 683 FC6B delete_line_loop: 684 ;copy first character into right margin of previous row 685 FC6B A4 52 ldy lmargn 686 FC6D B1 66 lda (toadr),y 687 FC6F A4 53 ldy rmargn 688 FC71 91 68 sta (frmadr),y 689 690 ;start shifting new row at left margin 691 FC73 A4 52 ldy lmargn 692 FC75 delete_shift_loop: 693 FC75 C8 iny 694 FC76 B1 66 lda (toadr),y 695 FC78 88 dey 696 FC79 91 66 sta (toadr),y 697 FC7B C8 iny 698 FC7C delete_shift_loop_entry: 699 FC7C C4 53 cpy rmargn 700 FC7E D0 F5 bne delete_shift_loop 701 702 ;next line 703 FC80 20 C5 FD jsr EditorNextLineAddr 704 705 ;check if the next row is a logical line start 706 FC83 A6 51 ldx hold1 707 FC85 E8 inx 708 FC86 EC BF 02 cpx botscr 709 FC89 B0 08 bcs delete_stop_shifting 710 FC8B 86 51 stx hold1 711 FC8D 8A txa 712 FC8E 20 7E FD jsr EditorTestLogicalLineBit 713 714 ;keep going if not 715 FC91 F0 D8 beq delete_line_loop 716 717 FC93 delete_stop_shifting: 718 ;blank the last character of the last line 719 FC93 A4 53 ldy rmargn 720 FC95 A9 00 lda #0 721 FC97 91 68 sta (frmadr),y 722 723 ;check if the last line is blank 724 FC99 delete_blank_test_loop: 725 FC99 B1 68 lda (frmadr),y 726 FC9B D0 19 bne delete_not_blank 727 FC9D 88 dey 728 FC9E C4 52 cpy lmargn 729 FCA0 B0 F7 bcs delete_blank_test_loop 730 731 ;the last line is blank... check if it is a logical line start 732 FCA2 C6 51 dec hold1 733 FCA4 A5 51 lda hold1 734 FCA6 20 7E FD jsr EditorTestLogicalLineBit 735 736 ;skip if so -- we can't delete the entire logical line 737 FCA9 D0 0B bne delete_not_blank 738 739 ;delete this physical line... however, do not move the cursor and 740 ;do not change the read line even if the cursor hops to a new one 741 FCAB A5 55 lda colcrs 742 FCAD 48 pha 743 FCAE A5 51 lda hold1 744 FCB0 20 CE FC jsr EditorDeleteLine 745 FCB3 68 pla 746 FCB4 85 55 sta colcrs 747 748 FCB6 delete_not_blank: 749 ;re-show cursor and exit 750 FCB6 60 rts 751 752 .endp 753 754 ;========================================================================== 755 FCB7 .proc EditorIsSpecial 756 FCB7 special_binsearch: 757 FCB7 DD FB FA cmp EditorPutByte.special_code_tab,x 758 FCBA F0 03 beq special_found 759 FCBC CA dex 760 FCBD 10 F8 bpl special_binsearch 761 FCBF special_found: 762 FCBF 60 rts 763 .endp 764 765 ;========================================================================== 766 FCC0 .proc EditorRecomputeCursorAddr 767 FCC0 A6 55 ldx colcrs 768 FCC2 A4 54 ldy rowcrs 769 FCC4 20 5F F9 jsr ScreenComputeAddr 770 FCC7 86 5E stx oldadr 771 FCC9 85 5F sta oldadr+1 772 FCCB 60 rts 773 .endp 774 775 ;========================================================================== 776 ; Delete a logical line on screen, and scroll the remainder of the screen 777 ; upward. 778 ; 779 ; Inputs: 780 ; A = physical line row to delete 781 ; 782 ; Outputs: 783 ; DELTAR = number of lines scrolled 784 ; 785 = FCCE EditorDeleteLine = EditorDeleteLine0.use_line 786 FCCC .proc EditorDeleteLine0 787 FCCC A9 00 lda #0 788 FCCE use_line: 789 FCCE 85 51 sta hold1 790 FCD0 A2 00 ldx #0 791 FCD2 86 76 stx deltar 792 793 FCD4 scroll_loop: 794 ;compute base address and set that as destination 795 FCD4 A4 51 ldy hold1 796 797 .if _KERNEL_XLXE 798 FCD6 38 sec 799 FCD7 D0 21 bne nofine 800 FCD9 AE 6E 02 ldx fine 801 FCDC F0 1C beq nofine 802 FCDE A2 00 ldx #0 803 FCE0 xloop: 804 FCE0 A5 14 lda rtclok+2 805 FCE2 C5 14 F0 FC cmp:req rtclok+2 806 FCE6 E8 inx 807 FCE7 8E 05 D4 stx vscrol 808 FCEA E0 07 cpx #7 809 FCEC D0 F2 bne xloop 810 FCEE A9 10 lda #32/2 811 FCF0 CD 0B D4 90 FB cmp:rcc vcount 812 FCF5 CD 0B D4 B0 FB cmp:rcs vcount 813 FCFA nofine: 814 FCFA 08 php ;C=0 for fine scroll, C=1 for coarse scroll 815 .endif 816 817 ;set TOADR to the line to be deleted 818 FCFB 20 75 F9 jsr ScreenComputeToAddrX0 819 820 FCFE A6 51 ldx hold1 821 FD00 10 0C bpl line_loop_start 822 823 FD02 line_loop: 824 ;bump line: FRMADR <- TOADR, TOADR += 40 825 FD02 20 C5 FD jsr EditorNextLineAddr 826 827 ;move line -- note that we are copying backwards (TOADR to FRMADR)! 828 FD05 A0 27 ldy #39 829 FD07 B1 66 91 68 88 10 + mva:rpl (toadr),y (frmadr),y- 830 831 FD0E line_loop_start: 832 FD0E E8 inx 833 FD0F EC BF 02 cpx botscr 834 FD12 D0 EE bne line_loop 835 836 ;clear the last line 837 FD14 A0 27 ldy #39 838 FD16 A9 00 lda #0 839 FD18 91 66 88 10 FB sta:rpl (toadr),y- 840 841 .if _KERNEL_XLXE 842 FD1D 28 plp 843 FD1E B0 03 bcs nofinescroll2 844 FD20 8D 05 D4 sta vscrol 845 FD23 nofinescroll2: 846 .endif 847 848 FD23 20 58 FD jsr adjust_lines 849 850 ;delete bits out of the logical mask until we get to the next 851 ;logical line, computing the number of lines to scroll 852 FD26 A5 51 lda hold1 853 FD28 20 71 FD jsr EditorGetLogicalLineInfo 854 FD2B BE 55 FD ldx update_table,y ;get number of masks to shift 855 FD2E 38 sec ;setup to add a new logical line at the end 856 FD2F F0 09 beq do_mask ;jump to masking if we're on byte 2 857 FD31 2E B4 02 rol logmap+2 ;shift byte 2 858 FD34 CA dex ; 859 FD35 F0 03 beq do_mask ;jump to masking if we're on byte 1 860 FD37 2E B3 02 rol logmap+1 ;shift byte 1 861 FD3A do_mask: 862 FD3A 85 64 sta adress ;stash mask 863 FD3C 49 FF eor #$ff ;invert mask 864 FD3E 39 B2 02 and logmap,y ;kill target bit 865 FD41 85 65 sta adress+1 ;stash modified mask 866 FD43 C6 64 dec adress ;form mask for LSBs below bit 867 FD45 25 64 and adress ;isolate those bits 868 FD47 65 65 adc adress+1 ;shift those up and the bit from the next byte in 869 FD49 99 B2 02 sta logmap,y ;write to logmap 870 871 FD4C E6 76 inc deltar ;increment line count 872 FD4E E6 64 inc adress ;revert mask 873 FD50 24 64 bit adress ;test if we still have a logical line 874 875 ;loop back if we need to delete more physical lines 876 FD52 F0 80 beq scroll_loop 877 878 ;all done 879 FD54 60 rts 880 881 FD55 update_table: 882 FD55 02 01 00 dta 2,1,0 883 884 FD58 adjust_lines: 885 FD58 A5 52 lda lmargn ;prep for line adjustments 886 887 ;adjust the read row if it is affected by the deletion 888 FD5A A2 6C ldx # $ff-$fd) 1007 ; 1008 FDA7 .proc EditorGetLogicalColumn 1009 ;get starting row of logical line 1010 FDA7 A5 54 lda rowcrs 1011 FDA9 20 87 FD jsr EditorPhysToLogicalRow 1012 1013 ;subtract off current row 1014 FDAC 18 clc 1015 FDAD E5 54 sbc rowcrs 1016 FDAF AA tax 1017 1018 ;multiply negated difference by 40 1019 FDB0 BD DB FC lda EditorLineLengthTab-$fc,x 1020 1021 ;add in physical column 1022 FDB3 65 55 adc colcrs 1023 FDB5 60 rts 1024 .endp 1025 1026 ;========================================================================== 1027 FDB6 .proc EditorSetupTabIndex 1028 FDB6 98 tya 1029 FDB7 29 07 and #7 1030 FDB9 AA tax 1031 FDBA BD C1 E4 lda ReversedBitMasks,x 1032 FDBD 48 pha 1033 FDBE 98 tya 1034 FDBF 4A lsr 1035 FDC0 4A lsr 1036 FDC1 4A lsr 1037 FDC2 AA tax 1038 FDC3 68 pla 1039 FDC4 60 rts 1040 .endp 1041 1042 ;========================================================================== 1043 ; Copy TOADR to FRMADR and add 40 to TOADR. 1044 ; 1045 FDC5 .proc EditorNextLineAddr 1046 FDC5 A5 66 lda toadr 1047 FDC7 85 68 sta frmadr 1048 FDC9 18 69 28 add #40 1049 FDCC 85 66 sta toadr 1050 FDCE A5 67 lda toadr+1 1051 FDD0 85 69 sta frmadr+1 1052 FDD2 69 00 adc #0 1053 FDD4 85 67 sta toadr+1 1054 FDD6 60 rts 1055 .endp 1056 1057 ;========================================================================== 1058 FDD7 .proc EditorLineLengthTab 1059 FDD7 78 50 28 00 dta 120, 80, 40, 0 1060 .endp 1061 271 272 .ifdef _KERNEL_816 273 icl 'screenext816.s' 274 .else 275 FDDB icl 'screenext.s' Source: source/Shared/screenext.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Screen Handler extension routines 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 FDDB ScreenEncodingOffsetTable: 12 FDDB 00 dta $00 ;4-bit 13 FDDC 10 dta $10 ;2-bit 14 FDDD 14 dta $14 ;1-bit 15 16 .if !_KERNEL_XLXE 17 _SCREEN_TABLES_3 18 .endif 19 20 ;========================================================================== 21 ; ScreenFineScrollDLI 22 ; 23 ; This DLI routine is used to set the PF1 color to PF2 to kill junk that 24 ; would appear on the extra line added with vertical scrolling. 25 ; 26 .if _KERNEL_XLXE 27 FDDE .proc ScreenFineScrollDLI 28 FDDE 48 pha 29 FDDF AD C6 02 lda color2 30 FDE2 45 4F eor colrsh 31 FDE4 25 4E and drkmsk 32 FDE6 8D 17 D0 sta colpf1 33 FDE9 68 pla 34 FDEA 40 rti 35 .endp 36 .endif 37 38 ;========================================================================== 39 ; ScreenResetLogicalLineMap 40 ; 41 ; Marks all lines as the start of logical lines. 42 ; 43 ; Exit: 44 ; X = 0 45 ; 46 FDEB .proc ScreenResetLogicalLineMap 47 FDEB A2 FF ldx #$ff 48 FDED 8E B2 02 stx logmap 49 FDF0 8E B3 02 stx logmap+1 50 FDF3 8E B4 02 stx logmap+2 51 52 ;reset line read position 53 FDF6 E8 inx 54 FDF7 86 6C stx bufstr 55 FDF9 A5 52 lda lmargn 56 FDFB 85 6D sta bufstr+1 57 58 ;note - X=0 relied on here by EditorOpen 59 FDFD 60 rts 60 .endp 61 62 ;========================================================================== 63 ; ScreenSetLastPosition 64 ; 65 ; Copies COLCRS/ROWCRS to OLDCOL/OLDROW. 66 ; 67 FDFE .proc ScreenSetLastPosition 68 FDFE A2 02 ldx #2 69 FE00 loop: 70 FE00 B5 54 lda rowcrs,x 71 FE02 95 5A sta oldrow,x 72 FE04 CA dex 73 FE05 10 F9 bpl loop 74 FE07 60 rts 75 .endp 76 77 ;========================================================================== 78 ; ScreenAdvancePosMode0 79 ; 80 ; Advance to the next cursor position in reading order, for mode 0. 81 ; 82 ; Exit: 83 ; C = 1 if no wrap, 0 if wrapped 84 ; 85 ; Modified: 86 ; X 87 ; 88 ; Preserved: 89 ; A 90 ; 91 FE08 .proc ScreenAdvancePosMode0 92 FE08 E6 55 inc colcrs 93 FE0A A6 53 ldx rmargn 94 FE0C E4 55 cpx colcrs 95 FE0E B0 06 bcs post_wrap 96 FE10 A6 52 ldx lmargn 97 FE12 86 55 stx colcrs 98 FE14 E6 54 inc rowcrs 99 FE16 post_wrap: 100 FE16 60 rts 101 .endp 102 103 104 ;========================================================================== 105 ; Output: 106 ; Y=1 for convenience 107 ; 108 ; (OLDADR) must point to the cursor location with OLDCHR even if the cursor 109 ; is hidden. This is required by SDX QUICKED.SYS, which always restores the 110 ; cursor. 111 ; 112 FE17 .proc ScreenShowCursorAndXitOK 113 ;;##ASSERT dw(oldadr) >= dw(savmsc) 114 ;check if the cursor is enabled 115 FE17 A0 00 ldy #0 116 FE19 B1 5E lda (oldadr),y 117 FE1B 85 5D sta oldchr 118 FE1D AC F0 02 ldy crsinh 119 FE20 D0 04 bne cursor_inhibited 120 FE22 49 80 eor #$80 121 FE24 91 5E sta (oldadr),y 122 FE26 cursor_inhibited: 123 FE26 C8 iny 124 FE27 60 rts 125 .endp 126 127 ;========================================================================== 128 ; Close screen (S:). 129 ; 130 ; This is a no-op in OS-B mode. In XL/XE mode, it reopens the device in 131 ; Gr.0 if fine scrolling is on, since this is necessary to clear the DLI. 132 ; This happens even if S: doesn't correspond to the text window. Only 133 ; the high bit of FINE is checked. 134 ; 135 .if !_KERNEL_XLXE 136 ScreenClose = CIOExitSuccess 137 .else 138 FE28 .proc ScreenClose 139 FE28 2C 6E 02 bit fine 140 FE2B 30 03 bmi disable_fine_scrolling 141 142 FE2D A0 01 ldy #1 143 FE2F 60 rts 144 145 FE30 disable_fine_scrolling: 146 ;turn off DLI 147 FE30 A9 40 8D 0E D4 mva #$40 nmien 148 149 ;restore vdslst 150 FE35 A2 55 ldx #IntExitHandler_None 152 FE39 20 A0 F5 jsr ScreenOpenGr0.write_vdslst 153 154 FE3C 4C EE F3 jmp ScreenOpenGr0 155 .endp 156 .endif 157 158 ;========================================================================== 159 .if !_KERNEL_XLXE 160 _SCREEN_TABLES_2 161 .endif 276 .endif 277 278 FE3F _KERNEL_REPORT_MODULE_SIZE 'Display routines', 0 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'Display routines' 1 $FE3F -> $0ADF($0000) Display routines 3 = FE3F .def ?@_kernel_lastpt = * Source: source/main.xasm 279 280 .ifdef _KERNEL_816 281 icl 'keyboard816.s' 282 .else 283 FE3F icl 'keyboard.s' Source: source/Shared/keyboard.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Keyboard Handler 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 ;========================================================================== 11 ; Oddly, the keyboard IRQs are not enabled from the keyboard init 12 ; routine. It's done by the Display Handler instead on open. 13 ; 14 FE3F .proc KeyboardInit 15 FE3F A2 FF ldx #$ff 16 FE41 8E FC 02 stx ch 17 FE44 8E F2 02 stx ch1 18 FE47 E8 inx 19 FE48 8E F1 02 stx keydel 20 FE4B 8E B6 02 stx invflg 21 22 ;turn on shift lock 23 FE4E A9 40 8D BE 02 mva #$40 shflok 24 25 ;set keyboard definition table pointer 26 .if _KERNEL_XLXE 27 FE53 A9 1D 85 79 A9 FF + mwa #KeyCodeToATASCIITable keydef 28 .endif 29 FE5B 60 rts 30 .endp 31 32 = E4C9 KeyboardOpen = CIOExitSuccess 33 = E4C9 KeyboardClose = CIOExitSuccess 34 35 ;========================================================================== 36 ; K: GET BYTE handler. 37 ; 38 ; Behavior: 39 ; - Exits with a Break error when break key is pressed. 40 ; - Ctrl-1 does not suspend input here (it is handled by S:/E:). 41 ; - Ctrl-3 returns an EOF error. 42 ; - Caps Lock sets caps mode on OS-A/B depending on Ctrl and Shift key 43 ; state. On the XL/XE OS, pressing Caps Lock alone will enable shift 44 ; lock if no lock is enabled and disable it otherwise. 45 ; - Shift/Control lock is applied by K:, but only on alpha keys. 46 ; - Inverse mode is also applied by K:. Control characters are excluded: 47 ; 1B-1F/7C-7F/9B-9F/FD-FF. 48 ; - Any Ctrl+Shift key code (>=$C0) produces a key click but is otherwise 49 ; ignored. 50 ; 51 FE5C .nowarn .proc _KeyboardGetByte 52 FE5C toggle_shift: 53 .if _KERNEL_XLXE 54 ;Caps Lock without Shift or Control is a toggle on the XL/XE line: 55 ; None -> Shifted 56 ; Shifted, Control -> None 57 FE5C AE BE 02 ldx shflok 58 FE5F D0 02 bne caps_off 59 FE61 A0 40 ldy #$40 60 .endif 61 FE63 shift_ctrl_on: 62 FE63 caps_off: 63 FE63 98 tya 64 FE64 29 C0 and #$c0 65 FE66 write_shflok: 66 FE66 8D BE 02 sta shflok 67 68 = FE69 .def :KeyboardGetByte 69 FE69 waitForChar: 70 FE69 A2 FF ldx #$ff 71 FE6B waitForChar2: 72 FE6B A5 11 lda brkkey 73 FE6D F0 57 beq isBreak 74 FE6F AD FC 02 lda ch 75 FE72 C9 FF cmp #$ff 76 FE74 F0 F5 beq waitForChar2 77 78 ;invalidate char 79 FE76 8E FC 02 stx ch 80 81 ;do keyboard click (we do this even for ignored ctrl+shift+keys) 82 FE79 A0 0C ldy #12 83 FE7B 20 CC E4 jsr Bell 84 85 ;ignore char if both ctrl and shift are pressed 86 FE7E C9 C0 cmp #$c0 87 FE80 B0 E7 bcs waitForChar 88 89 ;trap Ctrl-3 and return EOF 90 FE82 C9 9A cmp #$9a 91 FE84 F0 45 beq isCtrl3 92 93 ;translate char 94 FE86 A8 tay 95 96 .if _KERNEL_XLXE 97 FE87 B1 79 lda (keydef),y 98 .else 99 lda KeyCodeToATASCIITable,y 100 .endif 101 102 ;handle special keys (see keytable.s) 103 FE89 10 0E bpl valid_key 104 FE8B C9 81 cmp #$81 105 FE8D 90 DA bcc waitForChar ;$80 - invalid 106 FE8F F0 2B beq isInverse ;$81 - inverse video 107 FE91 C9 83 cmp #$83 108 FE93 90 C7 bcc toggle_shift ;$82 - caps lock 109 FE95 C9 85 cmp #$85 110 FE97 90 CA bcc shift_ctrl_on ;$83 - shift caps lock / $84 - ctrl caps lock 111 112 FE99 valid_key: 113 ;check for alpha key 114 FE99 C9 61 cmp #'a' 115 FE9B 90 0F bcc notAlpha 116 FE9D C9 7B cmp #'z'+1 117 FE9F B0 0B bcs notAlpha 118 119 ;check for shift/control lock 120 FEA1 2C BE 02 bit shflok 121 FEA4 70 04 bvs doShiftLock 122 FEA6 10 04 bpl notAlpha 123 124 ;do control lock logic 125 FEA8 29 1F and #$1f 126 127 FEAA doShiftLock: 128 FEAA 29 DF and #$df 129 130 FEAC notAlpha: 131 ;check if we should apply inverse flag -- special characters are excluded 132 FEAC A2 10 ldx #EditorPutByte.special_code_tab_end_2-EditorPutByte.special_code_tab-1 133 FEAE 20 B7 FC jsr EditorIsSpecial 134 FEB1 F0 03 beq skip_inverse 135 136 ;apply inverse flag 137 FEB3 4D B6 02 eor invflg 138 FEB6 skip_inverse: 139 140 ;return char 141 FEB6 8D FB 02 sta atachr ;required or CON.SYS (SDX 4.46) breaks 142 FEB9 A0 01 ldy #1 143 FEBB 60 rts 144 145 FEBC isInverse: 146 FEBC AD B6 02 lda invflg 147 FEBF 49 80 eor #$80 148 FEC1 8D B6 02 sta invflg 149 FEC4 B0 A3 bcs waitForChar ;!! - unconditional 150 151 FEC6 isBreak: 152 FEC6 86 11 stx brkkey 153 FEC8 A0 80 ldy #CIOStatBreak 154 FECA 60 rts 155 156 FECB isCtrl3: 157 FECB A0 88 ldy #CIOStatEndOfFile 158 FECD 60 rts 159 .endp 160 161 ;============================================================================== 162 = E4CB KeyboardPutByte = CIOExitNotSupported 163 = E4C9 KeyboardGetStatus = CIOExitSuccess 164 = E4CB KeyboardSpecial = CIOExitNotSupported 165 166 ;============================================================================== 167 ; Keyboard IRQ 168 ; 169 ; HELP button ($11, $51, and $91): 170 ; - Affects SRTIMR, ATRACT, KEYDEL, and HELPFG 171 ; - Does NOT affect CH, CH1 172 ; 173 FECE .proc KeyboardIRQ 174 ;reset software repeat timer 175 .if _KERNEL_XLXE 176 FECE AD D9 02 8D 2B 02 mva krpdel srtimr 177 .else 178 mva #$30 srtimr 179 .endif 180 181 ;read new key 182 FED4 AD 09 D2 lda kbcode 183 184 .if _KERNEL_XLXE 185 ;check for HELP 186 FED7 29 3F and #$3f 187 FED9 C9 11 cmp #$11 188 FEDB D0 05 bne not_help 189 FEDD 8D DC 02 sta helpfg 190 FEE0 F0 1E beq xit2 191 192 FEE2 not_help: 193 FEE2 AD 09 D2 lda kbcode 194 .endif 195 196 ;check if it is the same as the prev key 197 FEE5 CD F2 02 cmp ch1 198 FEE8 D0 08 bne debounced 199 200 ;reject key if debounce timer is still running 201 FEEA AD F1 02 lda keydel 202 FEED D0 16 bne xit 203 FEEF AD F2 02 lda ch1 204 FEF2 debounced: 205 206 ;check for Ctrl+1 to toggle display activity 207 FEF2 C9 9F cmp #$9f 208 FEF4 F0 11 beq is_suspend 209 210 ;store key 211 FEF6 8D FC 02 sta ch 212 FEF9 8D F2 02 sta ch1 213 214 ;reset attract 215 FEFC A9 00 85 4D mva #0 atract 216 217 FF00 xit2: 218 ;reset key delay 219 FF00 A9 03 8D F1 02 mva #3 keydel 220 221 FF05 xit: 222 ;all done 223 FF05 68 pla 224 FF06 40 rti 225 226 FF07 is_suspend: 227 ;toggle stop/start flag 228 FF07 AD FF 02 lda ssflag 229 FF0A 49 FF eor #$ff 230 FF0C 8D FF 02 sta ssflag 231 FF0F B0 EF bcs xit2 ;!! carry set from cmp #$9f! 232 .endp 233 234 ;============================================================================== 235 FF11 .proc KeyboardBreakIRQ 236 FF11 A9 00 85 11 mva #0 brkkey 237 238 ;need to clear the suspend flag as BREAK automatically nukes a pending Ctrl+1 239 FF15 8D FF 02 sta ssflag 240 241 ;interestingly, the default break handler forces the cursor back on. 242 FF18 8D F0 02 sta crsinh 243 244 FF1B 68 pla 245 FF1C 40 rti 246 .endp 284 .endif 285 286 FF1D icl 'keytable.s' Source: source/Shared/keytable.s 1 ; Altirra - Atari 800/800XL/5200 emulator 2 ; Modular Kernel ROM - Keyboard Scan Code Table 3 ; Copyright (C) 2008-2016 Avery Lee 4 ; 5 ; Copying and distribution of this file, with or without modification, 6 ; are permitted in any medium without royalty provided the copyright 7 ; notice and this notice are preserved. This file is offered as-is, 8 ; without any warranty. 9 10 FF1D KeyCodeToATASCIITable: 11 ;Special codes in this table (values important for compat): 12 ; $80 - invalid key 13 ; $81 - inverse video 14 ; $82 - caps lock 15 ; $83 - shift caps lock 16 ; $84 - control caps lock 17 18 ;lowercase 19 FF1D 6C 6A 3B 80 80 6B + dta $6C, $6A, $3B, $80, $80, $6B, $2B, $2A 20 FF25 6F 80 70 75 9B 69 + dta $6F, $80, $70, $75, $9B, $69, $2D, $3D 21 FF2D 76 80 63 80 80 62 + dta $76, $80, $63, $80, $80, $62, $78, $7A 22 FF35 34 80 33 36 1B 35 + dta $34, $80, $33, $36, $1B, $35, $32, $31 23 FF3D 2C 20 2E 6E 80 6D + dta $2C, $20, $2E, $6E, $80, $6D, $2F, $81 24 FF45 72 80 65 79 7F 74 + dta $72, $80, $65, $79, $7F, $74, $77, $71 25 FF4D 39 80 30 37 7E 38 + dta $39, $80, $30, $37, $7E, $38, $3C, $3E 26 FF55 66 68 64 80 82 67 + dta $66, $68, $64, $80, $82, $67, $73, $61 27 28 ;SHIFT 29 FF5D 4C 4A 3A 80 80 4B + dta $4C, $4A, $3A, $80, $80, $4B, $5C, $5E 30 FF65 4F 80 50 55 9B 49 + dta $4F, $80, $50, $55, $9B, $49, $5F, $7C 31 FF6D 56 80 43 80 80 42 + dta $56, $80, $43, $80, $80, $42, $58, $5A 32 FF75 24 80 23 26 1B 25 + dta $24, $80, $23, $26, $1B, $25, $22, $21 33 FF7D 5B 20 5D 4E 80 4D + dta $5B, $20, $5D, $4E, $80, $4D, $3F, $80 34 FF85 52 80 45 59 9F 54 + dta $52, $80, $45, $59, $9F, $54, $57, $51 35 FF8D 28 80 29 27 9C 40 + dta $28, $80, $29, $27, $9C, $40, $7D, $9D 36 FF95 46 48 44 80 83 47 + dta $46, $48, $44, $80, $83, $47, $53, $41 37 38 ;CTRL 39 FF9D 0C 0A 7B 80 80 0B + dta $0C, $0A, $7B, $80, $80, $0B, $1E, $1F 40 FFA5 0F 80 10 15 9B 09 + dta $0F, $80, $10, $15, $9B, $09, $1C, $1D 41 FFAD 16 80 03 80 80 02 + dta $16, $80, $03, $80, $80, $02, $18, $1A 42 FFB5 80 80 9B 80 1B 80 + dta $80, $80, $9B, $80, $1B, $80, $FD, $80 43 FFBD 00 20 60 0E 80 0D + dta $00, $20, $60, $0E, $80, $0D, $80, $80 44 FFC5 12 80 05 19 9E 14 + dta $12, $80, $05, $19, $9E, $14, $17, $11 45 FFCD 80 80 80 80 FE 80 + dta $80, $80, $80, $80, $FE, $80, $7D, $FF 46 FFD5 06 08 04 80 84 07 + dta $06, $08, $04, $80, $84, $07, $13, $01 287 FFDD _KERNEL_REPORT_MODULE_SIZE 'Keyboard routines', 0 Macro: _KERNEL_REPORT_MODULE_SIZE [Source: source/main.xasm] 1 .echo ' ', *, ' -> ', *-?@_kernel_lastpt, '(', 0, ')', ' ', 'Keyboard routines' 1 $FFDD -> $019E($0000) Keyboard routines 3 = FFDD .def ?@_kernel_lastpt = * Source: source/main.xasm 288 289 .if _KERNEL_XLXE 290 .echo 'Free space: ', $FFEE-*, ' bytes' 290 Free space: $0011 bytes 291 .else 292 .echo 'Free space: ', $FFFA-*, ' bytes' 293 .endif 294 295 ;============================================================================== 296 ; version block (XL/XE) 297 ;============================================================================== 298 299 .ifdef _KERNEL_816 300 org $ffe4 301 dta a(IntDispatchNativeCop) ;$FFE4 302 dta a(IntDispatchNativeBreak) ;$FFE6 303 dta a(IntDispatchNativeAbort) ;$FFE8 304 dta a(IntDispatchNativeNmi) ;$FFEA 305 dta a(0) ;$FFEC 306 dta a(IntDispatchNativeIrq) ;$FFEE 307 dta $13 ;$FFF0 308 dta $02 ;$FFF1 option byte - !!CHECKED BY ARCHON 309 dta 'CX' ;$FFF2 310 dta a(IntDispatchCop) ;$FFF4 311 dta a(0) ;$FFF6 312 dta a(IntDispatchAbort) ;$FFF8 313 .elif _KERNEL_XLXE 314 FFDD org $ffee 315 FFEE 01 01 13 dta $01,$01,$13 316 FFF1 02 dta $02 ;option byte - !!CHECKED BY ARCHON 317 FFF2 43 58 00 00 00 dta 'CX',$00,$00,$00 318 FFF7 00 dta $00 319 FFF8 00 00 dta a(0) 320 .endif 321 322 ;============================================================================== 323 ; reset vectors 324 ;============================================================================== 325 FFFA org $fffa 326 FFFA 81 C1 dta a(IntDispatchNMI) 327 FFFC B9 EE dta a(InitReset) 328 FFFE 95 C1 dta a(IntDispatchIRQ) 329 330 end