Update the discussion of themeing in the manual, and put a note in the wps tags appen...
[kugel-rb.git] / apps / plugins / zxbox / spmain.c
blobe27770c70c2e88e257e6b7d6643b149f756a5eea
1 /*
2 * Copyright (C) 1996-1998 Szeredi Miklos
3 * Email: mszeredi@inf.bme.hu
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version. See the file COPYING.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "zxmisc.h"
21 #include "zxconfig.h"
22 #include "lib/configfile.h"
24 #include "spperif.h"
25 #include "z80.h"
26 #include "spmain.h"
27 #include "sptiming.h"
28 #include "spscr.h"
29 #include "spkey_p.h"
30 #include "spkey.h"
31 #include "sptape.h"
32 #include "spsound.h"
33 #include "snapshot.h"
35 #include "spconf.h"
37 #include "interf.h"
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <errno.h>
44 #ifdef USE_GREY
45 #include "lib/grey.h"
46 #endif
48 #include "zxbox_keyb.h"
50 int endofsingle IBSS_ATTR;
52 int sp_nosync IBSS_ATTR = 0;
54 int showframe IBSS_ATTR = 1;
55 int load_immed = 1;
57 qbyte sp_int_ctr IBSS_ATTR = 0;
58 int intkeys[5] IBSS_ATTR;
60 #ifdef USE_DJGPP
61 #define DOS
62 #endif
64 #define GLOBALCFG "zxbox.cfg"
66 /* here goes settings hadling */
68 /*static struct zxbox_settings settings;*/
69 static struct zxbox_settings old_settings;
71 static char* noyes_options[] = { "No", "Yes" };
72 /*static char* kempston_options[] = { "No", "Yes" };
73 static char* showfps_options[] = {"No", "Yes"};*/
75 static struct configdata config[] =
77 {TYPE_ENUM, 0, 2, { .int_p = &settings.invert_colors }, "Invert Colors",
78 noyes_options},
79 {TYPE_ENUM, 0, 2, { .int_p = &settings.kempston }, "Map keys to kempston",
80 noyes_options},
81 {TYPE_ENUM, 0, 2, { .int_p = &settings.showfps }, "Show Speed",
82 noyes_options},
83 {TYPE_ENUM, 0, 2, { .int_p = &settings.sound }, "Sound", noyes_options},
84 {TYPE_INT, 0, 9, { .int_p = &settings.frameskip }, "Frameskip", NULL},
85 {TYPE_INT, 1, 10, { .int_p = &settings.volume }, "Volume", NULL},
86 {TYPE_STRING, 0, 5, { .string = (char*)&settings.keymap }, "Key Mapping",
87 NULL},
89 int spcf_read_conf_file(const char *filename)
91 settings.volume = 10;
92 settings.showfps=1;
93 settings.keymap[0]='2';
94 settings.keymap[1]='w';
95 settings.keymap[2]='9';
96 settings.keymap[3]='0';
97 settings.keymap[4]='z';
98 settings.kempston = 1 ;
99 settings.invert_colors=0;
100 settings.sound = 0;
101 settings.frameskip = 0;
104 if (configfile_load(filename, config,
105 sizeof(config)/sizeof(*config),
106 SETTINGS_MIN_VERSION
107 ) < 0)
109 /* If the loading failed, save a new config file (as the disk is
110 already spinning) */
111 configfile_save(filename, config,
112 sizeof(config)/sizeof(*config),
113 SETTINGS_VERSION);
115 /* Keep a copy of the saved version of the settings - so we can check if
116 the settings have changed when we quit */
117 old_settings = settings;
118 sound_on = settings.sound;
119 showframe = settings.frameskip+1;
120 int i;
121 for ( i=0 ; i<5 ; i++){
122 if (settings.keymap[i] == 'E')
123 intkeys[i]=SK_KP_Enter;
124 else if ( settings.keymap[i] == 'S' )
125 intkeys[i]=SK_KP_Space;
126 else
127 intkeys[i] = (unsigned) settings.keymap[i];
129 return 1;
132 /* and here it stops (settings loading ;) )*/
134 /* set keys */
135 static void set_keys(void){
136 char c;
137 int selected=0;
138 int result;
139 int menu_quit=0;
140 MENUITEM_STRINGLIST(menu, "Custom keymap", NULL,
141 "Map Up key", "Map Down key", "Map Left key",
142 "Map Right key", "Map Fire/Jump key");
144 rb->button_clear_queue();
146 while (!menu_quit) {
147 result = rb->do_menu(&menu, &selected, NULL, false);
149 switch(result)
151 case 0:
152 if (!zx_kbd_input((char*) &c))
154 settings.keymap[0]=c;
156 break;
157 case 1:
158 if (!zx_kbd_input((char*) &c))
160 settings.keymap[1]=c;
162 break;
163 case 2:
164 if (!zx_kbd_input((char*) &c))
166 settings.keymap[2]=c;
168 break;
169 case 3:
170 if (!zx_kbd_input((char*) &c))
172 settings.keymap[3]=c;
174 break;
175 case 4:
176 if (!zx_kbd_input((char*) &c))
178 settings.keymap[4]=c;
180 break;
181 default:
182 menu_quit=1;
183 break;
188 /* select predefined keymap */
189 static void select_keymap(void){
190 int selected=0;
191 int result;
192 int menu_quit=0;
193 MENUITEM_STRINGLIST(menu, "Predefined keymap", NULL,
194 "2w90z", "qaopS", "7658S");
196 rb->button_clear_queue();
198 while (!menu_quit) {
199 result = rb->do_menu(&menu, &selected, NULL, false);
201 switch(result)
203 case 0:
204 rb->memcpy ( (void*)&settings.keymap[0] , (void*)"2w90z" , 5);
205 menu_quit=1;
206 break;
207 case 1:
208 rb->memcpy ( (void*)&settings.keymap[0] , (void*)"qaopS" , 5);
209 menu_quit=1;
210 break;
211 case 2:
212 rb->memcpy ( (void*)&settings.keymap[0] , (void*)"7658S" , 5);
213 menu_quit=1;
214 break;
215 default:
216 menu_quit=1;
217 break;
222 /* options menu */
223 static void options_menu(void){
224 static const struct opt_items no_yes[2] = {
225 { "No", -1 },
226 { "Yes", -1 },
228 int selected;
229 int result;
230 int menu_quit=0;
231 int new_setting;
232 MENUITEM_STRINGLIST(menu, "Options", NULL,
233 "Map Keys to kempston", "Display Speed",
234 "Invert Colors", "Frameskip", "Sound", "Volume",
235 "Predefined keymap", "Custom keymap");
237 static struct opt_items frameskip_items[] = {
238 { "0", -1 },
239 { "1", -1 },
240 { "2", -1 },
241 { "3", -1 },
242 { "4", -1 },
243 { "5", -1 },
244 { "6", -1 },
245 { "7", -1 },
246 { "8", -1 },
247 { "9", -1 },
251 rb->button_clear_queue();
253 while (!menu_quit) {
254 result = rb->do_menu(&menu, &selected, NULL, false);
256 switch(result)
258 case 0:
259 new_setting=settings.kempston;
260 rb->set_option("Map Keys to kempston",&new_setting,INT,
261 no_yes, 2, NULL);
262 if (new_setting != settings.kempston )
263 settings.kempston=new_setting;
264 break;
265 case 1:
266 new_setting = settings.showfps;
267 rb->set_option("Display Speed",&new_setting,INT,
268 no_yes, 2, NULL);
269 if (new_setting != settings.showfps )
270 settings.showfps=new_setting;
271 break;
272 case 2:
273 new_setting = settings.invert_colors;
274 rb->set_option("Invert Colors",&new_setting,INT,
275 no_yes, 2, NULL);
276 if (new_setting != settings.invert_colors )
277 settings.invert_colors=new_setting;
278 rb->splash(HZ, "Restart to see effect");
279 break;
280 case 3:
281 new_setting = settings.frameskip;
282 rb->set_option("Frameskip",&new_setting,INT,
283 frameskip_items, 10, NULL);
284 if (new_setting != settings.frameskip )
285 settings.frameskip=new_setting;
286 break;
287 case 4:
288 new_setting = settings.sound;
289 rb->set_option("Sound",&new_setting,INT,
290 no_yes, 2, NULL);
291 if (new_setting != settings.sound )
292 settings.sound=new_setting;
293 #if CONFIG_CODEC == SWCODEC && !defined SIMULATOR
294 rb->pcm_play_stop();
295 #endif
296 break;
297 case 5:
298 new_setting = 9 - settings.volume;
299 rb->set_option("Volume",&new_setting,INT,
300 frameskip_items, 10, NULL);
301 new_setting = 9 - new_setting;
302 if (new_setting != settings.volume )
303 settings.volume=new_setting;
304 break;
305 case 6:
306 select_keymap();
307 break;
308 case 7:
309 set_keys();
310 break;
311 default:
312 menu_quit=1;
313 break;
318 /* menu */
319 static bool zxbox_menu(void)
321 #if CONFIG_CODEC == SWCODEC && !defined SIMULATOR
322 rb->pcm_play_stop();
323 #endif
324 int selected=0;
325 int result;
326 int menu_quit=0;
327 int exit=0;
328 char c;
329 MENUITEM_STRINGLIST(menu, "ZXBox Menu", NULL,
330 "VKeyboard", "Play/Pause Tape",
331 "Save quick snapshot", "Load quick snapshot",
332 "Save Snapshot", "Toggle \"fast\" mode",
333 "Options", "Quit");
335 rb->button_clear_queue();
337 while (!menu_quit) {
338 result = rb->do_menu(&menu, &selected, NULL, false);
340 switch(result)
342 case 0:
343 if (!zx_kbd_input((char*) &c))
345 press_key(c);
347 clear_kbd=1;
348 menu_quit=1;
349 break;
350 case 1:
351 pause_play();
352 menu_quit=1;
353 break;
354 case 2:
355 save_quick_snapshot();
356 menu_quit = 1;
357 break;
358 case 3:
359 load_quick_snapshot();
360 menu_quit = 1;
361 break;
362 case 4:
363 save_snapshot();
364 break;
365 case 5:
366 sp_nosync=!sp_nosync;
367 menu_quit=1;
368 break;
369 case 6:
370 options_menu();
371 break;
372 case 7:
373 menu_quit=1;
374 exit=1;
375 break;
376 default:
377 menu_quit=1;
378 break;
382 #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
383 rb->cpu_boost(true);
384 #endif
386 int i;
387 for ( i=0 ; i<5 ; i++){
388 if (settings.keymap[i] == 'E')
389 intkeys[i]=SK_KP_Enter;
390 else if ( settings.keymap[i] == 'S' )
391 intkeys[i]=SK_KP_Space;
392 else
393 intkeys[i] = (unsigned) settings.keymap[i];
395 #ifdef USE_GREY
396 grey_show(true);
397 #endif
398 return (exit);
402 /* */
403 extern unsigned char loadim[];
404 extern unsigned long loadim_size;
406 #define SHOW_OFFS 1
408 static void update(void)
410 update_screen();
411 sp_border_update >>= 1;
412 sp_imag_vert = sp_imag_horiz = 0;
415 static void run_singlemode(void)
417 int t = 0;
418 int evenframe, halfsec, updateframe;
420 sp_int_ctr = 0;
421 endofsingle = 0;
422 spti_reset();
424 while(!endofsingle) {
425 video_frames++;
426 if (clear_kbd){
427 clear_keystates();
428 clear_kbd=0;
430 if(exit_requested){
431 if (zxbox_menu()){
432 /* Save the user settings if they have changed */
433 if (rb->memcmp(&settings,&old_settings,sizeof(settings))!=0) {
434 #ifdef USE_GREY
435 grey_show(false);
436 #endif
437 rb->splash(0, "Saving settings...");
438 configfile_save(GLOBALCFG, config,sizeof(config)/sizeof(*config),SETTINGS_VERSION);
441 return;
443 exit_requested = 0;
444 video_frames=-1;
445 start_time = *rb->current_tick;
446 sound_on = settings.sound;
447 showframe = settings.frameskip+1;
448 spti_reset();
450 halfsec = !(sp_int_ctr % 25);
451 evenframe = !(sp_int_ctr & 1);
453 if(screen_visible) updateframe = sp_nosync ? halfsec :
454 !((sp_int_ctr+SHOW_OFFS) % showframe);
455 else updateframe = 0;
456 if(halfsec) {
457 sp_flash_state = ~sp_flash_state;
458 flash_change();
460 if(evenframe) {
461 play_tape();
462 sp_scline = 0;
464 spkb_process_events(evenframe);
465 sp_updating = updateframe;
466 t += CHKTICK;
467 t = sp_halfframe(t, evenframe ? EVENHF : ODDHF);
468 if(SPNM(load_trapped)) {
469 SPNM(load_trapped) = 0;
470 DANM(haltstate) = 0;
471 qload();
473 z80_interrupt(0xFF);
474 sp_int_ctr++;
475 if(!evenframe) rec_tape();
476 if(!sp_nosync) {
477 if(!sound_avail) spti_wait();
479 if(updateframe) update();
480 play_sound(evenframe);
482 else if(updateframe) update();
488 void check_params(const void* parameter)
490 spcf_read_conf_file(GLOBALCFG);
491 spcf_read_command_line(parameter);
494 static void init_load(const void *parameter)
496 if(load_immed) snsh_z80_load_intern(loadim, loadim_size);
498 check_params(parameter);
499 if(spcf_init_snapshot != NULL) {
500 #ifndef USE_GREY
501 rb->splashf(HZ, "Loading snapshot '%s'", spcf_init_snapshot);
502 #endif
504 load_snapshot_file_type(spcf_init_snapshot, spcf_init_snapshot_type);
505 free_string(spcf_init_snapshot);
508 if(spcf_init_tapefile != NULL) {
509 /*sprintf(msgbuf, "Loading tape '%s'", spcf_init_tapefile);
510 put_msg(msgbuf);*/
511 start_play_file_type(spcf_init_tapefile, 0, spcf_init_tapefile_type);
512 if(!load_immed) pause_play();
513 free_string(spcf_init_tapefile);
517 void start_spectemu(const void *parameter)
519 spti_init();
520 init_load(parameter);
521 init_spect_scr();
522 init_spect_sound();
523 init_spect_key();
525 run_singlemode();