]> 4ch.mooo.com Git - 16.git/blob - 16/tweak16/TWEAK.CPP
having the palette in the game code may help. also i added wolf3d's palette for exama...
[16.git] / 16 / tweak16 / TWEAK.CPP
1 /*\r
2         TWEAK 1.6á - Mold your own VGA modes\r
3 \r
4         by Robert Schmidt of Ztiff Zox Softwear, (C) Copyright 1992-93\r
5 \r
6         For documentation, see TWEAK.DOC.\r
7 \r
8 \r
9         History:\r
10 \r
11         0.9\r
12                 First version available to the public.\r
13                 Aw, what the heck, I'll admit this is the first version ever...\r
14                 I know the usage of C++ classes may look a little stupid,\r
15                         but it works.\r
16                 Another stupid, *stupid* thing is the mixed use of conio and\r
17                         iostream, but hey, it works too!\r
18                 This version is not commented whatsoever.\r
19                 Pretty lame interface - no help.\r
20                 Test screens assume text start at segment 0xb800, and graphics\r
21                 at 0xa000.\r
22         1.0\r
23                 Changed from small to large memory model.  Not that I need it, it\r
24                         just makes the code more readable.\r
25                 Commented heavily, and beautified the code.\r
26                 Nearly rewrote the program completely, by using another OO strategy.\r
27                 Changed use of abort() to exit(1).\r
28                 Text test pattern now fills entire text buffer from 0xb800:0x0000\r
29                         to 0xb800:0xffff.\r
30                 TWEAK now captures whatever screen mode is active at startup,\r
31                         instead of defaulting to BIOS mode 3 (80x25).\r
32                 The screen is reset to the startup BIOS mode at exit, too.\r
33                 Added 'S' and 'L' as synonyms for F9 and F10.\r
34                 Added Shift+TAB as a companion to TAB.\r
35                 Editing screen now uses 80x50 instead of 80x25.\r
36                 Added one text test screen which uses the 8x8 font.\r
37                 Added online help, not context sensitive as promised.  Maybe later.\r
38                 Edititing screen is cleared when a test is initiated, so that it\r
39                         is easier to see that something happened if the wrong test\r
40                         screen is selected.\r
41                 Removed startup banner.\r
42                 Removed use of cout and cin for screen/keyboard I/O, in favour of\r
43                         the colors and windows provided by conio.h.\r
44                 Instead, I use fstreams for *file* I/O... much more convenient than\r
45                         FILEs.\r
46                 Made the interface more cheerful by using lots of colors.\r
47         1.1\r
48                 Nuked a serious bug in the text test pattern.  At the end, it\r
49                         wrote characters far outside of the video buffer, overwriting\r
50                         0x800 bytes at the start of the 0xC000 segment.\r
51                         Most PCs have ROM in this area, so I didn't notice the\r
52                         bug until I ran TWEAK on some 486s with a SCSI harddisk.\r
53                         I think those map some RAM to that segment, in any case\r
54                         TWEAK crashed whenever the text pattern was used on those\r
55                         machines.\r
56                 I Decided not to read back the registers when returning from the\r
57                         test screen.  It was not very usable, and imposed some\r
58                         problems when using different test screens.\r
59                 Never released.\r
60         1.5\r
61                 Added the AutoDetect testing pattern, which makes use of my new,\r
62                         mode independant VGA graphics library to make the testing\r
63                         much more interesting and informative.  Might add simple\r
64                         menus to this later.\r
65                 Fixed a bug in the VGA library for Chained 256-color modes, which\r
66                         caused scrolling to go four times as far as intended.\r
67                 Made the help window larger, more readable.\r
68                 Added question of confirmation to quit when ESC is pressed.\r
69                 Added lots more sample modes (from xlib06).\r
70         1.6\r
71                 Added the mode heuristics seen in the autodetect test screen to\r
72                         the editor screen.  This gives the user instant feedback on\r
73                         his work.\r
74                 Fixed the RegTable::out() method to correctly reset the sequencer.\r
75                         Result: no flickering when testing modes.\r
76                 The autodetect screen sets the VGA palettes to the BIOS default.\r
77 */\r
78 \r
79 #ifndef __LARGE__\r
80 # ifndef __COMPACT__\r
81 #  ifndef __HUGE__\r
82 #   error A large data model is required!\r
83 #  endif\r
84 # endif\r
85 #endif\r
86 \r
87 \r
88 #include <stdio.h>\r
89 #include <dos.h>\r
90 #include <stdlib.h>\r
91 #include <conio.h>\r
92 #include <fstream.h>\r
93 #include <ctype.h>\r
94 #include <string.h>\r
95 \r
96 #include "Screen.HPP"\r
97 #include "RegEdit.HPP"\r
98 #include "TestPat.HPP"\r
99 #include "detect.hpp"\r
100 \r
101 \r
102 void helpWindow()\r
103         {\r
104         tempBuffer swap(textScr);\r
105         swap.save();\r
106         window(5,5,editWidth-5,33);\r
107         textattr(HELP_COLOR);\r
108         clrscr();\r
109         window(6,6,editWidth-6,32);\r
110         gotoxy(1,1);\r
111         cprintf("TWEAK 1.6á by Robert Schmidt - Ztiff Zox Softwear\n\r"\r
112                         "Quick reference help screen\n\r"\r
113                         "\n\r"\r
114                         "Up/Down/Home/End: select register\n\r"\r
115                         "       Backspace: enable/disable register\n\r"\r
116                         "    2 hex digits: set register value\n\r"\r
117                         "             -/+: decrease/increase register value\n\r"\r
118                         "           F1-F8: toggle register bits 7-0\n\r"\r
119                         "       F9 or 'S': save register set to file\n\r"\r
120                         "      F10 or 'L': load set from file\n\r"\r
121                         "             'M': select BIOS mode to work from\n\r"\r
122                         "   TAB/Shift-TAB: select test screen\n\r"\r
123                         "           ENTER: show test screen\n\r"\r
124                         "             'H': show this help window\n\r"\r
125                         "             ESC: Quit TWEAK immediately\n\r"\r
126                         "\n\r"\r
127                         "The mode heuristics shown are NOT perfect.  It is practically\n\r"\r
128                         "impossible to foresee what your screen will show.  Use the\n\r"\r
129                         "values given as guidance, or hints.\n\r"\r
130                         "\n\r"\r
131                         "When viewing the autodetect test screen, you may use the\n\r"\r
132                         "arrows to scroll over the virtual screen.  Press ESC or ENTER\n\r"\r
133                         "to leave.\n\r"\r
134                         "\n\r"\r
135                         "For more information, see the TWEAK.DOC file.\n\r"\r
136                         "Now press the 'any' key to return to the editor.\n\r"\r
137                         );\r
138         getch();\r
139         window(1,1,editWidth,editHeight);\r
140         swap.restore();\r
141         }\r
142 \r
143 \r
144 void prompt(char *p = 0, int attr = PROMPT_COLOR)\r
145         {\r
146         textattr(7);\r
147         gotoxy(42,editHeight-1);\r
148         clreol();\r
149         textattr(attr);\r
150         if (p)\r
151                 cprintf(p);\r
152         }\r
153 \r
154 \r
155 int main(int argc, char **argv)\r
156         {\r
157         // Initialize the register table with descriptions and all.\r
158         RegisterEditor regEditor(ifstream("TWEAK.DAT"));\r
159         TestPatterns test;\r
160 \r
161         int parentBiosMode = getBiosMode();\r
162         preparePalettes();\r
163         // Set our default editing screen, and get its dimensions\r
164         setBiosMode(3);\r
165         textmode(C4350);\r
166         clrscr();\r
167         text_info *ti = new text_info;\r
168         gettextinfo(ti);\r
169         editMode = ti->currmode;\r
170         editHeight = ti->screenheight;\r
171         editWidth = ti->screenwidth;\r
172         editSize = editHeight * editWidth;\r
173         delete ti;\r
174 \r
175         tempBuffer swap(textScr);       // Establish the temporary screen buffer\r
176 \r
177         unsigned char quit = 0;                 // Non-zero when a quit command is\r
178                                                                         //      initiated.\r
179         int key;                                                // The last key pressed.\r
180 \r
181         // Build the editing screen:\r
182 \r
183         regEditor.printAllCon();\r
184         gotoxy(42, editHeight-20);\r
185         textattr(HELP_COLOR);\r
186         cprintf("(Press H if you need help)");\r
187 \r
188         ModeInfo minfo(regEditor);\r
189 \r
190         // Start the main keyboard polling loop:\r
191 \r
192         while (!quit)\r
193                 {\r
194                 test.tellTest();\r
195                 regEditor.showBitMask();\r
196                 minfo.show();\r
197                 regEditor.updateSelect();\r
198 \r
199                 int key = getch();\r
200                 if (!key)\r
201                         key = getch() << 8;\r
202                 else\r
203                         key = tolower(key);\r
204 \r
205 keyentry:\r
206                 switch (key)\r
207                         {\r
208                         case 0x4700:                    //HOME\r
209                                 regEditor.setSelect(0);\r
210                                 break;\r
211                         case 0x4800:                    //UP\r
212                                 --regEditor;\r
213                                 break;\r
214                         case 0x4F00:                    //END\r
215                                 regEditor.setSelect(regEditor.getMaxReg());\r
216                                 break;\r
217                         case 0x5000:                    //DOWN\r
218                                 ++regEditor;\r
219                                 break;\r
220 \r
221                         // Function keys - toggle single bit in selected reg.\r
222                         case 0x3B00:                    //F1\r
223                         case 0x3C00:\r
224                         case 0x3D00:\r
225                         case 0x3E00:\r
226                         case 0x3F00:\r
227                         case 0x4000:\r
228                         case 0x4100:\r
229                         case 0x4200:                    //F8\r
230                                 **regEditor ^= (1<<7-((key>>8)-0x3B));\r
231                                 break;\r
232 \r
233                         case 0x4300:                    //F9\r
234                         case 0x4400:                    //F10\r
235                                 // Handle file operations (save/load):\r
236                                 char fname[63];\r
237                                 int save=(key==0x4300);\r
238 \r
239                                 // Prompt for filename.\r
240                                 if (save)\r
241                                         prompt("Save file name: ");\r
242                                 else\r
243                                         prompt("Load file name: ");\r
244                                 gets(fname);\r
245                                 if (strlen(fname) == 0)\r
246                                         {\r
247                                         prompt("File operation canceled.");\r
248                                         break;\r
249                                         }\r
250 \r
251                                 prompt(0, ERROR_COLOR); // prepare for error\r
252                                 if (save)\r
253                                         {\r
254                                         ofstream out(fname, ios::trunc|ios::binary|ios::out);\r
255                                         if (out.bad())\r
256                                                 cprintf("Error creating '%s'!", fname);\r
257                                         else\r
258                                                 {\r
259                                                 out << regEditor;\r
260                                                 if (out.bad())\r
261                                                         cprintf("Error writing '%s'!", fname);\r
262                                                 else\r
263                                                         {\r
264                                                         prompt(fname);\r
265                                                         cprintf(" written.");\r
266                                                         }\r
267                                                 }\r
268                                         }\r
269                                 else\r
270                                         {\r
271                                         ifstream in(fname, ios::binary|ios::in|ios::nocreate);\r
272                                         if (in.bad())\r
273                                                 cprintf("Error opening '%s'!", fname);\r
274                                         else\r
275                                                 {\r
276                                                 in >> regEditor;\r
277                                                 if (in.bad())\r
278                                                         cprintf("Error reading '%s'!", fname);\r
279                                                 else\r
280                                                         {\r
281                                                         prompt(fname);\r
282                                                         cprintf(" read.");\r
283                                                         }\r
284                                                 }\r
285                                         }\r
286 \r
287                                 // Update screen to reflect changes (if any).\r
288                                 regEditor.printAllCon();\r
289                                 test.tellTest();\r
290                                 break;\r
291 \r
292                         case '0': case '1': case '2': case '3': case '4': case '5':\r
293                         case '6': case '7': case '8': case '9': case 'a': case 'b':\r
294                         case 'c': case 'd': case 'e': case 'f':\r
295                                 // Input hexadecimal number:\r
296                                 gotoxy(40*(regEditor.getSelect()/editHeight)+38,\r
297                                         regEditor.getSelect()%editHeight+1);\r
298                                 ungetch(key);\r
299                                 cprintf("%c \b", key);\r
300                                 unsigned char newValue;\r
301                                 cscanf("%2hx", &newValue);\r
302                                 (*regEditor).setValue(newValue);\r
303                                 break;\r
304 \r
305                         case 'h':\r
306                                 // Help:\r
307                                 helpWindow();\r
308                                 break;\r
309 \r
310                         // Alternate file I/O keys:\r
311                         case 's':\r
312                                 key = 0x4300;\r
313                                 goto keyentry;\r
314 \r
315                         case 'l':\r
316                                 key = 0x4400;\r
317                                 goto keyentry;\r
318 \r
319                         case 'm':\r
320 \r
321                                 // Select a BIOS mode to work from.\r
322                                 int baseMode;\r
323                                 prompt("Base BIOS screen mode: 0x");\r
324                                 cscanf("%2hx",&baseMode);\r
325                                 swap.save();                            //save edit buffer\r
326 \r
327                                 // Set the selected mode, and grab register values.\r
328                                 setBiosMode(baseMode);\r
329                                 regEditor.in();\r
330                                 swap.restore();                         //reset edit mode and buffer\r
331                                 regEditor.printAllCon();\r
332                                 prompt();\r
333                                 cprintf("Got registers from mode 0x%02x", baseMode);\r
334                                 break;\r
335 \r
336                         case 8:\r
337                                 (*regEditor).toggleEnable();\r
338                                 ++regEditor;\r
339                                 break;\r
340 \r
341                         case '-':\r
342                                 // Decrease register value:\r
343                                 // Note that * (dereferencing) is overloaded for both\r
344                                 //      RegisterTable and Register!  Pretty fancy, but hard\r
345                                 //      to read!\r
346                                 -- **regEditor;\r
347                                 break;\r
348 \r
349                         case '+':\r
350                                 // Increase register value\r
351                                 ++ **regEditor;\r
352                                 break;\r
353 \r
354                         case 13:        //ENTER\r
355                                 // Test the screen mode.\r
356                                 swap.save();\r
357                                 // Clear the text screen, so the user can see something is\r
358                                 //      happening even if he chose the wrong test screen.\r
359                                 clrscr();\r
360                                 test.run(regEditor);\r
361                                 swap.restore();\r
362                                 break;\r
363 \r
364                         case 9:         //TAB\r
365                                 // Select next test pattern:\r
366                                 ++test;\r
367                                 break;\r
368 \r
369                         case 0x0F00: // shift-TAB\r
370                                 // Select previous test pattern:\r
371                                 --test;\r
372                                 break;\r
373 \r
374                         case 27:        //ESC\r
375                                 // Quit TWEAK:\r
376                                 prompt("Really quit [n]?");\r
377                                 if (toupper(getch()) == 'Y')\r
378                                         quit = 1;\r
379                                 prompt();\r
380                                 break;\r
381                         }\r
382                 minfo.detectFrom(regEditor);\r
383                 }\r
384 \r
385         // Reset BIOS mode detected at startup.\r
386         setBiosMode(parentBiosMode);\r
387 \r
388         return 0;\r
389         }