2022-02-08 15:05:20 +01:00
|
|
|
#ifndef _CONTROLLER_H
|
|
|
|
#define _CONTROLLER_H
|
2023-08-16 19:29:21 +02:00
|
|
|
|
2022-02-08 15:05:20 +01:00
|
|
|
#include "os_internal.h"
|
|
|
|
#include "rcp.h"
|
|
|
|
|
|
|
|
//should go somewhere else but
|
2023-08-16 19:29:21 +02:00
|
|
|
#define ARRLEN(x) ((s32)(sizeof(x) / sizeof(x[0])))
|
|
|
|
#define CHNL_ERR(format) (((format).rxsize & CHNL_ERR_MASK) >> 4)
|
2022-02-08 15:05:20 +01:00
|
|
|
|
2023-08-16 19:29:21 +02:00
|
|
|
typedef struct
|
|
|
|
{
|
2022-02-08 15:05:20 +01:00
|
|
|
/* 0x0 */ u32 ramarray[15];
|
|
|
|
/* 0x3C */ u32 pifstatus;
|
|
|
|
} OSPifRam;
|
|
|
|
|
2023-08-16 19:29:21 +02:00
|
|
|
typedef struct
|
|
|
|
{
|
2022-02-08 15:05:20 +01:00
|
|
|
/* 0x0 */ u8 dummy;
|
|
|
|
/* 0x1 */ u8 txsize;
|
|
|
|
/* 0x2 */ u8 rxsize;
|
|
|
|
/* 0x3 */ u8 cmd;
|
|
|
|
/* 0x4 */ u16 button;
|
|
|
|
/* 0x6 */ s8 stick_x;
|
|
|
|
/* 0x7 */ s8 stick_y;
|
|
|
|
} __OSContReadFormat;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* 0x0 */ u8 dummy;
|
|
|
|
/* 0x1 */ u8 txsize;
|
|
|
|
/* 0x2 */ u8 rxsize;
|
|
|
|
/* 0x3 */ u8 cmd;
|
|
|
|
/* 0x4 */ u8 typeh;
|
|
|
|
/* 0x5 */ u8 typel;
|
|
|
|
/* 0x6 */ u8 status;
|
|
|
|
/* 0x7 */ u8 dummy1;
|
|
|
|
} __OSContRequesFormat;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* 0x0 */ u8 txsize;
|
|
|
|
/* 0x1 */ u8 rxsize;
|
|
|
|
/* 0x2 */ u8 cmd;
|
|
|
|
/* 0x3 */ u8 typeh;
|
|
|
|
/* 0x4 */ u8 typel;
|
|
|
|
/* 0x5 */ u8 status;
|
|
|
|
} __OSContRequesFormatShort;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* 0x0 */ u8 dummy;
|
|
|
|
/* 0x1 */ u8 txsize;
|
|
|
|
/* 0x2 */ u8 rxsize;
|
|
|
|
/* 0x3 */ u8 cmd;
|
2022-03-21 07:47:44 +01:00
|
|
|
/* 0x4 */ u8 addrh;
|
|
|
|
/* 0x5 */ u8 addrl;
|
2022-02-08 15:05:20 +01:00
|
|
|
/* 0x6 */ u8 data[BLOCKSIZE];
|
|
|
|
/* 0x26 */ u8 datacrc;
|
|
|
|
} __OSContRamReadFormat;
|
|
|
|
|
|
|
|
typedef union {
|
|
|
|
/* 0x0 */ struct
|
|
|
|
{
|
|
|
|
/* 0x0 */ u8 bank;
|
|
|
|
/* 0x1 */ u8 page;
|
|
|
|
} inode_t;
|
|
|
|
/* 0x0 */ u16 ipage;
|
|
|
|
} __OSInodeUnit;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* 0x0 */ u32 game_code;
|
|
|
|
/* 0x4 */ u16 company_code;
|
|
|
|
/* 0x6 */ __OSInodeUnit start_page;
|
|
|
|
/* 0x8 */ u8 status;
|
|
|
|
/* 0x9 */ s8 reserved;
|
|
|
|
/* 0xA */ u16 data_sum;
|
|
|
|
/* 0xC */ u8 ext_name[PFS_FILE_EXT_LEN];
|
|
|
|
/* 0x10 */ u8 game_name[PFS_FILE_NAME_LEN];
|
|
|
|
} __OSDir;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* 0x0 */ __OSInodeUnit inode_page[128];
|
|
|
|
} __OSInode;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* 0x0 */ u32 repaired;
|
|
|
|
/* 0x4 */ u32 random;
|
|
|
|
/* 0x8 */ u64 serial_mid;
|
|
|
|
/* 0x10 */ u64 serial_low;
|
|
|
|
/* 0x18 */ u16 deviceid;
|
|
|
|
/* 0x1A */ u8 banks;
|
|
|
|
/* 0x1B */ u8 version;
|
|
|
|
/* 0x1C */ u16 checksum;
|
|
|
|
/* 0x1E */ u16 inverted_checksum;
|
|
|
|
} __OSPackId;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* 0x0 */ u8 txsize;
|
|
|
|
/* 0x1 */ u8 rxsize;
|
|
|
|
/* 0x2 */ u8 cmd;
|
|
|
|
/* 0x3 */ u8 address;
|
|
|
|
/* 0x4 */ u8 data[EEPROM_BLOCK_SIZE];
|
|
|
|
} __OSContEepromFormat;
|
|
|
|
|
2023-08-16 19:29:21 +02:00
|
|
|
// Joybus commands
|
2022-03-21 07:47:44 +01:00
|
|
|
//from: http://en64.shoutwiki.com/wiki/SI_Registers_Detailed#CONT_CMD_Usage
|
2023-08-16 19:29:21 +02:00
|
|
|
#define CONT_CMD_REQUEST_STATUS 0
|
|
|
|
#define CONT_CMD_READ_BUTTON 1
|
|
|
|
#define CONT_CMD_READ_PAK 2
|
|
|
|
#define CONT_CMD_WRITE_PAK 3
|
|
|
|
#define CONT_CMD_READ_EEPROM 4
|
|
|
|
#define CONT_CMD_WRITE_EEPROM 5
|
|
|
|
#define CONT_CMD_READ36_VOICE 9
|
|
|
|
#define CONT_CMD_WRITE20_VOICE 10
|
|
|
|
#define CONT_CMD_READ2_VOICE 11
|
|
|
|
#define CONT_CMD_WRITE4_VOICE 12
|
|
|
|
#define CONT_CMD_SWRITE_VOICE 13
|
|
|
|
#define CONT_CMD_CHANNEL_RESET 0xFD
|
|
|
|
#define CONT_CMD_RESET 0xFF
|
|
|
|
|
|
|
|
// Bytes transmitted for each joybus command
|
|
|
|
#define CONT_CMD_REQUEST_STATUS_TX 1
|
|
|
|
#define CONT_CMD_READ_BUTTON_TX 1
|
|
|
|
#define CONT_CMD_READ_PAK_TX 3
|
|
|
|
#define CONT_CMD_WRITE_PAK_TX 35
|
|
|
|
#define CONT_CMD_READ_EEPROM_TX 2
|
|
|
|
#define CONT_CMD_WRITE_EEPROM_TX 10
|
|
|
|
#define CONT_CMD_READ36_VOICE_TX 3
|
|
|
|
#define CONT_CMD_WRITE20_VOICE_TX 23
|
|
|
|
#define CONT_CMD_READ2_VOICE_TX 3
|
|
|
|
#define CONT_CMD_WRITE4_VOICE_TX 7
|
|
|
|
#define CONT_CMD_SWRITE_VOICE_TX 3
|
|
|
|
#define CONT_CMD_RESET_TX 1
|
|
|
|
|
|
|
|
// Bytes received for each joybus command
|
|
|
|
#define CONT_CMD_REQUEST_STATUS_RX 3
|
|
|
|
#define CONT_CMD_READ_BUTTON_RX 4
|
|
|
|
#define CONT_CMD_READ_PAK_RX 33
|
|
|
|
#define CONT_CMD_WRITE_PAK_RX 1
|
|
|
|
#define CONT_CMD_READ_EEPROM_RX 8
|
|
|
|
#define CONT_CMD_WRITE_EEPROM_RX 1
|
|
|
|
#define CONT_CMD_READ36_VOICE_RX 37
|
|
|
|
#define CONT_CMD_WRITE20_VOICE_RX 1
|
|
|
|
#define CONT_CMD_READ2_VOICE_RX 3
|
|
|
|
#define CONT_CMD_WRITE4_VOICE_RX 1
|
|
|
|
#define CONT_CMD_SWRITE_VOICE_RX 1
|
|
|
|
#define CONT_CMD_RESET_RX 3
|
|
|
|
|
|
|
|
#define CONT_CMD_NOP 0xff
|
|
|
|
#define CONT_CMD_END 0xfe //indicates end of a command
|
|
|
|
#define CONT_CMD_EXE 1 //set pif ram status byte to this to do a command
|
|
|
|
|
|
|
|
#define DIR_STATUS_EMPTY 0
|
|
|
|
#define DIR_STATUS_UNKNOWN 1
|
|
|
|
#define DIR_STATUS_OCCUPIED 2
|
|
|
|
|
|
|
|
// Controller accessory addresses
|
|
|
|
// https://github.com/joeldipops/TransferBoy/blob/master/docs/TransferPakReference.md
|
|
|
|
|
|
|
|
// Accesory detection
|
|
|
|
#define CONT_ADDR_DETECT 0x8000
|
|
|
|
// Rumble
|
|
|
|
#define CONT_ADDR_RUMBLE 0xC000
|
|
|
|
// Controller Pak
|
|
|
|
// Transfer Pak
|
|
|
|
#define CONT_ADDR_GB_POWER 0x8000 // Same as the detection address, but semantically different
|
|
|
|
#define CONT_ADDR_GB_BANK 0xA000
|
|
|
|
#define CONT_ADDR_GB_STATUS 0xB000
|
|
|
|
|
|
|
|
// Addresses sent to controller accessories are in blocks, not bytes
|
|
|
|
#define CONT_BLOCKS(x) ((x) / BLOCKSIZE)
|
|
|
|
|
|
|
|
// Block addresses of the above
|
|
|
|
#define CONT_BLOCK_DETECT CONT_BLOCKS(CONT_ADDR_DETECT)
|
|
|
|
#define CONT_BLOCK_RUMBLE CONT_BLOCKS(CONT_ADDR_RUMBLE)
|
|
|
|
#define CONT_BLOCK_GB_POWER CONT_BLOCKS(CONT_ADDR_GB_POWER)
|
|
|
|
#define CONT_BLOCK_GB_BANK CONT_BLOCKS(CONT_ADDR_GB_BANK)
|
|
|
|
#define CONT_BLOCK_GB_STATUS CONT_BLOCKS(CONT_ADDR_GB_STATUS)
|
|
|
|
|
|
|
|
|
|
|
|
// Transfer pak
|
|
|
|
|
|
|
|
#define GB_POWER_ON 0x84
|
|
|
|
#define GB_POWER_OFF 0xFE
|
|
|
|
|
2022-02-08 15:05:20 +01:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* 0x0 */ __OSInode inode;
|
|
|
|
/* 0x100 */ u8 bank;
|
2023-08-16 19:29:21 +02:00
|
|
|
/* 0x101 */ u8 map[PFS_INODE_DIST_MAP];
|
2022-02-08 15:05:20 +01:00
|
|
|
} __OSInodeCache;
|
|
|
|
|
|
|
|
extern s32 __osEepStatus(OSMesgQueue *, OSContStatus *);
|
|
|
|
u16 __osSumcalc(u8 *ptr, int length);
|
|
|
|
s32 __osIdCheckSum(u16 *ptr, u16 *csum, u16 *icsum);
|
|
|
|
s32 __osRepairPackId(OSPfs *pfs, __OSPackId *badid, __OSPackId *newid);
|
|
|
|
s32 __osCheckPackId(OSPfs *pfs, __OSPackId *temp);
|
|
|
|
s32 __osGetId(OSPfs *pfs);
|
|
|
|
s32 __osCheckId(OSPfs *pfs);
|
|
|
|
s32 __osPfsRWInode(OSPfs *pfs, __OSInode *inode, u8 flag, u8 bank);
|
2022-03-21 07:47:44 +01:00
|
|
|
s32 __osPfsSelectBank(OSPfs *pfs, u8 bank);
|
2023-08-16 19:29:21 +02:00
|
|
|
s32 __osPfsDeclearPage(OSPfs *pfs, __OSInode *inode, int file_size_in_pages, int *first_page, u8 bank, int *decleared, int *last_page);
|
|
|
|
s32 __osPfsReleasePages(OSPfs *pfs, __OSInode *inode, u8 start_page, u8 bank, __OSInodeUnit *last_page);
|
2022-02-08 15:05:20 +01:00
|
|
|
s32 __osBlockSum(OSPfs *pfs, u8 page_no, u16 *sum, u8 bank);
|
|
|
|
s32 __osContRamRead(OSMesgQueue *mq, int channel, u16 address, u8 *buffer);
|
|
|
|
s32 __osContRamWrite(OSMesgQueue *mq, int channel, u16 address, u8 *buffer, int force);
|
|
|
|
void __osContGetInitData(u8 *pattern, OSContStatus *data);
|
|
|
|
void __osPackRequestData(u8 cmd);
|
|
|
|
void __osPfsRequestData(u8 cmd);
|
|
|
|
void __osPfsGetInitData(u8* pattern, OSContStatus* data);
|
|
|
|
u8 __osContAddressCrc(u16 addr);
|
|
|
|
u8 __osContDataCrc(u8 *data);
|
|
|
|
s32 __osPfsGetStatus(OSMesgQueue *queue, int channel);
|
|
|
|
|
|
|
|
extern u8 __osContLastCmd;
|
|
|
|
extern OSTimer __osEepromTimer;
|
|
|
|
extern OSMesg __osEepromTimerMsg;
|
|
|
|
extern OSMesgQueue __osEepromTimerQ;
|
|
|
|
extern OSPifRam __osEepPifRam;
|
|
|
|
extern OSPifRam __osContPifRam;
|
|
|
|
extern OSPifRam __osPfsPifRam;
|
|
|
|
extern u8 __osMaxControllers;
|
|
|
|
|
|
|
|
//some version of this almost certainly existed since there's plenty of times where it's used right before a return 0
|
|
|
|
#define ERRCK(fn) \
|
|
|
|
ret = fn; \
|
|
|
|
if (ret != 0) \
|
2023-08-16 19:29:21 +02:00
|
|
|
return ret
|
2022-02-08 15:05:20 +01:00
|
|
|
|
|
|
|
#define SET_ACTIVEBANK_TO_ZERO \
|
|
|
|
if (pfs->activebank != 0) \
|
|
|
|
{ \
|
2023-08-16 19:29:21 +02:00
|
|
|
ERRCK(__osPfsSelectBank(pfs, 0)); \
|
|
|
|
} (void)0
|
2022-02-08 15:05:20 +01:00
|
|
|
|
|
|
|
#define PFS_CHECK_ID \
|
|
|
|
if (__osCheckId(pfs) == PFS_ERR_NEW_PACK) \
|
2023-08-16 19:29:21 +02:00
|
|
|
return PFS_ERR_NEW_PACK
|
2022-02-08 15:05:20 +01:00
|
|
|
|
|
|
|
#define PFS_CHECK_STATUS \
|
|
|
|
if ((pfs->status & PFS_INITIALIZED) == 0) \
|
2023-08-16 19:29:21 +02:00
|
|
|
return PFS_ERR_INVALID
|
2022-02-08 15:05:20 +01:00
|
|
|
|
|
|
|
#define PFS_GET_STATUS \
|
|
|
|
__osSiGetAccess(); \
|
|
|
|
ret = __osPfsGetStatus(queue, channel); \
|
|
|
|
__osSiRelAccess(); \
|
|
|
|
if (ret != 0) \
|
2023-08-16 19:29:21 +02:00
|
|
|
return ret
|
|
|
|
|
|
|
|
#endif
|