1 /* FCE Ultra - NES/Famicom Emulator
3 * Copyright notice for this file:
4 * Copyright (C) 1998 BERO
5 * Copyright (C) 2002 Ben Parnell
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 extern INPUTC *FCEU_InitZapper(int w);
39 extern INPUTC *FCEU_InitPowerpadA(int w);
40 extern INPUTC *FCEU_InitArkanoid(int w);
42 extern INPUTCFC *FCEU_InitArkanoidFC(void);
43 extern INPUTCFC *FCEU_InitSpaceShadow(void);
44 extern INPUTCFC *FCEU_InitFKB(void);
45 static uint8 joy_readbit[2];
46 static uint8 joy[4]={0,0,0,0};
47 static uint8 LastStrobe;
49 static int FSDisable=0; /* Set to 1 if NES-style four-player adapter is disabled. */
50 static int JPAttrib[2]={0,0};
51 static int JPType[2]={0,0};
52 static void *InputDataPtr[2];
54 static int JPAttribFC=0;
55 static int JPTypeFC=0;
56 static void *InputDataPtrFC;
58 void (*InputScanlineHook)(uint8 *bg, uint8 *spr, uint32 linets, int final);
60 static INPUTC DummyJPort={0,0,0,0,0};
61 static INPUTC *JPorts[2]={&DummyJPort,&DummyJPort};
62 static INPUTCFC *FCExp=0;
64 /* This function is a quick hack to get the NSF player to use emulated gamepad
67 uint8 FCEU_GetJoyJoy(void)
69 return(joy[0]|joy[1]|joy[2]|joy[3]);
72 static uint8 FP_FASTAPASS(1) ReadGPVS(int w)
80 ret = ((joy[w]>>(joy_readbit[w]))&1);
86 static uint8 FP_FASTAPASS(1) ReadGP(int w)
91 //ret = ((joy[w]>>(joy_readbit[w]))&1)|
92 //(((joy[w]>>(joy_readbit[w]+8))&1)<<1);
93 //if(joy_readbit[w]>8) ret=0;
95 ret = ((joy[w]>>(joy_readbit[w]))&1);
98 if(joy_readbit[w]>=8) ret|=1;
102 if(joy_readbit[w]==19-w) ret|=1;
108 static DECLFR(JPRead)
112 if(JPorts[A&1]->Read)
113 ret|=JPorts[A&1]->Read(A&1);
117 ret=FCExp->Read(A&1,ret);
120 dprintf("JPRead %i %02x", A&1, ret);
131 JPorts[0]->Write(V&1);
133 JPorts[1]->Write(V&1);
135 if((LastStrobe&1) && (!(V&1)))
137 /* This strobe code is just for convenience. If it were
138 with the code in input / *.c, it would more accurately represent
139 what's really going on. But who wants accuracy? ;)
140 Seriously, though, this shouldn't be a problem.
142 if(JPorts[0]->Strobe)
143 JPorts[0]->Strobe(0);
144 if(JPorts[1]->Strobe)
145 JPorts[1]->Strobe(1);
153 static void FP_FASTAPASS(1) StrobeGP(int w)
158 static INPUTC GPC={ReadGP,0,StrobeGP,0,0,0};
159 static INPUTC GPCVS={ReadGPVS,0,StrobeGP,0,0,0};
161 void DrawInput(uint8 *buf)
167 JPorts[x]->Draw(x,buf,JPAttrib[x]);
170 FCExp->Draw(buf,JPAttribFC);
173 void UpdateInput(void)
182 if(!x) joy[0]=*(uint16 *)InputDataPtr[0];
183 else joy[1]=*(uint16 *)InputDataPtr[1];
186 if(JPorts[x]->Update)
187 JPorts[x]->Update(x,InputDataPtr[x],JPAttrib[x]);
193 FCExp->Update(InputDataPtrFC,JPAttribFC);
195 if(FCEUGameInfo.type==GIT_VSUNI)
198 joy[0]=(joy[0]&0xC)|(joy[1]&0xF3);
199 joy[1]=(joy[1]&0xC)|(t&0xF3);
203 if(netplay) NetplayUpdate(&joy[0],&joy[1]);
205 if (current < 0) FCEUMOV_AddJoy(joy);
206 else framecount++; // for debug
207 //FlushCommandQueue();
210 static DECLFR(VSUNIRead0)
215 ret|=(JPorts[0]->Read(0))&1;
223 static DECLFR(VSUNIRead1)
228 ret|=(JPorts[1]->Read(1))&1;
233 static void SLHLHook(uint8 *bg, uint8 *spr, uint32 linets, int final)
238 if(JPorts[x]->SLHook)
239 JPorts[x]->SLHook(x,bg,spr,linets,final);
242 FCExp->SLHook(bg,spr,linets,final);
245 static void CheckSLHook(void)
248 if(JPorts[0]->SLHook || JPorts[1]->SLHook)
249 InputScanlineHook=SLHLHook;
252 InputScanlineHook=SLHLHook;
255 static void FASTAPASS(1) SetInputStuff(int x)
260 if(FCEUGameInfo.type==GIT_VSUNI)
265 case SI_ARKANOID:JPorts[x]=FCEU_InitArkanoid(x);break;
266 case SI_ZAPPER:JPorts[x]=FCEU_InitZapper(x);break;
267 case SI_POWERPADA:JPorts[x]=FCEU_InitPowerpadA(x);break;
268 case SI_NONE:JPorts[x]=&DummyJPort;break;
274 static uint8 F4ReadBit[2];
275 static void StrobeFami4(void)
277 F4ReadBit[0]=F4ReadBit[1]=0;
280 static uint8 FP_FASTAPASS(2) ReadFami4(int w, uint8 ret)
284 ret |= ((joy[w]>>(F4ReadBit[w]+8))&1)<<1;
285 if(F4ReadBit[w]>=8) ret|=2;
291 static INPUTCFC FAMI4C={ReadFami4,0,StrobeFami4,0,0,0};
292 static void SetInputStuffFC(void)
296 case SIFC_NONE:FCExp=0;break;
297 case SIFC_ARKANOID:FCExp=FCEU_InitArkanoidFC();break;
298 case SIFC_SHADOW:FCExp=FCEU_InitSpaceShadow();break;
299 case SIFC_4PLAYER:FCExp=&FAMI4C;memset(&F4ReadBit,0,sizeof(F4ReadBit));break;
300 case SIFC_FKB:FCExp=FCEU_InitFKB();break;
305 // VS Unisystem code called after SetInputMap() hooks B4016. Need to
306 // rewrite code to make this more sane?
308 void InitializeInput(void)
310 memset(joy_readbit,0,sizeof(joy_readbit));
311 memset(joy,0,sizeof(joy));
314 if(FCEUGameInfo.type==GIT_VSUNI)
316 SetReadHandler(0x4016,0x4016,VSUNIRead0);
317 SetReadHandler(0x4017,0x4017,VSUNIRead1);
320 SetReadHandler(0x4016,0x4017,JPRead);
321 SetWriteHandler(0x4016,0x4016,B4016);
328 void FCEUI_SetInput(int port, int type, void *ptr, int attrib)
330 JPAttrib[port]=attrib;
332 InputDataPtr[port]=ptr;
336 void FCEUI_DisableFourScore(int s)
341 void FCEUI_SetInputFC(int type, void *ptr, int attrib)
349 void FCEU_DoSimpleCommand(int cmd)
351 printf("FCEU_DoSimpleCommand: %i\n", cmd);
354 case FCEUNPCMD_FDSINSERT: FCEU_FDSInsert();break;
355 case FCEUNPCMD_FDSSELECT: FCEU_FDSSelect();break;
356 // case FCEUNPCMD_FDSEJECT: FCEU_FDSEject();break;
357 case FCEUNPCMD_VSUNICOIN: FCEU_VSUniCoin(); break;
358 case FCEUNPCMD_VSUNIDIP0 ... (FCEUNPCMD_VSUNIDIP0 + 7): FCEU_VSUniToggleDIP(cmd - FCEUNPCMD_VSUNIDIP0);break;
359 case FCEUNPCMD_POWER: PowerNES();break;
360 case FCEUNPCMD_RESET: ResetNES();break;
361 default: printf("FCEU_DoSimpleCommand: can't handle cmd %i\n", cmd); break;
365 void FCEU_QSimpleCommand(int cmd)
368 // FCEUNET_SendCommand(cmd, 0);
372 // if(!FCEUMOV_IsPlaying())
373 // FCEU_DoSimpleCommand(cmd);
375 // FCEUMOV_AddCommand(cmd);
377 FCEU_DoSimpleCommand(cmd);
378 // if(FCEUMOV_IsRecording())
379 // FCEUMOV_AddCommand(cmd);
383 void FCEUI_FDSSelect(void)
385 FCEU_QSimpleCommand(FCEUNPCMD_FDSSELECT);
388 int FCEUI_FDSInsert(void)
390 FCEU_QSimpleCommand(FCEUNPCMD_FDSINSERT);
395 int FCEUI_FDSEject(void)
397 FCEU_QSimpleCommand(FCEUNPCMD_FDSEJECT);
401 void FCEUI_VSUniToggleDIP(int w)
403 FCEU_QSimpleCommand(FCEUNPCMD_VSUNIDIP0 + w);
406 void FCEUI_VSUniCoin(void)
408 FCEU_QSimpleCommand(FCEUNPCMD_VSUNICOIN);
411 void FCEUI_ResetNES(void)
413 FCEU_QSimpleCommand(FCEUNPCMD_RESET);
416 void FCEUI_PowerNES(void)
418 FCEU_QSimpleCommand(FCEUNPCMD_POWER);
423 SFORMAT FCEUCTRL_STATEINFO[]={
424 { joy_readbit, 2, "JYRB"},
426 { &LastStrobe, 1, "LSTS"},