some movies fixed
[fceu.git] / input.c
CommitLineData
c62d2810 1/* FCE Ultra - NES/Famicom Emulator
2 *
3 * Copyright notice for this file:
5a2aa426 4 * Copyright (C) 1998 BERO
c62d2810 5 * Copyright (C) 2002 Ben Parnell
6 *
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.
11 *
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.
16 *
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
20 */
5232c20c 21#include <string.h>
c62d2810 22#include "types.h"
23#include "x6502.h"
24
25#include "fce.h"
26#include "sound.h"
27#include "netplay.h"
28#include "svga.h"
29
30#include "input.h"
890e37ba 31#include "state.h"
5a2aa426 32#include "movie.h"
c62d2810 33
4fdfab07 34#include "dprintf.h"
35
c62d2810 36extern INPUTC *FCEU_InitZapper(int w);
37extern INPUTC *FCEU_InitPowerpad(int w);
38extern INPUTC *FCEU_InitArkanoid(int w);
39
40extern INPUTCFC *FCEU_InitArkanoidFC(void);
41extern INPUTCFC *FCEU_InitSpaceShadow(void);
42extern INPUTCFC *FCEU_InitFKB(void);
43static uint8 joy_readbit[2];
890e37ba 44static uint8 joy[4]={0,0,0,0};
45static uint8 LastStrobe;
c62d2810 46
47extern int coinon;
48
49static int FSDisable=0; /* Set to 1 if NES-style four-player adapter is disabled. */
50static int JPAttrib[2]={0,0};
51static int JPType[2]={0,0};
52static void *InputDataPtr[2];
53
54static int JPAttribFC=0;
55static int JPTypeFC=0;
56static void *InputDataPtrFC;
57
58void (*InputScanlineHook)(uint8 *buf, int line);
59
60static INPUTC DummyJPort={0,0,0,0,0};
61static INPUTC *JPorts[2]={&DummyJPort,&DummyJPort};
62static INPUTCFC *FCExp=0;
63
64static uint8 FP_FASTAPASS(1) ReadGPVS(int w)
65{
66 uint8 ret=0;
67
68 if(joy_readbit[w]>=8)
69 ret=1;
70 else
71 {
72 ret = ((joy[w]>>(joy_readbit[w]))&1);
73 joy_readbit[w]++;
74 }
75 return ret;
76}
77
78static uint8 FP_FASTAPASS(1) ReadGP(int w)
79{
80 uint8 ret;
5a2aa426 81 //if(JoyMulti)
c62d2810 82 //{
83 //ret = ((joy[w]>>(joy_readbit[w]))&1)|
84 //(((joy[w]>>(joy_readbit[w]+8))&1)<<1);
85 //if(joy_readbit[w]>8) ret=0;
86 //}
87 ret = ((joy[w]>>(joy_readbit[w]))&1);
88 if(FSDisable)
89 {
90 if(joy_readbit[w]>=8) ret|=1;
91 }
92 else
93 {
94 if(joy_readbit[w]==19-w) ret|=1;
95 }
96 joy_readbit[w]++;
97 return ret;
98}
99
100static DECLFR(JPRead)
101{
102 uint8 ret=0;
103
104 if(JPorts[A&1]->Read)
105 ret|=JPorts[A&1]->Read(A&1);
5a2aa426 106
c62d2810 107 if(FCExp)
108 if(FCExp->Read)
109 ret=FCExp->Read(A&1,ret);
110
111 ret|=X.DB&0xC0;
4fdfab07 112 dprintf("JPRead %02x", ret);
c62d2810 113 return(ret);
114}
115
116static DECLFW(B4016)
117{
118 if(FCExp)
119 if(FCExp->Write)
120 FCExp->Write(V&7);
121
122 if(JPorts[0]->Write)
123 JPorts[0]->Write(V&1);
124 if(JPorts[1]->Write)
125 JPorts[1]->Write(V&1);
126
890e37ba 127 if((LastStrobe&1) && (!(V&1)))
c62d2810 128 {
129 /* This strobe code is just for convenience. If it were
130 with the code in input / *.c, it would more accurately represent
131 what's really going on. But who wants accuracy? ;)
132 Seriously, though, this shouldn't be a problem.
133 */
134 if(JPorts[0]->Strobe)
135 JPorts[0]->Strobe(0);
136 if(JPorts[1]->Strobe)
137 JPorts[1]->Strobe(1);
138 if(FCExp)
139 if(FCExp->Strobe)
140 FCExp->Strobe();
141 }
890e37ba 142 LastStrobe=V&1;
c62d2810 143}
144
145static void FP_FASTAPASS(1) StrobeGP(int w)
146{
147 joy_readbit[w]=0;
148}
149
150static INPUTC GPC={ReadGP,0,StrobeGP,0,0,0};
151static INPUTC GPCVS={ReadGPVS,0,StrobeGP,0,0,0};
152
153void DrawInput(uint8 *buf)
154{
155 int x;
156
157 for(x=0;x<2;x++)
158 if(JPorts[x]->Draw)
159 JPorts[x]->Draw(x,buf,JPAttrib[x]);
160 if(FCExp)
161 if(FCExp->Draw)
162 FCExp->Draw(buf,JPAttribFC);
163}
164
165void UpdateInput(void)
166{
167 int x;
168
169 for(x=0;x<2;x++)
170 {
171 switch(JPType[x])
172 {
173 case SI_GAMEPAD:
174 if(!x) joy[0]=*(uint16 *)InputDataPtr[0];
175 else joy[1]=*(uint16 *)InputDataPtr[1];
176 break;
177 default:
178 if(JPorts[x]->Update)
179 JPorts[x]->Update(x,InputDataPtr[x],JPAttrib[x]);
180 break;
181 }
182 }
183 if(FCExp)
184 if(FCExp->Update)
185 FCExp->Update(InputDataPtrFC,JPAttribFC);
186
187 if(FCEUGameInfo.type==GIT_VSUNI)
188 {
189 uint16 t=joy[0];
190 joy[0]=(joy[0]&0xC)|(joy[1]&0xF3);
191 joy[1]=(joy[1]&0xC)|(t&0xF3);
192 if(coinon) coinon--;
193 }
194 #ifdef NETWORK
195 if(netplay) NetplayUpdate(&joy[0],&joy[1]);
196 #endif
5a2aa426 197 if (current < 0) FCEUMOV_AddJoy(joy);
c62d2810 198 FlushCommandQueue();
199}
200
201static DECLFR(VSUNIRead0)
202{
203 uint8 ret=0;
204
205 if(JPorts[0]->Read)
206 ret|=(JPorts[0]->Read(0))&1;
207
208 ret|=(vsdip&3)<<3;
209 if(coinon)
210 ret|=0x4;
211 return ret;
212}
213
214static DECLFR(VSUNIRead1)
215{
216 uint8 ret=0;
217
218 if(JPorts[1]->Read)
219 ret|=(JPorts[1]->Read(1))&1;
220 ret|=vsdip&0xFC;
221 return ret;
222}
223
224static void SLHLHook(uint8 *buf, int line)
225{
226 int x;
227
228 for(x=0;x<2;x++)
229 if(JPorts[x]->SLHook)
230 JPorts[x]->SLHook(x,buf,line);
5a2aa426 231 if(FCExp)
c62d2810 232 if(FCExp->SLHook)
233 FCExp->SLHook(buf,line);
234}
235
236static void CheckSLHook(void)
237{
238 InputScanlineHook=0;
239 if(JPorts[0]->SLHook || JPorts[1]->SLHook)
240 InputScanlineHook=SLHLHook;
241 if(FCExp)
242 if(FCExp->SLHook)
243 InputScanlineHook=SLHLHook;
244}
245
246static void FASTAPASS(1) SetInputStuff(int x)
247{
248 switch(JPType[x])
249 {
250 case SI_GAMEPAD:
251 if(FCEUGameInfo.type==GIT_VSUNI)
252 JPorts[x]=&GPCVS;
253 else
254 JPorts[x]=&GPC;
255 break;
256 case SI_ARKANOID:JPorts[x]=FCEU_InitArkanoid(x);break;
257 case SI_ZAPPER:JPorts[x]=FCEU_InitZapper(x);break;
258 case SI_POWERPAD:JPorts[x]=FCEU_InitPowerpad(x);break;
259 case SI_NONE:JPorts[x]=&DummyJPort;break;
260 }
261
262 CheckSLHook();
263}
264
265static uint8 F4ReadBit[2];
266static void StrobeFami4(void)
267{
268 F4ReadBit[0]=F4ReadBit[1]=0;
269}
270
271static uint8 FP_FASTAPASS(2) ReadFami4(int w, uint8 ret)
272{
273 ret&=1;
274
275 ret |= ((joy[w]>>(F4ReadBit[w]+8))&1)<<1;
276 if(F4ReadBit[w]>=8) ret|=2;
277 else F4ReadBit[w]++;
278
279 return(ret);
280}
281
282static INPUTCFC FAMI4C={ReadFami4,0,StrobeFami4,0,0,0};
283static void SetInputStuffFC(void)
284{
285 switch(JPTypeFC)
286 {
287 case SIFC_NONE:FCExp=0;break;
288 case SIFC_ARKANOID:FCExp=FCEU_InitArkanoidFC();break;
289 case SIFC_SHADOW:FCExp=FCEU_InitSpaceShadow();break;
290 case SIFC_4PLAYER:FCExp=&FAMI4C;memset(&F4ReadBit,0,sizeof(F4ReadBit));break;
291 case SIFC_FKB:FCExp=FCEU_InitFKB();break;
292 }
293 CheckSLHook();
294}
295
296// VS Unisystem code called after SetInputMap() hooks B4016. Need to
297// rewrite code to make this more sane?
298
299void InitializeInput(void)
5a2aa426 300{
c62d2810 301 memset(joy_readbit,0,sizeof(joy_readbit));
302 memset(joy,0,sizeof(joy));
890e37ba 303 LastStrobe=0;
c62d2810 304
305 if(FCEUGameInfo.type==GIT_VSUNI)
306 {
307 SetReadHandler(0x4016,0x4016,VSUNIRead0);
308 SetReadHandler(0x4017,0x4017,VSUNIRead1);
309 }
310 else
311 SetReadHandler(0x4016,0x4017,JPRead);
312 SetWriteHandler(0x4016,0x4016,B4016);
313
314 SetInputStuff(0);
315 SetInputStuff(1);
316 SetInputStuffFC();
317}
318
319void FCEUI_SetInput(int port, int type, void *ptr, int attrib)
320{
321 JPAttrib[port]=attrib;
322 JPType[port]=type;
323 InputDataPtr[port]=ptr;
324 SetInputStuff(port);
325}
326
327void FCEUI_DisableFourScore(int s)
328{
329 FSDisable=s;
330}
331
332void FCEUI_SetInputFC(int type, void *ptr, int attrib)
333{
334 JPAttribFC=attrib;
335 JPTypeFC=type;
336 InputDataPtrFC=ptr;
337 SetInputStuffFC();
338}
890e37ba 339
340// quick paste
341#define FCEUNPCMD_RESET 0x01
342#define FCEUNPCMD_POWER 0x02
343
344#define FCEUNPCMD_VSUNICOIN 0x07
345#define FCEUNPCMD_VSUNIDIP0 0x08
346#define FCEUNPCMD_FDSINSERT 0x18
347#define FCEUNPCMD_FDSSELECT 0x1A
348
349
350void FCEU_DoSimpleCommand(int cmd)
351{
352 switch(cmd)
353 {
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;
362 }
363}
364
365
366SFORMAT FCEUCTRL_STATEINFO[]={
367 { joy_readbit, 2, "JYRB"},
368 { joy, 4, "JOYS"},
369 { &LastStrobe, 1, "LSTS"},
370 { 0 }
371};
372
373