Skip to content

Commit

Permalink
Merge pull request #88 from imaandrew/sc64
Browse files Browse the repository at this point in the history
Add SC64 support
  • Loading branch information
JCog authored Sep 24, 2024
2 parents 327706d + 6613027 commit 7a2935d
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 4 deletions.
1 change: 1 addition & 0 deletions lib/libpm-jp.a
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pm_fioFetchSavedFileInfo = 0x8002B114;
pm_fioDeserializeState = 0x8002B450;
pm_fioReadFlash = 0x8002B828;
pm_fioWriteFlash = 0x8002B908;
pm_fioEraseFlash = 0x8002B9DC;
pm_setCurtainScaleGoal = 0x8002BE9C;
pm_update_cameras = 0x8002D090;
pm_update_camera_zone_interp = 0x80031124;
Expand Down
1 change: 1 addition & 0 deletions lib/libpm-us.a
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pm_fioFetchSavedFileInfo = 0x8002B154;
pm_fioDeserializeState = 0x8002B490;
pm_fioReadFlash = 0x8002B868;
pm_fioWriteFlash = 0x8002B948;
pm_fioEraseFlash = 0x8002BA1C;
pm_setCurtainScaleGoal = 0x8002BEDC;
pm_setCurtainDrawCallback = 0x8002BF04;
pm_setCurtainFadeGoal = 0x8002BF14;
Expand Down
6 changes: 2 additions & 4 deletions src/io/io.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "ed64_io.h"
#include "hb_io.h"
#include "iodev.h"
#include "sc64_io.h"
#include <errno.h>
#include <n64.h>

Expand All @@ -18,10 +19,7 @@ static struct Iodev *currentDev;

s32 ioInit(void) {
struct Iodev *devs[] = {
&homeboyIodev,
&everdrive64X,
&everdrive64V2,
&everdrive64V1,
&homeboyIodev, &everdrive64X, &everdrive64V2, &everdrive64V1, &sc64,
};

s32 nDevs = sizeof(devs) / sizeof(devs[0]);
Expand Down
191 changes: 191 additions & 0 deletions src/io/sc64.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#include "sc64.h"
#include "io/iodev.h"
#include "pi.h"
#include "util/util.h"
#include <stddef.h>

static s32 cartIrqf;
static u32 cartLat;
static u32 cartPwd;

_Alignas(16) static u64 cartBuf[512 / 8];

static void cartBufRd(const void *addr) {
const uu64 *ptr = addr;
for (s32 i = 0; i < 512 / 8; i += 2) {
u64 a = ptr[i + 0];
u64 b = ptr[i + 1];
cartBuf[i + 0] = a;
cartBuf[i + 1] = b;
}
}

static void cartBufWr(void *addr) {
uu64 *ptr = addr;
for (s32 i = 0; i < 512 / 8; i += 2) {
u64 a = cartBuf[i + 0];
u64 b = cartBuf[i + 1];
ptr[i + 0] = a;
ptr[i + 1] = b;
}
}

static void cartLock(void) {
__osPiGetAccess();

cartIrqf = setIrqf(0);

cartLat = pi_regs.dom1_lat;
cartPwd = pi_regs.dom1_pwd;
}

static void cartUnlock(void) {
pi_regs.dom1_lat = cartLat;
pi_regs.dom1_pwd = cartPwd;

__osPiRelAccess();

setIrqf(cartIrqf);
}

static inline u32 regRd(s32 reg) {
return __piReadRaw((u32)&REGS_PTR[reg]);
}

static inline void regWr(s32 reg, u32 dat) {
return __piWriteRaw((u32)&REGS_PTR[reg], dat);
}

static s32 scSync(void) {
while (regRd(SC_STATUS_REG) & SC_CMD_BUSY) {
;
}
if (regRd(SC_STATUS_REG) & SC_CMD_ERROR) {
return -1;
}
return 0;
}

static s32 probe(void) {
cartLock();

/* open registers */
regWr(SC_KEY_REG, SC_KEY_RESET);
regWr(SC_KEY_REG, SC_KEY_UNL);
regWr(SC_KEY_REG, SC_KEY_OCK);

/* check magic number */
if ((regRd(SC_IDENTIFIER_REG)) != SC_IDENTIFIER) {
regWr(SC_KEY_REG, 0);
CART_ABORT();
}

scSync();
cartUnlock();
return 0;
}

static s32 diskInit(void) {
cartLock();
scSync();

regWr(SC_DATA1_REG, SC_SD_INIT);
regWr(SC_COMMAND_REG, SC_SD_OP);

if (scSync()) {
regWr(SC_KEY_REG, 0);
CART_ABORT();
}

cartUnlock();
return 0;
}

static s32 diskRead(size_t lba, size_t nBlocks, void *dst) {
char *addr = dst;
s32 n;
cartLock();
scSync();

while (nBlocks > 0) {
n = nBlocks < 16 ? nBlocks : 16;

regWr(SC_DATA0_REG, lba);
regWr(SC_COMMAND_REG, SC_SD_SECTOR_SET);

if (scSync()) {
CART_ABORT();
}

regWr(SC_DATA0_REG, SC_BUFFER_REG);
regWr(SC_DATA1_REG, n);
regWr(SC_COMMAND_REG, SC_SD_READ);

if (scSync()) {
CART_ABORT();
}

if ((u32)addr & 7) {
for (s32 i = 0; i < n; i++) {
piReadLocked(SC_BUFFER_REG + 512 * i, cartBuf, 512);
cartBufWr(addr);
addr += 512;
}
} else {
piReadLocked(SC_BUFFER_REG, addr, 512 * n);
addr += 512 * n;
}

lba += n;
nBlocks -= n;
}

cartUnlock();
return 0;
}

static s32 diskWrite(size_t lba, size_t nBlocks, const void *src) {
const char *addr = src;
s32 n;
cartLock();
scSync();

while (nBlocks > 0) {
n = nBlocks < 16 ? nBlocks : 16;

if ((u32)addr & 7) {
for (s32 i = 0; i < n; i++) {
cartBufRd(addr);
piWriteLocked(SC_BUFFER_REG + 512 * i, cartBuf, 512);
addr += 512;
}
} else {
piWriteLocked(SC_BUFFER_REG, addr, 512 * n);
addr += 512 * n;
}

scSync();
regWr(SC_DATA0_REG, lba);
regWr(SC_COMMAND_REG, SC_SD_SECTOR_SET);

if (scSync()) {
CART_ABORT();
}

regWr(SC_DATA0_REG, SC_BUFFER_REG);
regWr(SC_DATA1_REG, n);
regWr(SC_COMMAND_REG, SC_SD_WRITE);

if (scSync()) {
CART_ABORT();
}

lba += n;
nBlocks -= n;
}

cartUnlock();
return 0;
}

struct Iodev sc64 = {.probe = probe, .diskInit = diskInit, .diskRead = diskRead, .diskWrite = diskWrite};
56 changes: 56 additions & 0 deletions src/io/sc64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef SC64_H
#define SC64_H

#include "types.h"

#define SC_BASE_REG 0xBFFF0000
#define SC_BUFFER_REG 0xBFFE0000
#define REGS_PTR ((volatile u32 *)SC_BASE_REG)

#define SC_STATUS_REG 0
#define SC_COMMAND_REG 0
#define SC_DATA0_REG 1
#define SC_DATA1_REG 2
#define SC_IDENTIFIER_REG 3
#define SC_KEY_REG 4

#define SC_CMD_BUSY 0x80000000
#define SC_CMD_ERROR 0x40000000
#define SC_IRQ_PENDING 0x20000000

#define SC_CONFIG_GET 'c'
#define SC_CONFIG_SET 'C'
#define SC_SD_OP 'i'
#define SC_SD_SECTOR_SET 'I'
#define SC_SD_READ 's'
#define SC_SD_WRITE 'S'

#define SC_CFG_ROM_WRITE 1
#define SC_CFG_DD_MODE 3
#define SC_CFG_SAVE_TYPE 6

#define SC_SD_DEINIT 0
#define SC_SD_INIT 1
#define SC_SD_GET_STATUS 2
#define SC_SD_GET_INFO 3
#define SC_SD_BYTESWAP_ON 4
#define SC_SD_BYTESWAP_OFF 5

#define SC_DD_MODE_REGS 1
#define SC_DD_MODE_IPL 2

#define SC_IDENTIFIER 0x53437632 /* SCv2 */

#define SC_KEY_RESET 0x00000000
#define SC_KEY_LOCK 0xFFFFFFFF
#define SC_KEY_UNL 0x5F554E4C /* _UNL */
#define SC_KEY_OCK 0x4F434B5F /* OCK_ */

typedef u64 uu64 __attribute__((aligned(1))); // NOLINT
#define CART_ABORT() \
{ \
cartUnlock(); \
return -1; \
}

#endif
8 changes: 8 additions & 0 deletions src/io/sc64_io.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef SC64_IO_H
#define SC64_IO_H

struct Iodev;

extern struct Iodev sc64;

#endif
1 change: 1 addition & 0 deletions src/pm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,7 @@ bool pm_fioFetchSavedFileInfo(void);
void pm_fioDeserializeState(void);
void pm_fioReadFlash(s32 slot, void *buffer, u32 size); // writes to buffer in 128-byte blocks
void pm_fioWriteFlash(s32 slot, void *buffer, u32 size);
void pm_fioEraseFlash(s32 slot);
void pm_setCurtainScaleGoal(f32 goal);
void pm_setCurtainDrawCallback(void *callback);
void pm_setCurtainFadeGoal(f32 goal);
Expand Down
1 change: 1 addition & 0 deletions src/sys/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ void settingsSave(s32 profile) {
pm_fioReadFlash(SETTINGS_FIO_PAGE, &settingsBuffer, sizeof(settingsBuffer));
settingsStore.header.dataChecksum = settingsChecksumCompute(&settingsStore);
memcpy(&settingsBuffer[profile], &settingsStore, sizeof(settingsStore));
pm_fioEraseFlash(SETTINGS_FIO_PAGE);
pm_fioWriteFlash(SETTINGS_FIO_PAGE, &settingsBuffer, sizeof(settingsBuffer));
}

Expand Down

0 comments on commit 7a2935d

Please sign in to comment.