diff -urNx '*.o' Nestopia137_orig/Makefile Nestopia137/Makefile --- Nestopia137_orig/Makefile 2007-07-02 23:42:29.000000000 -0700 +++ Nestopia137/Makefile 2007-07-02 23:42:36.000000000 -0700 @@ -17,9 +17,11 @@ EXE = nst LIBS = -lm -lz -lasound `sdl-config --libs` `pkg-config --libs gtk+-2.0` +GENNSTCONTROLS = gennstcontrols + # Linux objs OBJS = objs/linux/main.o objs/linux/oss.o objs/linux/interface.o objs/linux/support.o objs/linux/settings.o -OBJS += objs/linux/auxio.o objs/linux/input.o +OBJS += objs/linux/auxio.o objs/linux/input.o objs/linux/kentry.o # 7-zip decoder OBJS += objs/linux/7zip/7zAlloc.o objs/linux/7zip/7zBuffer.o objs/linux/7zip/7zCrc.o objs/linux/7zip/7zDecode.o objs/linux/7zip/7zExtract.o @@ -128,7 +130,7 @@ @echo Compiling $<... @$.o) $(CFLAGS) $.oFLAGS) $< -o $@ -all: maketree $(EXE) +all: maketree $(EXE) $(GENNSTCONTROLS) maketree: $(sort $(OBJDIRS)) @@ -138,8 +140,17 @@ # link the commandline exe $(EXE): $(OBJS) - @echo Linking $(EXE)... - @$(CPP) -g -o $(EXE) $(OBJS) $(LIBS) + @echo Linking $@... + @$(CPP) -g -o $(EXE) $^ $(LIBS) + +# link the gennstcontrols utility +$(GENNSTCONTROLS): objs/linux/kentry.o objs/linux/gennstcontrols.o + @echo Linking $@... + @$(CPP) -g -o $@ $^ $(LIBS) clean: - rm -f $(OBJS) $(EXE) + -@rm -f $(OBJS) $(EXE) $(GENNSTCONTROLS) + +install: all + @cp $(EXE) $(GENNSTCONTROLS) /usr/games/bin + diff -urNx '*.o' Nestopia137_orig/README.Linux Nestopia137/README.Linux --- Nestopia137_orig/README.Linux 2007-05-20 16:53:40.000000000 -0700 +++ Nestopia137/README.Linux 2007-07-02 23:28:54.000000000 -0700 @@ -38,14 +38,31 @@ * Get the official 1.37 source from http://nestopia.sourceforge.net/ * Unpack it * Unpack this overlay over it -* Go to the directory where you unpacked this and type "make". ("make -j2" for dual-core, "make -j4" for quad). +* Go to the directory where you unpacked this and type "make". ("make -j2" for + dual-core, "make -j4" for quad). -Before running the emulator, copy your nstcontrols file to a folder named .nestopia in your home directory. -This is also where you should put the NEStopia database (NstDatabase.dat), the Disk System BIOS named -"disksys.rom", and this is also where NEStopia saves your settings (nstsettings). +Before running the emulator, copy the appropriate nstcontrols file (rename to +"nstcontrols") to a folder named .nestopia in your home directory, e.g. to use +XBox controllers: -Marty and I try to ensure maximum portability of the code, but at this time it has not been tested on 64-bit -or big-endian targets, although the Mac version obviously runs fine on big-endian. + $ mkdir ~/.nestopia + $ cp nstcontrols.xbox ~/.nestopia/nstcontrols + +If you're using another controller, or want to define your keys interactively, +run the gennstcontrols utility and enter your keys; it will write out a config +file, so for example use: + + $ ./gennstcontrols > ~/.nestopia/nstcontrols + +to write the generated file to the default location. + +This is also where you should put the NEStopia database (NstDatabase.dat), the +Disk System BIOS named "disksys.rom", and this is also where NEStopia saves +your settings (nstsettings). + +Marty and I try to ensure maximum portability of the code, but at this time it +has not been tested on 64-bit or big-endian targets, although the Mac version +obviously runs fine on big-endian. Changes from preview #4 Files Nestopia137_orig/gennstcontrols and Nestopia137/gennstcontrols differ Files Nestopia137_orig/nst and Nestopia137/nst differ diff -urNx '*.o' Nestopia137_orig/nstcontrols Nestopia137/nstcontrols --- Nestopia137_orig/nstcontrols 2007-03-19 20:38:22.000000000 -0700 +++ Nestopia137/nstcontrols 1969-12-31 16:00:00.000000000 -0800 @@ -1,44 +0,0 @@ -; -; NEStopia Linux controls file -; -; First column cannot be changed or you'll break the emulator -; Second column is the key for the first column, or one of these special names: -; -; _ENTER, _LCTRL, _RCTRL, _LALT, _RALT, _SPACE, _LSHIFT, _RSHIFT, _TAB -; _UP, _DOWN, _LEFT, _RIGHT, _KPENTER, _KP0, _KP1, _KP2, _KP3, _KP4, _KP5, _KP6, -; _KP7, _KP8, _KP9, _KPDOT, _KPSLASH, _KPSTAR, _KPMINUS, _KPPLUS (use __ to bind the actual _) -; -; Third column maps joypads: -; _JxAyPLUS = joystick #x axis #y positive direction -; _JxAyMINUS = joystick #x axis #y negative direction -; _JxBy = joystick #x button #y pressed -; -; Some keys are special: -; ESC always exits -; ALT-ENTER always toggles screen modes -; - -; player 1 -; default joypad values are for a PlayStation 2 controller via an EMS USB adaptor -; -P1UP _UP _J0A1MINUS -P1DN _DOWN _J0A1PLUS -P1LT _LEFT _J0A0MINUS -P1RT _RIGHT _J0A0PLUS -P1A , _J0B2 -P1B . _J0B3 -P1START 1 _J0B9 -P1SELECT 2 _J0B8 - -; player 2 -P2UP _KP8 _J1A1MINUS -P2DN _KP2 _J1A1PLUS -P2LT _KP4 _J1A0MINUS -P2RT _KP6 _J1A0PLUS -P2A _KPSLASH _J1B2 -P2B _KPSTAR _J1B3 -P2START _KPENTER _J1B9 -P2SELECT _KPPLUS _J1B8 - -; end of file - diff -urNx '*.o' Nestopia137_orig/nstcontrols.ps2 Nestopia137/nstcontrols.ps2 --- Nestopia137_orig/nstcontrols.ps2 1969-12-31 16:00:00.000000000 -0800 +++ Nestopia137/nstcontrols.ps2 2007-07-03 14:50:02.000000000 -0700 @@ -0,0 +1,55 @@ +; +; NEStopia Linux controls file +; +; First column cannot be changed or you'll break the emulator +; Second column is the key for the first column, or one of these special names: +; +; _ENTER, _LCTRL, _RCTRL, _LALT, _RALT, _SPACE, _LSHIFT, _RSHIFT, _TAB +; _UP, _DOWN, _LEFT, _RIGHT, _KPENTER, _KP0, _KP1, _KP2, _KP3, _KP4, _KP5, _KP6, +; _KP7, _KP8, _KP9, _KPDOT, _KPSLASH, _KPSTAR, _KPMINUS, _KPPLUS (use __ to bind the actual _) +; +; Third column maps joypads: +; _JxAyPLUS = joystick #x axis #y positive direction +; _JxAyMINUS = joystick #x axis #y negative direction +; _JxBy = joystick #x button #y pressed +; +; Some keys are special: +; ESC always exits +; ALT-ENTER always toggles screen modes +; + +; player 1 +; default joypad values are for a PlayStation 2 controller via an EMS USB adaptor +; +P1UP _UP _J0A1MINUS +P1DN _DOWN _J0A1PLUS +P1LT _LEFT _J0A0MINUS +P1RT _RIGHT _J0A0PLUS +P1A , _J0B2 +P1B . _J0B3 +P1START 1 _J0B9 +P1SELECT 2 _J0B8 + +; player 2 +P2UP _KP8 _J1A1MINUS +P2DN _KP2 _J1A1PLUS +P2LT _KP4 _J1A0MINUS +P2RT _KP6 _J1A0PLUS +P2A _KPSLASH _J1B2 +P2B _KPSTAR _J1B3 +P2START _KPENTER _J1B9 +P2SELECT _KPPLUS _J1B8 + +; meta +MSAVE _F1 +MLOAD _F2 +MSTOP _F3 +RESET _F4 +FLIP _F5 +SAVE _F7 +LOAD _F8 +RBACK _BACKSPACE +RFORE \ + +; end of file + diff -urNx '*.o' Nestopia137_orig/nstcontrols.xbox Nestopia137/nstcontrols.xbox --- Nestopia137_orig/nstcontrols.xbox 1969-12-31 16:00:00.000000000 -0800 +++ Nestopia137/nstcontrols.xbox 2007-07-02 23:24:55.000000000 -0700 @@ -0,0 +1,67 @@ +; +; NEStopia Linux controls file +; +; First column cannot be changed or you'll break the emulator +; Subsequent columns are keys or one of these special names: +; +; _ENTER, _LCTRL, _RCTRL, _LALT, _RALT, _SPACE, _LSHIFT, _RSHIFT, _TAB +; _UP, _DOWN, _LEFT, _RIGHT, _KPENTER, _KP0, _KP1, _KP2, _KP3, _KP4, _KP5, _KP6, +; _KP7, _KP8, _KP9, _KPDOT, _KPSLASH, _KPSTAR, _KPMINUS, _KPPLUS (use __ to bind the actual _) +; _BACKSPACE, _F1.._F12, _ESCAPE +; +; Third column maps joypads: +; _JxAy+ = joystick #x axis #y positive direction +; _JxAy- = joystick #x axis #y negative direction +; _JxBy = joystick #x button #y pressed +; _JxHy+ = joystick #x hat #y positive direction +; _JxHy- = joystick #x hat #y negative direction +; +; Some keys are special: +; ESC always exits +; ALT-ENTER always toggles screen modes +; + +; player 1 +; default joypad values are for a (wired) XBox 360 USB controller + +; Xbox controller: +; B0 = "A", B1 = "B", B3 = "Y", ; B4 = "X", B5 = unused?, B6 = "LB", B7 = "RB" +; B8 = "start", B9 = center "X", B16 = "back" (use as select) +; B12-15 = "+" sub-controller up/left/down/right resp., +; Use A2-/A5- for the back lower left/right push-buttons resp. + +P1UP _UP _J0A1- +P1DN _DOWN _J0A1+ +P1LT _LEFT _J0A0- +P1RT _RIGHT _J0A0+ +P1A , _J0B1 +P1B . _J0B0 +P1START 1 _J0B8 +P1SELECT 2 _J0B16 + +; player 2 +; default joypad values are for a (wired) XBox 360 USB controller +P2UP _KP8 _J1A1- +P2DN _KP2 _J1A1+ +P2LT _KP4 _J1A0- +P2RT _KP6 _J1A0+ +P2A _KPSLASH _J1B1 +P2B _KPSTAR _J1B0 +P2START _KPENTER _J1B8 +P2SELECT _KPPLUS _J1B16 + +; meta-commands +QSAVE1 _F1 _J0B7 +QLOAD1 _F2 _J0B6 +QSAVE2 _F3 _J0A5- +QLOAD2 _F4 _J0A2- +RESET _F5 +SAVE _F7 +LOAD _F8 +RBACK _BACKSPACE +RFORE \ +STOP _ESCAPE +EXIT Q _J0B9 + +; end of file + Files Nestopia137_orig/source/linux/.main.cpp.swp and Nestopia137/source/linux/.main.cpp.swp differ diff -urNx '*.o' Nestopia137_orig/source/linux/SDL-event/Makefile Nestopia137/source/linux/SDL-event/Makefile --- Nestopia137_orig/source/linux/SDL-event/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ Nestopia137/source/linux/SDL-event/Makefile 2007-07-02 23:43:18.000000000 -0700 @@ -0,0 +1,19 @@ +# makefile for SDL-event +# dbr 20070701 + +SDL_CFLAGS = $(shell sdl-config --cflags) +SDL_LDFLAGS = $(shell sdl-config --libs) + +CXXFLAGS += $(SDL_CFLAGS) -Wall +LDFLAGS += $(SDL_LDFLAGS) + +TARGET = SDL-event +OBJS = sdlevent.o + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) $(LDFLAGS) $(OBJS) -o $(TARGET) + +clean: + -@rm $(TARGET) $(OBJS) Files Nestopia137_orig/source/linux/SDL-event/SDL-event and Nestopia137/source/linux/SDL-event/SDL-event differ diff -urNx '*.o' Nestopia137_orig/source/linux/SDL-event/sdlevent.cpp Nestopia137/source/linux/SDL-event/sdlevent.cpp --- Nestopia137_orig/source/linux/SDL-event/sdlevent.cpp 1969-12-31 16:00:00.000000000 -0800 +++ Nestopia137/source/linux/SDL-event/sdlevent.cpp 2007-07-02 21:26:58.000000000 -0700 @@ -0,0 +1,135 @@ +/* SDL-event.cpp */ + +#include +#include +#include "SDL.h" + +int main(int argc, const char **argv) +{ + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) + { + fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + + // set up joysticks + SDL_JoystickEventState(SDL_ENABLE); + int cjoy = SDL_NumJoysticks(); + printf("%d joystick(s) detected.\n", cjoy); + for (int ijoy = 0; ijoy < cjoy; ++ijoy) + { + SDL_Joystick *pjoy = SDL_JoystickOpen(0); + printf("Joystick %d is '%s' with %d axes, %d buttons, %d balls.\n", + ijoy, SDL_JoystickName(ijoy), SDL_JoystickNumAxes(pjoy), + SDL_JoystickNumButtons(pjoy), SDL_JoystickNumBalls(pjoy)); + } + printf("\n"); + + // we need to set a video mode to get keyboard events + if (!SDL_SetVideoMode(64, 64, 0, SDL_ANYFORMAT)) + { + fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); + exit(1); + } + + printf("SDL initialized.\n" + "Make sure the black window is active and start generating keyboard or " + "joystick events; press ESC to quit.\n\n"); + + int quit = 0; + while (!quit) + { + SDL_Event evt; + if (!SDL_WaitEvent(&evt)) + { + fprintf(stderr, "SDL_WaitEvent failed: %s\n", SDL_GetError()); + exit(1); + } + + switch (evt.type) + { + case SDL_NOEVENT: + printf("SDL_NOEVENT"); + break; + + case SDL_ACTIVEEVENT: + printf("SDL_ACTIVEEVENT %s%s%s%s", + evt.active.gain ? "gain" : "loss", + (evt.active.state & SDL_APPMOUSEFOCUS) ? " mouse focus" : "", + (evt.active.state & SDL_APPINPUTFOCUS) ? " input focus" : "", + (evt.active.state & SDL_APPACTIVE) ? + (evt.active.gain ? " restored" : " iconified") : ""); + break; + + case SDL_KEYDOWN: + case SDL_KEYUP: + printf("SDL_KEY%s %s %s (scan %d sym %d mod 0x%x)", + (evt.type == SDL_KEYDOWN) ? "DOWN" : "UP", + SDL_GetKeyName(evt.key.keysym.sym), + (evt.key.state == SDL_PRESSED) ? "pressed" : "released", + evt.key.keysym.scancode, evt.key.keysym.sym, evt.key.keysym.mod); + if (evt.type == SDL_KEYDOWN && evt.key.state == SDL_PRESSED + && evt.key.keysym.sym == SDLK_ESCAPE && evt.key.keysym.mod == 0) + { + quit = 1; + } + break; + + case SDL_MOUSEMOTION: + printf("SDL_MOUSEMOTION state 0x%x pos (%d, %d) rel (%d, %d)", + evt.motion.state, evt.motion.x, evt.motion.y, + evt.motion.xrel, evt.motion.yrel); + break; + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + printf("SDL_MOUSEBUTTON%s %s %s pos (%d, %d)", + (evt.type == SDL_MOUSEBUTTONDOWN) ? "DOWN" : "UP", + (evt.button.button == SDL_BUTTON_LEFT) ? "left" : + (evt.button.button == SDL_BUTTON_RIGHT) ? "right" : + (evt.button.button == SDL_BUTTON_MIDDLE) ? "middle" : "?", + (evt.button.state == SDL_PRESSED) ? "pressed" : "released", + evt.button.x, evt.button.y); + break; + + case SDL_JOYAXISMOTION: + case SDL_JOYBALLMOTION: + case SDL_JOYHATMOTION: + printf("SDL_JOY%sMOTION device %d axis %d value %d", + (evt.type == SDL_JOYAXISMOTION) ? "AXIS" : + (evt.type == SDL_JOYBALLMOTION) ? "BALL" : "HAT", + evt.jaxis.which, evt.jaxis.axis, evt.jaxis.value); + if (evt.type == SDL_JOYBALLMOTION) + printf(" rel (%d, %d)", evt.jball.xrel, evt.jball.yrel); + break; + + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: + printf("SDL_JOYBUTTON%s device %d button %d %s", + (evt.type == SDL_JOYBUTTONDOWN) ? "DOWN" : "UP", + evt.jbutton.which, evt.jbutton.button, + (evt.jbutton.state == SDL_PRESSED) ? "pressed" : "released"); + break; + + case SDL_QUIT: + printf("SDL_QUIT"); + quit = 1; + break; + + case SDL_SYSWMEVENT: + case SDL_EVENT_RESERVEDA: + case SDL_EVENT_RESERVEDB: + case SDL_VIDEORESIZE: + case SDL_VIDEOEXPOSE: + /*ignore*/ + break; + + default: + printf("Unknown event (%d)", evt.type); + } + printf ("\n\n"); + } + + printf("\nExiting.\n"); +} diff -urNx '*.o' Nestopia137_orig/source/linux/gennstcontrols.cpp Nestopia137/source/linux/gennstcontrols.cpp --- Nestopia137_orig/source/linux/gennstcontrols.cpp 1969-12-31 16:00:00.000000000 -0800 +++ Nestopia137/source/linux/gennstcontrols.cpp 2007-07-03 15:08:24.000000000 -0700 @@ -0,0 +1,334 @@ +/* gennstcontrols.cpp: generate nstcontrols file interactively + * + * David B. Robins for NEStopia Linux overlay, 2007-07-02 + * + * Generates nstcontrols Linux controller configuration (writes to stdout; + * use as "gennstcontrols > nstcontrols"). + */ + +#include +#include +#include +#include +#include +#include +#include "SDL.h" +#include "kentry.h" +#include "input.h" + + +// represents an axis that is not centered in the "dead zone" +struct AxisNoise +{ + int which; + int axis; + Sint16 pos; + + AxisNoise(int _which, int _axis, Sint16 _pos) : + which(_which), axis(_axis), pos(_pos) {} + + bool match(const SDL_Event &evt) const + { + assert(evt.type == SDL_JOYAXISMOTION); + return evt.jaxis.which == which && evt.jaxis.axis == axis + && abs(evt.jaxis.value - pos) <= DEADZONE; + } +}; + +typedef std::vector AxisNoiseVec; +static AxisNoiseVec axisNoise; + +struct EventMatch +{ + SDL_Event evt; + int len; // of the user text + std::string code; // code for the nstcontrols file + + EventMatch(const SDL_Event &_evt, int _len, const char *_code) : + evt(_evt), len(_len), code(_code) {} +}; +typedef std::vector EventVec; + + +// user strings for meta-events, "!" means just use that key +const KEntry metanames[] = +{ + { "reset emulator", RESET }, + { "quick save slot 1", QSAVE1 }, + { "quick load slot 1", QLOAD1 }, + { "quick save slot 2", QSAVE2 }, + { "quick load slot 2", QLOAD2 }, + { "full save", SAVE }, + { "full load", LOAD }, + { "save movie", MSAVE }, + { "load movie", MLOAD }, + { "stop movie", MSTOP }, + { "flip FDS disk", FLIP }, + { "!_BACKSPACE", RBACK }, + { "!\\", RFORE }, + { "stop emulator", STOP }, + { "exit emulator", EXIT }, + { NULL, -1 } +}; + + +// check for noisy axis that shouldn't count as motion +inline static bool noisy_axis(const SDL_Event &evt) +{ + for (AxisNoiseVec::const_iterator i = axisNoise.begin(); + i != axisNoise.end(); ++i) + { + if (i->match(evt)) + return true; + } + return false; +} + + +// have we already used this input (or axis) for this event? +// (it's OK to assign the same key to multiple events, just not the same one!) +static bool match_event(const EventVec &evtvec, const SDL_Event &evt) +{ + for (EventVec::const_iterator i = evtvec.begin(); i != evtvec.end(); ++i) + { + const SDL_Event &evtT = i->evt; + if (evtT.type != evt.type) + continue; + switch (evtT.type) + { + case SDL_KEYDOWN: + if (evtT.key.keysym.sym == evt.key.keysym.sym) + return true; + break; + + case SDL_JOYBUTTONDOWN: + if (evtT.jbutton.which == evt.jbutton.which + && evtT.jbutton.button == evt.jbutton.button) + { + return true; + } + break; + + case SDL_JOYAXISMOTION: + if (evtT.jaxis.which == evt.jaxis.which + && evtT.jaxis.axis == evt.jaxis.axis) + { + return true; + } + break; + } + } + return false; +} + + +// read an event from SDL and output it in nstcontrols format +static void read_event(const char *entry, const char *desc = NULL) +{ + if (!desc) + desc = entry; + fprintf(stderr, "%s:", desc); + + // use to ensure we don't record multiple events for same axis movement + static struct + { + time_t t; // time when movement counts as new + int which; // which joystick? + int axis; // which axis? + char dir; // direction ('+' or '-') + } + lastAxis; + + int quit = 0; + EventVec evtvec; // input events already seen + while (!quit) + { + SDL_Event evt; + if (!SDL_WaitEvent(&evt)) + { + fprintf(stderr, "SDL_WaitEvent failed: %s\n", SDL_GetError()); + exit(1); + } + + // if we've already seen this input, ignore it + if (match_event(evtvec, evt)) + continue; + + char match[20] = { 0 }; + char input[20] = { 0 }; + switch (evt.type) + { + case SDL_KEYDOWN: + { + int ksym = int(evt.key.keysym.sym); + if (ksym == SDLK_RETURN) + { + fprintf(stderr, " %s\n", evtvec.empty() ? "" : ""); + quit = 1; + break; + } + else if (ksym == SDLK_BACKSPACE && !evtvec.empty()) + { + // remove the last input + const EventMatch &evtm = evtvec.back(); + evtvec.pop_back(); + int len = evtm.len + (evtvec.empty() ? 1 : 2); + for (int i = 0; i < len; ++i) + fprintf(stderr, "\b \b"); + break; + } + + const char *key = kentry_find_code(keycodes, ksym); + if (key != NULL) + { + sprintf(input, "_%s", key); + } + else if (isprint(ksym)) + { + sprintf(input, "%c", ksym); + } + else + { + fprintf(stderr, "\a"); // beep + break; + } + sprintf(match, "%s", SDL_GetKeyName(SDLKey(ksym))); + break; + } + + case SDL_JOYAXISMOTION: + if (abs(evt.jaxis.value) > DEADZONE) + { + // check for a noisy axis with bad centering + if (noisy_axis(evt)) + break; + + char dir = (evt.jaxis.value) > 0 ? '+' : '-'; + time_t t = time(NULL); + + if (lastAxis.dir == dir && lastAxis.which == evt.jaxis.which + && lastAxis.axis == evt.jaxis.axis && t < lastAxis.t) + { + break; + } + lastAxis.dir = dir; + lastAxis.which = evt.jaxis.which; + lastAxis.axis = evt.jaxis.axis; + lastAxis.t = t + 2; + + sprintf(match, "joy %d axis %d %c", + evt.jaxis.which + 1, evt.jaxis.axis, dir); + sprintf(input, "_J%dA%d%c", evt.jaxis.which, evt.jaxis.axis, dir); + } + break; + + case SDL_JOYBUTTONDOWN: + sprintf(match, "joy %d button %d", + evt.jbutton.which + 1, evt.jbutton.button); + sprintf(input, "_J%dB%d", evt.jbutton.which, evt.jbutton.button); + break; + + case SDL_QUIT: + exit(1); + break; + } + + if (match[0]) + { + fprintf(stderr, "%s %s", evtvec.empty() ? "" : ",", match); + evtvec.push_back(EventMatch(evt, strlen(match), input)); + } + } + + // write the nstcontrols line + printf("%s", entry); + for (EventVec::const_iterator i = evtvec.begin(); i != evtvec.end(); ++i) + printf("\t%s", i->code.c_str()); + printf("\n"); +} + + +int main(int argc, const char **argv) +{ + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) + { + fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + + fprintf(stderr, + "gennstcontrols utility version 1.0 by David B. Robins (c)2007.\n" + "Released under the GNU General Public License (GPL) v2.\n\n"); + + // set up joysticks + int cjoy = SDL_NumJoysticks(); + fprintf(stderr, "%d joystick(s) detected.\n", cjoy); + for (int ijoy = 0; ijoy < cjoy; ++ijoy) + { + SDL_Joystick *pjoy = SDL_JoystickOpen(ijoy); + int caxis = SDL_JoystickNumAxes(pjoy); + fprintf(stderr, "Joystick %d is '%s' has %d axes and %d buttons.\n", + ijoy + 1, SDL_JoystickName(ijoy), caxis, SDL_JoystickNumButtons(pjoy)); + + // calibrate - read axis positions and store as "centered" + // we expect joysticks to be centered in (-DEADZONE, DEADZONE) but + // need to filter out noise + for (int iaxis = 0; iaxis < caxis; ++iaxis) + { + Sint16 pos = SDL_JoystickGetAxis(pjoy, iaxis); + if (abs(pos) > DEADZONE) + axisNoise.push_back(AxisNoise(ijoy, iaxis, pos)); + } + } + SDL_JoystickEventState(SDL_ENABLE); + fprintf(stderr, "\n"); + + // we need to set a video mode to get keyboard events + if (!SDL_SetVideoMode(64, 64, 0, SDL_ANYFORMAT)) + { + fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); + exit(1); + } + + fprintf(stderr, "For each entry, press keys or joystick buttons, ENTER when " + "done (or to skip).\nMake sure the small black window is active.\n\n"); + + time_t t = time(NULL); + struct tm *tmNow = localtime(&t); + char now[17]; // yyyy-mm-dd HH:MM + strftime(now, sizeof(now), "%Y-%m-%d %H:%M", tmNow); + printf(";\n; nstcontrols file generated by gennstcontrols on %s\n;\n\n", now); + + // get controls for both players + for (int player = 1; player <= 2; ++player) + { + printf("; player %d controls\n", player); + std::string prefix = std::string("P") + std::string(1, '0' + player); + for (const KEntry *ctrl = controlcodes; ctrl->string != NULL; ++ctrl) + { + std::string entry = prefix + ctrl->string; // e.g. "P1LEFT" + read_event(entry.c_str()); + } + fprintf(stderr, "\n"); + printf("\n"); + } + + // get meta-controls + printf("; meta-controls\n"); + for (const KEntry *meta = metanames; meta->string != NULL; ++meta) + { + const char *code = kentry_find_code(metacodes, meta->code); + assert(code != NULL); + if (meta->string[0] == '!') + { + printf("%s\t%s\n", code, meta->string + 1); + } + else + read_event(code, meta->string); + } + + fprintf(stderr, "Done.\n"); + printf("\n; end of file\n"); + exit(0); +} diff -urNx '*.o' Nestopia137_orig/source/linux/input.cpp Nestopia137/source/linux/input.cpp --- Nestopia137_orig/source/linux/input.cpp 2007-03-19 15:57:30.000000000 -0700 +++ Nestopia137/source/linux/input.cpp 2007-07-03 11:27:34.000000000 -0700 @@ -15,7 +15,6 @@ #include "core/api/NstApiEmulator.hpp" #include "core/api/NstApiVideo.hpp" #include "core/api/NstApiSound.hpp" -#include "core/api/NstApiInput.hpp" #include "core/api/NstApiMachine.hpp" #include "core/api/NstApiUser.hpp" #include "core/api/NstApiNsf.hpp" @@ -26,119 +25,193 @@ #include "settings.h" #include "auxio.h" #include "input.h" +#include "kentry.h" static char linebuf[256]; static FILE *infile; -typedef struct -{ - char *string; - int code; -} KEntry; -static KEntry keycodes[] = +// translate player control to Nes::Api code +static int translate_code(const char *str) { - { "ENTER", SDLK_RETURN }, - { "LCTRL", SDLK_LCTRL }, - { "RCTRL", SDLK_RCTRL }, - { "LALT", SDLK_LALT }, - { "RALT", SDLK_RALT }, - { "SPACE", SDLK_SPACE }, - { "LSHIFT", SDLK_LSHIFT }, - { "RSHIFT", SDLK_RSHIFT }, - { "TAB", SDLK_TAB }, - { "UP", SDLK_UP }, - { "DOWN", SDLK_DOWN }, - { "LEFT", SDLK_LEFT }, - { "RIGHT", SDLK_RIGHT }, - { "KPENTER", SDLK_KP_ENTER }, - { "KP0", SDLK_KP0 }, - { "KP1", SDLK_KP1 }, - { "KP2", SDLK_KP2 }, - { "KP3", SDLK_KP3 }, - { "KP4", SDLK_KP4 }, - { "KP5", SDLK_KP5 }, - { "KP6", SDLK_KP6 }, - { "KP7", SDLK_KP7 }, - { "KP8", SDLK_KP8 }, - { "KP9", SDLK_KP9 }, - { "KPDOT", SDLK_KP_PERIOD }, - { "KPSLASH", SDLK_KP_DIVIDE }, - { "KPSTAR", SDLK_KP_MULTIPLY }, - { "KPMINUS", SDLK_KP_MINUS }, - { "KPPLUS", SDLK_KP_PLUS }, - { "", -1 } -}; + int i = kentry_find_str(controlcodes, str); + if (i == -1) + std::cout << "Error understanding control type '" << str << "'\n"; + return i; +} -static int translate_code(char *substr) +// translate key descriptor into SDL keycode +static bool translate_key(const char *substr, SDL_Event &evt) { - if (!strcmp(substr, "UP")) - { - return Nes::Api::Input::Controllers::Pad::UP; - } - else if (!strcmp(substr, "DN")) - { - return Nes::Api::Input::Controllers::Pad::DOWN; - } - else if (!strcmp(substr, "LT")) + evt.type = SDL_KEYDOWN; + + if (substr[0] != '_') // literal case + { + evt.key.keysym.sym = SDLKey(tolower(substr[0])); + return true; + } + + if (substr[1] == '_') // quoted _ + { + evt.key.keysym.sym = SDLKey('_'); + return true; + } + + int i = kentry_find_str(keycodes, substr + 1); + + if (i == -1) { - return Nes::Api::Input::Controllers::Pad::LEFT; + std::cout << "unknown key " << substr << "\n"; + return false; } - else if (!strcmp(substr, "RT")) + + evt.key.keysym.sym = SDLKey(i); + return true; +} + + +// translate event type into InputEvtT value +static int translate_meta(const char *str) +{ + int i = kentry_find_str(metacodes, str); + if (i == -1) + std::cout << "invalid event type '" << str << "'\n"; + return i; +} + + +// add a control to the list, fail if we're full +bool add_control(const InputDefT &control, + InputDefT *pcontrol, int &icontrol, int ccontrol) +{ + if (icontrol >= ccontrol) { - return Nes::Api::Input::Controllers::Pad::RIGHT; + std::cout << "Too many controls (max " << ccontrol << ")\n"; + return false; } - else if (!strcmp(substr, "A")) + memcpy(pcontrol + icontrol++, &control, sizeof(control)); + + return true; +} + + +// translate joystick/gamepad spec: +// _ ( A | B