File: dos\tplus.c
1 /* TPLUS.C, (C) 1991 The Yankee Programmer
2 All Rights Reserved.
3
4 This code may be distributed only when bundled with the Fractint
5 source code.
6
7 Mark C. Peterson
8 The Yankee Programmer
9 405-C Queen Street, Suite #181
10 Southington, CT 06489
11 (203) 276-9721
12
13 */
14
15 #include <conio.h>
16 #include <string.h>
17
18 /* see Fractint.c for a description of the "include" hierarchy */
19 #include "port.h"
20 #include "prototyp.h"
21 #include "tplus.h"
22
23 struct TPWrite far WriteOffsets = {
24 0, 1, 2, 3, 0x400, 0x401, 0x402,
25 0x403, 0x800, 0x801, 0x802, 0x803, 0xc00, 0xc01,
26 0xc02, 0xc03
27 };
28
29 struct TPRead far ReadOffsets = {
30 0, 2, 3, 0x400, 0x401, 0x402,
31 0x403, 0x800, 0x801, 0x802, 0x803, 0xc00, 0xc01,
32 0xc02, 0xc03
33 };
34
35 struct _BOARD far TPlus;
36 int TPlusErr = 0;
37
38 void WriteTPWord(unsigned Register, unsigned Number) {
39 OUTPORTB(TPlus.Write.INDIRECT, Register);
40 OUTPORTW(TPlus.Write.WBL, Number);
41 }
42
43 void WriteTPByte(unsigned Register, unsigned Number) {
44 OUTPORTB(TPlus.Write.INDIRECT, Register);
45 OUTPORTB(TPlus.Write.WBL, Number);
46 }
47
48 unsigned ReadTPWord(unsigned Register) {
49 OUTPORTB(TPlus.Write.INDIRECT, Register);
50 return(INPORTW(TPlus.Read.RBL));
51 }
52
53 BYTE ReadTPByte(unsigned Register) {
54 OUTPORTB(TPlus.Write.INDIRECT, Register);
55 return((BYTE)INPORTB(TPlus.Read.RBL));
56 }
57
58 void DisableMemory(void) {
59 unsigned Mode1;
60
61 Mode1 = INPORTB(TPlus.Read.MODE1);
62 Mode1 &= 0xfe;
63 OUTPORTB(TPlus.Write.MODE1, Mode1);
64 }
65
66 void EnableMemory(void) {
67 unsigned Mode1;
68
69 Mode1 = INPORTB(TPlus.Read.MODE1);
70 Mode1 |= 1;
71 OUTPORTB(TPlus.Write.MODE1, Mode1);
72 }
73
74 struct TPLUS_IO {
75 unsigned Cmd;
76 int Initx, Finalx, Inity, Finaly, Destx, Desty;
77 unsigned long Color;
78 unsigned RegsOffset, RegsSegment, RegListOffset, RegListSegment,
79 BoardNumber, StructSize;
80 } far TPlusIO;
81
82 /* TARGAP.SYS Commands */
83 #define READALL 0
84 #define WRITEALL 0
85 #define NUMBOARDS 3
86 #define FILLBLOCK 4
87 #define GRABFIELD 4
88 #define RESET 5
89 #define GRABFRAME 5
90 #define WAITFORVB 6
91 #define SETBOARD 8
92 #define IOBASE 9
93
94 /* DOS IO Commands */
95 #define DOS_READ 0x4402
96 #define DOS_WRITE 0x4403
97
98 int hTPlus = -1;
99 unsigned NumTPlus = 0;
100
101 int TargapSys(int Command, unsigned DOS) {
102 struct TPLUS_IO far *IOPtr;
103 unsigned far *RegPtr;
104 union REGS r;
105 struct SREGS s;
106
107 if(hTPlus != -1) {
108 r.x.ax = DOS;
109 r.x.bx = hTPlus;
110 r.x.cx = sizeof(TPlusIO);
111 IOPtr = &TPlusIO;
112 RegPtr = TPlus.Reg;
113 r.x.dx = FP_OFF(IOPtr);
114 s.ds = FP_SEG(IOPtr);
115 TPlusIO.Cmd = Command;
116 TPlusIO.StructSize = sizeof(TPlus.Reg);
117 TPlusIO.RegsOffset = FP_OFF(RegPtr);
118 TPlusIO.RegsSegment = FP_SEG(RegPtr);
119 intdosx(&r, &r, &s);
120 return(!r.x.cflag);
121 }
122 return(0);
123 }
124
125 int _SetBoard(int BoardNumber) {
126 TPlusIO.BoardNumber = BoardNumber;
127 return(TargapSys(SETBOARD, DOS_WRITE));
128 }
129
130 int TPlusLUT(BYTE far *LUTData, unsigned Index, unsigned Number,
131 unsigned DosFlag)
132 {
133 struct TPLUS_IO far *IOPtr;
134 union REGS r;
135 struct SREGS s;
136
137 if(hTPlus != -1) {
138 r.x.ax = DosFlag;
139 r.x.bx = hTPlus;
140 r.x.cx = sizeof(TPlusIO);
141 IOPtr = &TPlusIO;
142 r.x.dx = FP_OFF(IOPtr);
143 s.ds = FP_SEG(IOPtr);
144 TPlusIO.Cmd = 9;
145 TPlusIO.StructSize = sizeof(TPlus.Reg);
146 TPlusIO.RegsOffset = FP_OFF(LUTData);
147 TPlusIO.RegsSegment = FP_SEG(LUTData);
148 TPlusIO.BoardNumber = Number;
149 TPlusIO.RegListOffset = Index;
150 intdosx(&r, &r, &s);
151 return(!r.x.cflag);
152 }
153 return(0);
154 }
155
156 int SetVGA_LUT(void) {
157 char PathName[FILE_MAX_PATH];
158 FILE *Data = NULL;
159 BYTE LUTData[256 * 3];
160
161 findpath("tplus.dat", PathName);
162 if(PathName[0]) {
163 if((Data = fopen(PathName, "rb")) != NULL) {
164 if(!fseek(Data, 16L << 8, SEEK_SET)) {
165 if(fread(LUTData, 1, sizeof(LUTData), Data) == sizeof(LUTData)) {
166 fclose(Data);
167 return(TPlusLUT(LUTData, 0, sizeof(LUTData), DOS_WRITE));
168 }
169 }
170 }
171 }
172 if(Data != NULL)
173 fclose(Data);
174 return(0);
175 }
176
177 int SetColorDepth(int Depth) {
178 if(TPlus.Reg[HIRES] && Depth == 4)
179 Depth = 2;
180 switch(Depth) {
181 case 1:
182 if(TPlus.Reg[XDOTS] > 512) {
183 TPlus.Reg[PERM] = 1;
184 TPlus.Reg[BYCAP] = 3;
185 TPlus.RowBytes = 10;
186 }
187 else {
188 TPlus.Reg[PERM] = 0;
189 TPlus.Reg[BYCAP] = 1;
190 TPlus.RowBytes = 9;
191 }
192 TPlus.Reg[BUFFPORTSRC] = 0;
193 TPlus.Reg[CM1] = 0;
194 TPlus.Reg[CM2] = 0;
195 TPlus.Reg[DEPTH] = 1;
196 TPlus.Reg[LIVE8] = 1;
197 TPlus.Reg[DISPMODE] = 0;
198 TPlus.Reg[LIVEPORTSRC] = 1;
199 TPlus.Reg[LUTBYPASS] = 0;
200 break;
201 case 2:
202 if(TPlus.Reg[XDOTS] > 512) {
203 TPlus.Reg[PERM] = 3;
204 TPlus.Reg[BYCAP] = 15;
205 TPlus.Reg[CM2] = 1;
206 TPlus.RowBytes = 11;
207 }
208 else {
209 TPlus.Reg[PERM] = 1;
210 TPlus.Reg[BYCAP] = 3;
211 TPlus.Reg[CM2] = 0;
212 TPlus.RowBytes = 10;
213 }
214 TPlus.Reg[BUFFPORTSRC] = 1;
215 TPlus.Reg[CM1] = 0;
216 TPlus.Reg[DEPTH] = 2;
217 TPlus.Reg[LIVE8] = 0;
218 TPlus.Reg[DISPMODE] = 0;
219 TPlus.Reg[LIVEPORTSRC] = 1;
220 TPlus.Reg[LUTBYPASS] = 1;
221 break;
222 case 3:
223 case 4:
224 TPlus.Reg[PERM] = (Depth == 3) ? 2 : 3;
225 TPlus.Reg[BYCAP] = 0xf;
226 TPlus.Reg[BUFFPORTSRC] = 3;
227 TPlus.Reg[CM1] = 1;
228 TPlus.Reg[CM2] = 1;
229 TPlus.Reg[DEPTH] = 4;
230 TPlus.Reg[LIVE8] = 0;
231 TPlus.Reg[DISPMODE] = 0;
232 TPlus.Reg[LIVEPORTSRC] = 1;
233 TPlus.Reg[LUTBYPASS] = 1;
234 TPlus.RowBytes = 11;
235 break;
236 default:
237 return(0);
238 }
239 TPlus.Plot = WriteTPlusBankedPixel;
240 TPlus.GetColor = ReadTPlusBankedPixel;
241 TPlus.Reg[LIVEMIXSRC] = 0;
242 TPlus.Reg[CM3] = 1;
243 TPlus.RowsPerBank = 16 - TPlus.RowBytes;
244 if(TargapSys(WRITEALL, DOS_WRITE)) {
245 if(Depth == 1)
246 SetVGA_LUT();
247 if(TPlus.ClearScreen)
248 ClearTPlusScreen();
249 TargapSys(READALL, DOS_READ);
250 return(Depth);
251 }
252 return(0);
253 }
254
255 int SetBoard(int BoardNumber) {
256 unsigned ioBase, n;
257 unsigned long MemBase;
258
259 if(TPlus.ThisBoard != -1)
260 DisableMemory();
261 if(!_SetBoard(BoardNumber))
262 return(0);
263 if(!TargapSys(READALL, DOS_READ))
264 return(0);
265 TPlus.VerPan = TPlus.Reg[VPAN];
266 TPlus.HorPan = TPlus.Reg[HPAN];
267 TPlus.Top = TPlus.Reg[TOP];
268 TPlus.Bottom = TPlus.Reg[BOT];
269 TPlus.Bank64k = 0xffff; /* Force a bank switch */
270
271 MemBase = TPlus.Reg[MEM_BASE];
272 MemBase += (TPlus.Reg[MEM_MAP] != 3) ? 8 : 0;
273 TPlus.Screen = (BYTE far *)(MemBase << 28);
274
275 if(!TargapSys(IOBASE, DOS_READ))
276 return(0);
277 ioBase = TPlusIO.BoardNumber;
278 TPlus.Read = ReadOffsets;
279 TPlus.Write = WriteOffsets;
280 for(n = 0; n < sizeof(TPlus.Read) / sizeof(unsigned); n++)
281 ((unsigned far *)&(TPlus.Read))[n] += ioBase;
282 for(n = 0; n < sizeof(TPlus.Write) / sizeof(unsigned); n++)
283 ((unsigned far *)&(TPlus.Write))[n] += ioBase;
284
285 EnableMemory();
286 return(1);
287 }
288
289 int ResetBoard(int BoardNumber) {
290 int CurrBoard, Status = 0;
291
292 CurrBoard = TPlus.ThisBoard;
293 if(_SetBoard(BoardNumber))
294 Status = TargapSys(RESET, DOS_WRITE);
295 if(CurrBoard > 0)
296 _SetBoard(CurrBoard);
297 return(Status);
298 }
299
300 #include <fcntl.h>
301 #include <io.h>
302
303 int CheckForTPlus(void) {
304 unsigned n;
305
306 if((hTPlus = open("TARGPLUS", O_RDWR | O_BINARY )) != -1) {
307 if(!TargapSys(NUMBOARDS, DOS_READ))
308 return(0);
309 NumTPlus = TPlusIO.BoardNumber;
310 TPlus.ThisBoard = -1;
311 TPlus.ClearScreen = 1;
312 for(n = 0; n < NumTPlus; n++)
313 if(!ResetBoard(n))
314 return(0);
315 if(SetBoard(0))
316 return(1);
317 }
318 return(0);
319 }
320
321 int SetTPlusMode(int Mode, int NotIntFlag, int Depth, int Zoom) {
322 unsigned n;
323 char PathName[FILE_MAX_PATH];
324 FILE *Data = NULL;
325 unsigned NewRegs[128];
326
327 findpath("tplus.dat", PathName);
328 if(PathName[0]) {
329 if((Data = fopen(PathName, "rb")) != NULL) {
330 if(!fseek(Data, (long)Mode << 8, SEEK_SET)) {
331 if(fread(NewRegs, 1, 256, Data) == 256) {
332 fclose(Data);
333 NewRegs[PE] = TPlus.Reg[PE];
334 NewRegs[OVLE] = TPlus.Reg[OVLE];
335 NewRegs[RGB] = TPlus.Reg[RGB];
336 NewRegs[SVIDEO] = TPlus.Reg[SVIDEO];
337 NewRegs[DAC567DATA] = TPlus.Reg[DAC567DATA];
338 NewRegs[VGASRC] = TPlus.Reg[VGASRC];
339 for(n = 0; n < 128; n++)
340 TPlus.Reg[n] = NewRegs[n];
341 if(TPlus.Reg[VTOP + 1] == 0xffff)
342 TPlus.Reg[NOT_INT] = 0;
343 else if(TPlus.Reg[VTOP] == 0xffff && !NotIntFlag) {
344 TPlusErr = 1;
345 return(0);
346 }
347 else
348 TPlus.Reg[NOT_INT] = NotIntFlag;
349 TPlus.xdots = TPlus.Reg[XDOTS];
350 TPlus.ydots = TPlus.Reg[YDOTS];
351 if(Zoom) {
352 TPlus.Reg[ZOOM] = Zoom;
353 TPlus.xdots >>= Zoom;
354 TPlus.ydots >>= Zoom;
355 }
356 return(SetColorDepth(Depth));
357 }
358 }
359 }
360 }
361 if(Data != NULL)
362 fclose(Data);
363 return(0);
364 }
365
366 int FillTPlusRegion(unsigned x, unsigned y, unsigned xdots, unsigned ydots,
367 unsigned long Color) {
368 int Status = 0;
369
370 TPlusIO.Initx = x;
371 TPlusIO.Inity = TPlus.Reg[YDOTS] - (y + ydots) - 2;
372 TPlusIO.Finalx = x + xdots - 1;
373 TPlusIO.Finaly = TPlus.Reg[YDOTS] - y - 1;
374 TPlusIO.Color = Color;
375 Status = TargapSys(FILLBLOCK, DOS_WRITE);
376 EnableMemory();
377 return(Status);
378 }
379
380 void BlankScreen(unsigned long Color) {
381 unsigned BufferPort;
382
383 OUTPORTW(TPlus.Write.COLOR0, ((unsigned*)&Color)[0]);
384 OUTPORTB(TPlus.Write.COLOR2, ((unsigned*)&Color)[1]);
385 OUTPORTB(TPlus.Write.COLOR3, 0xff);
386 BufferPort = ReadTPByte(0xe9);
387 BufferPort |= 3;
388 WriteTPByte(0xe9, BufferPort);
389 }
390
391 void UnBlankScreen(void) {
392 unsigned BufferPort;
393
394 BufferPort = ReadTPByte(0xe9);
395 BufferPort &= 0xfe;
396 WriteTPByte(0xe9, BufferPort);
397 }
398
399 void EnableOverlayCapture(void) {
400 unsigned Mode2;
401
402 Mode2 = INPORTB(TPlus.Read.MODE2);
403 Mode2 |= (1 << 6);
404 Mode2 &= (0xff ^ (3 << 4));
405 Mode2 |= (1 << 5);
406 OUTPORTB(TPlus.Write.MODE2, Mode2);
407 }
408
409 void DisableOverlayCapture(void) {
410 unsigned Mode2;
411
412 Mode2 = INPORTB(TPlus.Read.MODE2);
413 Mode2 &= (0xff ^ (7 << 4));
414 OUTPORTB(TPlus.Write.MODE2, Mode2);
415 }
416
417 void ClearTPlusScreen(void) {
418 BlankScreen(0L);
419 EnableOverlayCapture();
420 TargapSys(WAITFORVB, DOS_READ);
421 TargapSys(WAITFORVB, DOS_READ);
422 TargapSys(WAITFORVB, DOS_READ);
423 DisableOverlayCapture();
424 UnBlankScreen();
425 }
426
427 static struct {
428 unsigned xdots, ydots, Template, Zoom, Depth;
429 } far ModeTable[] = {
430 {512, 400, 0, 0, 4},
431 {512, 476, 1, 0, 4},
432 {512, 486, 2, 0, 4},
433 {512, 576, 3, 0, 4},
434 {640, 480, 4, 0, 2},
435 {648, 486, 5, 0, 2},
436 {720, 486, 6, 0, 2},
437 {720, 576, 7, 0, 2},
438 {756, 486, 8, 0, 2},
439 {768, 576, 9, 0, 2},
440 {800, 600, 10, 0, 2},
441 {1024,768, 11, 0, 2},
442 {640, 400, 13, 0, 2},
443 {320, 200, 13, 1, 2},
444 {512, 496, 14, 0, 4},
445 {640, 496, 15, 0, 2}
446 };
447
448 static unsigned TableSize = (sizeof(ModeTable) / sizeof(ModeTable[0]));
449
450 int MatchTPlusMode(unsigned xdots, unsigned ydots, unsigned MaxColorRes,
451 unsigned PixelZoom, unsigned NonInterlaced) {
452 unsigned n, Depth;
453
454 for(n = 0; n < TableSize; n++) {
455 if(ModeTable[n].xdots == xdots && ModeTable[n].ydots == ydots)
456 break;
457 }
458 if(n < TableSize) {
459 if(ModeTable[n].Zoom)
460 PixelZoom += ModeTable[n].Zoom;
461 if(PixelZoom > 4)
462 PixelZoom = 4;
463 switch(MaxColorRes) {
464 case 24:
465 Depth = 4;
466 break;
467 case 16:
468 Depth = 2;
469 break;
470 case 8:
471 default:
472 Depth = 1;
473 break;
474 }
475 if(ModeTable[n].Depth < Depth)
476 Depth = ModeTable[n].Depth;
477 return(SetTPlusMode(ModeTable[n].Template, NonInterlaced, Depth,
478 PixelZoom));
479 }
480 return(0);
481 }
482
483 void TPlusZoom(int Zoom) {
484 unsigned Mode2;
485
486 Zoom &= 3;
487 Mode2 = INPORTB(TPlus.Read.MODE2);
488 Mode2 &= (0xff ^ (3 << 2));
489 Mode2 |= (Zoom << 2);
490 OUTPORTB(TPlus.Write.MODE2, Mode2);
491 }
492