1 #include "3dc.h"
2
3 #include <sys/stat.h>
4 #include <string.h>
5
6 #include "inline.h"
7 #include "module.h"
8
9 #include "chnktexi.h"
10 #include "d3d_hud.h"
11 #define UseLocalAssert Yes
12 #include "ourasert.h"
13 #include "hud_layout.h"
14
15 #undef textprint
16
17 #define textprintOn Yes
18
19 #define DHMtextprint Yes
20 /* define to use Dave Malcolm's replacement textprint routines */
21
22
23 /* As specified by Roxby */
24 #define ClearScreenColour 1000
25
26 /*
27 Experiment to try and fix mystery driver problems
28 Don't set with ForceWindowsPalette on!!!
29 Leave this on!!!
30 On some video cards it seems necessary not only to
31 set palette on vblanking interval, but also AFTER
32 D3D initialisation is complete...
33 */
34
35 #define ChangePaletteOnVBAlways Yes
36
37 /*
38 Turn on or off checking for the validity
39 of a video mode before switching to it.
40 Actually causes problems on some systems
41 because the DirectDraw enumerator fails to
42 report valid modes (although on other systems
43 it can report ones that can't be reached, ho
44 hum), so at least for Chris H. it needs to be
45 turned off.
46 NOTE THAT THIS SHOULD HAVE THE SAME SETTING AS
47 CheckVideoModes at the start of dd_func.cpp, at
48 least until we make it a system.h value or
49 something else sensible...
50 */
51
52 #define CheckVideoModes No
53
54
55 /*
56
57 externs for commonly used global variables and arrays
58
59 */
60
61 extern SHAPEHEADER **mainshapelist;
62 extern SHAPEHEADER *testpaletteshapelist[];
63 extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
64 extern int *Global_ShapeNormals;
65 extern int *Global_ShapePoints;
66 extern int *ItemPointers[];
67 extern int ItemData[];
68 extern char projectsubdirectory[];
69
70 extern int WinLeftX;
71 extern int WinRightX;
72 extern int WinTopY;
73 extern int WinBotY;
74
75 extern int WindowRequestMode;
76 extern int VideoRequestMode;
77 extern int ZBufferRequestMode;
78 extern int RasterisationRequestMode;
79 extern int SoftwareScanDrawRequestMode;
80 extern int DXMemoryRequestMode;
81
82 extern int TotalVideoMemory;
83 extern int NumAvailableVideoModes;
84 extern VIDEOMODEINFO AvailableVideoModes[];
85
86 extern int memoryInitialisationFailure;
87
88 extern IMAGEHEADER ImageHeaderArray[]; /* Array of Image Headers */
89
90 /*
91
92 Global Variables for PC Watcom Functions
93 and Windows 95!
94
95 */
96
97 /* Timer */
98 long lastTickCount;
99
100 unsigned char *ScreenBuffer = 0; /* Ensure initialised to Null */
101
102 unsigned char LPTestPalette[1024]; /* to cast to lp*/
103
104 int InputMode;
105
106 int VideoMode;
107 int VideoModeType;
108 int VideoModeTypeScreen;
109 int WindowMode;
110 int ScanDrawMode;
111 int ZBufferMode;
112 int DXMemoryMode;
113 unsigned char AttemptVideoModeRestart;
114 VIDEORESTARTMODES VideoRestartMode;
115
116 PROCESSORTYPES ProcessorType;
117 BOOL MMXAvailable;
118
119 unsigned char *TextureLightingTable = 0;
120
121 unsigned char *PaletteRemapTable = 0;
122
123 int NumShadingTables = 0;
124
125 int NumPaletteShadingTables = 0;
126
127 int FrameRate;
128 int NormalFrameTime;
129 int PrevNormalFrameTime;
130 extern int CloakingPhase;
131
132 /* These two are dummy values to get the DOS platform to compile */
133
134 unsigned char KeyCode;
135 unsigned char KeyASCII;
136
137
138 #if SuppressWarnings
139 unsigned char *palette_tmp;
140 static VIEWDESCRIPTORBLOCK* vdb_tmp;
141 static SCREENDESCRIPTORBLOCK* sdb_tmp;
142 #endif
143
144 /* Keyboard */
145 unsigned char KeyboardInput[MAX_NUMBER_OF_INPUT_KEYS];
146 unsigned char GotAnyKey;
147
148 /* Input communication with Windows Procedure */
149 /* Print system */
150
151 #if !DHMtextprint
152 PRINTQUEUEITEM PrintQueue[MaxMessages];
153 int MessagesStoredThisFrame;
154 #endif
155
156 int textprintPosX;
157 int textprintPosY;
158 IMAGEHEADER* fontHeader;
159
160 /* Added 28/11/97 by DHM: boolean for run-time switching on/off of textprint */
161 int bEnableTextprint = No;
162
163 /* Added 28/1/98 by DHM: as above, but applies specifically to textprintXY */
164 int bEnableTextprintXY = Yes;
165
166 /* Palette */
167
168 unsigned char PaletteBuffer[768 + 1];
169
170 /* Test Palette */
171
172 unsigned char TestPalette[768];
173 unsigned char TestPalette2[768];
174
175
176
177
178 /* KJL 11:48:45 28/01/98 - used to scale NormalFrameTime, so the game can be slowed down */
179 int TimeScale=65536;
180
181 /* KJL 16:00:11 28/01/98 - unscaled frame time */
182 int RealFrameTime;
183 int GlobalFrameCounter;
184 int RouteFinder_CallsThisFrame;
185
186 /* KJL 15:08:43 29/03/98 - added to give extra flexibility to debugging text */
187 int PrintDebuggingText(const char* t, ...);
188 int ReleasePrintDebuggingText(const char* t, ...);
189
190
191 /*
192
193 IO and Other Functions for the PC
194
195 */
196
197
198 /*
199
200 Get Shape Data
201
202 Function returns a pointer to the Shape Header Block
203
204 */
205
GetShapeData(int shapenum)206 SHAPEHEADER* GetShapeData(int shapenum)
207
208 {
209
210 if(shapenum>=0 && shapenum< maxshapes)
211 {
212 SHAPEHEADER *sptr = mainshapelist[shapenum];
213 return sptr;
214 }
215
216 return NULL;
217 }
218
219
220 /*
221
222 Platform specific VDB functions for Initialisation and ShowView()
223
224 */
225
PlatformSpecificVDBInit(VIEWDESCRIPTORBLOCK * vdb)226 void PlatformSpecificVDBInit(VIEWDESCRIPTORBLOCK *vdb)
227
228 {
229 #if SuppressWarnings
230 vdb_tmp = vdb;
231 #endif
232 }
233
234
PlatformSpecificShowViewEntry(VIEWDESCRIPTORBLOCK * vdb,SCREENDESCRIPTORBLOCK * sdb)235 void PlatformSpecificShowViewEntry(VIEWDESCRIPTORBLOCK *vdb, SCREENDESCRIPTORBLOCK *sdb)
236
237 {
238 #if SuppressWarnings
239 vdb_tmp = vdb;
240 sdb_tmp = sdb;
241 #endif
242 }
243
244
PlatformSpecificShowViewExit(VIEWDESCRIPTORBLOCK * vdb,SCREENDESCRIPTORBLOCK * sdb)245 void PlatformSpecificShowViewExit(VIEWDESCRIPTORBLOCK *vdb, SCREENDESCRIPTORBLOCK *sdb)
246
247 {
248 #if SuppressWarnings
249 vdb_tmp = vdb;
250 sdb_tmp = sdb;
251 #endif
252 }
253
254
255 /*
256
257 Convert UNIX to MS-DOS
258
259 */
260
GetDOSFilename(char * fnameptr)261 void GetDOSFilename(char *fnameptr)
262
263 {
264
265 while(*fnameptr) {
266
267 if(*fnameptr == 0x2f) *fnameptr = 0x5c;
268 fnameptr++;
269
270 }
271
272 }
273
274 /*
275
276 Compare two filenames.
277
278 The first filename is assumed to be raw i.e. has no project subdirectory appended.
279 The second is assumed to be ready for use.
280
281 Make a copy of both strings, prefix the copy of the first with the project subdirectory
282 and convert them to DOS format before the comparison.
283
284 */
285
CompareFilenameCH(char * string1,char * string2)286 int CompareFilenameCH(char *string1, char *string2)
287
288 {
289
290 char *srtmp1;
291 char *srtmp2;
292 int slen1 = 0;
293 int slen2 = 0;
294 int i;
295 char fname1[ImageNameSize];
296 char fname2[ImageNameSize];
297
298
299 #if 0
300 textprint(" Compare "); textprint(string1); textprint("\n");
301 textprint(" with "); textprint(string2); textprint("\n");
302 /*WaitForReturn();*/
303 #endif
304
305
306 /* Make a copy of string 1, adding the project subdirectory */
307
308 srtmp1 = projectsubdirectory;
309 srtmp2 = fname1;
310 while(*srtmp1) *srtmp2++ = *srtmp1++;
311 srtmp1 = string1;
312 while(*srtmp1) *srtmp2++ = *srtmp1++;
313 *srtmp2 = 0;
314
315 /* Make a copy of string 2 */
316
317 srtmp1 = string2;
318 srtmp2 = fname2;
319 while(*srtmp1) *srtmp2++ = *srtmp1++;
320 *srtmp2 = 0;
321
322 /* How long are they? */
323
324 srtmp1 = fname1;
325 while(*srtmp1++ != 0)
326 slen1++;
327
328 srtmp2 = fname2;
329 while(*srtmp2++ != 0)
330 slen2++;
331
332 fname1[slen1] = 0; /* Term */
333 fname2[slen2] = 0;
334
335 #if 0
336 textprint("slen1 = %d, ", slen1);
337 textprint("slen2 = %d\n", slen2);
338 #endif
339
340 #if 0
341 textprint(" Compare "); textprint(fname1); textprint("\n");
342 textprint(" with "); textprint(fname2); textprint("\n");
343 /*WaitForReturn();*/
344 #endif
345
346
347 GetDOSFilename(fname1);
348 GetDOSFilename(fname2);
349
350
351 if(slen1 != slen2) {
352 /*textprint("not same\n");*/
353 return No;
354 }
355
356 srtmp1 = fname1;
357 srtmp2 = fname2;
358
359 #if 0
360 textprint(" Compare "); textprint(srtmp1); textprint("\n");
361 textprint(" with "); textprint(srtmp2); textprint("\n");
362 WaitForReturn();
363 #endif
364
365 for(i = slen1; i!=0; i--) {
366 if(*srtmp1++ != *srtmp2++) {
367 /*textprint("not same\n");*/
368 return No;
369 }
370 }
371
372 /*textprint("same\n");*/
373 return Yes;
374
375 }
376
377
378
379
380
381
382
383 /*
384
385 Create an RGB table for "palette"
386
387 "GetRemappedPaletteColour()" is an access function for this table
388
389 */
390
NearestColour(int rs,int gs,int bs,unsigned char * palette)391 int NearestColour(int rs, int gs, int bs, unsigned char *palette)
392
393 {
394
395 int i;
396 VECTORCH p0;
397 VECTORCH p1;
398 int nearest_index;
399 int nearest_delta;
400 int d;
401
402
403 p0.vx = rs;
404 p0.vy = gs;
405 p0.vz = bs;
406
407 nearest_index = 0;
408 nearest_delta = bigint;
409
410 for(i = 0; i < 256; i++) {
411
412 p1.vx = palette[0];
413 p1.vy = palette[1];
414 p1.vz = palette[2];
415
416 d = FandVD_Distance_3d(&p0, &p1);
417
418 if(d < nearest_delta) {
419
420 nearest_delta = d;
421 nearest_index = i;
422
423 }
424
425 palette += 3;
426
427 }
428
429 return nearest_index;
430
431 }
432
433
434 /*************************************************************************/
435 /*************************************************************************/
436
437
438 /*
439
440 Initialise System and System Variables
441
442 */
443
InitialiseSystem()444 void InitialiseSystem()
445 {
446 BOOL rc;
447 HINSTANCE hInstance = 0;
448 int nCmdShow = 1;
449
450 /*
451 Pick up processor type
452 */
453
454 ProcessorType = ReadProcessorType();
455
456 if ((ProcessorType == PType_PentiumMMX) ||
457 (ProcessorType == PType_Klamath) ||
458 (ProcessorType == PType_OffTopOfScale))
459 MMXAvailable = TRUE;
460 else
461 MMXAvailable = FALSE;
462
463 /*
464 Copy initial requests to current variables,
465 subject to later modification.
466 */
467
468 VideoMode = VideoRequestMode;
469 WindowMode = WindowRequestMode;
470
471 /*
472 Initialise dubious restart
473 system for ModeX emulation
474 and other problems
475 */
476
477 AttemptVideoModeRestart = No;
478
479 VideoRestartMode = NoRestartRequired;
480
481 /*
482 Potentially a whole suite of caps
483 functions could be sensibly called
484 from here, to determine available
485 sound hardware, network links, 3D
486 hardware acceleration etc
487 */
488
489 /*
490 Initialise the basic Direct Draw object,
491 find a hardware 3D capable driver if
492 possible and appropriate, and
493 determine what display modes, available
494 video memory etc exist.
495 */
496
497 #if 0 /* LINUX */
498 if (InitialiseDirectDrawObject()
499 == FALSE)
500 /*
501 If we cannot get a video mode,
502 fail. No point in a non debugging option
503 for this.
504 */
505 {
506 ReleaseDirect3D();
507 exit(0x997799);
508 }
509
510 /*
511 Initialise global to say whether
512 we think there is an onboard 3D
513 acceleration card / motherboard
514 built-in
515 */
516
517 TestInitD3DObject();
518
519 /*
520 This is (HOPEFULLY!!) now the right
521 place to put this call. Note that it is
522 not absolutely certain that we can do test
523 blits from DirectDraw without setting
524 a cooperative level, however... And note also
525 that MMX works better with the back buffer in
526 system memory...
527 */
528 TestMemoryAccess();
529 #endif
530
531 /* Initialise main window, windows procedure etc */
532 rc = InitialiseWindowsSystem(hInstance, nCmdShow, WinInitFull);
533
534 /* Initialise input interface */
535 memset((void*)KeyboardInput, No, MAX_NUMBER_OF_INPUT_KEYS);
536 GotAnyKey = No;
537
538 #if 0 /* LINUX */
539 /* launch Direct Input */
540 InitialiseDirectInput();
541 InitialiseDirectKeyboard();
542 InitialiseDirectMouse();
543 InitJoysticks();
544 #endif
545
546 /* Initialise textprint system */
547 textprintPosX = 0;
548 textprintPosY = 0;
549 #if debug
550 InitPrintQueue();
551 #endif
552
553 #if SUPPORT_MMX
554 SelectMMXOptions();
555 #endif
556
557 {
558 /* CDF 4/2/97 */
559 extern void ConstructOneOverSinTable(void);
560
561 ConstructOneOverSinTable();
562 }
563
564 }
565
566
567 /*
568
569 Exit the system
570
571 */
572
ExitSystem(void)573 void ExitSystem(void)
574 {
575 /* Game specific exit functions */
576 ExitGame();
577
578
579 // Added by Mark so that Direct Sound exits cleanly
580 #if SOUND_ON
581 ExitSoundSystem(); // In ds_func.cpp
582 #endif
583
584 /*
585 Shaft DirectDraw and hit Direct3D
586 with a blunt Bill.
587 Note that ReleaseDirect3D is currently
588 responsible for whacking DirectDraw
589 and DirectInput as well; I should probably
590 rename it ReleaseDirectX sometime...
591 */
592
593 ReleaseDirect3D();
594
595 /* Kill windows procedures */
596 ExitWindowsSystem();
597 }
598
599 /*
600 Timer functions are based on Windows timer
601 giving number of millisecond ticks since Windows
602 was last booted. Note this will wrap round after
603 Windows has been up continuously for approximately
604 49.7 days. This is not considered to be too
605 significant a limitation...
606 */
607
608
609
ResetFrameCounter(void)610 void ResetFrameCounter(void)
611 {
612 lastTickCount = timeGetTime();
613
614 /* KJL 15:03:33 12/16/96 - I'm setting NormalFrameTime too, rather than checking that it's
615 non-zero everytime I have to divide by it, since it usually is zero on the first frame. */
616 NormalFrameTime = 65536 >> 4;
617 PrevNormalFrameTime = NormalFrameTime;
618
619 RealFrameTime = NormalFrameTime;
620 FrameRate = 16;
621 GlobalFrameCounter=0;
622 CloakingPhase = 0;
623
624
625 RouteFinder_CallsThisFrame=0;
626 }
FrameCounterHandler(void)627 void FrameCounterHandler(void)
628 {
629 int newTickCount = timeGetTime();
630 int fcnt;
631
632 fcnt = newTickCount - lastTickCount;
633 lastTickCount = newTickCount;
634
635 if (fcnt == 0)
636 fcnt = 1; /* for safety */
637
638 FrameRate = TimerFrame / fcnt;
639
640 PrevNormalFrameTime = NormalFrameTime;
641 NormalFrameTime = DIV_FIXED(fcnt,TimerFrame);
642
643 RealFrameTime = NormalFrameTime;
644
645 {
646 if (TimeScale!=ONE_FIXED)
647 {
648 NormalFrameTime = MUL_FIXED(NormalFrameTime,TimeScale);
649 }
650
651 }
652 /* cap NormalFrameTime if frame rate is really low */
653 if (NormalFrameTime>16384) NormalFrameTime=16384;
654 GlobalFrameCounter++;
655 CloakingPhase += NormalFrameTime>>5;
656
657 RouteFinder_CallsThisFrame=0;
658 }
659
660 /*
661
662 Wait for Return Key
663
664 Such a function may not be defined on some platforms
665
666 On Windows 95 the description of this function has
667 been changed, so that it calls FlushTextprintBuffer
668 and FlipBuffers before going into the actual
669 WaitForReturn code. This is necessary if it is to
670 behave in the same way after a textprint call as it
671 does on the DOS platform.
672
673 */
674
WaitForReturn(void)675 void WaitForReturn(void)
676
677 {
678 /* Crude but probably serviceable for now */
679 long SavedTickCount;
680 SavedTickCount = lastTickCount;
681
682 /* Display any lingering text */
683 FlushTextprintBuffer();
684 FlipBuffers();
685
686 while (!(KeyboardInput[KEY_CR]))
687 DirectReadKeyboard();
688
689 lastTickCount = SavedTickCount;
690 }
691
692
693
694
695 /*
696 By copying the globals here we guarantee
697 that game functions will receive a set of
698 input values updated at a defined time
699 */
700
701
ReadUserInput(void)702 void ReadUserInput(void)
703 {
704 DirectReadMouse();
705 ReadJoysticks();
706 DirectReadKeyboard();
707 }
708
709 /*
710 At present all keyboard and mouse input is handled
711 through project specific functionality in win_func,
712 and all these functions are therefore empty. Later
713 we may port to DirectInput, at which point we
714 may reactivate these.
715 */
716
717
718
ReadKeyboard(void)719 void ReadKeyboard(void)
720
721 {
722 }
723
724
ReadMouse(void)725 void ReadMouse(void)
726
727 {
728
729
730 }
731
732
733
734 /*
735 Not NECESSARILY the standard functionality,
736 but it seems good enough to me...
737 */
738
CursorHome(void)739 void CursorHome(void)
740
741 {
742 /* Reset positions for textprint system */
743 textprintPosX = 0;
744 textprintPosY = 0;
745 }
746
747
GetProjectFilename(char * fname,char * image)748 void GetProjectFilename(char *fname, char *image)
749 {
750
751 char *src;
752 char *dst;
753
754
755 src = projectsubdirectory;
756 dst = fname;
757
758 while(*src)
759 *dst++ = *src++;
760
761 src = image;
762
763 while(*src)
764 *dst++ = *src++;
765
766 *dst = 0;
767
768 }
769
770
771 /*
772
773 Attempts to load the image file.
774
775 Returns a pointer to the image if successful, else zero.
776
777 Image Header is filled out if successful, else ignore it.
778
779 NOTE
780
781 The pointer to the image data is also stored in the image
782 header.
783
784 */
785
LoadImageCH(char * fname,IMAGEHEADER * iheader)786 TEXTURE* LoadImageCH(char *fname, IMAGEHEADER *iheader)
787 {
788 return 0;
789 }
790
791
ConvertToDDPalette(unsigned char * src,unsigned char * dst,int length,int flags)792 void ConvertToDDPalette(unsigned char* src, unsigned char* dst, int length, int flags)
793 {
794 int i;
795
796 /*
797 Copy palette, introducing flags and shifting up
798 to 8 bit triple
799 */
800
801 for (i=0; i<length; i++)
802 {
803 *dst++ = (*src++) << 2;
804 *dst++ = (*src++) << 2;
805 *dst++ = (*src++) << 2;
806 *dst++ = flags;
807 }
808 }
809
810 /*
811
812 Platform specific version of "printf()"
813
814 Not all platforms support, or indeed are ABLE to support printf() in its
815 general form. For this reasons calls to textprint() are made through this
816 function.
817
818 */
819
820 /*
821 If debug or textprintOn are not defined, these
822 function defintions are collapsed to a simple
823 return value, which should collapse to no object
824 code under optimisation.
825 The whole issue of turning on or off textprint
826 beyond this point is hereby left to Kevin and
827 Chris H to fight to the death about...
828 */
829
830 #if DHMtextprint
831
832
833 /*
834 Dave Malcolm 21/11/96:
835
836 I have rewritten the Win95 textprint routines below.
837
838 It should now support:
839 - carriage returns are no longer automatic at the end of lines; there is a #define if you want this behaviour back
840 - carriage return characters cause a carriage return
841 - wraparound at the right-hand edge of the screen, with textprint() wrapping to the left-hand edge,
842 and textprintXY() wrapping back to the X coordinate
843 - clipping at the bottom edge of the screen
844 - a warning message if text has been lost due to clipping or buffer overflows etc.
845 - a y-offset that can be used to scroll up and down the text overlay output from textprint
846 */
847
848 /* VERSION SETTINGS: */
849 #define AutomaticNewLines No
850 /* set this to Yes and you will get a \n inserted automatically at the end of each line */
851 #if AutomaticNewLines
852 #error Not yet written...
853 #endif
854
855 /* LOW LEVEL ASSERTION SUPPORT */
856 /*
857 We cannot use standard assertions in this routine because this routine is called by the standard
858 assertion routine, and so would run the risk of infinite loops and excitingly obscure bugs.
859
860 For this reason we define a special assert macro.
861 */
862
863 #if 1
864 #define LOWLEVELASSERT(ignore)
865 #else
866 #if debug
867
868 #define LOWLEVELASSERT(x) \
869 (void) \
870 ( \
871 (x) \
872 ? 1 : (ReleaseDirect3D(),exit(GlobalAssertCode),0) \
873 )
874
875 #else
876 /* Assertions are disabled at compile-time: */
877 #define LOWLEVELASSERT(ignore)
878
879 #endif
880 #endif
881
882
883 /*
884 We extract arguments into a buffer, with a dodgy hack to increase it in size to give more defence
885 against buffer overflows; there seems to be no easy & robust way to give vsprintf() a buffer size...
886
887 This buffer is reset once per string per frame
888 */
889 #define PARANOIA_BYTES (1024)
890 #define TEXTPRINT_BUFFER_SIZE (MaxMsgChars+PARANOIA_BYTES+1)
891 static char TextprintBuffer[TEXTPRINT_BUFFER_SIZE]="";
892
893 /*
894
895 The PRINTQUEUEITEM structure from PLATFORM.H is not used by my system; instead of queueing strings to be
896 displayed we do it on a character by character basis, with a limit on the total number of chars per frame.
897
898 This limit is set to be (MaxMsgChars*MaxMessages), which gives the same power and more flexibility than the
899 old system.
900
901 When the queue is full, additional characters get ignored.
902
903 This is queue is reset once per frame.
904
905 */
906
907 typedef struct daveprintchar {
908 char CharToPrint;
909 int x,y;
910 } DAVEPRINTCHAR;
911
912 #define DHM_PRINT_QUEUE_SIZE (MaxMsgChars*MaxMessages)
913
914 static DAVEPRINTCHAR DHM_PrintQueue[DHM_PRINT_QUEUE_SIZE];
915 static int DHM_NumCharsInQueue=0;
916
917 static int fTextLost=No;
918 static char TextLostMessage[]="textprint warning:TEXT LOST";
919 #define TEXT_LOST_X (50)
920 #define TEXT_LOST_Y (20)
921
922 volatile int textprint_Y_offset=0;
923
924
925 /* Dave's version of initialising the print queue */
InitPrintQueue(void)926 void InitPrintQueue(void)
927 {
928 DHM_NumCharsInQueue=0;
929 fTextLost=No;
930 }
931
932 /*
933
934 Old systems comment:
935 Write all messages in buffer to screen
936 (to be called at end of frame, after surface
937 / execute buffer unlock in DrawItemListContents,
938 so that text appears at the front of the back
939 buffer immediately before the flip).
940
941 This is Dave's version of the same:
942 */
943
FlushTextprintBuffer(void)944 void FlushTextprintBuffer(void)
945
946 {
947 /* PRECONDITION: */
948 {
949 LOWLEVELASSERT(DHM_NumCharsInQueue<DHM_PRINT_QUEUE_SIZE);
950 }
951
952 /* CODE: */
953 {
954 {
955 int i;
956 DAVEPRINTCHAR* pDPR=&DHM_PrintQueue[0];
957
958 for (i=0; i<DHM_NumCharsInQueue; i++)
959 {
960 #if 0
961 BlitWin95Char
962 (
963 pDPR->x,
964 pDPR->y,
965 pDPR->CharToPrint
966 );
967 #else
968 D3D_BlitWhiteChar
969 (
970 pDPR->x,
971 pDPR->y,
972 pDPR->CharToPrint
973 );
974 #endif
975 pDPR++;
976 }
977
978 if (fTextLost)
979 {
980 /* Display error message in case test has been lost due to clipping of Y edge, or buffer overflow */
981 int i;
982 int NumChars=strlen(TextLostMessage);
983
984 for (i=0;i<NumChars;i++)
985 {
986 // BlitWin95Char(TEXT_LOST_X+(i*CharWidth),TEXT_LOST_Y,TextLostMessage[i]);
987 }
988
989 fTextLost=No;
990 }
991 }
992 DHM_NumCharsInQueue=0;
993
994 }
995 }
996
LastDisplayableXForChars(void)997 static int LastDisplayableXForChars(void)
998 {
999 return ScreenDescriptorBlock.SDB_Width-CharWidth;
1000 }
1001
LastDisplayableYForChars(void)1002 static int LastDisplayableYForChars(void)
1003 {
1004 return ScreenDescriptorBlock.SDB_Height-CharHeight;
1005 }
1006
1007
DHM_AddToQueue(int x,int y,char Ch)1008 static void DHM_AddToQueue(int x,int y, char Ch)
1009 {
1010
1011 if
1012 (
1013 (y>=0)
1014 &&
1015 (y<=LastDisplayableYForChars())
1016 )
1017 {
1018 if (DHM_NumCharsInQueue<DHM_PRINT_QUEUE_SIZE)
1019 {
1020 DAVEPRINTCHAR* pDPR=&DHM_PrintQueue[DHM_NumCharsInQueue++];
1021 /* We insert into the queue at this position, updating the length of the queue */
1022
1023 pDPR->x=x;
1024 pDPR->y=y;
1025 pDPR->CharToPrint=Ch;
1026 }
1027 else
1028 {
1029 /* Otherwise the queue if full, we will have to ignore this char; set an error flag so we get a message*/
1030 fTextLost=Yes;
1031 }
1032 }
1033 else
1034 {
1035 /* Otherwise the text is off the top or bottom of the screen; set an error flag to get a message up*/
1036 fTextLost=Yes;
1037 }
1038 }
1039
DHM_MoveBufferToQueue(int * pPosX,int * pPosY,int fZeroLeftMargin)1040 static int DHM_MoveBufferToQueue(int* pPosX,int* pPosY,int fZeroLeftMargin)
1041 {
1042 /*
1043 Function takes two integers by reference (using pointers), and outputs whatever is in
1044 the string buffer into the character queue, so that code can be shared by textprint() and textprintXY()
1045
1046 Returns "number of lines": any carriage returns or word wraps
1047 */
1048
1049 /* PRECONDITION */
1050 {
1051 LOWLEVELASSERT(pPosX);
1052 LOWLEVELASSERT(pPosY);
1053 }
1054
1055 /* CODE */
1056 {
1057 int NumLines=0;
1058
1059 int LeftMarginX;
1060
1061 if (fZeroLeftMargin)
1062 {
1063 LeftMarginX=0;
1064 }
1065 else
1066 {
1067 LeftMarginX=*pPosX;
1068 }
1069
1070
1071
1072 /* Iterate through the string in the buffer, adding the individual characters to the queue */
1073 {
1074 char* pCh=&TextprintBuffer[0];
1075 int SafetyCount=0;
1076
1077 while
1078 (
1079 ((*pCh)!='\0')
1080 &&
1081 ((SafetyCount++)<MaxMsgChars)
1082 )
1083 {
1084 switch (*pCh)
1085 {
1086 case '\n':
1087 {
1088 /* Wrap around to next line.,. */
1089 (*pPosY)+=HUD_FONT_HEIGHT;
1090 (*pPosX)=LeftMarginX;
1091 NumLines++;
1092
1093 }
1094 break;
1095 default:
1096 {
1097 /* It is a standard character or a space */
1098 DHM_AddToQueue(*pPosX,(*pPosY)+textprint_Y_offset, *pCh);
1099
1100 (*pPosX)+=AAFontWidths[(unsigned char)*pCh];//CharWidthInPixels(*pCh);
1101
1102 if ((*pPosX)>LastDisplayableXForChars())
1103 {
1104 /* Wrap around to next line.,. */
1105 (*pPosY)+=HUD_FONT_HEIGHT;
1106 (*pPosX)=LeftMarginX;
1107 NumLines++;
1108 }
1109 }
1110 }
1111
1112 /* ...and on to the next character*/
1113 pCh++;
1114 }
1115 }
1116
1117 /* Clear the string buffer */
1118 {
1119 TextprintBuffer[0]='\0';
1120 }
1121
1122 return NumLines;
1123 }
1124
1125 }
1126
1127
textprint(const char * t,...)1128 int textprint(const char* t, ...)
1129 {
1130 #if (debug && textprintOn)
1131 if
1132 (
1133 bEnableTextprint
1134 )
1135 {
1136 /*
1137 Get message string from arguments into buffer...
1138 */
1139 {
1140 va_list ap;
1141
1142 va_start(ap, t);
1143 vsprintf(&TextprintBuffer[0], t, ap);
1144 va_end(ap);
1145 }
1146
1147 /*
1148 Attempt to trap buffer overflows...
1149 */
1150 {
1151 LOWLEVELASSERT(strlen(TextprintBuffer)<TextprintBuffer);
1152 }
1153
1154 return DHM_MoveBufferToQueue(&textprintPosX,&textprintPosY,Yes);
1155
1156
1157 }
1158 else
1159 {
1160 // Run-time disabling of textprint()
1161 return 0;
1162 }
1163 #else
1164 /* Do nothing; hope the function call gets optimised away */
1165 return 0;
1166 #endif
1167 }
PrintDebuggingText(const char * t,...)1168 int PrintDebuggingText(const char* t, ...)
1169 {
1170 /*
1171 Get message string from arguments into buffer...
1172 */
1173 {
1174 va_list ap;
1175
1176 va_start(ap, t);
1177 vsprintf(&TextprintBuffer[0], t, ap);
1178 va_end(ap);
1179 }
1180
1181 /*
1182 Attempt to trap buffer overflows...
1183 */
1184 {
1185 LOWLEVELASSERT(strlen(TextprintBuffer)<TextprintBuffer);
1186 }
1187
1188 return DHM_MoveBufferToQueue(&textprintPosX,&textprintPosY,Yes);
1189 }
ReleasePrintDebuggingText(const char * t,...)1190 int ReleasePrintDebuggingText(const char* t, ...)
1191 {
1192 /*
1193 Get message string from arguments into buffer...
1194 */
1195 {
1196 va_list ap;
1197
1198 va_start(ap, t);
1199 vsprintf(&TextprintBuffer[0], t, ap);
1200 va_end(ap);
1201 }
1202
1203 /*
1204 Attempt to trap buffer overflows...
1205 */
1206 {
1207 LOWLEVELASSERT(strlen(TextprintBuffer)<TextprintBuffer);
1208 }
1209
1210 return DHM_MoveBufferToQueue(&textprintPosX,&textprintPosY,Yes);
1211 }
1212
1213
textprintXY(int x,int y,const char * t,...)1214 int textprintXY(int x, int y, const char* t, ...)
1215
1216 {
1217 #if (debug && textprintOn)
1218 if
1219 (
1220 bEnableTextprintXY
1221 )
1222 {
1223 /*
1224 Get message string from arguments into buffer...
1225 */
1226 {
1227 va_list ap;
1228
1229 va_start(ap, t);
1230 vsprintf(&TextprintBuffer[0], t, ap);
1231 va_end(ap);
1232 }
1233
1234 /*
1235 Attempt to trap buffer overflows...
1236 */
1237 {
1238 LOWLEVELASSERT(strlen(TextprintBuffer)<TextprintBuffer);
1239 }
1240
1241 {
1242 int localX=x;
1243 int localY=y;
1244
1245 return DHM_MoveBufferToQueue(&localX,&localY,No);
1246 }
1247
1248
1249 }
1250 else
1251 {
1252 // Run-time disabling of textprint()
1253 return 0;
1254 }
1255 #else
1256 {
1257 /* Do nothing; hope the function call gets optimised away */
1258
1259 return 0;
1260 }
1261 #endif
1262 }
1263
1264
1265
1266 /*
1267 *
1268 *
1269
1270 End of Dave Malcolm's text routines; old version is below
1271
1272 *
1273 *
1274 */
1275 #else
1276
1277 /*
1278 NOTE!!!! All this software is intended for debugging
1279 only. It emulates the print interface in any video
1280 mode supported by the engine, but there are limits -
1281 messages will pile up at the bottom of the screen
1282 and overwrite each other, all messages will appear at the
1283 fron in the main screen (NOT clipped to the VDB), messages
1284 will not wrap round if they are longer than a screen line
1285 unless \n is inserted in the print string, and the text colour
1286 is not guaranteed to be white in paletted modes.
1287 So there.
1288 */
1289
1290
1291 /*
1292 IMPORTANT!!!!
1293 Messages longer than MaxMsgChars are liable
1294 to CRASH this routine. I haven't bothered
1295 to do anything about this on the grounds that
1296 we can't tell how long the message is until after
1297 the vsprintf call, and the crash is likely to
1298 occur in vsprintf itself as it overflows the
1299 buffer.
1300 */
1301
1302 /*
1303 !!!!! FIXME??
1304 textprints don't seem to appear
1305 in SubWindow mode --- possibly
1306 because the colours in the font
1307 are going to system font colours which
1308 are invisible???
1309 */
1310
1311 #if (debug && textprintOn)
1312
textprint(const char * t,...)1313 int textprint(const char* t, ...)
1314
1315 {
1316 int i,j;
1317 va_list ap;
1318 char message[MaxMsgChars];
1319 char outmsg[MaxMsgChars];
1320 int numlines;
1321 int CharCount;
1322 int XPos=0;
1323
1324 va_start(ap, t);
1325
1326 vsprintf(&message[0], t, ap);
1327
1328 va_end(ap);
1329
1330 i = 0;
1331 j = 0;
1332 numlines = 0;
1333 CharCount = strlen(&message[0]);
1334
1335 /* Read through message buffer until we reach the terminator */
1336 while ((i < CharCount) && (message[i] != '\0'))
1337 {
1338 outmsg[j++] = message[i];
1339 XPos+=CharWidth;
1340 /* newline within string */
1341 if ((message[i] == '\n')||(XPos>ScreenDescriptorBlock.SDB_Width))
1342 {
1343 /* Display string and reset to start of next line */
1344 WriteStringToTextBuffer(textprintPosX, textprintPosY,
1345 &outmsg[0]);
1346 textprintPosX = 0;
1347 textprintPosY += HUD_FONT_HEIGHT;
1348 XPos=0;
1349 /* Messages can pile up at bottom of screen */
1350 if (textprintPosY > ScreenDescriptorBlock.SDB_Height)
1351 textprintPosY = ScreenDescriptorBlock.SDB_Height;
1352 /* Clear output string and reset variables */
1353 {
1354 int k;
1355 for (k=0; k<(j+1); k++)
1356 outmsg[k] = 0;
1357 }
1358 j = 0;
1359 /* Record number of lines output */
1360 numlines++;
1361 }
1362 i++;
1363 }
1364
1365 /* Flush any remaining characters */
1366 WriteStringToTextBuffer(textprintPosX, textprintPosY,
1367 &outmsg[0]);
1368 textprintPosX = 0;
1369 textprintPosY += HUD_FONT_HEIGHT;
1370 /* Messages can pile up at bottom of screen */
1371 if (textprintPosY > ScreenDescriptorBlock.SDB_Height)
1372 textprintPosY = ScreenDescriptorBlock.SDB_Height;
1373 numlines++;
1374
1375 return numlines;
1376 }
1377
1378 /*
1379 Textprint to defined location on screen
1380 (in screen coordinates for current video
1381 mode).
1382 NOTE!!! Newlines within strings sent to this
1383 function will be IGNORED.
1384 */
1385
textprintXY(int x,int y,const char * t,...)1386 int textprintXY(int x, int y, const char* t, ...)
1387
1388 {
1389 va_list ap;
1390 char message[MaxMsgChars];
1391
1392 va_start(ap, t);
1393
1394 vsprintf(&message[0], t, ap);
1395
1396 va_end(ap);
1397
1398 WriteStringToTextBuffer(x, y, &message[0]);
1399
1400 return 1; /* for one line */
1401 }
1402
1403 #else
1404
textprint(const char * t,...)1405 int textprint(const char* t, ...)
1406
1407 {
1408 return 0;
1409 }
1410
textprintXY(int x,int y,const char * t,...)1411 int textprintXY(int x, int y, const char* t, ...)
1412
1413 {
1414 return 0;
1415 }
1416
1417 #endif
1418
1419
1420 /*
1421 Add string to text buffer
1422 */
1423
WriteStringToTextBuffer(int x,int y,unsigned char * buffer)1424 void WriteStringToTextBuffer(int x, int y, unsigned char *buffer)
1425
1426 {
1427 if (MessagesStoredThisFrame < MaxMessages)
1428 {
1429 strcpy(PrintQueue[MessagesStoredThisFrame].text, buffer);
1430
1431 PrintQueue[MessagesStoredThisFrame].text_length = strlen(buffer);
1432 PrintQueue[MessagesStoredThisFrame].x = x;
1433 PrintQueue[MessagesStoredThisFrame].y = y;
1434
1435 MessagesStoredThisFrame++;
1436 }
1437 }
1438
1439
1440 /*
1441 Display string of chracters, starting at passed pointer,
1442 at location on screen starting with x and y.
1443
1444 Patched by Dave Malcolm 20/11/96 so that text wraps around when it reaches the right hand edge of the screen, in
1445 this routine, at least...
1446 */
1447
1448
DisplayWin95String(int x,int y,unsigned char * buffer)1449 void DisplayWin95String(int x, int y, unsigned char *buffer)
1450
1451 {
1452 int InitialX=x;
1453 int stlen;
1454 unsigned char ch;
1455
1456 stlen = strlen(buffer);
1457
1458 do
1459 {
1460 ch = (unsigned char) *buffer;
1461 BlitWin95Char(x, y, ch);
1462 x += CharWidth;
1463 if (x > (ScreenDescriptorBlock.SDB_Width
1464 - CharWidth))
1465 {
1466 #if 1
1467 /* Wrap to new line, based on coordinates for display...*/
1468 x=InitialX;
1469 y+=HUD_FONT_HEIGHT;
1470 #else
1471 /* Characters will pile up at screen edge */
1472 x = (ScreenDescriptorBlock.SDB_Width - CharWidth);
1473 #endif
1474 }
1475
1476 buffer++;
1477 stlen--;
1478 }
1479 while ((ch != '\n') && (ch != '\0') &&
1480 (stlen > 0));
1481 }
1482
1483 /*
1484 Write all messages in buffer to screen
1485 (to be called at end of frame, after surface
1486 / execute buffer unlock in DrawItemListContents,
1487 so that text appears at the front of the back
1488 buffer immediately before the flip).
1489 */
1490
FlushTextprintBuffer(void)1491 void FlushTextprintBuffer(void)
1492
1493 {
1494 int i;
1495
1496 for (i=0; i<MessagesStoredThisFrame; i++)
1497 {
1498 if (PrintQueue[i].text_length)
1499 DisplayWin95String(PrintQueue[i].x,
1500 PrintQueue[i].y, PrintQueue[i].text);
1501
1502 /*
1503 More mystery code from Roxby --- an extra safety
1504 check for printing?? Or a hangover from a linked
1505 list version of the data structure???
1506 */
1507 PrintQueue[i].text_length = 0;
1508 }
1509
1510 MessagesStoredThisFrame = 0;
1511 }
1512
1513 /* Initialise print queue */
1514
InitPrintQueue(void)1515 void InitPrintQueue(void)
1516
1517 {
1518 int i;
1519
1520 /* Mystery code from Roxby here... */
1521 for (i=0; i < MaxMessages; i++)
1522 PrintQueue[i].text_length = 0;
1523
1524 MessagesStoredThisFrame = 0;
1525 }
1526
1527 #endif
1528 /*end of old version of text routines */
1529
1530 /*
1531 Load main, 8 bit paletted, font
1532 (assumed to be on hard drive at present)
1533 and create hi and true colour mode fonts
1534 from it. Note that for this system to work
1535 properly all bits on must be white or similar
1536 in 8 bit mode 222 and Raw256 palettes as well
1537 as mode 8T.
1538 */
1539
1540 /*
1541 MUST be called after GenerateDirectDrawSurface,
1542 i.e. AFTER SetVideoMode.
1543 AND ONLY ONCE!!!!
1544 */
1545
1546
1547
1548 /*
1549 This function is intended to allow YOU,
1550 the user, to obtain your heart's fondest desires
1551 by one simple call. Money? Love? A better job?
1552 It's all here, you have only to ask...
1553 No, I was lying actually.
1554 In fact, this should allow you to change
1555 display modes cleanly. Pass your request modes
1556 (as normally set up in system.c). For all entries
1557 which you do not want to change, simply pass
1558 the current global value (e.g. ZBufferRequestMode
1559 in the NewZBufferMode entry).
1560
1561 Note that the function must always be passed the
1562 HINSTANCE and nCmdShow from winmain.
1563 */
1564
1565 /*
1566 Note that this function will NOT
1567 reinitialise the DirectDraw object
1568 or switch to or from a hardware DD
1569 device, but it will release and rebuild
1570 all the Direct3D objects.
1571 */
1572
1573 /*
1574 Note that you MUST be in the right
1575 directory for a texture reload before you
1576 call this, and normal operations CAN change
1577 the directory...
1578 */
1579
1580 /*
1581 NOTE!!! If you start in DirectDraw mode
1582 and go to Direct3D mode, this function
1583 CANNOT POSSIBLY WORK WITHOUT A FULL SHAPE
1584 RELOAD, since the shape data is overwritten
1585 during DirectDraw initialisation!!!!
1586
1587 NOTE ALSO: TEXTURE RELOAD MAY BE DODGY
1588 WITHOUT A SHAPE RELOAD!!!
1589 */
1590
ChangeDisplayModes(HINSTANCE hInst,int nCmd,int NewVideoMode,int NewWindowMode,int NewZBufferMode,int NewRasterisationMode,int NewSoftwareScanDrawMode,int NewDXMemoryMode)1591 int ChangeDisplayModes(HINSTANCE hInst, int nCmd,
1592 int NewVideoMode, int NewWindowMode,
1593 int NewZBufferMode, int NewRasterisationMode,
1594 int NewSoftwareScanDrawMode, int NewDXMemoryMode)
1595 {
1596 BOOL rc;
1597 BOOL ChangeWindow = No;
1598
1599 /*
1600 Shut down DirectX objects and destroy
1601 the current window, if necessary.
1602 */
1603
1604 if (NewWindowMode != WindowMode)
1605 ChangeWindow = Yes;
1606
1607 DeallocateAllImages();
1608
1609 ReleaseDirect3DNotDD();
1610
1611 finiObjectsExceptDD();
1612
1613
1614 if (ChangeWindow)
1615 ExitWindowsSystem();
1616
1617 /* Test!! */
1618
1619 /*
1620 Set the request modes and actual modes
1621 according to the passed values.
1622 */
1623
1624 VideoRequestMode = NewVideoMode;
1625 WindowRequestMode = NewWindowMode;
1626 ZBufferRequestMode = NewZBufferMode;
1627 RasterisationRequestMode = NewRasterisationMode;
1628 SoftwareScanDrawRequestMode = NewSoftwareScanDrawMode;
1629 DXMemoryRequestMode = NewDXMemoryMode;
1630
1631 VideoMode = VideoRequestMode;
1632 WindowMode = WindowRequestMode;
1633
1634 /* this may reconstruct the dd object depending
1635 on the rasterisation request mode and whether
1636 a hardware dd driver is selected or could be
1637 available */
1638 ChangeDirectDrawObject();
1639
1640 /*
1641 Check that our new video mode exists,
1642 and pick a valid option if it doesn't and
1643 we can find one.
1644 */
1645
1646 #if CheckVideoModes
1647 if (WindowMode == WindowModeFullScreen)
1648 {
1649 if (!(CheckForVideoModes(VideoMode)))
1650 {
1651 VideoMode = VideoMode_DX_640x480x8;
1652 if (!(CheckForVideoModes(VideoMode)))
1653 {
1654 VideoMode = VideoMode_DX_640x480x15;
1655 if (!(CheckForVideoModes(VideoMode)))
1656 {
1657 ReleaseDirect3D(); // for safety
1658 return FALSE;
1659 }
1660 }
1661 }
1662 }
1663 #endif
1664
1665 /*
1666 Recreate the window, allowing
1667 for possible change in WindowMode.
1668 */
1669
1670 if (ChangeWindow)
1671 {
1672 rc = InitialiseWindowsSystem(hInst, nCmd,
1673 WinInitChange);
1674
1675 if (rc == FALSE)
1676 return rc;
1677 }
1678
1679 /*
1680 Set the video mode again. This
1681 will handle all changes to DirectDraw
1682 objects, all Direct3D initialisation,
1683 and other request modes such as
1684 zbuffering.
1685 */
1686
1687 /*
1688 Err... shutting down and restarting
1689 on a hardware driver appears to
1690 screw up file handling somehow...
1691 umm... but not for Microsoft demos,
1692 obviously...
1693 FIXME!!!
1694 */
1695
1696 /*
1697 SetVideoMode[VideoMode]();
1698 */
1699
1700 /*
1701 Lose all the textures and reload the
1702 debugging font
1703 */
1704
1705 InitialiseTextures();
1706
1707
1708 /*
1709 Well, we HOPE it's okay...
1710 */
1711
1712 return TRUE;
1713 }
1714
1715
1716 /*
1717 Reverse of ConvertToDDPalette, introduced
1718 to maintain internal interfaces only...
1719 */
1720
ConvertDDToInternalPalette(unsigned char * src,unsigned char * dst,int length)1721 void ConvertDDToInternalPalette(unsigned char* src, unsigned char* dst, int length)
1722 {
1723 int i;
1724
1725 /*
1726 Copy palette, shifting down
1727 to 5 bit triple
1728 */
1729
1730 for (i=0; i<length; i++)
1731 {
1732 *dst++ = (*src++) >> 2;
1733 *dst++ = (*src++) >> 2;
1734 *dst++ = (*src++) >> 2;
1735 }
1736 }
1737