16f9e157aaa24f9632f5ed8e583d53600600ae9e
[fceu.git] / input / zapper.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Ben Parnell
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         uint32 colok;
31         uint32 coloklast;
32 } ZAPPER;
33
34 static ZAPPER ZD[2];
35
36 static void FP_FASTAPASS(3) ZapperThingy(int w, uint8 *buf, int line)
37 {
38         int mzx=ZD[w].mzx;
39
40         if(line==0) ZD[w].colok=1<<16;     /* Disable it. */
41
42         ZD[w].coloklast=ZD[w].colok;
43
44         if(ZD[w].mzb&2) return;
45         if((line>=ZD[w].mzy-3 && line<=ZD[w].mzy+3) && mzx<256)
46         {
47          int a,sum,x;
48
49          for(x=-4;x<4;x++)
50          {
51           if((mzx+x)<0 || (mzx+x)>255) continue;
52           a=buf[mzx+x]&63;
53           sum=palo[a].r+palo[a].g+palo[a].b;
54
55           if(sum>=100*3)
56           {
57            ZD[w].colok=timestamp+mzx/3;
58            break;
59           }
60          }
61         }
62
63 }
64
65 static INLINE int CheckColor(int w)
66 {
67   if( (timestamp>=ZD[w].coloklast && timestamp<=(ZD[w].coloklast+100)) ||
68    (timestamp>=ZD[w].colok && timestamp<=(ZD[w].colok+100)) )
69    return 0;
70   return 1;
71 }
72
73 static uint8 FP_FASTAPASS(1) ReadZapperVS(int w)
74 {
75                 uint8 ret=0;
76
77                 if(ZD[w].zap_readbit==4) ret=1;
78
79                 if(ZD[w].zap_readbit==7)
80                 {
81                  if(ZD[w].bogo)
82                   ret|=0x1;
83                 }
84                 if(ZD[w].zap_readbit==6)
85                 {
86                  if(!CheckColor(w))
87                   ret|=0x1;
88                 }
89                 ZD[w].zap_readbit++; 
90                 return ret;
91 }
92
93 static void FP_FASTAPASS(1) StrobeZapperVS(int w)
94 {                        
95                         ZD[w].zap_readbit=0;
96 }
97
98 static uint8 FP_FASTAPASS(1) ReadZapper(int w)
99 {
100                 uint8 ret=0;
101                 if(ZD[w].bogo)
102                  ret|=0x10;
103                 if(CheckColor(w))
104                  ret|=0x8;
105                 return ret;
106 }
107
108 static void FASTAPASS(3) DrawZapper(int w, uint8 *buf, int arg)
109 {
110  if(arg)
111   FCEU_DrawCursor(buf, ZD[w].mzx,ZD[w].mzy);
112 }
113
114 static void FP_FASTAPASS(3) UpdateZapper(int w, void *data, int arg)
115 {
116   uint32 *ptr=data;
117
118   if(ZD[w].bogo)
119    ZD[w].bogo--;
120   if(ptr[2]&3 && (!(ZD[w].mzb&3)))
121    ZD[w].bogo=5;
122
123   ZD[w].mzx=ptr[0];
124   ZD[w].mzy=ptr[1];
125   ZD[w].mzb=ptr[2];
126
127   if(ZD[w].mzb&2 || ZD[w].mzx>=256 || ZD[w].mzy>=240)
128    ZD[w].colok=0;
129 }
130
131 static INPUTC ZAPC={ReadZapper,0,0,UpdateZapper,ZapperThingy,DrawZapper};
132 static INPUTC ZAPVSC={ReadZapperVS,0,StrobeZapperVS,UpdateZapper,ZapperThingy,DrawZapper};
133
134 INPUTC *FCEU_InitZapper(int w)
135 {
136   memset(&ZD[w],0,sizeof(ZAPPER));
137   if(FCEUGameInfo.type==GIT_VSUNI)
138    return(&ZAPVSC);
139   else
140    return(&ZAPC);
141 }
142
143