mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-05 07:08:49 +00:00
drafting
This commit is contained in:
@@ -81,18 +81,12 @@ atom_dbg_skip MipsAtom_(tape_exit) { jump_reg(rret_addr), nop };
|
||||
//TODO(Ed): Do we backup R_S0-7 here? Have it in a heavier tape run as a opt-in? Same with V0-1 and A0-3?
|
||||
/* Generalized Tape Engine Runner */
|
||||
FI_ void tape_run(Slice_MipsCode tape) { register U4* tape_ptr rgcc(R_TapePtr) = u4_r(tape.ptr); asm volatile(
|
||||
// Removed, not needed
|
||||
/*add_ui( R_SP, R_SP, -MipsStackAlignment)*/ /* Allocate stack space */
|
||||
/*, store_word( R_RA, R_SP, 0)*/ /* Safely backup $ra to the stack */
|
||||
asm_words(
|
||||
load_word( R_AtomJmp, R_TapePtr, 0) /* Bootstrap the first jump */
|
||||
, add_ui_self(R_TapePtr, S_(MipsCode)) /* Advance tape */
|
||||
, call_reg( R_AtomJmp) /* jalr $t9 */
|
||||
, nop /* Branch delay slot */
|
||||
load_word( R_AtomJmp, R_TapePtr, 0) /* Bootstrap the first jump */
|
||||
, add_ui_self(R_TapePtr, S_(MipsCode)) /* Advance tape */
|
||||
, call_reg( R_AtomJmp) /* jalr $t9 */
|
||||
, nop /* Branch delay slot */
|
||||
)
|
||||
// Removed, not needed
|
||||
/*, load_word( R_RA, R_SP, 0)* /* Restore $ra from stack */
|
||||
/*, add_ui_self(R_SP, MipsStackAlignment)*/ /* Deallocate stack space */
|
||||
asm_rpins, r_use(tape_ptr)
|
||||
asm_clobber:
|
||||
rlit(R_AT)
|
||||
|
||||
@@ -36,3 +36,108 @@ enum {
|
||||
void pad_init(U4 mode) asm("PadInit");
|
||||
U4 pad_read(U4 id) asm("PadRead");
|
||||
|
||||
/* ============================================================
|
||||
* SIO0 raw controller polling surface (Phase 1 scaffolding)
|
||||
* Source of truth: docs/psx-spx/docs/serialinterfacessio.md
|
||||
* docs/psx-spx/docs/controllersandmemorycards.md
|
||||
* https://github.com/Lameguy64/PSn00bSDK (spi.c)
|
||||
* ============================================================ */
|
||||
|
||||
enum {
|
||||
/* SIO0 register offsets relative to IOBASE 0xBF800000 */
|
||||
pad_SIO_DATA_OFFSET = 0x1040, /* 8-bit data (TX write / RX read) */
|
||||
pad_SIO_STAT_OFFSET = 0x1044, /* 16-bit status */
|
||||
pad_SIO_MODE_OFFSET = 0x1048, /* 16-bit mode */
|
||||
pad_SIO_CTRL_OFFSET = 0x104A, /* 16-bit control */
|
||||
pad_SIO_BAUD_OFFSET = 0x104E, /* 16-bit baud */
|
||||
|
||||
/* SIO_CTRL bit flags */
|
||||
pad_SIO_CTRL_RESET = 0x0040, /* reset most SIO registers */
|
||||
pad_SIO_CTRL_TX_ENABLE = 0x0001, /* TX enable */
|
||||
pad_SIO_CTRL_DTR_CS = 0x0002, /* DTR drives /CS on controller */
|
||||
pad_SIO_CTRL_ACK = 0x0010, /* acknowledge / clear status */
|
||||
pad_SIO_CTRL_DSR_IRQ = 0x1000, /* enable /ACK IRQ (unused; polling) */
|
||||
|
||||
/* SIO_STAT bit flags */
|
||||
pad_SIO_STAT_TX_READY = 0x0001,
|
||||
pad_SIO_STAT_RX_NOT_EMPTY = 0x0002,
|
||||
pad_SIO_STAT_TX_IDLE = 0x0004,
|
||||
pad_SIO_STAT_DSR_ACK = 0x0080,
|
||||
|
||||
/* SIO init values (per docs/psx-spx/docs/serialinterfacessio.md) */
|
||||
pad_SIO_MODE_INIT = 0x000D, /* MUL1, 8-bit, no parity, idle-high */
|
||||
pad_SIO_BAUD_INIT = 0x0088, /* ~250 kHz standard rate */
|
||||
pad_SIO_CTRL_CLEANUP = 0x0010, /* raise /CS + clear stale status */
|
||||
|
||||
/* Controller protocol bytes (per docs/psx-spx/docs/controllersandmemorycards.md) */
|
||||
pad_PROTO_ADDR = 0x01,
|
||||
pad_PROTO_CMD_READ = 0x42,
|
||||
pad_PROTO_CMD_ENTERCFG = 0x43,
|
||||
pad_PROTO_CMD_SETLED = 0x44,
|
||||
pad_PROTO_PREFIX = 0x5A,
|
||||
pad_PROTO_PREFIX_QUIRK = 0x00, /* DualShock: Analog-button swap after cfg */
|
||||
|
||||
/* Controller response ID nibble (low 4 bits of ID byte) */
|
||||
pad_PROTO_ID_DIGITAL = 0x41,
|
||||
pad_PROTO_ID_ANALOG_STK = 0x53,
|
||||
pad_PROTO_ID_ANALOG = 0x73,
|
||||
pad_PROTO_ID_CONFIG = 0xF3,
|
||||
|
||||
/* Per-state constants */
|
||||
pad_SIO_SETTLE_BEFORE_TX = 1000, /* iterations after CTRL=0x0010 */
|
||||
pad_SIO_SETTLE_AFTER_TX = 2000, /* iterations after CTRL=port_select */
|
||||
pad_SIO_WAIT_BUDGET = 4096, /* max iterations per /ACK or RX wait */
|
||||
pad_SIO_CFG_MAX_ATTEMPTS = 3, /* DualShock config retries before reject */
|
||||
};
|
||||
|
||||
/* Pad status enum (per-port outcome) */
|
||||
typedef Enum_(U4, PadSioStatus) {
|
||||
PadSioStatus_Disconnected,
|
||||
PadSioStatus_Digital,
|
||||
PadSioStatus_AnalogStick,
|
||||
PadSioStatus_Analog,
|
||||
PadSioStatus_ConfigRejected,
|
||||
PadSioStatus_Invalid,
|
||||
PadSioStatus_TxTimeout,
|
||||
PadSioStatus_RxTimeout,
|
||||
PadSioStatus_AckTimeout,
|
||||
};
|
||||
|
||||
/* PadState — per-port runtime state */
|
||||
typedef Struct_(PadState) {
|
||||
PadSioStatus status;
|
||||
U4 buttons;
|
||||
U1 left_x;
|
||||
U1 left_y;
|
||||
U1 right_x;
|
||||
U1 right_y;
|
||||
U4 attempt;
|
||||
};
|
||||
|
||||
/* PadSioInit — boot-time C-side pointer table passed into the tape */
|
||||
typedef Struct_(PadSioInit) {
|
||||
U4 sio_base_addr[2];
|
||||
PadState* pad_state_ptr[2];
|
||||
};
|
||||
|
||||
/* Register aliases for the new atoms (post-2026-07-10 ABI) */
|
||||
#ifndef atom_reg
|
||||
#define atom_reg /* atom_reg: opt the preceding enum entry into the DWARF registry */
|
||||
#endif
|
||||
|
||||
enum {
|
||||
R_PadSioBase = R_T6 atom_reg, /* caller-pinned IO_BASE_ADDR */
|
||||
R_PadState = R_T7 atom_reg, /* caller-pinned PadState* */
|
||||
R_PadStatus = R_T4 atom_reg, /* scratch for status reads */
|
||||
R_PadCountdown = R_T5 atom_reg, /* scratch for countdown budget */
|
||||
#define R_PadSioBase_Code R_T6_Code
|
||||
#define R_PadState_Code R_T7_Code
|
||||
#define R_PadStatus_Code R_T4_Code
|
||||
#define R_PadCountdown_Code R_T5_Code
|
||||
};
|
||||
|
||||
/* Address of SIO0 block in KSEG1 (the PS1-side uncached mirror) */
|
||||
enum {
|
||||
pad_IO_KSEG1_BASE = 0xBF800000,
|
||||
};
|
||||
|
||||
|
||||
@@ -21,3 +21,29 @@ enum {
|
||||
};
|
||||
|
||||
#define v3s4_fp_one() v3s4(fp_one, fp_one, fp_one)
|
||||
|
||||
#ifdef INTELLISENSE_DIRECTIVES
|
||||
# include "duffle/pad.h"
|
||||
#endif
|
||||
|
||||
/* ============================================================
|
||||
* Raw SIO0 pad subsystem (raw_sio_pad_poll_20260802)
|
||||
* ============================================================ */
|
||||
|
||||
typedef Struct_(Binds_PadSioStep) {
|
||||
PadState* state0;
|
||||
PadState* state1;
|
||||
U4 sio_base_addr0;
|
||||
U4 sio_base_addr1;
|
||||
};
|
||||
|
||||
typedef Struct_(Binds_PadApplyInput) {
|
||||
PadState* state;
|
||||
V3_S2* cube_rot;
|
||||
V3_S2* floor_rot;
|
||||
};
|
||||
|
||||
/* Populates smem.pad_sio_init with the two PadState pointers and the
|
||||
* KSEG1 SIO0 base. The caller (main()) runs this once at boot before
|
||||
* the first tb_emit(pad_sio_init). */
|
||||
void pad_sio_init_setup(PadSioInit* init, PadState* s0, PadState* s1);
|
||||
|
||||
@@ -199,7 +199,7 @@ internal MipsAtom_(gp_screen_init) atom_info(atom_phase(screen_init), atom_reads
|
||||
};
|
||||
|
||||
enum {
|
||||
R_PadState = R_T4 atom_reg atom_type(U4),
|
||||
R_PadInState = R_T4 atom_reg atom_type(U4),
|
||||
R_PadSignal = R_T0 atom_reg atom_type(U4),
|
||||
R_CubeRot = R_T1 atom_reg atom_type(V3_S2*),
|
||||
R_FloorRot = R_T2 atom_reg atom_type(V3_S2*),
|
||||
@@ -210,15 +210,15 @@ typedef Struct_(Binds_PadInputDemo) {
|
||||
V3_S2* floor_rot;
|
||||
};
|
||||
internal MipsAtom_(pad_input_demo) atom_info(atom_bind(Binds_PadInputDemo)
|
||||
, atom_reads(R_PadState, R_CubeRot, R_FloorRot)
|
||||
, atom_reads(R_PadInState, R_CubeRot, R_FloorRot)
|
||||
, atom_writes(R_CubeRot, R_FloorRot)
|
||||
) {
|
||||
load_word(R_PadState, R_TapePtr, O_(Binds_PadInputDemo,pad_state)),
|
||||
load_word(R_PadInState, R_TapePtr, O_(Binds_PadInputDemo,pad_state)),
|
||||
load_word(R_CubeRot, R_TapePtr, O_(Binds_PadInputDemo,cube_rot)),
|
||||
load_word(R_FloorRot, R_TapePtr, O_(Binds_PadInputDemo,floor_rot)),
|
||||
add_ui_self( R_TapePtr, S_(Binds_PadInputDemo)),
|
||||
|
||||
and_i(R_PadSignal, R_PadState, pad0_(Pad_Left)), branch_le_zero(R_PadSignal, atom_offset(pad_left, exit_pad_left)),
|
||||
and_i(R_PadSignal, R_PadInState, pad0_(Pad_Left)), branch_le_zero(R_PadSignal, atom_offset(pad_left, exit_pad_left)),
|
||||
load_half( R_T5, R_CubeRot, O_(V3_S2,y)), // BD-Slot occupied
|
||||
load_half( R_T6, R_FloorRot, O_(V3_S2,y)),
|
||||
add_si( R_T5, R_T5, 30),
|
||||
@@ -227,7 +227,7 @@ internal MipsAtom_(pad_input_demo) atom_info(atom_bind(Binds_PadInputDemo)
|
||||
store_half(R_T6, R_FloorRot, O_(V3_S2,y)),
|
||||
atom_label(exit_pad_left)
|
||||
|
||||
and_i(R_PadSignal, R_PadState, pad0_(Pad_Right)), branch_le_zero(R_PadSignal, atom_offset(pad_right, exit_pad_right)),
|
||||
and_i(R_PadSignal, R_PadInState, pad0_(Pad_Right)), branch_le_zero(R_PadSignal, atom_offset(pad_right, exit_pad_right)),
|
||||
load_half( R_T5, R_CubeRot, O_(V3_S2,y)), // BD-Slot occupied
|
||||
load_half( R_T6, R_FloorRot, O_(V3_S2,y)),
|
||||
add_si( R_T5, R_T5, -30),
|
||||
@@ -376,4 +376,39 @@ internal MipsAtom_(sync_primitive_arena) atom_info(atom_bind(Binds_SyncPrimitive
|
||||
mac_yield()
|
||||
};
|
||||
|
||||
/* ----- pad_sio_init -----
|
||||
* Boot-time SIO0 init. Caller pins R_T6 = sio_base_addr0.
|
||||
* Issues SIO CTRL=0x0040 (reset), MODE=0x000D, BAUD=0x0088.
|
||||
* (Phase 2 fills the body.)
|
||||
*/
|
||||
internal MipsAtom_(pad_sio_init) atom_info(atom_phase(pad_init)
|
||||
, atom_reads(R_T5, R_PadSioBase)
|
||||
, atom_writes(R_T5)
|
||||
) {
|
||||
mac_yield(),
|
||||
};
|
||||
|
||||
/* ----- pad_sio_step -----
|
||||
* Per-frame bounded raw-SIO transaction. Reads PadState pointers + SIO
|
||||
* base addresses from Binds_PadSioStep; writes per-port status +
|
||||
* buttons + axes into smem.pad[0..1]. (Phase 3 fills the body.)
|
||||
*/
|
||||
internal MipsAtom_(pad_sio_step) atom_info(atom_bind(Binds_PadSioStep)
|
||||
, atom_reads(R_TapePtr, R_PadSioBase, R_PadState, R_PadStatus, R_PadCountdown)
|
||||
, atom_writes(R_PadStatus, R_PadCountdown)
|
||||
) {
|
||||
mac_yield(),
|
||||
};
|
||||
|
||||
/* ----- pad_apply_input -----
|
||||
* Reads pad[0].buttons + pad[0].left_x; applies the input-semantics
|
||||
* deltas to cube_rot.y + floor_rot.y. (Phase 4 fills the body.)
|
||||
*/
|
||||
internal MipsAtom_(pad_apply_input) atom_info(atom_bind(Binds_PadApplyInput)
|
||||
, atom_reads(R_T0, R_T1, R_T2, R_T5)
|
||||
, atom_writes(R_T1, R_T2)
|
||||
) {
|
||||
mac_yield(),
|
||||
};
|
||||
|
||||
#pragma endregion Baked Atoms
|
||||
|
||||
Reference in New Issue
Block a user