Skip to content

Sio0 rework/pocketstation command additions #995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 39 commits into from
Oct 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
27b6f14
Add enums for some card and pad values
johnbaumann Aug 14, 2022
22fb143
Formatting
johnbaumann Aug 14, 2022
4fd0125
Merge branch 'grumpycoders:main' into sio0_pocketstation_stuff
johnbaumann Aug 15, 2022
ba41d79
Add a command enum
johnbaumann Aug 15, 2022
9be70f2
More enums...
johnbaumann Aug 15, 2022
8209e5e
Moved some code around
johnbaumann Aug 16, 2022
579671a
struct wrapped enums > static casting all the things
johnbaumann Aug 17, 2022
8706e8b
Merge branch 'grumpycoders:main' into sio0_pocketstation_stuff
johnbaumann Aug 20, 2022
b5cba9d
Merge branch 'grumpycoders:main' into sio0_pocketstation_stuff
johnbaumann Aug 24, 2022
4ad87d4
Fully involved dumpster fire
johnbaumann Aug 24, 2022
c1fa9bf
Merge branch 'sio0_pocketstation_stuff' of https://github.com/johnbau…
johnbaumann Aug 24, 2022
3c916c5
Fixed recursive include issue, added a second card
johnbaumann Aug 25, 2022
309ec37
Moved more logic out from read8 and into write8
johnbaumann Aug 25, 2022
34ffec4
Progress commit
johnbaumann Aug 27, 2022
b2500fc
Moved some functions around, generally seems to be working.
johnbaumann Aug 28, 2022
a565bf0
Fix bios mc screen missed xfers, tidy up some
johnbaumann Sep 3, 2022
d93b3c0
Merge branch 'grumpycoders:main' into sio0_pocketstation_stuff
johnbaumann Sep 3, 2022
2f812cb
Organize and rename, try to tidy things up.
johnbaumann Sep 6, 2022
27e45ad
Codacity complaining about this throw
johnbaumann Sep 6, 2022
1f6638c
This one too...
johnbaumann Sep 6, 2022
99763b2
Close file before throwing an exception
johnbaumann Sep 6, 2022
bf80397
Fix a file read derp
johnbaumann Sep 6, 2022
dba0df0
Move registers to struct, begin swapping out savestate bits.
johnbaumann Sep 7, 2022
10e4d65
Move more code around
johnbaumann Sep 7, 2022
dd2c746
Worked on FIFO, changed some behavior
johnbaumann Sep 10, 2022
c84cac3
Rename constants+vars, add buffered writes, some tweaks
johnbaumann Sep 13, 2022
b2664c3
Merge branch 'grumpycoders:main' into sio0_pocketstation_stuff
johnbaumann Sep 13, 2022
c4a0b72
Rename some enums, make their usage a bit more explicit
johnbaumann Sep 14, 2022
6202cd7
Add ps toggle, add other interrupts
johnbaumann Sep 16, 2022
6a81b5e
Merge branch 'grumpycoders:main' into sio0_pocketstation_stuff
johnbaumann Sep 16, 2022
e44a6b0
Refine interrupt behavior, maybe.
johnbaumann Sep 17, 2022
3e66fce
Merge branch 'sio0_pocketstation_stuff' of https://github.com/johnbau…
johnbaumann Sep 17, 2022
c33564e
Add MC vars to savesate, change a few types etc
johnbaumann Sep 18, 2022
f49e19c
Fix pad ACKing bad commands like config mode on digital
johnbaumann Sep 18, 2022
da42c02
Just a quick tidy up here and there...
johnbaumann Sep 19, 2022
6f39af0
Address review concerns
johnbaumann Sep 21, 2022
bf4def5
Decorate all the things, breaks on default, and more
johnbaumann Sep 22, 2022
476b437
use std::make_unique instead
johnbaumann Sep 22, 2022
5244a19
Refine receive irq behavior
johnbaumann Sep 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
498 changes: 498 additions & 0 deletions src/core/memorycard.cc

Large diffs are not rendered by default.

134 changes: 134 additions & 0 deletions src/core/memorycard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/***************************************************************************
* Copyright (C) 2022 PCSX-Redux authors *
* *
* 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. *
***************************************************************************/

#pragma once

#include <stdint.h>

#include "core/sstate.h"

namespace PCSX {
class SIO;

class MemoryCard {
public:
MemoryCard() : m_sio(nullptr) { memset(m_mcdData, 0, c_cardSize); }
MemoryCard(SIO *parent) : m_sio(parent) { memset(m_mcdData, 0, c_cardSize); }

// Hardware events
void acknowledge();
void deselect() {
memset(&m_tempBuffer, 0, c_sectorSize);
m_currentCommand = Commands::None;
m_commandTicks = 0;
m_dataOffset = 0;
m_sector = 0;
m_spdr = Responses::IdleHighZ;
}

// File system / data manipulation
void commit(const PCSX::u8string path) {
if (!m_savedToDisk) {
saveMcd(path);
}
}
void createMcd(const PCSX::u8string mcd);
bool dataChanged() { return !m_savedToDisk; }
void disablePocketstation() { m_pocketstationEnabled = false; };
void enablePocketstation() { m_pocketstationEnabled = true; };
char *getMcdData() { return m_mcdData; }
void loadMcd(const PCSX::u8string str);
void saveMcd(const PCSX::u8string mcd, const char *data, uint32_t adr, size_t size);
void saveMcd(const PCSX::u8string path) { saveMcd(path, m_mcdData, 0, c_cardSize); }

private:
enum Commands : uint8_t {
Access = 0x81, // Memory Card Select
Read = 0x52, // Read Command
GetID = 0x53, // Get ID Command
Write = 0x57, // Write Command
None = 0x00, // No command, idle state
Error = 0xFF, // Bad command

// PocketStation command extensions
PS_ChangeFuncValue = 0x50, // Change a FUNC 03h related value or so
PS_GetVersion = 0x58, // Get an ID or Version value or so
PS_PrepFileExec = 0x59, // Prepare File Execution with Dir_index, and Parameter
PS_GetDirIndex = 0x5A, // Get Dir_index, ComFlags, F_SN, Date, and Time
PS_ExecXferPSToPSX = 0x5B, // Execute Function and transfer data from Pocketstation to PSX
PS_ExecXferPSXToPS = 0x5C, // Execute Function and transfer data from PSX to Pocketstation
PS_ExecCustom = 0x5D, // Execute Custom Download Notification Function ;via SWI 01h with r0=3
PS_GetComFlagsHi = 0x5E, // Get-and-Send ComFlags.bit1,3,2
PS_GetComFlagsLo = 0x5F, // Get-and-Send ComFlags.bit0
};
enum Flags : uint8_t {
DirectoryUnread = 0x08, // Initial power on value
DirectoryRead = 0x00 // Cleared after good MC Write
// (test write sector 3F = 0x1F80) offset
};
enum Responses : uint8_t {
IdleHighZ = 0xFF, // High default state
Dummy = 0x00, // Filler Data
ID1 = 0x5A, // Memory Card ID1
ID2 = 0x5D, // Memory Card ID2
CommandAcknowledge1 = 0x5C, // Command Acknowledge 1
CommandAcknowledge2 = 0x5D, // Command Acknowledge 2
GoodReadWrite = 0x47, // Good Read/Write
BadChecksum = 0x4E, // Bad Checksum during Write
BadSector = 0xFF, // Bad Memory Card Sector
};

friend class SIO;
friend SaveStates::SaveState SaveStates::constructSaveState();

static constexpr size_t c_sectorSize = 8 * 16;
static constexpr size_t c_blockSize = 8192;
static constexpr size_t c_cardSize = 1024 * c_sectorSize;

// State machine / handlers
uint8_t transceive(uint8_t value);
uint8_t tickReadCommand(uint8_t value);
uint8_t tickWriteCommand(uint8_t value);
uint8_t tickPS_GetDirIndex(uint8_t value); // 5Ah
uint8_t tickPS_GetVersion(uint8_t value); // 58h
uint8_t tickPS_PrepFileExec(uint8_t value); // 59h
uint8_t tickPS_ExecCustom(uint8_t value); // 5Dh

char m_mcdData[c_cardSize];
uint8_t m_tempBuffer[c_sectorSize];
bool m_savedToDisk = false;

uint8_t m_checksumIn = 0, m_checksumOut = 0;
uint16_t m_commandTicks = 0;
uint8_t m_currentCommand = Commands::None;
uint16_t m_sector = 0;
uint32_t m_dataOffset = 0;

uint8_t m_directoryFlag = Flags::DirectoryUnread;

uint8_t m_spdr = Responses::IdleHighZ;

// PocketStation Specific
bool m_pocketstationEnabled = false;
uint16_t m_directoryIndex = 0;

SIO *m_sio;
};

} // namespace PCSX
37 changes: 27 additions & 10 deletions src/core/pad.cc
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ bool PCSX::Pads::Pad::isControllerButtonPressed(int button, GLFWgamepadstate* st
return false;
default:
return state->buttons[mapped];
break;
}
}

Expand Down Expand Up @@ -240,7 +241,9 @@ void PCSX::Pads::Pad::getButtons() {
float a = 0;
if ((x * x) > (y * y)) {
a = std::acos(x);
if (y < 0) a = π(2.0f) - a;
if (y < 0) {
a = π(2.0f) - a;
}
} else {
a = std::asin(y);
if (x < 0) {
Expand Down Expand Up @@ -309,7 +312,7 @@ uint8_t PCSX::Pads::Pad::poll(uint8_t value, uint32_t& padState) {
PCSX::g_system->log(PCSX::LogClass::SIO0, _("Unknown command for pad: %02X\n"), value);
m_cmd = magic_enum::enum_integer(PadCommands::Idle);
m_bufferLen = 0;
padState = PAD_STATE_IDLE; // Tell the SIO class we're in an invalid state
padState = PAD_STATE_BAD_COMMAND; // Tell the SIO class we're in an invalid state
return 0xff;
}
} else if (m_currentByte >= m_bufferLen) {
Expand Down Expand Up @@ -361,7 +364,7 @@ uint8_t PCSX::Pads::Pad::doDualshockCommand(uint32_t& padState) {

if (m_cmd == magic_enum::enum_integer(PadCommands::SetConfigMode)) {
if (m_configMode) { // The config mode version of this command does not reply with pad data
static const uint8_t reply[] = {0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static constexpr uint8_t reply[] = {0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
std::memcpy(m_buf, reply, 8);
return 0xf3;
} else {
Expand Down Expand Up @@ -402,7 +405,7 @@ uint8_t PCSX::Pads::Pad::doDualshockCommand(uint32_t& padState) {
PCSX::g_system->log(PCSX::LogClass::SIO0, _("Unknown command for pad: %02X\n"), static_cast<uint8_t>(m_cmd));
m_cmd = magic_enum::enum_integer(PadCommands::Idle);
m_bufferLen = 0;
padState = PAD_STATE_IDLE; // Tell the SIO class we're in an invalid state
padState = PAD_STATE_BAD_COMMAND; // Tell the SIO class we're in an invalid state
return 0xff;
}
}
Expand Down Expand Up @@ -479,6 +482,7 @@ uint8_t PCSX::Pads::Pad::read() {
memcpy(m_buf, m_stdpar, 4);
m_bufferLen = 4;
return 0x41;
break;
}
}

Expand Down Expand Up @@ -776,6 +780,7 @@ int& PCSX::Pads::Pad::getButtonFromGUIIndex(int buttonIndex) {
return m_settings.get<Keyboard_PadLeft>().value;
default:
abort();
break;
}
}

Expand Down Expand Up @@ -827,8 +832,12 @@ void PCSX::Pads::Pad::setDefaults(bool firstController) {
void PCSX::Pads::setLua(Lua L) {
auto getButton = [this](Lua L, unsigned pad) -> int {
int n = L.gettop();
if (n == 0) return L.error("Not enough arguments to getButton");
if (!L.isnumber(1)) return L.error("Invalid argument to getButton");
if (n == 0) {
return L.error("Not enough arguments to getButton");
}
if (!L.isnumber(1)) {
return L.error("Invalid argument to getButton");
}
auto buttons = m_pads[pad].m_data.buttonStatus;
unsigned button = L.checknumber(1);
L.push((buttons & (1 << button)) == 0);
Expand All @@ -837,8 +846,12 @@ void PCSX::Pads::setLua(Lua L) {

auto setOverride = [this](Lua L, unsigned pad) -> int {
int n = L.gettop();
if (n == 0) return L.error("Not enough arguments to setOverride");
if (!L.isnumber(1)) return L.error("Invalid argument to setOverride");
if (n == 0) {
return L.error("Not enough arguments to setOverride");
}
if (!L.isnumber(1)) {
return L.error("Invalid argument to setOverride");
}
auto& overrides = m_pads[pad].m_data.overrides;
unsigned button = L.checknumber(1);
button = 1 << button;
Expand All @@ -848,8 +861,12 @@ void PCSX::Pads::setLua(Lua L) {

auto clearOverride = [this](Lua L, unsigned pad) -> int {
int n = L.gettop();
if (n == 0) return L.error("Not enough arguments to clearOverride");
if (!L.isnumber(1)) return L.error("Invalid argument to clearOverride");
if (n == 0) {
return L.error("Not enough arguments to clearOverride");
}
if (!L.isnumber(1)) {
return L.error("Invalid argument to clearOverride");
}
auto& overrides = m_pads[pad].m_data.overrides;
unsigned button = L.checknumber(1);
button = 1 << button;
Expand Down
16 changes: 13 additions & 3 deletions src/core/pad.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ enum {
PAD_STATE_IDLE = 0,
PAD_STATE_READ_COMMAND = 1,
PAD_STATE_READ_DATA = 2,
PAD_STATE_BAD_COMMAND = 3,
};

class Pads {
Expand All @@ -68,13 +69,21 @@ class Pads {

void setLua(Lua L);

bool isPadConnected(int pad) {
if (pad > m_pads.size()) {
return false;
} else {
return m_pads[pad - 1].isControllerConnected();
}
}

private:
EventBus::Listener m_listener;
int m_gamepadsMap[16] = {0};

static const int GLFW_GAMEPAD_BUTTON_LEFT_TRIGGER = GLFW_GAMEPAD_BUTTON_LAST + 1;
static const int GLFW_GAMEPAD_BUTTON_RIGHT_TRIGGER = GLFW_GAMEPAD_BUTTON_LAST + 2;
static const int GLFW_GAMEPAD_BUTTON_INVALID = GLFW_GAMEPAD_BUTTON_LAST + 3;
static constexpr int GLFW_GAMEPAD_BUTTON_LEFT_TRIGGER = GLFW_GAMEPAD_BUTTON_LAST + 1;
static constexpr int GLFW_GAMEPAD_BUTTON_RIGHT_TRIGGER = GLFW_GAMEPAD_BUTTON_LAST + 2;
static constexpr int GLFW_GAMEPAD_BUTTON_INVALID = GLFW_GAMEPAD_BUTTON_LAST + 3;

// settings block
// Pad keyboard bindings
Expand Down Expand Up @@ -164,6 +173,7 @@ class Pads {
uint8_t doDualshockCommand(uint32_t &padState);
void getButtons();
bool isControllerButtonPressed(int button, GLFWgamepadstate *state);
bool isControllerConnected() { return m_settings.get<SettingConnected>(); }

json getCfg();
void setCfg(const json &j);
Expand Down
2 changes: 1 addition & 1 deletion src/core/psxemulator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ int PCSX::Emulator::init() {
}

setPGXPMode(m_config.PGXP_Mode);
m_pads->init();
m_sio->init();
return ret;
}

Expand Down
5 changes: 4 additions & 1 deletion src/core/psxemulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,16 @@ class Emulator {
typedef Setting<int, TYPESTRING("MSAA"), 1> SettingMSAA;
typedef Setting<bool, TYPESTRING("LinearFiltering"), true> SettingLinearFiltering;
typedef Setting<bool, TYPESTRING("KioskMode"), false> SettingKioskMode;
typedef Setting<bool, TYPESTRING("Mcd1Pocketstation"), false> SettingMcd1Pocketstation;
typedef Setting<bool, TYPESTRING("Mcd2Pocketstation"), false> SettingMcd2Pocketstation;

Settings<SettingStdout, SettingLogfile, SettingMcd1, SettingMcd2, SettingBios, SettingPpfDir, SettingPsxExe,
SettingXa, SettingSpuIrq, SettingBnWMdec, SettingScaler, SettingAutoVideo, SettingVideo, SettingFastBoot,
SettingDebugSettings, SettingRCntFix, SettingIsoPath, SettingLocale, SettingMcd1Inserted,
SettingMcd2Inserted, SettingDynarec, Setting8MB, SettingGUITheme, SettingDither, SettingGLErrorReporting,
SettingGLErrorReportingSeverity, SettingFullCaching, SettingHardwareRenderer, SettingShownAutoUpdateConfig,
SettingAutoUpdate, SettingMSAA, SettingLinearFiltering, SettingKioskMode>
SettingAutoUpdate, SettingMSAA, SettingLinearFiltering, SettingKioskMode, SettingMcd1Pocketstation,
SettingMcd2Pocketstation>
settings;
class PcsxConfig {
public:
Expand Down
Loading