mirror of
https://github.com/dborth/fceugx.git
synced 2024-11-01 15:05:05 +01:00
225 lines
4.6 KiB
C++
225 lines
4.6 KiB
C++
/* FCE Ultra - NES/Famicom Emulator
|
|
*
|
|
* Copyright notice for this file:
|
|
* Copyright (C) 2002 Xodnizel
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "share.h"
|
|
#include "zapper.h"
|
|
#include "../movie.h"
|
|
|
|
ZAPPER ZD[2];
|
|
|
|
static void ZapperFrapper(int w, uint8 *bg, uint8 *spr, uint32 linets, int final)
|
|
{
|
|
int xs,xe;
|
|
int zx,zy;
|
|
|
|
if(!bg) // New line, so reset stuff.
|
|
{
|
|
ZD[w].zappo=0;
|
|
return;
|
|
}
|
|
xs=ZD[w].zappo;
|
|
xe=final;
|
|
|
|
zx=ZD[w].mzx;
|
|
zy=ZD[w].mzy;
|
|
|
|
if(xe>256) xe=256;
|
|
|
|
if(scanline>=(zy-4) && scanline<=(zy+4))
|
|
{
|
|
while(xs<xe)
|
|
{
|
|
uint8 a1,a2;
|
|
uint32 sum;
|
|
if(xs<=(zx+4) && xs>=(zx-4))
|
|
{
|
|
a1=bg[xs];
|
|
if(spr)
|
|
{
|
|
a2=spr[xs];
|
|
|
|
if(!(a2&0x80))
|
|
if(!(a2&0x40) || (a1&64))
|
|
a1=a2;
|
|
}
|
|
a1&=63;
|
|
|
|
sum=palo[a1].r+palo[a1].g+palo[a1].b;
|
|
if(sum>=100*3)
|
|
{
|
|
ZD[w].zaphit=((uint64)linets+(xs+16)*(PAL?15:16))/48+timestampbase;
|
|
goto endo;
|
|
}
|
|
}
|
|
xs++;
|
|
}
|
|
}
|
|
endo:
|
|
ZD[w].zappo=final;
|
|
|
|
//if this was a miss, clear out the hit
|
|
if(ZD[w].mzb&2)
|
|
ZD[w].zaphit=0;
|
|
|
|
}
|
|
|
|
static INLINE int CheckColor(int w)
|
|
{
|
|
FCEUPPU_LineUpdate();
|
|
|
|
if(newppu)
|
|
{
|
|
int x = (int)ZD[w].mzx;
|
|
int y = (int)ZD[w].mzy;
|
|
int b = (int)ZD[w].mzb;
|
|
bool block = (b&2)!=0;
|
|
|
|
int mousetime = y*256+x;
|
|
int nowtime = scanline*256 + g_rasterpos;
|
|
|
|
if(!block && mousetime < nowtime && mousetime >= nowtime - 384)
|
|
{
|
|
extern uint8 *XBuf;
|
|
uint8 *pix = XBuf+(ZD[w].mzy<<8);
|
|
uint8 a1 = pix[ZD[w].mzx];
|
|
a1&=63;
|
|
uint32 sum=palo[a1].r+palo[a1].g+palo[a1].b;
|
|
//return ZD[w].zaphit = sum != 0;
|
|
ZD[w].zaphit = (sum>=100*3)?1:0;
|
|
}
|
|
else
|
|
{
|
|
ZD[w].zaphit = 0;
|
|
}
|
|
|
|
return ZD[w].zaphit?0:1;
|
|
}
|
|
|
|
|
|
if((ZD[w].zaphit+100)>=(timestampbase+timestamp))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static uint8 ReadZapperVS(int w)
|
|
{
|
|
uint8 ret=0;
|
|
|
|
if(ZD[w].zap_readbit==4) ret=1;
|
|
|
|
if(ZD[w].zap_readbit==7)
|
|
{
|
|
if(ZD[w].bogo)
|
|
ret|=0x1;
|
|
}
|
|
if(ZD[w].zap_readbit==6)
|
|
{
|
|
if(!CheckColor(w))
|
|
ret|=0x1;
|
|
}
|
|
if(!fceuindbg)
|
|
ZD[w].zap_readbit++;
|
|
return ret;
|
|
}
|
|
|
|
static void StrobeZapperVS(int w)
|
|
{
|
|
ZD[w].zap_readbit=0;
|
|
}
|
|
|
|
static uint8 ReadZapper(int w)
|
|
{
|
|
uint8 ret=0;
|
|
if(ZD[w].bogo)
|
|
ret|=0x10;
|
|
if(CheckColor(w))
|
|
ret|=0x8;
|
|
return ret;
|
|
}
|
|
|
|
static void DrawZapper(int w, uint8 *buf, int arg)
|
|
{
|
|
FCEU_DrawGunSight(buf, ZD[w].mzx,ZD[w].mzy);
|
|
}
|
|
|
|
static void UpdateZapper(int w, void *data, int arg)
|
|
{
|
|
uint32 *ptr=(uint32 *)data;
|
|
|
|
bool newclicked = (ptr[2]&3)!=0;
|
|
bool oldclicked = (ZD[w].lastInput)!=0;
|
|
|
|
if(ZD[w].bogo)
|
|
{
|
|
ZD[w].bogo--;
|
|
}
|
|
|
|
ZD[w].lastInput = ptr[2]&3;
|
|
|
|
//woah.. this looks like broken bit logic.
|
|
if(newclicked && !oldclicked)
|
|
{
|
|
ZD[w].bogo=5;
|
|
ZD[w].mzb=ptr[2];
|
|
ZD[w].mzx=ptr[0];
|
|
ZD[w].mzy=ptr[1];
|
|
}
|
|
|
|
}
|
|
|
|
static void LogZapper(int w, MovieRecord* mr)
|
|
{
|
|
mr->zappers[w].x = ZD[w].mzx;
|
|
mr->zappers[w].y = ZD[w].mzy;
|
|
mr->zappers[w].b = ZD[w].mzb;
|
|
mr->zappers[w].bogo = ZD[w].bogo;
|
|
mr->zappers[w].zaphit = ZD[w].zaphit;
|
|
}
|
|
|
|
static void LoadZapper(int w, MovieRecord* mr)
|
|
{
|
|
ZD[w].mzx = mr->zappers[w].x;
|
|
ZD[w].mzy = mr->zappers[w].y;
|
|
ZD[w].mzb = mr->zappers[w].b;
|
|
ZD[w].bogo = mr->zappers[w].bogo;
|
|
ZD[w].zaphit = mr->zappers[w].zaphit;
|
|
}
|
|
|
|
|
|
static INPUTC ZAPC={ReadZapper,0,0,UpdateZapper,ZapperFrapper,DrawZapper,LogZapper,LoadZapper};
|
|
static INPUTC ZAPVSC={ReadZapperVS,0,StrobeZapperVS,UpdateZapper,ZapperFrapper,DrawZapper,LogZapper,LoadZapper};
|
|
|
|
INPUTC *FCEU_InitZapper(int w)
|
|
{
|
|
memset(&ZD[w],0,sizeof(ZAPPER));
|
|
if(GameInfo->type == GIT_VSUNI)
|
|
return(&ZAPVSC);
|
|
else
|
|
return(&ZAPC);
|
|
}
|
|
|
|
|