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