home *** CD-ROM | disk | FTP | other *** search
- (* ----------------------------------------------------------------------- *)
- (* SHARPGRF.PAS *)
- (* Grafik auf dem Sharp MZ800 mit Turbo Pascal *)
- (* Bruno Volkmer 1987, fuer PASCAL INTERNATIONAL *)
-
- TYPE graf_code = ARRAY[1..11] OF BYTE;
-
- CONST (* Maschinen-Routinen: *)
- toVideo : graf_code = ($f3,$47,$db,$e0,$d3,$e0,$70,$db,$e1,$fb,$c9);
- fromVideo : graf_code = ($f3,$db,$e0,$d3,$e0,$46,$db,$e1,$78,$fb,$c9);
- copyVideo : graf_code = ($f3,$db,$e0,$ed,$b0,$db,$e1,$fb,$c9, 0, 0);
-
- PALPort = $f0; (* verantwortlich fuer die Farbe *)
- ModePort = $ce; (* Bildschirmaufloesung *)
- ReadPort = $cd; (* von welcher Bildebene wird gelesen *)
- WritePort = $cc; (* in welche Ebene wird geschrieben *)
- (* und wie werden Werte verknuepft *)
- ScreenXmax = 639;
- ScreenYmax = 191; (* wegen der Statuszeile 200-8 *)
- VideoBegin = $8000; (* Adresse des Videorams *)
- VideoRAM = $4000; (* Groesse des Videorams, 16kB *)
- VideoSize = 2048; (* Buffer zum Speichern des Bildes *)
-
- TYPE MaxColor = 0..15;
- SysColors = (Black, Blue, Red, Magenta, Green, Cyan, Brown,
- LightGray, DarkGray, LightBlue, LightRed, LightMagenta,
- LightGreen, LightCyan, Yellow, White);
- PicName = STRING [14];
- Planes = 0..3;
-
- VAR
- VideoIn : graf_code ABSOLUTE $130; (* Lage der Umleitungen *)
- VideoOut : graf_code ABSOLUTE $140;
- VideoCop : graf_code ABSOLUTE $170 ;
- TextPlane : BYTE ABSOLUTE $FD52; (* TextColor *)
- (* ----------------------------------------------------------------------- *)
- PROCEDURE InitGrafik; (* initialisiert und aktiviert Grafik *)
- BEGIN
- ClrScr;
- VideoIn := toVideo; (* ML-Routinen eintragen ,'poken' *)
- VideoOut := fromVideo;
- VideoCop := copyVideo;
- Mem[$ee29] := 01; (* Patch des BIOS fuer 4 Farben *)
- Mem[$ee2a] := 05;
- Mem[$ee37] := 06; (* Modus 6, wie im Basic *)
- Mem[$e092] := $27; (* Ebene 2 = Farbe 7 *)
- Mem[$e093] := $3c; (* Ebene 3 = Farbe 12 *)
- INLINE ($cd/$ee1d); (* zur Initialisierung notwendig *)
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE VideoPoke (adr: INTEGER; wert: BYTE);
- BEGIN
- INLINE ($3a/wert/$2a/adr/$cd/$130);
- END; (* LD A,(wert) LD HL,(adr) CALL toVideo *)
-
- FUNCTION VideoAddr (x,y: INTEGER): INTEGER;
- BEGIN VideoAddr := y * 80 + x SHR 3 + VideoBegin; END;
- (* ----------------------------------------------------------------------- *)
- (* Fuellt Farbtopf (Plane = 0,1,2 oder 3) mit gewuenschter Farbe: *)
- PROCEDURE SetColor (Plane: Planes; Color: SysColors);
- BEGIN
- Port[PALPort] := (Ord(Color)) OR ((Plane*16) AND $30);
- END;
-
- PROCEDURE SetPalette (Col0, Col1, Col2, Col3: SysColors); (* klar ?! *)
- BEGIN
- SetColor(0,Col0); SetColor(1,Col1); SetColor(2,Col2); SetColor(3,Col3);
- END;
- (* ----------------------------------------------------------------------- *)
- (* waehlt Farbtopf fuer folgende Zeichen-Operationen aus: *)
- PROCEDURE Color (Col: Planes);
- VAR temp: BYTE;
- BEGIN
- temp := Col; (* Farbtopfnummer an Ebene anpassen: *)
- IF temp > 1 THEN temp := temp + 2;
- temp := temp AND 5; Port[WritePort] := temp OR $C0;
- END;
-
- (* setzt einen Punkt in der Farbe des mit Color() ausgewaehlten Farbtopfes *)
- PROCEDURE SetPixel (x,y: INTEGER);
- VAR adr: INTEGER; wert: BYTE;
- BEGIN
- IF (x > -1) AND (x <= ScreenXmax) AND (y > -1) AND (y <= ScreenYmax) THEN
- BEGIN
- adr := VideoAddr(x,y); wert:= 1 SHL (x AND 7); VideoPoke (adr,wert);
- END;
- END;
-
- (* setzt einen Punkt mit der Farbe aus dem mit Col gewaehlten Farbtopf: *)
- PROCEDURE Plot (x,y: INTEGER; Col: Planes);
- BEGIN Color(Col); SetPixel(x,y); END;
-
- PROCEDURE Draw (ax,ay,bx,by: INTEGER; Col: Planes); (* dito, eine Linie *)
- VAR xdiff, ydiff, xstep, ystep, summe, merker: INTEGER;
- BEGIN
- Color(Col);
- IF (ax <> bx) OR (ay <> by) THEN BEGIN
- xdiff := bx-ax; ydiff := by-ay; xstep := 1; ystep := 1;
- IF xdiff < 0 THEN BEGIN xstep := -1; xdiff := abs(xdiff); END;
- IF ydiff < 0 THEN BEGIN ystep := -1; ydiff := abs(ydiff); END;
- IF xdiff <> 0 THEN summe := 0 ELSE summe := -1;
- merker := summe;
- REPEAT
- IF summe < 0 THEN BEGIN ay := ay+ystep; summe := summe+xdiff END
- ELSE BEGIN ax := ax+xstep; summe := summe-ydiff; END;
- IF (merker < 0) OR (summe > -1) THEN SetPixel (ax,ay);
- merker := summe;
- UNTIL (ax = bx) AND (ay = by);
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* Pixel aus Farbtopf abfragen: *)
- FUNCTION ColSearch (adr: INTEGER; Color: Planes): BYTE;
- VAR help, temp: BYTE;
- BEGIN
- temp := Color; IF temp > 1 THEN temp := temp + 2;
- INLINE ($3a/temp/$f6/$80/$d3/ReadPort/$2a/adr/$cd/$140/$32/help);
- (* LD A,(temp) OR $80 OUT($CD),A LD HL,(ADR) CALL fromVideo
- LD (help), A *)
- ColSearch := help;
- END;
-
- (* pruefen, ob Punkt aus dem genannten Farbtopf gesetzt ist. Wenn ja, ist *)
- (* GetPixel TRUE, sonst FALSE: *)
- FUNCTION GetPixel (x,y: INTEGER; Color: Planes): BOOLEAN;
- VAR inhalt, wert: BYTE; adr: INTEGER;
- BEGIN
- adr := VideoAddr(x,y); inhalt := ColSearch(adr,Color);
- wert := 1 SHL (x AND 7); GetPixel := (inhalt AND wert) <> 0;
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE TextColor (Color: Planes); (* Textfarbe setzen *)
- VAR temp: BYTE;
- BEGIN
- temp := Color; IF temp > 1 THEN temp := temp + 2; TextPlane := temp;
- END;
-
- PROCEDURE BORDER (Col: SysColors); (* Randfarbe setzen *)
- BEGIN INLINE (1/$6cf/$3a/Col/$ed/$79); END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE hardcopy; (* fuer den ITOH 8510 *)
- CONST esc = #27;
- normal = #27'A'; (* normaler Zeilenabstand *)
- eng = #27'T16'; (* Abstand 16/144 Zoll *)
- uni = #27#62; (* unidirektional *)
- bi = #27#60; (* bidirektional *)
- fett = #27'!'; (* doppelter Anschlag *)
- unfett = #27'"'; (* einfacher Anschlag *)
- gstring = #27'S0640'; (* es folgen 640 Grafikbytes *)
- CR = #13;
- maxzeile = 47; (* 48 Halbzeilen *)
- maxspalte = 79; (* 80 Bytes Breite *)
- TYPE feld8 = ARRAY [0..7] OF BYTE;
- VAR f: TEXT; DrZeile: 0..maxzeile; Drspalte: 0..maxspalte; code: feld8;
- k,nochmal : BYTE;
-
- PROCEDURE hol8BYTE (x,y: INTEGER; VAR code: feld8; Col: Planes);
- VAR adr, i: INTEGER; inhalt, wert2: BYTE;
- BEGIN
- adr := y * 320 + x + VideoBegin;
- FOR i := 0 TO 3 DO BEGIN
- inhalt := ColSearch(adr, Col);
- IF Col = 2 THEN wert2 := 0 ELSE wert2 := inhalt;
- code[i*2] := inhalt; (* Zur vertikalen Spreizung jede *)
- code[i*2+1] := wert2; (* Zeile in 2 Halbzeilen zerlegen *)
- adr := adr+80; (* und halbe Zeile doppeln *)
- END;
- END;
-
- PROCEDURE drucke (acht: feld8);
- VAR zeile, spalte: 0..7; drBYTE: feld8;
- BEGIN
- INLINE ($f3/$0e/8/$21/drBYTE/$36/0/6/8/ $11/acht/$1a/$cb/$3f/
- $12/$cb/$1e/$13/$10/$f7/$23/ $0d/$20/$ec/$fb);
- FOR spalte := 0 TO 7 DO Write(f,Chr(drBYTE[spalte]));
- END;
-
- BEGIN (* hardcopy *)
- Assign (f,'LST:'); WriteLn(f,uni,eng);
- WriteLn(f,esc,'N'); (* esc 'N' ist Schnellschrift, 640 Dots *)
- FOR DrZeile := 0 TO maxzeile DO BEGIN
- WriteLn(f); k := 1;
- FOR nochmal := 1 TO 3 DO BEGIN;
- IF k = 3 THEN Write(f,fett) ELSE Write (f,unfett);
- Write(f,gstring);
- FOR Drspalte := 0 TO maxspalte DO BEGIN
- hol8BYTE(Drspalte,DrZeile,code,k); drucke(code);
- END;
- Write(f,CR);
- IF k = 2 THEN k := 3 ELSE IF k = 1 THEN k := 2;
- END;
- END;
- WriteLn(f,bi,normal,unfett); WriteLn(f);
- END; (* hardcopy *)
- (* ----------------------------------------------------------------------- *)
- (* Die folgenden Routinen bitte selbst schreiben
- PROCEDURE moveto (x,y: INTEGER);
- PROCEDURE drawto (x,y: INTEGER; Col: Planes);
- PROCEDURE box (x1,y1,x2,y2: INTEGER; Col: Planes);
- PROCEDURE circle (mx,my,rd: INTEGER; elli: real; Col: Planes);
- PROCEDURE fill (x,y: INTEGER; Col: Planes);
- siehe Serie 'Vom Punkt zur dritten Dimension' in PASCAL INTERNATIONAL *)
- (* ----------------------------------------------------------------------- *)
- PROCEDURE PicSave (name: PicName);
- VAR datei: FILE; i,ort,k,dummi: INTEGER; records: BYTE;
- Puffer: ARRAY [1..VideoSize] OF BYTE;
- BEGIN
- records:= VideoSize DIV 128; dummi := (VideoRAM DIV VideoSize) -1;
- name := name+'.PIC'; Assign(datei,name); ReWrite(datei);
- Port[ReadPort] := 1; (* zuerst Ebene 1 auslesen *)
- FOR k := 1 TO 2 DO BEGIN
- FOR i := 0 TO dummi DO BEGIN
- ort := i * VideoSize + VideoBegin;
- INLINE (1/VideoSize/$2a/ort/$11/Puffer/$cd/$170);
- BlockWrite(datei,Puffer,records);
- END;
- Port[ReadPort] := 4; (* und dann Ebene 4 *)
- END;
- Close(datei);
- END;
-
- PROCEDURE PicLoad (name: PicName);
- VAR datei: FILE; k,i,ort,dummi: INTEGER; records: BYTE;
- Puffer: ARRAY [1..VideoSize] OF BYTE;
- BEGIN
- records := VideoSize DIV 128; dummi := (VideoRAM DIV VideoSize) -1;
- name := name+'.PIC'; Assign(datei,name); ReSet(datei);
- Port[WritePort] := $41; (* Ebene 1 zur Aufnahme vorbereiten *)
- FOR k := 1 TO 2 DO BEGIN (* und auf Oderverknuepfung schalten*)
- FOR i := 0 TO dummi DO BEGIN
- BlockRead(datei,Puffer,records); ort := i * VideoSize + VideoBegin;
- INLINE(1/VideoSize/$21/Puffer/$ed/$5b/ort/$cd/$170);
- END;
- Port[WritePort] := $44; (* nochmal in Ebene 4 laden, ODERn *)
- END;
- Close(datei);
- END;
- (* ----------------------------------------------------------------------- *)