sameboy: input

This commit is contained in:
nattthebear 2017-07-18 18:19:51 -04:00
parent 721a6c0470
commit 1f89158179
7 changed files with 90 additions and 34 deletions
BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy
waterbox/sameboy

View File

@ -3,6 +3,7 @@ using BizHawk.Emulation.Cores.Waterbox;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
@ -10,6 +11,26 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
{
public abstract class LibSameboy : LibWaterboxCore
{
[Flags]
public enum Buttons : uint
{
A = 0x01,
B = 0x02,
SELECT = 0x04,
START = 0x08,
RIGHT = 0x10,
LEFT = 0x20,
UP = 0x40,
DOWN = 0x80
}
[StructLayout(LayoutKind.Sequential)]
public new class FrameInfo : LibWaterboxCore.FrameInfo
{
public long Time;
public Buttons Keys;
}
[BizImport(CC)]
public abstract bool Init(bool cgb);
}

View File

@ -32,6 +32,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
private LibSameboy _core;
private bool _cgb;
private bool _sgb;
[CoreConstructor("GB")]
public Sameboy(CoreComm comm, byte[] rom)
@ -76,10 +77,65 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
PostInit();
}
#region Controller
private static readonly ControllerDefinition _gbDefinition;
private static readonly ControllerDefinition _sgbDefinition;
public override ControllerDefinition ControllerDefinition => _sgb ? _sgbDefinition : _gbDefinition;
private static ControllerDefinition CreateControllerDefinition(int p)
{
var ret = new ControllerDefinition { Name = "Gameboy Controller" };
for (int i = 0; i < p; i++)
{
ret.BoolButtons.AddRange(
new[] { "Up", "Down", "Left", "Right", "A", "B", "Select", "Start" }
.Select(s => $"P{i + 1} {s}"));
}
return ret;
}
static Sameboy()
{
_gbDefinition = CreateControllerDefinition(1);
_sgbDefinition = CreateControllerDefinition(4);
}
private LibSameboy.Buttons GetButtons(IController c)
{
LibSameboy.Buttons b = 0;
for (int i = _sgb ? 4 : 1; i > 0; i--)
{
if (c.IsPressed($"P{i} Up"))
b |= LibSameboy.Buttons.UP;
if (c.IsPressed($"P{i} Down"))
b |= LibSameboy.Buttons.DOWN;
if (c.IsPressed($"P{i} Left"))
b |= LibSameboy.Buttons.LEFT;
if (c.IsPressed($"P{i} Right"))
b |= LibSameboy.Buttons.RIGHT;
if (c.IsPressed($"P{i} A"))
b |= LibSameboy.Buttons.A;
if (c.IsPressed($"P{i} B"))
b |= LibSameboy.Buttons.B;
if (c.IsPressed($"P{i} Select"))
b |= LibSameboy.Buttons.SELECT;
if (c.IsPressed($"P{i} Start"))
b |= LibSameboy.Buttons.START;
if (i != 1)
b = (LibSameboy.Buttons)((uint)b << 8);
}
return b;
}
#endregion
protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound)
{
return new LibSameboy.FrameInfo
{
Time = 0,
Keys = GetButtons(controller)
};
}

View File

@ -91,6 +91,8 @@ ECL_EXPORT bool Init(bool cgb)
struct MyFrameInfo : public FrameInfo
{
int64_t Time;
uint32_t Keys;
};
static int FrameOverflow;
@ -98,8 +100,7 @@ static int FrameOverflow;
ECL_EXPORT void FrameAdvance(MyFrameInfo &f)
{
GB_set_pixels_output(&GB, f.VideoBuffer);
for (int i = 0; i < (int)GB_KEY_MAX; i++)
GB_set_key_state(&GB, (GB_key_t)i, false);
GB_set_key_state(&GB, f.Keys & 0xff);
sound_start_clock = GB_epoch(&GB);

View File

@ -252,14 +252,12 @@ void GB_run(GB_gameboy_t *gb)
uint64_t GB_run_cycles(GB_gameboy_t *gb, uint32_t cycles)
{
GB_update_joyp(gb);
GB_rtc_run(gb);
uint64_t start = gb->cycles_since_epoch;
uint64_t target = start + cycles;
while (gb->cycles_since_epoch < target) {
GB_run(gb);
if (gb->vblank_just_occured) {
GB_update_joyp(gb);
GB_rtc_run(gb);
}
}
return gb->cycles_since_epoch - start;
}

View File

@ -380,7 +380,7 @@ struct GB_gameboy_internal_s {
/* I/O */
uint32_t *screen;
bool keys[GB_KEY_MAX];
int keys;
/* Timing */
uint64_t cycles_since_epoch;

View File

@ -9,7 +9,7 @@ void GB_update_joyp(GB_gameboy_t *gb)
/* Todo: add delay to key selection */
previous_state = gb->io_registers[GB_IO_JOYP] & 0xF;
key_selection = (gb->io_registers[GB_IO_JOYP] >> 4) & 3;
key_selection = gb->io_registers[GB_IO_JOYP] >> 4 & 3;
gb->io_registers[GB_IO_JOYP] &= 0xF0;
switch (key_selection) {
case 3:
@ -19,24 +19,17 @@ void GB_update_joyp(GB_gameboy_t *gb)
case 2:
/* Direction keys */
for (uint8_t i = 0; i < 4; i++) {
gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i]) << i;
}
gb->io_registers[GB_IO_JOYP] |= ~gb->keys >> 4 & 0xf;
break;
case 1:
/* Other keys */
for (uint8_t i = 0; i < 4; i++) {
gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i + 4]) << i;
}
gb->io_registers[GB_IO_JOYP] |= ~gb->keys & 0xf;
break;
case 0:
/* Todo: verifiy this is correct */
for (uint8_t i = 0; i < 4; i++) {
gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i]) << i;
gb->io_registers[GB_IO_JOYP] |= (!gb->keys[i + 4]) << i;
}
gb->io_registers[GB_IO_JOYP] |= ~(gb->keys >> 4 & gb->keys) & 0xf;
break;
default:
@ -49,8 +42,7 @@ void GB_update_joyp(GB_gameboy_t *gb)
gb->io_registers[GB_IO_JOYP] |= 0xC0; // No SGB support
}
void GB_set_key_state(GB_gameboy_t *gb, GB_key_t index, bool pressed)
void GB_set_key_state(GB_gameboy_t *gb, int keys)
{
assert(index >= 0 && index < GB_KEY_MAX);
gb->keys[index] = pressed;
gb->keys = keys;
}

View File

@ -2,19 +2,7 @@
#define joypad_h
#include "gb_struct_def.h"
typedef enum {
GB_KEY_RIGHT,
GB_KEY_LEFT,
GB_KEY_UP,
GB_KEY_DOWN,
GB_KEY_A,
GB_KEY_B,
GB_KEY_SELECT,
GB_KEY_START,
GB_KEY_MAX
} GB_key_t;
void GB_set_key_state(GB_gameboy_t *gb, GB_key_t index, bool pressed);
void GB_set_key_state(GB_gameboy_t *gb, int keys);
#ifdef GB_INTERNAL
void GB_update_joyp(GB_gameboy_t *gb);