aseg org 0100h wboot equ 0000h Bdos equ 0005h ESC equ 1bh CR equ 0dh LF equ 0ah jp start ;Die nachfolgenden Zellen muessen fuer den jeweiligen Computer ;angepasst werden ;cls ist die Zeichenfolge fuer Bildschirm loeschen ;Das erste Byte gibt die Anzahl der folgenden Zeichen an, die ;zwischen 1 und 4 liegen kann, wobei dies natrlich erweitert ;werden kann ;setc ist die Zeichenfolge fuer Cursor setzen ;Das erste Byte gibt die Anzahl der folgenden Zeichen an, die ;zwischen 1 und 4 liegen kann, wobei dies natrlich erweitert ;werden kann ;coloffset ist der Offset, der zur Spaltennummer addiert ;werden mua ;lineoffset ist der Offset, der zur Zeilennummer addiert ;werden mua ;Falls noetig, muss auch die Routine setcursor verndert, ;wenn z.B. Zeile und Spalte in umgekehrter Reihenfolge ;gesendet werden mua. Dazu kann man einfach das H-Register ;und das L-Register vertauschen. cls: defb 4 defb ESC,'E',ESC,'H' setc: defb 2 defb ESC,'Y',0,0 coloffset: defb 32 lineoffset: defb 32 readsec: ;einen physikalischen Sektor ld bc,Puffer ;lesen call setdma ld bc,(Track) call settrk ld hl,(Sector) ld a,(physshift) ld b,a rs1: srl h rr l djnz rs1 ld b,h ld c,l call setsec call read or a jr nz,readerr ld hl,(Sector) ld (lastsector),hl ld hl,(Track) ld (lasttrack),hl ld a,(Drive) ld (lastdrive),a ret readerr: push af ld de,rderrmsg call prtstr pop af ret rderrmsg: defb 'Lesefehler',Cr,Lf,'$' writesec: ;einen physikalischen Sektor ld bc,Puffer ;schreiben call setdma ld bc,(Track) call settrk ld hl,(Sector) ld a,(physshift) ld b,a ws1: srl h rr l djnz ws1 ld b,h ld c,l call setsec ld c,1 call write or a jr nz,wrterr ld hl,(Sector) ld (lastsector),hl ld hl,(Track) ld (lasttrack),hl ld a,(Drive) ld (lastdrive),a ret wrterr: push af ld de,wrerrmsg call prtstr pop af ret wrerrmsg: defb 'Schreibfehler',Cr,Lf,'$' prtstr: ;String auf Bildschirm ausgeben ld c,9 jp Bdos settrk: ld a,10 jr directbios setsec: ld a,11 jr directbios setdma: ld a,12 jr directbios read: ld a,13 jr directbios write: ld a,14 directbios: ld (biospb),a ld (biospb+2),bc ld c,32h ld de,biospb jp bdos biospb: defs 8 offset: ;Offset fuer den logischen push af ;Sektor im Puffer berechnen ld a,(physmaske) ld l,a ld a,(Lastsector) and l ld l,a ld h,0 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl pop af ret hexout: ;das Byte im Akku in Hex push af ;ausgeben srl a srl a srl a srl a call hexascii pop af and 0fh hexascii: cp 0ah jr c,noletter add a,07h noletter: add a,30h jp ttyout hexpruefen: ;Falls das Zeichen im Akku eine cp '0' ;Hex-Ziffer ist, so ist das ret c ;Carry-Flag nicht gesetzt cp 'F'+1 ccf ret c cp 'A' ret nc cp '9'+1 ccf ret incsec: ; Sektornummer um eins erhoehen ld hl,(Maxsector) ld de,(Sector) scf sbc hl,de jr c,inc1 inc de ld (Sector),de ret inc1: ld hl,(Maxtrack) ld de,(Track) scf sbc hl,de jr nc,inc2 ld hl,(Maxtrack) ld (track),hl ld hl,(Maxsector) ld (Sector),hl ret inc2: inc de ld (Track),de ld hl,0000h ld (Sector),hl ret decsec: ;Sektor nummer um eins ld hl,(Sector) ;erniedrigen ld a,h or l jr z,dec1 dec hl ld (Sector),hl ret dec1: ld hl,(Track) ld a,h or l jr nz,dec2 ret dec2: dec hl ld (Track),hl ld hl,(Maxsector) ld (Sector),hl ret ; Dezimalzahl einlesen ; in HL steht die Adresse auf den Zahlenstring ; Jedes andere Zeichen, das nicht im Bereich '0'..'9' ; liegt, beendet das Einlesen ; Das Ergebnis steht im HL-Register dezhex: ld de,0000H nextzif: ld a,(hl) cp '0' jr c,stringend cp '9'+1 jr nc,stringend ex de,hl add hl,hl ld b,h ld c,l add hl,hl add hl,hl add hl,bc sub 30h ld c,a ld b,0 add hl,bc ex de,hl inc hl jr nextzif stringend: ex de,hl ret HEXDEZ: ;Der Wert des hl-Register wird ex de,hl ;dezimal ausgegeben, und zwar LD A,0 ;rechtsbuendig fhrende Nullen LD B,3 ;werden unterdrueckt LD HL,L0200 L0107: LD (HL),A INC HL DJNZ L0107 LD B,10H L0112: EX DE,HL ADD HL,HL EX DE,HL PUSH BC LD B,3 LD HL,L0200 L011D: LD A,(HL) ADC A,(HL) DAA LD (HL),A INC HL DJNZ L011D POP BC DJNZ L0112 LD B,3 LD C,3*2 LD HL,L0200+2 NBYTE: LD A,(HL) CALL BYTEOUT DEC HL DJNZ NBYTE RET BYTEOUT: PUSH AF SRL A SRL A SRL A SRL A CALL DECOUT POP AF DECOUT: AND 0FH OR 030H DEC C JR Z,TTYOUT BIT 7,C JR NZ,TTYOUT CP '0' JR Z,ZERO SET 7,C ZERO: JR NZ,TTYOUT LD A,' ' TTYOUT: PUSH BC PUSH DE PUSH HL LD E,A LD C,2 CALL 5 POP HL POP DE POP BC RET L0200: ds 4 ttyin: ;Ein Zeichen von der Tastatur ld e,0fdh ;lesen ld c,6 jp bdos ; Maxsector, Maxtrack und physmaske bestimmen getdiskpar: ld c,31 call bdos ld a,(hl) inc hl push hl ld h,(hl) ld l,a dec hl ld (maxsector),hl pop hl inc hl ld b,(hl) inc hl inc hl inc hl ld a,(hl) inc hl push hl ld h,(hl) ld l,a inc hl diskpar: add hl,hl djnz diskpar ex de,hl ld hl,(Maxsector) inc hl ex de,hl ld a,h ld c,l call div ld d,a ld e,c ld a,l or h jr nz,diskpar1 dec de diskpar1: pop hl ld bc,7 add hl,bc ld c,(hl) inc hl ld b,(hl) push hl ex de,hl add hl,bc ld (Maxtrack),hl pop hl inc hl ld a,(hl) ld (physshift),a inc hl ld a,(hl) ld (physmaske),a ld de,String7 call prtstr ld hl,(Maxtrack) call hexdez ld de,String8 call prtstr ld hl,(Maxsector) call hexdez jp crlf String7: defb 'Maximale Spurnummer =$' String8: defb ' Maximale Sektornummer =$' div: ;Divisionsroutinc fuer 16 BIT ld hl,0 ;in AC steht der Dividend ld b,16 ;in DE der Divisor div1: ;in AC das Ergebnis rl c ;in HL der Rest rla adc hl,hl sbc hl,de jr nc,$+3 add hl,de ccf djnz div1 rl c ret delspace: ;fuehrende Leerzeichen ld a,(hl) ;ueberlesen cp ' ' ret nz inc hl jr delspace clrscr: ; Bildschirm loeschen ld hl,cls ld a,(hl) or a ret z ld b,a clr1: inc hl ld a,(hl) call ttyout djnz clr1 ret setcursor: ;Cursor setzen dec h ;Spalte im H-Register dec l ;Zeile im L-Register ex de,hl ld hl,setc ld a,(hl) or a ret z ld b,a set1: inc hl ld a,(hl) call ttyout djnz set1 ld a,(lineoffset) add a,e call ttyout ld a,(coloffset) add a,d jp ttyout sektorfestlegen: ;Sektor anzeigen,wenn keine Zahl call delspace ;dahinter angegeben ist, ld a,(hl) ;ansonsten Sektornummer einlesen or a jr z,Secf1 call dezhex ld (Sector),hl ex de,hl ld hl,(Maxsector) or a sbc hl,de ret nc add hl,de ld (Sector),hl ret Secf1: ld de,String5 call prtstr ld hl,(Sector) jp hexdez String5: defb 'Sektor =$' spurfestlegen: ;Spur anzeigen oder einlesen call delspace ld a,(hl) or a jr z,Spurf1 call dezhex ld (Track),hl ex de,hl ld hl,(Maxtrack) or a sbc hl,de ret nc add hl,de ld (Track),hl ret Spurf1: ld de,String6 call prtstr ld hl,(Track) jp hexdez String6: defb 'Spur =$' druck: ;falls das Zeichen im Akku auf call druckbar ;dem Bilds. nicht darstellbar jr nc,dr1 ;ist, dann wird stattdessen ein ld a,'.' ;Punkt ausgegeben dr1: jp ttyout druckbar: cp 32 ret c cp 127 ccf ret upcase: ;Alle Kleinbuchstaben werden in cp 'a' ;Grossbuchstaben umgewandelt ret c cp 'z'+1 ret nc sub 20h ret sektorausgeben: ;Sektor auf dem Bildschirm call clrscr ;ausgeben ld de,String1 call prtstr ld a,(LastDrive) add a,'A' call ttyout ld de,String2 call prtstr ld hl,(Lasttrack) call hexdez ld de,String3 call prtstr ld hl,(lastsector) call hexdez call crlf call crlf ld b,0 seca3: push bc ld a,b sla a sla a sla a sla a push bc call hexout ld a,' ' call ttyout ld a,' ' call ttyout pop bc ld c,0 seca1: push bc ld a,b sla a sla a sla a sla a add a,c ld c,a ld b,0 call offset ld de,puffer add hl,de add hl,bc ld a,(hl) call hexout ld a,' ' call ttyout pop bc inc c ld a,16 cp c jr nz,seca1 ld c,0 seca2: push bc ld a,b sla a sla a sla a sla a add a,c ld c,a ld b,0 call offset ld de,puffer add hl,de add hl,bc ld a,(hl) call druck pop bc inc c ld a,16 cp c jr nz,seca2 call crlf pop bc inc b ld a,8 cp b jr nz,seca3 ret String1: defb 'Laufwerk $' String2: defb ': Spur $' String3: defb ' Sektor $' poscurbyte: ; Cursor auf das entsprechende ld a,(curpos) ;Byte am Bilds. positionieren dec a ld c,a and 0fh ld b,a sla a add a,b ld b,a ld a,(highlow) add a,b ld b,5 add a,b ld h,a ld a,c srl a srl a srl a srl a inc a inc a inc a ld l,a jp setcursor poscurchar: ;Cursor auf das entsprechende ld a,(curpos) ;Zeichen am Bildschirm dec a ;positionieren ld c,a and 0fh ld b,53 add a,b ld h,a ld a,c srl a srl a srl a srl a inc a inc a inc a ld l,a jp setcursor cursorrechts: ;Cursor wird um ein Byte oder ld a,(ascii) ;ein Zeichen nach rechts bewegt or a jr z,cr1 ld a,(curpos) cp 128 ret z inc a ld (curpos),a ret cr1: ld a,(highlow) or a jr nz,cr2 inc a ld (highlow),a ret cr2: ld b,a ld a,(curpos) cp 128 ret z inc a ld (curpos),a xor a ld (highlow),a ret cursorlinks: ;Cursor wird um ein Byte oder ld a,(ascii) ;ein Zeichen nach links bewegt or a jr z,cl1 ld a,(curpos) cp 1 ret z dec a ld (curpos),a ret cl1: ld a,(highlow) or a jr z,cl2 dec a ld (highlow),a ret cl2: ld b,a ld a,(curpos) cp 1 ret z dec a ld (curpos),a ld a,1 ld (highlow),a ret cursoroben: ;Cursor wird um ein Byte oder ld a,(curpos) ;ein Zeichen nach oben bewegt cp 17 ret c sub 16 ld (curpos),a ret cursorunten: ;Cursor wird um ein Byte oder ld a,(curpos) ;ein Zeichen nach unten bewegt cp 113 ret nc add a,16 ld (curpos),a ret changebyte: ;im C-Register steht ein Hex- call offset ;Zeichen, wobei mit diesem der ld a,(curpos) ;hoeher- oder niederwertige Teil dec a ;des Bytes veraendert wird ld e,a ld d,0 add hl,de ld de,puffer add hl,de ld a,(highlow) or a jr nz,cb1 ld a,c call asciihex sla a sla a sla a sla a ld b,a ld a,(hl) and 0fh or b ld (hl),a ret cb1: ld a,c call asciihex ld b,a ld a,(hl) and 0f0h or b ld (hl),a ret asciihex: ;Ascii nach hex umwandeln sub 30h cp 0ah ret c sub 7 ret sektoreditieren: ;Sektor im Puffer editieren xor a ld (highlow),a ld (Ende),a ld (ascii),a inc a ld (curpos),a call sektorausgeben se0: ld hl,se4 push hl ld h,40 ld l,1 call setcursor ld de,String4 call prtstr ld a,(curpos) ld l,a ld h,0 call hexdez ld a,(ascii) or a push af call z,poscurbyte pop af call nz,poscurchar call ttyin ld b,a ld a,(ascii) or a ld a,b call z,upcase cp ESC jr nz,se1 ld a,0ffh ld (ende),a ret se1: cp 'D'-'@' jp z,cursorrechts cp 'S'-'@' jp z,cursorlinks cp 'E'-'@' jp z,cursoroben cp 'X'-'@' jp z,cursorunten cp 'C'-'@' jr nz,se2 ld a,(ascii) cpl ld (ascii),a ret se2: ld b,a ld a,(ascii) or a ld a,b jr nz,se3 call hexpruefen ret c push af call ttyout pop af ld c,a call changebyte call poscurchar call offset ld a,(curpos) dec a ld e,a ld d,0 ld bc,puffer add hl,de add hl,bc ld a,(hl) call druck jp cursorrechts se3: call druckbar ret c push af call ttyout call offset ld a,(curpos) dec a ld e,a ld d,0 pop af ld bc,puffer add hl,de add hl,bc ld (hl),a push af xor a ld (highlow),a call poscurbyte pop af call hexout jp cursorrechts se4: ld a,(ende) or a jp z,se0 ld h,1 ld l,12 jp setcursor String4: defb 'Byte $' Laufwerkselektieren: ;Entsprechendes Laufwerk ld a,(hl) ;auswaehlen or a jr nz,ls1 ld a,'A' ls1: call upcase sub 'A' ld (drive),a ld c,14 ld e,a call bdos jp getdiskpar CRLF: ld a,CR call ttyout ld a,LF jp ttyout keinplus: ld de,String9 call prtstr jp 0 String9: defb CR,LF,'Dieses Programm laeuft' defb ' nur unter CP/M 3.X$' Start: ld c,0ch call bdos ld a,2fh cp l jr nc,keinplus ld hl,0 ld (track),hl ld (sector),hl ld (lasttrack),hl ld (lastsector),hl xor a ld (quit),a call getdiskpar ld c,25 call bdos ld (drive),a ld (lastdrive),a call readsec s0: ld hl,s8 push hl call crlf ld a,'?' call ttyout ld a,' ' call ttyout ld de,Befehl ld a,8 ld (de),a ld c,10 call bdos ld hl,befehl+1 ld c,(hl) ld b,0 inc hl push hl add hl,bc xor a ld (hl),a pop hl call delspace ld a,(hl) inc hl call upcase cp 'T' jr nz,s1 jp spurfestlegen s1: cp 'S' jr nz,s2 jp sektorfestlegen s2: cp 'R' jr nz,s3 call readsec call z,sektorausgeben ret s3: cp 'W' jr nz,s4 jp writesec s4: cp '+' jr nz,s5 call incsec call readsec call z,sektorausgeben ret s5: cp '-' jr nz,s6 call decsec call readsec call z,sektorausgeben ret s6: cp 'D' jp z,sektorausgeben cp 'E' jp z,sektoreditieren cp 'L' jr nz,s7 call delspace jp laufwerkselektieren s7: cp 'Q' jr nz,s8 ld a,0ffh ld (quit),a ret s8: ld a,(quit) or a jp z,s0 jp wboot Drive: defb 0 Lastdrive: defb 0 Track: defw 0 Lasttrack: defw 0 Sector: defw 0 Lastsector: defw 0 Maxtrack: defw 0 Maxsector: defw 0 Quit: defb 0 Ende: defb 0 highlow: defb 0 ascii: defb 0 curpos: defb 0 physmaske: defb 0 physshift: defb 0 Befehl: defs 10 Puffer: end