1caaff0aeb726f51e8b874779939d2a27f3be3b6
[fceu.git] / input / zapper.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Xodnizel
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include        <string.h>
22 #include        <stdlib.h>
23
24 #include        "share.h"
25
26 typedef struct {
27         uint32 mzx,mzy,mzb;
28         int zap_readbit;
29         int bogo;
30         int zappo;
31         uint64 zaphit;
32 } ZAPPER;
33
34 static ZAPPER ZD[2];
35
36 static void FP_FASTAPASS(3) ZapperFrapper(int w, uint8 *bg, uint8 *spr, uint32 linets, int final)
37 {
38  int xs,xe;
39  int zx,zy;
40
41  if(!bg) // New line, so reset stuff.
42  {
43   ZD[w].zappo=0;
44   return;
45  }
46  xs=ZD[w].zappo;
47  xe=final;
48
49  zx=ZD[w].mzx;
50  zy=ZD[w].mzy;
51
52  if(xe>256) xe=256;
53
54  if(scanline>=(zy-4) && scanline<=(zy+4))
55  {
56   while(xs<xe)
57   {
58     uint8 a1,a2;
59     uint32 sum;
60     if(xs<=(zx+4) && xs>=(zx-4))
61     {
62      a1=bg[xs];
63      if(spr)
64      {
65       a2=spr[xs];
66
67       if(!(a2&0x80))
68        if(!(a2&0x40) || (a1&64))
69         a1=a2;
70      }
71      a1&=63;
72
73      sum=palo[a1].r+palo[a1].g+palo[a1].b;
74      if(sum>=100*3)
75      {
76       ZD[w].zaphit=((uint64)linets+(xs+16)*(PAL?15:16))/48+timestampbase;
77       goto endo;
78      }
79     }
80    xs++;
81   }
82  }
83  endo:
84  ZD[w].zappo=final;
85 }
86
87 static INLINE int CheckColor(int w)
88 {
89  //FCEUPPU_LineUpdate();
90
91  if((ZD[w].zaphit+100)>=(timestampbase+timestamp)
92   && !(ZD[w].mzb&2)) return(0);
93
94  return(1);
95 }
96
97 static uint8 FP_FASTAPASS(1) ReadZapperVS(int w)
98 {
99                 uint8 ret=0;
100
101                 if(ZD[w].zap_readbit==4) ret=1;
102
103                 if(ZD[w].zap_readbit==7)
104                 {
105                  if(ZD[w].bogo)
106                   ret|=0x1;
107                 }
108                 if(ZD[w].zap_readbit==6)
109                 {
110                  if(!CheckColor(w))
111                   ret|=0x1;
112                 }
113                 if(!fceuindbg)
114                  ZD[w].zap_readbit++;
115                 return ret;
116 }
117
118 static void FP_FASTAPASS(1) StrobeZapperVS(int w)
119 {
120                         ZD[w].zap_readbit=0;
121 }
122
123 static uint8 FP_FASTAPASS(1) ReadZapper(int w)
124 {
125                 uint8 ret=0;
126                 if(ZD[w].bogo)
127                  ret|=0x10;
128                 if(CheckColor(w))
129                  ret|=0x8;
130                 return ret;
131 }
132
133 static void FASTAPASS(3) DrawZapper(int w, uint8 *buf, int arg)
134 {
135  if(arg)
136   FCEU_DrawGunSight(buf, ZD[w].mzx,ZD[w].mzy);
137 }
138
139 static void FP_FASTAPASS(3) UpdateZapper(int w, void *data, int arg)
140 {
141   uint32 *ptr=(uint32 *)data;
142
143  //FCEU_DispMessage("%3d:%3d",ZD[w].mzx,ZD[w].mzy);
144   if(ZD[w].bogo)
145    ZD[w].bogo--;
146   if(ptr[2]&3 && (!(ZD[w].mzb&3)))
147    ZD[w].bogo=5;
148
149   ZD[w].mzx=ptr[0];
150   ZD[w].mzy=ptr[1];
151   ZD[w].mzb=ptr[2];
152 }
153
154 static INPUTC ZAPC={ReadZapper,0,0,UpdateZapper,ZapperFrapper,DrawZapper};
155 static INPUTC ZAPVSC={ReadZapperVS,0,StrobeZapperVS,UpdateZapper,ZapperFrapper,DrawZapper};
156
157 INPUTC *FCEU_InitZapper(int w)
158 {
159   memset(&ZD[w],0,sizeof(ZAPPER));
160   if(FCEUGameInfo.type == GIT_VSUNI)
161    return(&ZAPVSC);
162   else
163    return(&ZAPC);
164 }
165
166