sameboy: input
This commit is contained in:
parent
721a6c0470
commit
1f89158179
BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy
waterbox/sameboy
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue