/* These functions are specific to BDS C Version 1.50 They are */ /* for use with DHIRES.DVR. The definitions should be moved to */ /* a separate include file, with the functions compiled into a */ /* library, to save compilation times. -Rod Pederson */ /****** Apple Addresses *******/ #define AuxPage 0xc055 #define MainPage 0xc054 #define ScrnBase 0x2000 /****** Driver Constants ******/ /* Commands */ #define readdvr 0xfd #define writdvr 0xfe #define othrdvr 0xff #define bw 0x00 #define colour 0x01 #define gfx 0x02 #define txt 0x03 #define sndmode 0x04 #define clrg 0x05 /* Colour Codes */ #define black 0x00 #define dkblue 0x80 #define magenta 0x10 #define purple 0x90 #define brown 0x20 #define grey2 0xa0 #define orange 0x30 #define pink 0xb0 #define dkgreen 0x40 #define mdblue 0xc0 #define grey1 0x50 #define ltblue 0xd0 #define green 0x60 #define aqua 0xe0 #define yellow 0x70 #define white 0xf0 /********* Z80B Data **********/ /* Commands */ #define RBytsCmd 0x01 #define WBytsCmd 0x02 #define GotoCmd 0x03 #define RdBytCmd 0x06 #define WrBytCmd 0x07 /* Z80 Ports */ #define Z80Out 0x00 #define AplIn 0x20 #define Ztatus 0x40 /* Z80 Routines */ #define RdApByts 0xFFEC #define WrApByts 0xFFEF #define RdAplWrd 0xFFE6 #define WrAplWrd 0xFFE9 #define RdAplByt 0xFFE0 #define WrAplByt 0xFFE3 char dhrmode; ByteIn () /* ByteIn returns a byte written to the Z80 by the Apple. */ /* It continues to read the Z80 side of the status port */ /* until a byte is ready to be read, indicated by the */ /* port bit 7 being set . The value at the input port is */ /* assigned to the function return value. ByteIn should */ /* normally be used only by one of the higher level */ /* procedures defined further on in this include file. */ { while (inp (Ztatus) < 0x80); return (inp (AplIn)); } ByteOut (Val) char Val; /* ByteOut sends a byte from the Z80 to the Apple. */ /* It continues to read the Z80 side of the status port */ /* until the Apple is ready read, indicated by the status */ /* port bit 0 being set, at which time the port value is */ /* an odd number. The value of the byte parameter is */ /* assigned to the Z80-to-Apple output port. ByteOut will */ /* normally be used only by one of the higher level */ /* procedures defined further on in this include file. */ { while (inp (Ztatus) & 0x01); outp (Z80Out,Val); } TxBytes (FmAdrs, ToAdrs, Count) int FmAdrs, ToAdrs, Count; /* FmAdrs is the address in the Z80 of a number of bytes */ /* to be sent to the Apple, ToAdrs is the address in the */ /* Apple to which the bytes are to be written. Count is */ /* the number of bytes to be transferred. Data is read */ /* from the Z80 and written to the Apple beginning with */ /* the lowest address. WrApByts is the PCPI bios routine */ /* that does the actual transfer of data. */ { ByteOut (WBytsCmd); ByteOut (ToAdrs); ByteOut (ToAdrs >> 8); ByteOut (Count); ByteOut (Count >> 8); call (WrApByts,0x00,FmAdrs,0,Count); } RxBytes (FmAdrs, ToAdrs, Count) int FmAdrs, ToAdrs, Count; /* FmAdrs is the address in the Apple of a number of bytes */ /* to be transferred to the Z80, ToAdrs is the address in */ /* the Z80 to which the bytes are to be written. Count is */ /* the number of bytes to be transferred. Data is read */ /* from the Apple and written to the Z80 beginning with */ /* the lowest address. RdApByts is the PCPI bios routine */ /* that does the actual transfer of data. */ { ByteOut (RBytsCmd); ByteOut (FmAdrs); ByteOut (FmAdrs >> 8); ByteOut (Count); ByteOut (Count >> 8); call (RdApByts,0x00,ToAdrs,0,Count); } WriteByte (ToAdrs, DataByte) int ToAdrs; char DataByte; /* WriteByte is the equivalent of a 'POKE' into the Apple */ /* memory. ToAdrs is the address in the Apple to which */ /* DataByte will be written. */ { ByteOut (WrBytCmd); ByteOut (ToAdrs); ByteOut (ToAdrs >> 8); ByteOut (DataByte); } ReadByte (FmAdrs) int FmAdrs; /* ReadByte is the equivalent of a 'PEEK' into the Apple */ /* memory. FmAdrs is the address in the Apple from which */ /* a byte is to be read. */ { ByteOut (RdBytCmd); ByteOut (FmAdrs); ByteOut (FmAdrs >> 8); return (ByteIn); } DoAppleRoutine (GotoAdrs) int GotoAdrs; /* GotoAdrs is the address in the Apple of a sub-routine */ /* to be executed by the Apple. The Apple will do the */ /* sub-routine (for instance a Monitor routine) and */ /* return to normal operation. */ { ByteOut (GotoCmd); ByteOut (GotoAdrs); ByteOut (GotoAdrs >> 8); } grafmode (mode) char mode; /* Mode is a DHIRES.DVR 'other' command telling the driver */ /* to do either colour or black-and-white plotting. If an */ /* incorrect mode is supplied, the procedure will return */ /* having done nothing. The returned byte is ignored. */ { char ans; if ((mode == bw) || (mode == colour)) { ByteOut (othrdvr); ByteOut (mode); ans = ByteIn (); dhrmode = mode; } } grafix () /* The Apple is switched from text to double-high resolution */ /* graphics using a DHIRES.DVR 'other' command. The returned */ /* byte is ignored. */ { char ans; ByteOut (othrdvr); ByteOut (gfx); ans = ByteIn (); } text () /* The Apple is switched from double-high resolution graphics */ /* to 80-column text using a DHIRES.DVR 'other' command. The */ /* returned byte is ignored. */ { char ans; ByteOut (othrdvr); ByteOut (txt); ans = ByteIn (); dhrmode = txt; } clrgraf (value) char value; /* The double-high resolution graphics screen is cleared to */ /* the colour specified using a DHIRES.DVR 'other' command. */ /* As usual, the returned byte is ignored. */ { char ans; ByteOut (othrdvr); ByteOut (clrg); ByteOut (value); ans = ByteIn (); } graferror () /* If an attempt is made to use the colour procedures and functions */ /* while in black-and-white mode, or vice-versa, this procedure */ /* be called to write an appropriate message to the text screen. It */ /* will display the message until 'ESC' is typed, at which point it */ /* will reset the mode actually selected and continue with the */ /* program. If the compiler 'C' option has been left on (this is */ /* the default) it can be used, here, to halt the program. */ { char tmode, c; tmode = dhrmode; text (); printf ("Cannot plot "); if (dhrmode == colour) printf ("colour in black-and-white mode. "); else if (dhrmode == bw) printf ("black-and-white in colour mode. "); else printf ("unless the graphics mode is set. "); printf ("'ESC' continues, '^C' halts.\n"); do pause (); while (((c = getchar()) != 0x1b) && (c != 0x03)); if (c == 0x03) exit (); grafix (); grafmode (tmode); } bplot (x,y) int x,y; /* A pixel is plotted on the black-and-white screen. The high */ /* byte of the x-coordinate is sent first because the DHIRES.DVR */ /* routine used to read the coordinates is also used to read the */ /* coordinates and colour in the colour mode. If not in black-and */ /* -white mode, an error message will be written to the text */ /* screen and nothing will be plotted. */ { if (dhrmode != bw) graferror (); else if ((x>=0) && (x<560) && (y>=0) && (y<192)) { ByteOut (writdvr); ByteOut (x >> 8); ByteOut (y); ByteOut (x); } } unplot (x,y) int x,y; /* The only difference between unplot and bplot is that the */ /* high bit of the high byte of the x-coordinate is set to */ /* indicate to DHIRES.DVR that the pixel is to be erased. */ { if (dhrmode != bw) graferror (); else if ((x>=0) && (x<560) && (y>=0) && (y<192)) { ByteOut (writdvr); ByteOut ((x | 0x8000) >> 8); ByteOut (y); ByteOut (x); } } bpset (x,y) int x,y; /* The DHIRES.DVR 'read' entry point is used to determine whether */ /* or not a black-and-white pixel is set. It returns 0x00 if the */ /* pixel is not set, or if the coordinates given are outside the */ /* screen boundaries, otherwise it returns non-zero indicating */ /* that the pixel is set. */ { if (dhrmode != bw) graferror (); else { if ((x>=0) && (x<560) && (y>=0) && (y<192)) { ByteOut (readdvr); ByteOut (x >> 8); ByteOut (y); ByteOut (x); return (ByteIn ()); } else return (0x00); } } cplot (x,y,c) int x,y; char c; /* A pixel is plotted at the x and y coordinates passed. */ /* The colours available on the Apple are defined as */ /* constants at the beginning of this include file. An */ /* attempt to plot colour in black-and-white mode will */ /* result in an error message. */ { if (dhrmode != colour) graferror (); else if ((x>=0) && (x<140) && (y>=0) && (y<192)) { ByteOut (writdvr); ByteOut (c); ByteOut (y); ByteOut (x); } } cpset (x,y) int x,y; /* The colour set at the coordinates passed will be */ /* returned. Black is returned for coordinates */ /* outside the screen boundaries. An attempt to call */ /* cpset in black-and-white mode will result in an */ /* error message. */ { if (dhrmode != colour) graferror (); else { if ((x>=0) && (x<140) && (y>=0) && (y<192)) { ByteOut (readdvr); ByteOut (x >> 8); ByteOut (y); ByteOut (x); return (ByteIn ()); } else return (0x00); } } Upload (ToAdrs) int ToAdrs; /* A copy of the double-high resolution screen is copied from */ /* the Apple into the Z80 memory at ToAdrs. The auxilliary */ /* memory half of the screen is copied first, followed by the */ /* main memory half of the screen. It is important to leave */ /* the main memory turned on upon exiting a procedure. */ { WriteByte (AuxPage,0x00); RxBytes (ScrnBase, ToAdrs, 8192); WriteByte (MainPage,0x00); RxBytes (ScrnBase, ToAdrs+8192, 8192); } Download (FmAdrs) int FmAdrs; /* A copy of the double-high resolution screen is copied from */ /* Z80 memory at FmAdrs to the Apple screen. The auxilliary */ /* memory half of the screen is copied first, followed by the */ /* main memory half of the screen. It is important to leave */ /* the main memory turned on upon exiting a procedure. */ { WriteByte (AuxPage,0x00); TxBytes (FmAdrs, ScrnBase, 8192); WriteByte (MainPage,0x00); TxBytes (FmAdrs+8192, ScrnBase, 8192); }