Starting to work on some api stuff

ngp only for now
This commit is contained in:
nattthebear 2020-05-22 13:53:34 -04:00
parent 9f358bc8cc
commit 39c0402bd8
6 changed files with 322 additions and 7 deletions

View File

@ -6,6 +6,9 @@
#include "mednafen/src/mednafen-driver.h"
#include "mednafen/src/player.h"
#include <stdio.h>
#include <stdarg.h>
namespace Mednafen
{
MDFNGI *MDFNGameInfo = NULL;
@ -17,16 +20,40 @@ namespace Mednafen
}
// mednafen-driver.h
static int curindent = 0;
void MDFN_indent(int indent)
{}
{
curindent += indent;
if(curindent < 0)
{
fprintf(stderr, "MDFN_indent negative!\n");
curindent = 0;
}
}
void MDFN_printf(const char *format, ...) noexcept
{}
{
for (int i = 0; i < curindent; i++)
putchar('\t');
va_list argp;
va_start(argp, format);
vprintf(format, argp);
va_end(argp);
}
void MDFND_OutputNotice(MDFN_NoticeType t, const char* s) noexcept
{}
{
fputs(s, t == MDFN_NOTICE_ERROR ? stderr : stdout);
fputc('\n', t == MDFN_NOTICE_ERROR ? stderr : stdout);
}
void MDFND_OutputInfo(const char* s) noexcept
{}
{
puts(s);
}
void MDFN_Notify(MDFN_NoticeType t, const char* format, ...) noexcept
{}
{
va_list argp;
va_start(argp, format);
vfprintf(t == MDFN_NOTICE_ERROR ? stderr : stdout, format, argp);
}
void MDFND_MidSync(EmulateSpecStruct *espec, const unsigned flags)
{}

269
waterbox/nyma/NymaCore.cpp Normal file
View File

@ -0,0 +1,269 @@
#include "mednafen/src/types.h"
#include <emulibc.h>
#include <waterboxcore.h>
#include <mednafen/mednafen.h>
#include <stdint.h>
#include "mednafen/src/FileStream.h"
#include "nyma.h"
using namespace Mednafen;
#define Game MDFNGameInfo
static EmulateSpecStruct* EES;
static MDFN_Surface* Surf;
static uint32_t* pixels;
static int16_t* samples;
struct InitData
{
const char* FileNameBase;
const char* FileNameExt;
const char* FileNameFull;
};
enum { MAX_PORTS = 16 };
enum { MAX_PORT_DATA = 16 };
static uint8_t InputPortData[MAX_PORTS * MAX_PORT_DATA];
ECL_EXPORT bool Init(const InitData& data)
{
try
{
SetupMDFNGameInfo();
pixels = new uint32_t[Game->fb_width * Game->fb_height];
samples = new int16_t[22050 * 2];
Surf = new MDFN_Surface(
pixels, Game->fb_width, Game->fb_height, Game->fb_width,
MDFN_PixelFormat(MDFN_COLORSPACE_RGB, 0, 8, 16, 24)
);
EES = new EmulateSpecStruct();
EES->surface = Surf;
EES->VideoFormatChanged = true;
EES->LineWidths = new int32_t[Game->fb_height];
EES->SoundBuf = samples;
EES->SoundBufMaxSize = 22050;
EES->SoundFormatChanged = true;
EES->SoundRate = 44100;
GameFile gf({
&NVFS,
"",
std::unique_ptr<Stream>(new FileStream(data.FileNameFull, FileStream::MODE_READ, false)).get(),
data.FileNameExt,
data.FileNameBase,
&NVFS,
"",
data.FileNameBase
});
Game->Load(&gf);
}
catch(...)
{
return false;
}
return true;
}
struct MyFrameInfo: public FrameInfo
{
// true to skip video rendering
int32_t SkipRendering;
// a single MDFN_MSC_* command to run at the start of this frame; 0 if none
int32_t Command;
// raw data for each input port, assumed to be MAX_PORTS * MAX_PORT_DATA long
uint8_t* InputPortData;
};
ECL_EXPORT void FrameAdvance(MyFrameInfo& frame)
{
EES->skip = frame.SkipRendering;
if (frame.Command)
Game->DoSimpleCommand(frame.Command);
memcpy(InputPortData, frame.InputPortData, sizeof(InputPortData));
Game->TransformInput();
Game->Emulate(EES);
EES->VideoFormatChanged = false;
EES->SoundFormatChanged = false;
frame.Cycles = EES->MasterCycles; // TODO: Was this supposed to be total or delta?
memcpy(frame.SoundBuffer, EES->SoundBuf, EES->SoundBufSize * 4);
frame.Samples = EES->SoundBufSize;
// TODO: Use linewidths
int w = EES->DisplayRect.w;
int h = EES->DisplayRect.h;
frame.Width = w;
frame.Height = h;
int srcp = Game->fb_width;
int dstp = Game->fb_height;
uint32_t* src = pixels + EES->DisplayRect.x + EES->DisplayRect.y * srcp;
uint32_t* dst = pixels;
for (int line = 0; line < h; line++)
{
memcpy(dst, src, w * 4);
src += srcp;
dst += dstp;
}
}
ECL_EXPORT void SetLayers(uint64_t layers)
{
Game->SetLayerEnableMask(layers);
}
ECL_EXPORT void GetMemoryAreas(MemoryArea* m)
{}
ECL_EXPORT void SetInputCallback(void (*cb)())
{}
// same information as PortInfo, but easier to marshal
struct NPortInfo
{
const char *ShortName;
const char *FullName;
const char *DefaultDeviceShortName;
struct NDeviceInfo
{
const char *ShortName;
const char *FullName;
const char *Description;
uint32_t Flags;
uint32_t ByteLength;
struct NInput
{
const char *SettingName;
const char *Name;
int16_t ConfigOrder;
uint16_t BitOffset;
InputDeviceInputType Type; // uint8_t
uint8_t Flags;
uint8_t BitSize;
uint8_t _Padding;
union
{
struct
{
const char* ExcludeName;
} Button;
struct
{
// negative, then positive
const char* SettingName[2];
const char* Name[2];
} Axis;
struct
{
struct
{
const char* SettingName;
const char* Name;
const char* Description;
}* Positions;
uint32_t NumPositions;
uint32_t DefaultPosition;
} Switch;
struct
{
struct
{
const char* ShortName;
const char* Name;
int32_t Color; // (msb)0RGB(lsb), -1 for unused.
int32_t _Padding;
}* States;
uint32_t NumStates;
} Status;
};
} Inputs[256];
} Devices[32];
};
NPortInfo PortInfos[MAX_PORTS] = {};
ECL_EXPORT NPortInfo* GetInputDevices()
{
for (unsigned port = 0; port < MAX_PORTS && port < Game->PortInfo.size(); port++)
{
auto& a = PortInfos[port];
auto& x = Game->PortInfo[port];
a.ShortName = x.ShortName;
a.FullName = x.FullName;
a.DefaultDeviceShortName = x.DefaultDevice;
for (unsigned dev = 0; dev < 32 && dev < x.DeviceInfo.size(); dev++)
{
auto& b = a.Devices[dev];
auto& y = x.DeviceInfo[dev];
b.ShortName = y.ShortName;
b.FullName = y.FullName;
b.Description = y.Description;
b.Flags = y.Flags;
b.ByteLength = y.IDII.InputByteSize;
for (unsigned input = 0; input < 256 && input < y.IDII.size(); input++)
{
auto& c = b.Inputs[input];
auto& z = y.IDII[input];
c.SettingName = z.SettingName;
c.Name = z.Name;
c.ConfigOrder = z.ConfigOrder;
c.BitOffset = z.BitOffset;
c.Type = z.Type;
c.Flags = z.Flags;
c.BitSize = z.BitSize;
switch (z.Type)
{
case IDIT_BUTTON:
case IDIT_BUTTON_CAN_RAPID:
c.Button.ExcludeName = z.Button.ExcludeName;
break;
case IDIT_SWITCH:
c.Switch.NumPositions = z.Switch.NumPos;
c.Switch.DefaultPosition = z.Switch.DefPos;
c.Switch.Positions = (decltype(c.Switch.Positions))calloc(z.Switch.NumPos, sizeof(*c.Switch.Positions));
for (unsigned i = 0; i < z.Switch.NumPos; i++)
{
c.Switch.Positions[i].SettingName = z.Switch.Pos[i].SettingName;
c.Switch.Positions[i].Name = z.Switch.Pos[i].Name;
c.Switch.Positions[i].Description = z.Switch.Pos[i].Description;
}
break;
case IDIT_STATUS:
c.Status.NumStates = z.Status.NumStates;
c.Status.States = (decltype(c.Status.States))calloc(z.Status.NumStates, sizeof(*c.Status.States));
for (unsigned i = 0; i < z.Status.NumStates; i++)
{
c.Status.States[i].ShortName = z.Status.States[i].ShortName;
c.Status.States[i].Name = z.Status.States[i].Name;
c.Status.States[i].Color = z.Status.States[i].Color;
}
break;
case IDIT_AXIS:
case IDIT_AXIS_REL:
c.Axis.SettingName[0] = z.Axis.sname_dir[0];
c.Axis.SettingName[1] = z.Axis.sname_dir[1];
c.Axis.Name[0] = z.Axis.name_dir[0];
c.Axis.Name[1] = z.Axis.name_dir[1];
break;
default:
// other types have no extended information
break;
}
}
}
}
return PortInfos;
}
ECL_EXPORT void SetInputDevices(const char** devices)
{
for (unsigned port = 0; port < MAX_PORTS && devices[port]; port++)
{
Game->SetInput(port, devices[port], &InputPortData[port * MAX_PORT_DATA]);
}
}

View File

@ -47,5 +47,6 @@ SRCS := \
$(call cdir,trio) \
$(call cdir,cputest) \
$(call cppdir,compress) \
$(call cppdir,video) \
$(filter-out %generate.cpp,$(call cppdir,sound)) \
Interfaces.cpp
Interfaces.cpp NymaCore.cpp

View File

@ -0,0 +1,4 @@
#pragma once
// the one linked core should set the MDFNGameInfo global
void SetupMDFNGameInfo();

13
waterbox/nyma/ngp.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "mednafen/src/types.h"
#include "nyma.h"
#include <emulibc.h>
#include "mednafen/src/ngp/neopop.h"
using namespace MDFN_IEN_NGP;
extern Mednafen::MDFNGI EmulatedNGP;
void SetupMDFNGameInfo()
{
Mednafen::MDFNGameInfo = &EmulatedNGP;
}

View File

@ -2,6 +2,7 @@ include common.mak
SRCS += \
$(call cppdir,ngp) \
$(call cppdir,hw_cpu/z80-fuse)
$(call cppdir,hw_cpu/z80-fuse) \
ngp.cpp
include ../common.mak