/* SG C Tools 1.0 (C) 1993 Steve Goldsmith All Rights Reserved The VDC module provides a high level interface to access the C128's 8563 VDC (16K or 64K) chip. Functions are provided for high speed fills, copies, string output, etc. savevdc() should be called before any other VDC routines. This saves off key VDC registers and sets global 'vdc' prefixed vars. You are responsible for restoring any VDC RAM modified by your program. For example, if you over write RAM used by the character set for a bit map you must restore the character set before calling restorevdc() and exiting back to CP/M. Compiled with HI-TECH C 3.09 (CP/M-80). */ #include #include #include #include uchar vdcRegsToSave[] = /* vdc registers to save and restore */ {0,1,2,3,4,5,6,7,8,9,10,11,12,13, 22,23,24,25,26,27,28,29,34,35,36}; uchar vdcRegs[sizeof(vdcRegsToSave)-1]; /* saved vdc registers */ uchar vdcScrHorz; /* vars initilized by savevdc() */ uchar vdcScrVert; ushort vdcScrSize; ushort vdcDispMem; ushort vdcAttrMem; uchar invdc(uchar RegNum) { outp(vdcStatusReg,RegNum); /* internal vdc register to read */ while ((inp(vdcStatusReg) & 0x80) == 0x00); /* wait for status bit to be set */ return(inp(vdcDataReg)); /* read register */ } void outvdc(uchar RegNum, uchar RegVal) { outp(vdcStatusReg,RegNum); /* internal vdc register to write */ while ((inp(vdcStatusReg) & 0x80) == 0x00); /* wait for status bit to be set */ outp(vdcDataReg,RegVal); /* write register */ } void savevdc(void) { uchar I; for(I = 0; I < sizeof(vdcRegs); I++) /* save key vdc regs */ vdcRegs[I] = invdc(vdcRegsToSave[I]); vdcScrHorz = invdc(vdcHzDisp); /* init global vdc vars */ vdcScrVert = invdc(vdcVtDisp); vdcScrSize = vdcScrHorz*vdcScrVert; vdcDispMem = (ushort) ((invdc(vdcDspStAddrHi) << 8)+invdc(vdcDspStAddrLo)); vdcAttrMem = (ushort) ((invdc(vdcAttrStAddrHi) << 8)+invdc(vdcAttrStAddrLo)); } void restorevdc(void) { uchar I; for(I = 0; I < sizeof(vdcRegs); I++) /* restore vdc regs saved with savevdc() */ outvdc(vdcRegsToSave[I],vdcRegs[I]); } /* set cursor's top and bottom scan lines and mode */ void setcursorvdc(uchar Top, uchar Bottom, uchar Mode) { outvdc(vdcCurStScanLine,(Top | (Mode << 5))); outvdc(vdcCurEndScanLine,Bottom); } /* fast fill using block writes */ void fillmemvdc(ushort FillMem, ushort FillLen, uchar Filler) { uchar Blocks, Remain, I; outvdc(vdcUpdAddrHi,(uchar) (FillMem >> 8)); outvdc(vdcUpdAddrLo,(uchar) FillMem); outvdc(vdcVtSmScroll,(invdc(vdcVtSmScroll) & 0x7F)); outvdc(vdcCPUData,Filler); if (FillLen > vdcMaxBlock) { Blocks = FillLen/vdcMaxBlock; Remain = FillLen%vdcMaxBlock; for(I = 1; I <= Blocks; I++) outvdc(vdcWordCnt,vdcMaxBlock); if (Remain > 1) outvdc(vdcWordCnt,--Remain); } else if (FillLen > 1) outvdc(vdcWordCnt,--FillLen); } /* fast copy using block copy */ void copymemvdc(ushort SMem, ushort DMem, ushort CopyLen) { uchar Blocks, Remain, I; outvdc(vdcUpdAddrHi,(uchar) (DMem >> 8)); outvdc(vdcUpdAddrLo,(uchar) DMem); outvdc(vdcVtSmScroll,(invdc(vdcVtSmScroll) | 0x80)); outvdc(vdcBlkCpySrcAddrHi,(uchar) (SMem >> 8)); outvdc(vdcBlkCpySrcAddrLo,(uchar) SMem); if (CopyLen > vdcMaxBlock) { Blocks = CopyLen/vdcMaxBlock; Remain = CopyLen%vdcMaxBlock; for(I = 1; I <= Blocks; I++) outvdc(vdcWordCnt,vdcMaxBlock); if (Remain > 0) outvdc(vdcWordCnt,Remain); } else if (CopyLen > 0) outvdc(vdcWordCnt,CopyLen); } /* sets which disp and attr page is showing */ void setdsppagevdc(ushort DPage, ushort APage) { outvdc(vdcDspStAddrHi,(uchar) (DPage >> 8)); outvdc(vdcDspStAddrLo,(uchar) DPage); outvdc(vdcAttrStAddrHi,(uchar) (APage >> 8)); outvdc(vdcAttrStAddrLo,(uchar) APage); } /* copies disp and attr page to new pages */ void copydspvdc(ushort SDPage, ushort SAPage, ushort DDPage, ushort DAPage) { copymemvdc(SDPage,DDPage,vdcScrSize); copymemvdc(SAPage,DAPage,vdcScrSize); } /* fast disp page clear with any byte */ void clrscrvdc(uchar Ch) { fillmemvdc(vdcDispMem,vdcScrSize,Ch); } /* fast attr page clear with any byte */ void clrattrvdc(uchar Attr) { fillmemvdc(vdcAttrMem,vdcScrSize,Attr); } /* fill disp mem given x and y offset in current page */ void filldspvdc(uchar X, uchar Y, uchar CLen, uchar Ch) { fillmemvdc(vdcDispMem+Y*vdcScrHorz+X,CLen,Ch); } /* fill attr mem given x and y offset in current page */ void fillattrvdc(uchar X, uchar Y, uchar ALen, uchar Attr) { fillmemvdc(vdcAttrMem+Y*vdcScrHorz+X,ALen,Attr); } /* fast vdc string print given x and y offset in current page */ void printstrvdc(uchar X, uchar Y, uchar Attr, char * TextStr) { uchar I, TextLen; ushort DispOfs; DispOfs = vdcDispMem+Y*vdcScrHorz+X; /* calc disp mem offset */ TextLen = strlen(TextStr); fillattrvdc(X,Y,TextLen,Attr); /* use block fill for attrs */ outvdc(vdcUpdAddrHi,(uchar) (DispOfs >> 8)); outvdc(vdcUpdAddrLo,(uchar) DispOfs); /* set addr of first char */ for(I = 0; I < TextLen; I++) /* send str to vdc disp mem */ outvdc(vdcCPUData,TextStr[I]); }