NEW AUTO 3,1 * prodos greeting splash screen LDR.Splash lda SPEAKER click speaker sta CLR80DISP disable 80 col hardware sta CLR80STORE disable 80 col store jsr setnorm set normal text mode jsr init init text screen jsr setvid reset output to screen jsr setkbd reset input to keyboard cld jsr home ldx #$07 .1 lda LDR.MSG.AppleII,x sta vline10+16,x dex bpl .1 ldx #$1D .2 lda LDR.MSG.ProDOS,x sta vline12+5,x dex bpl .2 ldx #$0B .3 lda H202F,x sta vline14+14,x dex bpl .3 ldx #$26 .4 lda LDR.MSG.Copyright,x sta vline23,x dex bpl .4 ldx #$13 .5 lda LDR.MSG.Reserved,x sta vline24+10,x dex bpl .5 sec jsr idroutine returns system info bcs .8 taken if not a //gs lda #$80 trb newvideo video mode select .8 lda SPEAKER click speaker rts * find all disk devices in system slots and set up address * and device table in prodos global page. if there is a disk * card in slot 2 then limit the # of devices in slot 5 * smartport to only 2 numdev2 .HS 0000000000000000 8 bytes for smartport call driveradr .DA 0 d2idx .DA #0 diskins2 .DA #0 msb clear if drive in slot 2 devsrch stz dst stz dst+1 stz idxl ldx #$FF init to no active devices. stx numdevs count (-1) active devices. lda #$0E start disk // area at end of devlist. sta d2idx * check slot 2. if there is a disk card then clear the msb of diskins2. this * will limit the # of devices in any slot 5 spartport card to 2. lda #$C2 sta idxl+1 check slot 2 jsr cmpid is there a disk in slot 2 ? ror diskins2 if so, clear msb else set it. lda #$C7 search slots from high to low sta idxl+1 H26AB jsr cmpid bcs H270C if no ProDOS device in this slot. lda (idxl),y check last byte of $Cn rom (y = $ff) beq diskii branch if 16 sector disk II. cmp #$FF if = $FF then 13 sector disk II. bcs H270C ignore if 13 sector boot ROM sta driveradr else assume it's an intelligent disk. ldy #$07 check for a smartport device. lda (idxl),y bne H26C4 no smartport jmp smartprt H26C4 ldy #$FE lda (idxl),y get attributes. and #$03 verify it provides read and status calls. cmp #$03 sec assume it's an off-brand disk bne H270C jsr setdevid set up the devid byte from attributes clc php remember that it's not a disk //. lsr move # of units (0=1, 1=2) to carry. lda idxl+1 store hi entry addr (low already done) bne H26E6 branch always. diskii sta devid =0 since disk ii's have null attributes sec php remember it's a disk // lda H2802 sta driveradr lda H2802+1 H26E6 sta driveradr+1 jsr installdev install 1 or 2 devices from this slot. plp get back if it's a disk // (carry). bcc nxtdsk2 if not disk //. dex move the list pointer back by 2 devices dex stx numdevs count (-1) active devices dec d2idx increase the disk two index dec d2idx ldy d2idx inx adj since device count starts with $FF. lda devlist+1,x get entries for disk // sta devlist,y move then toward the end of the list lda devlist,x sta devlist+1,y dex back to numdevs again nxtdsk2 clc H270C jsr sltrom test for ROM in given slot and set flags dec idxl+1 next lower slot. lda idxl+1 and #$07 have all slots been checked ? bne H26AB no. * perform the new device search, mapping unmounted smartport devices * to empty slots in the device table. jsr newmount * now copy the disk // list to the end of the regular list. * start by making the device count include disk //'s ldx numdevs current device count - 1 lda #$0E sec sbc d2idx beq H2747 if there were no disk //'s then done. clc adc numdevs sum of disk //'s and others. sta numdevs inx move to open space in regular list. ldy #$0D first disk // entry. H272F lda devlist,y pha lda devlist,x sta devlist,y pla sta devlist,x inx dey sty d2idx use as a temp cpx d2idx bcc H272F continue until indexes cross H2747 ldy #$00 ldx numdevs now change the device order so that H274C lda devlist,x the boot device will have highest pha priority. and #$7F strip off high bit eor devnum for comparison. asl bne H275A pla iny H275A dex bpl H274C ldx numdevs now reverse order of search, hi to lo. tya was boot device found ? beq H2777 lda devnum make boot device 1st in search order. sta devlist,x dex bmi H277E branch if only one device. dey is this a 2 drive device ? beq H2777 branch if not. eor #$80 make boot device, drive 2 next. sta devlist,x dex bmi H277E branch if only 1 device, 2 drives. H2777 pla sta devlist,x dex bpl H2777 H277E jsr fndtrd save accumulated machine id. beq H2787 sta machid machine ID byte rts H2787 jmp H25B6 stadrv ora devid combine with attributes. ldx numdevs inx put device # into device list. sta devlist,x asl now form drive 2 device number, if any. rts sltrom bcc H27F3 branch if disk drive * test for clock card ldy #$06 H2799 lda (idxl),y cmp dskid,y bne H27BA no clock dey dey bpl H2799 lda idxl+1 transfer hi slot address sbc #$C1 minus $C1 (default) to relocate sta clock64 references to clock rom. lda #$4C enable jump vector in globals. sta clockv P8 clock vector. lda idapple mark clock as present. beq H277E ora #$01 sta idapple xxxxxxx1 = clock present. bne H27F3 always taken. * test for 80 col card H27BA ldy #$05 lda (idxl),y cmp #$38 bne H27E4 ldy #$07 lda (idxl),y cmp #$18 bne H27E4 ldy #$0B lda (idxl),y dec must = 1 bne H27E4 iny lda (idxl),y and #$F0 mask off low nibble. cmp #$80 generic for 80-col card. bne H27E4 lda idapple beq H277E ora #$02 sta idapple xxxxxx1x = 80 col card. bne H27F3 always taken. * test for any other rom H27E4 ldx #$00 lda (idxl) cmp #$FF apple /// non-slot? beq H2801 invalid rom H27EC cmp (idxl) look for floating bus bne H2801 no rom inx bne H27EC H27F3 lda idxl+1 mark a bit in slot byte and #$07 to indicate rom present. tax lda sltbit,x ora rommap mark bit to flag rom present sta rommap slot ROM bit map H2801 rts H2802 .DA rwts disk ii driver * id bytes: evens for clock, odds for disk dskid .HS 082028005803703C * slot bits sltbit .HS 0002040810204080 fndtrd clc ldy sltbit H2818 lda (lookptr),y and #$DF adc sltbit sta sltbit rol sltbit iny cpy sltbit+3 bne H2818 tya asl asl asl asl tay eor sltbit adc #$0B bne H283B lda idapple rts H283B lda #$00 rts installdev php how many drives (carry). lda idxl+1 get index to global device table and #$07 for this slot... asl tay into y reg. asl asl now form device # = slot # asl in high nibble. jsr stadrv OR in low nibble, store in dev list. plp restore # of devices in carry. ror if 2 drives, then bit 7=1. bpl H2853 branch if a 1 drive device (e.g. hard drive) inx else presume that 2nd drive is present. sta devlist,x active device list. H2853 stx numdevs save updated device count. asl shift # of drives back into carry. lda driveradr get high address of device driver. sta drivertbl1,y device driver table 1. bcc H2862 branch if single drive. sta drivertbl2,y device driver table 2. H2862 lda driveradr+1 sta drivertbl1+1,y bcc H286D sta drivertbl2+1,y H286D rts * query smartport status to determine # of devices * and install up to 4 units in table if card is in slot 5 * otherwise only 2 units. this includes a patch #74 smartprt jsr setdevid setup the devid byte from attributes lda idxl+1 sta driveradr+1 lda driveradr sta pscall+1 modify operand clc adc #$03 sta spvect+1 lda driveradr+1 sta spvect+2 sta pscall+2 modify operand asl convert $Cn to $n0 asl asl asl sta unitnum unit number stz A4L force a prodos status call stz buf dummy pointer stz bloknml # of bytes to transfer stz bloknml+1 lda #$10 sta buf+1 dummy pointer should be <> 0 * do a prodos status call patched in from above pscall jsr $0000 self modifying code ldy #$FB lda (idxl),y check device id and #$02 SCSI? beq H28B1 no, no need to init Cocoon sta statunit device = 2 for SCSI * initialize SCSI Cocoon to build internal device tables * and report true # of devices attached jsr spvect status of Cocoon .HS 00 .DA spcparms ignore any errors. H28B1 stz statunit set unit# = 0 jsr spvect call to get the device count. .HS 00 this is a status call .DA spcparms lda numdev2 beq donesp no devices, so done. cmp #$02 carry set if 2,3,4 jsr installdev do the 1st and 2nd device if exists. lda idxl+1 cmp #$C5 bne donesp if not slot 5 * for slot 5, if there is a disk card in slot 2 * then only install 2 devices otherwise map * extra devices as slot 2 bit diskins2 disk in slot 2 ? bpl donesp yes - so done lda numdev2 cmp #$03 carry set if 3,4,... bcc donesp cmp #$04 carry set if 4,5,6,... lda #$C2 map extra devices as slot 2 sta idxl+1 jsr installdev lda #$C5 sta idxl+1 donesp jmp nxtdsk2 it's a disk device. setdevid ldy #$FE check attributes byte. H28E8 lda (idxl),y lsr move hi nibble to lo nibble for lsr device table entries. lsr lsr sta devid rts * check unknown card to see if disk id = $Cn00:nn 20 nn 00 nn 03 cmpid lda CLRC8ROM switch out $C8 ROMs ldy #$05 H28F6 lda (idxl),y compare id bytes cmp dskid,y sec set if no disk card bne H2903 dey dey bpl H28F6 loop until all 4 id bytes match. clc clear if disk card H2903 rts * smartport call parameters spcparms .DA #$03 # of parms statunit .DA #$00 unit number (code for smartport stat) .DA numdev2 .DA #00 status code (0 = general status) * indexes into driver table driveridx .DA #$06 s3, d1 .DA #$1E s7, d2 .DA #$0E s7, d1 .DA #$1C s6, d2 .DA #$0C s6, d1 .DA #$1A s5, d2 .DA #$0A s5, d1 .DA #$14 s2, d2 .DA #$04 s2, d1 .DA #$12 s1, d2 .DA #$02 s1, d1 .DA #$18 s4, d2 .DA #$08 s4, d1 * self modifying jmp = smartport entry address spvect jmp $0000 self modifying newmount stz idxl lda #$C7 start with slot 7 ($C700) sta idxl+1 H291F jsr H29EB is there a smartport device here? bcs H2974 no, next device. ldy #$FF get smartport address. lda (idxl),y clc adc #$03 add 3 for smartport call sta spvect+1 lda idxl+1 sta spvect+2 dey jsr H28E8 set up device attributes stz statunit jsr spvect do a status call on smartport itself .HS 00 .DA spcparms lda numdev2 # of devices on smartport cmp #$03 bcc H2974 only 2 devices,skip to next one. inc add 1 for comparisons. sta driveradr # of devices + 1. lda #$03 start at unit #3 (non-slot 5) ldx spvect+2 cpx #$C5 is this slot 5? bne H295B no, start at 3. bit diskins2 disk controller in slot 2? bpl H295B yes, so allow remapping of s5 devices lda #$05 else start looking at unit #5 * find block devices on this smartport H295B cmp driveradr have we done all units in this slot? bcs H2974 yes, skip to next slot. sta statunit store the unit#. jsr spvect do status call .HS 00 .DA spcparms lda numdev2 is this a block device? bmi mount yes, so mount it. H296E lda statunit go check the next unit# inc bra H295B H2974 dec idxl+1 lda idxl+1 cmp #$C0 searched down to slot 0? bne H291F if not. rts mount ldx #$0C H297F ldy driveridx,x lda drivertbl1,y device driver table 1 cmp #nodevice bne H2990 lda drivertbl1+1,y cmp /nodevice beq H2994 H2990 dex bpl H297F rts ran out of space for devices, exit. * empty slot found H2994 lda idxl+1 pha phx phy tya which slot is empty? lsr shift into slot# and #$07 now 1-7 ora #$C0 now $C1-$C7 sta idxl+1 jsr H29EB smartport interface in this slot? ply plx pla sta idxl+1 bcc H2990 yes, can't use to mirror the device. jsr lc1in write enable LC ram bank 1. tya divide index by 2 lsr tax lda statunit sta spunit-1,x store the smartport unit # lda spvect+1 and entry address. sta spvectlo-1,x lda spvect+2 sta spvecthi-1,x lda RROMBNK2 write protect lc ram. inc numdevs ldx numdevs tya lsr cmp #$08 bcc nodev2 drive 2 mount sbc #$08 ora #$08 nodev2 asl asl asl asl ora devid include device attributes sta devlist,x in the active device list. lda #remap_sp sta drivertbl1,y device driver table 1 lda /remap_sp sta drivertbl1+1,y bra H296E H29EB jsr cmpid is it a disk controller? bcs H29F8 no, so return. sec assume no smartport ldy #$07 lda (idxl),y is it a smartport? bne H29F8 if not. clc smartport found H29F8 rts * relocation subroutine. on entry, regs yx = address of parameter table * with the following parameters: * * (1) command: 0 = zero destination range * 1 = move data from src to dst * 2 = hi addr ref tbl, relocate and move * 3 = lo/hi addr ref tbl, relocate and move * 4 = program, relocate and move * >4 = end of sequence of commands * (2) destination * (2) length * (2) source * (1) # of address ranges (n) to be relocated * (n+1) list of low page addresses to be relocated * (n+1) list of high page addresses to be relocated * (n+1) list of offset amounts to be added to be added * if low and high limits have not been met * * on exit, carry set if error and yx = addr of error * with acc = $00 for table error or $FF if illegal opcode reloc stx idxl save address of control table sty idxl+1 rloop lda (idxl) get relocation command. cmp #$05 bcs rlend taken if >= 5 then done. tax move destination to page 0 ldy #$01 for indirect access. lda (idxl),y sta dst iny lda (idxl),y sta dst+1 iny lda (idxl),y also the length (byte count) sta cnt of the destination area. iny lda (idxl),y sta cnt+1 bmi rlerr branch if >= 32k. txa is it a request to zero destination? beq zero if yes. iny lda (idxl),y get source address. sta src used for move. sta cde used for relocation iny clc adc cnt add length to get final address sta ecde lda (idxl),y sta src+1 sta cde+1 adc cnt+1 sta ecde+1 dex test for 'move' command beq H2AA3 branch if move only (no relocation) stx wsize save element size (1,2,3) iny lda (idxl),y get # of ranges that are valid sta sgcnt relocation target addresses. tax separate serial range groups into tbls H2A42 iny lda (idxl),y transfer low limits to 'limlo' table sta limlo,x dex bpl H2A42 ldx sgcnt # of ranges H2A4E iny lda (idxl),y transfer high limits to 'limhi' table sta limhi,x dex bpl H2A4E ldx sgcnt # of ranges H2A5A iny lda (idxl),y transfer offsets to 'ofset' table sta ofset,x dex bpl H2A5A jsr adjtbl adj index pointer to next entry. ldx wsize test for machine code relocation cpx #$03 beq rlcode branch if program relocation jsr reladr otherwise, relocate addresses in H2A70 jsr moveSrcDst tables then move to destination. bra rloop do next table rlend clc rts rlerr jmp tblerr rlcode jsr rlprog relocate machine code refs bra H2A70 * fill destination range with 0's zero jsr adjtbl adj table pointer to next entry. lda #$00 ldy cnt+1 is it at least 1 page? beq H2A94 branch if not. tay H2A89 sta (dst),y iny bne H2A89 inc dst+1 next page dec cnt+1 bne H2A89 if more pages to clear. H2A94 ldy cnt any bytes left to 0? beq H2AA0 if not. tay H2A99 sta (dst),y zero out remainder iny cpy cnt bcc H2A99 H2AA0 jmp rloop H2AA3 jsr adjtbl bra H2A70 adjtbl tya add previous table length to sec get next entry position in table adc idxl sta idxl bcc H2AB2 inc idxl+1 H2AB2 rts moveSrcDst lda src+1 is move up, down or not at all? cmp dst+1 bcc movup bne movdn lda src cmp dst bcc movup bne movdn rts no move. movup ldy cnt+1 calc highest page to move up tya and adj src and dst. clc adc src+1 sta src+1 tya clc adc dst+1 sta dst+1 ldy cnt move partial page 1st. beq H2ADE taken if no partial pages H2AD6 dey lda (src),y sta (dst),y tya end of page transfer? bne H2AD6 no H2ADE dec dst+1 dec src+1 dec cnt+1 done with all pages? bpl H2AD6 no rts movdn ldy #$00 lda cnt+1 partial page move only? beq H2AFC taken if < 1 page to move H2AED lda (src),y sta (dst),y iny bne H2AED inc dst+1 next page inc src+1 dec cnt+1 more pages? bne H2AED if more. H2AFC lda cnt move partial page. beq H2B09 if no more to move H2B00 lda (src),y sta (dst),y iny cpy cnt bne H2B00 H2B09 rts * relocate addresses reladr ldy wsize 1 or 2 byte reference dey lda (cde),y jsr adjadr relocate reference. lda wsize update and test code pointer. jsr adjcde bcc reladr if more to do rts rlprog ldy #$00 get next opcode lda (cde),y jsr oplen determine if a 3 byte instruction. beq rperr branch if not an opcode cmp #$03 bne H2B30 ldy #$02 jsr adjadr relocate address lda #$03 H2B30 jsr adjcde update and test if done. bcc rlprog if more to do rts rperr pla pla ldx cde bad code address in y,x ldy cde+1 lda #$FF indicates bad opcode sec rts tblerr ldx idxl bad table address in y,x ldy idxl+1 lda #$00 indicates input table error sec rts adjadr lda (cde),y get page address and ldx sgcnt test against limits. H2B4D cmp limlo,x is it >= low? bcc H2B59 if not. cmp limhi,x is it <= high? bcc H2B5D branch if it is beq H2B5D H2B59 dex try next limit set bpl H2B4D rts return w/o adjustment. H2B5D clc add offset to form relocated adc ofset,x page address and replace sta (cde),y old address with result. rts adjcde clc update code pointer adc cde ldy cde+1 bcc H2B6C branch if not page cross iny otherwise, update page#. H2B6C cpy ecde+1 has all code/data been processed? bcc H2B72 if not. cmp ecde H2B72 sta cde save updated values. sty cde+1 rts return result (carry set = done). oplen pha form index to tbl & which 2-bit group. and #$03 low 2 bits specify group tay pla lsr upper 6 bits specify byte in table lsr tax lda opcodln,x nxgroup dey is opcode len in lowest 2 bits of acc? bmi H2B89 branch if it is lsr shift to next group. lsr (if length = 0 then error) bne nxgroup .BS $2B89-* H2B89 and #$03 rts if z-set then error * relocation table contains length of each opcode in 2-bit groups opcodln .HS 0928193C0A280D3C .HS 0B2A193F0A280D3C .HS 0928193F0A280D3C .HS 0928193F0A280D3C .HS 082A113F0A2A1D0C .HS 2A2A193F0A2A1D3F .HS 0A2A193F0A280D3C .HS 0A2A193F0A280D3C wsize .HS 00 sgcnt .HS 00 limlo .HS 0000000000000000 limhi .HS 0000000000000000 ofset .HS 0000000000000000 * patch to gsos vectors so error is returned for os calls - rev note #101 patch101 php sei disable interrupts clc xce full native mode >LONGMX phb save DBR pha pha pea $0000 length of patch pea $0010 0000/0010 = 16 bytes pea $3101 user id for prodos 8 pea $8018 attributes (locked/nospec/nocross) pha pha >IIGS NewHandle lda $01,s retrieve handle tax lda $03,s tay pea $0000 copy the code into the handle pea L2C4D phy phx pea $0000 length of patch = 0000/0010 pea $0010 >IIGS PtrToHand plx low word of handle plb set DBR to handle's bank lda >1,x get upper 16 bits of 24 bit address tay save in y lda >0,x get low 8 bits of address and ##$00FF clear high byte xba put address in high byte ora ##$005C include JML opcode sta GSOS2 store in gsos vectors clc adc ##$000B sta GSOS tya store upper 16 bits too sta GSOS2+2 adc ##$0000 adj for possible page crossing sta GSOS+2 plb remove garbage byte from stack plb restore DBR. sec xce back to emulation mode plp rts * copy of the code that goes in the handle L2C4D lda 1,s sta 7,s lda 2,s sta 8,s pla pla pla lda ##$00FF #NoOS sec rtl .BS $2C80-* RAMDRV.Install ldy #$99 move $9A bytesfrom lcsrc to lcdest. .1 lda RAM,y transfer main bank portion of driver sta RAMDRV,y dey cpy #$FF bne .1 ldx #RAMX set up to move aux portion of driver stx A1L dex stx A2L ldx /RAMX stx A1L+1 inx stx A2L+1 lda #RAMXDRV sta A4L lda /RAMXDRV RAMX to RAMXDRV sta A4L+1 sec irection = to aux bank. jsr auxmove move aux bank portion of driver. lda #RAMDRV put driver address into sta drivertbl2+6 slot 3, drive 2. lda /RAMDRV sta drivertbl2+7 inc numdevs count (-1) active devices ldx numdevs lda #$BF unit num of /RAM sta devlist,x rts end of obj ram_1 RAM_1_END .EQ * end of /RAM installer .BS $2D00-* pad 0's to page boundary MAN SAVE usr/src/prodos.203/prodos.s.ldr.b LOAD usr/src/prodos.203/prodos.s ASM