nestopia/source/core/input/NstInpAdapter.cpp
2025-03-04 19:59:01 -05:00

284 lines
5.7 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////
//
// Nestopia - NES/Famicom emulator written in C++
//
// Copyright (C) 2003-2008 Martin Freij
//
// This file is part of Nestopia.
//
// Nestopia 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.
//
// Nestopia 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 Nestopia; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////////////
#include "NstInpDevice.hpp"
#include "NstInpAdapter.hpp"
namespace Nes
{
namespace Core
{
namespace Input
{
#ifdef NST_MSVC_OPTIMIZE
#pragma optimize("s", on)
#endif
Adapter::Adapter(Type t)
: type(t) {}
AdapterTwo::AdapterTwo(Device& a,Device& b,Type t)
: Adapter(t)
{
devices[0] = &a;
devices[1] = &b;
}
bool AdapterTwo::SetType(Type t)
{
if (type != t)
{
type = t;
return true;
}
return false;
}
Device& AdapterTwo::Connect(uint port,Device& device)
{
NST_ASSERT( port < 2 );
Device& old = *devices[port];
devices[port] = &device;
return old;
}
void AdapterTwo::Initialize(bool arcade)
{
for (uint i=0; i < 2; ++i)
devices[i]->Initialize( arcade );
}
void AdapterTwo::Reset()
{
for (uint i=0; i < 2; ++i)
devices[i]->Reset();
}
#ifdef NST_MSVC_OPTIMIZE
#pragma optimize("", on)
#endif
uint AdapterTwo::NumPorts() const
{
return 2;
}
Device& AdapterTwo::GetDevice(uint port) const
{
NST_ASSERT( port < 2 );
return *devices[port];
}
void AdapterTwo::BeginFrame(Controllers* input)
{
devices[0]->BeginFrame( input );
devices[1]->BeginFrame( input );
}
void AdapterTwo::EndFrame()
{
devices[0]->EndFrame();
devices[1]->EndFrame();
}
void AdapterTwo::Poke(uint data)
{
devices[0]->Poke( data );
devices[1]->Poke( data );
}
uint AdapterTwo::Peek(uint line)
{
NST_ASSERT( line < 2 );
return devices[line]->Peek( line );
}
#ifdef NST_MSVC_OPTIMIZE
#pragma optimize("s", on)
#endif
AdapterFour::AdapterFour(Device& a,Device& b,Device& c,Device& d,Type t)
: Adapter(t), increaser(1)
{
count[0] = 0;
count[1] = 0;
devices[0] = &a;
devices[1] = &b;
devices[2] = &c;
devices[3] = &d;
}
Device& AdapterFour::Connect(uint port,Device& device)
{
NST_ASSERT( port < 4 );
Device& old = *devices[port];
devices[port] = &device;
return old;
}
void AdapterFour::Initialize(bool arcade)
{
for (uint i=0; i < 4; ++i)
devices[i]->Initialize( arcade );
}
void AdapterFour::Reset()
{
increaser = 1;
count[0] = 0;
count[1] = 0;
for (uint i=0; i < 4; ++i)
devices[i]->Reset();
}
bool AdapterFour::SetType(Type t)
{
if (type != t)
{
type = t;
increaser = 1;
count[0] = 0;
count[1] = 0;
return true;
}
return false;
}
void AdapterFour::SaveState(State::Saver& state,const dword chunk) const
{
if (type == Api::Input::ADAPTER_NES)
{
const byte data[3] =
{
static_cast<byte>(increaser ^ 1),
static_cast<byte>(count[0]),
static_cast<byte>(count[1])
};
state.Begin( chunk ).Write( data ).End();
}
}
void AdapterFour::LoadState(State::Loader& state)
{
if (type == Api::Input::ADAPTER_NES)
{
State::Loader::Data<3> data( state );
increaser = ~data[0] & 0x1;
count[0] = (data[1] <= 20) ? data[1] : 0;
count[1] = (data[2] <= 20) ? data[2] : 0;
}
}
#ifdef NST_MSVC_OPTIMIZE
#pragma optimize("", on)
#endif
uint AdapterFour::NumPorts() const
{
return 4;
}
Device& AdapterFour::GetDevice(uint port) const
{
NST_ASSERT( port < 4 );
return *devices[port];
}
void AdapterFour::BeginFrame(Controllers* input)
{
for (uint i=0; i < 4; ++i)
devices[i]->BeginFrame( input );
}
void AdapterFour::EndFrame()
{
for (uint i=0; i < 4; ++i)
devices[i]->EndFrame();
}
void AdapterFour::Poke(const uint data)
{
if (type == Api::Input::ADAPTER_NES)
{
increaser = ~data & 0x1;
if (!increaser)
{
count[0] = 0;
count[1] = 0;
}
}
for (uint i=0; i < 4; ++i)
devices[i]->Poke( data );
}
uint AdapterFour::Peek(const uint line)
{
NST_ASSERT( line < 2 );
if (type == Api::Input::ADAPTER_NES)
{
const uint index = count[line];
if (index < 20)
{
count[line] += increaser;
if (index < 16)
{
return devices[line + (index < 8 ? 0 : 2)]->Peek( line );
}
else if (index >= 18)
{
return (index - 18) ^ line;
}
}
return 0;
}
else
{
return
(
(devices[line+0]->Peek( line ) << 0 & 0x1) |
(devices[line+2]->Peek( line ) << 1 & 0x2)
);
}
}
}
}
}