misc code cleanup
This commit is contained in:
parent
37b285fe8d
commit
80698781b1
|
@ -76,7 +76,7 @@ ECL_EXPORT int Init(const char *rom, int romlen, const char *bios, int bioslen)
|
|||
|
||||
ECL_EXPORT void FrameAdvance(FrameInfo* f)
|
||||
{
|
||||
cpu_exec(20000);
|
||||
cpu_exec(6026);
|
||||
f->Samples = 735;
|
||||
f->Width = 320;
|
||||
f->Height = 240;
|
||||
|
|
|
@ -221,7 +221,7 @@ Byte read_P2(void)
|
|||
{
|
||||
int i, si, so, km;
|
||||
|
||||
return 0;
|
||||
return 0xff;
|
||||
// TODO
|
||||
/*if (NeedsPoll)
|
||||
poll_keyboard();
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "ss.h"
|
||||
#include "stream/MemoryStream.h"
|
||||
#include <memory>
|
||||
#include "cdrom/cdromif.h"
|
||||
#include "cdb.h"
|
||||
|
@ -257,26 +256,7 @@ EXPORT void SetVideoParameters(bool correctAspect, bool hBlend, bool hOverscan,
|
|||
Cleanup();
|
||||
}*/
|
||||
|
||||
/*static MDFN_COLD void SaveBackupRAM(void)
|
||||
{
|
||||
FileStream brs(MDFN_MakeFName(MDFNMKF_SAV, 0, "bkr"), FileStream::MODE_WRITE_INPLACE);
|
||||
|
||||
brs.write(BackupRAM, sizeof(BackupRAM));
|
||||
|
||||
brs.close();
|
||||
}
|
||||
|
||||
static MDFN_COLD void LoadBackupRAM(void)
|
||||
{
|
||||
FileStream brs(MDFN_MakeFName(MDFNMKF_SAV, 0, "bkr"), FileStream::MODE_READ);
|
||||
|
||||
brs.read(BackupRAM, sizeof(BackupRAM));
|
||||
}
|
||||
|
||||
static MDFN_COLD void BackupBackupRAM(void)
|
||||
{
|
||||
MDFN_BackupSavFile(10, "bkr");
|
||||
}
|
||||
/*
|
||||
|
||||
static MDFN_COLD void BackupCartNV(void)
|
||||
{
|
||||
|
|
|
@ -1,64 +1,59 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_CDROM_CDROMIF_H
|
||||
#define __MDFN_CDROM_CDROMIF_H
|
||||
|
||||
#include "CDUtility.h"
|
||||
#include "stream/Stream.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
typedef CDUtility::TOC CD_TOC;
|
||||
|
||||
class CDIF
|
||||
{
|
||||
public:
|
||||
|
||||
CDIF();
|
||||
virtual ~CDIF();
|
||||
|
||||
static const int32 LBA_Read_Minimum = -150;
|
||||
static const int32 LBA_Read_Maximum = 449849; // 100 * 75 * 60 - 150 - 1
|
||||
|
||||
inline void ReadTOC(CDUtility::TOC *read_target)
|
||||
{
|
||||
*read_target = disc_toc;
|
||||
}
|
||||
|
||||
virtual void HintReadSector(int32 lba) = 0;
|
||||
virtual bool ReadRawSector(uint8 *buf, int32 lba) = 0; // Reads 2352+96 bytes of data into buf.
|
||||
virtual bool ReadRawSectorPWOnly(uint8* pwbuf, int32 lba, bool hint_fullread) = 0; // Reads 96 bytes(of raw subchannel PW data) into pwbuf.
|
||||
|
||||
// Call for mode 1 or mode 2 form 1 only.
|
||||
bool ValidateRawSector(uint8 *buf);
|
||||
|
||||
// Utility/Wrapped functions
|
||||
// Reads mode 1 and mode2 form 1 sectors(2048 bytes per sector returned)
|
||||
// Will return the type(1, 2) of the first sector read to the buffer supplied, 0 on error
|
||||
int ReadSector(uint8* buf, int32 lba, uint32 sector_count, bool suppress_uncorrectable_message = false);
|
||||
|
||||
// For Mode 1, or Mode 2 Form 1.
|
||||
// No reference counting or whatever is done, so if you destroy the CDIF object before you destroy the returned Stream, things will go BOOM.
|
||||
Stream *MakeStream(int32 lba, uint32 sector_count);
|
||||
|
||||
protected:
|
||||
bool UnrecoverableError;
|
||||
CDUtility::TOC disc_toc;
|
||||
};
|
||||
|
||||
#endif
|
||||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_CDROM_CDROMIF_H
|
||||
#define __MDFN_CDROM_CDROMIF_H
|
||||
|
||||
#include "CDUtility.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
typedef CDUtility::TOC CD_TOC;
|
||||
|
||||
class CDIF
|
||||
{
|
||||
public:
|
||||
|
||||
CDIF();
|
||||
virtual ~CDIF();
|
||||
|
||||
static const int32 LBA_Read_Minimum = -150;
|
||||
static const int32 LBA_Read_Maximum = 449849; // 100 * 75 * 60 - 150 - 1
|
||||
|
||||
inline void ReadTOC(CDUtility::TOC *read_target)
|
||||
{
|
||||
*read_target = disc_toc;
|
||||
}
|
||||
|
||||
virtual void HintReadSector(int32 lba) = 0;
|
||||
virtual bool ReadRawSector(uint8 *buf, int32 lba) = 0; // Reads 2352+96 bytes of data into buf.
|
||||
virtual bool ReadRawSectorPWOnly(uint8* pwbuf, int32 lba, bool hint_fullread) = 0; // Reads 96 bytes(of raw subchannel PW data) into pwbuf.
|
||||
|
||||
// Call for mode 1 or mode 2 form 1 only.
|
||||
bool ValidateRawSector(uint8 *buf);
|
||||
|
||||
// Utility/Wrapped functions
|
||||
// Reads mode 1 and mode2 form 1 sectors(2048 bytes per sector returned)
|
||||
// Will return the type(1, 2) of the first sector read to the buffer supplied, 0 on error
|
||||
int ReadSector(uint8* buf, int32 lba, uint32 sector_count, bool suppress_uncorrectable_message = false);
|
||||
|
||||
protected:
|
||||
bool UnrecoverableError;
|
||||
CDUtility::TOC disc_toc;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -85,219 +85,8 @@ typedef struct
|
|||
#define MDFN_FORMATSTR(...)
|
||||
#define require assert
|
||||
|
||||
enum InputDeviceInputType : uint8
|
||||
{
|
||||
IDIT_BUTTON, // 1-bit
|
||||
IDIT_BUTTON_CAN_RAPID, // 1-bit
|
||||
|
||||
IDIT_SWITCH, // ceil(log2(n))-bit
|
||||
// Current switch position(default 0).
|
||||
// Persistent, and bidirectional communication(can be modified driver side, and Mednafen core and emulation module side)
|
||||
|
||||
IDIT_STATUS, // ceil(log2(n))-bit
|
||||
// emulation module->driver communication
|
||||
|
||||
IDIT_X_AXIS, // (mouse) 16-bits, signed - in-screen/window range: [0.0, nominal_width)
|
||||
IDIT_Y_AXIS, // (mouse) 16-bits, signed - in-screen/window range: [0.0, nominal_height)
|
||||
|
||||
IDIT_X_AXIS_REL, // (mouse) 32-bits, signed
|
||||
IDIT_Y_AXIS_REL, // (mouse) 32-bits, signed
|
||||
|
||||
IDIT_BYTE_SPECIAL,
|
||||
|
||||
IDIT_RESET_BUTTON, // 1-bit
|
||||
|
||||
IDIT_BUTTON_ANALOG, // 16-bits, 0 - 32767
|
||||
|
||||
IDIT_RUMBLE, // 16-bits, lower 8 bits are weak rumble(0-255), next 8 bits are strong rumble(0-255), 0=no rumble, 255=max rumble. Somewhat subjective, too...
|
||||
// It's a rather special case of game module->driver code communication.
|
||||
};
|
||||
|
||||
#define IDIT_BUTTON_ANALOG_FLAG_SQLR 0x00000001 // Denotes analog data that may need to be scaled to ensure a more squareish logical range(for emulated
|
||||
// analog sticks).
|
||||
struct IDIIS_StatusState
|
||||
{
|
||||
const char *ShortName;
|
||||
const char *Name;
|
||||
int32 Color; // (msb)0RGB(lsb), -1 for unused.
|
||||
};
|
||||
struct InputDeviceInputInfoStruct
|
||||
{
|
||||
const char *SettingName; // No spaces, shouldbe all a-z0-9 and _. Definitely no ~!
|
||||
const char *Name;
|
||||
int ConfigOrder; // Configuration order during in-game config process, -1 for no config.
|
||||
InputDeviceInputType Type;
|
||||
const char *ExcludeName; // SettingName of a button that can't be pressed at the same time as this button
|
||||
// due to physical limitations.
|
||||
uint8 Flags;
|
||||
uint8 BitSize;
|
||||
uint16 BitOffset;
|
||||
|
||||
union {
|
||||
struct
|
||||
{
|
||||
const char *const *SwitchPosName; //
|
||||
uint32 SwitchNumPos;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
const IDIIS_StatusState *StatusStates;
|
||||
uint32 StatusNumStates;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct IDIISG : public std::vector<InputDeviceInputInfoStruct>
|
||||
{
|
||||
IDIISG()
|
||||
{
|
||||
InputByteSize = 0;
|
||||
}
|
||||
|
||||
IDIISG(std::initializer_list<InputDeviceInputInfoStruct> l) : std::vector<InputDeviceInputInfoStruct>(l)
|
||||
{
|
||||
size_t bit_offset = 0;
|
||||
|
||||
for (auto &idii : *this)
|
||||
{
|
||||
size_t bit_size = 0;
|
||||
size_t bit_align = 1;
|
||||
|
||||
switch (idii.Type)
|
||||
{
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
|
||||
case IDIT_BUTTON:
|
||||
case IDIT_BUTTON_CAN_RAPID:
|
||||
case IDIT_RESET_BUTTON:
|
||||
bit_size = 1;
|
||||
break;
|
||||
|
||||
case IDIT_SWITCH:
|
||||
bit_size = ceil(log2(idii.SwitchNumPos));
|
||||
break;
|
||||
|
||||
case IDIT_STATUS:
|
||||
bit_size = ceil(log2(idii.StatusNumStates));
|
||||
break;
|
||||
|
||||
case IDIT_X_AXIS:
|
||||
case IDIT_Y_AXIS:
|
||||
bit_size = 16;
|
||||
bit_align = 8;
|
||||
break;
|
||||
|
||||
case IDIT_X_AXIS_REL:
|
||||
case IDIT_Y_AXIS_REL:
|
||||
bit_size = 32;
|
||||
bit_align = 8;
|
||||
break;
|
||||
|
||||
case IDIT_BYTE_SPECIAL:
|
||||
bit_size = 8;
|
||||
bit_align = 8;
|
||||
break;
|
||||
|
||||
case IDIT_BUTTON_ANALOG:
|
||||
bit_size = 16;
|
||||
bit_align = 8;
|
||||
break;
|
||||
|
||||
case IDIT_RUMBLE:
|
||||
bit_size = 16;
|
||||
bit_align = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
bit_offset = (bit_offset + (bit_align - 1)) & ~(bit_align - 1);
|
||||
|
||||
// printf("%s, %zu(%zu)\n", idii.SettingName, bit_offset, bit_offset / 8);
|
||||
|
||||
idii.BitSize = bit_size;
|
||||
idii.BitOffset = bit_offset;
|
||||
|
||||
assert(idii.BitSize == bit_size);
|
||||
assert(idii.BitOffset == bit_offset);
|
||||
|
||||
bit_offset += bit_size;
|
||||
}
|
||||
|
||||
InputByteSize = (bit_offset + 7) / 8;
|
||||
}
|
||||
uint32 InputByteSize;
|
||||
};
|
||||
|
||||
struct IDIIS_Switch : public InputDeviceInputInfoStruct
|
||||
{
|
||||
IDIIS_Switch(const char *sname, const char *name, int co, const char *const *spn, const uint32 spn_num)
|
||||
{
|
||||
SettingName = sname;
|
||||
Name = name;
|
||||
ConfigOrder = co;
|
||||
Type = IDIT_SWITCH;
|
||||
|
||||
ExcludeName = NULL;
|
||||
Flags = 0;
|
||||
SwitchPosName = spn;
|
||||
SwitchNumPos = spn_num;
|
||||
}
|
||||
};
|
||||
|
||||
struct IDIIS_Status : public InputDeviceInputInfoStruct
|
||||
{
|
||||
IDIIS_Status(const char *sname, const char *name, const IDIIS_StatusState *ss, const uint32 ss_num)
|
||||
{
|
||||
SettingName = sname;
|
||||
Name = name;
|
||||
ConfigOrder = -1;
|
||||
Type = IDIT_STATUS;
|
||||
|
||||
ExcludeName = NULL;
|
||||
Flags = 0;
|
||||
StatusStates = ss;
|
||||
StatusNumStates = ss_num;
|
||||
}
|
||||
};
|
||||
|
||||
struct InputDeviceInfoStruct
|
||||
{
|
||||
const char *ShortName;
|
||||
const char *FullName;
|
||||
const char *Description;
|
||||
|
||||
const IDIISG &IDII;
|
||||
|
||||
unsigned Flags;
|
||||
|
||||
enum
|
||||
{
|
||||
FLAG_KEYBOARD = (1U << 0)
|
||||
};
|
||||
};
|
||||
|
||||
struct InputPortInfoStruct
|
||||
{
|
||||
const char *ShortName;
|
||||
const char *FullName;
|
||||
const std::vector<InputDeviceInfoStruct> &DeviceInfo;
|
||||
const char *DefaultDevice; // Default device for this port.
|
||||
};
|
||||
|
||||
#include "endian.h"
|
||||
|
||||
inline char *strdup(const char *p)
|
||||
{
|
||||
char *ret = (char *)malloc(strlen(p) + 1);
|
||||
if (ret)
|
||||
strcpy(ret, p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include "stream/Stream.h"
|
||||
#include "stream/MemoryStream.h"
|
||||
#include "math_ops.h"
|
||||
|
||||
#include "../emulibc/emulibc.h"
|
||||
|
|
|
@ -128,41 +128,4 @@ uint8 IODevice_3DPad::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asser
|
|||
return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted);
|
||||
}
|
||||
|
||||
static const char* const ModeSwitchPositions[] =
|
||||
{
|
||||
gettext_noop("Digital(+)"),
|
||||
gettext_noop("Analog(○)"),
|
||||
};
|
||||
|
||||
IDIISG IODevice_3DPad_IDII =
|
||||
{
|
||||
{ "up", "D-Pad UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "down", "D-Pad DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "D-Pad LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
{ "right", "D-Pad RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
|
||||
{ "b", "B", 6, IDIT_BUTTON },
|
||||
{ "c", "C", 7, IDIT_BUTTON },
|
||||
{ "a", "A", 5, IDIT_BUTTON },
|
||||
{ "start", "START", 4, IDIT_BUTTON },
|
||||
|
||||
{ "z", "Z", 10, IDIT_BUTTON },
|
||||
{ "y", "Y", 9, IDIT_BUTTON },
|
||||
{ "x", "X", 8, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
IDIIS_Switch("mode", "Mode", 17, ModeSwitchPositions, sizeof(ModeSwitchPositions) / sizeof(ModeSwitchPositions[0])),
|
||||
|
||||
{ "analog_left", "Analog LEFT ←", 15, IDIT_BUTTON_ANALOG },
|
||||
{ "analog_right", "Analog RIGHT →", 16, IDIT_BUTTON_ANALOG },
|
||||
{ "analog_up", "Analog UP ↑", 13, IDIT_BUTTON_ANALOG },
|
||||
{ "analog_down", "Analog DOWN ↓", 14, IDIT_BUTTON_ANALOG },
|
||||
|
||||
{ "rs", "Right Shoulder (Analog)", 12, IDIT_BUTTON_ANALOG },
|
||||
{ "ls", "Left Shoulder (Analog)", 11, IDIT_BUTTON_ANALOG },
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,56 +1,53 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* 3dpad.h:
|
||||
** Copyright (C) 2016-2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_3DPAD_H
|
||||
#define __MDFN_SS_INPUT_3DPAD_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_3DPad final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_3DPad() MDFN_COLD;
|
||||
virtual ~IODevice_3DPad() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
uint16 dbuttons;
|
||||
uint8 thumb[2];
|
||||
uint8 shoulder[2];
|
||||
|
||||
uint8 buffer[0x10];
|
||||
uint8 data_out;
|
||||
bool tl;
|
||||
int8 phase;
|
||||
bool mode;
|
||||
};
|
||||
|
||||
|
||||
extern IDIISG IODevice_3DPad_IDII;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* 3dpad.h:
|
||||
** Copyright (C) 2016-2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_3DPAD_H
|
||||
#define __MDFN_SS_INPUT_3DPAD_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_3DPad final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_3DPad() MDFN_COLD;
|
||||
virtual ~IODevice_3DPad() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
uint16 dbuttons;
|
||||
uint8 thumb[2];
|
||||
uint8 shoulder[2];
|
||||
|
||||
uint8 buffer[0x10];
|
||||
uint8 data_out;
|
||||
bool tl;
|
||||
int8 phase;
|
||||
bool mode;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,81 +1,57 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* gamepad.cpp - Digital Gamepad Emulation
|
||||
** Copyright (C) 2015-2017 Mednafen Team
|
||||
**
|
||||
** 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 "common.h"
|
||||
#include "gamepad.h"
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
IODevice_Gamepad::IODevice_Gamepad() : buttons(~3)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
IODevice_Gamepad::~IODevice_Gamepad()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IODevice_Gamepad::Power(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IODevice_Gamepad::UpdateInput(const uint8* data, const int32 time_elapsed)
|
||||
{
|
||||
buttons = (~(data[0] | (data[1] << 8))) &~ 0x3000;
|
||||
}
|
||||
|
||||
uint8 IODevice_Gamepad::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted)
|
||||
{
|
||||
uint8 tmp;
|
||||
|
||||
tmp = (buttons >> ((smpc_out >> 5) << 2)) & 0xF;
|
||||
|
||||
return 0x10 | (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted);
|
||||
}
|
||||
|
||||
IDIISG IODevice_Gamepad_IDII =
|
||||
{
|
||||
{ "z", "Z", 10, IDIT_BUTTON },
|
||||
{ "y", "Y", 9, IDIT_BUTTON },
|
||||
{ "x", "X", 8, IDIT_BUTTON },
|
||||
{ "rs", "Right Shoulder", 12, IDIT_BUTTON },
|
||||
|
||||
{ "up", "UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "down", "DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
{ "right", "RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
|
||||
{ "b", "B", 6, IDIT_BUTTON },
|
||||
{ "c", "C", 7, IDIT_BUTTON },
|
||||
{ "a", "A", 5, IDIT_BUTTON },
|
||||
{ "start", "START", 4, IDIT_BUTTON },
|
||||
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ "ls", "Left Shoulder", 11, IDIT_BUTTON },
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* gamepad.cpp - Digital Gamepad Emulation
|
||||
** Copyright (C) 2015-2017 Mednafen Team
|
||||
**
|
||||
** 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 "common.h"
|
||||
#include "gamepad.h"
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
IODevice_Gamepad::IODevice_Gamepad() : buttons(~3)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
IODevice_Gamepad::~IODevice_Gamepad()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IODevice_Gamepad::Power(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IODevice_Gamepad::UpdateInput(const uint8* data, const int32 time_elapsed)
|
||||
{
|
||||
buttons = (~(data[0] | (data[1] << 8))) &~ 0x3000;
|
||||
}
|
||||
|
||||
uint8 IODevice_Gamepad::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted)
|
||||
{
|
||||
uint8 tmp;
|
||||
|
||||
tmp = (buttons >> ((smpc_out >> 5) << 2)) & 0xF;
|
||||
|
||||
return 0x10 | (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,48 +1,45 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* gamepad.h:
|
||||
** Copyright (C) 2015-2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_GAMEPAD_H
|
||||
#define __MDFN_SS_INPUT_GAMEPAD_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_Gamepad final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_Gamepad() MDFN_COLD;
|
||||
virtual ~IODevice_Gamepad() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
uint16 buttons;
|
||||
};
|
||||
|
||||
|
||||
extern IDIISG IODevice_Gamepad_IDII;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* gamepad.h:
|
||||
** Copyright (C) 2015-2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_GAMEPAD_H
|
||||
#define __MDFN_SS_INPUT_GAMEPAD_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_Gamepad final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_Gamepad() MDFN_COLD;
|
||||
virtual ~IODevice_Gamepad() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
uint16 buttons;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,397 +1,231 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* keyboard.cpp:
|
||||
** Copyright (C) 2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
// TODO: Debouncing?
|
||||
|
||||
//
|
||||
// PS/2 keyboard adapter seems to do PS/2 processing near/at the end of a Saturn-side read sequence, which creates about 1 frame of extra latency
|
||||
// in practice. We handle things a bit differently here, to avoid the latency.
|
||||
//
|
||||
// Also, the PS/2 adapter seems to set the typematic delay to around 250ms, but we emulate it here as 400ms, as 250ms is
|
||||
// a tad bit too short. It can be changed to 250ms by adjusting a single #if statement, though.
|
||||
//
|
||||
// During testing, a couple of early-1990s PS/2 keyboards malfunctioned and failed to work with the PS/2 adapter.
|
||||
// Not sure why, maybe a power draw issue?
|
||||
//
|
||||
// The keyboard emulated doesn't have special Windows-keyboard keys, as they don't appear to work correctly with the PS/2 adapter
|
||||
// (scancode field is updated, but no make nor break bits are set to 1), and it's good to have some non-shared keys for input grabbing toggling purposes...
|
||||
//
|
||||
//
|
||||
|
||||
// make and break bits should not both be set to 1 at the same time.
|
||||
// pause is special
|
||||
// new key press halts repeat of held key, and it doesn't restart even if new key is released.
|
||||
//
|
||||
|
||||
#include "common.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
IODevice_Keyboard::IODevice_Keyboard() : phys{0,0,0,0}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
IODevice_Keyboard::~IODevice_Keyboard()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IODevice_Keyboard::Power(void)
|
||||
{
|
||||
phase = -1;
|
||||
tl = true;
|
||||
data_out = 0x01;
|
||||
|
||||
simbutt = simbutt_pend = 0;
|
||||
lock = lock_pend = 0;
|
||||
|
||||
mkbrk_pend = 0;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
//memcpy(processed, phys, sizeof(processed));
|
||||
memset(processed, 0, sizeof(processed));
|
||||
memset(fifo, 0, sizeof(fifo));
|
||||
fifo_rdp = 0;
|
||||
fifo_wrp = 0;
|
||||
fifo_cnt = 0;
|
||||
|
||||
rep_sc = -1;
|
||||
rep_dcnt = 0;
|
||||
}
|
||||
|
||||
void IODevice_Keyboard::UpdateInput(const uint8* data, const int32 time_elapsed)
|
||||
{
|
||||
phys[0] = MDFN_de64lsb(&data[0x00]);
|
||||
phys[1] = MDFN_de64lsb(&data[0x08]);
|
||||
phys[2] = MDFN_de16lsb(&data[0x10]);
|
||||
phys[3] = 0;
|
||||
//
|
||||
if(rep_dcnt > 0)
|
||||
rep_dcnt -= time_elapsed;
|
||||
|
||||
for(unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
uint64 tmp = phys[i] ^ processed[i];
|
||||
unsigned bp;
|
||||
|
||||
while((bp = (63 ^ MDFN_lzcount64(tmp))) < 64)
|
||||
{
|
||||
const uint64 mask = ((uint64)1 << bp);
|
||||
const int sc = ((i << 6) + bp);
|
||||
|
||||
if(fifo_cnt >= (fifo_size - (sc == 0x82)))
|
||||
goto fifo_oflow_abort;
|
||||
|
||||
if(phys[i] & mask)
|
||||
{
|
||||
rep_sc = sc;
|
||||
#if 1
|
||||
rep_dcnt = 400000;
|
||||
#else
|
||||
rep_dcnt = 250000;
|
||||
#endif
|
||||
fifo[fifo_wrp] = 0x800 | sc;
|
||||
fifo_wrp = (fifo_wrp + 1) % fifo_size;
|
||||
fifo_cnt++;
|
||||
}
|
||||
|
||||
if(!(phys[i] & mask) == (sc != 0x82))
|
||||
{
|
||||
if(rep_sc == sc)
|
||||
rep_sc = -1;
|
||||
|
||||
fifo[fifo_wrp] = 0x100 | sc;
|
||||
fifo_wrp = (fifo_wrp + 1) % fifo_size;
|
||||
fifo_cnt++;
|
||||
}
|
||||
|
||||
processed[i] = (processed[i] & ~mask) | (phys[i] & mask);
|
||||
tmp &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
if(rep_sc >= 0)
|
||||
{
|
||||
while(rep_dcnt <= 0)
|
||||
{
|
||||
if(fifo_cnt >= fifo_size)
|
||||
goto fifo_oflow_abort;
|
||||
|
||||
fifo[fifo_wrp] = 0x800 | rep_sc;
|
||||
fifo_wrp = (fifo_wrp + 1) % fifo_size;
|
||||
fifo_cnt++;
|
||||
|
||||
rep_dcnt += 33333;
|
||||
}
|
||||
}
|
||||
|
||||
fifo_oflow_abort:;
|
||||
}
|
||||
|
||||
void IODevice_Keyboard::UpdateOutput(uint8* data)
|
||||
{
|
||||
data[0x12] = lock;
|
||||
}
|
||||
|
||||
uint8 IODevice_Keyboard::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted)
|
||||
{
|
||||
if(smpc_out & 0x40)
|
||||
{
|
||||
phase = -1;
|
||||
tl = true;
|
||||
data_out = 0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((bool)(smpc_out & 0x20) != tl)
|
||||
{
|
||||
tl = !tl;
|
||||
phase += (phase < 11);
|
||||
|
||||
if(!phase)
|
||||
{
|
||||
if(mkbrk_pend == (uint8)mkbrk_pend && fifo_cnt)
|
||||
{
|
||||
mkbrk_pend = fifo[fifo_rdp];
|
||||
fifo_rdp = (fifo_rdp + 1) % fifo_size;
|
||||
fifo_cnt--;
|
||||
|
||||
bool p = mkbrk_pend & 0x800;
|
||||
|
||||
switch(mkbrk_pend & 0xFF)
|
||||
{
|
||||
case 0x89: /* Up */ simbutt_pend = simbutt & ~(1 << 0); simbutt_pend &= ~(p << 1); simbutt_pend |= (p << 0); break;
|
||||
case 0x8A: /*Down */ simbutt_pend = simbutt & ~(1 << 1); simbutt_pend &= ~(p << 0); simbutt_pend |= (p << 1); break;
|
||||
case 0x86: /*Left */ simbutt_pend = simbutt & ~(1 << 2); simbutt_pend &= ~(p << 3); simbutt_pend |= (p << 2); break;
|
||||
case 0x8D: /*Right*/ simbutt_pend = simbutt & ~(1 << 3); simbutt_pend &= ~(p << 2); simbutt_pend |= (p << 3); break;
|
||||
case 0x22: /* X */ simbutt_pend = simbutt & ~(1 << 4); simbutt_pend |= (p << 4); break;
|
||||
case 0x21: /* C */ simbutt_pend = simbutt & ~(1 << 5); simbutt_pend |= (p << 5); break;
|
||||
case 0x1A: /* Z */ simbutt_pend = simbutt & ~(1 << 6); simbutt_pend |= (p << 6); break;
|
||||
case 0x76: /* Esc */ simbutt_pend = simbutt & ~(1 << 7); simbutt_pend |= (p << 7); break;
|
||||
case 0x23: /* D */ simbutt_pend = simbutt & ~(1 << 8); simbutt_pend |= (p << 8); break;
|
||||
case 0x1B: /* S */ simbutt_pend = simbutt & ~(1 << 9); simbutt_pend |= (p << 9); break;
|
||||
case 0x1C: /* A */ simbutt_pend = simbutt & ~(1 << 10); simbutt_pend |= (p << 10); break;
|
||||
case 0x24: /* E */ simbutt_pend = simbutt & ~(1 << 11); simbutt_pend |= (p << 11); break;
|
||||
case 0x15: /* Q */ simbutt_pend = simbutt & ~(1 << 15); simbutt_pend |= (p << 15); break;
|
||||
|
||||
case 0x7E: /* Scrl */ lock_pend = lock ^ (p ? LOCK_SCROLL : 0); break;
|
||||
case 0x77: /* Num */ lock_pend = lock ^ (p ? LOCK_NUM : 0); break;
|
||||
case 0x58: /* Caps */ lock_pend = lock ^ (p ? LOCK_CAPS : 0); break;
|
||||
}
|
||||
}
|
||||
buffer[ 0] = 0x3;
|
||||
buffer[ 1] = 0x4;
|
||||
buffer[ 2] = (((simbutt_pend >> 0) ^ 0xF) & 0xF);
|
||||
buffer[ 3] = (((simbutt_pend >> 4) ^ 0xF) & 0xF);
|
||||
buffer[ 4] = (((simbutt_pend >> 8) ^ 0xF) & 0xF);
|
||||
buffer[ 5] = (((simbutt_pend >> 12) ^ 0xF) & 0x8) | 0x0;
|
||||
buffer[ 6] = lock_pend;
|
||||
buffer[ 7] = ((mkbrk_pend >> 8) & 0xF) | 0x6;
|
||||
buffer[ 8] = (mkbrk_pend >> 4) & 0xF;
|
||||
buffer[ 9] = (mkbrk_pend >> 0) & 0xF;
|
||||
buffer[10] = 0x0;
|
||||
buffer[11] = 0x1;
|
||||
}
|
||||
|
||||
if(phase == 9)
|
||||
{
|
||||
mkbrk_pend = (uint8)mkbrk_pend;
|
||||
lock = lock_pend;
|
||||
simbutt = simbutt_pend;
|
||||
}
|
||||
|
||||
data_out = buffer[phase];
|
||||
}
|
||||
}
|
||||
|
||||
return (smpc_out & (smpc_out_asserted | 0xE0)) | (((tl << 4) | data_out) &~ smpc_out_asserted);
|
||||
}
|
||||
|
||||
static const IDIIS_StatusState Lock_SS[] =
|
||||
{
|
||||
{ "off", gettext_noop("Off") },
|
||||
{ "on", gettext_noop("On") },
|
||||
};
|
||||
|
||||
const IDIISG IODevice_Keyboard_US101_IDII =
|
||||
{
|
||||
/* 0x00 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x01 */ { "f9", "F9", -1, IDIT_BUTTON },
|
||||
/* 0x02 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x03 */ { "f5", "F5", -1, IDIT_BUTTON },
|
||||
/* 0x04 */ { "f3", "F3", -1, IDIT_BUTTON },
|
||||
/* 0x05 */ { "f1", "F1", -1, IDIT_BUTTON },
|
||||
/* 0x06 */ { "f2", "F2", -1, IDIT_BUTTON },
|
||||
/* 0x07 */ { "f12", "F12", -1, IDIT_BUTTON },
|
||||
/* 0x08 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x09 */ { "f10", "F10", -1, IDIT_BUTTON },
|
||||
/* 0x0A */ { "f8", "F8", -1, IDIT_BUTTON },
|
||||
/* 0x0B */ { "f6", "F6", -1, IDIT_BUTTON },
|
||||
/* 0x0C */ { "f4", "F4", -1, IDIT_BUTTON },
|
||||
/* 0x0D */ { "tab", "Tab", -1, IDIT_BUTTON },
|
||||
/* 0x0E */ { "grave", "Grave `", -1, IDIT_BUTTON },
|
||||
/* 0x0F */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
|
||||
/* 0x10 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x11 */ { "lalt", "Left Alt", -1, IDIT_BUTTON },
|
||||
/* 0x12 */ { "lshift", "Left Shift", -1, IDIT_BUTTON },
|
||||
/* 0x13 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x14 */ { "lctrl", "Left Ctrl", -1, IDIT_BUTTON },
|
||||
/* 0x15 */ { "q", "Q", -1, IDIT_BUTTON },
|
||||
/* 0x16 */ { "1", "1(One)", -1, IDIT_BUTTON },
|
||||
/* 0x17 */ { "ralt", "Right Alt", -1, IDIT_BUTTON },
|
||||
/* 0x18 */ { "rctrl", "Right Ctrl", -1, IDIT_BUTTON },
|
||||
/* 0x19 */ { "kp_enter", "Keypad Enter", -1, IDIT_BUTTON },
|
||||
/* 0x1A */ { "z", "Z", -1, IDIT_BUTTON },
|
||||
/* 0x1B */ { "s", "S", -1, IDIT_BUTTON },
|
||||
/* 0x1C */ { "a", "A", -1, IDIT_BUTTON },
|
||||
/* 0x1D */ { "w", "W", -1, IDIT_BUTTON },
|
||||
/* 0x1E */ { "2", "2", -1, IDIT_BUTTON },
|
||||
/* 0x1F */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
|
||||
/* 0x20 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x21 */ { "c", "C", -1, IDIT_BUTTON },
|
||||
/* 0x22 */ { "x", "X", -1, IDIT_BUTTON },
|
||||
/* 0x23 */ { "d", "D", -1, IDIT_BUTTON },
|
||||
/* 0x24 */ { "e", "E", -1, IDIT_BUTTON },
|
||||
/* 0x25 */ { "4", "4", -1, IDIT_BUTTON },
|
||||
/* 0x26 */ { "3", "3", -1, IDIT_BUTTON },
|
||||
/* 0x27 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x28 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x29 */ { "space", "Space", -1, IDIT_BUTTON },
|
||||
/* 0x2A */ { "v", "V", -1, IDIT_BUTTON },
|
||||
/* 0x2B */ { "f", "F", -1, IDIT_BUTTON },
|
||||
/* 0x2C */ { "t", "T", -1, IDIT_BUTTON },
|
||||
/* 0x2D */ { "r", "R", -1, IDIT_BUTTON },
|
||||
/* 0x2E */ { "5", "5", -1, IDIT_BUTTON },
|
||||
/* 0x2F */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
|
||||
/* 0x30 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x31 */ { "n", "N", -1, IDIT_BUTTON },
|
||||
/* 0x32 */ { "b", "B", -1, IDIT_BUTTON },
|
||||
/* 0x33 */ { "h", "H", -1, IDIT_BUTTON },
|
||||
/* 0x34 */ { "g", "G", -1, IDIT_BUTTON },
|
||||
/* 0x35 */ { "y", "Y", -1, IDIT_BUTTON },
|
||||
/* 0x36 */ { "6", "6", -1, IDIT_BUTTON },
|
||||
/* 0x37 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x38 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x39 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x3A */ { "m", "M", -1, IDIT_BUTTON },
|
||||
/* 0x3B */ { "j", "J", -1, IDIT_BUTTON },
|
||||
/* 0x3C */ { "u", "U", -1, IDIT_BUTTON },
|
||||
/* 0x3D */ { "7", "7", -1, IDIT_BUTTON },
|
||||
/* 0x3E */ { "8", "8", -1, IDIT_BUTTON },
|
||||
/* 0x3F */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
|
||||
/* 0x40 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x41 */ { "comma", "Comma ,", -1, IDIT_BUTTON },
|
||||
/* 0x42 */ { "k", "K", -1, IDIT_BUTTON },
|
||||
/* 0x43 */ { "i", "I", -1, IDIT_BUTTON },
|
||||
/* 0x44 */ { "o", "O", -1, IDIT_BUTTON },
|
||||
/* 0x45 */ { "0", "0(Zero)", -1, IDIT_BUTTON },
|
||||
/* 0x46 */ { "9", "9", -1, IDIT_BUTTON },
|
||||
/* 0x47 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x48 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x49 */ { "period", "Period .", -1, IDIT_BUTTON },
|
||||
/* 0x4A */ { "slash", "Slash /", -1, IDIT_BUTTON },
|
||||
/* 0x4B */ { "l", "L", -1, IDIT_BUTTON },
|
||||
/* 0x4C */ { "semicolon", "Semicolon ;", -1, IDIT_BUTTON },
|
||||
/* 0x4D */ { "p", "P", -1, IDIT_BUTTON },
|
||||
/* 0x4E */ { "Minus", "Minus -", -1, IDIT_BUTTON },
|
||||
/* 0x4F */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
|
||||
/* 0x50 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x51 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x52 */ { "quote", "Quote '", -1, IDIT_BUTTON },
|
||||
/* 0x53 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x54 */ { "leftbracket", "Left Bracket [", -1, IDIT_BUTTON },
|
||||
/* 0x55 */ { "equals", "Equals =", -1, IDIT_BUTTON },
|
||||
/* 0x56 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x57 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x58 */ { "capslock", "Caps Lock", -1, IDIT_BUTTON },
|
||||
/* 0x59 */ { "rshift", "Right Shift", -1, IDIT_BUTTON },
|
||||
/* 0x5A */ { "enter", "Enter", -1, IDIT_BUTTON },
|
||||
/* 0x5B */ { "rightbracket", "Right Bracket ]", -1, IDIT_BUTTON },
|
||||
/* 0x5C */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x5D */ { "backslash", "Backslash \\", -1, IDIT_BUTTON },
|
||||
/* 0x5E */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x5F */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
|
||||
/* 0x60 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x61 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x62 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x63 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x64 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x65 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x66 */ { "backspace", "Backspace", -1, IDIT_BUTTON },
|
||||
/* 0x67 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x68 */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x69 */ { "kp_end", "Keypad End/1", -1, IDIT_BUTTON },
|
||||
/* 0x6A */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x6B */ { "kp_left", "Keypad Left/4", -1, IDIT_BUTTON },
|
||||
/* 0x6C */ { "kp_home", "Keypad Home/7", -1, IDIT_BUTTON },
|
||||
/* 0x6D */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x6E */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x6F */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
|
||||
/* 0x70 */ { "kp_insert", "Keypad Insert/0", -1, IDIT_BUTTON },
|
||||
/* 0x71 */ { "kp_delete", "Keypad Delete", -1, IDIT_BUTTON },
|
||||
/* 0x72 */ { "kp_down", "Keypad Down/2", -1, IDIT_BUTTON },
|
||||
/* 0x73 */ { "kp_center", "Keypad Center/5", -1, IDIT_BUTTON },
|
||||
/* 0x74 */ { "kp_right", "Keypad Right/6", -1, IDIT_BUTTON },
|
||||
/* 0x75 */ { "kp_up", "Keypad Up/8", -1, IDIT_BUTTON },
|
||||
/* 0x76 */ { "esc", "Escape", -1, IDIT_BUTTON },
|
||||
/* 0x77 */ { "numlock", "Num Lock", -1, IDIT_BUTTON },
|
||||
/* 0x78 */ { "f11", "F11", -1, IDIT_BUTTON },
|
||||
/* 0x79 */ { "kp_plus", "Keypad Plus", -1, IDIT_BUTTON },
|
||||
/* 0x7A */ { "kp_pagedown", "Keypad Pagedown/3", -1, IDIT_BUTTON },
|
||||
/* 0x7B */ { "kp_minus", "Keypad Minus", -1, IDIT_BUTTON },
|
||||
/* 0x7C */ { "kp_asterisk", "Keypad Asterisk(Multiply)", -1, IDIT_BUTTON },
|
||||
/* 0x7D */ { "kp_pageup", "Keypad Pageup/9", -1, IDIT_BUTTON },
|
||||
/* 0x7E */ { "scrolllock", "Scroll Lock", -1, IDIT_BUTTON },
|
||||
/* 0x7F */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
|
||||
/* 0x80 */ { "kp_slash", "Keypad Slash(Divide)", -1, IDIT_BUTTON },
|
||||
/* 0x81 */ { "insert", "Insert", -1, IDIT_BUTTON },
|
||||
/* 0x82 */ { "pause", "Pause", -1, IDIT_BUTTON },
|
||||
/* 0x83 */ { "f7", "F7", -1, IDIT_BUTTON },
|
||||
/* 0x84 */ { "printscreen", "Print Screen", -1, IDIT_BUTTON },
|
||||
/* 0x85 */ { "delete", "Delete", -1, IDIT_BUTTON },
|
||||
/* 0x86 */ { "left", "Cursor Left", -1, IDIT_BUTTON },
|
||||
/* 0x87 */ { "home", "Home", -1, IDIT_BUTTON },
|
||||
/* 0x88 */ { "end", "End", -1, IDIT_BUTTON },
|
||||
/* 0x89 */ { "up", "Up", -1, IDIT_BUTTON },
|
||||
/* 0x8A */ { "down", "Down", -1, IDIT_BUTTON },
|
||||
/* 0x8B */ { "pageup", "Page Up", -1, IDIT_BUTTON },
|
||||
/* 0x8C */ { "pagedown", "Page Down", -1, IDIT_BUTTON },
|
||||
/* 0x8D */ { "right", "Right", -1, IDIT_BUTTON },
|
||||
/* 0x8E */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
/* 0x8F */ { NULL, "empty", -1, IDIT_BUTTON },
|
||||
|
||||
IDIIS_Status("scrolllock_status", "Scroll Lock", Lock_SS, sizeof(Lock_SS) / sizeof(Lock_SS[0])),
|
||||
IDIIS_Status("numlock_status", "Num Lock", Lock_SS, sizeof(Lock_SS) / sizeof(Lock_SS[0])),
|
||||
IDIIS_Status("capslock_status", "Caps Lock", Lock_SS, sizeof(Lock_SS) / sizeof(Lock_SS[0]))
|
||||
};
|
||||
|
||||
}
|
||||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* keyboard.cpp:
|
||||
** Copyright (C) 2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
// TODO: Debouncing?
|
||||
|
||||
//
|
||||
// PS/2 keyboard adapter seems to do PS/2 processing near/at the end of a Saturn-side read sequence, which creates about 1 frame of extra latency
|
||||
// in practice. We handle things a bit differently here, to avoid the latency.
|
||||
//
|
||||
// Also, the PS/2 adapter seems to set the typematic delay to around 250ms, but we emulate it here as 400ms, as 250ms is
|
||||
// a tad bit too short. It can be changed to 250ms by adjusting a single #if statement, though.
|
||||
//
|
||||
// During testing, a couple of early-1990s PS/2 keyboards malfunctioned and failed to work with the PS/2 adapter.
|
||||
// Not sure why, maybe a power draw issue?
|
||||
//
|
||||
// The keyboard emulated doesn't have special Windows-keyboard keys, as they don't appear to work correctly with the PS/2 adapter
|
||||
// (scancode field is updated, but no make nor break bits are set to 1), and it's good to have some non-shared keys for input grabbing toggling purposes...
|
||||
//
|
||||
//
|
||||
|
||||
// make and break bits should not both be set to 1 at the same time.
|
||||
// pause is special
|
||||
// new key press halts repeat of held key, and it doesn't restart even if new key is released.
|
||||
//
|
||||
|
||||
#include "common.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
IODevice_Keyboard::IODevice_Keyboard() : phys{0,0,0,0}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
IODevice_Keyboard::~IODevice_Keyboard()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IODevice_Keyboard::Power(void)
|
||||
{
|
||||
phase = -1;
|
||||
tl = true;
|
||||
data_out = 0x01;
|
||||
|
||||
simbutt = simbutt_pend = 0;
|
||||
lock = lock_pend = 0;
|
||||
|
||||
mkbrk_pend = 0;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
//memcpy(processed, phys, sizeof(processed));
|
||||
memset(processed, 0, sizeof(processed));
|
||||
memset(fifo, 0, sizeof(fifo));
|
||||
fifo_rdp = 0;
|
||||
fifo_wrp = 0;
|
||||
fifo_cnt = 0;
|
||||
|
||||
rep_sc = -1;
|
||||
rep_dcnt = 0;
|
||||
}
|
||||
|
||||
void IODevice_Keyboard::UpdateInput(const uint8* data, const int32 time_elapsed)
|
||||
{
|
||||
phys[0] = MDFN_de64lsb(&data[0x00]);
|
||||
phys[1] = MDFN_de64lsb(&data[0x08]);
|
||||
phys[2] = MDFN_de16lsb(&data[0x10]);
|
||||
phys[3] = 0;
|
||||
//
|
||||
if(rep_dcnt > 0)
|
||||
rep_dcnt -= time_elapsed;
|
||||
|
||||
for(unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
uint64 tmp = phys[i] ^ processed[i];
|
||||
unsigned bp;
|
||||
|
||||
while((bp = (63 ^ MDFN_lzcount64(tmp))) < 64)
|
||||
{
|
||||
const uint64 mask = ((uint64)1 << bp);
|
||||
const int sc = ((i << 6) + bp);
|
||||
|
||||
if(fifo_cnt >= (fifo_size - (sc == 0x82)))
|
||||
goto fifo_oflow_abort;
|
||||
|
||||
if(phys[i] & mask)
|
||||
{
|
||||
rep_sc = sc;
|
||||
#if 1
|
||||
rep_dcnt = 400000;
|
||||
#else
|
||||
rep_dcnt = 250000;
|
||||
#endif
|
||||
fifo[fifo_wrp] = 0x800 | sc;
|
||||
fifo_wrp = (fifo_wrp + 1) % fifo_size;
|
||||
fifo_cnt++;
|
||||
}
|
||||
|
||||
if(!(phys[i] & mask) == (sc != 0x82))
|
||||
{
|
||||
if(rep_sc == sc)
|
||||
rep_sc = -1;
|
||||
|
||||
fifo[fifo_wrp] = 0x100 | sc;
|
||||
fifo_wrp = (fifo_wrp + 1) % fifo_size;
|
||||
fifo_cnt++;
|
||||
}
|
||||
|
||||
processed[i] = (processed[i] & ~mask) | (phys[i] & mask);
|
||||
tmp &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
if(rep_sc >= 0)
|
||||
{
|
||||
while(rep_dcnt <= 0)
|
||||
{
|
||||
if(fifo_cnt >= fifo_size)
|
||||
goto fifo_oflow_abort;
|
||||
|
||||
fifo[fifo_wrp] = 0x800 | rep_sc;
|
||||
fifo_wrp = (fifo_wrp + 1) % fifo_size;
|
||||
fifo_cnt++;
|
||||
|
||||
rep_dcnt += 33333;
|
||||
}
|
||||
}
|
||||
|
||||
fifo_oflow_abort:;
|
||||
}
|
||||
|
||||
void IODevice_Keyboard::UpdateOutput(uint8* data)
|
||||
{
|
||||
data[0x12] = lock;
|
||||
}
|
||||
|
||||
uint8 IODevice_Keyboard::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted)
|
||||
{
|
||||
if(smpc_out & 0x40)
|
||||
{
|
||||
phase = -1;
|
||||
tl = true;
|
||||
data_out = 0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((bool)(smpc_out & 0x20) != tl)
|
||||
{
|
||||
tl = !tl;
|
||||
phase += (phase < 11);
|
||||
|
||||
if(!phase)
|
||||
{
|
||||
if(mkbrk_pend == (uint8)mkbrk_pend && fifo_cnt)
|
||||
{
|
||||
mkbrk_pend = fifo[fifo_rdp];
|
||||
fifo_rdp = (fifo_rdp + 1) % fifo_size;
|
||||
fifo_cnt--;
|
||||
|
||||
bool p = mkbrk_pend & 0x800;
|
||||
|
||||
switch(mkbrk_pend & 0xFF)
|
||||
{
|
||||
case 0x89: /* Up */ simbutt_pend = simbutt & ~(1 << 0); simbutt_pend &= ~(p << 1); simbutt_pend |= (p << 0); break;
|
||||
case 0x8A: /*Down */ simbutt_pend = simbutt & ~(1 << 1); simbutt_pend &= ~(p << 0); simbutt_pend |= (p << 1); break;
|
||||
case 0x86: /*Left */ simbutt_pend = simbutt & ~(1 << 2); simbutt_pend &= ~(p << 3); simbutt_pend |= (p << 2); break;
|
||||
case 0x8D: /*Right*/ simbutt_pend = simbutt & ~(1 << 3); simbutt_pend &= ~(p << 2); simbutt_pend |= (p << 3); break;
|
||||
case 0x22: /* X */ simbutt_pend = simbutt & ~(1 << 4); simbutt_pend |= (p << 4); break;
|
||||
case 0x21: /* C */ simbutt_pend = simbutt & ~(1 << 5); simbutt_pend |= (p << 5); break;
|
||||
case 0x1A: /* Z */ simbutt_pend = simbutt & ~(1 << 6); simbutt_pend |= (p << 6); break;
|
||||
case 0x76: /* Esc */ simbutt_pend = simbutt & ~(1 << 7); simbutt_pend |= (p << 7); break;
|
||||
case 0x23: /* D */ simbutt_pend = simbutt & ~(1 << 8); simbutt_pend |= (p << 8); break;
|
||||
case 0x1B: /* S */ simbutt_pend = simbutt & ~(1 << 9); simbutt_pend |= (p << 9); break;
|
||||
case 0x1C: /* A */ simbutt_pend = simbutt & ~(1 << 10); simbutt_pend |= (p << 10); break;
|
||||
case 0x24: /* E */ simbutt_pend = simbutt & ~(1 << 11); simbutt_pend |= (p << 11); break;
|
||||
case 0x15: /* Q */ simbutt_pend = simbutt & ~(1 << 15); simbutt_pend |= (p << 15); break;
|
||||
|
||||
case 0x7E: /* Scrl */ lock_pend = lock ^ (p ? LOCK_SCROLL : 0); break;
|
||||
case 0x77: /* Num */ lock_pend = lock ^ (p ? LOCK_NUM : 0); break;
|
||||
case 0x58: /* Caps */ lock_pend = lock ^ (p ? LOCK_CAPS : 0); break;
|
||||
}
|
||||
}
|
||||
buffer[ 0] = 0x3;
|
||||
buffer[ 1] = 0x4;
|
||||
buffer[ 2] = (((simbutt_pend >> 0) ^ 0xF) & 0xF);
|
||||
buffer[ 3] = (((simbutt_pend >> 4) ^ 0xF) & 0xF);
|
||||
buffer[ 4] = (((simbutt_pend >> 8) ^ 0xF) & 0xF);
|
||||
buffer[ 5] = (((simbutt_pend >> 12) ^ 0xF) & 0x8) | 0x0;
|
||||
buffer[ 6] = lock_pend;
|
||||
buffer[ 7] = ((mkbrk_pend >> 8) & 0xF) | 0x6;
|
||||
buffer[ 8] = (mkbrk_pend >> 4) & 0xF;
|
||||
buffer[ 9] = (mkbrk_pend >> 0) & 0xF;
|
||||
buffer[10] = 0x0;
|
||||
buffer[11] = 0x1;
|
||||
}
|
||||
|
||||
if(phase == 9)
|
||||
{
|
||||
mkbrk_pend = (uint8)mkbrk_pend;
|
||||
lock = lock_pend;
|
||||
simbutt = simbutt_pend;
|
||||
}
|
||||
|
||||
data_out = buffer[phase];
|
||||
}
|
||||
}
|
||||
|
||||
return (smpc_out & (smpc_out_asserted | 0xE0)) | (((tl << 4) | data_out) &~ smpc_out_asserted);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,73 +1,72 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* keyboard.h:
|
||||
** Copyright (C) 2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_KEYBOARD_H
|
||||
#define __MDFN_SS_INPUT_KEYBOARD_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_Keyboard final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_Keyboard() MDFN_COLD;
|
||||
virtual ~IODevice_Keyboard() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
virtual void UpdateOutput(uint8* data) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
|
||||
uint64 phys[4];
|
||||
uint64 processed[4];
|
||||
uint8 lock;
|
||||
uint8 lock_pend;
|
||||
uint16 simbutt;
|
||||
uint16 simbutt_pend;
|
||||
enum { fifo_size = 16 };
|
||||
uint16 fifo[fifo_size];
|
||||
uint8 fifo_rdp;
|
||||
uint8 fifo_wrp;
|
||||
uint8 fifo_cnt;
|
||||
enum
|
||||
{
|
||||
LOCK_SCROLL = 0x01,
|
||||
LOCK_NUM = 0x02,
|
||||
LOCK_CAPS = 0x04
|
||||
};
|
||||
|
||||
int16 rep_sc;
|
||||
int32 rep_dcnt;
|
||||
|
||||
int16 mkbrk_pend;
|
||||
uint8 buffer[12];
|
||||
uint8 data_out;
|
||||
bool tl;
|
||||
int8 phase;
|
||||
};
|
||||
|
||||
extern const IDIISG IODevice_Keyboard_US101_IDII;
|
||||
}
|
||||
|
||||
#endif
|
||||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* keyboard.h:
|
||||
** Copyright (C) 2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_KEYBOARD_H
|
||||
#define __MDFN_SS_INPUT_KEYBOARD_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_Keyboard final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_Keyboard() MDFN_COLD;
|
||||
virtual ~IODevice_Keyboard() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
virtual void UpdateOutput(uint8* data) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
|
||||
uint64 phys[4];
|
||||
uint64 processed[4];
|
||||
uint8 lock;
|
||||
uint8 lock_pend;
|
||||
uint16 simbutt;
|
||||
uint16 simbutt_pend;
|
||||
enum { fifo_size = 16 };
|
||||
uint16 fifo[fifo_size];
|
||||
uint8 fifo_rdp;
|
||||
uint8 fifo_wrp;
|
||||
uint8 fifo_cnt;
|
||||
enum
|
||||
{
|
||||
LOCK_SCROLL = 0x01,
|
||||
LOCK_NUM = 0x02,
|
||||
LOCK_CAPS = 0x04
|
||||
};
|
||||
|
||||
int16 rep_sc;
|
||||
int32 rep_dcnt;
|
||||
|
||||
int16 mkbrk_pend;
|
||||
uint8 buffer[12];
|
||||
uint8 data_out;
|
||||
bool tl;
|
||||
int8 phase;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -157,173 +157,4 @@ uint8 IODevice_Mission::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_ass
|
|||
return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted);
|
||||
}
|
||||
|
||||
static const char* const SpeedSwitchPositions[] =
|
||||
{
|
||||
gettext_noop("1/7"),
|
||||
gettext_noop("2/7"),
|
||||
gettext_noop("3/7"),
|
||||
gettext_noop("4/7"),
|
||||
gettext_noop("5/7"),
|
||||
gettext_noop("6/7"),
|
||||
gettext_noop("7/7")
|
||||
};
|
||||
|
||||
static const char* const AFSwitchPositions[] =
|
||||
{
|
||||
gettext_noop("• (Off)"),
|
||||
gettext_noop("•• (On)")
|
||||
};
|
||||
|
||||
IDIISG IODevice_Mission_IDII =
|
||||
{
|
||||
// 0
|
||||
{ "b", "B (Stick Left Button)", 6, IDIT_BUTTON },
|
||||
{ "c", "C (Stick Right Button)", 8, IDIT_BUTTON },
|
||||
{ "a", "A (Stick Trigger)", 7, IDIT_BUTTON },
|
||||
{ "start", "START", 9, IDIT_BUTTON },
|
||||
|
||||
// 4
|
||||
{ "z", "Z", 13, IDIT_BUTTON },
|
||||
{ "y", "Y", 12, IDIT_BUTTON },
|
||||
{ "x", "X", 11, IDIT_BUTTON },
|
||||
{ "r", "R", 14, IDIT_BUTTON },
|
||||
|
||||
// 8
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ "l", "L", 10, IDIT_BUTTON },
|
||||
|
||||
// 12
|
||||
IDIIS_Switch("afb", "B AF", 20, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
IDIIS_Switch("afc", "C AF", 21, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
IDIIS_Switch("afa", "A AF", 19, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 16
|
||||
IDIIS_Switch("afz", "Z AF", 17, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
IDIIS_Switch("afy", "Y AF", 16, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
IDIIS_Switch("afx", "X AF", 15, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
IDIIS_Switch("afr", "R AF", 22, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
|
||||
// 20
|
||||
IDIIS_Switch("afspeed", "AF Speed", 23, SpeedSwitchPositions, sizeof(SpeedSwitchPositions) / sizeof(SpeedSwitchPositions[0])),
|
||||
IDIIS_Switch("afl", "L AF", 18, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
|
||||
// 24
|
||||
{ "stick_left", "Stick LEFT ← (Analog)", 2, IDIT_BUTTON_ANALOG },
|
||||
{ "stick_right", "Stick RIGHT → (Analog)", 3, IDIT_BUTTON_ANALOG },
|
||||
{ "stick_fore", "Stick FORE ↑ (Analog)", 0, IDIT_BUTTON_ANALOG },
|
||||
{ "stick_back", "Stick BACK ↓ (Analog)", 1, IDIT_BUTTON_ANALOG },
|
||||
|
||||
{ "throttle_down", "Throttle Down (Analog)", 5, IDIT_BUTTON_ANALOG },
|
||||
{ "throttle_up", "Throttle Up (Analog)", 4, IDIT_BUTTON_ANALOG },
|
||||
};
|
||||
|
||||
IDIISG IODevice_MissionNoAF_IDII =
|
||||
{
|
||||
// 0
|
||||
{ "b", "B (Stick Left Button)", 6, IDIT_BUTTON },
|
||||
{ "c", "C (Stick Right Button)", 8, IDIT_BUTTON },
|
||||
{ "a", "A (Stick Trigger)", 7, IDIT_BUTTON },
|
||||
{ "start", "START", 9, IDIT_BUTTON },
|
||||
|
||||
// 4
|
||||
{ "z", "Z", 13, IDIT_BUTTON },
|
||||
{ "y", "Y", 12, IDIT_BUTTON },
|
||||
{ "x", "X", 11, IDIT_BUTTON },
|
||||
{ "r", "R", 14, IDIT_BUTTON },
|
||||
|
||||
// 8
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ "l", "L", 10, IDIT_BUTTON },
|
||||
|
||||
// 12
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 16
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 20
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 24
|
||||
{ "stick_left", "Stick LEFT ← (Analog)", 2, IDIT_BUTTON_ANALOG },
|
||||
{ "stick_right", "Stick RIGHT → (Analog)", 3, IDIT_BUTTON_ANALOG },
|
||||
{ "stick_fore", "Stick FORE ↑ (Analog)", 0, IDIT_BUTTON_ANALOG },
|
||||
{ "stick_back", "Stick BACK ↓ (Analog)", 1, IDIT_BUTTON_ANALOG },
|
||||
|
||||
{ "throttle_down", "Throttle Down (Analog)", 5, IDIT_BUTTON_ANALOG },
|
||||
{ "throttle_up", "Throttle Up (Analog)", 4, IDIT_BUTTON_ANALOG },
|
||||
};
|
||||
|
||||
|
||||
IDIISG IODevice_DualMission_IDII =
|
||||
{
|
||||
// 0
|
||||
{ "b", "B (R Stick Left Button)", 15, IDIT_BUTTON },
|
||||
{ "c", "C (R Stick Right Button)", 17, IDIT_BUTTON },
|
||||
{ "a", "A (R Stick Trigger)", 16, IDIT_BUTTON },
|
||||
{ "start", "START", 18, IDIT_BUTTON },
|
||||
|
||||
// 4
|
||||
{ "z", "Z (L Stick Right Button)", 8, IDIT_BUTTON },
|
||||
{ "y", "Y (L Stick Left Button)", 6, IDIT_BUTTON },
|
||||
{ "x", "X (L Stick Trigger)", 7, IDIT_BUTTON },
|
||||
{ "r", "R", 20, IDIT_BUTTON },
|
||||
|
||||
// 8
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ "l", "L", 19, IDIT_BUTTON },
|
||||
|
||||
// 12
|
||||
IDIIS_Switch("afb", "B AF", 26, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
IDIIS_Switch("afc", "C AF", 27, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
IDIIS_Switch("afa", "A AF", 25, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 16
|
||||
IDIIS_Switch("afz", "Z AF", 23, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
IDIIS_Switch("afy", "Y AF", 22, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
IDIIS_Switch("afx", "X AF", 21, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
IDIIS_Switch("afr", "R AF", 28, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
|
||||
// 20
|
||||
IDIIS_Switch("afspeed", "Autofire Speed", 29, SpeedSwitchPositions, sizeof(SpeedSwitchPositions) / sizeof(SpeedSwitchPositions[0])),
|
||||
IDIIS_Switch("afl", "L AF", 24, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
|
||||
|
||||
// 24
|
||||
{ "rstick_left", "R Stick LEFT ← (Analog)", 11, IDIT_BUTTON_ANALOG },
|
||||
{ "rstick_right", "R Stick RIGHT → (Analog)", 12, IDIT_BUTTON_ANALOG },
|
||||
{ "rstick_fore", "R Stick FORE ↑ (Analog)", 9, IDIT_BUTTON_ANALOG },
|
||||
{ "rstick_back", "R Stick BACK ↓ (Analog)", 10, IDIT_BUTTON_ANALOG },
|
||||
|
||||
{ "rthrottle_down", "R Throttle Down (Analog)", 14, IDIT_BUTTON_ANALOG },
|
||||
{ "rthrottle_up", "R Throttle Up (Analog)", 13, IDIT_BUTTON_ANALOG },
|
||||
|
||||
{ "lstick_left", "L Stick LEFT ← (Analog)", 2, IDIT_BUTTON_ANALOG },
|
||||
{ "lstick_right", "L Stick RIGHT → (Analog)", 3, IDIT_BUTTON_ANALOG },
|
||||
{ "lstick_fore", "L Stick FORE ↑ (Analog)", 0, IDIT_BUTTON_ANALOG },
|
||||
{ "lstick_back", "L Stick BACK ↓ (Analog)", 1, IDIT_BUTTON_ANALOG },
|
||||
|
||||
{ "lthrottle_down", "L Throttle Down (Analog)", 5, IDIT_BUTTON_ANALOG },
|
||||
{ "lthrottle_up", "L Throttle Up (Analog)", 4, IDIT_BUTTON_ANALOG },
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,64 +1,58 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* mission.h:
|
||||
** Copyright (C) 2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_MISSION_H
|
||||
#define __MDFN_SS_INPUT_MISSION_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_Mission final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_Mission(const bool dual_) MDFN_COLD;
|
||||
virtual ~IODevice_Mission() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
uint16 dbuttons;
|
||||
uint16 afeswitches;
|
||||
uint8 afspeed;
|
||||
|
||||
uint8 axes[2][3];
|
||||
|
||||
uint8 buffer[0x20];
|
||||
uint8 data_out;
|
||||
bool tl;
|
||||
int8 phase;
|
||||
uint8 afcounter;
|
||||
bool afphase;
|
||||
|
||||
const bool dual;
|
||||
};
|
||||
|
||||
|
||||
extern IDIISG IODevice_Mission_IDII;
|
||||
extern IDIISG IODevice_MissionNoAF_IDII;
|
||||
|
||||
extern IDIISG IODevice_DualMission_IDII;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* mission.h:
|
||||
** Copyright (C) 2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_MISSION_H
|
||||
#define __MDFN_SS_INPUT_MISSION_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_Mission final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_Mission(const bool dual_) MDFN_COLD;
|
||||
virtual ~IODevice_Mission() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
uint16 dbuttons;
|
||||
uint16 afeswitches;
|
||||
uint8 afspeed;
|
||||
|
||||
uint8 axes[2][3];
|
||||
|
||||
uint8 buffer[0x20];
|
||||
uint8 data_out;
|
||||
bool tl;
|
||||
int8 phase;
|
||||
uint8 afcounter;
|
||||
bool afphase;
|
||||
|
||||
const bool dual;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -128,16 +128,4 @@ uint8 IODevice_Mouse::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asser
|
|||
return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted);
|
||||
}
|
||||
|
||||
IDIISG IODevice_Mouse_IDII =
|
||||
{
|
||||
{ "x_axis", "X Axis", -1, IDIT_X_AXIS_REL },
|
||||
{ "y_axis", "Y Axis", -1, IDIT_Y_AXIS_REL },
|
||||
|
||||
{ "left", "Left Button", 0, IDIT_BUTTON },
|
||||
{ "right", "Right Button", 2, IDIT_BUTTON },
|
||||
{ "middle", "Middle Button", 1, IDIT_BUTTON },
|
||||
{ "start", "Start", 3, IDIT_BUTTON },
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,55 +1,52 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* mouse.h:
|
||||
** Copyright (C) 2016-2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_MOUSE_H
|
||||
#define __MDFN_SS_INPUT_MOUSE_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_Mouse final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_Mouse() MDFN_COLD;
|
||||
virtual ~IODevice_Mouse() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
int32 accum_xdelta;
|
||||
int32 accum_ydelta;
|
||||
|
||||
uint8 buttons;
|
||||
uint8 buffer[0x10];
|
||||
uint8 data_out;
|
||||
bool tl;
|
||||
int8 phase;
|
||||
};
|
||||
|
||||
|
||||
extern IDIISG IODevice_Mouse_IDII;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* mouse.h:
|
||||
** Copyright (C) 2016-2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_MOUSE_H
|
||||
#define __MDFN_SS_INPUT_MOUSE_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_Mouse final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_Mouse() MDFN_COLD;
|
||||
virtual ~IODevice_Mouse() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
int32 accum_xdelta;
|
||||
int32 accum_ydelta;
|
||||
|
||||
uint8 buttons;
|
||||
uint8 buffer[0x10];
|
||||
uint8 data_out;
|
||||
bool tl;
|
||||
int8 phase;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -102,33 +102,4 @@ uint8 IODevice_Wheel::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asser
|
|||
return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted);
|
||||
}
|
||||
|
||||
IDIISG IODevice_Wheel_IDII =
|
||||
{
|
||||
{ "up", "L Gear Shift(Equiv. UP ↑)", 2, IDIT_BUTTON, "down" },
|
||||
{ "down", "R Gear Shift(Equiv. DOWN ↓)", 3, IDIT_BUTTON, "up" },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON }, // left
|
||||
{ NULL, "empty", 0, IDIT_BUTTON }, // right
|
||||
|
||||
{ "b", "B (R Group)", 9, IDIT_BUTTON },
|
||||
{ "c", "C (R Group)", 10, IDIT_BUTTON },
|
||||
{ "a", "A (R Group)", 8, IDIT_BUTTON },
|
||||
{ "start", "START", 7, IDIT_BUTTON },
|
||||
|
||||
{ "z", "Z (L Group)", 4, IDIT_BUTTON },
|
||||
{ "y", "Y (L Group)", 5, IDIT_BUTTON },
|
||||
{ "x", "X (L Group)", 6, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
{ "analog_left", "Analog LEFT ←", 0, IDIT_BUTTON_ANALOG },
|
||||
{ "analog_right", "Analog RIGHT →", 1, IDIT_BUTTON_ANALOG },
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,54 +1,51 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* wheel.h:
|
||||
** Copyright (C) 2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_WHEEL_H
|
||||
#define __MDFN_SS_INPUT_WHEEL_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_Wheel final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_Wheel() MDFN_COLD;
|
||||
virtual ~IODevice_Wheel() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
uint16 dbuttons;
|
||||
uint8 wheel;
|
||||
|
||||
uint8 buffer[0x10];
|
||||
uint8 data_out;
|
||||
bool tl;
|
||||
int8 phase;
|
||||
};
|
||||
|
||||
|
||||
extern IDIISG IODevice_Wheel_IDII;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* wheel.h:
|
||||
** Copyright (C) 2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_INPUT_WHEEL_H
|
||||
#define __MDFN_SS_INPUT_WHEEL_H
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
class IODevice_Wheel final : public IODevice
|
||||
{
|
||||
public:
|
||||
IODevice_Wheel() MDFN_COLD;
|
||||
virtual ~IODevice_Wheel() override MDFN_COLD;
|
||||
|
||||
virtual void Power(void) override MDFN_COLD;
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed) override;
|
||||
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) override;
|
||||
|
||||
private:
|
||||
uint16 dbuttons;
|
||||
uint8 wheel;
|
||||
|
||||
uint8 buffer[0x10];
|
||||
uint8 data_out;
|
||||
bool tl;
|
||||
int8 phase;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
2882
waterbox/ss/smpc.cpp
2882
waterbox/ss/smpc.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1,100 +1,100 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* smpc.h:
|
||||
** Copyright (C) 2015-2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_SMPC_H
|
||||
#define __MDFN_SS_SMPC_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
SMPC_AREA_JP = 0x1,
|
||||
SMPC_AREA_ASIA_NTSC = 0x2,
|
||||
SMPC_AREA_NA = 0x4,
|
||||
SMPC_AREA_CSA_NTSC = 0x5,
|
||||
SMPC_AREA_KR = 0x6,
|
||||
|
||||
SMPC_AREA_ASIA_PAL = 0xA,
|
||||
SMPC_AREA_EU_PAL = 0xC,
|
||||
SMPC_AREA_CSA_PAL = 0xD,
|
||||
//
|
||||
//
|
||||
//
|
||||
SMPC_AREA__PAL_MASK = 0x8
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SMPC_RTC_LANG_ENGLISH = 0,
|
||||
SMPC_RTC_LANG_GERMAN = 1,
|
||||
SMPC_RTC_LANG_FRENCH = 2,
|
||||
SMPC_RTC_LANG_SPANISH = 3,
|
||||
SMPC_RTC_LANG_ITALIAN = 4,
|
||||
SMPC_RTC_LANG_JAPANESE = 5,
|
||||
};
|
||||
|
||||
void SMPC_Init(const uint8 area_code, const int32 master_clock) MDFN_COLD;
|
||||
bool SMPC_IsSlaveOn(void);
|
||||
void SMPC_Reset(bool powering_up) MDFN_COLD;
|
||||
void SMPC_LoadNV(Stream* s) MDFN_COLD;
|
||||
void SMPC_SaveNV(Stream* s) MDFN_COLD;
|
||||
|
||||
void SMPC_SetRTC(const struct tm* ht, const uint8 lang) MDFN_COLD;
|
||||
|
||||
void SMPC_Write(const sscpu_timestamp_t timestamp, uint8 A, uint8 V) MDFN_HOT;
|
||||
uint8 SMPC_Read(const sscpu_timestamp_t timestamp, uint8 A) MDFN_HOT;
|
||||
|
||||
sscpu_timestamp_t SMPC_Update(sscpu_timestamp_t timestamp);
|
||||
void SMPC_ResetTS(void);
|
||||
|
||||
int32 SMPC_StartFrame(EmulateSpecStruct* espec);
|
||||
void SMPC_UpdateInput(const int32 time_elapsed);
|
||||
void SMPC_UpdateOutput(void);
|
||||
void SMPC_SetInput(unsigned port, const char* type, uint8* ptr) MDFN_COLD;
|
||||
void SMPC_SetMultitap(unsigned sport, bool enabled) MDFN_COLD;
|
||||
|
||||
void SMPC_SetVB(sscpu_timestamp_t event_timestamp, bool vb_status);
|
||||
|
||||
class IODevice
|
||||
{
|
||||
public:
|
||||
|
||||
IODevice() MDFN_COLD;
|
||||
virtual ~IODevice() MDFN_COLD;
|
||||
|
||||
virtual void Power(void) MDFN_COLD;
|
||||
|
||||
//
|
||||
// time_elapsed is emulated time elapsed since last call to UpdateInput(), in microseconds;
|
||||
// it's mostly for keyboard emulation, to keep the implementation from becoming unnecessarily complex.
|
||||
//
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed);
|
||||
virtual void UpdateOutput(uint8* data);
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted);
|
||||
};
|
||||
|
||||
//extern const std::vector<InputPortInfoStruct> SMPC_PortInfo;
|
||||
|
||||
}
|
||||
#endif
|
||||
/******************************************************************************/
|
||||
/* Mednafen Sega Saturn Emulation Module */
|
||||
/******************************************************************************/
|
||||
/* smpc.h:
|
||||
** Copyright (C) 2015-2017 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_SS_SMPC_H
|
||||
#define __MDFN_SS_SMPC_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
SMPC_AREA_JP = 0x1,
|
||||
SMPC_AREA_ASIA_NTSC = 0x2,
|
||||
SMPC_AREA_NA = 0x4,
|
||||
SMPC_AREA_CSA_NTSC = 0x5,
|
||||
SMPC_AREA_KR = 0x6,
|
||||
|
||||
SMPC_AREA_ASIA_PAL = 0xA,
|
||||
SMPC_AREA_EU_PAL = 0xC,
|
||||
SMPC_AREA_CSA_PAL = 0xD,
|
||||
//
|
||||
//
|
||||
//
|
||||
SMPC_AREA__PAL_MASK = 0x8
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SMPC_RTC_LANG_ENGLISH = 0,
|
||||
SMPC_RTC_LANG_GERMAN = 1,
|
||||
SMPC_RTC_LANG_FRENCH = 2,
|
||||
SMPC_RTC_LANG_SPANISH = 3,
|
||||
SMPC_RTC_LANG_ITALIAN = 4,
|
||||
SMPC_RTC_LANG_JAPANESE = 5,
|
||||
};
|
||||
|
||||
void SMPC_Init(const uint8 area_code, const int32 master_clock) MDFN_COLD;
|
||||
bool SMPC_IsSlaveOn(void);
|
||||
void SMPC_Reset(bool powering_up) MDFN_COLD;
|
||||
//void SMPC_LoadNV(Stream* s) MDFN_COLD;
|
||||
//void SMPC_SaveNV(Stream* s) MDFN_COLD;
|
||||
|
||||
void SMPC_SetRTC(const struct tm* ht, const uint8 lang) MDFN_COLD;
|
||||
|
||||
void SMPC_Write(const sscpu_timestamp_t timestamp, uint8 A, uint8 V) MDFN_HOT;
|
||||
uint8 SMPC_Read(const sscpu_timestamp_t timestamp, uint8 A) MDFN_HOT;
|
||||
|
||||
sscpu_timestamp_t SMPC_Update(sscpu_timestamp_t timestamp);
|
||||
void SMPC_ResetTS(void);
|
||||
|
||||
int32 SMPC_StartFrame(EmulateSpecStruct* espec);
|
||||
void SMPC_UpdateInput(const int32 time_elapsed);
|
||||
void SMPC_UpdateOutput(void);
|
||||
void SMPC_SetInput(unsigned port, const char* type, uint8* ptr) MDFN_COLD;
|
||||
void SMPC_SetMultitap(unsigned sport, bool enabled) MDFN_COLD;
|
||||
|
||||
void SMPC_SetVB(sscpu_timestamp_t event_timestamp, bool vb_status);
|
||||
|
||||
class IODevice
|
||||
{
|
||||
public:
|
||||
|
||||
IODevice() MDFN_COLD;
|
||||
virtual ~IODevice() MDFN_COLD;
|
||||
|
||||
virtual void Power(void) MDFN_COLD;
|
||||
|
||||
//
|
||||
// time_elapsed is emulated time elapsed since last call to UpdateInput(), in microseconds;
|
||||
// it's mostly for keyboard emulation, to keep the implementation from becoming unnecessarily complex.
|
||||
//
|
||||
virtual void UpdateInput(const uint8* data, const int32 time_elapsed);
|
||||
virtual void UpdateOutput(uint8* data);
|
||||
virtual uint8 UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted);
|
||||
};
|
||||
|
||||
//extern const std::vector<InputPortInfoStruct> SMPC_PortInfo;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,22 +21,10 @@
|
|||
|
||||
// WARNING: Be careful with 32-bit access to 16-bit space, bus locking, etc. in respect to DMA and event updates(and where they can occur).
|
||||
|
||||
/*#include <mednafen/general.h>
|
||||
#include <mednafen/FileStream.h>
|
||||
#include <mednafen/compress/GZFileStream.h>
|
||||
#include <mednafen/mempatcher.h>
|
||||
#include <mednafen/hash/sha256.h>
|
||||
#include <mednafen/hash/md5.h>
|
||||
#include <mednafen/Time.h>*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <bitset>
|
||||
|
||||
//#include <zlib.h>
|
||||
|
||||
//extern MDFNGI EmulatedSS;
|
||||
|
||||
#include "ss.h"
|
||||
#include "cdrom/cdromif.h"
|
||||
#include "sound.h"
|
||||
|
|
|
@ -1,324 +0,0 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen - Multi-system Emulator */
|
||||
/******************************************************************************/
|
||||
/* MemoryStream.cpp:
|
||||
** Copyright (C) 2012-2016 Mednafen Team
|
||||
**
|
||||
** 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 "ss.h"
|
||||
#include "MemoryStream.h"
|
||||
#include "math_ops.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
TODO: Copy and assignment constructor fixes.
|
||||
|
||||
Proper negative position behavior?
|
||||
*/
|
||||
|
||||
MemoryStream::MemoryStream() : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0)
|
||||
{
|
||||
data_buffer_size = 0;
|
||||
data_buffer_alloced = 64;
|
||||
if(!(data_buffer = (uint8*)realloc(data_buffer, data_buffer_alloced)))
|
||||
abort();//throw MDFN_Error(ErrnoHolder(errno));
|
||||
}
|
||||
|
||||
MemoryStream::MemoryStream(uint64 alloc_hint, int alloc_hint_is_size) : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0)
|
||||
{
|
||||
if(alloc_hint_is_size != 0)
|
||||
{
|
||||
data_buffer_size = alloc_hint;
|
||||
data_buffer_alloced = alloc_hint;
|
||||
|
||||
if(alloc_hint > SIZE_MAX)
|
||||
abort();//throw MDFN_Error(ErrnoHolder(ENOMEM));
|
||||
}
|
||||
else
|
||||
{
|
||||
data_buffer_size = 0;
|
||||
data_buffer_alloced = (alloc_hint > SIZE_MAX) ? SIZE_MAX : alloc_hint;
|
||||
}
|
||||
|
||||
data_buffer_alloced = std::max<uint64>(data_buffer_alloced, 1);
|
||||
|
||||
if(!(data_buffer = (uint8*)realloc(data_buffer, data_buffer_alloced)))
|
||||
abort();//throw MDFN_Error(ErrnoHolder(errno));
|
||||
|
||||
if(alloc_hint_is_size > 0)
|
||||
memset(data_buffer, 0, data_buffer_size);
|
||||
}
|
||||
|
||||
MemoryStream::MemoryStream(Stream *stream, uint64 size_limit) : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0)
|
||||
{
|
||||
if((position = stream->tell()) != 0)
|
||||
stream->seek(0, SEEK_SET);
|
||||
|
||||
void* tp;
|
||||
data_buffer_size = data_buffer_alloced = stream->alloc_and_read(&tp, size_limit);
|
||||
data_buffer = (uint8*)tp;
|
||||
stream->close();
|
||||
delete stream;
|
||||
}
|
||||
|
||||
MemoryStream::MemoryStream(const MemoryStream &zs)
|
||||
{
|
||||
data_buffer_size = zs.data_buffer_size;
|
||||
data_buffer_alloced = zs.data_buffer_alloced;
|
||||
if(!(data_buffer = (uint8*)malloc(data_buffer_alloced)))
|
||||
abort();//throw MDFN_Error(ErrnoHolder(errno));
|
||||
|
||||
memcpy(data_buffer, zs.data_buffer, data_buffer_size);
|
||||
|
||||
position = zs.position;
|
||||
}
|
||||
|
||||
#if 0
|
||||
MemoryStream & MemoryStream::operator=(const MemoryStream &zs)
|
||||
{
|
||||
if(this != &zs)
|
||||
{
|
||||
if(data_buffer)
|
||||
{
|
||||
free(data_buffer);
|
||||
data_buffer = NULL;
|
||||
}
|
||||
|
||||
data_buffer_size = zs.data_buffer_size;
|
||||
data_buffer_alloced = zs.data_buffer_alloced;
|
||||
|
||||
if(!(data_buffer = (uint8*)malloc(data_buffer_alloced)))
|
||||
throw MDFN_Error(ErrnoHolder(errno));
|
||||
|
||||
memcpy(data_buffer, zs.data_buffer, data_buffer_size);
|
||||
|
||||
position = zs.position;
|
||||
}
|
||||
return(*this);
|
||||
}
|
||||
#endif
|
||||
|
||||
MemoryStream::~MemoryStream()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
uint64 MemoryStream::attributes(void)
|
||||
{
|
||||
return (ATTRIBUTE_READABLE | ATTRIBUTE_WRITEABLE | ATTRIBUTE_SEEKABLE);
|
||||
}
|
||||
|
||||
|
||||
uint8 *MemoryStream::map(void) noexcept
|
||||
{
|
||||
return data_buffer;
|
||||
}
|
||||
|
||||
uint64 MemoryStream::map_size(void) noexcept
|
||||
{
|
||||
return data_buffer_size;
|
||||
}
|
||||
|
||||
void MemoryStream::unmap(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
INLINE void MemoryStream::grow_if_necessary(uint64 new_required_size, uint64 hole_end)
|
||||
{
|
||||
if(new_required_size > data_buffer_size)
|
||||
{
|
||||
const uint64 old_data_buffer_size = data_buffer_size;
|
||||
|
||||
if(new_required_size > data_buffer_alloced)
|
||||
{
|
||||
uint64 new_required_alloced = round_up_pow2(new_required_size);
|
||||
uint8 *new_data_buffer;
|
||||
|
||||
// first condition will happen at new_required_size > (1ULL << 63) due to round_up_pow2() "wrapping".
|
||||
// second condition can occur when running on a 32-bit system.
|
||||
if(new_required_alloced < new_required_size || new_required_alloced > SIZE_MAX)
|
||||
new_required_alloced = SIZE_MAX;
|
||||
|
||||
// If constrained alloc size isn't enough, throw an out-of-memory/address-space type error.
|
||||
if(new_required_alloced < new_required_size)
|
||||
abort();//throw MDFN_Error(ErrnoHolder(ENOMEM));
|
||||
|
||||
if(!(new_data_buffer = (uint8*)realloc(data_buffer, new_required_alloced)))
|
||||
abort();//throw MDFN_Error(ErrnoHolder(errno));
|
||||
|
||||
//
|
||||
// Assign all in one go after the realloc() so we don't leave our object in an inconsistent state if the realloc() fails.
|
||||
//
|
||||
data_buffer = new_data_buffer;
|
||||
data_buffer_size = new_required_size;
|
||||
data_buffer_alloced = new_required_alloced;
|
||||
}
|
||||
else
|
||||
data_buffer_size = new_required_size;
|
||||
|
||||
if(hole_end > old_data_buffer_size)
|
||||
memset(data_buffer + old_data_buffer_size, 0, hole_end - old_data_buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryStream::shrink_to_fit(void) noexcept
|
||||
{
|
||||
if(data_buffer_alloced > data_buffer_size)
|
||||
{
|
||||
uint8 *new_data_buffer;
|
||||
const uint64 new_data_buffer_alloced = std::max<uint64>(data_buffer_size, 1);
|
||||
|
||||
new_data_buffer = (uint8*)realloc(data_buffer, new_data_buffer_alloced);
|
||||
|
||||
if(new_data_buffer != NULL)
|
||||
{
|
||||
data_buffer = new_data_buffer;
|
||||
data_buffer_alloced = new_data_buffer_alloced;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64 MemoryStream::read(void *data, uint64 count, bool error_on_eos)
|
||||
{
|
||||
//printf("%llu %llu %llu\n", position, count, data_buffer_size);
|
||||
|
||||
if(count > data_buffer_size)
|
||||
{
|
||||
if(error_on_eos)
|
||||
abort();//throw MDFN_Error(0, _("Unexpected EOF"));
|
||||
|
||||
count = data_buffer_size;
|
||||
}
|
||||
|
||||
if(position > (data_buffer_size - count))
|
||||
{
|
||||
if(error_on_eos)
|
||||
abort();//throw MDFN_Error(0, _("Unexpected EOF"));
|
||||
|
||||
if(data_buffer_size > position)
|
||||
count = data_buffer_size - position;
|
||||
else
|
||||
count = 0;
|
||||
}
|
||||
|
||||
memmove(data, &data_buffer[position], count);
|
||||
position += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void MemoryStream::write(const void *data, uint64 count)
|
||||
{
|
||||
uint64 nrs = position + count;
|
||||
|
||||
if(nrs < position)
|
||||
abort();//throw MDFN_Error(ErrnoHolder(EFBIG));
|
||||
|
||||
grow_if_necessary(nrs, position);
|
||||
|
||||
memmove(&data_buffer[position], data, count);
|
||||
position += count;
|
||||
}
|
||||
|
||||
//
|
||||
// Don't add code to reduce the amount of memory allocated(when possible) without providing a
|
||||
// per-stream setting to disable that behavior.
|
||||
//
|
||||
void MemoryStream::truncate(uint64 length)
|
||||
{
|
||||
grow_if_necessary(length, length);
|
||||
|
||||
data_buffer_size = length;
|
||||
}
|
||||
|
||||
void MemoryStream::seek(int64 offset, int whence)
|
||||
{
|
||||
uint64 new_position;
|
||||
|
||||
switch(whence)
|
||||
{
|
||||
default:
|
||||
abort();//throw MDFN_Error(ErrnoHolder(EINVAL));
|
||||
break;
|
||||
|
||||
case SEEK_SET:
|
||||
new_position = offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
new_position = position + offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
new_position = data_buffer_size + offset;
|
||||
break;
|
||||
}
|
||||
|
||||
if(new_position < 0)
|
||||
abort();//throw MDFN_Error(ErrnoHolder(EINVAL));
|
||||
|
||||
position = new_position;
|
||||
}
|
||||
|
||||
uint64 MemoryStream::tell(void)
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
uint64 MemoryStream::size(void)
|
||||
{
|
||||
return data_buffer_size;
|
||||
}
|
||||
|
||||
void MemoryStream::flush(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MemoryStream::close(void)
|
||||
{
|
||||
if(data_buffer)
|
||||
{
|
||||
free(data_buffer);
|
||||
data_buffer = NULL;
|
||||
}
|
||||
|
||||
data_buffer_size = 0;
|
||||
data_buffer_alloced = 0;
|
||||
position = 0;
|
||||
}
|
||||
|
||||
|
||||
int MemoryStream::get_line(std::string &str)
|
||||
{
|
||||
str.clear(); // or str.resize(0)??
|
||||
|
||||
while((uint64)position < data_buffer_size)
|
||||
{
|
||||
uint8 c = data_buffer[position++];
|
||||
|
||||
if(c == '\r' || c == '\n' || c == 0)
|
||||
return(c);
|
||||
|
||||
str.push_back(c); // Should be faster than str.append(1, c)
|
||||
}
|
||||
|
||||
return(str.length() ? 256 : -1);
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen - Multi-system Emulator */
|
||||
/******************************************************************************/
|
||||
/* MemoryStream.h:
|
||||
** Copyright (C) 2012-2016 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Notes:
|
||||
For performance reasons(like in the state rewinding code), we should try to make sure map()
|
||||
returns a pointer that is aligned to at least what malloc()/realloc() provides.
|
||||
(And maybe forcefully align it to at least 16 bytes in the future)
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_MEMORYSTREAM_H
|
||||
#define __MDFN_MEMORYSTREAM_H
|
||||
|
||||
#include "Stream.h"
|
||||
|
||||
class MemoryStream : public Stream
|
||||
{
|
||||
public:
|
||||
|
||||
MemoryStream();
|
||||
MemoryStream(uint64 alloc_hint, int alloc_hint_is_size = false); // Pass -1 instead of 1 for alloc_hint_is_size to skip initialization of the memory.
|
||||
MemoryStream(Stream *stream, uint64 size_limit = ~(uint64)0);
|
||||
// Will create a MemoryStream equivalent of the contents of "stream", and then "delete stream".
|
||||
// Will only work if stream->tell() == 0, or if "stream" is seekable.
|
||||
// stream will be deleted even if this constructor throws.
|
||||
//
|
||||
// Will throw an exception if the initial size() of the MemoryStream would be greater than size_limit(useful for when passing
|
||||
// in GZFileStream streams).
|
||||
|
||||
MemoryStream(const MemoryStream &zs);
|
||||
MemoryStream & operator=(const MemoryStream &zs);
|
||||
|
||||
virtual ~MemoryStream() override;
|
||||
|
||||
virtual uint64 attributes(void) override;
|
||||
|
||||
virtual uint8 *map(void) noexcept override;
|
||||
virtual uint64 map_size(void) noexcept override;
|
||||
virtual void unmap(void) noexcept override;
|
||||
|
||||
virtual uint64 read(void *data, uint64 count, bool error_on_eos = true) override;
|
||||
virtual void write(const void *data, uint64 count) override;
|
||||
virtual void truncate(uint64 length) override;
|
||||
virtual void seek(int64 offset, int whence) override;
|
||||
virtual uint64 tell(void) override;
|
||||
virtual uint64 size(void) override;
|
||||
virtual void flush(void) override;
|
||||
virtual void close(void) override;
|
||||
|
||||
virtual int get_line(std::string &str) override;
|
||||
|
||||
void shrink_to_fit(void) noexcept; // Minimizes alloced memory.
|
||||
|
||||
#if 0
|
||||
// No methods on the object may be called externally(other than the destructor) after steal_malloced_ptr()
|
||||
INLINE void* steal_malloced_ptr(void)
|
||||
{
|
||||
void* ret = data_buffer;
|
||||
|
||||
data_buffer = nullptr;
|
||||
data_buffer_size = 0;
|
||||
data_buffer_alloced = 0;
|
||||
position = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
uint8 *data_buffer;
|
||||
uint64 data_buffer_size;
|
||||
uint64 data_buffer_alloced;
|
||||
|
||||
uint64 position;
|
||||
|
||||
void grow_if_necessary(uint64 new_required_size, uint64 hole_end);
|
||||
};
|
||||
#endif
|
|
@ -1,223 +0,0 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen - Multi-system Emulator */
|
||||
/******************************************************************************/
|
||||
/* Stream.cpp:
|
||||
** Copyright (C) 2012-2016 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include "ss.h"
|
||||
#include "Stream.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
Stream::Stream()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Stream::~Stream()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Stream::require_fast_seekable(void)
|
||||
{
|
||||
const auto attr = attributes();
|
||||
|
||||
if(!(attr & ATTRIBUTE_SEEKABLE))
|
||||
abort();//throw MDFN_Error(0, _("Stream is not seekable."));
|
||||
|
||||
if(attr & ATTRIBUTE_SLOW_SEEK)
|
||||
abort();//throw MDFN_Error(0, _("Stream is not capable of fast seeks."));
|
||||
}
|
||||
|
||||
uint64 Stream::read_discard(uint64 count)
|
||||
{
|
||||
uint8 buf[1024];
|
||||
uint64 tmp;
|
||||
uint64 ret = 0;
|
||||
|
||||
do
|
||||
{
|
||||
tmp = read(buf, std::min<uint64>(count, sizeof(buf)), false);
|
||||
count -= tmp;
|
||||
ret += tmp;
|
||||
} while(tmp == sizeof(buf));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64 Stream::alloc_and_read(void** data_out, uint64 size_limit)
|
||||
{
|
||||
uint8 *data_buffer = NULL;
|
||||
uint64 data_buffer_size = 0;
|
||||
uint64 data_buffer_alloced = 0;
|
||||
|
||||
//try
|
||||
//{
|
||||
if(attributes() & ATTRIBUTE_SLOW_SIZE)
|
||||
{
|
||||
uint64 rti;
|
||||
|
||||
data_buffer_size = 0;
|
||||
data_buffer_alloced = 65536;
|
||||
|
||||
if(!(data_buffer = (uint8*)realloc(data_buffer, data_buffer_alloced)))
|
||||
abort();//throw MDFN_Error(ErrnoHolder(errno));
|
||||
|
||||
while((rti = read(data_buffer + data_buffer_size, data_buffer_alloced - data_buffer_size, false)) > 0)
|
||||
{
|
||||
uint8* new_data_buffer;
|
||||
|
||||
data_buffer_size += rti;
|
||||
|
||||
if(data_buffer_size == data_buffer_alloced)
|
||||
{
|
||||
data_buffer_alloced <<= 1;
|
||||
|
||||
if(data_buffer_alloced >= SIZE_MAX)
|
||||
abort();//throw MDFN_Error(ErrnoHolder(ENOMEM));
|
||||
|
||||
if(data_buffer_alloced > size_limit) // So we can test against our size limit without going far far over it in temporary memory allocations.
|
||||
data_buffer_alloced = size_limit + 1;
|
||||
|
||||
if(data_buffer_size > size_limit)
|
||||
abort();//throw MDFN_Error(0, _("Size limit of %llu bytes would be exceeded."), (unsigned long long)size_limit);
|
||||
|
||||
if(data_buffer_alloced > SIZE_MAX)
|
||||
abort();//throw MDFN_Error(ErrnoHolder(ENOMEM));
|
||||
|
||||
if(!(new_data_buffer = (uint8 *)realloc(data_buffer, data_buffer_alloced)))
|
||||
abort();//throw MDFN_Error(ErrnoHolder(errno));
|
||||
data_buffer = new_data_buffer;
|
||||
}
|
||||
else // EOS
|
||||
break;
|
||||
}
|
||||
|
||||
if(data_buffer_alloced > data_buffer_size)
|
||||
{
|
||||
uint8 *new_data_buffer;
|
||||
const uint64 new_data_buffer_alloced = std::max<uint64>(data_buffer_size, 1);
|
||||
|
||||
new_data_buffer = (uint8*)realloc(data_buffer, new_data_buffer_alloced);
|
||||
|
||||
if(new_data_buffer != NULL)
|
||||
{
|
||||
data_buffer = new_data_buffer;
|
||||
data_buffer_alloced = new_data_buffer_alloced;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data_buffer_size = size();
|
||||
data_buffer_size -= std::min<uint64>(data_buffer_size, tell());
|
||||
data_buffer_alloced = std::max<uint64>(data_buffer_size, 1);
|
||||
|
||||
if(data_buffer_size > size_limit)
|
||||
abort();//throw MDFN_Error(0, _("Size limit of %llu bytes would be exceeded."), (unsigned long long)size_limit);
|
||||
|
||||
if(data_buffer_alloced > SIZE_MAX)
|
||||
abort();//throw MDFN_Error(ErrnoHolder(ENOMEM));
|
||||
|
||||
if(!(data_buffer = (uint8*)realloc(data_buffer, data_buffer_alloced)))
|
||||
abort();//throw MDFN_Error(ErrnoHolder(errno));
|
||||
|
||||
read(data_buffer, data_buffer_size);
|
||||
}
|
||||
//}
|
||||
//catch(...)
|
||||
//{
|
||||
// if(data_buffer)
|
||||
// {
|
||||
// free(data_buffer);
|
||||
// data_buffer = NULL;
|
||||
// }
|
||||
// throw;
|
||||
//}
|
||||
|
||||
*data_out = data_buffer;
|
||||
return data_buffer_size;
|
||||
}
|
||||
|
||||
|
||||
uint8* Stream::map(void) noexcept
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
uint64 Stream::map_size(void) noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Stream::unmap(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Stream::put_line(const std::string& str)
|
||||
{
|
||||
char l = '\n';
|
||||
|
||||
write(&str[0], str.size());
|
||||
write(&l, sizeof(l));
|
||||
}
|
||||
|
||||
|
||||
void Stream::print_format(const char *format, ...)
|
||||
{
|
||||
char *str = NULL;
|
||||
int rc;
|
||||
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
|
||||
rc = vasprintf(&str, format, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
if(rc < 0)
|
||||
abort();//throw MDFN_Error(0, "Error in trio_vasprintf()");
|
||||
else
|
||||
{
|
||||
write(str, rc);
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
|
||||
int Stream::get_line(std::string &str)
|
||||
{
|
||||
uint8 c;
|
||||
|
||||
str.clear(); // or str.resize(0)??
|
||||
|
||||
while(read(&c, sizeof(c), false) > 0)
|
||||
{
|
||||
if(c == '\r' || c == '\n' || c == 0)
|
||||
return(c);
|
||||
|
||||
str.push_back(c);
|
||||
}
|
||||
|
||||
return(str.length() ? 256 : -1);
|
||||
}
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen - Multi-system Emulator */
|
||||
/******************************************************************************/
|
||||
/* Stream.h:
|
||||
** Copyright (C) 2012-2016 Mednafen Team
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_STREAM_H
|
||||
#define __MDFN_STREAM_H
|
||||
|
||||
// TODO?: BufferedStream, no virtual functions, yes inline functions, constructor takes a Stream* argument.
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdio.h> // For SEEK_* defines, which we will use in Stream out of FORCE OF HABIT.
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
The data read into the pointer passed to read*() functions should be considered undefined if the function throws
|
||||
or propagates an exception.
|
||||
*/
|
||||
|
||||
class Stream
|
||||
{
|
||||
public:
|
||||
|
||||
Stream();
|
||||
virtual ~Stream();
|
||||
|
||||
enum
|
||||
{
|
||||
ATTRIBUTE_READABLE = 1U << 0,
|
||||
ATTRIBUTE_WRITEABLE = 1U << 1,
|
||||
ATTRIBUTE_SEEKABLE = 1U << 2, // Indicates that Stream is capable of being seeked, regardless of how performant seeking is.
|
||||
|
||||
ATTRIBUTE_SLOW_SEEK = 1U << 3, // Indicates that seeking(particularly backwards) is slow, and should be avoided if at all possible.
|
||||
ATTRIBUTE_SLOW_SIZE = 1U << 4 // Indicates that size() is slow, and should be avoided if at all possible.
|
||||
};
|
||||
virtual uint64 attributes(void) = 0;
|
||||
|
||||
//
|
||||
// Throw an exception if stream is not fast-seekable; exists to allow for class-specific generic but helpful
|
||||
// error messages(such as perhaps "MeowZip file is missing a seek index.").
|
||||
//
|
||||
virtual void require_fast_seekable(void);
|
||||
|
||||
virtual uint8 *map(void) noexcept;
|
||||
// Map the entirety of the stream data into the address space of the process, if possible, and return a pointer.
|
||||
// (the returned pointer must be cached, and returned on any subsequent calls to map() without an unmap()
|
||||
// in-between, to facilitate a sort of "feature-testing", to determine if an alternative like "MemoryStream"
|
||||
// should be used).
|
||||
//
|
||||
// If the mapping fails for whatever reason, return NULL rather than throwing an exception.
|
||||
//
|
||||
// For code using this functionality, ensure usage of map_size() instead of size(), unless you're only using a specific derived
|
||||
// class like MemoryStream() where the value returned by size() won't change unexpectedly due to outside factors.
|
||||
|
||||
virtual uint64 map_size(void) noexcept;
|
||||
// The size of the memory mapping area, point to which returned by map().
|
||||
//
|
||||
// Returns 0 on supported, or if no mapping currently exists.
|
||||
|
||||
virtual void unmap(void) noexcept;
|
||||
// Unmap the stream data from the address space. (Possibly invalidating the pointer returned from map()).
|
||||
// (must automatically be called, if necessary, from the destructor).
|
||||
//
|
||||
// If the data can't be "unmapped" as such because it was never mmap()'d or similar in the first place(such as with MemoryStream),
|
||||
// then this will be a nop.
|
||||
|
||||
virtual uint64 read(void *data, uint64 count, bool error_on_eos = true) = 0;
|
||||
virtual void write(const void *data, uint64 count) = 0;
|
||||
|
||||
virtual void truncate(uint64 length) = 0; // Should have ftruncate()-like semantics; but avoid using it to extend files.
|
||||
|
||||
virtual void seek(int64 offset, int whence = SEEK_SET) = 0;
|
||||
inline void rewind(void)
|
||||
{
|
||||
seek(0, SEEK_SET);
|
||||
}
|
||||
virtual uint64 tell(void) = 0;
|
||||
virtual uint64 size(void) = 0; // May implicitly call flush() if the stream is writeable.
|
||||
virtual void flush(void) = 0;
|
||||
virtual void close(void) = 0; // Flushes(in the case of writeable streams) and closes the stream.
|
||||
// Necessary since this operation can fail(running out of disk space, for instance),
|
||||
// and throw an exception in the destructor would be a Bad Idea(TM).
|
||||
//
|
||||
// Manually calling this function isn't strictly necessary, but recommended when the
|
||||
// stream is writeable; it will be called automatically from the destructor, with any
|
||||
// exceptions thrown caught and logged.
|
||||
|
||||
//
|
||||
// Utility functions(TODO):
|
||||
//
|
||||
INLINE uint8 get_u8(void)
|
||||
{
|
||||
uint8 ret;
|
||||
|
||||
read(&ret, sizeof(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
INLINE void put_u8(uint8 c)
|
||||
{
|
||||
write(&c, sizeof(c));
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
INLINE T get_NE(void)
|
||||
{
|
||||
T ret;
|
||||
|
||||
read(&ret, sizeof(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
INLINE T get_RE(void)
|
||||
{
|
||||
uint8 tmp[sizeof(T)];
|
||||
union
|
||||
{
|
||||
T ret;
|
||||
uint8 ret_u8[sizeof(T)];
|
||||
};
|
||||
|
||||
read(tmp, sizeof(tmp));
|
||||
|
||||
for(unsigned i = 0; i < sizeof(T); i++)
|
||||
ret_u8[i] = tmp[sizeof(T) - 1 - i];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
INLINE void put_NE(T c)
|
||||
{
|
||||
write(&c, sizeof(c));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
INLINE void put_RE(T c)
|
||||
{
|
||||
uint8 tmp[sizeof(T)];
|
||||
|
||||
for(unsigned i = 0; i < sizeof(T); i++)
|
||||
tmp[i] = ((uint8 *)&c)[sizeof(T) - 1 - i];
|
||||
|
||||
write(tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
INLINE T get_LE(void)
|
||||
{
|
||||
#ifdef LSB_FIRST
|
||||
return get_NE<T>();
|
||||
#else
|
||||
return get_RE<T>();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
INLINE void put_LE(T c)
|
||||
{
|
||||
#ifdef LSB_FIRST
|
||||
return put_NE<T>(c);
|
||||
#else
|
||||
return put_RE<T>(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
INLINE T get_BE(void)
|
||||
{
|
||||
#ifndef LSB_FIRST
|
||||
return get_NE<T>();
|
||||
#else
|
||||
return get_RE<T>();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
INLINE void put_BE(T c)
|
||||
{
|
||||
#ifndef LSB_FIRST
|
||||
return put_NE<T>(c);
|
||||
#else
|
||||
return put_RE<T>(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
INLINE void put_string(const char* str)
|
||||
{
|
||||
write(str, strlen(str));
|
||||
}
|
||||
|
||||
// Reads a line into "str", overwriting its contents; returns the line-end char('\n' or '\r' or '\0'), or 256 on EOF and
|
||||
// data has been read into "str", and -1 on EOF when no data has been read into "str".
|
||||
// The line-end char won't be added to "str".
|
||||
// It's up to the caller to handle extraneous empty lines caused by DOS-format text lines(\r\n).
|
||||
// ("str" is passed by reference for the possibility of improved performance by reusing alloced memory for the std::string, though part
|
||||
// of it would be up to the STL implementation).
|
||||
// Implemented as virtual so that a higher-performance version can be implemented if possible(IE with MemoryStream)
|
||||
virtual int get_line(std::string &str);
|
||||
|
||||
virtual void put_line(const std::string& str);
|
||||
|
||||
virtual void print_format(const char *format, ...) MDFN_FORMATSTR(gnu_printf, 2, 3);
|
||||
|
||||
#if 0
|
||||
int scanf(const char *format, ...) MDFN_FORMATSTR(gnu_scanf, 2, 3);
|
||||
void put_string(const char *str);
|
||||
void put_string(const std::string &str);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Read until end-of-stream(or count), discarding any read data, and returns the amount of data "read".
|
||||
// (Useful for detecting and printing warnings about extra garbage data without needing to call size(),
|
||||
// which can be problematic for some types of Streams).
|
||||
uint64 read_discard(uint64 count = ~(uint64)0);
|
||||
|
||||
//
|
||||
// Reads stream starting at the current stream position(as returned by tell()), into memory allocated with malloc() and realloc(), and
|
||||
// sets *data_out to a pointer to the memory(which the caller will need to free() at some point).
|
||||
//
|
||||
// *data_out is only an output.
|
||||
//
|
||||
// If size_limit is/will be exceeded, an exception will be thrown, and *data_out will not be written to.
|
||||
//
|
||||
// Will return the amount of data read.
|
||||
//
|
||||
// If the returned value is 0, *data_out will still be a valid non-NULL pointer.
|
||||
//
|
||||
uint64 alloc_and_read(void** data_out, uint64 size_limit = ~(uint64)0);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue