/* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: * Copyright (C) 2002 Xodnizel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include // next three includes required for archos key code and usb #include #include #include #include "main.h" #include "dface.h" #include "input.h" #include "../common/cheat.h" /* UsrInputType[] is user-specified. InputType[] is current (game loading can override user settings) */ int UsrInputType[3]={SI_GAMEPAD,SI_GAMEPAD,SIFC_NONE}; int InputType[3]; static int cspec; int gametype; /* Necessary for proper GUI functioning(configuring when a game isn't loaded). */ void InputUserActiveFix(void) { int x; for(x=0;x<3;x++) InputType[x]=UsrInputType[x]; } void ParseGIInput(FCEUGI *gi) { gametype=gi->type; InputType[0]=UsrInputType[0]; InputType[1]=UsrInputType[1]; InputType[2]=UsrInputType[2]; if(gi->input[0]>=0) InputType[0]=gi->input[0]; if(gi->input[1]>=0) InputType[1]=gi->input[1]; if(gi->inputfc>=0) InputType[2]=gi->inputfc; cspec = gi->cspecial; #ifdef EXTGUI Giggles(gi->cspecial); #endif } static uint8 QuizKingData; static uint8 HyperShotData; static uint32 MahjongData; static uint32 FTrainerData; static uint8 TopRiderData; static uint8 BWorldData[1+13+1]; static void UpdateFKB(void); static void UpdateGamepad(void); static void UpdateQuizKing(void); static void UpdateHyperShot(void); static void UpdateMahjong(void); static void UpdateFTrainer(void); static void UpdateTopRider(void); static uint32 JSreturn; int NoWaiting=1; #ifndef EXTGUI static void DoCheatSeq(void) { #if defined(DOS) || defined(SDL) SilenceSound(1); #endif KillKeyboard(); KillVideo(); DoConsoleCheatConfig(); InitVideo(CurGame); InitKeyboard(); #if defined(DOS) || defined(SDL) SilenceSound(0); #endif } #endif #include "keyscan.h" static char *keys; static int DIPS=0; static uint8 keyonce[MKK_COUNT]; #define KEY(__a) keys[MKK(__a)] static int _keyonly(int a) { if(keys[a]) { if(!keyonce[a]) { keyonce[a]=1; return(1); } } else keyonce[a]=0; return(0); } #define keyonly(__a) _keyonly(MKK(__a)) static int cidisabled=0; /* From Compaq's Touch Screen Specification version 0.2 (draft) */ struct ts_event { unsigned short pressure; unsigned short x; unsigned short y; unsigned short millisecs; }; extern int rotate_mode; extern usb_dev_handle *usb_fdev; static void KeyboardCommands(void) { int is_shift, is_alt; keys=GetKeyboard(); // custom code to read archos touchscreen,key & usb events // ******************************************************* static int tsfd=0, ttyfd=0, maxfd; struct ts_event tsev; uint8 archoskey; // variables used by the select() command to poll keyboard fd_set rfds; struct timeval tv; int retval; // Open the touchscreen for reading if (!tsfd) tsfd = open("/dev/input/tsraw0", O_RDONLY) ; if (!tsfd) { printf("Error: cannot open touchscreen raw device.\n"); exit(1); } if (!ttyfd) ttyfd = open("/dev/tty0", O_RDONLY); if (!ttyfd) { printf("Error: cannot open /dev/tty0.\n"); exit(1); } /* Watch keys and touchscreen for input */ FD_ZERO(&rfds); FD_SET(tsfd, &rfds); FD_SET(ttyfd, &rfds); /* Set wait period to 0 millisecs */ tv.tv_sec = 0; tv.tv_usec = 0; maxfd = ttyfd+1; if (tsfd > ttyfd) maxfd = tsfd+1; retval = select(maxfd, &rfds, NULL, NULL, &tv); if (retval) { if (FD_ISSET(ttyfd, &rfds)) // was a key pressed? { // decode the key press event read(ttyfd, &archoskey, 1); switch (archoskey) { case 0x3c: KEY(ESCAPE)=1; break;// X case 0x1c: KEY(ENTER)=1; break;// OK (NES Select button) case 0x9c: KEY(ENTER)=0; break; case 0x67: if (rotate_mode) KEY(S)=1; else KEY(W)=1; break;// Up case 0xe7: if (rotate_mode) KEY(S)=0; else KEY(W)=0; break; case 0x6c: if (rotate_mode) KEY(A)=1; else KEY(Z)=1; break;// Down case 0xec: if (rotate_mode) KEY(A)=0; else KEY(Z)=0; break; case 0x69: if (rotate_mode) KEY(W)=1; else KEY(A)=1; break;// Left case 0xe9: if (rotate_mode) KEY(W)=0; else KEY(A)=0; break; case 0x6a: if (rotate_mode) KEY(Z)=1; else KEY(S)=1; break;// Right case 0xea: if (rotate_mode) KEY(Z)=0; else KEY(S)=0; break; case 0x73: KEY(KP3)=1; break;// Vol Up (NES button A) case 0xf3: KEY(KP3)=0; break; case 0x72: KEY(TAB)=1; break;// Vol Down (TAB - use on menu selection screens)) case 0xf2: KEY(TAB)=0; break; case 0x3e: KEY(F9)=1; break;// Menu left (F9 = Save Screen Snapshot)) case 0xbe: KEY(F9)=0; break; case 0x3b: KEY(KP2)=1; break;// Menu right (NES button B) case 0xbb: KEY(KP2)=0; break; } } if (FD_ISSET(tsfd, &rfds)) // was there a touchscreen event? { read(tsfd, &tsev, 8); //printf("pressure=%u x=%u y=%u msec=%u\n", tsev.pressure, tsev.x, tsev.y, tsev.millisecs); if (tsev.y > 2047) KEY(KP3)=1; else KEY(KP2)=1; if (tsev.pressure == 0) { KEY(KP3)=0; KEY(KP2)=0; } } } // end of select() poll checks if (usb_fdev) // is there a usb device (psx gamepad) attached? { char buf[4] = {0,0,0,0}; //for psx gamepad read 4 bytes using bulk_read (need 6 if we use rh analogue stick) if (usb_bulk_read(usb_fdev, 0x81, buf, 4, 0)) { // 0ms timeout KEY(KP3) = buf[0]&1 ? 1 : 0; KEY(KP2) = buf[0]&2 ? 1 : 0; KEY(ENTER) = (buf[0]&4) ? 1 : 0; KEY(TAB) = (buf[0]&8) ? 1 : 0; KEY(A) = (buf[2] < 64) ? 1 : 0; KEY(S) = (buf[2] > 192) ? 1 : 0; KEY(W) = (buf[3] < 64) ? 1 : 0; KEY(Z) = (buf[3] > 192) ? 1 : 0; } //usb_clear_halt(usb_fdev, 0x81); // reset the device node } //int ii; //for (ii=0; ii<360; ii++) printf("%03u %u ", ii, keys[ii]); //printf("\n"); //************************************** // end of custom archos key code if(InputType[2]==SIFC_FKB) { if(keyonly(SCROLLLOCK)) { cidisabled^=1; FCEUI_DispMessage("Family Keyboard %sabled.",cidisabled?"en":"dis"); } #ifdef SDL SDL_WM_GrabInput(cidisabled?SDL_GRAB_ON:SDL_GRAB_OFF); #endif if(cidisabled) return; } is_shift = KEY(LEFTSHIFT) | KEY(RIGHTSHIFT); is_alt = KEY(LEFTALT) | KEY(RIGHTALT); if(keyonly(F4)) { if(is_shift) FCEUI_SetRenderDisable(-1, 2); else FCEUI_SetRenderDisable(2, -1); } #ifdef SDL if(keyonly(ENTER) && is_alt) ToggleFS(); #endif NoWaiting&=~1; if(KEY(GRAVE)) NoWaiting|=1; if(gametype==GIT_FDS) { if(keyonly(F6)) FCEUI_FDSSelect(); if(keyonly(F8)) FCEUI_FDSInsert(0); } if(keyonly(F9)) FCEUI_SaveSnapshot(); if(gametype!=GIT_NSF) { #ifndef EXTGUI if(keyonly(F2)) DoCheatSeq(); #endif if(keyonly(F5)) { if(is_shift) FCEUI_SaveMovie(NULL); else FCEUI_SaveState(NULL); } if(keyonly(F7)) { if(is_shift) FCEUI_LoadMovie(NULL); else FCEUI_LoadState(NULL); } } if(keyonly(F1)) FCEUI_ToggleTileView(); if(keyonly(F10)) FCEUI_ResetNES(); if(keyonly(F11)) FCEUI_PowerNES(); #ifdef EXTGUI if(keyonly(F3)) GUI_Hide(-1); if(KEY(F12)) GUI_RequestExit(); if(KEY(ESCAPE)) CloseGame(); #else if(KEY(F12) || KEY(ESCAPE)) CloseGame(); #endif if(gametype==GIT_VSUNI) { if(keyonly(F8)) FCEUI_VSUniCoin(); if(keyonly(F6)) { DIPS^=1; FCEUI_VSUniToggleDIPView(); } if(!(DIPS&1)) goto DIPSless; if(keyonly(1)) FCEUI_VSUniToggleDIP(0); if(keyonly(2)) FCEUI_VSUniToggleDIP(1); if(keyonly(3)) FCEUI_VSUniToggleDIP(2); if(keyonly(4)) FCEUI_VSUniToggleDIP(3); if(keyonly(5)) FCEUI_VSUniToggleDIP(4); if(keyonly(6)) FCEUI_VSUniToggleDIP(5); if(keyonly(7)) FCEUI_VSUniToggleDIP(6); if(keyonly(8)) FCEUI_VSUniToggleDIP(7); } else { static uint8 bbuf[32]; static int bbuft; static int barcoder = 0; if(keyonly(H)) FCEUI_NTSCSELHUE(); if(keyonly(T)) FCEUI_NTSCSELTINT(); if(KEY(KP_MINUS) || KEY(MINUS)) FCEUI_NTSCDEC(); if(KEY(KP_PLUS) || KEY(EQUAL)) FCEUI_NTSCINC(); if((InputType[2] == SIFC_BWORLD) || (cspec == SIS_DATACH)) { if(keyonly(F8)) { barcoder ^= 1; if(!barcoder) { if(InputType[2] == SIFC_BWORLD) { strcpy(&BWorldData[1],bbuf); BWorldData[0]=1; } else FCEUI_DatachSet(bbuf); FCEUI_DispMessage("Barcode Entered"); } else { bbuft = 0; FCEUI_DispMessage("Enter Barcode");} } } else barcoder = 0; #define SSM(x) \ { if(barcoder) { if(bbuft < 13) {bbuf[bbuft++] = '0' + x; bbuf[bbuft] = 0;} FCEUI_DispMessage("Barcode: %s",bbuf);} \ else { \ if(is_shift) FCEUI_SelectMovie(x); \ else FCEUI_SelectState(x); \ } } DIPSless: if(keyonly(0)) SSM(0); if(keyonly(1)) SSM(1); if(keyonly(2)) SSM(2); if(keyonly(3)) SSM(3); if(keyonly(4)) SSM(4); if(keyonly(5)) SSM(5); if(keyonly(6)) SSM(6); if(keyonly(7)) SSM(7); if(keyonly(8)) SSM(8); if(keyonly(9)) SSM(9); #undef SSM } } #define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1} #define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2} #define MKZ() {{0},{0},{0},0} #define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()} ButtConfig GamePadConfig[4][10]={ /* Gamepad 1 */ { MK(KP3), MK(KP2), MK(TAB), MK(ENTER), MK(W),MK(Z), MK(A), MK(S), MKZ(), MKZ() }, /* Gamepad 2 */ GPZ(), /* Gamepad 3 */ GPZ(), /* Gamepad 4 */ GPZ() }; static void UpdateGamepad(void) { static int rapid=0; uint32 JS=0; int x; int wg; rapid^=1; for(wg=0;wg<4;wg++) { for(x=0;x<8;x++) if(DTestButton(&GamePadConfig[wg][x])) JS|=(1<ButtType[wc]==bc->ButtType[wc-1] && bc->DeviceNum[wc]==bc->DeviceNum[wc-1] && bc->ButtonNum[wc]==bc->ButtonNum[wc-1]) break; } bc->NumC=wc; } void ConfigDevice(int which, int arg) { uint8 buf[256]; int x; ButtonConfigBegin(); switch(which) { case FCFGD_QUIZKING: for(x=0;x<6;x++) { sprintf(buf,"Quiz King Buzzer #%d", x+1); subcon(buf,&QuizKingButtons[x]); } break; case FCFGD_HYPERSHOT: for(x=0;x<4;x++) { sprintf(buf,"Hyper Shot %d: %s",((x&2)>>1)+1,(x&1)?"JUMP":"RUN"); subcon(buf,&HyperShotButtons[x]); } break; case FCFGD_POWERPAD: for(x=0;x<12;x++) { sprintf(buf,"PowerPad %d: %d", (arg&1)+1,x+11); subcon(buf,&powerpadsc[arg&1][x]); } break; case FCFGD_GAMEPAD: { char *str[10]={"A","B","SELECT","START","UP","DOWN","LEFT","RIGHT","Rapid A","Rapid B"}; for(x=0;x<10;x++) { sprintf(buf,"GamePad #%d: %s",arg+1,str[x]); subcon(buf,&GamePadConfig[arg][x]); } } break; } ButtonConfigEnd(); } CFGSTRUCT InputConfig[]={ ACA(UsrInputType), AC(powerpadsc), AC(QuizKingButtons), AC(FTrainerButtons), AC(HyperShotButtons), AC(MahjongButtons), AC(GamePadConfig), AC(fkbmap), ENDCFGSTRUCT }; static void InputCfg(char *text) { if(!strncasecmp(text,"gamepad",strlen("gamepad"))) { ConfigDevice(FCFGD_GAMEPAD,(text[strlen("gamepad")]-'1')&3); } else if(!strncasecmp(text,"powerpad",strlen("powerpad"))) { ConfigDevice(FCFGD_POWERPAD,(text[strlen("powerpad")]-'1')&1); } else if(!strcasecmp(text,"hypershot")) ConfigDevice(FCFGD_HYPERSHOT,0); else if(!strcasecmp(text,"quizking")) ConfigDevice(FCFGD_QUIZKING,0); } static void FCExp(char *text) { static char *fccortab[11]={"none","arkanoid","shadow","4player","fkb","hypershot", "mahjong","quizking","ftrainera","ftrainerb","oekakids"}; static int fccortabi[11]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW, SIFC_4PLAYER,SIFC_FKB,SIFC_HYPERSHOT,SIFC_MAHJONG,SIFC_QUIZKING, SIFC_FTRAINERA,SIFC_FTRAINERB,SIFC_OEKAKIDS}; int y; for(y=0;y<11;y++) if(!strcmp(fccortab[y],text)) UsrInputType[2]=fccortabi[y]; } static char *cortab[6]={"none","gamepad","zapper","powerpada","powerpadb","arkanoid"}; static int cortabi[6]={SI_NONE,SI_GAMEPAD, SI_ZAPPER,SI_POWERPADA,SI_POWERPADB,SI_ARKANOID}; static void Input1(char *text) { int y; for(y=0;y<6;y++) if(!strcmp(cortab[y],text)) UsrInputType[0]=cortabi[y]; } static void Input2(char *text) { int y; for(y=0;y<6;y++) if(!strcmp(cortab[y],text)) UsrInputType[1]=cortabi[y]; } ARGPSTRUCT InputArgs[]={ {"-inputcfg",0,(void *)InputCfg,0x2000}, {"-fcexp",0,(void *)FCExp,0x2000}, {"-input1",0,(void *)Input1,0x2000}, {"-input2",0,(void *)Input2,0x2000}, {0,0,0,0} };