.xlist ;;************************************************************ ;;* * ;;* MAKRO - Bibliothek fuer CP/M-System-Routinen * ;;* 15.10.1986 Thomas Wolf THK/PEB * ;;* * ;;************************************************************ ;; ;; ;;Inhaltsverzeichnis definierter MAKROS ;;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;;____________________________________________________________ ;; ;; Namen Parameter Flags ;;____________________________________________________________ ;; ;;abort MACRO char CI ;;ambig MACRO (keine) ;;bell MACRO BL,CO ;;binbin MACRO reg BN,CO ;;close MACRO pointr CL,CR,CO,PR,OP, ;; MV,DE,CI,UN,RN,S2 ;;compar MACRO first, second, byte CM ;;compra MACRO first, second, byte CP ;;crlf MACRO CR,CO ;;delete MACRO pointr, where DE,CI,CO,PR,UN ;;enter MACRO (keine) ;;errorm MACRO text, where CO,CR,PR,BL ;;exit MACRO where?, space? (keine) ;;fill MACRO addr, bytes, char FL ;;gfname MACRO fcb FN,BL,CR,CO,RC,PR ;;gotoxy MACRO row, column GO,CO ;;hexhl MACRO HX ;;hldec MACRO DC,CO ;;lchar MACRO par LO ;;ldfile MACRO fcb, buffer, char CO,DM,RD ;;make MACRO pointr MK,CO,CR,PR ;;move MACRO from, to, bytes (keine) ;;open MACRO pointr, where OP,CO,CR,PR,BL ;;outhex MACRO reg CX,CO ;;outhl MACRO CX,CO ;;pchar MACRO par CO ;;pfname MACRO fcb CO ;;print MACRO text, bytes PR, CO ;;readb MACRO RC ;;readch MACRO reg CI ;;reads MACRO pointr, char RD,CO ;;rename MACRO pointr RN,CO,PR,CR ;;setdma MACRO pointr DM ;;setup2 MACRO S2,CI,CO,CR,CM,UN ;; DE,MK,MV,OP,PR, ;;syschk MACRO sign, nr, text CO,CR,PR,BL,CM ;;sysf MACRO func, ae (keine) ;;ucase MACRO reg (keine) ;;unprot MACRO pointr UN ;;versn MACRO num (keine) ;;wrfile MACRO fcb, buffer, char CO,DM,CR,WR ;;writes MACRO pointr, char WR,CO,PR ;; ;;____________________________________________________________ ;;In einigen Makros wird bei Abbruch (z.B. Fehler) zur Marke ;;DONE gesprungen. Der Programmierer muss diese Marke im Haupt- ;;programm selbst definieren. In vielen Faellen ist es sinnvoll, ;;diese Marke direkt vor den Makro EXIT zu legen. ;;Konstantendefinition ;;~~~~~~~~~~~~~~~~~~~~ BDOS ASET 5 ;BDOS-Systemaufruf BELL ASET 7 ;CTRL-G (Tonausgabe) BLANK ASET 32 ;Leerzeichen BS ASET 8 ;Backspace CR ASET 13 ;Kursor zum Zeilenanfang EOF ASET 1Ah ;Dateiende EOL ASET 16h ;Loeschen des BS bis Zeilenende EOS ASET 14h ;Loeschen des BS bis Ende ESC ASET 1Bh ;Escape FCB1 ASET 5Ch ;File-Control-Block 1 FCB2 ASET 6Ch ;File-Control-Block 2 FFEED ASET 0Ch ;Form Feed (Seitenanfang) INV ASET 85h ;Bildschirm invers KON ASET 82h ;Kursor einschalten KOFF ASET 83h ;Kursor ausschalten LF ASET 10 ;Kursor naechste Zeile NRM ASET 84h ;Bildschirm normal TAB ASET 9 ;CTRL-I (Tabulator) UP ASET 1Ah ;Kursor Zeile zurueck FALSE ASET 0 TRUE ASET NOT FALSE BLFLAG ASET FALSE BNFLAG ASET FALSE CIFLAG ASET FALSE CLFLAG ASET FALSE CMFLAG ASET FALSE COFLAG ASET FALSE ;Flags definieren CPFLAG ASET FALSE CRFLAG ASET FALSE CXFLAG ASET FALSE DCFLAG ASET FALSE DEFLAG ASET FALSE DMFLAG ASET FALSE FLFLAG ASET FALSE FNFLAG ASET FALSE GOFLAG ASET FALSE HXFLAG ASET FALSE LOFLAG ASET FALSE MKFLAG ASET FALSE OPFLAG ASET FALSE PRFLAG ASET FALSE RCFLAG ASET FALSE RDFLAG ASET FALSE RNFLAG ASET FALSE S2FLAG ASET FALSE UNFLAG ASET FALSE WRFLAG ASET FALSE ;;____________________________________________________________ ;; ABORT MACRO CHAR ;; ;;11.09.86 ;;Inline Makro, um ein Programm abzubrechen, wenn die Taste ;;CHAR gedrueckt wird. ;;Fehlt der Parameter CHAR, so fuehrt eine beliebige Taste ;;zum Programmabruch. ;;Sprung zur globalen Marke DONE bei Abbruch. ;;Register AF veraendert ;;benoetigtes Makro: READCH ;; ;;Anwendung ABORT ESC ;; LOCAL around push hl push de push bc ld c,11 ;Konsolenstatus call bdos pop bc pop de pop hl rrca jr nc,around ;kein Zeichen READCH ;Zeichen lesen IF NUL CHAR jp done ELSE cp CHAR ;Zeichen vergleichen jp z,done ENDIF around: ;;ABORT ENDM ;;____________________________________________________________ ;; AMBIG MACRO OLD, NEW ;; ;;05.08.86 ;;Inline Makro, um einen nicht eindeutigen Dateinamen bei ;;FCB-NEW in einen eindeutigen umzuwandeln. Die '?' werden ;;durch die Zeichen in FCB-OLD ersetzt. ;;Register AF veraendert ;; ;;Anwendung AMBIG FCB1, FCB2 ;; LOCAL amb2?, amb3? push hl push de push bc ld hl,NEW+1 ld de,OLD+1 ld b,11 ;Anzahl der Zeichen in B amb2?: ld a,'?' cp (hl) ;Fragezeichen ? jr nz,amb3? ;nein ld a,(de) ;Zeichen aus OLD holen ld (hl),a ;in NEW kopieren amb3?: inc hl inc de djnz amb2? pop bc pop de pop hl ;;AMBIG ENDM ;;____________________________________________________________ ;; BINBIN MACRO REG ;; ;;05.10.86 ;;Inline Makro zum Konvertieren einer Binaerziffer aus REG in ;;eine Binaerdarstellung (Folge von '0' bzw. '1') ;;Wenn REG nicht definiert ist, so wird Register A ausgegeben. ;;Alle Register unveraendert ;;benoetigtes Makro: PCHAR ;; LOCAL around, bit? push af IF NOT NUL REG ld a,REG ENDIF call binb? pop af IF NOT BNFLAG jr around binb?: push bc ld c,a ld b,8 bit?: sla c ;CARRY setzen, wenn Bitstelle = 1 ld a,'0'/2 adc a,a ;in A Wert fuer 0 oder 1 PCHAR djnz bit? pop bc ret BNFLAG ASET TRUE ENDIF around: ;BINBIN ENDM ;;____________________________________________________________ ;; BELL MACRO ;; ;;17.04.86 ;;Inline Makro zur Ausgabe eines Fehlertones ;;Alle Register unveraendert ;;benoetigtes Makro: PCHAR ;; LOCAL around call bell? IF NOT BLFLAG jr around bell?: push af PCHAR BELL ;Tonausgabe pop af ret BLFLAG ASET TRUE ENDIF around: ;;BELL ENDM ;;____________________________________________________________ ;; CLOSE MACRO POINTR ;; ;;02.10.86 ;;Inline-Makro zum Schliessen einer neuen Datei. ;;POINTR zeigt auf den File-Control-Block. ;;Wenn POINTR nicht definiert ist, wird die Adresse aus dem ;;Registerpaar DE entnommen. ;;Wenn die Datei nicht existiert, wird zu DONE gesprungen. ;;Wenn das S2FLAG von SETUP2 wahr ist, wird mit Hilfe der ;;'DUP'-Merkzelle geprueft, ob die Originaldatei in *.BAK ;;und die neue Datei auf den Originalnamen umbenannt werden muss. ;;Register DE, AF veraendert ;;Der Bereiche FCB1 ist auf 05Ch vordefiniert. DFCB wird in ;;SETUP2 vereinbart. ;;benoetigte Makros: SYSF, ERRORM, OPEN, PRINT, MOVE, ;; DELETE, RENAME ;; LOCAL around, clos3? IF NOT NUL POINTR ld de,POINTR ENDIF call clos2? inc a ;Fehler, wenn A = 0FFh IF NOT S2FLAG jp nz,around ;SETUP2 Makro beachten ELSE jp z,clos3? ld a,(dupl) ;Namen duplizieren ? or a jp z,around ;nein MOVE 'BAK',FCB1+10h+9 MOVE FCB1+9,DFCB+10h+9,3 MOVE FCB1,FCB1+10h,9 MOVE DFCB,DFCB+10h,9 DELETE FCB1+10h ;'BAK' loeschen, falls vorhanden RENAME FCB1 ;Originalname in 'BAK' RENAME DFCB ;$$$ in Originalnamen MOVE 'BAK',FCB1+9 ;restauriere Namen OPEN FCB1 jp around ENDIF IF NOT CLFLAG clos3?: ERRORM 'Datei nicht gefunden?',DONE clos2?: SYSF 16 ;Datei schliessen CLFLAG ASET TRUE ENDIF around: ;;CLOSE ENDM ;;____________________________________________________________ ;; COMPAR MACRO FIRST, SECOND, BYTES ;; ;;09.05.86 ;;Inline-Makro zum Vergleich zweier Bereiche. ;;Das Z-Flag ist gesetzt, wenn beide Bereiche gleich sind. ;;Der erste und zweite Parameter koennen Adressen sein, ;;der dritte ist die Anzahl der Bytes. ;;Der erste Parameter darf eine Textkonstante sein. ;;In diesem Fall fehlt der dritte Parameter. ;;Jeder der Parameter darf fehlen. ;;Register AF wird veraendert. ;; ;;Anwendung: COMPAR FCB1,FCB2,12 ;; COMPAR '???',FCB1+9 ;; COMPAR ,,5 ;; LOCAL mesg, around push hl push de push bc IF NUL BYTES ld hl,mesg ;Textkonstante ld b,around-mesg ;Laenge des Textes ELSE ld b,BYTES ;Laenge als Parameter IF NOT NUL FIRST ld hl,FIRST ;1.Bereich in HL ENDIF ENDIF IF NOT NUL SECOND ld de,SECOND ;2.Bereich on DE ENDIF call comp2? pop bc pop de pop hl IF NOT CMFLAG or NUL BYTES jr around ENDIF ;; IF NOT CMFLAG comp2?: ld a,(de) cp (hl) ret nz inc hl inc de djnz comp2? ret ;; CMFLAG ASET TRUE ENDIF IF NUL BYTES mesg: db FIRST ;Textkonstante abspeichern ENDIF around: ;;COMPAR ENDM ;;____________________________________________________________ ;; COMPRA MACRO FIRST, SECOND, BYTES ;; ;;09.05.86 ;;ASCII-Version (Bit 7 wird geloescht). ;;Inline-Makro zum Vergleich zweier Bereiche. ;;Das Z-Flag ist gesetzt, wenn beide Bereiche gleich sind. ;;Der erste und zweite Parameter koennen Adressen sein, ;;der dritte ist die Anzahl der Bytes. ;;Der erste Parameter darf eine Textkonstante sein. ;;In diesem Fall fehlt der dritte Parameter. ;;Jeder der Parameter darf fehlen. ;;Register A wird veraendert. ;; ;;Anwendung: COMPRA FCB1,FCB2,11 ;; COMPRA 'COM',FCB1+9 ;; COMPRA ,FCB1+1,11 ;; LOCAL mesg, around push hl push de push bc IF NUL BYTES ld hl,mesg ;Textkonstante ld b,around-mesg ;Laenge des Textes ELSE ld b,BYTES ;Laenge als Parameter IF NOT NUL FIRST ld hl,FIRST ;1.Bereich in HL ENDIF ENDIF IF NOT NUL SECOND ld de,SECOND ;2.Bereich on DE ENDIF call comp2? pop bc pop de pop hl IF NOT CPFLAG or NUL BYTES jr around ENDIF ;; IF NOT CPFLAG comp2?: ld a,(de) sub (hl) and 7Fh ret nz inc hl inc de djnz comp2? ret ;; CPFLAG ASET TRUE ENDIF IF NUL BYTES mesg: db FIRST ;Textkonstante abspeichern ENDIF around: ;;COMPAR ENDM ;;____________________________________________________________ ;; CRLF MACRO ;; ;;19.04.86 ;;Inline-Makro fuer die Ausgabe der Zeichen ;;CR und LF zum Beginn einer neuen Zeile ;;Alle Register bleiben erhalten ;;benoetigtes Makro: PCHAR ;; LOCAL around call crlf2? IF NOT CRFLAG jr around crlf2?: push af PCHAR CR ;CR an Konsole PCHAR LF ;LF an Konsole pop af ret CRFLAG ASET TRUE ENDIF around: ;;CRLF ENDM ;;____________________________________________________________ ;; DELETE MACRO POINTR, WHERE ;; ;;12.09.86 ;;Inline-Makro zum Loeschen einer Datei. POINTR zeigt auf den ;;File-Control-Block der Datei. Ist die Datei schreibgeschuetzt, ;;erfolgt eine Abfrage. Bei ein wird die Datei nicht ge- ;;loescht, und das Programm bei WHERE fortgesetzt. Ist WHERE ;;nicht definiert, so Sprung zur globalen Marke DONE. ;;Register DE und AF veraendert. ;;Achtung !! Vor einem DELETE muss die Datei mit OPEN eroeffnet ;;~~~~~~~~~~ sein. ;; ;;benoetigte Makros: SYSF, UNPROT, READCH, PFNAME, ;; UCASE, PRINT, CRLF ;; ;;Anwendung: DELETE FCB1, FEHLER ;; LOCAL around, del3? ld de,POINTR ld a,(POINTR+9) bit 7,a ;Schreibgeschuetzt ? jp z,del3? ;nein CRLF ;ja PFNAME POINTR ;Ausgabe des Filenamens PRINT <' -- Datei schreibgeschuetzt! Loeschen (J/N) ',BELL> READCH UCASE cp 'J' ;Loeschen ? IF NOT NUL WHERE jp nz,WHERE ;nein ELSE jp nz,DONE ;nein, wenn WHERE nicht definiert ENDIF UNPROT POINTR ;Schreibschutz aufheben del3?: call del2? IF NOT DEFLAG jr around del2?: SYSF 19 ;Datei loeschen DEFLAG ASET TRUE ENDIF around: ;;DELETE ENDM ;;____________________________________________________________ ;; ENTER MACRO ;; ;;08.05.86 ;;Inline-Makro zum Retten des uebergebenen Stack-Pointers ;; ld (oldstk),sp ld sp,stack ;;ENTER ENDM ;;____________________________________________________________ ;; ERRORM MACRO TEXT, WHERE ;; ;;05.08.86 ;;Makro fuer die Ausgabe einer Nachricht auf die Konsole. ;;Die Nachricht muss in Apostrophe eingeschlossen werden. ;;Wenn WHERE fehlt, wird ein Sprung zu DONE ausgefuehrt. ;;Register AF veraendert ;;Benoetigte Makros: PRINT, CRLF, BELL ;; ;;Anwendung: ERRORM 'Falsche Eingabe' ;; ERRORM 'File existiert nicht !', open CRLF PRINT BELL IF NUL WHERE jp DONE ;globale Marke DONE ELSE jp WHERE ENDIF ;;ERRORM ENDM ;;____________________________________________________________ ;; EXIT MACRO WHERE?, SPACE? ;; ;;08.05.86 ;;Inline-Makro zur Wiederherstellung des alten Stack-Pointers ;;und Sprung zu Adresse WHERE? ;;Fehlt WHERE? wird ein RET-Befehl ausgefuehrt. ;;SPACE? definiert den Stackbereich; Standard ist 34 Byte. ;; ld sp,(oldstk) IF NUL WHERE? ret ELSE jp WHERE? ENDIF ; oldstk: ds 2 ;uebergebener Stack-Pointer IF NUL SPACE? ds 34 ELSE ds SPACE? ENDIF stack: ;;EXIT ENDM ;;____________________________________________________________ ;; FILL MACRO ADDR, BYTES, CHAR ;; ;;05.10.86 ;;Inline-Makro zum Fuellen eines Bereiches ab der Adresse ;;ADDR und der Laenge BYTES mit dem Zeichen CHAR. ;;Fehlt ADDR, wird HL verwendet. Fehlt BYTES, wird die ;;Anzahl aus BC uebernommen. ;;Alle Register unveraendert. ;; ;;Anwendung: FILL FCB+1,8,BLANK ;; FILL FCB+9,3,'?' ;; LOCAL fill2, around push hl push bc IF NOT NUL ADDR ld hl,ADDR ;;ADDR darf fehlen, dann HL ENDIF IF NOT NUL BYTES ld bc,BYTES ;;Wenn BYTES nicht angegen, ENDIF ;;dann BC call fill? pop bc pop hl IF NOT FLFLAG jr around fill?: push af fill2: ld (hl),CHAR ;;Bereich fuellen inc hl dec bc ld a,c or b jr nz,fill2 pop af ret FLFLAG ASET TRUE ENDIF around: ;;FILL ENDM ;;____________________________________________________________ ;; GOTOXY MACRO ROW, COLUMN ;; ;;19.05.86 ;;Inline-Makro zur direkten Cursor-Positionierung ;;ROW legt die Zeile fest und COLUMN die Spalte. ;;Wenn die Parameter nicht definiert sind, wird ;;der Wert fuer ROW aus dem Register H und der ;;Wert fuer COLUMN aus dem Register L entnommen. ;;ROW = [0...15(23)] COLUMN = [0...63(79)] ;;Alle Register unveraendert ;;benoetigtes Makro: PCHAR ;; ;;Anwendung: GOTOXY 2,12 ;; GOTOXY 1, ;; LOCAL around push hl IF NOT NUL ROW ld h,ROW ;in H Zeilenwert ENDIF IF NOT NUL COLUMN ld l,COLUMN ;in L Spaltenwert ENDIF call gxy? pop hl IF NOT GOFLAG jr around gxy?: push af PCHAR ESC ;ESC als Cursorsequenzbeginn set 7,h PCHAR h ;Zeile (mit Bit 7 = 1) set 7,l PCHAR l ;Spalte (mit Bit 7 = 1) pop af ret GOFLAG ASET TRUE ENDIF around: ;;GOTOXY ENDM ;;____________________________________________________________ ;; GFNAME MACRO FCB ;; ;;06.08.86 ;;Inline-Makro fuer die Eingabe eines Filenamens von der Konsole ;;und Speicherung im FCB. Kleinbuchstaben werden in Grossbuchsta- ;;ben umgewandelt. ;;FCB zeigt auf den File-Control-Block. ;;(Subroutine GETCH ist Bestandteil des Makros READB) ;;Register AF veraendert ;;benoetigte Makros: READB, FILL, UCASE, CRLF, BELL ;; ;;Anwendungen: GFNAME FCB1 LOCAL around, pname, ename, exten, gchar, gnam1, gnam2 push hl push de push bc ld hl,FCB ld (fcbs?),hl ;Abspeichern des Zeigers in fcbs? call gnam? ;fcbs? ist global verfuegbar! pop bc pop de pop hl IF NOT FNFLAG jp around fcbs?: ds 2 ;Zeiger auf FCB gnam?: CRLF jr gnam1 gnam2: BELL gnam1: PRINT ld hl,(fcbs?) ld (hl),0 ;Standardlaufwerk vordefinieren inc hl FILL ,11,BLANK ;Namen mit Leerzeichen fuellen ex de,hl READB ;Eingabe call getch ;1. Zeichen holen jp c,gnam2 ;neue Eingabe, wenn Puffer leer cp BLANK ;neue Eingabe bei Leerzeichen jp z,gnam2 UCASE ld (de),a ;1. Zeichen in FCB call getch ;2. Zeichen holen ret c ;Name nur aus einem Zeichen cp BLANK ret z ;wie oben ld b,7 ;in B Laenge - 1 UCASE cp '.' jr z,ename ;Sprung zur Namenserweiterung cp ':' ;Laufwerksangabe ? jr nz,pname ;nein ld a,(de) ;ja, erstes Zeichen zurueck sub 'A'-1 ;Binaerwert des Laufwerkes dec de ld (de),a ;eintragen call getch ;3. Zeichen holen jp c,gnam2 ;neuer Name, da nur Laufwerk UCASE inc b ;noch max. 8 Zeichen erwarten pname: inc de ;Dateiname eintragen ld (de),a call getch ret c cp BLANK ret z UCASE cp '.' ;Beginn der Namenserweiterung ? jr z,ename ;ja djnz pname jp gnam2 ;Fehler, mehr als 8 Zeichen ename: ld hl,(fcbs?) ld de,9 add hl,de ;DE auf Beginn der Namenserweiterung ex de,hl ld b,3 exten: call getch ret c cp BLANK ret z UCASE ld (de),a inc de djnz exten ret ;Dateiname komplett FNFLAG ASET TRUE ENDIF around: ;;GFNAME ENDM ;;____________________________________________________________ ;; HEXHL MACRO ;; ;;05.08.86 ;;Inline-Makro zum Konvertieren von ASCII-Hex-Zeichen ;;im Puffer in eine 16-bit Binaerzahl in HL. ;;Die Zeichenfolge ist durch POINTR adressiert. ;;Carry-Flag wird bei ungueltigen Hex-Zeichen gesetzt. ;;Register AF,HL veraendert ;; !! Achtung !! vor dem Aufruf von HEXHL muss der ;; ~~~~~~~~~~~~~ Puffer mit READB gefuellt werden. ;;benoetigte Makros: READB, UCASE ;; LOCAL around, rdhl2, nib? call rdhl? IF NOT HXFLAG ;nur eine Kopie jp around rdhl?: ld hl,0 ;Startwert 0 in HL rdhl2?: call getch ;Zeichen aus Konsolenpuffer ccf ;lesen ret nc ;Ende der Zeile - Return UCASE ;Zeichen in Grossbuchstabe call nib? ;Binaerwandlung ret c ;Fehler ! add hl,hl add hl,hl add hl,hl ;HL = HL * 16 add hl,hl or l ;neue Stelle einfuegen ld l,a jp rdhl2? nib?: sub '0' ;ASCII-Grundwert subtrahieren cp 10 ccf ret nc ;0..9 sub 'A'-'0' cp 6 ccf ret c ;nicht A..F add a,10 ret HXFLAG ASET TRUE ENDIF around: ;;HEXHL ENDM ;;____________________________________________________________ ;; HLDEC MACRO ;; ;;05.10.86 ;;Inline-Makro fuer die Ausgabe von HL als Dezimalzahl. ;;Register AF veraendert. ;;benoetigtes Makro: PCHAR ;; LOCAL around, subtr, subt2, nzero call hldc? IF NOT DCFLAG jr around hldc?: push hl push de push bc ld b,0 ;Flag fuer fuehrende Nullen ld de,-10000 ;Zehntausender call subtr ld de,-1000 ;Tausender call subtr ld de,-100 ;Hunderter call subtr ld de,-10 ;Zehner call subtr ld a,l add a,'0' ;Einer ausgeben PCHAR pop bc pop de pop hl ret subtr: ld a,'0'-1 subt2: inc a add hl,de ;negative Zahl addieren jr c,subt2 sbc hl,de ;Korrektur cp '0' ;Ausgabewert = '0' ? jr nz,nzero ;nein bit 0,b ;Testen Nullflag ret z ;fuehrende Null unterdruecken nzero: ld b,1 ;Flag setzen PCHAR ret DCFLAG ASET TRUE ENDIF around: ;HLDEC ENDM ;;____________________________________________________________ ;; LCHAR MACRO PAR ;; ;;05.08.86 ;;Inline-Makro zum Drucken eines Zeichens. ;;Wenn PAR fehlt, wird Register A zur Uebernahme verwendet. ;;Register AF veraendert ;;benoetigtes Makro: SYSF ;; ;;Anwendung: LCHAR ;; LCHAR '*' ;; LCHAR (hl) ;; LOCAL around IF NOT NUL PAR ld a,PAR ENDIF call lch2? IF NOT LOFLAG jr around lch2?: SYSF 5,AE ;drucke Zeichen LOFLAG ASET TRUE around: ;;LCHAR ENDM ;;____________________________________________________________ ;; LDFILE MACRO FCB, POINTR, CHAR ;; ;;02.10.86 ;;Inline-Makro zum Einlesen einer Datei in den Speicher ab der ;;der Adresse in (POINTR). ;;POINTR muss auf Ende des Hauptprogrammes gelegt werden. ;;HL zeigt auf das Ende des geladenen Files. ;;FCB zeigt auf den File-Control-Block. ;;Der optionale Parameter CHAR wird nach jedem Sektor ausgegeben. ;;CCP kann ueberschrieben werden; BDOS ist geschuetzt. ;;Das Carry-Flag ist gesetzt, wenn die Datei zu gross ist. ;;Die DMA-Adresse steht nach Programmende wieder auf 80h. ;;Bei Anwendung von LDFILE und WRFILE ist folgende Datenbereichs- ;;organisation zu empfehlen: ;;Register AF,HL,DE veraendert ;;pointr: dw buffer ;;buffer: ds 1 ;Puffer bis max. BDOS-Anfang ;; END ;;benoetigte Makros: SETDMA, READS ;; ;;Anwendung: LDFILE FCB1,DBUFFP,'*' ;; LDFILE 05Ch,BUFFP ;; load2?: SETDMA (POINTR) READS FCB,CHAR jr nz,load3? ;fertig, wenn nicht Null ld hl,(POINTR) ld de,80h add hl,de ;Bufferzeiger aktualisieren ld (POINTR),hl ld a,(7) ;in A H-Teil der BDOS-Adresse sub 2 ;zwei Bloecke zurueck cp h ;HL zu gross ? jp nc,load2? ;nein, weiter load3?: push af ;Carry-Flag retten SETDMA 80h ;DMA zurueck pop af ;;LDFILE ENDM ;;____________________________________________________________ ;; MAKE MACRO POINTR ;; ;;12.09.86 ;;Inline-Makro zum Erstellen einer neuen Datei. ;;POINTR zeigt auf den File-Control-Block. ;;Extend und laufende Satznummer werden geloescht. ;;Bei Fehler wird die globale Marke DONE angesprungen. ;;Register DE und AF werden veraendert. ;;Benoetigte Makros: SYSF, ERRORM ;; ;;Anwendung: MAKE FCB1 ;; LOCAL around ld de,POINTR xor a ld (POINTR+12),a ;Extend loeschen ld (POINTR+32),a ;laufende Satznummer loeschen call make2? inc a ;0 = Ok. , FF = Fehler jp nz,around ERRORM <'Directory voll !',7>,DONE IF NOT MKFLAG make2?: SYSF 22 ;erzeuge eine Datei MKFLAG ASET TRUE ENDIF around: ;;MAKE ENDM ;;____________________________________________________________ ;; MOVE MACRO FROM, TO, BYTES ;; ;;08.05.86 ;;Inline-Makro zum Umspeichern von Text. ;;FROM ist der Anfang des Quellbereiches, ;;TO der Anfang des Zielbereiches und ;;BYTES charakterisiert die Bereichslaenge ;;Ueberlappungen werden nicht beachtet! ;;Alle Register unveraendert ;; ;;Anwendung: MOVE TEXT1,TEXT2,TEXT2-TEXT1 ;; MOVE <2,'SUBMIT'>,FCB2 ;; MOVE 'HALLO!',BUFFER ;; LOCAL around, mesg push hl push de push bc IF NOT NUL TO ;;wenn TO nicht definiert, ld de,TO ;;wird DE als Ziel angenommen ENDIF IF NUL BYTES ;;Textkonstante speichern, ld hl,mesg ;;wenn BYTES nicht definiert ld bc,around-mesg ELSE IF NOT NUL FROM ;;wenn FROM nicht definiert, ld hl,FROM ;;wird HL als Quelle angenommen ENDIF ld bc,BYTES ;;BC enthaelt Textlaenge ENDIF ldir ;;Transfer pop bc pop de pop hl IF NUL BYTES jr around ;; mesg: db FROM ;;Textkonstante ENDIF around: ;;MOVE ENDM ;;____________________________________________________________ ;; OPEN MACRO POINTR, WHERE ;; ;;06.08.1986 ;;Inline-Makro fuer die Eroeffnung einer existierenden Datei. ;;POINTR zeigt auf den File-Control-Block der Datei. ;;Extend und laufende Satznummer werden geloescht. ;;Sprung nach WHERE, wenn die Datei nicht existiert. ;; ;;Fehlt WHERE, so erfolgt eine Fehlermeldung und ein Sprung ;;zu einer globalen Marke DONE, die im Hauptprogramm definiert ;;sein muss!!! ;;Register AF,DE veraendert ;;Benoetigte Makros: SYSF, ERRORM ;; ;;Anwendung: OPEN FCB1,CONT1 ;; OPEN 005Ch LOCAL around ld de,POINTR xor a ld (POINTR+12),a ;Extend und laufende ld (POINTR+32),a ;Satznummer loeschen call open2? inc a ;0=Ok., 0FFh heisst Fehler jr nz,around IF NUL WHERE ERRORM 'Keine Quelldatei!',DONE ELSE jp WHERE ENDIF IF NOT OPFLAG open2?: SYSF 15 ;OPEN-Aufruf fuer BDOS OPFLAG ASET TRUE ENDIF around: ;;OPEN ENDM ;;____________________________________________________________ ;; OUTHEX MACRO REG ;; ;;17.04.1986 ;;Inline-Makro, um Binaerzahl in ;;REG in zwei Hex-Zeichen umzuwandeln und zu drucken. ;;Byte wird in A erwartet, wenn REG fehlt. ;;Register AF veraendert ;;benoetigtes Makro: PCHAR ;; LOCAL around, hex1? IF NOT NUL REG ld a, REG ENDIF call outhx? IF NOT CXFLAG jr around outhx?: push bc ld c,a ;A retten in C rrca rrca rrca rrca call hex1? ;oberes Halbbyte ld a,c call hex1? ;unteres Halbbyte ld a,c ;A zurueck pop bc ret hex1?: and 15 ;Ausgabe Halbbyte add a,90h daa adc a,40h ;ASCII-Wert erzeugen daa PCHAR ;Makro fuer Ausgabe ret CXFLAG ASET TRUE ENDIF around: ;;OUTHEX ENDM ;;____________________________________________________________ ;; OUTHL MACRO ;; ;;05.10.86 ;;Inline-Makro fuer die Anzeige von HL in hexadezimaler Form. ;;Register AF veraendert. ;;benoetigtes Makro: OUTHEX ;; OUTHEX h OUTHEX l ;;OUTHL ENDM ;;____________________________________________________________ ;; PCHAR MACRO PAR ;; ;;17.04.86 ;;Inline-Makro zum Ausgeben eines Zeichens auf die Konsole ;;Parameter, falls angegeben, wird in das Register A geladen ;;Register AF veraendert ;;benoetigte Makros: SYSF ;; ;;Anwendung: PCHAR ;; PCHAR '*' ;; LOCAL around IF NOT NUL PAR ld a, PAR ENDIF call pch2? IF NOT COFLAG jr around pch2?: SYSF 2,AE COFLAG ASET TRUE ;nur einmal 'pch?' erzeugen ENDIF around: ;;PCHAR ENDM ;;____________________________________________________________ ;; PFNAME MACRO FCB ;; ;;12.09.86 ;;Inline-Makro zum Ausgeben eines Dateinamens aus einem File- ;;Control-Block FCB auf die Console. ;;Register AF veraendert. ;;benoetigtes Makro: PCHAR ;; ;;Anwendung: PFNAME FCB1 ;; LOCAL pfna1?, pfna2? push hl push bc ld bc,802h ;Namenslaenge ld hl,FCB+1 ;Namensanfang in HL pfna1?: ld a,(hl) ;Zeichen in A res 7,a cp blank ;Namensende ? jr z,pfna2? pfna2?: PCHAR inc hl djnz pfna1? ;max 8 Zeichen ausgeben ld b,4 ;Namenserweiterung ld hl,FCB+8 ld a,'.' dec c ;fertig ? jr nz,pfna2? ;nein pop bc ;ja, Register zurueck pop hl ;;PFNAME ENDM ;;____________________________________________________________ ;; PRINT MACRO TEXT, BYTES ;; ;;20.04.86 ;;Inline-Makro fuer die Ausgabe eines Textes auf die Konsole. ;;TEXT ist die Adresse des Textes, BYTES ist die Laenge. ;;TEXT darf in Apostrophe eingeschlossen sein, wenn ;;BYTES fehlt. ;;Register AF veraendert ;;benoetigtes Makro: PCHAR ;; ;;Anwendung: PRINT FCB1+1, 11 ;; PRINT 'Dateiende' ;; PRINT ;; PRINT , 12 ;; LOCAL around, mesg push hl push bc IF NUL BYTES ld hl,mesg ;in HL Anfangsadresse ld b,around-mesg ;Laenge des Textes in B ELSE IF NOT NUL TEXT ld hl,TEXT ENDIF ld b,BYTES ENDIF call pbuf? pop bc pop hl IF NOT PRFLAG or NUL BYTES jp around ENDIF IF NOT PRFLAG pbuf?: PCHAR (hl) ;Zeichenausgabe aus (HL) inc hl ;bis B = 0 djnz pbuf? ret PRFLAG ASET TRUE ENDIF IF NUL BYTES mesg: db TEXT ;Speicher fuer Text ENDIF around: ;;PRINT ENDM ;;____________________________________________________________ ;; READB MACRO ;; ;;11.05.86 ;;Inline-Makro fuer die Eingabe einer Zeile von der Konsole. ;;Puffer liegt am Ende des Makros. ;;Durch den Aufruf von READB wird die Eingabe einer Zeile vom ;;Bediener erwartet. Die max. Laenge ist hier mit 16 definiert. ;;Die eingegebenen Zeichen stehen im Puffer 'rbuf' zur Verfuegung. ;; ;;Die Zeichen werden durch Aufruf der globalen Subroutine GETCH ;;aus dem Puffer gelesen. Es wird das aktuelle Zeichen im Register A ;;uebergebenm und der Puffer-Zeiger inkrementiert. Wenn CARRY=1, ;;dann ist der Puffer leer. A ist in diesem Fall ungueltig. ;;Puffer-Zeiger RBUFP ist ebenfalls global. ;;Register AF veraendert ;; LOCAL around, rbufm, rbuf, rbufc, rbufe call rdb2? IF NOT RCFLAG jr around ;; rdb2?: push hl push de push bc ld de,rbufm ld c,10 call bdos ld hl,rbufm+2 ld (rbufm-2),hl pop bc pop de pop hl ret ;............................................................. ;globale Routine zum Lesen eines Zeichens aus dem Puffer getch: ld a,(rbufc) ;Zeichenzahl in A sub 1 ;minus 1 ret c ;CY=1, wenn Puffer leer ld (rbufc),a push hl ld hl,(rbufp) ld a,(hl) ;Zeichen lesen inc hl ;Pufferzeiger erhoehen ld (rbufp),hl pop hl ret ;CY=0 und Zeichen in A ; RCFLAG ASET TRUE ;nur eine Kopie ; rbufp: dw rbuf ;Zwischenspeicher fuer Zeiger rbufm: db rbufe-rbuf ;max. Pufferlaenge rbufc: ds 1 ;aktuelle Laenge rbuf: ds 16 ;Pufferanfang rbufe: ;Pufferende ENDIF around: ;;READB ENDM ;;____________________________________________________________ ;; READCH MACRO REG ;; ;;11.05.86 ;;Inline-Makro zum Lesen eines Zeichens von der Konsole. ;;Das Zeichen wird im Register A uebergeben, wenn der ;;zweite Parameter fehlt. ;;Register AF veraendert ;;benoetigtes Makro: SYSF ;; ;;Anwendung: READCH ;; READCH C ;; LOCAL around call rdch? IF NOT NUL REG ld REG,a ENDIF IF NOT CIFLAG jr around rdch?: SYSF 1 CIFLAG ASET TRUE ENDIF around: ;;READCH ENDM ;;____________________________________________________________ ;; READS MACRO POINTR, CHAR ;; ;;06.08.86 ;;Inline-Makro zum Lesen eines Sektors. ;;POINTR zeigt auf den File-Control-Block. ;;Wenn POINTR nicht definiert ist, wird die Adresse aus dem ;;Registerpaar DE entnommen. ;;Wenn CHAR angegeben wird, so erfolgt vor dem Lesen eines ;;jeden Sektors eine Ausgabe des Zeichens CHAR auf die Konsole. ;;Wenn das Dateiende erreicht ist, so ist Z-Flag = 0 ;;Register AF veraendert ;;benoetigtes Makro: SYSF, PCHAR ;; ;;Anwendungen: READS FCB1 ;; READS 005Ch, '*' LOCAL around IF NOT NUL CHAR PCHAR CHAR ;Zeichen ausgeben ENDIF IF NOT NUL POINTR ld de,POINTR ENDIF call read2? or a ;setze Z-Flag IF NOT RDFLAG jr around read2?: SYSF 20 ;Lesen des Sektors RDFLAG ASET TRUE ENDIF around: ;;READS ENDM ;;____________________________________________________________ ;; RENAME MACRO POINTR ;; ;;02.10.86 ;;Inline-Makro zum Umbenennen einer existierenden Datei. ;;POINTR zeigt auf Originalnamen. ;;Der neue Name steht auf POINTR + 10h. ;;Register DE, AF veraendert ;;benoetigtes Makro: SYSF, PRINT, UNPROT, CRLF ;; LOCAL around, ren2? ld de,POINTR ld a,(POINTR+9) bit 7,a ;Datei R/O ? jr z,ren2? ;nein UNPROT POINTR ;ja, Schutz aufheben ren2?: call renam? IF NOT RNFLAG jr around renam?: SYSF 23 ;BDOS-Funktion 'Umbenennen' RNFLAG ASET TRUE ENDIF around: ;RENAME ENDM ;;____________________________________________________________ ;; SETDMA MACRO POINTR ;; ;;06.08.86 ;;Inline-Makro zum Setzen der DMA-Adresse fuer das Lesen und ;;Schreiben von Sektoren. ;;Wenn POINTR nicht definiert ist, wird die Adresse aus dem ;;Registerpaar DE entnommen. ;;Register AF,DE veraendert ;;benoetigtes Makro: SYSF ;; LOCAL around IF NOT NUL POINTR ld de,POINTR ENDIF call dma2? IF NOT DMFLAG jr around dma2?: SYSF 26 ;DMA-Adresse setzen DMFLAG ASET TRUE ENDIF around: ;;SETDMA ENDM ;;____________________________________________________________ ;; SETUP2 MACRO ;; ;;12.09.86 ;;Inline-Makro zum Eroeffnen von zwei Dateien. Die Eingabe-Datei ;;ist die erste Datei einer Kommandozeile, deren File-Control- ;;Block FCB1 auf 05Ch liegt. Die Ausgabedatei ist der zweite ;;Parameter mit dem File-Control-Block FCB2, der zunaechst auf ;;06Ch liegt. Der FCB2 wird in den Makrobereich umgespeichert. ;;Wenn nur eine Datei angegeben wird oder beide gleich sind, ;;erhaelt die zweite Datei die Namenserweiterung '$$$'. Das ;;Makro CLOSE benennt die Originaldatei 'BAK' und gibt der Ziel- ;;datei den Originalnamen. Die Umbenennung in CLOSE erfolgt nur, ;;wenn das S2FLAG wahr ist. ;;Die Adressen fuer FCB1 und FCB2 sind auf 05Ch bzw. 06Ch vordefi- ;;niert. ;;Register AF,DE veraendert ;; ;;benoetigte Makros: MOVE, OPEN, MAKE, DELETE, ERRORM, ;; AMBIG, COMPAR ;; LOCAL around, set2?, set3?, set4? S2FLAG ASET TRUE ;Kennzeichnung fuer CLOSE ld a,(fcb2+1) cp blank ;zweiter Parameter vorhanden ? jr nz,set4? ;ja ;nein, Dateinamen und -typ duplizieren, Laufwerk erhalten MOVE FCB1+1, FCB2+1, 11 set4?: AMBIG FCB1, FCB2 ;'?' im Namen ersetzen COMPAR FCB1, FCB2, 12 ;beide gleich ? jr nz,set2? ;nein ld a,TRUE ;ja ld (dupl),a ;'DUP'-Flag setzen fuer CLOSE MOVE '$$$', FCB2+9 ;Scratch-Datei erzeugen set2?: MOVE FCB2, DFCB, 12 ;FCB2 in Makrobereich umspeichern OPEN FCB1 ;Quelldatei eroeffnen OPEN DFCB, set3? ;Zieldatei eroeffnen set3?: DELETE DFCB ;Zieldatei loeschen MAKE DFCB ;Zieldatei neu eroeffnen jr around dupl: db FALSE ;Flag fuer CLOSE dfcb: ds 33 ;Bereich fuer FCB2 around: ;;SETUP2 ENDM ;;___________________________________________________________ ;; SYSCHK MACRO SIGN, NR, TEXT ;; ;;06.10.86 ;;Inline-Makro zum Testen des Systemkennzeichens und der Ver- ;;sionsnummer des BIOS. Dieser Makro ist fuer hardwarespezi- ;;fische Programme notwendig. ;;SIGN ist 2-Byte-Text fuer Systemkennzeichen. ;;NR ist 3-Byte-Text fuer Versionsnummer des Betriebssystems. ;;TEXT ist die Fehlermeldung, wenn keine Systemuebereinstimmung ;;festgestellt wird. Es erfolgt ein Sprung zu globalen Marke ;;DONE. Bei der NR gelten groesser und gleich als gueltig. ;;Register AF,HL,DE veraendert ;;benoetigte Makros: ENTER, ERRORM, COMPAR ;; ;;Anwendung: SYSCHK 'BW',' 14','SCPX ab 1.4 erforderlich!' ;; LOCAL nrchk, syserr ENTER ld hl,(1) ;Adresse fuer BIOS+3 in HL ld de,30h ;Abstand bis zum Signum add hl,de ex de,hl COMPAR SIGN ;Testen des Systemkennzeichens jr z,nrchk syserr: ERRORM TEXT,DONE ;Fehlerausschrift, Sprung zu DONE nrchk: inc de inc de ;DE zeigt auf Versionsnummer COMPAR NR jp c,syserr ;NR ist kleiner ;;SYSCHK ENDM ;;___________________________________________________________ ;; SYSF MACRO FUNC,AE ;; ;;17.04.86 ;;Makro zum Generieren des BDOS-Aufrufes ;;FUNC ist die BDOS-Nummer fuer Register C ;;A wird nach E geladen, wenn der zweite Parameter angegeben ist ;;kein INLINE-MAKRO!! ;; ;;Anwendung: OPEN SYSF 15 ;; PCHAR SYSF 2, AE ;; push hl push de push bc ld c, FUNC ;in C BDOS-Nummer IF NOT NUL AE ld e,a ;fuer Konsole und Drucker push af ;retten von A call bdos pop af ELSE call bdos ENDIF pop bc pop de pop hl ret ;;SYSF ENDM ;;____________________________________________________________ ;; UCASE MACRO REG ;; ;;07.05.86 ;;Inline-Makro, um ein Zeichen in einem beliebigen ;;Register in einen Grossbuchstaben umzuwandeln. ;;Fehlt der Parameter wird Register A angenommen. ;;Nur Register AF bzw. 'REG' veraendert ;; ;;Anwendung: UCASE ;; UCASE C ;; LOCAL notup? IF NOT NUL REG bit 6,REG jr z,notup? res 5,REG ELSE bit 6,a ;Buchstabe? jr z,notup? ;nein res 5,a ;ja, umwandeln ENDIF notup?: ;;UCASE ENDM ;;____________________________________________________________ ;; UNPROT MACRO POINTR ;; ;;12.09.86 ;;Inline-Makro zum Aendern des Dateiattributs R/O in R/W. ;;POINTR zeigt auf den File-Control-Block. ;;Register DE und AF veraendert. ;;Benoetigtes Makro: SYSF ;; ;;Anwendung: UNPROT FCB1 ;; LOCAL around ld de,POINTR ld a,(POINTR+9) res 7,a ;setzen auf R/W ld (POINTR+9),a call unpr2? IF NOT UNFLAG jr around unpr2?: SYSF 30 UNFLAG ASET TRUE ENDIF around: ;;UNPROT ENDM ;;____________________________________________________________ ;; VERSN MACRO NUM ;; ;;08.05.86 ;;Inline-Makro zum Einfuegen der Versionsnummer. ;;NUM wird in Apostrophe eingeschlossen. ;;Alle Register unveraendert ;; ;; LOCAL around jr around db 'Ver ',NUM around: ;;VERSN ENDM ;;____________________________________________________________ ;; WRFILE MACRO FCB, POINTR, CHAR ;; ;;02.10.86 ;;Inline-Makro zum Schreiben einer Datei aus dem Speicher. ;;Der Puffer beginnt ab der Adresse POINTR+2. ;;(POINTR) zeigt auf das Ende der Datei. ;;FCB zeigt auf den File-Control-Block. ;;Der optionale Parameter CHAR wird nach jedem Sektor ausgegeben. ;;Die DMA-Adresse steht nach Programmende wieder auf 80h. ;;Bei Anwendung von LDFILE und WRFILE ist folgende Datenbereichs- ;;organisation zu empfehlen: ;;pointr: dw buffer ;;buffer: ds 1 ;Puffer bis max. BDOS-Anfang ;; END ;;Register AF,HL,DE veraendert ;;benoetigte Makros: WRITES, SETDMA, CRLF ;; ;;Anwendung: WRFILE FCB1,DBUFFP,'*' ;; WRFILE 05Ch,BUFFP ;; LOCAL wrfil?, even? ld de,(POINTR) ;Ende in DE ld hl,POINTR+2 ld (POINTR),hl ;Bufferanfang in HL ex de,hl or a sbc hl,de ;Laenge des Bereiches in HL ld a,l ld l,h ld h,0 add hl,hl ;in HL Anzahl der Sektoren or a jr z,even? inc hl ;ungerade Anzahl even?: push bc ld b,h ld c,l ;Sektoranzahl in BC wrfil?: SETDMA (POINTR) WRITES FCB,CHAR ;Sektor schreiben ld hl,(POINTR) ld de,80h add hl,de ;Bufferzeiger aktualisieren ld (POINTR),hl dec bc ;Sektoranzahl - 1 ld a,b or c ;= Null ? jp nz,wrfil? pop bc SETDMA 80h ;DMA zurueck ;;WRFILE ENDM ;;____________________________________________________________ ;; WRITES MACRO POINTR, CHAR ;; ;;02.10.86 ;;Inline-Makro zum Schreiben eines Sektors. ;;POINTR zeigt auf den File-Control-Block. ;;Wenn POINTR nicht definiert ist, wird die Adresse aus dem ;;Registerpaar DE entnommen. ;;CHAR ist ein Zeichen, das nach jedem Sektor auf die Console ;;ausgegeben wird, falls es definiert wurde. ;;Register DE, AF veraendert ;;benoetigte Makros: SYSF, PCHAR, ERRORM ;; LOCAL around IF NOT NUL CHAR PCHAR CHAR ENDIF IF NOT NUL POINTR ld de,POINTR ENDIF call writ2? or a ;Schreiben Ok. ? IF WRFLAG jp nz,nroom? ELSE jp z,around ;ja nroom?: ERRORM 'Diskette voll!',DONE writ2?º SYSF 21 ;Schreiben eines Sektors WRFLAG ASET TRUE ENDIF around: ;;WRITES ENDM ;;____________________________________________________________ .list ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ