* * Custom kernal routines, from Blahtune. (Ignore the ENTs) * *------------------------------- * * My own little kernal routines -- useful utility * routines. * * INPUT -- Read string * KERPLOP * PLOPXY * PLOP -- Fast screen (text) plotting routines * CHAROUT -- PLOPs a character to the screen * PRINT -- Prints a string using CHROUT * STROUT -- Prints a string immediately following call * PRINPLOP -- Like PRINT but uses PLOP * PLOPSTR -- PLOPs a string immediately following call * MULT16 -- 16-bit integer multiply routine * DIV16 -- 16-bit divide * ASCTONUM -- Convert string to 16-bit number * PLOPNUM -- PLOPs 16-bit number to screen * PHBYTE -- PLOP two digit hex byte * BLMOVE -- Block memory move * SCREENP = $FB READST = $FFB7 SETLFS = $FFBA SETNAM = $FFBD OPEN = $FFC0 CLOSE = $FFC3 CHKIN = $FFC6 CHKOUT = $FFC9 CLRCHN = $FFCC CHRIN = $FFCF CHROUT = $FFD2 LOAD = $FFD5 SAVE = $FFD8 STOP = $FFE1 GETIN = $FFE4 CLALL = $FFE7 FAQ2 = $69 ACC = FAQ2 AUX = ACC+2 EXT = AUX+2 BLNSW = $CC BLNON = $CF BLNCT = $CD * * INPUT inputs a string of data into STRBUF. The maximum * number of chars to be read are passed in X. On output, * zero set means the input was aborted with R/S or is * empty. .A (and STRLEN) contains the string length. * STRBUF EQU $0200 STRLEN ENT DFB 00 MAXLEN DFB 00 INPUT ENT STX MAXLEN LDA #00 STA STRLEN STA STRBUF LDA $0286 ;Set blink color to STA $0287 ;current color. :LOOP LDA #00 STA BLNSW ;Blink :WAIT JSR STOP BEQ :RTS JSR GETIN BEQ :WAIT LDY #1 STY BLNCT :WAIT2 LDY BLNON BNE :WAIT2 INC BLNSW CMP #160 ;Alphanumeric characters BCS :NORMAL CMP #128 BCS :LOOP CMP #13 BEQ :DONE CMP #20 BEQ :DEL CMP #32 BCC :LOOP :NORMAL LDY STRLEN CPY MAXLEN BCS :LOOP STA STRBUF,Y JSR CHROUT INC STRLEN BNE :LOOP :DEL LDY STRLEN BEQ :LOOP JSR CHROUT DEC STRLEN BPL :LOOP :DONE LDY STRLEN LDA #00 STA STRBUF,Y TYA ;Z set if string empty :RTS RTS * * PLOP * Stores the value in A to the screen at the point * (ROW,COLUMN) and the color in COLOR to the * colormap. If entered at PLOPXY, ROW is set to X and * column is set to Y. If entered at KERPLOP, char * is stored to the kerrent screen pointer. * On exit, A X and Y are preserved; carry set indicates * an error, i.e. row/col out of range. * ROW ENT DFB 0 ;Current row,column COLUMN ENT DFB 0 COLOR ENT DFB 0 PLOPXY ENT ;Set Y=column, X=row CPX #25 BCS PLOPRTS CPY #40 BCS PLOPRTS STY COLUMN STX ROW PLOP ENT PHA LDA ROW ;We need 40*ROW ASL ASL ADC ROW ;5*ROW STA SCREENP LDA #00 ;A=high byte ASL SCREENP ;Mult by 8 ROL ASL SCREENP ROL ASL SCREENP ROL ADC #$04 ;Add 1024 STA SCREENP+1 ;SCREENP now points to screen PLA PLOPRTS RTS KTEMP DS 1 STAXY ENT JSR PLOPXY ;plop to X,Y KERPLOP ENT ;PLOP to kerrent screen loc. STY KTEMP LDY COLUMN STA (SCREENP),Y LDA SCREENP+1 CLC ADC #$D4 ;Color mem at $D800 STA SCREENP+1 LDA COLOR STA (SCREENP),Y LDA SCREENP+1 ;Restore SCREENP to point to SEC ;screen SBC #$D4 STA SCREENP+1 CLC ;Signal all is well. LDA (SCREENP),Y ;restore A LDY KTEMP RTS * * CHAROUT * Sticks a CHR$ character to the screen at the current * row,column and advances the column. * All registers are preserved. * CHAROUT ENT EOR #$E0 ;Convert to screen char CLC ADC #32 BPL :CONT ADC #64 BPL :CONT EOR #$A0 :CONT JSR KERPLOP INC COLUMN RTS * * PRINT * As the name suggests, this prints a string to the * screen, where the address of the string is * contained in (.X,.A) = (lo,hi). The string is * assumed to be null-terminated. * * On exit, the location of the last character read * (the null-terminator hopefully) is returned in * (.X,.A) = (lo,hi). Y is preserved. * PRINT ENT STA :LOOP+2 :LOOP LDA $A000,X BEQ :DONE JSR CHROUT INX BNE :LOOP INC :LOOP+2 BNE :LOOP :DONE LDA :LOOP+2 RTS * * STROUT * Like PRINT, but the string immediately follows the * subroutine call; execution resumes right after the * null-termination byte. * * On exit, A and X are thoroughly hosed. * STROUT ENT PLA TAX ;Lo byte PLA INX BNE :CONT CLC ADC #01 :CONT JSR PRINT PHA ;lo byte TXA PHA ;hi byte RTS * * Like PRINT, but uses PLOP. * PRINPLOP ENT STA :LOOP+2 :LOOP LDA $A000,X BEQ :DONE JSR CHAROUT INX BNE :LOOP INC :LOOP+2 BNE :LOOP :DONE LDA :LOOP+2 RTS * * PLOPSTR * Like STROUT, but uses PLOP * TEMPA DFB 00 TEMPX DFB 00 PLOPSTR ENT STA TEMPA STX TEMPX PLA TAX ;Lo byte PLA INX BNE :CONT CLC ADC #01 :CONT JSR PRINPLOP PHA ;lo byte TXA PHA ;hi byte LDX TEMPX LDA TEMPA RTS *------------------------------------- * 16 bit multiply and divide routines. * Three 16 bit (two-byte) locations * ACC, AUX and EXT must be set up, * preferably on zero page. *------------------------------------- * MULTIPLY ROUTINE * ACC*AUX -> [ACC,EXT] (low,hi) 32 bit result MULT16 ENT LDA #0 STA EXT+1 LDY #$11 ]LOOP LSR EXT+1 ROR ROR ACC+1 ROR ACC BCC MUL2 CLC ADC AUX PHA LDA AUX+1 ADC EXT+1 STA EXT+1 PLA MUL2 DEY BNE ]LOOP STA EXT RTS * DIVIDE ROUTINE * ACC/AUX -> ACC, remainder in EXT DIV16 ENT LDA #0 STA EXT+1 LDY #$10 ]LOOP ASL ACC ROL ACC+1 ROL ROL EXT+1 PHA CMP AUX LDA EXT+1 SBC AUX+1 BCC DIV2 STA EXT+1 PLA SBC AUX PHA INC ACC DIV2 PLA DEY BNE ]LOOP STA EXT RTS * * ASCTONUM * Converts a string to a 16-bit number. The address * of the string is passed in in (A,X) = (lo,hi), and * the base of the number is contained in Y. Valid * bases are 0-16. The string is assumed to be * null-terminated. * * On exit, carry set denotes an error, either an * invalid base, an invalid string, or a number * overflow. The number is contained in ACC, as * used in MULT16. The last char read is contained * in (A,X)=(lo,hi). Y is toast. * ASCTONUM ENT CPY #17 BCS :EXIT STY AUX ;AUX=number base LDY #00 STY AUX+1 STY ACC STY ACC+1 STX :LOOP+2 TAX ;X=lo byte string :LOOP LDA $A000,X ;Valid chars are $30-$39, $41-$46 BEQ :EXIT EOR #$30 CMP #10 BCC :CONT EOR #$70 ;Should use SBC #$70-9 ADC #8 ;Now A-F = 10-16 :CONT CMP AUX ;Compare with number base BCS :EXIT PHA JSR MULT16 ;Multiply number times base PLA LDY EXT ;Did multiplication exceed 16 bits? BNE :ERROR CLC ADC ACC STA ACC LDA ACC+1 ADC #00 STA ACC+1 INX BNE :LOOP INC :LOOP+2 BNE :LOOP :ERROR SEC :EXIT TXA LDX :LOOP+2 RTS * * PRINTNUM * Prints the 16-bit number in (A,X) = (lo,hi) * to the screen, i.e. prints using CHROUT. * The number base is contained in Y. * PRINTNUM ENT STA ACC STX ACC+1 STY AUX ;Base LDX #00 STX AUX+1 * ACC/AUX -> ACC, remainder in EXT :LOOP JSR DIV16 INX LDA EXT PHA LDA ACC ORA ACC+1 BNE :LOOP ;Divide until result=0 :POOP PLA ORA #$30 ;Convert to chr$ CMP #$3A BCC :PLOP ADC #$06 ;$3A->A $3B->B etc. :PLOP JSR CHROUT DEX BNE :POOP RTS * * PLOPNUM * Plops the 16-bit number in (A,X) = (lo,hi) * to the screen, i.e. prints using PLOP routine. * The number base is contained in Y. * PLOPNUM ENT STA ACC STX ACC+1 STY AUX ;Base LDX #00 STX AUX+1 * ACC/AUX -> ACC, remainder in EXT :LOOP JSR DIV16 INX LDA EXT PHA LDA ACC ORA ACC+1 BNE :LOOP ;Divide until result=0 :POOP PLA ORA #$30 ;Convert to chr$ CMP #$3A BCC :PLOP ADC #$06 ;$3A->A $3B->B etc. :PLOP JSR CHAROUT DEX BNE :POOP RTS * * PHBYTE * Print a hex byte in .A, including trailing zeros * PHBYTE ENT PHA LSR LSR LSR LSR JSR :PRINT PLA AND #$0F :PRINT ORA #$30 CMP #$3A BCC :PLOP ADC #$06 :PLOP JMP CHAROUT * * BLMOVE * Moves a block of memory to another location. * Set BLSTART to the beginning of the block of * memory, BLEND to the last byte of the block, * and BLDEST to the destination byte (2-bytes * each, in lo,hi format). * * The routine is smart, and can tell the difference * between forwards and backwards moves, etc. * * AUX and EXT are used, from mult routine. * BLSTART ENT DA 0 BLEND ENT DA 0 BLDEST ENT DA 0 BLMOVE ENT LDA BLEND ;Number of bytes to move SEC SBC BLSTART TAX LDA BLEND+1 SBC BLSTART+1 BCC :DONE STA AUX ;(.X,AUX) = (LO,HI) LDA BLSTART SEC SBC BLDEST LDA BLSTART+1 SBC BLDEST+1 BCC :FORWARD LDA BLSTART STA :BSRC+1 LDA BLSTART+1 STA :BSRC+2 LDA BLDEST STA :BDEST+1 LDA BLDEST+1 STA :BDEST+2 INC AUX INX LDY #00 :LOOP :BSRC LDA $1000,Y :BDEST STA $1000,Y INY BNE :C1 INC :BSRC+2 INC :BDEST+2 :C1 DEX BNE :LOOP DEC AUX BNE :LOOP :DONE RTS :FORWARD ;Move block forwards TXA ADC BLDEST ;Copy to end of blocks STA :FDEST+1 LDA AUX ADC BLDEST+1 STA :FDEST+2 LDA BLEND STA :FSRC+1 LDA BLEND+1 STA :FSRC+2 INC AUX INX LDY #00 :FLOOP :FSRC LDA $1000,Y :FDEST STA $1000,Y DEY CPY #$FF BNE :C2 DEC :FSRC+2 DEC :FDEST+2 :C2 DEX BNE :FLOOP DEC AUX BNE :FLOOP RTS