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