Skip to content

Commit 31d8180

Browse files
committed
Proper copy/move semantic.
1 parent 80e942a commit 31d8180

File tree

4 files changed

+219
-246
lines changed

4 files changed

+219
-246
lines changed

src/core/sio.cc

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <sys/stat.h>
2323

2424
#include <algorithm>
25+
#include <bitset>
2526
#include <stdexcept>
2627

2728
#include "core/misc.h"
@@ -729,6 +730,7 @@ void PCSX::SIO::getMcdBlockInfo(int mcd, int block, McdBlock &info) {
729730

730731
info.reset();
731732
info.number = block;
733+
info.mcd = mcd;
732734

733735
char *data = getMcdData(mcd);
734736
uint8_t *ptr = reinterpret_cast<uint8_t *>(data) + block * MCD_BLOCK_SIZE + 2;
@@ -837,11 +839,12 @@ void PCSX::SIO::getMcdBlockInfo(int mcd, int block, McdBlock &info) {
837839
uint16_t nextBlock = 0;
838840
nextBlock |= directoryFrame[8];
839841
nextBlock |= directoryFrame[9] << 8;
840-
info.nextBlock = nextBlock;
842+
info.nextBlock = nextBlock == 0xffff ? -1 : (nextBlock + 1);
841843

842844
// Check if the block is marked as free in the directory frame and adjust the name/filename if so
843845
if (info.isErased()) {
844846
info.reset();
847+
info.allocState = 0xa0;
845848
info.titleAscii = "Free Block";
846849
info.titleSjis = "Free Block";
847850
info.titleUtf8 = "Free Block";
@@ -862,8 +865,8 @@ char *PCSX::SIO::getMcdData(int mcd) {
862865

863866
// Erase a memory card block by clearing it with 0s
864867
// mcd: The memory card we want to use (1 or 2)
865-
void PCSX::SIO::eraseMcdBlock(int mcd, const McdBlock &block) {
866-
char *data = getMcdData(mcd);
868+
void PCSX::SIO::eraseMcdFile(const McdBlock &block) {
869+
char *data = getMcdData(block.mcd);
867870

868871
// Set the block data to 0
869872
const size_t offset = block.number * MCD_BLOCK_SIZE;
@@ -881,8 +884,83 @@ void PCSX::SIO::eraseMcdBlock(int mcd, const McdBlock &block) {
881884
auto nextBlock = block.nextBlock;
882885
if ((nextBlock >= 1) && (nextBlock <= 15)) {
883886
McdBlock next;
884-
getMcdBlockInfo(mcd, nextBlock, next);
885-
eraseMcdBlock(mcd, next);
887+
getMcdBlockInfo(block.mcd, nextBlock, next);
888+
eraseMcdFile(next);
889+
}
890+
}
891+
892+
unsigned PCSX::SIO::getFreeSpace(int mcd) {
893+
unsigned count = 0;
894+
for (int i = 1; i < 16; i++) {
895+
McdBlock block;
896+
getMcdBlockInfo(mcd, i, block);
897+
if (block.isErased()) count++;
898+
}
899+
900+
return count;
901+
}
902+
903+
unsigned PCSX::SIO::getFileBlockCount(McdBlock block) {
904+
if (block.isErased()) return 0;
905+
906+
std::bitset<16> walked;
907+
unsigned count = 1;
908+
909+
while (true) {
910+
if ((block.nextBlock < 1) || (block.nextBlock > 15)) return count;
911+
if (walked.test(block.nextBlock)) return count;
912+
walked.set(block.nextBlock);
913+
getMcdBlockInfo(block.mcd, block.nextBlock, block);
914+
count++;
915+
}
916+
}
917+
918+
int PCSX::SIO::findFirstFree(int mcd) {
919+
McdBlock block;
920+
for (int i = 1; i < 16; i++) {
921+
getMcdBlockInfo(mcd, i, block);
922+
if (block.isErased()) return i;
923+
}
924+
925+
return -1;
926+
}
927+
928+
bool PCSX::SIO::copyMcdFile(McdBlock block) {
929+
auto other = otherMcd(block);
930+
if (getFreeSpace(other) < getFileBlockCount(block)) return false;
931+
const auto const data = getMcdData(block);
932+
const auto otherData = getMcdData(other);
933+
934+
std::bitset<16> walked;
935+
int prevBlock = -1;
936+
937+
while (true) {
938+
int dstBlock = findFirstFree(other);
939+
if (dstBlock < 1 || dstBlock > 16) throw std::runtime_error("Inconsistent memory card state");
940+
941+
// copy block data
942+
size_t srcOffset = block.number * MCD_BLOCK_SIZE;
943+
size_t dstOffset = dstBlock * MCD_BLOCK_SIZE;
944+
std::memcpy(otherData + dstOffset, data + srcOffset, MCD_BLOCK_SIZE);
945+
946+
// copy directory entry
947+
srcOffset = block.number * MCD_SECT_SIZE;
948+
dstOffset = dstBlock * MCD_SECT_SIZE;
949+
std::memcpy(otherData + dstOffset, data + srcOffset, MCD_SECT_SIZE);
950+
951+
// Fix up the corresponding directory frame in block 0.
952+
if (prevBlock != -1) {
953+
const auto frame = reinterpret_cast<uint8_t *>(otherData) + prevBlock * MCD_SECT_SIZE;
954+
uint8_t crcFix = frame[8] ^ (dstBlock - 1);
955+
frame[8] = dstBlock - 1;
956+
frame[0x7f] ^= crcFix;
957+
}
958+
prevBlock = dstBlock;
959+
if (block.nextBlock == -1) return true;
960+
if ((block.nextBlock < 1) || (block.nextBlock > 15)) return false;
961+
if (walked.test(block.nextBlock)) return false;
962+
walked.set(block.nextBlock);
963+
getMcdBlockInfo(block.mcd, block.nextBlock, block);
886964
}
887965
}
888966

src/core/sio.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ class SIO {
135135

136136
struct McdBlock {
137137
McdBlock() { reset(); }
138+
int mcd;
138139
int number;
139140
std::string titleAscii;
140141
std::string titleSjis;
@@ -147,6 +148,7 @@ class SIO {
147148
uint32_t allocState;
148149
int16_t nextBlock;
149150
void reset() {
151+
mcd = 0;
150152
number = 0;
151153
titleAscii.clear();
152154
titleSjis.clear();
@@ -164,13 +166,24 @@ class SIO {
164166
};
165167

166168
void getMcdBlockInfo(int mcd, int block, McdBlock &info);
167-
void eraseMcdBlock(int mcd, const McdBlock &block);
168-
void eraseMcdBlock(int mcd, int block) {
169+
void eraseMcdFile(const McdBlock &block);
170+
void eraseMcdFile(int mcd, int block) {
169171
McdBlock info;
170172
getMcdBlockInfo(mcd, block, info);
171-
eraseMcdBlock(mcd, block);
173+
eraseMcdFile(info);
172174
}
175+
static constexpr int otherMcd(int mcd) {
176+
if ((mcd != 1) && (mcd != 2)) throw std::runtime_error("Bad memory card number");
177+
if (mcd == 1) return 2;
178+
return 1;
179+
}
180+
static constexpr int otherMcd(const McdBlock &block) { return otherMcd(block.mcd); }
181+
unsigned getFreeSpace(int mcd);
182+
unsigned getFileBlockCount(McdBlock block);
183+
int findFirstFree(int mcd);
184+
bool copyMcdFile(McdBlock block);
173185
char *getMcdData(int mcd);
186+
char *getMcdData(const McdBlock &block) { return getMcdData(block.mcd); }
174187

175188
static void SIO1irq(void) { psxHu32ref(0x1070) |= SWAP_LEu32(0x100); }
176189

0 commit comments

Comments
 (0)