{ ******************************************************* * * * Title: PRINTMASTER GALLERY * * Author: MARK SNOOK * * Last Update: 27/1/90 * * Requires: GALLERY.HEX * * SLIB.SDR * * SLIB.SHP * * Notes: The above files must be on the same * * drive as the compiled .COM program. * * This was written for Hisoft Devpac80. * * * * This is a program written to read the PRINTMASTER * * library file SLIB.SHP and to display the pictures. * * * ******************************************************* } {$y,l-,c-,vBFFF} { Locate below common ram at #C000 } PROGRAM PMGallery(INPUT,OUTPUT); CONST LibFile = ' slib .shp'; {file of picture data } NameFile = ' slib .sdr'; {file of picture names} HexFile = ' gallery .hex'; {file of machine code } RecSize = 577; {record size of a picture} MaxMenuLen = 28; MaxMenuWidth = 16; NumPics = 124; Return = CHR(13); UpArrow = CHR(11); {control-K} DownArrow = CHR(10); {control-J} Can = CHR(8); {control-H} DelLeft = CHR(127); TYPE MenuOption = ARRAY [1..MaxMenuWidth] OF CHAR; MenuList = ARRAY [1..MaxMenuLen] OF MenuOption; Gallery = ARRAY [0..NumPics] OF MenuOption; PicRec = RECORD w,h,d1,d2:CHAR; Pic:ARRAY[0..571] OF CHAR; Term:CHAR; END; VAR MCFile,PicLib,PicMenu:TEXT; Letters,Punct:SET OF CHAR; PicList:Gallery; {================== SCREEN ROUTINES ===================} PROCEDURE StatusOff; VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('0')) END; {======================================================} PROCEDURE StatusOn; VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('1')) END; {======================================================} PROCEDURE CursorOff; VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('f')) END; {======================================================} PROCEDURE CursorOn; VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('e')) END; {======================================================} PROCEDURE GotoXY(col,row:INTEGER); VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('Y')); dummy:=CPM(2,row+32); dummy:=CPM(2,col+32) END; {======================================================} PROCEDURE Window(Col,Row,Height,Width:INTEGER); VAR dummy:INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('X')); dummy:=CPM(2,Row+32); dummy:=CPM(2,Col+32); dummy:=CPM(2,Height+31); dummy:=CPM(2,Width+31) END; {======================================================} PROCEDURE FullScreen; VAR dummy:INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('X')); dummy:=CPM(2,32); dummy:=CPM(2,32); dummy:=CPM(2,31+31); dummy:=CPM(2,90+31) END; {======================================================} PROCEDURE CLS; VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('E')) END; {======================================================} PROCEDURE CursorUp; VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('A')) END; {======================================================} PROCEDURE CursorDown; VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('B')) END; {======================================================} PROCEDURE CursorLeft; VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('D')) END; {======================================================} PROCEDURE CursorRight; VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('D')) END; {========== FILE READING PROCEDURES ===================} { READRAND is a function which returns TRUE if a record can not be found on the disc. It returns FALSE if the data was read successfully. The first parameter is the Text File variable you wish to read. This should be opened using RESET (or REWRITE if you use WRITERAND on it first). The second parameter is the File Component you wish to read starting from 0. The third parameter is the address of the variable you wish to read. The fourth parameter is the size (in bytes) of the file components. } FUNCTION ReadR(VAR F:TEXT;I,B:INTEGER):INTEGER; VAR Dum:INTEGER; BEGIN POKE(ADDR(F)+40,I);POKE(ADDR(F)+42,CHR(0)); Dum:=CPM(26,B); { Set DMA address } ReadR:=CPM(33,ADDR(F)+7); { Random read } END; FUNCTION ReadRand(VAR F:TEXT;LogRec,Adr,Nbytes:INTEGER):BOOLEAN; VAR ByteNo:REAL; Valid,Snum,Offset,Start,i:INTEGER; NoMore:BOOLEAN; b: ARRAY[1..128] OF CHAR; BEGIN ByteNo:=LogRec * Nbytes; Snum:=ENTIER(ByteNo/128); Offset:=ROUND(ByteNo-Snum*128); Start:=0; NoMore:=FALSE; REPEAT IF READR(F,Snum,ADDR(b)) <> 0 THEN NoMore:=TRUE ELSE BEGIN IF Offset+Nbytes-Start>128 THEN Valid:=128-Offset ELSE Valid:=Nbytes-Start; FOR i:=0 TO Valid-1 DO POKE(Adr+Start+i,b[Offset+1+i]); Start:=Start+Valid; Snum:=Snum+1;Offset:=0; END UNTIL (Start=Nbytes) OR NoMore; ReadRand:=nomore; END; {============== LOAD MACHINE CODE =====================} PROCEDURE LoadHex; VAR Posn:INTEGER; NotGotByte:BOOLEAN; Buff:CHAR; BEGIN RESET(MCFile,HexFile); FOR Posn:=#0 TO #47 DO BEGIN NotGotByte:=ReadRand(MCFile,Posn,ADDR(Buff),1); POKE(#C000+Posn,Buff); IF NotGotByte THEN Write('Transfer not complete',Posn:4:H) END END; {============== MENU PROCEDURES =======================} PROCEDURE PrintRow(Width,StartChar,EndChar,MiddleChar:INTEGER); VAR n : INTEGER; BEGIN WRITE(CHR(StartChar)); FOR n:= 1 TO Width DO WRITE(CHR(MiddleChar)); WRITE(CHR(EndChar)) END; {======================================================} PROCEDURE DrawBorder(x,y,Width,Length:INTEGER); VAR n : INTEGER; BEGIN GotoXY(x,y); PrintRow(Width,134,140,138); FOR n:= 1 TO Length DO BEGIN GotoXY(x,y+n); Write(CHR(133)); GotoXY(x+Width+1,y+n); Write(CHR(133)) END; GotoXY(x,y+n); PrintRow(Width,131,137,138); GotoXY(x+1,y+1) END; {======================================================} PROCEDURE ReverseVideo; VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('p')) END; PROCEDURE NormalVideo; VAR dummy : INTEGER; BEGIN dummy:=CPM(2,27); dummy:=CPM(2,ORD('q')) END; {======================================================} PROCEDURE MenuChoice(x,y,Width,Length:INTEGER;Choices:MenuList; VAR Val:INTEGER;Redraw:BOOLEAN); VAR n,m:INTEGER; Key,Letter:CHAR; PROCEDURE WriteNormal; BEGIN GotoXY(x+1,y+Val); NormalVideo; FOR m:=1 TO Width DO BEGIN Letter:=Choices[Val][m]; IF Letter = CHR(0) THEN Letter:=' '; WRITE(Letter) END END; PROCEDURE WriteReverse; BEGIN GotoXY(x+1,y+Val); ReverseVideo; FOR m:=1 TO Width DO BEGIN Letter:=Choices[Val][m]; IF Letter = CHR(0) THEN Letter:=' '; WRITE(Letter) END END; BEGIN IF Redraw THEN BEGIN DrawBorder(x,y,Width,Length); FOR n:= 1 TO Length DO BEGIN GotoXY(x+1,y+n); FOR m:=1 TO Width DO WRITE(Choices[n][m]) END END; IF Val > 0 THEN BEGIN WriteReverse; Key:=INCH; WHILE (Key <> Return) AND (Key <> Can) DO BEGIN IF Key = DownArrow THEN BEGIN WriteNormal; Val:=Val+1; IF Val > Length THEN Val:=1; WriteReverse END; IF Key = UpArrow THEN BEGIN WriteNormal; Val:=Val-1; IF Val < 1 THEN Val:=Length; WriteReverse END; Key:=INCH END; IF Key = Can THEN Val:=0 END; NormalVideo; END; {======================================================} PROCEDURE EraseMenu; BEGIN Window(0,0,31,18); CLS; Window(0,0,31,90) END; {================== END OF MENU PROCEDURES ============} PROCEDURE Initialise; BEGIN DrawBorder(29,0,40,1); GotoXY(31,1); Write('P R I N T M A S T E R G A L L E R Y'); GotoXY(36,5); Write('Hit [CAN] to return to CP/M') END; {======================================================} PROCEDURE GetMenu; VAR Count:INTEGER; NotGotPic:BOOLEAN; BEGIN RESET(PicMenu,NameFile); FOR Count:= 0 TO NumPics DO BEGIN NotGotPic:=READRAND(PicMenu,Count,ADDR(PicList[Count]),MaxMenuWidth); IF NotGotPic THEN WRITE('No entry in MenuFile for number ',Count) END END; {======================================================} PROCEDURE PlotByte(x,y,data:CHAR); BEGIN POKE(#C000,x); POKE(#C001,y); POKE(#C002,data); USER(#C003) {Call machine code plot routine} END; {======================================================} PROCEDURE PlotPic(tlx,tly,PicNum:INTEGER); VAR x,y,NumBytes:INTEGER; Symbol:PicRec; NotGotRec:BOOLEAN; Byte:CHAR; BEGIN RESET(PicLib,LibFile); NotGotRec:=READRAND(PicLib,PicNum,ADDR(Symbol),RecSize); IF NotGotRec THEN WRITE('Picture not found with record number ',PicNum) ELSE FOR y:=0 TO 51 DO FOR x:=0 TO 10 DO BEGIN Byte:=Symbol.Pic[y*11+x]; PlotByte(CHR(tlx+x),CHR(tly+y),Byte) END END; {======================================================} PROCEDURE BuildMenu(VAR MenuNum,Choice:INTEGER;VAR ReDraw:BOOLEAN); VAR Length,Count:INTEGER; PicName:MenuList; BEGIN Length:=-1; {some out of range value} REPEAT IF Choice = Length THEN BEGIN EraseMenu; Choice:=1; ReDraw:=TRUE; END; MenuNum:=(MenuNum+1) MOD 5; IF MenuNum = 4 THEN Length:=15 ELSE Length:=MaxMenuLen; FOR Count:=1 TO Length-1 DO PicName[Count]:=PicList[MenuNum*27+Count-1]; PicName[Length]:='Next Menu '; MenuChoice(0,0,MaxMenuWidth,Length,PicName,Choice,ReDraw); UNTIL Choice <> Length; ReDraw:=FALSE END; {======================================================} PROCEDURE BrowseLib; VAR x,y,MenuNum,Choice:INTEGER; ReDraw:BOOLEAN; BEGIN x:=0; y:=0; MenuNum:=4; Choice:=1; ReDraw:=TRUE; REPEAT BuildMenu(MenuNum,Choice,ReDraw); IF Choice <> 0 THEN PlotPic(x+24,y+32,MenuNum*27+Choice-1); x:=((x+12) MOD 60); IF x = 0 THEN y:=(y+55) MOD 220; MenuNum:=MenuNum-1 UNTIL Choice = 0; END; {======================================================} {Main Program} BEGIN CLS; CursorOff; StatusOff; Initialise; LoadHex; GetMenu; GotoXY(36,5); Write(' '); BrowseLib; CursorOn; StatusOn; CLS END. ; GetMenu; GotoXY(36,5); Write('