]> icculus.org git repositories - btb/d2x.git/blob - main/kconfig.c
more header fixes
[btb/d2x.git] / main / kconfig.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Routines to configure keyboard, joystick, etc..
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 #ifdef WINDOWS
25 #include "desw.h"
26 #endif
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <ctype.h>
33
34 #include "error.h"
35 #include "gr.h"
36 #include "vid.h"
37 #include "mono.h"
38 #include "key.h"
39 #include "palette.h"
40 #include "inferno.h"
41 #include "iff.h"
42 #include "u_mem.h"
43 #include "joy.h"
44 #include "mouse.h"
45 #include "timer.h"
46 #include "args.h"
47
48 #if defined (TACTILE)
49  #include "tactile.h"
50 #endif
51
52 #ifdef USE_LINUX_JOY
53 #include "joystick.h"
54 #endif
55
56
57 ubyte ExtGameStatus=1;
58
59 vms_vector ExtForceVec;
60 vms_matrix ExtApplyForceMatrix;
61
62 int ExtJoltInfo[3]={0,0,0};
63 int ExtXVibrateInfo[2]={0,0};
64 int ExtYVibrateInfo[2]={0,0};
65 ubyte ExtXVibrateClear=0;
66 ubyte ExtYVibrateClear=0;
67
68 #define TABLE_CREATION 1
69
70 // Array used to 'blink' the cursor while waiting for a keypress.
71 sbyte fades[64] = { 1,1,1,2,2,3,4,4,5,6,8,9,10,12,13,15,16,17,19,20,22,23,24,26,27,28,28,29,30,30,31,31,31,31,31,30,30,29,28,28,27,26,24,23,22,20,19,17,16,15,13,12,10,9,8,6,5,4,4,3,2,2,1,1 };
72
73 //char * invert_text[2] = { "N", "Y" };
74 //char * joyaxis_text[4] = { "X1", "Y1", "X2", "Y2" };
75 //char * mouseaxis_text[2] = { "L/R", "F/B" };
76
77 int invert_text[2] = { TNUM_N, TNUM_Y };
78
79 #ifndef USE_LINUX_JOY
80 #if defined(SDL_INPUT)
81 char *joyaxis_text[JOY_MAX_AXES];
82 #else
83         int joyaxis_text[7] = { TNUM_X1, TNUM_Y1, TNUM_Z1, TNUM_UN, TNUM_P1,TNUM_R1,TNUM_YA1 };
84 //      int joyaxis_text[4] = { TNUM_X1, TNUM_Y1, TNUM_X2, TNUM_Y2 };
85 #endif
86 #endif
87
88 int mouseaxis_text[3] = { TNUM_L_R, TNUM_F_B, TNUM_Z1 };
89
90 #if !defined OGL && !defined SDL_INPUT
91 char * key_text[256] = {         \
92 "","ESC","1","2","3","4","5","6","7","8","9","0","-",                   \
93 "=","BSPC","TAB","Q","W","E","R","T","Y","U","I","O",                           \
94 "P","[","]","\x83","LCTRL","A","S","D","F",        \
95 "G","H","J","K","L",";","'","`",        \
96 "LSHFT","\\","Z","X","C","V","B","N","M",",",      \
97 ".","/","RSHFT","PAD*","LALT","SPC",      \
98 "CPSLK","F1","F2","F3","F4","F5","F6","F7","F8","F9",        \
99 "F10","NMLCK","SCLK","PAD7","PAD8","PAD9","PAD-",   \
100 "PAD4","PAD5","PAD6","PAD+","PAD1","PAD2","PAD3","PAD0", \
101 "PAD.","","","","F11","F12","","","","","","","","","",         \
102 "","","","","","","","","","","","","","","","","","","","",     \
103 "","","","","","","","","","","","","","","","","","","","",     \
104 "","","","","","","","","","","","","","","","","","",           \
105 "PAD\x83","RCTRL","","","","","","","","","","","","","", \
106 "","","","","","","","","","","PAD/","","","RALT","",      \
107 "","","","","","","","","","","","","","HOME","\x82","PGUP",     \
108 "","\x81","","\x7f","","END","\x80","PGDN","INS",       \
109 "DEL","","","","","","","","","","","","","","","","","",     \
110 "","","","","","","","","","","","","","","","","","","","",     \
111 "","","","","","","" };
112 #endif /* OGL */
113
114 ubyte system_keys[] = { KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_PRINT_SCREEN };
115
116 //extern void GameLoop(int, int );
117
118 // macros for drawing lo/hi res kconfig screens (see scores.c as well)
119
120 #define LHX(x)          ((x)*(MenuHires?2:1))
121 #define LHY(y)          ((y)*(MenuHires?2.4:1))
122
123
124 #define BT_KEY                          0
125 //#define BT_MOUSE_BUTTON       1
126 #define BT_MOUSE_AXIS           2
127 //#define BT_JOY_BUTTON                 3
128 #define BT_JOY_AXIS                     4
129 #define BT_INVERT                               5
130
131 char *btype_text[] = { "BT_KEY", "BT_MOUSE_BUTTON", "BT_MOUSE_AXIS", "BT_JOY_BUTTON", "BT_JOY_AXIS", "BT_INVERT" };
132
133 #define INFO_Y 28
134
135 typedef struct kc_item {
136         short id;                               // The id of this item
137         short x, y;                             
138         short w1;
139         short w2;
140         short u,d,l,r;
141         //short text_num1;
142         char *text;
143         ubyte type;
144         ubyte value;            // what key,button,etc
145 } kc_item;
146
147 int Num_items=28;
148 kc_item *All_items;
149
150
151 #define NUM_KEY_CONTROLS    57
152 #define NUM_OTHER_CONTROLS  24
153 #define NUM_D2X_CONTROLS    24
154
155 //----------- WARNING!!!!!!! -------------------------------------------
156 // THESE NEXT FOUR BLOCKS OF DATA ARE GENERATED BY PRESSING DEL+F12 WHEN
157 // IN THE KEYBOARD CONFIG SCREEN.  BASICALLY, THAT PROCEDURE MODIFIES THE
158 // U,D,L,R FIELDS OF THE ARRAYS AND DUMPS THE NEW ARRAYS INTO KCONFIG.COD
159 //-------------------------------------------------------------------------
160
161 kc_item kc_keyboard[NUM_KEY_CONTROLS] = {
162         {  0, 15, 49, 71, 26, 55,  2, 56,  1,"Pitch forward", BT_KEY, 255 },
163         {  1, 15, 49,100, 26, 50,  3,  0, 24,"Pitch forward", BT_KEY, 255 },
164         {  2, 15, 57, 71, 26,  0,  4, 25,  3,"Pitch backward", BT_KEY, 255 },
165         {  3, 15, 57,100, 26,  1,  5,  2, 26,"Pitch backward", BT_KEY, 255 },
166         {  4, 15, 65, 71, 26,  2,  6, 27,  5,"Turn left", BT_KEY, 255 },
167         {  5, 15, 65,100, 26,  3,  7,  4, 28,"Turn left", BT_KEY, 255 },
168         {  6, 15, 73, 71, 26,  4,  8, 29,  7,"Turn right", BT_KEY, 255 },
169         {  7, 15, 73,100, 26,  5,  9,  6, 34,"Turn right", BT_KEY, 255 },
170         {  8, 15, 85, 71, 26,  6, 10, 35,  9,"Slide on", BT_KEY, 255 },
171         {  9, 15, 85,100, 26,  7, 11,  8, 36,"Slide on", BT_KEY, 255 },
172         { 10, 15, 93, 71, 26,  8, 12, 37, 11,"Slide left", BT_KEY, 255 },
173         { 11, 15, 93,100, 26,  9, 13, 10, 44,"Slide left", BT_KEY, 255 },
174         { 12, 15,101, 71, 26, 10, 14, 45, 13,"Slide right", BT_KEY, 255 },
175         { 13, 15,101,100, 26, 11, 15, 12, 30,"Slide right", BT_KEY, 255 },
176         { 14, 15,109, 71, 26, 12, 16, 31, 15,"Slide up", BT_KEY, 255 },
177         { 15, 15,109,100, 26, 13, 17, 14, 32,"Slide up", BT_KEY, 255 },
178         { 16, 15,117, 71, 26, 14, 18, 33, 17,"Slide down", BT_KEY, 255 },
179         { 17, 15,117,100, 26, 15, 19, 16, 46,"Slide down", BT_KEY, 255 },
180         { 18, 15,129, 71, 26, 16, 20, 47, 19,"Bank on", BT_KEY, 255 },
181         { 19, 15,129,100, 26, 17, 21, 18, 38,"Bank on", BT_KEY, 255 },
182         { 20, 15,137, 71, 26, 18, 22, 39, 21,"Bank left", BT_KEY, 255 },
183         { 21, 15,137,100, 26, 19, 23, 20, 40,"Bank left", BT_KEY, 255 },
184         { 22, 15,145, 71, 26, 20, 48, 41, 23,"Bank right", BT_KEY, 255 },
185         { 23, 15,145,100, 26, 21, 49, 22, 42,"Bank right", BT_KEY, 255 },
186         { 24,158, 49, 83, 26, 51, 26,  1, 25,"Fire primary", BT_KEY, 255 },
187         { 25,158, 49,112, 26, 56, 27, 24,  2,"Fire primary", BT_KEY, 255 },
188         { 26,158, 57, 83, 26, 24, 28,  3, 27,"Fire secondary", BT_KEY, 255 },
189         { 27,158, 57,112, 26, 25, 29, 26,  4,"Fire secondary", BT_KEY, 255 },
190         { 28,158, 65, 83, 26, 26, 34,  5, 29,"Fire flare", BT_KEY, 255 },
191         { 29,158, 65,112, 26, 27, 35, 28,  6,"Fire flare", BT_KEY, 255 },
192         { 30,158,105, 83, 26, 44, 32, 13, 31,"Accelerate", BT_KEY, 255 },
193         { 31,158,105,112, 26, 45, 33, 30, 14,"Accelerate", BT_KEY, 255 },
194         { 32,158,113, 83, 26, 30, 46, 15, 33,"reverse", BT_KEY, 255 },
195         { 33,158,113,112, 26, 31, 47, 32, 16,"reverse", BT_KEY, 255 },
196         { 34,158, 73, 83, 26, 28, 36,  7, 35,"Drop Bomb", BT_KEY, 255 },
197         { 35,158, 73,112, 26, 29, 37, 34,  8,"Drop Bomb", BT_KEY, 255 },
198         { 36,158, 85, 83, 26, 34, 44,  9, 37,"REAR VIEW", BT_KEY, 255 },
199         { 37,158, 85,112, 26, 35, 45, 36, 10,"REAR VIEW", BT_KEY, 255 },
200         { 38,158,133, 83, 26, 46, 40, 19, 39,"Cruise Faster", BT_KEY, 255 },
201         { 39,158,133,112, 26, 47, 41, 38, 20,"Cruise Faster", BT_KEY, 255 },
202         { 40,158,141, 83, 26, 38, 42, 21, 41,"Cruise Slower", BT_KEY, 255 },
203         { 41,158,141,112, 26, 39, 43, 40, 22,"Cruise Slower", BT_KEY, 255 },
204         { 42,158,149, 83, 26, 40, 52, 23, 43,"Cruise Off", BT_KEY, 255 },
205         { 43,158,149,112, 26, 41, 53, 42, 48,"Cruise Off", BT_KEY, 255 },
206         { 44,158, 93, 83, 26, 36, 30, 11, 45,"Automap", BT_KEY, 255 },
207         { 45,158, 93,112, 26, 37, 31, 44, 12,"Automap", BT_KEY, 255 },
208         { 46,158,121, 83, 26, 32, 38, 17, 47,"Afterburner", BT_KEY, 255 },
209         { 47,158,121,112, 26, 33, 39, 46, 18,"Afterburner", BT_KEY, 255 },
210         { 48, 15,161, 71, 26, 22, 50, 43, 49,"Cycle Primary", BT_KEY, 255 },
211         { 49, 15,161,100, 26, 23, 51, 48, 52,"Cycle Primary", BT_KEY, 255 },
212         { 50, 15,169, 71, 26, 48,  1, 53, 51,"Cycle Second", BT_KEY, 255 },
213         { 51, 15,169,100, 26, 49, 24, 50, 54,"Cycle Second", BT_KEY, 255 },
214         { 52,158,163, 83, 26, 42, 54, 49, 53,"Headlight", BT_KEY, 255 },
215         { 53,158,163,112, 26, 43, 55, 52, 50,"Headlight", BT_KEY, 255 },
216         { 54,158,171, 83, 26, 52, 56, 51, 55,"Energy->Shield", BT_KEY, 255 },
217         { 55,158,171,112, 26, 53,  0, 54, 56,"Energy->Shield", BT_KEY, 255 },
218         { 56,158,179, 83, 26, 54, 25, 55,  0,"Toggle Bomb", BT_KEY, 255 },
219 };
220
221 char *kc_key_bind_text[NUM_KEY_CONTROLS] = {
222         "+lookdown",    "+lookdown",
223         "+lookup",      "+lookup",
224         "+left",        "+left",
225         "+right",       "+right",
226         "+strafe",      "+strafe",
227         "+moveleft",    "+moveleft",
228         "+moveright",   "+moveright",
229         "+moveup",      "+moveup",
230         "+movedown",    "+movedown",
231         "+bank",        "+bank",
232         "+bankleft",    "+bankleft",
233         "+bankright",   "+bankright",
234         "+attack",      "+attack",
235         "+attack2",     "+attack2",
236         "flare",        "flare",
237         "+forward",     "+forward",
238         "+back",        "+back",
239         "bomb",         "bomb",
240         "+rearview",    "+rearview",
241         "+cruiseup",    "+cruiseup",
242         "+cruisedown",  "+cruisedown",
243         "+cruiseoff",   "+cruiseoff",
244         "+automap",     "+automap",
245         "+afterburner", "+afterburner",
246         "cycle",        "cycle",
247         "cycle2",       "cycle2",
248         "headlight",    "headlight",
249         "+nrgshield",   "+nrgshield",
250         "togglebomb",
251 };
252
253 ubyte default_kc_keyboard_settings[NUM_KEY_CONTROLS] = {0x48,0xc8,0x50,0xd0,0x4b,0xcb,0x4d,0xcd,0x38,0xff,0x4f,0xff,0x51,0xff,0x4a,0xff,0x4e,0xff,0x2a,0xff,0x10,0x47,0x12,0x49,0x1d,0x80,0x39,0x81,0x21,0x24,0x1e,0xff,0x2c,0xff,0x30,0xff,0x13,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf,0xff,0x1f,0xff,0x33,0xff,0x34,0xff,0x23,0xff,0x14,0xff,0xff};
254
255 kc_item kc_other[NUM_OTHER_CONTROLS] = {
256         {  0, 22,138, 51, 40, 23,  2, 23,  1,"Pitch U/D", BT_JOY_AXIS, 255 },
257         {  1, 22,138, 99,  8, 10,  3,  0, 12,"Pitch U/D", BT_INVERT, 255 },
258         {  2, 22,146, 51, 40,  0,  4, 13,  3,"Turn L/R", BT_JOY_AXIS, 255 },
259         {  3, 22,146, 99,  8,  1,  5,  2, 14,"Turn L/R", BT_INVERT, 255 },
260         {  4, 22,154, 51, 40,  2,  6, 15,  5,"Slide L/R", BT_JOY_AXIS, 255 },
261         {  5, 22,154, 99,  8,  3,  7,  4, 16,"Slide L/R", BT_INVERT, 255 },
262         {  6, 22,162, 51, 40,  4,  8, 17,  7,"Slide U/D", BT_JOY_AXIS, 255 },
263         {  7, 22,162, 99,  8,  5,  9,  6, 18,"Slide U/D", BT_INVERT, 255 },
264         {  8, 22,170, 51, 40,  6, 10, 19,  9,"Bank L/R", BT_JOY_AXIS, 255 },
265         {  9, 22,170, 99,  8,  7, 11,  8, 20,"Bank L/R", BT_INVERT, 255 },
266         { 10, 22,182, 51, 40,  8,  1, 21, 11,"throttle", BT_JOY_AXIS, 255 },
267         { 11, 22,182, 99,  8,  9, 12, 10, 22,"throttle", BT_INVERT, 255 },
268         { 12,182,138, 51, 40, 11, 14,  1, 13,"Pitch U/D", BT_MOUSE_AXIS, 255 },
269         { 13,182,138, 99,  8, 22, 15, 12,  2,"Pitch U/D", BT_INVERT, 255 },
270         { 14,182,146, 51, 40, 12, 16,  3, 15,"Turn L/R", BT_MOUSE_AXIS, 255 },
271         { 15,182,146, 99,  8, 13, 17, 14,  4,"Turn L/R", BT_INVERT, 255 },
272         { 16,182,154, 51, 40, 14, 18,  5, 17,"Slide L/R", BT_MOUSE_AXIS, 255 },
273         { 17,182,154, 99,  8, 15, 19, 16,  6,"Slide L/R", BT_INVERT, 255 },
274         { 18,182,162, 51, 40, 16, 20,  7, 19,"Slide U/D", BT_MOUSE_AXIS, 255 },
275         { 19,182,162, 99,  8, 17, 21, 18,  8,"Slide U/D", BT_INVERT, 255 },
276         { 20,182,170, 51, 40, 18, 22,  9, 21,"Bank L/R", BT_MOUSE_AXIS, 255 },
277         { 21,182,170, 99,  8, 19, 23, 20, 10,"Bank L/R", BT_INVERT, 255 },
278         { 22,182,182, 51, 40, 20, 13, 11, 23,"throttle", BT_MOUSE_AXIS, 255 },
279         { 23,182,182, 99,  8, 21,  0, 22,  0,"throttle", BT_INVERT, 255 },
280 };
281
282 kc_axis_map kc_other_axismap[NUM_OTHER_CONTROLS] = {
283         AXIS_PITCH,     AXIS_NONE,
284         AXIS_TURN,      AXIS_NONE,
285         AXIS_LEFTRIGHT, AXIS_NONE,
286         AXIS_UPDOWN,    AXIS_NONE,
287         AXIS_BANK,      AXIS_NONE,
288         AXIS_THROTTLE,  AXIS_NONE,
289         AXIS_PITCH,     AXIS_NONE,
290         AXIS_TURN,      AXIS_NONE,
291         AXIS_LEFTRIGHT, AXIS_NONE,
292         AXIS_UPDOWN,    AXIS_NONE,
293         AXIS_BANK,      AXIS_NONE,
294         AXIS_THROTTLE,  AXIS_NONE,
295 };
296
297 ubyte default_kc_other_settings[NUM_OTHER_CONTROLS] = {0x1,0x0,0x0,0x0,0xff,0x0,0xff,0x0,0xff,0x0,0xff,0x0,0x1,0x0,0x0,0x0,0xff,0x0,0xff,0x0,0xff,0x0,0x2,0x0};
298
299 kc_item kc_d2x[NUM_D2X_CONTROLS] = {
300 //        id,x,y,w1,w2,u,d,l,r,text_num1,type,value
301         {  0, 15, 49, 71, 26, 23,  2, 23,  1,"WEAPON 1", BT_KEY, 255 },
302         {  1, 15, 49,100, 26, 22,  3,  0,  2,"WEAPON 1", BT_KEY, 255 },
303         {  2, 15, 57, 71, 26,  0,  4,  1,  3,"WEAPON 2", BT_KEY, 255 },
304         {  3, 15, 57,100, 26,  1,  5,  2,  4,"WEAPON 2", BT_KEY, 255 },
305         {  4, 15, 65, 71, 26,  2,  6,  3,  5,"WEAPON 3", BT_KEY, 255 },
306         {  5, 15, 65,100, 26,  3,  7,  4,  6,"WEAPON 3", BT_KEY, 255 },
307         {  6, 15, 73, 71, 26,  4,  8,  5,  7,"WEAPON 4", BT_KEY, 255 },
308         {  7, 15, 73,100, 26,  5,  9,  6,  8,"WEAPON 4", BT_KEY, 255 },
309         {  8, 15, 81, 71, 26,  6, 10,  7,  9,"WEAPON 5", BT_KEY, 255 },
310         {  9, 15, 81,100, 26,  7, 11,  8, 10,"WEAPON 5", BT_KEY, 255 },
311         { 10, 15, 89, 71, 26,  8, 12,  9, 11,"WEAPON 6", BT_KEY, 255 },
312         { 11, 15, 89,100, 26,  9, 13, 10, 12,"WEAPON 6", BT_KEY, 255 },
313         { 12, 15, 97, 71, 26, 10, 14, 11, 13,"WEAPON 7", BT_KEY, 255 },
314         { 13, 15, 97,100, 26, 11, 15, 12, 14,"WEAPON 7", BT_KEY, 255 },
315         { 14, 15,105, 71, 26, 12, 16, 13, 15,"WEAPON 8", BT_KEY, 255 },
316         { 15, 15,105,100, 26, 13, 17, 14, 16,"WEAPON 8", BT_KEY, 255 },
317         { 16, 15,113, 71, 26, 14, 18, 15, 17,"WEAPON 9", BT_KEY, 255 },
318         { 17, 15,113,100, 26, 15, 19, 16, 18,"WEAPON 9", BT_KEY, 255 },
319         { 18, 15,121, 71, 26, 16, 20, 17, 19,"WEAPON 0", BT_KEY, 255 },
320         { 19, 15,121,100, 26, 17, 21, 18, 20,"WEAPON 0", BT_KEY, 255 },
321         { 20, 15,131, 71, 26, 18, 22, 19, 21,"sizedown", BT_KEY, 255 },
322         { 21, 15,131,100, 26, 19, 23, 20, 22,"sizedown", BT_KEY, 255 },
323         { 22, 15,139, 71, 26, 20,  1, 21, 23,"sizeup", BT_KEY, 255 },
324         { 23, 15,139,100, 26, 21,  0, 22,  0,"sizeup", BT_KEY, 255 },
325         //{ 24,  8,147, 78, 26, 22, 26, 23, 25, "TOGGLE_PRIM AUTO", BT_KEY, 255},
326         //{ 25,  8,147,107, 26, 23, 27, 24, 26, "TOGGLE_PRIM_AUTO", BT_KEY, 255},
327         //{ 26,  8,155, 78, 26, 24,  1, 25, 27, "TOGGLE SEC AUTO", BT_KEY, 255},
328         //{ 27,  8,155,107, 26, 25,  0, 26,  0, "TOGGLE SEC AUTO", BT_KEY, 255},
329 };
330
331 ubyte default_kc_d2x_settings[NUM_D2X_CONTROLS] = {0x2,0xff,0x3,0xff,0x4,0xff,0x5,0xff,0x6,0xff,0x7,0xff,0x8,0xff,0x9,0xff,0xa,0xff,0xb,0xff,0xc,0xff,0xd,0xff};
332
333
334 void kc_drawitem( kc_item *item, int is_current );
335 void kc_change_key( kc_item * item );
336 void kc_next_joyaxis(kc_item *item);  //added by WraithX on 11/22/00
337 void kc_change_joyaxis( kc_item * item );
338 void kc_change_mouseaxis( kc_item * item );
339 void kc_change_invert( kc_item * item );
340
341 int kconfig_is_axes_used(int axis)
342 {
343         int i;
344         for (i=0; i<NUM_OTHER_CONTROLS; i++ )   {
345                 if (( kc_other[i].type == BT_JOY_AXIS ) && (kc_other[i].value == axis ))
346                         return 1;
347         }
348         return 0;
349 }
350
351 #ifdef TABLE_CREATION
352 int find_item_at( kc_item * items, int nitems, int x, int y )
353 {
354         int i;
355         
356         for (i=0; i<nitems; i++ )       {
357                 if ( ((items[i].x+items[i].w1)==x) && (items[i].y==y))
358                         return i;
359         }
360         return -1;
361 }
362
363 int find_next_item_up( kc_item * items, int nitems, int citem )
364 {
365         int x, y, i;
366
367         y = items[citem].y;
368         x = items[citem].x+items[citem].w1;
369         
370         do {    
371                 y--;
372                 if ( y < 0 ) {
373                         y = grd_curcanv->cv_bitmap.bm_h-1;
374                         x--;
375                         if ( x < 0 ) {
376                                 x = grd_curcanv->cv_bitmap.bm_w-1;
377                         }
378                 }
379                 i = find_item_at( items, nitems, x, y );
380         } while ( i < 0 );
381         
382         return i;
383 }
384
385 int find_next_item_down( kc_item * items, int nitems, int citem )
386 {
387         int x, y, i;
388
389         y = items[citem].y;
390         x = items[citem].x+items[citem].w1;
391         
392         do {    
393                 y++;
394                 if ( y > grd_curcanv->cv_bitmap.bm_h-1 ) {
395                         y = 0;
396                         x++;
397                         if ( x > grd_curcanv->cv_bitmap.bm_w-1 ) {
398                                 x = 0;
399                         }
400                 }
401                 i = find_item_at( items, nitems, x, y );
402         } while ( i < 0 );
403         
404         return i;
405 }
406
407 int find_next_item_right( kc_item * items, int nitems, int citem )
408 {
409         int x, y, i;
410
411         y = items[citem].y;
412         x = items[citem].x+items[citem].w1;
413         
414         do {    
415                 x++;
416                 if ( x > grd_curcanv->cv_bitmap.bm_w-1 ) {
417                         x = 0;
418                         y++;
419                         if ( y > grd_curcanv->cv_bitmap.bm_h-1 ) {
420                                 y = 0;
421                         }
422                 }
423                 i = find_item_at( items, nitems, x, y );
424         } while ( i < 0 );
425         
426         return i;
427 }
428
429 int find_next_item_left( kc_item * items, int nitems, int citem )
430 {
431         int x, y, i;
432
433         y = items[citem].y;
434         x = items[citem].x+items[citem].w1;
435         
436         do {    
437                 x--;
438                 if ( x < 0 ) {
439                         x = grd_curcanv->cv_bitmap.bm_w-1;
440                         y--;
441                         if ( y < 0 ) {
442                                 y = grd_curcanv->cv_bitmap.bm_h-1;
443                         }
444                 }
445                 i = find_item_at( items, nitems, x, y );
446         } while ( i < 0 );
447         
448         return i;
449 }
450 #endif
451
452 #ifdef NEWMENU_MOUSE
453 int get_item_height(kc_item *item)
454 {
455         int w, h, aw;
456         char btext[10];
457
458         if (item->value==255) {
459                 strcpy(btext, "");
460         } else {
461                 switch( item->type )    {
462                         case BT_KEY:
463                                 strncpy( btext, key_text[item->value], 10 ); break;
464                         case BT_MOUSE_AXIS:
465                                 strncpy( btext, Text_string[mouseaxis_text[item->value]], 10 ); break;
466                         case BT_JOY_AXIS:
467 #ifdef USE_LINUX_JOY
468                                 sprintf( btext, "J%d A%d", j_axis[item->value].joydev, j_Get_joydev_axis_number (item->value) );
469 #elif defined(SDL_INPUT)
470                                 if (joyaxis_text[item->value])
471                                         strncpy(btext, joyaxis_text[item->value], 10);
472                                 else
473                                         sprintf(btext, "AXIS%2d", item->value + 1);
474 #else
475                                 strncpy(btext, Text_string[joyaxis_text[item->value]], 10);
476 #endif
477                                 break;
478                         case BT_INVERT:
479                                 strncpy( btext, Text_string[invert_text[item->value]], 10 ); break;
480                 }
481         }
482         gr_get_string_size(btext, &w, &h, &aw  );
483
484         return h;
485 }
486 #endif
487
488 void kconfig_sub(kc_item * items,int nitems, char * title)
489 {
490         grs_canvas * save_canvas;
491         grs_font * save_font;
492         int old_keyd_repeat;
493 #ifdef NEWMENU_MOUSE
494         int mouse_state, omouse_state, mx, my, x1, x2, y1, y2;
495         int close_x, close_y, close_size;
496 #endif
497
498         int i,k,ocitem,citem;
499         int time_stopped = 0;
500
501         All_items = items;
502         Num_items = nitems;
503
504         if (!((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence)) )
505         {
506                 time_stopped = 1;
507                 stop_time();
508         }
509
510         save_canvas = grd_curcanv;
511
512
513         gr_set_current_canvas(NULL);
514         save_font = grd_curcanv->cv_font;
515
516         game_flush_inputs();
517         old_keyd_repeat = keyd_repeat;
518         keyd_repeat = 1;
519
520         //gr_clear_canvas( BM_XRGB(0,0,0) );
521
522         nm_draw_background(0, 0, grd_curcanv->cv_bitmap.bm_w - 1, grd_curcanv->cv_bitmap.bm_h - 1);
523    gr_palette_load (gr_palette);
524
525         grd_curcanv->cv_font = MEDIUM3_FONT;
526
527         {
528                 char * p;
529                 p = strchr( title, '\n' );
530                 if ( p ) *p = 32;
531                 gr_string( 0x8000, LHY(8), title );
532                 if ( p ) *p = '\n';
533         }
534
535
536 //      if ( items == kc_keyboard )     {
537 //              gr_string( 0x8000, 8, "Keyboard" );
538 //      } else if ( items == kc_other ) {
539 //              gr_string( 0x8000, 8, "Others" );
540 //      }
541
542 #ifdef NEWMENU_MOUSE
543         close_x = close_y = MenuHires?15:7;
544         close_size = MenuHires?10:5;
545         /*
546         gr_setcolor( BM_XRGB(0, 0, 0) );
547         gr_rect(close_x, close_y, close_x + close_size, close_y + close_size);
548         gr_setcolor( BM_XRGB(21, 21, 21) );
549         gr_rect(close_x + LHX(1), close_y + LHX(1), close_x + close_size - LHX(1), close_y + close_size - LHX(1));
550         */
551 #endif
552
553         grd_curcanv->cv_font = GAME_FONT;
554         gr_set_fontcolor( BM_XRGB(28,28,28), -1 );
555
556         gr_string( 0x8000, LHY(20), TXT_KCONFIG_STRING_1 );
557         gr_set_fontcolor( BM_XRGB(28,28,28), -1 );
558         if ( items == kc_keyboard )     {
559                 gr_set_fontcolor( BM_XRGB(31,27,6), -1 );
560                 gr_setcolor( BM_XRGB(31,27,6) );
561                 
562                 gr_scanline( LHX(98), LHX(106), LHY(42) );
563                 gr_scanline( LHX(120), LHX(128), LHY(42) );
564                 gr_pixel( LHX(98), LHY(43) );                                           
565                 gr_pixel( LHX(98), LHY(44) );                                           
566                 gr_pixel( LHX(128), LHY(43) );                                          
567                 gr_pixel( LHX(128), LHY(44) );                                          
568                 
569                 gr_string( LHX(109), LHY(40), "OR" );
570
571                 gr_scanline( LHX(253), LHX(261), LHY(42) );
572                 gr_scanline( LHX(274), LHX(283), LHY(42) );
573                 gr_pixel( LHX(253), LHY(43) );                                          
574                 gr_pixel( LHX(253), LHY(44) );                                          
575                 gr_pixel( LHX(283), LHY(43) );                                          
576                 gr_pixel( LHX(283), LHY(44) );                                          
577
578                 gr_string( LHX(264), LHY(40), "OR" );
579
580         } if ( items == kc_other )      {
581                 gr_set_fontcolor( BM_XRGB(31,27,6), -1 );
582                 gr_setcolor( BM_XRGB(31,27,6) );
583                 gr_scanline( LHX(18), LHX(60), LHY(119+5) );
584                 gr_scanline( LHX(102), LHX(144), LHY(119+5) );
585                 gr_string( LHX(63), LHY(117+5), TXT_CONTROL_JOYSTICK );
586                 gr_set_fontcolor( BM_XRGB(28,28,28), -1 );
587                 gr_string( LHX(84), LHY(129), TXT_AXIS );
588                 gr_string( LHX(110), LHY(129), TXT_INVERT );
589
590                 gr_set_fontcolor( BM_XRGB(31,27,6), -1 );
591                 gr_setcolor( BM_XRGB(31,27,6) );
592                 gr_scanline( LHX(178), LHX(226), LHY(119+5) );
593                 gr_scanline( LHX(256), LHX(304), LHY(119+5) );
594                 gr_string( LHX(229), LHY(117+5), TXT_CONTROL_MOUSE );
595                 gr_set_fontcolor( BM_XRGB(28,28,28), -1 );
596                 gr_string( LHX(244), LHY(129), TXT_AXIS );
597                 gr_string( LHX(270), LHY(129), TXT_INVERT );
598         }
599         else if ( items == kc_d2x )
600         {
601                 gr_set_fontcolor( BM_XRGB(31,27,6), -1 );
602                 gr_setcolor( BM_XRGB(31,27,6) );
603
604                 gr_scanline( LHX(98), LHX(106), LHY(42) );
605                 gr_scanline( LHX(120), LHX(128), LHY(42) );
606                 gr_pixel( LHX(98), LHY(43) );
607                 gr_pixel( LHX(98), LHY(44) );
608                 gr_pixel( LHX(128), LHY(43) );
609                 gr_pixel( LHX(128), LHY(44) );
610
611                 gr_string(LHX(109), LHY(40), "OR");
612         }
613
614         for (i=0; i<nitems; i++ )       {
615                 kc_drawitem( &items[i], 0 );
616         }
617
618         citem = 0;
619         while(items[citem].id == -1)
620                 citem++;
621         kc_drawitem( &items[citem], 1 );
622
623         newmenu_show_cursor();
624
625 #ifdef NEWMENU_MOUSE
626         mouse_state = omouse_state = 0;
627 #endif
628
629         while(1)                {
630         //      Windows addendum to allow for kconfig input.
631                 vid_update();
632
633                 //see if redbook song needs to be restarted
634                 songs_check_redbook_repeat();
635
636                 k = newmenu_inkey();
637
638 #ifdef NEWMENU_MOUSE
639                 omouse_state = mouse_state;
640                 mouse_state = mouse_button_state(0);
641 #endif
642
643                 if ( !time_stopped ) {
644                         #ifdef NETWORK
645                         if (multi_menu_poll() == -1)
646                                 k = -2;
647                         #endif
648                 }
649                 ocitem = citem;
650                 switch( k )     {
651                 case KEY_BACKSP:
652                         Int3();
653                         break;
654                 case KEY_COMMAND+KEY_SHIFTED+KEY_3:
655                 case KEY_PRINT_SCREEN:
656                         save_screen_shot(0);
657                         break;                                                  
658                 case KEY_CTRLED+KEY_D:
659                         items[citem].value = 255;
660                         kc_drawitem( &items[citem], 1 );
661                         break;
662                 case KEY_CTRLED+KEY_R:  
663                         if ( items == kc_keyboard )
664                                 for (i = 0; i < NUM_KEY_CONTROLS; i++) {
665                                         items[i].value = default_kc_keyboard_settings[i];
666                                         kc_drawitem( &items[i], 0 );
667                                 }
668                         else if ( items == kc_other )
669                                 for (i = 0; i < NUM_OTHER_CONTROLS; i++) {
670                                         items[i].value = default_kc_other_settings[i];
671                                         kc_drawitem( &items[i], 0 );
672                                 }
673                         else if ( items == kc_d2x )
674                                 for (i = 0; i < NUM_D2X_CONTROLS; i++)
675                                 {
676                                         items[i].value = default_kc_d2x_settings[i];
677                                         kc_drawitem( &items[i], 0 );
678                                 }
679                         kc_drawitem( &items[citem], 1 );
680                         break;
681                 case KEY_DELETE:
682                         items[citem].value=255;
683                         kc_drawitem( &items[citem], 1 );
684                         break;
685                 case KEY_UP:            
686                 case KEY_PAD8:
687 #ifdef TABLE_CREATION
688                         if (items[citem].u==-1) items[citem].u=find_next_item_up( items,nitems, citem);
689 #endif
690                         citem = items[citem].u; 
691                         break;
692                 
693                 case KEY_DOWN:  
694                 case KEY_PAD2:
695 #ifdef TABLE_CREATION
696                         if (items[citem].d==-1) items[citem].d=find_next_item_down( items,nitems, citem);
697 #endif
698                         citem = items[citem].d; 
699                         break;
700                 case KEY_LEFT:  
701                 case KEY_PAD4:
702 #ifdef TABLE_CREATION
703                         if (items[citem].l==-1) items[citem].l=find_next_item_left( items,nitems, citem);
704 #endif
705                         citem = items[citem].l; 
706                         break;
707                 case KEY_RIGHT:         
708                 case KEY_PAD6:
709 #ifdef TABLE_CREATION
710                         if (items[citem].r==-1) items[citem].r=find_next_item_right( items,nitems, citem);
711 #endif
712                         citem = items[citem].r; 
713                         break;
714                 case KEY_ENTER: 
715                 case KEY_PADENTER:      
716                         switch( items[citem].type )     {
717                         case BT_KEY:            kc_change_key( &items[citem] ); break;
718                         case BT_MOUSE_AXIS:     kc_change_mouseaxis( &items[citem] ); break;
719                         case BT_JOY_AXIS:       kc_change_joyaxis( &items[citem] ); break;
720                         case BT_INVERT:         kc_change_invert( &items[citem] ); break;
721                         }
722                         break;
723                 //the following case added by WraithX on 11/22/00 to work around the weird joystick bug...
724                 case KEY_SPACEBAR:
725                         switch(items[citem].type)
726                         {
727                         case BT_JOY_AXIS:
728                                 kc_next_joyaxis(&items[citem]);
729                                 break;
730                         }
731                         break;
732                 //end addition by WraithX
733                 case -2:        
734                 case KEY_ESC:
735                         grd_curcanv->cv_font    = save_font;
736
737                         gr_set_current_canvas( save_canvas );
738                         keyd_repeat = old_keyd_repeat;
739                         game_flush_inputs();
740                         newmenu_hide_cursor();
741                         if (time_stopped)
742                                 start_time();
743                         return;
744 #ifdef TABLE_CREATION
745                 case KEY_DEBUGGED+KEY_SHIFTED+KEY_2:
746                 case KEY_DEBUGGED+KEY_F12:      {
747                         FILE * fp;
748                         int j;
749
750                         for (i=0; i<NUM_KEY_CONTROLS; i++ )     {
751                                 kc_keyboard[i].u = find_next_item_up( kc_keyboard,NUM_KEY_CONTROLS, i);
752                                 kc_keyboard[i].d = find_next_item_down( kc_keyboard,NUM_KEY_CONTROLS, i);
753                                 kc_keyboard[i].l = find_next_item_left( kc_keyboard,NUM_KEY_CONTROLS, i);
754                                 kc_keyboard[i].r = find_next_item_right( kc_keyboard,NUM_KEY_CONTROLS, i);
755                         }
756                         for (i=0; i<NUM_OTHER_CONTROLS; i++ )   {
757                                 kc_other[i].u = find_next_item_up( kc_other,NUM_OTHER_CONTROLS, i);
758                                 kc_other[i].d = find_next_item_down( kc_other,NUM_OTHER_CONTROLS, i);
759                                 kc_other[i].l = find_next_item_left( kc_other,NUM_OTHER_CONTROLS, i);
760                                 kc_other[i].r = find_next_item_right( kc_other,NUM_OTHER_CONTROLS, i);
761                         }
762                         for (i = 0; i < NUM_D2X_CONTROLS; i++ ) {
763                                 kc_d2x[i].u = find_next_item_up( kc_d2x, NUM_D2X_CONTROLS, i);
764                                 kc_d2x[i].d = find_next_item_down( kc_d2x, NUM_D2X_CONTROLS, i);
765                                 kc_d2x[i].l = find_next_item_left( kc_d2x, NUM_D2X_CONTROLS, i);
766                                 kc_d2x[i].r = find_next_item_right( kc_d2x, NUM_D2X_CONTROLS, i);
767                         }
768                         fp = stderr; //fopen( "kconfig.cod", "wt" );
769
770                         fprintf( fp, "kc_item kc_keyboard[NUM_KEY_CONTROLS] = {\n" );
771                         for (i=0; i<NUM_KEY_CONTROLS; i++ )     {
772                                 fprintf( fp, "\t{ %2d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%c%s%c, %s, 255 },\n", 
773                                         kc_keyboard[i].id, kc_keyboard[i].x, kc_keyboard[i].y, kc_keyboard[i].w1, kc_keyboard[i].w2,
774                                         kc_keyboard[i].u, kc_keyboard[i].d, kc_keyboard[i].l, kc_keyboard[i].r,
775                                         34, kc_keyboard[i].text, 34, btype_text[kc_keyboard[i].type] );
776                         }
777                         fprintf( fp, "};\n\n" );
778                         fprintf( fp, "ubyte default_kc_keyboard_settings[NUM_KEY_CONTROLS] = " );
779                         fprintf( fp, "{0x%x", kc_keyboard[0].value );
780                         for (j = 1; j < NUM_KEY_CONTROLS; j++)
781                                 fprintf( fp, ",0x%x", kc_keyboard[j].value );
782                         fprintf( fp, "};\n\n" );
783
784                         fprintf( fp, "kc_item kc_other[NUM_OTHER_CONTROLS] = {\n" );
785                         for (i=0; i<NUM_OTHER_CONTROLS; i++ )   {
786                                 fprintf( fp, "\t{ %2d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%c%s%c, %s, 255 },\n",
787                                         kc_other[i].id, kc_other[i].x, kc_other[i].y, kc_other[i].w1, kc_other[i].w2,
788                                         kc_other[i].u, kc_other[i].d, kc_other[i].l, kc_other[i].r,
789                                         34, kc_other[i].text, 34, btype_text[kc_other[i].type] );
790                         }
791                         fprintf( fp, "};\n\n" );
792                         fprintf( fp, "ubyte default_kc_other_settings[NUM_OTHER_CONTROLS] = " );
793                         fprintf( fp, "{0x%x", kc_other[0].value );
794                         for (j = 1; j < NUM_OTHER_CONTROLS; j++)
795                                 fprintf( fp, ",0x%x", kc_other[j].value );
796                         fprintf( fp, "};\n" );
797
798                         fprintf( fp, "kc_item kc_d2x[NUM_D2X_CONTROLS] = {\n" );
799                         for (i=0; i<NUM_D2X_CONTROLS; i++ )     {
800                                 fprintf( fp, "\t{ %2d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%c%s%c, %s, 255 },\n",
801                                                 kc_d2x[i].id, kc_d2x[i].x, kc_d2x[i].y, kc_d2x[i].w1, kc_d2x[i].w2,
802                                                 kc_d2x[i].u, kc_d2x[i].d, kc_d2x[i].l, kc_d2x[i].r,
803                                                 34, kc_d2x[i].text, 34, btype_text[kc_d2x[i].type] );
804                         }
805                         fprintf( fp, "};\n\n" );
806                         fprintf( fp, "ubyte default_kc_d2x_settings[NUM_D2X_CONTROLS] = " );
807                         fprintf( fp, "{0x%x", kc_d2x[0].value );
808                         for (j = 1; j < NUM_D2X_CONTROLS; j++)
809                                 fprintf( fp, ",0x%x", kc_d2x[j].value );
810                         fprintf( fp, "};\n" );
811
812                         fclose(fp);
813
814                         }
815                         break;
816 #endif
817                 }
818
819 #ifdef NEWMENU_MOUSE
820                 if ( (mouse_state && !omouse_state) || (mouse_state && omouse_state) ) {
821                         int item_height;
822                         
823                         mouse_get_pos(&mx, &my);
824                         for (i=0; i<nitems; i++ )       {
825                                 item_height = get_item_height( &items[i] );
826                                 x1 = grd_curcanv->cv_bitmap.bm_x + LHX(items[i].x) + LHX(items[i].w1);
827                                 x2 = x1 + LHX(items[i].w2);
828                                 y1 = grd_curcanv->cv_bitmap.bm_y + LHY(items[i].y);
829                                 y2 = y1 + LHX(item_height);
830                                 if (((mx > x1) && (mx < x2)) && ((my > y1) && (my < y2))) {
831                                         citem = i;
832                                         break;
833                                 }
834                         }
835                 }
836                 else if ( !mouse_state && omouse_state ) {
837                         int item_height;
838                         
839                         mouse_get_pos(&mx, &my);
840                         item_height = get_item_height( &items[citem] );
841                         x1 = grd_curcanv->cv_bitmap.bm_x + LHX(items[citem].x) + LHX(items[citem].w1);
842                         x2 = x1 + LHX(items[citem].w2);
843                         y1 = grd_curcanv->cv_bitmap.bm_y + LHY(items[citem].y);
844                         y2 = y1 + LHY(item_height);
845                         if (((mx > x1) && (mx < x2)) && ((my > y1) && (my < y2))) {
846                                 newmenu_hide_cursor();
847                                 switch( items[citem].type )     {
848                                 case BT_KEY:                            kc_change_key( &items[citem] ); break;
849                                 case BT_MOUSE_AXIS:             kc_change_mouseaxis( &items[citem] ); break;
850                                 case BT_JOY_AXIS:               kc_change_joyaxis( &items[citem] ); break;
851                                 case BT_INVERT:                         kc_change_invert( &items[citem] ); break;
852                                 }
853                                 newmenu_show_cursor();
854                         } else {
855                                 x1 = grd_curcanv->cv_bitmap.bm_x + close_x + LHX(1);
856                                 x2 = x1 + close_size - LHX(1);
857                                 y1 = grd_curcanv->cv_bitmap.bm_y + close_y + LHX(1);
858                                 y2 = y1 + close_size - LHX(1);
859                                 if ( ((mx > x1) && (mx < x2)) && ((my > y1) && (my < y2)) ) {
860                                         grd_curcanv->cv_font    = save_font;
861                                         gr_set_current_canvas( save_canvas );
862                                         keyd_repeat = old_keyd_repeat;
863                                         game_flush_inputs();
864                                         newmenu_hide_cursor();
865                                         if (time_stopped)
866                                                 start_time();
867                                         return;
868                                 }
869                         }
870
871                 }
872 #endif // NEWMENU_MOUSE
873
874                 if (ocitem!=citem)      {
875                         newmenu_hide_cursor();
876                         kc_drawitem( &items[ocitem], 0 );
877                         kc_drawitem( &items[citem], 1 );
878                         newmenu_show_cursor();
879                 }
880         }
881 }
882
883
884 void kc_drawitem( kc_item *item, int is_current )
885 {
886         int x, w, h, aw;
887         char btext[16];
888
889         if (is_current)
890                 gr_set_fontcolor( BM_XRGB(20,20,29), -1 );
891         else
892                 gr_set_fontcolor( BM_XRGB(15,15,24), -1 );
893    gr_string( LHX(item->x), LHY(item->y), item->text );
894
895         if (item->value==255) {
896                 strcpy( btext, "" );
897         } else {
898                 switch( item->type )    {
899                         case BT_KEY:
900                                 strncpy( btext, key_text[item->value], 10 ); break;
901                         case BT_MOUSE_AXIS:
902                                 strncpy( btext, Text_string[mouseaxis_text[item->value]], 10 ); break;
903                         case BT_JOY_AXIS:
904 #ifdef USE_LINUX_JOY
905                                 sprintf(btext, "J%d A%d", j_axis[item->value].joydev, j_Get_joydev_axis_number(item->value));
906 #elif defined(SDL_INPUT)
907                                 if (joyaxis_text[item->value])
908                                         strncpy(btext, joyaxis_text[item->value], 10);
909                                 else
910                                         sprintf(btext, "AXIS%2d", item->value + 1);
911 #else
912                                 strncpy(btext, Text_string[joyaxis_text[item->value]], 10);
913 #endif
914                                 break;
915                         case BT_INVERT:
916                                 strncpy( btext, Text_string[invert_text[item->value]], 10 ); break;
917                 }
918         }
919         if (item->w1) {
920                 gr_get_string_size(btext, &w, &h, &aw  );
921
922                 if (is_current)
923                         gr_setcolor( BM_XRGB(21,0,24) );
924                 else
925                         gr_setcolor( BM_XRGB(16,0,19) );
926                 gr_urect( LHX(item->w1+item->x), LHY(item->y-1), LHX(item->w1+item->x+item->w2), LHY(item->y)+h );
927                 
928                 gr_set_fontcolor( BM_XRGB(28,28,28), -1 );
929
930                 x = LHX(item->w1+item->x)+((LHX(item->w2)-w)/2);
931         
932                 gr_string( x, LHY(item->y), btext );
933         }
934 }
935
936
937 static int looper=0;
938
939 void kc_drawquestion( kc_item *item )
940 {
941         int c, x, w, h, aw;
942
943         gr_get_string_size("?", &w, &h, &aw  );
944
945         c = BM_XRGB(21,0,24);
946
947         //@@gr_setcolor( gr_fade_table[fades[looper]*256+c] );
948         gr_setcolor(BM_XRGB(21*fades[looper]/31,0,24*fades[looper]/31));
949         looper++;
950         if (looper>63) looper=0;
951
952         gr_urect( LHX(item->w1+item->x), LHY(item->y-1), LHX(item->w1+item->x+item->w2), LHY(item->y)+h );
953         
954         gr_set_fontcolor( BM_XRGB(28,28,28), -1 );
955
956         x = LHX(item->w1+item->x)+((LHX(item->w2)-w)/2);
957    
958         gr_string( x, LHY(item->y), "?" );
959         vid_update();
960 }
961
962 void kc_change_key( kc_item * item )
963 {
964         int i,n,f,k;
965         ubyte keycode;
966
967         gr_set_fontcolor( BM_XRGB(28,28,28), -1 );
968         
969         gr_string( 0x8000, LHY(INFO_Y), TXT_PRESS_NEW_KEY );
970
971         game_flush_inputs();
972         keycode=255;
973         k=255;
974         
975         while( (k!=KEY_ESC) && (keycode==255) ) 
976         {                               
977                 #ifdef NETWORK
978                 if ((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence))
979                         multi_menu_poll();
980                 #endif
981 //              if ( Game_mode & GM_MULTI )
982 //                      GameLoop( 0, 0 );                               // Continue
983                 k = key_inkey();
984                 timer_delay(f0_1/10);
985                 kc_drawquestion( item );
986         
987                 for (i=0; i<256; i++ )  {
988                         if (keyd_pressed[i] && (strlen(key_text[i])>0)) {
989                                 f = 0;
990                                 for (n=0; n<sizeof(system_keys); n++ )
991                                         if ( system_keys[n] == i )
992                                                 f=1;
993                                 if (!f) 
994                                         keycode=i;
995                         }
996                 }
997         }
998
999         if (k!=KEY_ESC) {
1000                 for (i=0; i<Num_items; i++ )    {
1001                         n = (int)(item - All_items);
1002                         if ( (i!=n) && (All_items[i].type==BT_KEY) && (All_items[i].value==keycode) )           {
1003                                 All_items[i].value = 255;
1004                                 kc_drawitem( &All_items[i], 0 );
1005                         }
1006                 }
1007                 item->value = keycode;
1008         }
1009         kc_drawitem( item, 1 );
1010
1011         gr_set_fontcolor( BM_XRGB(28,28,28), BM_XRGB(0,0,0) );
1012
1013         nm_restore_background( 0, LHY(INFO_Y), LHX(310), grd_curcanv->cv_font->ft_h );
1014
1015         game_flush_inputs();
1016
1017 }
1018
1019
1020 // the following function added by WraithX on 11/22/00 to work around the weird joystick bug... - modified my Matt Mueller to skip already allocated axes
1021 void kc_next_joyaxis(kc_item *item)
1022 {
1023         int n, i, k, max, tries;
1024         ubyte code = 0;
1025
1026         k = 255;
1027         n = 0;
1028         i = 0;
1029
1030         // I modelled this ifdef after the code in the kc_change_joyaxis method.
1031         // So, if somethin's not workin here, it might not be workin there either.
1032         max = JOY_MAX_AXES;
1033         tries = 1;
1034         code = (item->value + 1) % max;
1035
1036         if (code != 255)
1037         {
1038                 for (i = 0; i < Num_items; i++)
1039                 {
1040                         n = (int)(item - All_items);
1041                         if ((i != n) && (All_items[i].type == BT_JOY_AXIS) && (All_items[i].value == code))
1042                         {
1043                                 if (tries > max)
1044                                         return; // all axes allocated already
1045                                 i = -1; // -1 so the i++ will push back to 0
1046                                 code = (item->value + ++tries) % max; // try next axis
1047                         }//end if
1048                 }//end for
1049
1050                 item->value = code;
1051         }//end if
1052
1053         kc_drawitem(item, 1);
1054         nm_restore_background(0, LHY(INFO_Y), LHX(310), grd_curcanv->cv_font->ft_h);
1055         game_flush_inputs();
1056
1057 }//method kc_next_joyaxis
1058 //end addition by WraithX
1059
1060
1061 void kc_change_joyaxis( kc_item * item )
1062 {
1063         int axis[JOY_MAX_AXES];
1064         int old_axis[JOY_MAX_AXES];
1065         int numaxis = joy_num_axes;
1066         int n,i,k;
1067         ubyte code;
1068
1069         gr_set_fontcolor( BM_XRGB(28,28,28), -1 );
1070         
1071         gr_string( 0x8000, LHY(INFO_Y), TXT_MOVE_NEW_JOY_AXIS );
1072
1073         game_flush_inputs();
1074         code=255;
1075         k=255;
1076
1077         joystick_read_raw_axis( JOY_ALL_AXIS, old_axis );
1078
1079         while( (k!=KEY_ESC) && (code==255))     
1080         {                               
1081                 #ifdef NETWORK
1082                 if ((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence))
1083                         multi_menu_poll();
1084                 #endif
1085 //              if ( Game_mode & GM_MULTI )
1086 //                      GameLoop( 0, 0 );                               // Continue
1087                 k = newmenu_inkey();
1088                 timer_delay(f0_1/10);
1089
1090                 if (k == KEY_PRINT_SCREEN)
1091                         save_screen_shot(0);
1092
1093                 kc_drawquestion( item );
1094
1095                 joystick_read_raw_axis( JOY_ALL_AXIS, axis );
1096
1097                 for (i=0; i<numaxis; i++ )      {
1098                         if ( abs(axis[i]-old_axis[i])>100 )
1099                         {
1100                                 code = i;
1101                                 con_printf(CON_DEBUG, "Axis Movement detected: Axis %i\n", i);
1102                         }
1103                         //old_axis[i] = axis[i];
1104                 }
1105                 for (i=0; i<Num_items; i++ )    
1106                  {
1107                         n = (int)(item - All_items);
1108                         if ( (i!=n) && (All_items[i].type==BT_JOY_AXIS) && (All_items[i].value==code) ) 
1109                                 code = 255;
1110                  }
1111         
1112         }
1113         if (code!=255)  {
1114                 for (i=0; i<Num_items; i++ )    {
1115                         n = (int)(item - All_items);
1116                         if ( (i!=n) && (All_items[i].type==BT_JOY_AXIS) && (All_items[i].value==code) ) {
1117                                 All_items[i].value = 255;
1118                                 kc_drawitem( &All_items[i], 0 );
1119                         }
1120                 }
1121
1122                 item->value = code;                                      
1123         }
1124         kc_drawitem( item, 1 );
1125         nm_restore_background( 0, LHY(INFO_Y), LHX(310), grd_curcanv->cv_font->ft_h );
1126         game_flush_inputs();
1127
1128 }
1129
1130 void kc_change_mouseaxis( kc_item * item )
1131 {
1132         int i,n,k;
1133         ubyte code;
1134         int dx, dy, dz;
1135
1136         gr_set_fontcolor( BM_XRGB(28,28,28), -1 );
1137         
1138         gr_string( 0x8000, LHY(INFO_Y), TXT_MOVE_NEW_MSE_AXIS );
1139
1140         game_flush_inputs();
1141         code=255;
1142         k=255;
1143
1144         mouse_get_delta( &dx, &dy, &dz );
1145
1146         while( (k!=KEY_ESC) && (code==255))     
1147         {                               
1148                 #ifdef NETWORK
1149                 if ((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence))
1150                         multi_menu_poll();
1151                 #endif
1152 //              if ( Game_mode & GM_MULTI )
1153 //                      GameLoop( 0, 0 );                               // Continue
1154                 k = newmenu_inkey();
1155                 timer_delay(f0_1/10);
1156
1157                 if (k == KEY_PRINT_SCREEN)
1158                         save_screen_shot(0);
1159
1160                 kc_drawquestion( item );
1161
1162                 mouse_get_delta( &dx, &dy, &dz );
1163                 if ( abs(dx)>20 ) code = 0;
1164                 if ( abs(dy)>20 ) code = 1;
1165                 if ( abs(dz)>20 ) code = 2;
1166         }
1167         if (code!=255)  {
1168                 for (i=0; i<Num_items; i++ )    {
1169                         n = (int)(item - All_items);
1170                         if ( (i!=n) && (All_items[i].type==BT_MOUSE_AXIS) && (All_items[i].value==code) )               {
1171                                 All_items[i].value = 255;
1172                                 kc_drawitem( &All_items[i], 0 );
1173                         }
1174                 }
1175                 item->value = code;
1176         }
1177         kc_drawitem( item, 1 );
1178         nm_restore_background( 0, LHY(INFO_Y), LHX(310), grd_curcanv->cv_font->ft_h );
1179         game_flush_inputs();
1180
1181 }
1182
1183
1184 void kc_change_invert( kc_item * item )
1185 {
1186         game_flush_inputs();
1187
1188         if (item->value)
1189                 item->value = 0;
1190         else 
1191                 item->value = 1;
1192
1193         kc_drawitem( item, 1 );
1194
1195 }
1196
1197 #include "screens.h"
1198
1199 void kconfig(int n, char * title)
1200 {
1201         int i, j;
1202         grs_bitmap *save_bm;
1203
1204         set_screen_mode( SCREEN_MENU );
1205
1206         kc_set_controls();
1207
1208         //save screen
1209         save_bm = gr_create_bitmap( grd_curcanv->cv_bitmap.bm_w, grd_curcanv->cv_bitmap.bm_h );
1210         Assert( save_bm != NULL );
1211         
1212         gr_bm_bitblt(grd_curcanv->cv_bitmap.bm_w, grd_curcanv->cv_bitmap.bm_w, 
1213                                         0, 0, 0, 0, &grd_curcanv->cv_bitmap, save_bm );
1214
1215         switch(n)       {
1216         case 0:kconfig_sub( kc_keyboard, NUM_KEY_CONTROLS, title );break;
1217         case 1:kconfig_sub( kc_other, NUM_OTHER_CONTROLS, title );break;
1218         case 2:kconfig_sub( kc_d2x, NUM_D2X_CONTROLS, title ); break;
1219         default:
1220                 Int3();
1221                 return;
1222         }
1223
1224         //restore screen
1225         gr_bitmap(0, 0, save_bm);
1226         gr_free_bitmap(save_bm);
1227
1228 #if 0 // set_screen_mode always calls this later... right?
1229         reset_cockpit();                //force cockpit redraw next time
1230 #endif
1231
1232         // Update save values...
1233         
1234         for (j=0; j<256; j++)
1235                 if (key_binding(j)) {
1236                         for (i = 0; i < NUM_KEY_CONTROLS; i++)
1237                                 if (strlen(key_text[j]) && !stricmp(key_binding(j), kc_key_bind_text[i])) {
1238                                         cmd_appendf("unbind %s", key_text[j]);
1239                                         break;
1240                                 }
1241                         for (i = 0; i < NUM_D2X_CONTROLS; i++)
1242                                 if (kc_d2x[i].type == BT_KEY && strlen(key_text[j]) && !stricmp(key_binding(j), kc_d2x[i].text)) {
1243                                         cmd_appendf("unbind %s", key_text[j]);
1244                                         break;
1245                                 }
1246                 }
1247
1248         for (i=0; i<NUM_KEY_CONTROLS; i++ )
1249                 if (kc_keyboard[i].value != 255 && key_text[kc_keyboard[i].value])
1250                         cmd_appendf("bind \"%s\" \"%s\"", key_text[kc_keyboard[i].value], kc_key_bind_text[i]);
1251
1252         for (i = 0; i < NUM_D2X_CONTROLS; i++)
1253                 if (kc_d2x[i].value != 255 && strlen(key_text[kc_d2x[i].value]))
1254                         cmd_appendf("bind \"%s\" \"%s\"", key_text[kc_d2x[i].value], kc_d2x[i].text);
1255
1256         for (i = 0; i < 6; i++) {
1257                 cvar_setint(&joy_advaxes[i], AXIS_NONE);
1258                 cvar_setint(&joy_invert[i], 0);
1259         }
1260         for (i = 0; i < 3; i++) {
1261                 cvar_setint(&mouse_axes[i], AXIS_NONE);
1262                 cvar_setint(&mouse_invert[i], 0);
1263         }
1264         for (i = 0; i < NUM_OTHER_CONTROLS; i++) {
1265                 if (kc_other[i].type == BT_JOY_AXIS && kc_other[i].value != 255) {
1266                         cvar_setint(&joy_advaxes[kc_other[i].value], kc_other_axismap[i]);
1267                         cvar_setint(&joy_invert[kc_other[i].value], kc_other[i+1].value);
1268                 }
1269                 if (kc_other[i].type == BT_MOUSE_AXIS && kc_other[i].value != 255) {
1270                         cvar_setint(&mouse_axes[kc_other[i].value], kc_other_axismap[i]);
1271                         cvar_setint(&mouse_invert[kc_other[i].value], kc_other[i+1].value);
1272                 }
1273         }
1274
1275         cmd_queue_process();
1276 }
1277
1278
1279 fix Last_angles_p = 0;
1280 fix Last_angles_b = 0;
1281 fix Last_angles_h = 0;
1282 ubyte Last_angles_read = 0;
1283
1284 extern int                      VR_sensitivity;
1285                                                 
1286 int VR_sense_range[3] = { 25, 50, 75 };
1287
1288 #if 0 // unused
1289 read_head_tracker()
1290 {
1291         fix yaw, pitch, roll;
1292         int buttons;
1293
1294 //------ read vfx1 helmet --------
1295         if (vfx1_installed) {
1296                 vfx_get_data(&yaw,&pitch,&roll,&buttons);
1297         } else if (iglasses_headset_installed)  {
1298                 iglasses_read_headset( &yaw, &pitch, &roll );
1299         } else if (Victor_headset_installed)   {
1300                 victor_read_headset_filtered( &yaw, &pitch, &roll );
1301         } else {
1302                 return;
1303         }
1304
1305         Use_player_head_angles = 0;
1306         if ( Last_angles_read ) {
1307                 fix yaw1 = yaw;
1308                 
1309                 yaw1 = yaw;
1310                 if ( (Last_angles_h < (F1_0/4) ) && (yaw > ((F1_0*3)/4) ) )     
1311                         yaw1 -= F1_0;
1312                 else if ( (yaw < (F1_0/4) ) && (Last_angles_h > ((F1_0*3)/4) ) )        
1313                         yaw1 += F1_0;
1314         
1315                 Controls.pitch_time     += fixmul((pitch- Last_angles_p)*VR_sense_range[VR_sensitivity],FrameTime);
1316                 Controls.heading_time+= fixmul((yaw1 -  Last_angles_h)*VR_sense_range[VR_sensitivity],FrameTime);
1317                 Controls.bank_time      += fixmul((roll - Last_angles_b)*VR_sense_range[VR_sensitivity],FrameTime);
1318         }
1319         Last_angles_read = 1;
1320         Last_angles_p = pitch;
1321         Last_angles_h = yaw;
1322         Last_angles_b = roll;
1323 }
1324 #endif
1325
1326
1327 void kc_set_controls()
1328 {
1329         int i, j;
1330
1331         for (i=0; i<NUM_KEY_CONTROLS; i++ )
1332                 kc_keyboard[i].value = 255;
1333
1334         for (i=0; i<NUM_OTHER_CONTROLS; i++ ) {
1335                 if (kc_other[i].type == BT_INVERT)
1336                         kc_other[i].value = 0;
1337                 else
1338                         kc_other[i].value = 255;
1339         }
1340
1341         for (i=0; i<NUM_D2X_CONTROLS; i++ )
1342                 kc_d2x[i].value = 255;
1343
1344         for (j = 0; j < 256; j++)
1345                 if (key_binding(j) && strlen(key_text[j])) {
1346                         for (i = 0; i < NUM_KEY_CONTROLS; i++)
1347                                 if (kc_keyboard[i].value == 255
1348                                         && !stricmp(key_binding(j), kc_key_bind_text[i])) {
1349                                         kc_keyboard[i].value = j;
1350                                         break;
1351                                 }
1352                 }
1353
1354         for(j = 0; j < 256; j++)
1355                 if (key_binding(j) && strlen(key_text[j])) {
1356                         for (i = 0; i < NUM_D2X_CONTROLS; i++)
1357                                 if (kc_d2x[i].value == 255
1358                                         && !stricmp(key_binding(j), kc_d2x[i].text)) {
1359                                         kc_d2x[i].value = j;
1360                                         break;
1361                                 }
1362                 }
1363
1364         for (i = 0; i < 6; i++) {
1365                 int inv = joy_invert[i].intval;
1366                 switch (joy_advaxes[i].intval) {
1367                         case AXIS_PITCH:     kc_other[ 0].value = i; kc_other[ 1].value = inv; break;
1368                         case AXIS_TURN:      kc_other[ 2].value = i; kc_other[ 3].value = inv; break;
1369                         case AXIS_LEFTRIGHT: kc_other[ 4].value = i; kc_other[ 5].value = inv; break;
1370                         case AXIS_UPDOWN:    kc_other[ 6].value = i; kc_other[ 7].value = inv; break;
1371                         case AXIS_BANK:      kc_other[ 8].value = i; kc_other[ 9].value = inv; break;
1372                         case AXIS_THROTTLE:  kc_other[10].value = i; kc_other[11].value = inv; break;
1373                         case AXIS_NONE:      break;
1374                         default:
1375                                 Int3();
1376                                 break;
1377                 }
1378         }
1379
1380         for (i = 0; i < 3; i++) {
1381                 int inv = mouse_invert[i].intval;
1382                 switch (mouse_axes[i].intval) {
1383                         case AXIS_PITCH:     kc_other[12].value = i; kc_other[13].value = inv; break;
1384                         case AXIS_TURN:      kc_other[14].value = i; kc_other[15].value = inv; break;
1385                         case AXIS_LEFTRIGHT: kc_other[16].value = i; kc_other[17].value = inv; break;
1386                         case AXIS_UPDOWN:    kc_other[18].value = i; kc_other[19].value = inv; break;
1387                         case AXIS_BANK:      kc_other[20].value = i; kc_other[21].value = inv; break;
1388                         case AXIS_THROTTLE:  kc_other[22].value = i; kc_other[23].value = inv; break;
1389                         case AXIS_NONE:      break;
1390                         default:
1391                                 Int3();
1392                                 break;
1393                 }
1394         }
1395 }
1396
1397 #if 0 // no mac support for vr headset
1398
1399 void kconfig_center_headset()
1400 {
1401         if (vfx1_installed)
1402                 vfx_center_headset();
1403 //      } else if (iglasses_headset_installed)  {
1404 //      } else if (Victor_headset_installed)   {
1405 //      } else {
1406 //      }
1407
1408 }
1409
1410 #endif // end of #if for kconfig_center_headset