diff options
| author | John Wilbert M. Villamor <lameguy64@gmail.com> | 2019-04-06 10:11:07 +0800 |
|---|---|---|
| committer | John Wilbert M. Villamor <lameguy64@gmail.com> | 2019-04-06 10:11:07 +0800 |
| commit | f3e040230772f978540a71aea43dfde200992922 (patch) | |
| tree | bd8ca31b72dd01e24980b073854e263589530f56 /libpsn00b | |
| download | psn00bsdk-f3e040230772f978540a71aea43dfde200992922.tar.gz | |
First commit
Diffstat (limited to 'libpsn00b')
130 files changed, 8680 insertions, 0 deletions
diff --git a/libpsn00b/include/ctype.h b/libpsn00b/include/ctype.h new file mode 100644 index 0000000..b79498a --- /dev/null +++ b/libpsn00b/include/ctype.h @@ -0,0 +1,7 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +extern int tolower(int chr); +extern int toupper(int chr); + +#endif
\ No newline at end of file diff --git a/libpsn00b/include/gtereg.h b/libpsn00b/include/gtereg.h new file mode 100644 index 0000000..0d051fc --- /dev/null +++ b/libpsn00b/include/gtereg.h @@ -0,0 +1,81 @@ +# GTE register definitions for GNU assembler (as). +# +# Part of the PSn00bSDK Project by Lameguy64. +# 2019 Meido-Tek Productions + +# +# GTE data registers (use mfc2, mtc2, lwc2, swc2) +# +.set C2_VXY0, $0 +.set C2_VZ0, $1 +.set C2_VXY1, $2 +.set C2_VZ1, $3 +.set C2_VXY2, $4 +.set C2_VZ2, $5 +.set C2_RGB, $6 +.set C2_OTZ, $7 + +.set C2_IR0, $8 +.set C2_IR1, $9 +.set C2_IR2, $10 +.set C2_IR3, $11 +.set C2_SXY0, $12 +.set C2_SXY1, $13 +.set C2_SXY2, $14 +.set C2_SXYP, $15 + +.set C2_SZ0, $16 +.set C2_SZ1, $17 +.set C2_SZ2, $18 +.set C2_SZ3, $19 +.set C2_RGB0, $20 +.set C2_RGB1, $21 +.set C2_RGB2, $22 + +.set C2_MAC0, $24 +.set C2_MAC1, $25 +.set C2_MAC2, $26 +.set C2_MAC3, $27 +.set C2_IRGB, $28 +.set C2_ORGB, $29 +.set C2_LZCS, $30 +.set C2_LZCR, $31 + +# +# GTE control registers (use cfc2/ctc2) +# +.set C2_R11R12, $0 +.set C2_R13R21, $1 +.set C2_R22R23, $2 +.set C2_R31R32, $3 +.set C2_R33, $4 +.set C2_TRX, $5 +.set C2_TRY, $6 +.set C2_TRZ, $7 + +.set C2_L11L12, $8 +.set C2_L13L21, $9 +.set C2_L22L23, $10 +.set C2_L31L32, $11 +.set C2_L33, $12 +.set C2_RBK, $13 +.set C2_GBK, $14 +.set C2_BBK, $15 + +.set C2_LR1LR2, $16 +.set C2_LR3LG1, $17 +.set C2_LG2LG3, $18 +.set C2_LB1LB2, $19 +.set C2_LB3, $20 +.set C2_RFC, $21 +.set C2_GFC, $22 +.set C2_BFC, $23 + +.set C2_OFX, $24 +.set C2_OFY, $25 +.set C2_H, $26 +.set C2_DQA, $27 +.set C2_DQB, $28 +.set C2_ZSF3, $29 +.set C2_ZSF4, $30 +.set C2_FLAG, $31 diff --git a/libpsn00b/include/hwregs_a.h b/libpsn00b/include/hwregs_a.h new file mode 100644 index 0000000..a71a657 --- /dev/null +++ b/libpsn00b/include/hwregs_a.h @@ -0,0 +1,97 @@ +# Hardware register definitions for GNU assembler (as) +# +# Part of the PSn00bSDK Project by Lameguy64 +# 2019 Meido-Tek Productions + + +.set IOBASE, 0x1f80 # IO segment base + +# GPU +.set GP0, 0x1810 # Also GPUREAD +.set GP1, 0x1814 # Also GPUSTAT + +# CD +.set CD_STAT, 0x1800 +.set CD_CMD, 0x1801 # Also response FIFO +.set CD_DATA, 0x1802 # Also parameters +.set CD_IRQ, 0x1803 + +.set CD_REG0, 0x1800 +.set CD_REG1, 0x1801 +.set CD_REG2, 0x1802 +.set CD_REG3, 0x1803 + +.set COM_DELAY, 0x1020 + +# SPU (must be used with 16-bit load/store instructions) +.set SPU_VOICE_BASE, 0x1c00 + +.set SPU_MASTER_VOL, 0x1d80 +.set SPU_REVERB_VOL, 0x1d84 +.set SPU_KEY_ON, 0x1d88 +.set SPU_KEY_OFF, 0x1d8c +.set SPU_FM_MODE, 0x1d90 +.set SPU_NOISE_MODE, 0x1d94 +.set SPU_REVERB_ON, 0x1d98 +.set SPU_CHAN_STATUS, 0x1d9c + +.set SPU_REVERB_ADDR, 0x1da2 +.set SPU_IRQ_ADDR, 0x1da4 +.set SPU_ADDR, 0x1da6 +.set SPU_DATA, 0x1da8 + +.set SPUCNT, 0x1daa +.set SPUDTCNT, 0x1dac +.set SPUSTAT, 0x1dae + +.set SPU_CD_VOL, 0x1db0 +.set SPU_EXT_VOL, 0x1db4 +.set SPU_CURRENT_VOL, 0x1db8 + +.set SPU_VOICE_VOL_L, 0x00 +.set SPU_VOICE_VOL_R, 0x02 +.set SPU_VOICE_FREQ, 0x04 +.set SPU_VOICE_ADDR, 0x06 +.set SPU_VOICE_ADSR_L, 0x08 +.set SPU_VOICE_ADSR_H, 0x0a +.set SPU_VOICE_LOOP, 0x0e + +# Pads +.set JOY_TXRX, 0x1040 +.set JOY_STAT, 0x1044 +.set JOY_MODE, 0x1048 +.set JOY_CTRL, 0x104A +.set JOY_BAUD, 0x104E + +# IRQ +.set ISTAT, 0x1070 +.set IMASK, 0x1074 + +# DMA +.set DPCR, 0x10f0 +.set DICR, 0x10f4 + +.set D2_MADR, 0x10a0 +.set D2_BCR, 0x10a4 +.set D2_CHCR, 0x10a8 + +.set D4_MADR, 0x10c0 +.set D4_BCR, 0x10c4 +.set D4_CHCR, 0x10c8 + +.set D6_MADR, 0x10e0 +.set D6_BCR, 0x10e4 +.set D6_CHCR, 0x10e8 + +# Timers +.set T0_CNT, 0x1100 +.set T0_MODE, 0x1104 +.set T0_TGT, 0x1108 + +.set T1_CNT, 0x1110 +.set T1_MODE, 0x1114 +.set T1_TGT, 0x1118 + +.set T2_CNT, 0x1120 +.set T2_MODE, 0x1124 +.set T2_TGT, 0x1128 diff --git a/libpsn00b/include/inline_c.h b/libpsn00b/include/inline_c.h new file mode 100644 index 0000000..4341624 --- /dev/null +++ b/libpsn00b/include/inline_c.h @@ -0,0 +1,433 @@ +/* Inline GTE macros for the GNU C compiler. + * + * Part of the PSn00bSDK Project by Lameguy64. + * 2019 Meido-Tek Production + * + * All GTE commands can be used without having to pass your object file + * through some stupid tool such as DMPSX. Perhaps it was Sony's attempt + * to prevent people from quickly discovering the GTE commands from the + * official SDK easily? Though people could just extract the cop2 opcodes + * of an object file after it has been passed through DMPSX. + * + * Todo: A couple of GTE operation macros are still missing such as + * gte_rtv*() though they appear to be just variants of gte_mvmva more or + * less (gte_rtv0() is actually gte_mvmva(1, 0, 0, 3, 0) for example). + * + */ + +#ifndef _INLINE_C_H +#define _INLINE_C_H + +/* + * GTE load macros + */ + +/* Load a SVECTOR (passed as a pointer) to GTE V0 + */ +#define gte_ldv0( r0 ) __asm__ volatile ( \ + "lwc2 $0 , 0( %0 );" \ + "lwc2 $1 , 4( %0 );" \ + : \ + : "r"( r0 ) \ + : "$t0" ) + +/* Load a SVECTOR (passed as a pointer) to GTE V1 + */ +#define gte_ldv1( r0 ) __asm__ volatile ( \ + "lwc2 $2 , 0( %0 );" \ + "lwc2 $3 , 4( %0 );" \ + : \ + : "r"( r0 ) \ + : "$t0" ) + +/* Load a SVECTOR (passed as a pointer) to GTE V2 + */ +#define gte_ldv2( r0 ) __asm__ volatile ( \ + "lwc2 $4 , 0( %0 );" \ + "lwc2 $5 , 4( %0 );" \ + : \ + : "r"( r0 ) \ + : "$t0" ) + +/* Load three SVECTORs (passed as a pointer) to the GTE at once + */ +#define gte_ldv3( r0, r1, r2 ) __asm__ volatile ( \ + "lwc2 $0 , 0( %0 );" \ + "lwc2 $1 , 4( %0 );" \ + "lwc2 $2 , 0( %1 );" \ + "lwc2 $3 , 4( %1 );" \ + "lwc2 $4 , 0( %2 );" \ + "lwc2 $5 , 4( %2 );" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) ) + +#define gte_ldrgb( r0 ) __asm__ volatile ( \ + "lwc2 $6 , 0( %0 );" \ + : \ + : "r"( r0 ) ) + +#define gte_ldopv2( r0 ) __asm__ volatile ( \ + "lwc2 $11, 8( %0 );" \ + "lwc2 $9 , 0( %0 );" \ + "lwc2 $10, 4( %0 );" \ + : \ + : "r"( r0 ) ) + +/* Sets the GTE offset + */ +#define gte_SetGeomOffset( r0, r1 ) __asm__ volatile ( \ + "sll $t0, %0, 16;" \ + "sll $t1, %1, 16;" \ + "ctc2 $t0, $24;" \ + "ctc2 $t1, $25;" \ + : \ + : "r"( r0 ), "r"( r1 ) \ + : "$t0", "$t1" ) + +#define gte_SetGeomScreen( r0 ) __asm__ volatile ( \ + "ctc2 %0, $26;" \ + : \ + : "r"( r0 ) ) + +#define gte_SetTransMatrix( r0 ) __asm__ volatile ( \ + "lw $t0, 20( %0 );" \ + "lw $t1, 24( %0 );" \ + "ctc2 $t0, $5;" \ + "lw $t2, 28( %0 );" \ + "ctc2 $t1, $6;" \ + "ctc2 $t2, $7;" \ + : \ + : "r"( r0 ) \ + : "$t2" ) + +#define gte_SetRotMatrix( r0 ) __asm__ volatile ( \ + "lw $t0, 0( %0 );" \ + "lw $t1, 4( %0 );" \ + "ctc2 $t0, $0;" \ + "ctc2 $t1, $1;" \ + "lw $t0, 8( %0 );" \ + "lw $t1, 12( %0 );" \ + "lhu $t2, 16( %0 );" \ + "ctc2 $t0, $2;" \ + "ctc2 $t1, $3;" \ + "ctc2 $t2, $4;" \ + : \ + : "r"( r0 ) \ + : "$t2" ) + +#define gte_SetLightMatrix( r0 ) __asm__ volatile ( \ + "lw $t0, 0( %0 );" \ + "lw $t1, 4( %0 );" \ + "ctc2 $t0, $8;" \ + "ctc2 $t1, $9;" \ + "lw $t0, 8( %0 );" \ + "lw $t1, 12( %0 );" \ + "lhu $t2, 16( %0 );" \ + "ctc2 $t0, $10;" \ + "ctc2 $t1, $11;" \ + "ctc2 $t2, $12;" \ + : \ + : "r"( r0 ) \ + : "$t2" ) + +#define gte_SetColorMatrix( r0 ) __asm__ volatile ( \ + "lw $t0, 0( %0 );" \ + "lw $t1, 4( %0 );" \ + "ctc2 $t0, $16;" \ + "ctc2 $t1, $17;" \ + "lw $t0, 8( %0 );" \ + "lw $t1, 12( %0 );" \ + "lhu $t2, 16( %0 );" \ + "ctc2 $t0, $18;" \ + "ctc2 $t1, $19;" \ + "ctc2 $t2, $20;" \ + : \ + : "r"( r0 ) \ + : "$t2" ) + +#define gte_SetBackColor( r0, r1, r2 ) __asm__ volatile ( \ + "sll $t0, %0, 4;" \ + "sll $t1, %1, 4;" \ + "sll $t2, %2, 4;" \ + "ctc2 $t0, $13;" \ + "ctc2 $t1, $14;" \ + "ctc2 $t2, $15;" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) \ + : "$t0", "$t1", "$t2" ) + +/* + * GTE store macros + */ + +#define gte_otz( r0 ) __asm__ volatile ( \ + "swc2 $7, 0( %0 );" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_stflg( r0 ) __asm__ volatile ( \ + "cfc2 $t0, $31;" \ + "nop;" \ + "sw $t0, 0( %0 );" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_stsxy( r0 ) __asm__ volatile ( \ + "swc2 $14, 0( %0 );" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_stsxy0( r0 ) __asm__ volatile ( \ + "swc2 $12, 0( %0 );" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_stsxy1( r0 ) __asm__ volatile ( \ + "swc2 $13, 0( %0 );" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_stsxy2( r0 ) __asm__ volatile ( \ + "swc2 $14, 0( %0 );" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_stsxy3( r0, r1, r2 ) __asm__ volatile ( \ + "swc2 $12, 0( %0 );" \ + "swc2 $13, 0( %1 );" \ + "swc2 $14, 0( %2 );" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) \ + : "memory" ) + +#define gte_stotz( r0 ) __asm__ volatile ( \ + "swc2 $7, 0( %0 );" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_stopz( r0 ) __asm__ volatile ( \ + "swc2 $24, 0( %0 );" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_strgb( r0 ) __asm__ volatile ( \ + "swc2 $22, 0( %0 );" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_strgb3( r0, r1, r2 ) __asm__ volatile ( \ + "swc2 $20, 0( %0 );" \ + "swc2 $21, 0( %1 );" \ + "swc2 $22, 0( %2 );" \ + : \ + : "r"( r0 ), "r"( r1 ), "r" ( r2 ) \ + : "memory" ) + +#define gte_stsv( r0 ) __asm__ volatile ( \ + "mfc2 $t0, $9;" \ + "mfc2 $t1, $10;" \ + "mfc2 $t2, $11;" \ + "sh $t0, 0( %0 );" \ + "sh $t1, 2( %0 );" \ + "sh $t2, 4( %0 );" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_stlvnl( r0 ) __asm__ volatile ( \ + "swc2 $25, 0( %0 );" \ + "swc2 $26, 4( %0 );" \ + "swc2 $27, 8( %0 );" \ + : \ + : "r"( r0 ) \ + : "memory" ) + + +/* + * GTE operation macros (does not need a stupid tool such as dmpsx!) + */ + +#define gte_rtps() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0180001;" ) + +#define gte_rtpt() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0280030;" ) + +#define gte_nclip() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x1400006;" ) + +#define gte_avsz3() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x158002D;" ) + +#define gte_avsz4() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x168002E;" ) + +#define gte_sqr0() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0A00428;" ) + +#define gte_sqr12() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0A80428;" ) + +#define gte_op0() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x170000C;" ) + +#define gte_op12() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x178000C;" ) + +#define gte_ncs() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0C8041E;" ) + +#define gte_nct() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0D80420;" ) + +#define gte_nccs() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x108041B;" ) \ + +#define gte_ncct() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x118043F;" ) + +#define gte_ncds() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0E80413;" ) + +#define gte_ncdt() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0F80416;" ) + +#define gte_cc() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x138041C;" ) + +#define gte_cdp() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x1280414;" ) + +#define gte_dcpl() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0680029;" ) + +#define gte_dpcs() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0780010;" ) + +#define gte_dpct() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0180001;" ) + +#define gte_intpl() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x0980011;" ) + +#define gte_gpf0() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x190003D;" ) + +#define gte_gpf12() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x198003D;" ) + +#define gte_gpl0() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x1A0003E;" ) + +#define gte_gpl12() __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 0x1A8003E;" ) + +#define gte_mvmva_core( r0 ) __asm__ volatile ( \ + "nop;" \ + "nop;" \ + "cop2 %0" \ + : \ + : "g"( r0 ) ) + +#define gte_mvmva(sf, mx, v, cv, lm) gte_mvmva_core( 0x0400012 | \ + ((sf)<<19) | ((mx)<<17) | ((v)<<15) | ((cv)<<13) | ((lm)<<10) ) + + +/* + * GTE operation macros without leading nops + * + * Checking assembler output when using these is advised. + */ + +#define gte_rtps_b() __asm__ volatile ( "cop2 0x0180001;" ) +#define gte_rtpt_b() __asm__ volatile ( "cop2 0x0280030;" ) +#define gte_nclip_b() __asm__ volatile ( "cop2 0x1400006;" ) +#define gte_avsz3_b() __asm__ volatile ( "cop2 0x158002D;" ) +#define gte_avsz4_b() __asm__ volatile ( "cop2 0x168002E;" ) +#define gte_sqr0_b() __asm__ volatile ( "cop2 0x0A00428;" ) +#define gte_sqr12_b() __asm__ volatile ( "cop2 0x0A80428;" ) +#define gte_op0_b() __asm__ volatile ( "cop2 0x170000C;" ) +#define gte_op12_b() __asm__ volatile ( "cop2 0x178000C;" ) +#define gte_ncs_b() __asm__ volatile ( "cop2 0x0C8041E;" ) +#define gte_nct_b() __asm__ volatile ( "cop2 0x0D80420;" ) +#define gte_nccs_b() __asm__ volatile ( "cop2 0x108041B;" ) +#define gte_ncct_b() __asm__ volatile ( "cop2 0x118043F;" ) +#define gte_ncds_b() __asm__ volatile ( "cop2 0x0E80413;" ) +#define gte_ncdt_b() __asm__ volatile ( "cop2 0x0F80416;" ) +#define gte_cc_b() __asm__ volatile ( "cop2 0x138041C;" ) +#define gte_cdp_b() __asm__ volatile ( "cop2 0x1280414;" ) +#define gte_dcpl_b() __asm__ volatile ( "cop2 0x0680029;" ) +#define gte_dpcs_b() __asm__ volatile ( "cop2 0x0780010;" ) +#define gte_dpct_b() __asm__ volatile ( "cop2 0x0180001;" ) +#define gte_intpl_b() __asm__ volatile ( "cop2 0x0980011;" ) +#define gte_gpf0_b() __asm__ volatile ( "cop2 0x190003D;" ) +#define gte_gpf12_b() __asm__ volatile ( "cop2 0x198003D;" ) +#define gte_gpl0_b() __asm__ volatile ( "cop2 0x1A0003E;" ) +#define gte_gpl12_b() __asm__ volatile ( "cop2 0x1A8003E;" ) +#define gte_mvmva_core_b( r0 ) __asm__ volatile ( \ + "cop2 %0" \ + : \ + : "g"( r0 ) ) +#define gte_mvmva_b(sf, mx, v, cv, lm) gte_mvmva_core_b( 0x0400012 | \ + ((sf)<<19) | ((mx)<<17) | ((v)<<15) | ((cv)<<13) | ((lm)<<10) ) + +#endif // _INLINE_C_H
\ No newline at end of file diff --git a/libpsn00b/include/inline_s.h b/libpsn00b/include/inline_s.h new file mode 100644 index 0000000..68e0d07 --- /dev/null +++ b/libpsn00b/include/inline_s.h @@ -0,0 +1,230 @@ +# Inline GTE macros for GNU assembler (as). +# +# Part of the PSn00bSDK Project by Lameguy64. +# 2019 Meido-Tek Productions +# +# Similar to inline_c.h, it does not require running your object file +# through some silly tool. + +.macro nRTPS + nop + nop + cop2 0x0180001 +.endm + +.macro nRTPT + nop + nop + cop2 0x0280030 +.endm + +.macro nNCLIP + nop + nop + cop2 0x1400006 +.endm + +.macro nAVSZ3 + nop + nop + cop2 0x158002D +.endm + +.macro nAVSZ4 + nop + nop + cop2 0x168002E +.endm + +.macro nMVMVA sf mx v cv lm + nop + nop + cop2 0x0400012|(\sf<<19)|(\mx<<17)|(\v<<15)|(\cv<<13)|(\lm<<10) +.endm + +.macro nSQR sf + nop + nop + cop2 0x0A00428|(\sf<<19) +.endm + +.macro nnOP sf lm # extra n to prevent conflict with the nop opcode + nop + nop + cop2 0x170000C|(\sf<<19)|(\lm<<10) +.endm + +.macro nNCS + nop + nop + cop2 0x0C8041E +.endm + +.macro nNCT + nop + nop + cop2 0x0D80420 +.endm + +.macro nNCCS + nop + nop + cop2 0x108041B +.endm + +.macro nNCCT + nop + nop + cop2 0x118043F +.endm + +.macro nNCDS + nop + nop + cop2 0x0E80413 +.endm + +.macro nNCDT + nop + nop + cop2 0x0F80416 +.endm + +.macro nCC + nop + nop + cop2 0x138041C +.endm + +.macro nCDP + nop + nop + cop2 0x1280414 +.endm + +.macro nDCPL + nop + nop + cop2 0x0680029 +.endm + +.macro nDPCS + nop + nop + cop2 0x0780010 +.endm + +.macro nDPCT + nop + nop + cop2 0x0180001 +.endm + +.macro nINTPL + nop + nop + cop2 0x0980011 +.endm + +.macro nGPF sf + nop + nop + cop2 0x190003D|(\sf<<19) +.endm + +.macro nGPL sf + nop + nop + cop2 0x1A0003E|(\sf<<19) +.endm + +# +# Macros without leading nops (for optimized usage) +# +.macro RTPS + cop2 0x0180001 +.endm + +.macro RTPT + cop2 0x0280030 +.endm + +.macro NCLIP + cop2 0x1400006 +.endm + +.macro AVSZ3 + cop2 0x158002D +.endm + +.macro AVSZ4 + cop2 0x168002E +.endm + +.macro MVMVA sf mx v cv lm + cop2 0x0400012|(\sf<<19)|(\mx<<17)|(\v<<15)|(\cv<<13)|(\lm<<10) +.endm + +.macro SQR sf + cop2 0x0A00428|(\sf<<19) +.endm + +.macro OP sf lm + cop2 0x170000C|(\sf<<19)|(\lm<<10) +.endm + +.macro NCS + cop2 0x0C8041E +.endm + +.macro NCT + cop2 0x0D80420 +.endm + +.macro NCCS + cop2 0x108041B +.endm + +.macro NCCT + cop2 0x118043F +.endm + +.macro NCDS + cop2 0x0E80413 +.endm + +.macro NCDT + cop2 0x0F80416 +.endm + +.macro CC + cop2 0x138041C +.endm + +.macro CDP + cop2 0x1280414 +.endm + +.macro DCPL + cop2 0x0680029 +.endm + +.macro DPCS + cop2 0x0780010 +.endm + +.macro DPCT + cop2 0x0180001 +.endm + +.macro INTPL + cop2 0x0980011 +.endm + +.macro GPF sf + cop2 0x190003D|(\sf<<19) +.endm + +.macro GPL sf + cop2 0x1A0003E|(\sf<<19) +.endm diff --git a/libpsn00b/include/lzconfig.h b/libpsn00b/include/lzconfig.h new file mode 100644 index 0000000..cb8a830 --- /dev/null +++ b/libpsn00b/include/lzconfig.h @@ -0,0 +1,68 @@ +/*! \file lzconfig.h + * \brief Library configuration header + * \details Define settings will only take effect when you recompile the library. + */ + +#ifndef _LZP_CONFIG_H +#define _LZP_CONFIG_H + + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + + +/* Set to TRUE to compile without data compression routines useful if you + * plan to use this library on a program that does not require said routines + * especially on a platform with limited memory (such as the PlayStation). + * + * This define will rule out lzCompress(), lzSetHashSizes() and + * lzResetHashSizes() functions and their associated functions. + */ +#define LZP_NO_COMPRESS TRUE + + +/* Set to TRUE to make default compression table sizes to maximum and works best + * when compressing large amounts of data. LZP_USE_MALLOC must be set to TRUE to + * prevent stack overflow errors. + * + * Do not enable this if you plan to compile for a platform with limited memory + * otherwise, the library will consume all memory and crash the system. + * + * This define only affects lzCompress(). + */ +#define LZP_MAX_COMPRESS FALSE + + +/* Uncomment to make the library use malloc() instead of array initializers to + * allocate hash tables. Enabling this is a must if you plan to use large hash + * and window table sizes. + */ +#define LZP_USE_MALLOC FALSE + + +/* Hash table sizes (in power-of-two multiple units) + * + * These define only affect lzCompress(). + */ +#if LZP_MAX_COMPRESS == TRUE + +// Minimal defaults +#define LZP_WINDOW_SIZE 17 +#define LZP_HASH1_SIZE 8 +#define LZP_HASH2_SIZE 10 + +#else + +// Maximum defaults +#define LZP_WINDOW_SIZE 17 +#define LZP_HASH1_SIZE 22 +#define LZP_HASH2_SIZE 24 + +#endif + + +#endif // _LZP_CONFIG_H diff --git a/libpsn00b/include/malloc.h b/libpsn00b/include/malloc.h new file mode 100644 index 0000000..e6cd126 --- /dev/null +++ b/libpsn00b/include/malloc.h @@ -0,0 +1,17 @@ +#ifndef _MALLOC_H +#define _MALLOC_H + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned int *GetBSSend(); +void InitHeap(unsigned int *addr, int size); +void *malloc(int size); +void free(void *ptr); + +#ifdef __cplusplus +} +#endif + +#endif // _MALLOC_H
\ No newline at end of file diff --git a/libpsn00b/include/psxapi.h b/libpsn00b/include/psxapi.h new file mode 100644 index 0000000..54b87ee --- /dev/null +++ b/libpsn00b/include/psxapi.h @@ -0,0 +1,97 @@ +#ifndef __PSXAPI__ +#define __PSXAPI__ + +typedef struct { // Device control block + char *name; + int flags; + int ssize; + char *desc; + void *f_init; + void *f_open; + void *f_inout; + void *f_close; + void *f_ioctl; + void *f_read; + void *f_write; + void *f_erase; + void *f_undelete; + void *f_firstfile; + void *f_nextfile; + void *f_format; + void *f_chdir; + void *f_rename; + void *f_remove; + void *f_testdevice; +} DCB; + +typedef struct { // File control block + int status; + unsigned int diskid; + void *trns_addr; + unsigned int trns_len; + unsigned int filepos; + unsigned int flags; + unsigned int lasterr; + DCB *dcb; + unsigned int filesize; + unsigned int lba; + unsigned int fcbnum; +} FCB; + +struct DIRENTRY { // Directory entry + char name[20]; + int attr; + int size; + struct DIRENTRY *next; + int head; + char system[4]; +}; + +// Not recommended to use these functions to install IRQ handlers + +typedef struct { + unsigned int* next; + unsigned int* func2; + unsigned int* func1; + unsigned int pad; +} INT_RP; + +extern void SysEnqIntRP(int pri, INT_RP *rp); +extern void SysDeqIntRP(int pri, INT_RP *rp); + +// Use event handlers instead + +extern int OpenEvent(unsigned int class, int spec, int mode, void (*func)()); +extern int CloseEvent(int ev_desc); +extern int EnableEvent(int ev_desc); +extern int DisableEvent(int ev_desc); + +// BIOS file functions + +extern int open(const char *name, int mode); +extern int close(int fd); +extern int seek(int fd, unsigned int offset, int mode); +extern int read(int fd, char *buff, unsigned int len); +extern int write(int fd, const char *buff, unsigned int len); +extern int ioctl(int fd, int cmd, int arg); +extern struct DIRENTRY *firstfile(const char *wildcard, struct DIRENTRY *entry); +extern struct DIRENTRY *nextfile(struct DIRENTRY *entry); +extern int erase(const char *name); +extern int chdir(const char *path); + +#define delete( p ) erase( p ) +#define cd( p ) chdir( p ) // For compatibility + +int AddDev(DCB *dcb); +int DelDev(const char *name); +extern void ListDev(); + +extern void EnterCriticalSection(); +extern void ExitCriticalSection(); + +extern void _96_init(); +extern void _96_remove(); + +extern void ChangeClearPAD(int mode); + +#endif diff --git a/libpsn00b/include/psxetc.h b/libpsn00b/include/psxetc.h new file mode 100644 index 0000000..67df29f --- /dev/null +++ b/libpsn00b/include/psxetc.h @@ -0,0 +1,15 @@ +#ifndef _PSXETC_H +#define _PSXETC_H + +#ifdef __cplusplus +extern "C" { +#endif + +void FntLoad(int x, int y); +char *FntSort(unsigned int *ot, char *pri, int x, int y, const char *text); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h new file mode 100644 index 0000000..24d023a --- /dev/null +++ b/libpsn00b/include/psxgpu.h @@ -0,0 +1,556 @@ +#ifndef __PSXGPU_H +#define __PSXGPU_H + +// Low-level display parameters for DISPENV_RAW. A leftover from prototyping +#define DISP_WIDTH_256 0 +#define DISP_WIDTH_320 1 +#define DISP_WIDTH_384 64 +#define DISP_WIDTH_512 2 +#define DISP_WIDTH_640 3 + +#define DISP_HEIGHT_LOW 0 // Could be 240 for NTSC, 256 for PAL +#define DISP_HEIGHT_HIGH 4 // Could be 480 for NTSC, 512 for PAL +#define DISP_INTERLACE 32 +#define DISP_24BIT_COLOR 16 +#define DISP_MODE_NTSC 0 +#define DISP_MODE_PAL 8 + + +#define MODE_NTSC 0 +#define MODE_PAL 1 + + +// Vector macros + +#define setVector( v, _x, _y, _z ) \ + (v)->vx = _x, (v)->vy = _y, (v)->vz = _z + +#define setRECT( r, _x, _y, _w, _h ) \ + (v)->x = _x, (v)->y = _y, (v)->w = _w, (v)->h = _h + + + + + +// Primitive macros + + +#define setDrawTPage( p, tp, abr, x, y ) \ + ( (p)->code[0] = getTPage( tp, abr, x, y ), \ + setlen( p, 1 ), setcode( p, 0xe1 ) ) + +/** ORIGINAL FUNCTION **/ +#define setDrawTPageVal( p, tp ) \ + ( (p)->code[0] = tp, \ + setlen( p, 1 ), setcode( p, 0xe1 ) ) + +/*#define setVram2Vram( p ) ( setlen( p, 8 ), setcode( p, 0x80 ), \ + (p)->nop[0] = 0, (p)->nop[1] = 0, (p)->nop[2] = 0, (p)->nop[3] = 0 )*/ + +/* + +#define setTPagePri2( p, dth, tp, abr, x, y ) \ + ( (p)->code[0] = getTPage( tp, abr, x, y )|(dth<<9), \ + setlen( p, 1 ), setcode( p, 0xe1 ) )*/ + +/* + * Set primitive attributes + */ +#define setTPage( p, tp, abr, x, y ) \ + ( (p)->tpage = getTPage( tp, abr, x, y ) ) + +#define setClut( p, x, y ) \ + ( (p)->clut = getClut(x, y) ) + + +/* + * Set primitive colors + */ +#define setRGB0( p, r, g, b ) ( (p)->r0 = r, (p)->g0 = g, (p)->b0 = b ) +#define setRGB1( p, r, g, b ) ( (p)->r1 = r, (p)->g1 = g, (p)->b1 = b ) +#define setRGB2( p, r, g, b ) ( (p)->r2 = r, (p)->g2 = g, (p)->b2 = b ) +#define setRGB3( p, r, g, b ) ( (p)->r3 = r, (p)->g3 = g, (p)->b3 = b ) + + +/* + * Set primitive screen coordinates + */ +#define setXY0( p, _x0, _y0 ) \ + (p)->x0 = _x0, (p)->y0 = _y0 + +#define setXY2( p, _x0, _y0, _x1, _y1 ) \ + (p)->x0 = _x0, (p)->y0 = _y0, \ + (p)->x1 = _x1, (p)->y1 = _y1 + +#define setXY3( p, _x0, _y0, _x1, _y1, _x2, _y2 ) \ + (p)->x0 = _x0, (p)->y0 = _y0, \ + (p)->x1 = _x1, (p)->y1 = _y1, \ + (p)->x2 = _x2, (p)->y2 = _y2 + +#define setXY4( p, _x0, _y0, _x1, _y1, _x2, _y2, _x3, _y3 ) \ + (p)->x0 = _x0, (p)->y0 = _y0, \ + (p)->x1 = _x1, (p)->y1 = _y1, \ + (p)->x2 = _x2, (p)->y2 = _y2, \ + (p)->x3 = _x3, (p)->y3 = _y3 + +#define setWH( p, _w, _h ) \ + (p)->w = _w, (p)->h = _h + + +/* + * Set texture coordinates + */ +#define setUV0( p, _u0, _v0 ) \ + (p)->u0 = _u0, (p)->v0 = _v0 + +#define setUV3( p, _u0, _v0, _u1, _v1, _u2, _v2 ) \ + (p)->u0 = _u0, (p)->v0 = _v0, \ + (p)->u1 = _u1, (p)->v1 = _v1, \ + (p)->u2 = _u2, (p)->v2 = _v2 + +#define setUV4( p, _u0, _v0, _u1, _v1, _u2, _v2, _u3, _v3 ) \ + (p)->u0 = _u0, (p)->v0 = _v0, \ + (p)->u1 = _u1, (p)->v1 = _v1, \ + (p)->u2 = _u2, (p)->v2 = _v2, \ + (p)->u3 = _u3, (p)->v3 = _v3 + +#define setUVWH( p, _u0, _v0, _w, _h ) \ + (p)->u0 = _u0, (p)->v0 = _v0, \ + (p)->u1 = _u1+(_w), (p)->v1 = _v1, \ + (p)->u2 = _u2, (p)->v2 = _v2+(_h), \ + (p)->u2 = _u3+(_h), (p)->v2 = _v3+(_h) + + +/* + * Primitive handling macros + */ +#define setlen( p, _len ) ( ((P_TAG*)(p))->len = (unsigned char)_len ) +#define setaddr( p, _addr ) ( ((P_TAG*)(p))->addr = (unsigned int)_addr ) +#define setcode( p, _code ) ( ((P_TAG*)(p))->code = (unsigned char)_code ) + +#define getlen( p ) ( ((P_TAG*)(p))->len ) +#define getaddr( p ) ( ((P_TAG*)(p))->addr ) +#define getcode( p ) ( ((P_TAG*)(p))->code ) + +#define nextPrim( p ) (void*)((((P_TAG*)(p))->addr)|0x80000000) +#define isendprim( p ) ((((P_TAG*)(p))->addr)==0xffffff) + +#define addPrim( ot, p ) setaddr( p, getaddr( ot ) ), setaddr( ot, p ) +#define addPrims(ot, p0, p1) setaddr( p1, getaddr( ot ) ), setaddr( ot, p0 ) + +#define catPrim( p0, p1 ) setaddr( p0, p1 ) +#define termPrim( p ) setaddr( p, 0xffffffff ) + +#define setSemiTrans( p, abe ) \ + ( (abe)?setcode( p, getcode( p )|0x2 ):setcode( p, getcode( p )&~0x2 ) ) + +#define setShadeTex( p, tge ) \ + ( (tge)?setcode( p, getcode( p )|0x1 ):setcode( p, getcode( p )&~0x1 ) ) + + +/* ORIGINAl CODE */ +#define setDrawMask( p, sb, mt ) \ + setlen( p, 1 ), p->code[0] = sb|(mt<<1), \ + setcode( p, 0xe6 ) + + +#define getTPage( tp, abr, x, y ) \ + ( (((x)&0x3ff)>>6) | (((y)>>8)<<4) | (((abr)&0x3)<<5) | (((tp)&0x3)<<7) ) + +#define getClut( x, y ) \ + ( ((y)<<6)|(((x)>>4)&0x3f) ) + + +/* + * Primitive initializers + */ +#define setPolyF3( p ) setlen( p, 4 ), setcode( p, 0x20 ) +#define setPolyFT3( p ) setlen( p, 7 ), setcode( p, 0x24 ) +#define setPolyG3( p ) setlen( p, 6 ), setcode( p, 0x30 ) +#define setPolyGT3( p ) setlen( p, 9 ), setcode( p, 0x34 ) + +#define setPolyF4( p ) setlen( p, 5 ), setcode( p, 0x28 ) +#define setPolyFT4( p ) setlen( p, 9 ), setcode( p, 0x2c ) +#define setPolyG4( p ) setlen( p, 8 ), setcode( p, 0x38 ) +#define setPolyGT4( p ) setlen( p, 12 ), setcode( p, 0x3c ) + +#define setSprt8( p ) setlen( p, 3 ), setcode( p, 0x74 ) +#define setSprt16( p ) setlen( p, 3 ), setcode( p, 0x7c ) +#define setSprt( p ) setlen( p, 4 ), setcode( p, 0x64 ) + +#define setTile1( p ) setlen( p, 2 ), setcode( p, 0x68 ) +#define setTile8( p ) setlen( p, 2 ), setcode( p, 0x70 ) +#define setTile16( p ) setlen( p, 2 ), setcode( p, 0x78 ) +#define setTile( p ) setlen( p, 3 ), setcode( p, 0x60 ) + +#define setLineG2( p ) setlen( p, 4 ), setcode( p, 0x50 ) + +#define setLineF4( p ) setlen( p, 6 ), setcode( p, 0x4c ), (p)->pad = 0x55555555 +#define setLineG4( p ) setlen( p, 9 ), setcode( p, 0x5c ), (p)->pad = 0x55555555, \ + (p)->p2 = 0, (p)->p3 = 0 + +#define setFill( p ) setlen( p, 3 ), setcode( p, 0x02 ) + + +/* + * Primitive definitions + */ +typedef struct { + unsigned int addr:24; + unsigned int len:8; + unsigned char r,g,b; + unsigned char code; +} P_TAG; + +/* + * Polygon primitive definitions + */ +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + short x1,y1; + short x2,y2; +} POLY_F3; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char u0,v0; + unsigned short clut; + short x1,y1; + unsigned char u1,v1; + unsigned short tpage; + short x2,y2; + unsigned char u2,v2; + unsigned short pad; +} POLY_FT3; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char r1,g1,b1,pad0; + short x1,y1; + unsigned char r2,g2,b2,pad1; + short x2,y2; +} POLY_G3; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char u0,v0; + unsigned short clut; + unsigned char r1,g1,b1,pad0; + short x1,y1; + unsigned char u1,v1; + unsigned short tpage; + unsigned char r2,g2,b2,pad1; + short x2,y2; + unsigned char u2,v2; + unsigned short pad2; +} POLY_GT3; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + short x1,y1; + short x2,y2; + short x3,y3; +} POLY_F4; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char u0,v0; + unsigned short clut; + short x1,y1; + unsigned char u1,v1; + unsigned short tpage; + short x2,y2; + unsigned char u2,v2; + unsigned short pad0; + short x3,y3; + unsigned char u3,v3; + unsigned short pad1; +} POLY_FT4; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char r1,g1,b1,pad0; + short x1,y1; + unsigned char r2,g2,b2,pad1; + short x2,y2; + unsigned char r3,g3,b3,pad2; + short x3,y3; +} POLY_G4; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char u0,v0; + unsigned short clut; + unsigned char r1,g1,b1,pad0; + short x1,y1; + unsigned char u1,v1; + unsigned short tpage; + unsigned char r2,g2,b2,pad1; + short x2,y2; + unsigned char u2,v2; + unsigned short pad2; + unsigned char r3,g3,b3,pad3; + short x3,y3; + unsigned char u3,v3; + unsigned short pad4; +} POLY_GT4; + +/* + * Line primitive definitions + */ +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + short x1,y1; +} LINE_F2; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char r1,g1,b1,p1; + short x1,y1; +} LINE_G2; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + short x1,y1; + short x2,y2; + unsigned int pad; +} LINE_F3; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char r1,g1,b1,p1; + short x1,y1; + unsigned char r2,g2,b2,p2; + short x2,y2; + unsigned int pad; +} LINE_G3; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + short x1,y1; + short x2,y2; + short x3,y3; + unsigned int pad; +} LINE_F4; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char r1,g1,b1,p1; + short x1,y1; + unsigned char r2,g2,b2,p2; + short x2,y2; + unsigned char r3,g3,b3,p3; + short x3,y3; + unsigned int pad; +} LINE_G4; + +/* + * Tile and sprite primitive definitions + */ +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + short w,h; +} TILE; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; +} TILE_1; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; +} TILE_8; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; +} TILE_16; + +/* + * Sprite primitive definitions + */ +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char u0,v0; + unsigned short clut; + unsigned short w,h; +} SPRT; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char u0,v0; + unsigned short clut; +} SPRT_8; + +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + short x0,y0; + unsigned char u0,v0; + unsigned short clut; +} SPRT_16; + +/* + * VRAM fill and transfer primitive definitions + */ +typedef struct { + unsigned int tag; + unsigned char r0,g0,b0,code; + unsigned short x0,y0; // Note: coordinates must be in 16 pixel steps + unsigned short w,h; +} FILL; + +typedef struct { + unsigned int tag; + unsigned char p0,p1,p2,code; + unsigned short x0,y0; + unsigned short x1,y1; + unsigned short w,h; + unsigned int nop[4]; +} VRAM2VRAM; + +typedef struct { + unsigned int tag; + unsigned int code[15]; +} DR_ENV; + +typedef struct { + unsigned int tag; + unsigned int code[2]; +} DR_TWIN; + +typedef struct { + unsigned int tag; + unsigned int code[1]; +} DR_TPAGE; + +typedef struct { /* ORIGINAL CODE */ + unsigned int tag; + unsigned int code[1]; +} DR_MASK; + + +// General structs + +typedef struct { + short x,y; + short w,h; +} RECT; + +typedef struct { + unsigned int vid_mode; // Video mode + short vid_xpos,vid_ypos; // Video position (not framebuffer) + short fb_x,fb_y; // Framebuffer display position +} DISPENV_RAW; + +typedef struct { + RECT disp; + RECT screen; + char isinter; + char isrgb24; + char reverse; + char pad; +} DISPENV; + +typedef struct { + RECT clip; // Drawing area + short ofs[2]; // GPU draw offset (relative to draw area) + RECT tw; // Texture window (doesn't do anything atm) + unsigned short tpage; // Initial tpage value + unsigned char dtd; // Dither processing flag (simply OR'ed to tpage) + unsigned char dfe; // Drawing to display area blocked/allowed (simply OR'ed to tpage) + unsigned char isbg; // Clear draw area if non-zero + unsigned char r0,g0,b0; // Draw area clear color (if isbg iz nonzero) + DR_ENV dr_env; // Draw mode packet area (used by PutDrawEnv) +} DRAWENV; + +typedef struct { + unsigned int mode; + RECT *crect; + unsigned int *caddr; + RECT *prect; + unsigned int *paddr; +} TIM_IMAGE; + + +#ifdef __cplusplus +extern "C" { +#endif + +// Function definitions (asm) + +void ResetGraph(int mode); + +int GetVideoMode(); +void SetVideoMode(int mode); + +void PutDispEnvRaw(DISPENV_RAW *disp); +void PutDispEnv(DISPENV *disp); +void PutDrawEnv(DRAWENV *draw); + +void SetDispMask(int mask); + +void VSync(); +void DrawSync(); +void WaitGPUcmd(); +void WaitGPUdma(); + +void VSyncCallback(void (*func)()); + +void LoadImage(RECT *rect, unsigned int *data); + +void ClearOTagR(unsigned int* ot, int n); +void DrawOTag(unsigned int* ot); + +void AddPrim(unsigned int* ot, void* pri); + +// Function definitions (C) + +int GetTimInfo(unsigned int *tim, TIM_IMAGE *timimg); + +DISPENV *SetDefDispEnv(DISPENV *disp, int x, int y, int w, int h); +DRAWENV *SetDefDrawEnv(DRAWENV *draw, int x, int y, int w, int h); + +#ifdef __cplusplus +} +#endif + +#endif
\ No newline at end of file diff --git a/libpsn00b/include/psxgte.h b/libpsn00b/include/psxgte.h new file mode 100644 index 0000000..0a8ded0 --- /dev/null +++ b/libpsn00b/include/psxgte.h @@ -0,0 +1,72 @@ +#ifndef _PSXGTE_H +#define _PSXGTE_H + + +#define ONE 4096 + + +// For compatibility with official library syntax +#define csin(a) isin(a) +#define ccos(a) icos(a) +#define rsin(a) isin(a) +#define rcos(a) icos(a) + + +typedef struct { + short m[3][3]; + int t[3]; +} MATRIX; + +typedef struct { + int vx, vy, vz; +} VECTOR; + +typedef struct { + short vx, vy, vz, pad; +} SVECTOR; + +typedef struct { + unsigned char r, g, b, cd; +} CVECTOR; + + +#ifdef __cplusplus +extern "C" { +#endif + +void InitGeom(); + +// Integer SIN/COS functions (4096 = 360 degrees) +// Does not use tables! +int isin(int a); +int icos(int a); + +// Higher precision integer sin/cos functions (131072 = 360 degrees) +// Does not use tables! +int hisin(int a); +int hicos(int a); + +void PushMatrix(); +void PopMatrix(); + +MATRIX *RotMatrix(SVECTOR *r, MATRIX *m); +MATRIX *HiRotMatrix(VECTOR *r, MATRIX *m); + +MATRIX *TransMatrix(MATRIX *m, VECTOR *r); +MATRIX *ScaleMatrix(MATRIX *m, VECTOR *s); + +MATRIX *MulMatrix(MATRIX *m0, MATRIX *m1); +MATRIX *MulMatrix0(MATRIX *m0, MATRIX *m1, MATRIX *m2); + +MATRIX *CompMatrixLV(MATRIX *v0, MATRIX *v1, MATRIX *v2); +VECTOR *ApplyMatrixLV(MATRIX *m, VECTOR *v0, VECTOR *v1); + +void VectorNormalS(VECTOR *v0, SVECTOR *v1); + +void Square0(VECTOR *v0, VECTOR *v1); + +#ifdef __cplusplus +} +#endif + +#endif // _PSXGTE_H diff --git a/libpsn00b/include/psxkernel.h b/libpsn00b/include/psxkernel.h new file mode 100644 index 0000000..0c55bcb --- /dev/null +++ b/libpsn00b/include/psxkernel.h @@ -0,0 +1,45 @@ +#ifndef _PSXKERNEL_H +#define _PSXKERNEL_H + +// Event descriptors +#define DescMask 0xff000000 // Event descriptor mask +#define DescTH DescMask +#define DescHW 0xf0000000 // Hardware event (IRQ) +#define DescEV 0xf1000000 // Event event +#define DescRC 0xf2000000 // Root counter event +#define DescUEV 0xf3000000 // User event +#define DescSW 0xf4000000 // BIOS event + +// Hardware events +#define HwVBLANK (DescHW|0x01) // VBlank +#define HwGPU (DescHW|0x02) // GPU +#define HwCdRom (DescHW|0x03) // CDROM +#define HwDMAC (DescHW|0x04) // DMA +#define HwRTC0 (DescHW|0x05) // Timer 0 +#define HwRTC1 (DescHW|0x06) // Timer 1 +#define HwRTC2 (DescHW|0x07) // Timer 2 +#define HwCNTL (DescHW|0x08) // Controller +#define HwSPU (DescHW|0x09) // SPU +#define HwPIO (DescHW|0x0a) // PIO & lightgun +#define HwSIO (DescHW|0x0b) // Serial + +#define HwCPU (DescHW|0x10) // Processor exception +#define HwCARD (DescHW|0x11) // Memory card (lower level BIOS functions) +#define HwCard_0 (DescHW|0x12) // Memory card (unused) +#define HwCard_1 (DescHW|0x13) // Memory card (unused) +#define SwCARD (DescSW|0x01) // Memory card (higher level BIOS functions) +#define SwMATH (DescSW|0x02) // Libmath related apparently, unknown purpose + +#define RCntCNT0 (DescRC|0x00) // Root counter 0 (dot clock) +#define RCntCNT1 (DescRC|0x01) // Horizontal sync +#define RCntCNT2 (DescRC|0x02) // 1/8 of system clock +#define RCntCNT3 (DescRC|0x03) // Vertical blank + +#define RCntMdINTR 0x1000 // General interrupt +#define RCntMdNOINTR 0x2000 // New device +#define RCntMdSC 0x0001 // Counter becomes zero +#define RCntMdSP 0x0000 // Unknown purpose +#define RCntMdFR 0x0000 +#define RCntMdGATE 0x0010 // Command acknowledged + +#endif // _PSXKERNEL_H
\ No newline at end of file diff --git a/libpsn00b/include/psxpad.h b/libpsn00b/include/psxpad.h new file mode 100644 index 0000000..09d17b1 --- /dev/null +++ b/libpsn00b/include/psxpad.h @@ -0,0 +1,108 @@ +/* Controller support header + * Part of PSn00bSDK + * 2019 Lameguy64 / Meido-Tek Productions + * + * Currently only provides a bunch of definitions and a few structs but no + * handling functions yet. Use the code in pad.s in one of the sample + * programs for the meantime instead. + * + * Work in progress, subject to change significantly in future releases. + */ + +#ifndef _PSXPAD_H +#define _PSXPAD_H + +// Pad button definitions for digital pad, joystick, dual analog, +// Dualshock and Jogcon +#define PAD_SELECT 1 +#define PAD_L3 2 +#define PAD_R3 4 +#define PAD_START 8 +#define PAD_UP 16 +#define PAD_RIGHT 32 +#define PAD_DOWN 64 +#define PAD_LEFT 128 +#define PAD_L2 256 +#define PAD_R2 512 +#define PAD_L1 1024 +#define PAD_R1 2048 +#define PAD_TRIANGLE 4096 +#define PAD_CIRCLE 8192 +#define PAD_CROSS 16384 +#define PAD_SQUARE 32768 + +// Mouse button definitions +#define MOUSE_RIGHT 1024 +#define MOUSE_LEFT 2048 + +// neGcon button definitions +#define NCON_START 8 +#define NCON_UP 16 +#define NCON_RIGHT 32 +#define NCON_DOWN 64 +#define NCON_LEFT 128 +#define NCON_R 256 +#define NCON_B 512 +#define NCON_A 1024 + +// Guncon button definitions +#define GCON_A 8 +#define GCON_TRIGGER 8192 +#define GCON_B 16384 + +// Struct for digital, joystick, dual analog and Dualshock controllers +typedef struct { + unsigned char stat; // Status + unsigned char len:4; // Data length (in halfwords) + unsigned char type:4; // Device type: + // 0x4 - digital pad + // 0x5 - analog joystick + // 0x7 - dual analog & Dualshock + unsigned short btn; // Button states + unsigned char rs_x,rs_y; // Right stick coordinates + unsigned char ls_x,ls_y; // Left stick coordinates +} PADTYPE; + +// Struct for a mouse controller +typedef struct { + unsigned char stat; + unsigned char len:4; + unsigned char type:4; // Device type (0x1) + unsigned char btn; + char x_mov; // X movement of mouse + char y_mov; // Y movement of mouse +} MOUSETYPE; + +// Struct for a neGcon controller (for Namco neGcon) +typedef struct { + unsigned char stat; + unsigned char len:4; + unsigned char type:4; // (0x2) + unsigned short btn; + unsigned char twist; // Controller twist + unsigned char btn_i; // I button value + unsigned char btn_ii; // II button value + unsigned char trg_l; // L trigger value +} NCONTYPE; + +// Struct for a Jogcon controller (for Namco Jogcon) +typedef struct { + unsigned char stat; + unsigned char len:4; + unsigned char type:4; // (0xE) + unsigned short btn; + unsigned short jog_rot; // Jog rotation +} JCONTYPE; + +// Struct for a Gun-Con controller (for Namco Gun-Con) +typedef struct { + unsigned char status; + unsigned char len:4; + unsigned char type:4; // (0x6) + unsigned short btn; + unsigned short gun_x; // Gun X position in dotclocks + unsigned short gun_y; // Gun Y position in scanlines +} GCONTYPE; + + +#endif
\ No newline at end of file diff --git a/libpsn00b/include/psxspu.h b/libpsn00b/include/psxspu.h new file mode 100644 index 0000000..a87e347 --- /dev/null +++ b/libpsn00b/include/psxspu.h @@ -0,0 +1,138 @@ +#ifndef __PSXSPU_H +#define __PSXSPU_H + +#include <sys/types.h> + +// Mask settings bits for specifying voice channels + +#define SPU_00CH (1<<0) +#define SPU_01CH (1<<1) +#define SPU_02CH (1<<2) +#define SPU_03CH (1<<3) +#define SPU_04CH (1<<4) +#define SPU_05CH (1<<5) +#define SPU_06CH (1<<6) +#define SPU_07CH (1<<7) +#define SPU_08CH (1<<8) +#define SPU_09CH (1<<9) +#define SPU_10CH (1<<10) +#define SPU_11CH (1<<11) +#define SPU_12CH (1<<12) +#define SPU_13CH (1<<13) +#define SPU_14CH (1<<14) +#define SPU_15CH (1<<15) +#define SPU_16CH (1<<16) +#define SPU_17CH (1<<17) +#define SPU_18CH (1<<18) +#define SPU_19CH (1<<19) +#define SPU_20CH (1<<20) +#define SPU_21CH (1<<21) +#define SPU_22CH (1<<22) +#define SPU_23CH (1<<23) + +#define SPU_0CH SPU_00CH +#define SPU_1CH SPU_01CH +#define SPU_2CH SPU_02CH +#define SPU_3CH SPU_03CH +#define SPU_4CH SPU_04CH +#define SPU_5CH SPU_05CH +#define SPU_6CH SPU_06CH +#define SPU_7CH SPU_07CH +#define SPU_8CH SPU_08CH +#define SPU_9CH SPU_09CH + +#define SPU_KEYCH(x) (1<<(x)) +#define SPU_VOICECH(x) SPU_KEYCH(x) + + +// Mask setting bits for SpuVoiceAttr.mask + +#define SPU_VOICE_VOLL (1<<0) // Left volume +#define SPU_VOICE_VOLR (1<<1) // Right volume +#define SPU_VOICE_VOLMODEL (1<<2) // Left volume mode +#define SPU_VOICE_VOLMODER (1<<3) // Right volume mode +#define SPU_VOICE_PITCH (1<<4) // Pitch tone +#define SPU_VOICE_NOTE (1<<5) // Pitch note +#define SPU_VOICE_SAMPLE_NOTE (1<<6) // Sample base frequency? +#define SPU_VOICE_WDSA (1<<7) // Sample start address (in SPU RAM) +#define SPU_VOICE_ADSR_AMODE (1<<8) // ADSR attack mode +#define SPU_VOICE_ADSR_SMODE (1<<9) // ADSR sustain mode +#define SPU_VOICE_ADSR_RMODE (1<<10) // ADSR release mode +#define SPU_VOICE_ADSR_AR (1<<11) // ADSR attack rate +#define SPU_VOICE_ADSR_DR (1<<12) // ADSR decay rate +#define SPU_VOICE_ADSR_SR (1<<13) // ADSR sustain rate +#define SPU_VOICE_ADSR_RR (1<<14) // ADSR release rate +#define SPU_VOICE_ADSR_SL (1<<15) // ADSR sustain level +#define SPU_VOICE_LSAX (1<<16) // Loop start address (in SPU RAM) +#define SPU_VOICE_ADSR_ADSR1 (1<<17) // adsr1 for VagAtr (?) +#define SPU_VOICE_ADSR_ADSR2 (1<<18) // adsr2 for VagAtr (?) + + +#define SPU_TRANSFER_BY_DMA 0 + + +typedef struct { + short left; + short right; +} SpuVolume; + +typedef struct { + SpuVolume vol; // 0 + unsigned short freq; // 4 + unsigned short addr; // 6 + unsigned short loop_addr; // 8 + unsigned short res; // 10 + unsigned int adsr_param; // 12 +} SpuVoiceRaw; + +typedef struct { + u_int voice; + u_int mask; + SpuVolume volume; + SpuVolume volmode; + SpuVolume volumex; + u_short pitch; + u_short note; + u_short sample_note; + short envx; + u_int addr; + u_int loop_addr; + int a_mode; + int s_mode; + int r_mode; + u_short ar; + u_short dr; + u_short sr; + u_short rr; + u_short sl; + u_short adsr1; + u_short adsr2; +} SpuVoiceAttr; + +#ifdef __cplusplus +extern "C" { +#endif + +void SpuInit(); + +void SpuSetVoiceRaw( int voice, SpuVoiceRaw* param ); +void SpuReverbOn( int voice ); +void SpuSetReverb(); + +void SpuSetReverbAddr( int addr ); +void SpuSetReverbVolume( int left, int right ); + + +void SpuSetKey(int on_off, u_int voice_bit); + +// SPU transfer functions +int SpuSetTransferMode(int mode); +int SpuSetTransferStartAddr(int addr); +int SpuWrite(unsigned char* addr, int size); +void SpuWait(); + +#ifdef __cplusplus +} +#endif + +#endif
\ No newline at end of file diff --git a/libpsn00b/include/stdarg.h b/libpsn00b/include/stdarg.h new file mode 100644 index 0000000..bdf4c00 --- /dev/null +++ b/libpsn00b/include/stdarg.h @@ -0,0 +1,122 @@ +/* Copyright (C) 1989-2018 Free Software Foundation, Inc. +This file is part of GCC. +GCC 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 3, or (at your option) +any later version. +GCC 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. +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +/* + * ISO C Standard: 7.15 Variable arguments <stdarg.h> + */ + +#ifndef _STDARG_H +#ifndef _ANSI_STDARG_H_ +#ifndef __need___va_list +#define _STDARG_H +#define _ANSI_STDARG_H_ +#endif /* not __need___va_list */ +#undef __need___va_list + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef __builtin_va_list __gnuc_va_list; +#endif + +/* Define the standard macros for the user, + if this invocation was from the user program. */ +#ifdef _STDARG_H + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L \ + || __cplusplus + 0 >= 201103L +#define va_copy(d,s) __builtin_va_copy(d,s) +#endif +#define __va_copy(d,s) __builtin_va_copy(d,s) + +/* Define va_list, if desired, from __gnuc_va_list. */ +/* We deliberately do not define va_list when called from + stdio.h, because ANSI C says that stdio.h is not supposed to define + va_list. stdio.h needs to have access to that data type, + but must not use that name. It should use the name __gnuc_va_list, + which is safe because it is reserved for the implementation. */ + +#ifdef _BSD_VA_LIST +#undef _BSD_VA_LIST +#endif + +#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST)) +/* SVR4.2 uses _VA_LIST for an internal alias for va_list, + so we must avoid testing it and setting it here. + SVR4 uses _VA_LIST as a flag in stdarg.h, but we should + have no conflict with that. */ +#ifndef _VA_LIST_ +#define _VA_LIST_ +#ifdef __i860__ +#ifndef _VA_LIST +#define _VA_LIST va_list +#endif +#endif /* __i860__ */ +typedef __gnuc_va_list va_list; +#ifdef _SCO_DS +#define __VA_LIST +#endif +#endif /* _VA_LIST_ */ +#else /* not __svr4__ || _SCO_DS */ + +/* The macro _VA_LIST_ is the same thing used by this file in Ultrix. + But on BSD NET2 we must not test or define or undef it. + (Note that the comments in NET 2's ansi.h + are incorrect for _VA_LIST_--see stdio.h!) */ +#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT) +/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */ +#ifndef _VA_LIST_DEFINED +/* The macro _VA_LIST is used in SCO Unix 3.2. */ +#ifndef _VA_LIST +/* The macro _VA_LIST_T_H is used in the Bull dpx2 */ +#ifndef _VA_LIST_T_H +/* The macro __va_list__ is used by BeOS. */ +#ifndef __va_list__ +typedef __gnuc_va_list va_list; +#endif /* not __va_list__ */ +#endif /* not _VA_LIST_T_H */ +#endif /* not _VA_LIST */ +#endif /* not _VA_LIST_DEFINED */ +#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__)) +#define _VA_LIST_ +#endif +#ifndef _VA_LIST +#define _VA_LIST +#endif +#ifndef _VA_LIST_DEFINED +#define _VA_LIST_DEFINED +#endif +#ifndef _VA_LIST_T_H +#define _VA_LIST_T_H +#endif +#ifndef __va_list__ +#define __va_list__ +#endif + +#endif /* not _VA_LIST_, except on certain systems */ + +#endif /* not __svr4__ */ + +#endif /* _STDARG_H */ + +#endif /* not _ANSI_STDARG_H_ */ +#endif /* not _STDARG_H */
\ No newline at end of file diff --git a/libpsn00b/include/stdio.h b/libpsn00b/include/stdio.h new file mode 100644 index 0000000..5ee9e9b --- /dev/null +++ b/libpsn00b/include/stdio.h @@ -0,0 +1,47 @@ +#ifndef _STDIO_H +#define _STDIO_H + +#include <stdarg.h> + +#ifndef NULL +#define NULL (void*)0 +#endif + +// BIOS seek modes +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif +#ifndef SEEK_END +#define SEEK_END 2 /* warning: reportedly buggy */ +#endif + +#ifndef _SIZE_T +#define _SIZE_T +typedef unsigned int size_t; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// The following functions use the BIOS +extern void printf (const char *__format, ...); + +extern int getc(int __fd); +extern int putc(int __char, int __fd); +extern void putchar(int __c); + +// The following functions do not use the BIOS +int vsnprintf(char *string, unsigned int size, char *fmt, va_list ap); +int vsprintf(char *string, char *fmt, va_list ap); +int sprintf(char *string, char *fmt, ...); +int snprintf(char *string, unsigned int size, char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +#endif // _STDIO_H
\ No newline at end of file diff --git a/libpsn00b/include/stdlib.h b/libpsn00b/include/stdlib.h new file mode 100644 index 0000000..3909796 --- /dev/null +++ b/libpsn00b/include/stdlib.h @@ -0,0 +1,57 @@ +/* + * stdlib.h + * + * Standard library functions + * + * Inherited from PSXSDK + */ + +#ifndef _STDLIB_H +#define _STDLIB_H + +#define RAND_MAX 0x7fff + +/* Conversion functions (not yet implemented) */ + +/* +extern int atoi(char *s); +extern long atol(char *s); +extern char atob(char *s); // Is this right? +*/ + +// Random number functions (not yet implemented) + +/* +int rand(); +void srand(unsigned int seed); +*/ + +// Quick sort (not yet implemented) + +//void qsort(void *base , int nel , int width , int (*cmp)(const void *,const void *)); + +// Memory allocation functions (not yet implemented, avoid using BIOS as they are reportedly buggy) + +/* +#warning "malloc() family of functions NEEDS MORE TESTING" + +void *malloc(int size); +void free(void *buf); +void *calloc(int number, int size); +void *realloc(void *buf , int n); +*/ + +int rand(); +void srand(unsigned long seed); + +int abs(int j); +long long strtoll(const char *nptr, char **endptr, int base); +long strtol(const char *nptr, char **endptr, int base); +long double strtold(const char *nptr, char **endptr); + +// Note: these use floats internally! +double strtod(const char *nptr, char **endptr); +float strtof(const char *nptr, char **endptr); + +#endif + diff --git a/libpsn00b/include/string.h b/libpsn00b/include/string.h new file mode 100644 index 0000000..95796d5 --- /dev/null +++ b/libpsn00b/include/string.h @@ -0,0 +1,42 @@ +/* + * string.h + * + * Prototypes for string functions of the C library + * + * PSXSDK + */ + +#ifndef _STRING_H +#define _STRING_H + +int strcmp(const char *dst , const char *src); +int strncmp(const char *dst , const char *src , int len); +char *strpbrk(const char *dst , const char *src); +char *strtok(char *s , char *set); +char *strstr(const char *big , const char *little); + +//int strspn(char *s , char *set); +//int strcspn(char *s , char *set); +//int index(char *s , int c); +//int rindex(char *s , int c); + +char *strcat(char *s , const char *append); +char *strncat(char *s , const char *append, int n); +char *strcpy(char *dst , const char *src); +char *strncpy(char *dst , const char *src , int n); +int strlen(const char *s); +//char *strchr(const char *s , int c); +//char *strrchr(const char *s , int c); + +void *memmove(void *dst , const void *src , int n); +void *memchr(void *s , int c , int n); + +// Functions converted to ASM + +void *memcpy(void *dst , const void *src , int n); +void *memset(void *dst , char c , int n); +int memcmp(const void *b1 , const void *b2 , int n); + + +#endif + diff --git a/libpsn00b/include/strings.h b/libpsn00b/include/strings.h new file mode 100644 index 0000000..e5e88d4 --- /dev/null +++ b/libpsn00b/include/strings.h @@ -0,0 +1,18 @@ +/* + * strings.h + * + * PSXSDK + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +#include <string.h> + +#define bcopy(src,dst,len) memmove(dst,src,len) +#define bzero(ptr, len) memset(ptr, 0, len) +#define bcmp(b1,b2,len) memcmp(b1,b2,len) +#define index(s, c) strchr(s, c) +#define rindex(s, c) strrchr(s, c) + +#endif diff --git a/libpsn00b/include/sys/fcntl.h b/libpsn00b/include/sys/fcntl.h new file mode 100644 index 0000000..dfbf5b2 --- /dev/null +++ b/libpsn00b/include/sys/fcntl.h @@ -0,0 +1,20 @@ +#ifndef _SYS_FCNTL_H +#define _SYS_FCNTL_H + +// File control mode flags for BIOS file functions +// (many weren't documented in nocash docs) +#define FREAD 0x1 // Read +#define FWRITE 0x2 // Write +#define FNBLOCK 0x4 // Non-blocking read access +#define FRLOCK 0x10 // Read lock +#define FWLOCK 0x20 // Write lock +#define FAPPEND 0x100 // Append +#define FCREATE 0x200 // Create if not exist +#define FTRUNC 0x400 // Truncate to zero length +#define FSCAN 0x2000 // Scanning type +#define FRCOM 0x2000 // Remote command entry +#define FNBUF 0x4000 // No ring buffer and terminal interrupt +#define FASYNC 0x8000 // Asynchronous I/O +#define FNBLOCKS(a) (a<<16) // Number of blocks? (from nocash docs) + +#endif
\ No newline at end of file diff --git a/libpsn00b/include/sys/types.h b/libpsn00b/include/sys/types.h new file mode 100644 index 0000000..2f30a5f --- /dev/null +++ b/libpsn00b/include/sys/types.h @@ -0,0 +1,9 @@ +#ifndef _TYPES_H +#define _TYPES_H + +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; + +#endif // _TYPES_H
\ No newline at end of file diff --git a/libpsn00b/libc/makefile b/libpsn00b/libc/makefile new file mode 100644 index 0000000..feadbdb --- /dev/null +++ b/libpsn00b/libc/makefile @@ -0,0 +1,38 @@ +# Run using make (Linux) or gmake (BSD) +# Part of the PSn00bSDK Project +# 2019 Lameguy64 / Meido-Tek Productions + +PREFIX = mipsel-unknown-elf- + +TARGET = ../libc.a + +CFILES = $(notdir $(wildcard ./*.c)) +AFILES = $(notdir $(wildcard ./*.s)) +OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) + +INCLUDE = -I../include + +CFLAGS = -O2 -msoft-float -fno-builtin -fdata-sections -ffunction-sections -Wa,--strip-local-absolute +AFLAGS = -msoft-float -Wa,--strip-local-absolute + +CC = $(PREFIX)gcc +AS = $(PREFIX)as +AR = $(PREFIX)ar +RANLIB = $(PREFIX)ranlib + +all: $(TARGET) + +$(TARGET): $(OFILES) + $(AR) cr $(TARGET) $(OFILES) + $(RANLIB) $(TARGET) + +build/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +build/%.o: %.s + @mkdir -p $(dir $@) + $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@ + +clean: + rm -Rf build $(TARGET) diff --git a/libpsn00b/libc/malloc.s b/libpsn00b/libc/malloc.s new file mode 100644 index 0000000..20e5371 --- /dev/null +++ b/libpsn00b/libc/malloc.s @@ -0,0 +1,216 @@ +# Custom first-fit malloc routines by Lameguy64 +# Part of the PSn00bSDK Project + +.set noreorder + +.set ND_PREV, 0 # Address to previous block (NULL if starting block) +.set ND_NEXT, 4 # Address to next block (NULL if end block) +.set ND_SIZE, 8 # Size of block +.set ND_HSIZ, 12 + +.section .text + + +# Stupid small function just to get bss end +# due to GCC insisting externs to be gp relative +.global GetBSSend +.type GetBSSend, @function +GetBSSend: + la $v0, _end + jr $ra + nop + + +# Initializes the heap for malloc +# a0 - Starting address of heap +# a1 - Size of memory heap +# +.global InitHeap +.type InitHeap, @function +InitHeap: + la $v0, _malloc_addr + sw $a0, 0($v0) + la $v0, _malloc_size + sw $a1, 0($v0) + + sw $0 , ND_PREV($a0) # Set heap header + sw $0 , ND_NEXT($a0) + jr $ra + sw $0 , ND_SIZE($a0) + + +# Allocates a block of memory in the heap +# a0 - Size of memory block to allocate. +# +.global malloc +.type malloc, @function +malloc: + addiu $a0, 3 # Round size to a multiple of 4 + srl $a0, 2 + + la $a2, _malloc_addr + lw $a2, 0($a2) + sll $a0, 2 + +.find_next: + + move $a1, $a2 + + lw $a2, ND_NEXT($a1) # Get block header + lw $v1, ND_SIZE($a1) + + subu $v0, $a2, $a1 # Compute space between current and next + + beqz $v1, .empty_block # Occupy empty block (if size = 0) + nop + + beqz $a2, .new_block # Allocate a new block (if no next) + nop + + addiu $v0, -(ND_HSIZ*2) # Compute remaining space of block + subu $v0, $v1 + + blt $v0, $a0, .find_next # Search for the next block if space is not big enough + nop + + # Perform a block split using remaining space of current block + + addiu $v0, $a1, ND_HSIZ # Compute address for new header + addu $v0, $v1 + + sw $a1, ND_PREV($v0) # Set the new block header + sw $a2, ND_NEXT($v0) + sw $a0, ND_SIZE($v0) + + sw $v0, ND_NEXT($a1) # Update previous and next blocks + sw $v0, ND_PREV($a2) + + jr $ra + addiu $v0, ND_HSIZ + +.empty_block: # Occupy an empty block + + beqz $a2, .no_next # Skip size calculation if there's no next + nop + + addiu $v0, -ND_HSIZ + blt $v0, $a0, .find_next + nop + + b .skip_space_check + nop + +.no_next: + + la $v1, _malloc_addr # Check if there's enough space for a block + lw $v1, 0($v1) + la $v0, _malloc_size + lw $v0, 0($v0) + + subu $v1, $a1, $v1 + addu $v1, $a0 + addiu $v1, ND_HSIZ + + bgt $v1, $v0, .no_space + nop + +.skip_space_check: + + sw $a0, ND_SIZE($a1) + jr $ra # Return address + addiu $v0, $a1, ND_HSIZ + +.new_block: # Create a new block + + addu $a2, $a1, $v1 # Compute address for new block + addiu $a2, ND_HSIZ + + la $v1, _malloc_addr + lw $v1, 0($v1) + la $v0, _malloc_size + lw $v0, 0($v0) + + subu $v1, $a2, $v1 + addu $v1, $a0 + addiu $v1, ND_HSIZ + + bgt $v1, $v0, .no_space # Reject if it exceeds specified size + nop + + sw $a1, ND_PREV($a2) + sw $0 , ND_NEXT($a2) + sw $a0, ND_SIZE($a2) + + sw $a2, ND_NEXT($a1) + + jr $ra # Return address + addiu $v0, $a2, ND_HSIZ + +.no_space: # Return a null if no space can be found + jr $ra + move $v0, $0 + + +# Allocates a block of memory in block units and zero fills the +# allocated block. +# a0 - Block size. +# a1 - Number of blocks to allocate +# +.global calloc +.type calloc, @function +calloc: + mult $a0, $a1 + addiu $sp, -4 + sw $ra, 0($sp) + + jal malloc + mflo $a0 + + move $a0, $v0 + mflo $a1 +.clear_loop: + sw $0 , 0($a0) + addi $a1, 4 + bgtz $a1, .clear_loop + addiu $a0, 4 + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + + +# Deallocates an allocated block +# a0 - An address returned by malloc to deallocate +# +.global free +.type free, @function +free: + + addiu $a0, -ND_HSIZ + lw $a1, ND_PREV($a0) + lw $a2, ND_NEXT($a0) + + beqz $a1, .is_start # Check if block is a starting block + nop + + beqz $a2, .is_end + nop + + # Unlink + + sw $a2, ND_NEXT($a1) + jr $ra + sw $a1, ND_PREV($a2) + +.is_end: # Unlinks the ending block + jr $ra + sw $0 , ND_NEXT($a1) +.is_start: # Simply set size to 0 if starting block + jr $ra + sw $0 , ND_SIZE($a0) + + +# Internal variables +.comm _malloc_addr, 4, 4 +.comm _malloc_size, 4, 4 diff --git a/libpsn00b/libc/memcmp.s b/libpsn00b/libc/memcmp.s new file mode 100644 index 0000000..b8b495d --- /dev/null +++ b/libpsn00b/libc/memcmp.s @@ -0,0 +1,31 @@ +# High speed ASM memcmp implementation by Lameguy64 +# +# Part of PSn00bSDK + +.set noreorder + +.section .text + +# Arguments: +# a0 - buffer 1 address +# a1 - buffer 2 address +# a2 - bytes to compare +.global memcmp +.type memcmp, @function +memcmp: + blez $a2, .exit + addi $a2, -1 + lbu $v0, 0($a0) + lbu $v1, 0($a1) + addiu $a0, 1 + bne $v0, $v1, .mismatch + addiu $a1, 1 + b memcmp + nop +.mismatch: + jr $ra + sub $v0, $v1 +.exit: + jr $ra + move $v0, $0 +
\ No newline at end of file diff --git a/libpsn00b/libc/memcpy.s b/libpsn00b/libc/memcpy.s new file mode 100644 index 0000000..e1a4e30 --- /dev/null +++ b/libpsn00b/libc/memcpy.s @@ -0,0 +1,28 @@ +# High speed ASM memcpy implementation by Lameguy64 +# +# Part of PSn00bSDK + +.set noreorder + +.section .text + +# Arguments: +# a0 - destination address +# a1 - source adress +# a2 - bytes to copy +.global memcpy +.type memcpy, @function +memcpy: + move $v0, $a0 +.loop: + blez $a2, .exit + addi $a2, -1 + lbu $a3, 0($a1) + addiu $a1, 1 + sb $a3, 0($a0) + b .loop + addiu $a0, 1 +.exit: + jr $ra + nop +
\ No newline at end of file diff --git a/libpsn00b/libc/memmove.s b/libpsn00b/libc/memmove.s new file mode 100644 index 0000000..961e71f --- /dev/null +++ b/libpsn00b/libc/memmove.s @@ -0,0 +1,29 @@ +.set noreorder + +.section .text + +# Arguments +# a0 - destination address +# a1 - source address +# a2 - bytes to move +.global memmove +.type memmove, @function +memmove: + move $v0, $a0 + addu $a0, $a2 + addu $a1, $a2 + addiu $a0, -1 + addiu $a1, -1 +.loop: + blez $a2, .exit + addi $a2, -1 + lbu $v1, 0($a1) + addiu $a1, -1 + sb $v1, 0($a0) + addiu $a0, -1 + b .loop + nop +.exit: + jr $ra + nop +
\ No newline at end of file diff --git a/libpsn00b/libc/memset.s b/libpsn00b/libc/memset.s new file mode 100644 index 0000000..f7d86b1 --- /dev/null +++ b/libpsn00b/libc/memset.s @@ -0,0 +1,25 @@ +# High speed ASM memset implementation by Lameguy64 +# +# Part of PSn00bSDK + +.set noreorder + +.section .text + +# Arguments: +# a0 - address to buffer +# a1 - value to set +# a2 - bytes to set +.global memset +.type memset,@function +memset: + move $v0, $a0 + blez $a2, .exit + addi $a2, -1 + sb $a1, 0($a0) + b memset + addiu $a0, 1 +.exit: + jr $ra + nop +
\ No newline at end of file diff --git a/libpsn00b/libc/printf.c b/libpsn00b/libc/printf.c new file mode 100644 index 0000000..7350648 --- /dev/null +++ b/libpsn00b/libc/printf.c @@ -0,0 +1,788 @@ +/* printf.c + * + * Inherited from the PSXSDK C library + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define SPRINTF_ALT_FLAG (1<<0) +#define SPRINTF_ZERO_FLAG (1<<1) +#define SPRINTF_NEGFIELD_FLAG (1<<2) +#define SPRINTF_SPACE_FLAG (1<<3) +#define SPRINTF_SIGN_FLAG (1<<4) + +// sprintf() macros to calculate the real padding and to write it +// these were made to not repeat the code in the function +// they can only be used in sprintf() + +// sprintf macros START + +#define calculate_real_padding() \ + y = 1; \ + \ + for(x=0;x<=19;x++) \ + { \ + if(x == 0) \ + pad_quantity--; \ + else \ + { \ + if(arg / y) \ + pad_quantity--; \ + } \ + \ + y *= 10; \ + } \ + \ + if(pad_quantity < 0) pad_quantity = 0; + +/*#define calculate_real_padding_hex() \ + for (x = 0; x < 8; x++) \ + { \ + if(x == 0) \ + pad_quantity--; \ + else \ + { \ + if((arg >> (x * 4)) & 0xf) \ + pad_quantity--; \ + } \ + }*/ + +#define calculate_real_padding_hex() \ + last = 0; \ + for (x = 0; x < 16; x++) \ + if((arg >> (x * 4)) & 0xf) \ + last = x; \ + \ + pad_quantity = (pad_quantity - 1) - last; \ + if(pad_quantity < 0) pad_quantity = 0; + +#define write_padding() \ + if(!(flags & SPRINTF_NEGFIELD_FLAG)) \ + for(x = 0; x < pad_quantity; x++) \ + { \ + if(flags & SPRINTF_ZERO_FLAG) \ + put_in_string(string, ssz, '0', string_pos++); \ + else \ + put_in_string(string, ssz, ' ', string_pos++); \ + } + +#define write_neg_padding() \ + if(flags & SPRINTF_NEGFIELD_FLAG) \ + { \ + for(x = 0; x < pad_quantity; x++) \ + put_in_string(string, ssz, ' ', string_pos++);\ + } + +// sprintf macros END + +enum +{ + SPRINTF_SIZE_CHAR, + SPRINTF_SIZE_SHORT, + SPRINTF_SIZE_INT, + SPRINTF_SIZE_LONG, + SPRINTF_SIZE_LONG_LONG, +}; + +unsigned int get_arg_in_size(int size, unsigned long long *arg, unsigned int check_sign) +{ + int s = 0; + + switch(size) + { + case SPRINTF_SIZE_CHAR: + *arg &= 0xff; + + if(check_sign) + { + if(*arg & (1<<7)) + { + *arg |= 0xffffff00; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + case SPRINTF_SIZE_SHORT: + *arg &= 0xffff; + + if(check_sign) + { + if(*arg & (1<<15)) + { + *arg |= 0xffff0000; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + +// sizeof(long) == sizeof(int) on 32bit, so this will suffice for the psx + + case SPRINTF_SIZE_INT: + case SPRINTF_SIZE_LONG: + *arg &= 0xffffffff; + + if(check_sign) + { + if(*arg & (1<<31)) + { + *arg |= (long long)0xffffffff00000000; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + + case SPRINTF_SIZE_LONG_LONG: + if(check_sign) + { + if(*arg & ((long long)1<<63)) + { + *arg = ~(*arg - 1); + s = 1; + } + } + break; + } + + return s; +} + +int put_in_string(char *string, unsigned int sz, char c, int pos) +{ + if(pos>=sz) + return 0; + else + string[pos] = c; + + return 1; +} + +int libc_ulltoa(unsigned long long i, char *dst, int n) +{ + int x, y; + unsigned long long a, b; + int empty_digit = 1; + int sp=0; + int n2=0; + + for(x=20;x>=0;x--) + { + a = 1; + for(y = 0; y<x; y++) + a *= 10; + + b = (i/a); + + if(b>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + i -= b*a; + + //put_in_string(string, ssz, b + '0', string_pos++); + if(n2!=n) + { + //printf("n2=%d\n",n2); + dst[sp++] = b + '0'; + n2++; + } + } + } + + if(n2!=n)dst[sp] = 0; + + return n2; +} + +void libc_float_to_string(float fl, char *dst, int n) +{ + unsigned int *p = (unsigned int*)&fl; + unsigned long long i = 0; + unsigned long long f = 0; + int e, m, s; + int x, y; + unsigned long long z; + + s = *p >> 31; + + e = (*p >> 23) & 0xff; + + m = *p & 0x7fffff; + + if(e == 255 && m == 0) // Infinity + { + if(s) strncpy(dst, "-inf", n); + else strncpy(dst, "inf", n); + }else if(e == 255 && m != 0) // NaN + { + strncpy(dst, "nan", n); + } + else + { + e -= 127; + m |= 1<<23; + + + + for(x = 23; x >= 0; x--) + { + if(m & (1<<x)) + { + if(e >= 0) + { + z = 1; + for(y=0;y<e;y++) + z*=2; + + i+=z; + } + else + { + z = 5000000000000000000; + for(y = 1; y < -e; y++) + z /= 2; + + f+=z; + } + } + e--; + } + + if(s && n) + { + *(dst++) = '-'; + n--; + } + + x = libc_ulltoa(i, dst, n); + n-=x; + dst+=x; + + if(n) + { + *(dst++) = '.'; + n--; + if(n) + { + x = libc_ulltoa(f, dst, n<6?n:6); + n-=x; + dst+=x; + + if(n) + *dst=0; + } + } + } +} + +void libc_double_to_string(double fl, char *dst, int n) +{ + unsigned long long *p = (unsigned long long *)&fl; + unsigned long long i = 0; + unsigned long long f = 0; + unsigned long long m, s; + long long e; + int x, y; + unsigned long long z; + + s = *p >> 63; + + e = (*p >> 52) & 0x7ff; + //printf("%d\n", e); + + m = *p & 0xfffffffffffff; + + for(x=0;x<52;x++) + if(m&((unsigned long long)1<<(52-x))) putchar('1'); else putchar('0'); + + if(e == 255 && m == 0) // Infinity + { + if(s) strncpy(dst, "-inf", n); + else strncpy(dst, "inf", n); + }else if(e == 255 && m != 0) // NaN + { + strncpy(dst, "nan", n); + } + else + { + e -= 1023; + m |= (unsigned long long)1<<52; + + for(x = 52; x >= 0; x--) + { + if(m & ((unsigned long long)1<<x)) + { + if(e >= 0) + { + z = (long long)1<<e; + + i+=z; + } + else + { + z = 5000000000000000000; + z >>= -(e + 1); + + f+=z; + } + } + e--; + } + + if(s && n) + { + *(dst++) = '-'; + n--; + } + + x = libc_ulltoa(i, dst, n); + n-=x; + dst+=x; + + if(n) + { + *(dst++) = '.'; + n--; + if(n) + libc_ulltoa(f, dst, n<6?n:6); + } + } +} + +char libc_sprintf_floatbuf[64]; + +int vsnprintf(char *string, unsigned int size, char *fmt, va_list ap) +{ + int string_pos,fmt_pos; + int l; + unsigned long long arg; + unsigned char *argcp; + unsigned char *argcp_tmp; + int directive_coming = 0; + int alternate_form = 0; + int flags = 0; + int argsize = 2; // int + int x, y; + unsigned long long a, b; + int empty_digit; + int ssz = size - 1; + int zero_flag_imp = 0; + int pad_quantity = 0; + int last; + + l = strlen(fmt); + + string_pos = 0; + + for(fmt_pos=0;fmt_pos<l;fmt_pos++) + { + if(directive_coming) + { + switch(fmt[fmt_pos]) + { + case '%': + put_in_string(string, ssz, '%', string_pos++); + directive_coming = 0; + break; + case ' ': + flags |= SPRINTF_SPACE_FLAG; + break; + case '#': // Specify alternate form + flags |= SPRINTF_ALT_FLAG; + break; + case '+': // Specify sign in signed conversions + flags |= SPRINTF_SIGN_FLAG; + break; + case '0': // Padding with zeros... + if(zero_flag_imp == 0) + { + flags |= SPRINTF_ZERO_FLAG; + zero_flag_imp = 1; + //printf("Zero padding enabled!\n"); + } + else + { + pad_quantity *= 10; + //printf("pad_quantity = %d\n", pad_quantity); + } + break; + case '1' ... '9': // '...' cases are a GNU extension, + // but they simplify a lot + + pad_quantity *= 10; + pad_quantity += fmt[fmt_pos] - '0'; + zero_flag_imp = 1; + + //printf("pad_quantity = %d\n", pad_quantity); + break; + case '-': // Negative field flag + if(flags & SPRINTF_ZERO_FLAG) + flags &= ~SPRINTF_ZERO_FLAG; + + flags |= SPRINTF_NEGFIELD_FLAG; + break; + case 'h': // Half argument size + if(argsize) argsize--; + break; + case 'l': // Double argument size + if(argsize < 2) argsize = 2; + else if(argsize < SPRINTF_SIZE_LONG_LONG) argsize++; + break; + case 'd': // signed decimal + case 'i': + empty_digit = 1; + + //printf("argsize = %d\n", argsize); + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long); + + if(get_arg_in_size(argsize, &arg, 1)) + { + put_in_string(string, ssz, '-', string_pos++); + pad_quantity--; + } + else + { + if(flags & SPRINTF_SIGN_FLAG) + { + put_in_string(string, ssz, '+', string_pos++); + pad_quantity--; + } + } + + /* Calculate how much padding we have to write */ + + /*y = 1; + + for(x=0;x<=9;x++) + { + if(x == 0) + pad_quantity--; + else + { + if(arg / y) + pad_quantity--; + } + + y *= 10; + } + if(pad_quantity < 0) pad_quantity = 0;*/ + + calculate_real_padding(); + + //printf("Actual pad quantity = %d\n", pad_quantity); + + + + /*if(!(flags & SPRINTF_NEGFIELD_FLAG)) + { + for(x = 0; x < pad_quantity; x++) + { + if(flags & SPRINTF_ZERO_FLAG) + put_in_string(string, ssz, '0', string_pos++); + else + put_in_string(string, ssz, ' ', string_pos++); + } + }*/ + + write_padding(); + + for(x=19;x>=0;x--) + { + a = 1; + for(y = 0; y<x; y++) + a *= 10; + + b = (arg/a); + + if(b>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + arg -= b*a; + + put_in_string(string, ssz, b + '0', string_pos++); + } + } + + /*if(flags & SPRINTF_NEGFIELD_FLAG) + { + for(x = 0; x < pad_quantity; x++) + put_in_string(string, ssz, ' ', string_pos++); + }*/ + write_neg_padding(); + + directive_coming = 0; + break; + case 'u': // unsigned decimal + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long); + + get_arg_in_size(argsize, &arg, 0); + + calculate_real_padding(); + write_padding(); + + for(x=19;x>=0;x--) + { + a = 1; + for(y = 0; y<x; y++) + a *= 10; + + + + b = (arg/a); + + if(b>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + arg -= b*a; + + put_in_string(string, ssz, b + '0', string_pos++); + } + } + + write_neg_padding(); + + directive_coming = 0; + break; + case 'x': // Hexadecimal + case 'X': // Hexadecimal with big letters + case 'p': // Hexadecimal with small letters with '0x' prefix + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long int); + + get_arg_in_size(argsize, &arg, 0); + + if(fmt_pos == 'p') + flags |= SPRINTF_ALT_FLAG; + + if(flags & SPRINTF_ALT_FLAG) + { + put_in_string(string, ssz, '0', string_pos++); + + if(fmt[fmt_pos] == 'X') + put_in_string(string, ssz, 'X', string_pos++); + else + put_in_string(string, ssz, 'x', string_pos++); + } + + calculate_real_padding_hex(); + write_padding(); + + for(x=15;x>=0;x--) + { + y = arg >> (x << 2); + y &= 0xf; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + if(y>=0 && y<=9) + put_in_string(string, ssz, y + '0', string_pos++); + else if(y>=0xA && y<=0xF) + { + if(fmt[fmt_pos] == 'X') + put_in_string(string, ssz, (y - 0xa) + 'A', string_pos++); + else + put_in_string(string, ssz, (y - 0xa) + 'a', string_pos++); + } + } + } + + write_neg_padding(); + + directive_coming = 0; + break; + case 'c': // character + arg = va_arg(ap, int); + + put_in_string(string, ssz, arg & 0xff, string_pos++); + + directive_coming = 0; + break; + case 's': // string + argcp = va_arg(ap, char *); + argcp_tmp = argcp; + + if(argcp == NULL) + { + // Non standard extension, but supported by Linux and the BSDs. + + put_in_string(string, ssz, '(', string_pos++); + put_in_string(string, ssz, 'n', string_pos++); + put_in_string(string, ssz, 'u', string_pos++); + put_in_string(string, ssz, 'l', string_pos++); + put_in_string(string, ssz, 'l', string_pos++); + put_in_string(string, ssz, ')', string_pos++); + + directive_coming = 0; + break; + } + + while(*argcp_tmp) + { + if(pad_quantity > 0) pad_quantity--; + argcp_tmp++; + } + + if(!(flags & SPRINTF_NEGFIELD_FLAG)) + { + while(pad_quantity > 0) + { + put_in_string(string,ssz, ' ', string_pos++); + pad_quantity--; + } + } + + while(*argcp) + { + put_in_string(string, ssz, *argcp, string_pos++); + argcp++; + } + + if(flags & SPRINTF_NEGFIELD_FLAG) + { + while(pad_quantity > 0) + { + put_in_string(string,ssz, ' ', string_pos++); + pad_quantity--; + } + } + + directive_coming = 0; + break; + case 'o': // Octal + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long); + + for(x=21;x>=0;x--) + { + y = arg >> (x * 3); + y &= 0x7; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + put_in_string(string, ssz, y + '0', string_pos++); + } + + directive_coming = 0; + break; + case '@': // Binary + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long); + + for(x=63;x>=0;x--) + { + y = (arg >> x); + y &= 1; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + put_in_string(string, ssz, y + '0', string_pos++); + } + + directive_coming = 0; + break; + + case 'f': + libc_double_to_string(va_arg(ap, double), libc_sprintf_floatbuf, 64); + + for(x=0;libc_sprintf_floatbuf[x]!=0;x++) + put_in_string(string, ssz, libc_sprintf_floatbuf[x], string_pos++); + + directive_coming = 0; + break; + case 'n': // Number of characters written + *(va_arg(ap,unsigned int*)) = string_pos; + + directive_coming = 0; + break; + // default + } + } + else + { + if(fmt[fmt_pos] == '%') + { + directive_coming = 1; + flags = 0; + argsize = 2; + pad_quantity = 0; + zero_flag_imp = 0; + } + else + put_in_string(string, ssz, fmt[fmt_pos], string_pos++); + } + } + string[string_pos] = 0; + return string_pos; +} + +int vsprintf(char *string, char *fmt, va_list ap) +{ + return vsnprintf(string, 0xffffffff, fmt, ap); +} + +int sprintf(char *string, char *fmt, ...) +{ + int r; + + va_list ap; + + va_start(ap, fmt); + + r = vsprintf(string, fmt, ap); + + va_end(ap); + + return r; +} + +int snprintf(char *string, unsigned int size, char *fmt, ...) +{ + int r; + + va_list ap; + + va_start(ap, fmt); + + r = vsnprintf(string, size, fmt, ap); + + va_end(ap); + + return r; +} diff --git a/libpsn00b/libc/rand.s b/libpsn00b/libc/rand.s new file mode 100644 index 0000000..a502e87 --- /dev/null +++ b/libpsn00b/libc/rand.s @@ -0,0 +1,38 @@ +.set noreorder +.set noat + +.section .text + + +.global rand +.type rand, @function +rand: + + la $at, _randseed + lw $v0, 0($at) + li $v1, 0x41c64e6d + + multu $v0, $v1 + mflo $v0 + nop + addiu $v0, 12345 + sw $v0, 0($at) + + jr $ra + andi $v0, 0x7fff + + +.global srand +.type srand, @function +srand: + la $at, _randseed + jr $ra + sw $a0, 0($at) + + +.section .data + +.type _randseed, @object +_randseed: + .word 1 +
\ No newline at end of file diff --git a/libpsn00b/libc/readme.txt b/libpsn00b/libc/readme.txt new file mode 100644 index 0000000..d7abf0a --- /dev/null +++ b/libpsn00b/libc/readme.txt @@ -0,0 +1,48 @@ +Limited C standard library implementation, part of PSn00bSDK +2019 Lameguy64 / Meido-Tek Productions + + Some components were inherited from PSXSDK. This library covers only the +most commonly used C functions, mainly most string and memory manipulation +functions. Improvements to this library such as adding more standard C +functions are welcome. + + This library also contains the start code written in assembler which +performs basic initialization such as clearing the bss section, setting the +correct gp register value and initializing the heap for malloc. + + The dynamic memory allocation functions featured in this library are of +an original implementation and do not use the BIOS memory allocation functions +as they are are reportedly prone to memory leakage and is even explained in +the official library documents. The implementation employed uses a simple +first-fit memory allocation logic. + + +Library developer(s)/contributor(s): + + Lameguy64 + + +Library header(s): + + stdio.h + stdlib.h + string.h + strings.h + malloc.h + + +Todo list: + + * Current vsprintf/sprintf implementation from PSXSDK needs to be replaced + as it performs quite slow likely due to the unnecessary int64 arithmetic + performed on any integer value which the compiler has to emulate on the + R3000. A more efficient implementation that only uses int32 is much + preferred. + + * Many of the string manipulation and memory fill functions in string.c + are yet to be replaced with more efficient assembly implementations. + + +Changelog: + + None thus far... diff --git a/libpsn00b/libc/scanf.c b/libpsn00b/libc/scanf.c new file mode 100644 index 0000000..b6d4510 --- /dev/null +++ b/libpsn00b/libc/scanf.c @@ -0,0 +1,427 @@ +// vsscanf +// Programmed by Giuseppe Gatta, 2011 +// Inherited from PSXSDK C library + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +char libc_vsscanf_buf[512]; +char libc_vsscanf_allow[256]; + +enum +{ + elem_skip_space = 1, +}; + +int libc_vsscanf_get_element(char *dst, const char *src, int flag, int s) +{ + int i; + const char *osrc = src; + + if(flag & elem_skip_space) + { + while(*src == ' ') + src++; + } + + for(i=0;i<s;i++) + { + if((flag & elem_skip_space) && *src == ' ') + break; + + if(*src != 0) + *(dst++) = *(src++); + else + break; + } + + *dst = 0; + + return src - osrc; +} + +enum +{ + scanf_s_char, scanf_s_short, scanf_s_int, + scanf_s_long, + scanf_s_long_long +}; + +int vsscanf(const char *str, const char *format, va_list ap) +{ + int fp = 0; + int sp = 0; + int conv = 0; + int sz = scanf_s_int; // size for numbers defaults to 32-bit + int i,x,y,z, h; + int suppress = 0; + int neg = 0; + int fsz = 512; + int def_fsz = 1; + int exspace = 0; + int alt = 0; + int r = 0; + int exit_loop=0; + int sp2,sp3; + char *ep; + long long buf; + double fbuf; + + + while(format[fp] && str[sp] && !exit_loop) + { + if(conv) + { + switch(format[fp]) + { + case '%': // Percent, assignment does not occur + conv = 0; + break; + + case 'h': // Halve size + sz--; + break; + + case 'l': // Double size + sz++; + break; + + case '*': // Suppress + suppress = 1; + break; + + case ' ': // Explicit space + exspace = 1; + break; + + case '#': // Alternate format + alt = 1; + break; + + case '0' ... '9': // '0' ... '9' is a GNU C extension! + if(def_fsz) + { + def_fsz = 0; + fsz = 0; + } + + fsz *= 10; + fsz+=format[fp]-'0'; + + if(fsz > 512) + fsz = 512; // 512 is the maximum. + break; + + case '@': // Binary. Non-standard extension + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + buf = strtoll(libc_vsscanf_buf, &ep, 2); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: *(va_arg(ap, signed char*)) = (signed char)buf;break; + case scanf_s_short: *(va_arg(ap, short*)) = (short)buf; break; + case scanf_s_int: *(va_arg(ap, int*)) = (int)buf; break; + case scanf_s_long: *(va_arg(ap, long*)) = (long)buf; break; + case scanf_s_long_long: *(va_arg(ap, long long*)) = buf; break; + } + r++; + } + + conv = 0; + break; + + case 'D': + sz++; + case 'd': // Decimal + case 'u': + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + buf = strtoll(libc_vsscanf_buf, &ep, 10); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: *(va_arg(ap, signed char*)) = (signed char)buf;break; + case scanf_s_short: *(va_arg(ap, short*)) = (short)buf; break; + case scanf_s_int: *(va_arg(ap, int*)) = (int)buf; break; + case scanf_s_long: *(va_arg(ap, long*)) = (long)buf; break; + case scanf_s_long_long: *(va_arg(ap, long long*)) = buf; break; + } + r++; + } + + conv = 0; + break; + + case 's': // String + sp += libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + + if(!suppress) + { + strcpy(va_arg(ap, char*), libc_vsscanf_buf); + r++; + } + + conv = 0; + break; + + case 'c': + if(def_fsz) + fsz = 1; + + sp += (i = libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], (exspace ? elem_skip_space : 0), fsz)); + if(!suppress) + { + memcpy(va_arg(ap, char*), libc_vsscanf_buf, (fsz>i)?i:fsz); + r++; + } + break; + + case 'n': + if(!suppress) + { + *(va_arg(ap, int*)) = sp; + r++; + } + break; + + case 'p': + case 'x': + case 'X': + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + buf = strtoll(libc_vsscanf_buf, &ep, 16); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: *(va_arg(ap, unsigned char*)) = (unsigned char)buf; break; + case scanf_s_short: *(va_arg(ap, unsigned short*)) = (unsigned short)buf; break; + case scanf_s_int: *(va_arg(ap, unsigned int*)) = (unsigned int)buf; break; + case scanf_s_long: *(va_arg(ap, unsigned long*)) = (unsigned long)buf; break; + case scanf_s_long_long: *(va_arg(ap, unsigned long long*)) = (unsigned long long)buf; break; + } + r++; + } + + conv = 0; + break; + + case 'O': + sz++; + case 'o': // Octal integer + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + buf = strtoll(libc_vsscanf_buf, &ep, 8); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: *(va_arg(ap, unsigned char*)) = (unsigned char)buf;break; + case scanf_s_short: *(va_arg(ap, unsigned short*)) = (unsigned short)buf; break; + case scanf_s_int: *(va_arg(ap, unsigned int*)) = (unsigned int)buf;break; + case scanf_s_long: *(va_arg(ap, unsigned long*)) = (unsigned long)buf; break; + case scanf_s_long_long: *(va_arg(ap, unsigned long long*)) = (unsigned long long)buf;break; + } + r++; + } + + conv = 0; + break; + + case 'i': + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + + if(libc_vsscanf_buf[0] == '0') + { + if(libc_vsscanf_buf[1] == 'x' || libc_vsscanf_buf[1] == 'X') + i = 16; + else + i = 8; + } + else + i = 10; + + buf = strtoll(libc_vsscanf_buf, &ep, i); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: *(va_arg(ap, signed char*)) = (signed char)buf; break; + case scanf_s_short: *(va_arg(ap, short*)) = (short)buf; break; + case scanf_s_int: *(va_arg(ap, int*)) = (int)buf; break; + case scanf_s_long: *(va_arg(ap, long*)) = (long)buf; break; + case scanf_s_long_long: *(va_arg(ap, long long*)) = (long long)buf; break; + } + r++; + } + + conv = 0; + break; + + case '[': + i=0; + x=0; // Exclusion? + h=0; // Hyphen? + + fp++; + i++; + + while(format[fp]) + { + if(format[fp] == '^' && i==1) + { + memset(libc_vsscanf_allow, 1, 256); + x = 1; + fp++; i++; continue; + } + + if(x) + { + if(format[fp] == ']' && i>=3) + break; + } + else + { + if(format[fp] == ']' && i>=2) + break; + } + + if(format[fp] == '-') + { + if(format[fp+1] != ']') + y = 1; + else + libc_vsscanf_allow['-'] = x^1; + } + else + { + if(y == 1) + { + if(format[fp] < format[fp-2]) + libc_vsscanf_allow[format[fp]] = x^1; + else + for(z = format[fp-2]; z <= format[fp]; z++) + libc_vsscanf_allow[z] = x^1; + + y = 0; + + //printf("%s all chars from %c to %c\n", x?"Excluding":"Including",format[fp-2], format[fp]); + } + else + libc_vsscanf_allow[format[fp]] = x^1; + } + + fp++; + i++; + } + +// Now as we know what our character set is, let's get data from the string + /* puts("Character set:"); + + for(y=0;y<16;y++) + { + for(x=0;x<16;x++) + if(libc_vsscanf_allow[(y*16) + x]) + putchar((y*16)+x); + else + putchar('*'); + + putchar('\n'); + } + */ + i = 0; + + while(libc_vsscanf_allow[str[sp]] && i<512) + libc_vsscanf_buf[i++] = str[sp++]; + + libc_vsscanf_buf[i] = 0; + + if(!suppress) + { + strcpy(va_arg(ap, char*), libc_vsscanf_buf); + r++; + } + break; + + case 'f': // Floating point number + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + fbuf = strtod(libc_vsscanf_buf, &ep); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: + case scanf_s_short: + case scanf_s_int: + *(va_arg(ap, float*)) = (float)fbuf; + break; + + case scanf_s_long: + case scanf_s_long_long: + *(va_arg(ap, double*)) = fbuf; + break; + } + r++; + } + + conv = 0; + break; + + } + } + else + { + if(format[fp] == '%') + { + conv = 1; + neg = 0; + suppress = 0; + sz = scanf_s_int; + fsz = 512; + def_fsz = 1; + exspace = 0; + alt = 0; + bzero(libc_vsscanf_allow, 256); + //chset = 0; + } + else if(format[fp] != ' ') + { + if(format[fp] != str[sp]) + exit_loop=1; + + sp++; + } + + } + + fp++; + } + + return r; +} + +int sscanf(const char *str, const char *fmt, ...) +{ + int r; + va_list ap; + + va_start(ap, fmt); + r = vsscanf(str, fmt, ap); + + va_end(ap); + return r; +} diff --git a/libpsn00b/libc/start.s b/libpsn00b/libc/start.s new file mode 100644 index 0000000..c9b529b --- /dev/null +++ b/libpsn00b/libc/start.s @@ -0,0 +1,39 @@ +# Start function! +# This is essentially the entrypoint of the PS-EXE + +.set noreorder + +.section .text + +.global _start +.type _start, @function +_start: + + addiu $sp, -32 + sw $ra, 28($sp) + + la $gp, _gp # Very important to set! + + la $a0, .bss # What are the CORRECT symbols for BSS start and end? + la $a1, _end +.clear_bss: + sb $0 , 0($a0) + blt $a0, $a1, .clear_bss + addiu $a0, 1 + + la $a0, _end+4 # Initialize heap for malloc (does not use BIOS maalloc) + li $a1, 1572864 + jal InitHeap + nop + + move $a0, $0 # No support for arguments for now + move $a1, $0 + + jal main + nop + + lw $ra, 28($sp) + addiu $sp, 32 + jr $ra + nop +
\ No newline at end of file diff --git a/libpsn00b/libc/string.c b/libpsn00b/libc/string.c new file mode 100644 index 0000000..4943877 --- /dev/null +++ b/libpsn00b/libc/string.c @@ -0,0 +1,301 @@ +/* + * string.c + * + * Inherited from PSXSDK C library + */ + +#include <stdio.h> +#include <string.h> +#include <malloc.h> + +int tolower(int chr) +{ + return (chr >='A' && chr<='Z') ? (chr + 32) : (chr); +} + +int toupper(int chr) +{ + return (chr >='a' && chr<='z') ? (chr - 32) : (chr); +} + +// Need to be replaced with MIPS assembler equivalents + +void *memchr(void *s , int c , int n) +{ + while(n--) + { + if(*((unsigned char*)s) == (unsigned char)c) + return s; + + s++; + } + + return NULL; +} + +char *strncpy(char *dst, const char *src, int len) +{ + char *odst=dst; + + while(*src && len) + { + *(dst++) = *(src++); + len--; + } + + if(len)*dst = 0; + + return odst; +} + +char *strcpy(char *dst, const char *src) +{ + char *odst = dst; + + while(*(dst++) = *(src++)); + return odst; +} + +char *strncat(char *s, const char *append, int len) +{ + char *o=s; + + while(*s) + s++; + + strncpy(s, append, len); + + return o; +} + +int strlen(const char *str) +{ + int i = 0; + while(*(str++))i++; + return i; +} + +char *strchr(const char *s, int c) +{ + int x; + + for(x = 0; x <= strlen(s); x++) + if(s[x] == c) return (char*)&s[x]; + + return NULL; +} + +char *strrchr(const char *s, int c) +{ + int x; + + for(x = strlen(s); x>=0; x--) + if(s[x] == c) return (char*)&s[x]; + + return NULL; +} + +char *strpbrk(const char *s, const char *charset) +{ + int x,y; + + for(x = 0; x < strlen(s); x++) + for(y = 0; y < strlen(charset); y++) + if(s[x] == charset[y]) return (char*)&s[x]; + + return NULL; +} + +char *strstr(const char *big, const char *little) +{ + int ls = strlen(little); + int bs = strlen(big); + int x; + + if(ls == 0) + return (char*)big; + + if(ls > bs) + return NULL; + + for(x = 0; x <= bs-ls; x++) + if(memcmp(little, &big[x], ls) == 0) + return (char*)&big[x]; + + return NULL; +} + +int strcmp(const char *s1, const char *s2) +{ + while(*s1 && *s2 && (*s1 == *s2)) + { + s1++; + s2++; + } + + return *s1-*s2; +} + +int strncmp(const char *s1, const char *s2, int len) +{ + int p = 0; + + while(*s1 && *s2 && (*s1 == *s2) && p<len) + { + p++; + + if(p<len) + { + s1++; + s2++; + } + } + + return *s1-*s2; +} + +// Requires a malloc implementation +char *strdup(const char *str) +{ + char *ns = (void*)malloc(strlen(str) + 1); + + if(ns == NULL) + return NULL; + + strcpy(ns, str); + return ns; +} + +char *strndup(const char *str, int len) +{ + int n=strlen(str); + char *ns = (void*)malloc((n+1)>len?len:(n+1)); + + if(ns == NULL) + return NULL; + + strncpy(ns, str, (n+1)>len?len:(n+1)); + return ns; +} + +long long strtoll(const char *nptr, char **endptr, int base) +{ + int r = 0; + int t = 0; + int n = 0; + + if(*nptr == '-') + { + nptr++; + n = 1; + } + + if(base == 0) + if(*nptr == '0') + base = 8; + else + base = 10; + + if(!(base >= 2 && base <= 36)) + return 0; + + if(base == 16 && *nptr == '0') + { + if(*(nptr+1) == 'x' || *(nptr+1) == 'X') + nptr+=2; + } + + while(*nptr) + { + switch(*nptr) + { + case '0'...'9': + t = *nptr - '0'; + break; + case 'a' ... 'z': + t = (*nptr - 'a') + 10; + break; + case 'A' ... 'Z': + t = (*nptr - 'A') + 10; + break; + default: + t = 1000; + break; + } + + if(t>=base) + break; + + r*=base; + r+=t; + nptr++; + } + + if(endptr)*endptr = (char*)nptr; + return n?-r:r; +} + +long strtol(const char *nptr, char **endptr, int base) +{ + return (long)strtoll(nptr, endptr, base); +} + +double strtod(const char *nptr, char **endptr) +{ + char strbuf[64]; + int x = 0; + int y; + double i=0, d=0; + int s=1; + + if(*nptr == '-') + { + nptr++; + s=-1; + } + + while(*nptr >= '0' && *nptr <= '9' && x < 18) + strbuf[x++] = *(nptr++); + + strbuf[x] = 0; + + i = (double)strtoll(strbuf, NULL, 10); + + if(*nptr == '.') + { + nptr++; + x = 0; + + while(*nptr >= '0' && *nptr <= '9' && x < 7) + strbuf[x++] = *(nptr++); + + strbuf[x] = 0; + + if(endptr != NULL) *endptr = (char*)nptr; + + y=1; + + for(x=0;x<strlen(strbuf);x++) + y*=10; + + d = (double)strtoll(strbuf, NULL, 10); + d /= y; + } + else + { + if(endptr != NULL) + *endptr = (char*)nptr; + } + + return (i + d)*s; +} + +long double strtold(const char *nptr, char **endptr) +{ + return (long double)strtod(nptr, endptr); +} + +float strtof(const char *nptr, char **endptr) +{ + return (float)strtod(nptr, endptr); +} diff --git a/libpsn00b/lzp/bit.c b/libpsn00b/lzp/bit.c new file mode 100644 index 0000000..aefa45d --- /dev/null +++ b/libpsn00b/lzp/bit.c @@ -0,0 +1,65 @@ +#include "bit.h" + +// Bit I/O +// + +unsigned char* inPtr = 0; +int inBytes = 0; +unsigned char* outPtr = 0; +int outBytes = 0; + +int bit_buf; +int bit_count; + +void init_bits() { + + bit_count = bit_buf=0; + +} + +void put_bits(int n, int x) { + + bit_buf |= x<<bit_count; + bit_count += n; + + while(bit_count >= 8) { + + *outPtr = bit_buf; + outPtr++; + outBytes++; + + bit_buf >>= 8; + bit_count -= 8; + + } + +} + +void flush_bits() { + + put_bits(7, 0); + bit_count = bit_buf = 0; + +} + +int get_bits(int n) { + + int x; + + while(bit_count < n) { + + bit_buf |= *inPtr<<bit_count; + inPtr++; + inBytes++; + + bit_count += 8; + + } + + x = bit_buf&((1<<n)-1); + bit_buf >>= n; + bit_count -= n; + + return(x); + +} diff --git a/libpsn00b/lzp/bit.h b/libpsn00b/lzp/bit.h new file mode 100644 index 0000000..ff71025 --- /dev/null +++ b/libpsn00b/lzp/bit.h @@ -0,0 +1,26 @@ +#ifndef _LZP_BIT_H +#define _LZP_BIT_H + +extern unsigned char* inPtr; +extern int inBytes; +extern unsigned char* outPtr; +extern int outBytes; + +extern int bit_buf; +extern int bit_count; + +#ifdef __cplusplus +extern "C" { +#endif + +void init_bits(); +void put_bits(int n, int x); +void flush_bits(); +int get_bits(int n); + +#ifdef __cplusplus +} +#endif + + +#endif // _LZP_BIT_H diff --git a/libpsn00b/lzp/compress.c b/libpsn00b/lzp/compress.c new file mode 100644 index 0000000..33af08d --- /dev/null +++ b/libpsn00b/lzp/compress.c @@ -0,0 +1,488 @@ +// Based on ilia muraviev's CRUSH compressor program which falls under public domain + +#include <string.h> +#if LZP_USE_MALLOC == TRUE +#include <stdlib.h> +#endif + +#include "lzconfig.h" +#include "bit.h" +#include "lzp.h" + + +// Internal structure for hash table allocation sizes +#if LZP_NO_COMPRESS == FALSE + +struct { + short WindowSize; // Window size (17 - 23) + short Hash1Size; // Hash 1 table size (10 - 21) + short Hash2Size; // Hash 2 table size (12 - 24) +} lzHashParam = { + LZP_WINDOW_SIZE, + LZP_HASH1_SIZE, + LZP_HASH2_SIZE +}; + +#endif + + +// Defines and macros for lz77 compression/decompression (don't touch) +#define W_BITS lzHashParam.WindowSize +#define HASH1_BITS lzHashParam.Hash1Size +#define HASH2_BITS lzHashParam.Hash2Size + +#define W_SIZE (1<<W_BITS) +#define W_MASK (W_SIZE-1) +#define SLOT_BITS 4 +#define NUM_SLOTS (1<<SLOT_BITS) + +#define A_BITS 2 // 1 xx +#define B_BITS 2 // 01 xx +#define C_BITS 2 // 001 xx +#define D_BITS 3 // 0001 xxx +#define E_BITS 5 // 00001 xxxxx +#define F_BITS 9 // 00000 xxxxxxxxx +#define A (1<<A_BITS) +#define B ((1<<B_BITS)+A) +#define C ((1<<C_BITS)+B) +#define D ((1<<D_BITS)+C) +#define E ((1<<E_BITS)+D) +#define F ((1<<F_BITS)+E) +#define MIN_MATCH 3 +#define MAX_MATCH ((F-1)+MIN_MATCH) + +#define BUF_SIZE (1<<26) +#define TOO_FAR (1<<16) + +#define HASH1_LEN MIN_MATCH +#define HASH2_LEN (MIN_MATCH+1) +#define HASH1_SIZE (1<<HASH1_BITS) +#define HASH2_SIZE (1<<HASH2_BITS) +#define HASH1_MASK (HASH1_SIZE-1) +#define HASH2_MASK (HASH2_SIZE-1) +#define HASH1_SHIFT ((HASH1_BITS+(HASH1_LEN-1))/HASH1_LEN) +#define HASH2_SHIFT ((HASH2_BITS+(HASH2_LEN-1))/HASH2_LEN) + + +// LZ77 +// + +#if LZP_NO_COMPRESS == FALSE + +int update_hash1(int h, int c) { + + return(((h<<HASH1_SHIFT)+c)&HASH1_MASK); + +} + +int update_hash2(int h, int c) { + + return(((h<<HASH2_SHIFT)+c)&HASH2_MASK); + +} + +int get_min(int a, int b) { + + return(a<b?a:b); + +} + +int get_max(int a, int b) { + + return(a>b?a:b); + +} + +int get_penalty(int a, int b) { + + int p=0; + + while(a > b) { + a >>= 3; + ++p; + } + + return(p); + +} + +int lzCompress(void* outBuff, void* inBuff, int inSize, int level) { + + #if LZP_USE_MALLOC == FALSE + int head[HASH1_SIZE+HASH2_SIZE]; + int prev[W_SIZE]; + #else + int* head = malloc(4*(HASH1_SIZE+HASH2_SIZE)); + int* prev = malloc(4*W_SIZE); + #endif + + + int max_chain[] = {4, 256, 1<<12}; + + int i,s; + int h1=0; + int h2=0; + int p=0; + + int len; + int offset; + + int max_match; + int limit; + + int chain_len; + int next_p; + int max_lazy; + int log; + + + inPtr = (unsigned char*)inBuff; + outPtr = (unsigned char*)outBuff; + outBytes = 0; + + + for (i=0; i<HASH1_SIZE+HASH2_SIZE; ++i) + head[i] = -1; + + for (i=0; i<HASH1_LEN; ++i) + h1=update_hash1(h1, inPtr[i]); + + for (i=0; i<HASH2_LEN; ++i) + h2=update_hash2(h2, inPtr[i]); + + init_bits(); + + // Put window size value so that the compressed data will be independent of the compression settings + put_bits(5, lzHashParam.WindowSize); + + while(p < inSize) { + + len = MIN_MATCH-1; + offset = W_SIZE; + + max_match = get_min(MAX_MATCH, inSize-p); + limit = get_max(p-W_SIZE, 0); + + if (head[h1] >= limit) { + + s = head[h1]; + + if (inPtr[s] == inPtr[p]) { + + i = 0; + + while(++i < max_match) { + if (inPtr[s+i] != inPtr[p+i]) + break; + } + + if (i > len) { + len = i; + offset = p-s; + } + + } + + } + + if (len < MAX_MATCH) { + + chain_len = max_chain[level]; + s = head[h2+HASH1_SIZE]; + + while((chain_len-- != 0) && (s >= limit)) { + + if ((inPtr[s+len] == inPtr[p+len]) && (inPtr[s] == inPtr[p])) { + + i = 0; + + while(++i < max_match) { + if (inPtr[s+i] != inPtr[p+i]) + break; + } + + if (i > len+get_penalty((p-s)>>4, offset)) { + len = i; + offset = p-s; + } + + if (i == max_match) + break; + + } + + s=prev[s&W_MASK]; + + } + + } + + if ((len == MIN_MATCH) && (offset > TOO_FAR)) + len=0; + + if ((level >= 2) && (len >= MIN_MATCH) && (len < max_match)) { + + next_p = p+1; + max_lazy = get_min(len+4, max_match); + + chain_len = max_chain[level]; + s = head[update_hash2(h2, inPtr[next_p+(HASH2_LEN-1)])+HASH1_SIZE]; + + while((chain_len-- != 0) && (s >= limit)) { + + if ((inPtr[s+len] == inPtr[next_p+len]) && (inPtr[s] == inPtr[next_p])) { + + i = 0; + + while(++i < max_lazy) { + if (inPtr[s+i] != inPtr[next_p+i]) + break; + } + + if (i > len+get_penalty(next_p-s, offset)) { + len = 0; + break; + } + + if (i == max_lazy) + break; + + } + + s = prev[s&W_MASK]; + + } + + } + + + if (len >= MIN_MATCH) { // Match + + put_bits(1, 1); + + i = len-MIN_MATCH; + + if (i < A) { + put_bits(1, 1); // 1 + put_bits(A_BITS, i); + } else if (i < B) { + put_bits(2, 1<<1); // 01 + put_bits(B_BITS, i-A); + } else if (i < C) { + put_bits(3, 1<<2); // 001 + put_bits(C_BITS, i-B); + } else if (i < D) { + put_bits(4, 1<<3); // 0001 + put_bits(D_BITS, i-C); + } else if (i < E) { + put_bits(5, 1<<4); // 00001 + put_bits(E_BITS, i-D); + } else { + put_bits(5, 0); // 00000 + put_bits(F_BITS, i-E); + } + + --offset; + log = W_BITS-NUM_SLOTS; + + while(offset >= (2<<log)) + ++log; + + put_bits(SLOT_BITS, log-(W_BITS-NUM_SLOTS)); + + if (log>(W_BITS-NUM_SLOTS)) + put_bits(log, offset-(1<<log)); + else + put_bits(W_BITS-(NUM_SLOTS-1), offset); + + } else { // Literal + + len = 1; + put_bits(9, inPtr[p]<<1); // 0 xxxxxxxx + + } + + while(len-- != 0) { // Insert new strings + + head[h1] = p; + prev[p&W_MASK] = head[h2+HASH1_SIZE]; + head[h2+HASH1_SIZE] = p; + + ++p; + + h1 = update_hash1(h1, inPtr[p+(HASH1_LEN-1)]); + h2 = update_hash2(h2, inPtr[p+(HASH2_LEN-1)]); + + } + + } + + flush_bits(); + + #if LZP_USE_MALLOC == TRUE + free(head); + free(prev); + #endif + + return(outBytes); + +} + +void lzSetHashSizes(int window, int hash1, int hash2) { + + lzHashParam.WindowSize = window; + lzHashParam.Hash1Size = hash1; + lzHashParam.Hash2Size = hash2; + +} + +void lzResetHashSizes() { + + lzHashParam.WindowSize = LZP_WINDOW_SIZE; + lzHashParam.Hash1Size = LZP_HASH1_SIZE; + lzHashParam.Hash2Size = LZP_HASH2_SIZE; + +} + +#endif // LZP_NO_COMPRESS + +int lzDecompress(void* outBuff, void* inBuff, int inSize) { + + int p=0; + int len; + int log; + int s; + int windowSize; + + inPtr = (unsigned char*)inBuff; + outPtr = (unsigned char*)outBuff; + inBytes = 0; + outBytes = 0; + + init_bits(); + + // Get window size value + windowSize = get_bits(5); + + while(inBytes < inSize) { + + if (get_bits(1)) { + + if (get_bits(1)) + len = get_bits(A_BITS); + else if (get_bits(1)) + len = get_bits(B_BITS)+A; + else if (get_bits(1)) + len = get_bits(C_BITS)+B; + else if (get_bits(1)) + len = get_bits(D_BITS)+C; + else if (get_bits(1)) + len = get_bits(E_BITS)+D; + else + len = get_bits(F_BITS)+E; + + log = get_bits(SLOT_BITS)+(windowSize-NUM_SLOTS); + + s =~ (log>(windowSize-NUM_SLOTS) ? get_bits(log)+(1<<log) : get_bits(windowSize-(NUM_SLOTS-1)))+p; + + if (s < 0) + return(LZP_ERR_DECOMPRESS); + + outPtr[p++] = outPtr[s++]; + outPtr[p++] = outPtr[s++]; + outPtr[p++] = outPtr[s++]; + + while(len-- != 0) + outPtr[p++] = outPtr[s++]; + + } else { + + outPtr[p++] = get_bits(8); + + } + + } + + return(p); + +} + +int lzDecompressLen(void* outBuff, int outSize, void* inBuff, int inSize) { + + int p=0; + int len; + int log; + int s; + int windowSize; + + inPtr = (unsigned char*)inBuff; + outPtr = (unsigned char*)outBuff; + inBytes = 0; + outBytes = 0; + + init_bits(); + + // Get window size value + windowSize = get_bits(5); + + while(inBytes < inSize) { + + if (get_bits(1)) { + + if (get_bits(1)) + len = get_bits(A_BITS); + else if (get_bits(1)) + len = get_bits(B_BITS)+A; + else if (get_bits(1)) + len = get_bits(C_BITS)+B; + else if (get_bits(1)) + len = get_bits(D_BITS)+C; + else if (get_bits(1)) + len = get_bits(E_BITS)+D; + else + len = get_bits(F_BITS)+E; + + log = get_bits(SLOT_BITS)+(windowSize-NUM_SLOTS); + + s =~ (log>(windowSize-NUM_SLOTS) ? get_bits(log)+(1<<log) : get_bits(windowSize-(NUM_SLOTS-1)))+p; + + if (s < 0) + return(LZP_ERR_DECOMPRESS); + + outPtr[p++] = outPtr[s++]; + if (p >= outSize) + break; + + outPtr[p++] = outPtr[s++]; + if (p >= outSize) + break; + + outPtr[p++] = outPtr[s++]; + if (p >= outSize) + break; + + while(len-- != 0) { + + outPtr[p++] = outPtr[s++]; + if (p >= outSize) + break; + + } + + if (p >= outSize) + break; + + } else { + + outPtr[p++] = get_bits(8); + + } + + if (p >= outSize) + break; + + } + + return(p); + +} diff --git a/libpsn00b/lzp/crc.c b/libpsn00b/lzp/crc.c new file mode 100644 index 0000000..c5ab702 --- /dev/null +++ b/libpsn00b/lzp/crc.c @@ -0,0 +1,91 @@ +#include "lzp.h" + +void initTable16(unsigned short* table) { + + int i, j; + unsigned short crc, c; + + for (i=0; i<256; i++) { + + crc = 0; + c = (unsigned short) i; + + for (j=0; j<8; j++) { + + if ( (crc ^ c) & 0x0001 ) + crc = ( crc >> 1 ) ^ 0xA001; + else + crc = crc >> 1; + + c = c >> 1; + } + + table[i] = crc; + } + +} + +void initTable32(unsigned int* table) { + + int i,j; + unsigned int crcVal; + + for(i=0; i<256; i++) { + + crcVal = i; + + for(j=0; j<8; j++) { + + if (crcVal&0x00000001L) + crcVal = (crcVal>>1)^0xEDB88320L; + else + crcVal = crcVal>>1; + + } + + table[i] = crcVal; + + } + +} + +unsigned short lzCRC16(void* buff, int bytes, unsigned short crc) { + + int i; + unsigned short tmp, short_c; + unsigned short crcTable[256]; + + initTable16(crcTable); + + for(i=0; i<bytes; i++) { + + short_c = 0x00ff & (unsigned short)((unsigned char*)buff)[i]; + + tmp = crc ^ short_c; + crc = (crc >> 8) ^ crcTable[tmp&0xff]; + + } + + return(crc); + +} + +unsigned int lzCRC32(void* buff, int bytes, unsigned int crc) { + + int i; + unsigned char* byteBuff = (unsigned char*)buff; + unsigned int byte; + unsigned int crcTable[256]; + + initTable32(crcTable); + + for(i=0; i<bytes; i++) { + + byte = 0x000000ffL&(unsigned int)byteBuff[i]; + crc = (crc>>8)^crcTable[(crc^byte)&0xff]; + + } + + return(crc^0xFFFFFFFF); + +} diff --git a/libpsn00b/lzp/lzp.c b/libpsn00b/lzp/lzp.c new file mode 100644 index 0000000..1f4fea4 --- /dev/null +++ b/libpsn00b/lzp/lzp.c @@ -0,0 +1,88 @@ +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#include "lzp.h" + + +static char* lcase(char* text) { + + int i; + + for(i=0; text[i]!=0x00; i++) + text[i] = tolower(text[i]); + + return(text); + +} + + +int lzpSearchFile(const char* fileName, void* lzpack) { + + int i; + char searchName[16]; + char compareName[16]; + LZP_FILE* fileEntry; + + strcpy(searchName, fileName); + lcase(searchName); + + fileEntry = (LZP_FILE*)(lzpack+4); + for(i=0; i<((LZP_HEAD*)lzpack)->numFiles; i++) { + + strcpy(compareName, fileEntry[i].fileName); + lcase(compareName); + + if (strcmp(searchName, compareName) == 0) + return(i); + + } + + return(LZP_ERR_NOTFOUND); + +} + +LZP_FILE* lzpFileEntry(void* lzpack, int fileNum) { + + if (strncmp("LZP", ((LZP_HEAD*)lzpack)->id, 3) != 0) + return(NULL); + + if ((fileNum < 0) || (fileNum > (((LZP_HEAD*)lzpack)->numFiles-1))) + return(NULL); + + return(&((LZP_FILE*)(lzpack+4))[fileNum]); + +} + +int lzpFileSize(void* lzpack, int fileNum) { + + if (strncmp("LZP", ((LZP_HEAD*)lzpack)->id, 3) != 0) + return 0; + + if ((fileNum < 0) || (fileNum > (((LZP_HEAD*)lzpack)->numFiles-1))) + return 0; + + return ((LZP_FILE*)(lzpack+4))[fileNum].fileSize; +} + +int lzpUnpackFile(void* buff, void* lzpack, int fileNum) { + + LZP_FILE* fileEntry = &((LZP_FILE*)(lzpack+4))[fileNum]; + int unpackedSize; + + // Check ID header + if (strncmp("LZP", ((LZP_HEAD*)lzpack)->id, 3) != 0) + return(LZP_ERR_INVALID_PACK); + + // Do a CRC16 check of the compressed data's integrity + if (lzCRC32(lzpack+fileEntry->offset, fileEntry->packedSize, LZP_CRC32_REMAINDER) != fileEntry->crc) + return(LZP_ERR_CRC_MISMATCH); + + // Decompress data to the specified address + unpackedSize = lzDecompress(buff, lzpack+fileEntry->offset, fileEntry->packedSize); + if (unpackedSize < 0) + return(unpackedSize); + + return(unpackedSize); + +} diff --git a/libpsn00b/lzp/lzp.h b/libpsn00b/lzp/lzp.h new file mode 100644 index 0000000..ffd7933 --- /dev/null +++ b/libpsn00b/lzp/lzp.h @@ -0,0 +1,223 @@ +/*! \file lzp.h + * \brief Main library header + */ + +/*! \mainpage + * \version 0.20b + * \author John Wilbert 'Lameguy64' Villamor + * + * \section creditsSection Credits + * - LZ77 data compression/decompression routines based from Ilya Muravyov's + * crush.cpp released under public domain. Refined and ported to C by Lameguy64. + * - CRC calculation routines based from Lammert Bies' lib_crc routines. + * + */ + +#ifndef _LZPACK_H +#define _LZPACK_H + +#include <sys/types.h> +#ifdef _WIN32 +#include <windows.h> +#endif + +/*! \addtogroup crcBaseRemainders CRC Base Remainder Values + * @{ + */ +//! Initial remainder value for lzCRC16() +#define LZP_CRC16_REMAINDER 0x0000 +//! Initial remainder value for lzCRC32() +#define LZP_CRC32_REMAINDER 0xFFFFFFFF +/*! @} */ + + +/*! \addtogroup compLevels Compression Levels + * \brief Compression levels for the lzCompress() function. + * @{ + */ +//! Minimal (but fast) compression +#define LZP_COMPRESS_FAST 0 +//! Normal compression level +#define LZP_COMPRESS_NORMAL 1 +//! Maximum compression level +#define LZP_COMPRESS_MAX 2 +/*! @} */ + + +/*! \addtogroup libraryErrorCodes Library Error Codes + * @{ + */ +//! No error +#define LZP_ERR_NONE 0 +//! Decompression error +#define LZP_ERR_DECOMPRESS -1 +//! Not a valid LZP/QLP/PCK archive +#define LZP_ERR_INVALID_PACK -2 +//! File not found +#define LZP_ERR_NOTFOUND -3 +//! CRC check mismatch (data corruption) +#define LZP_ERR_CRC_MISMATCH -4 +/*! @} */ + + +//! Header structure of an LZP format archive file +typedef struct { + + //! File ID (must always be 'LZP') + char id[3]; + //! File count + u_char numFiles; + +} LZP_HEAD; + +//! File entry structure for an LZP format archive file +typedef struct { + + //! File name + char fileName[16]; + //! CRC32 checksum of file + u_int crc; + //! Original size of file in bytes + u_int fileSize; + //! Compressed size of file + u_int packedSize; + //! File data offset + u_int offset; + +} LZP_FILE; + + +// Function prototypes +#ifdef __cplusplus +extern "C" { +#endif + + +/*! \addtogroup compressFuncs Data Compression and Decompression Functions + * \brief Functions to compress and decompress data. + * @{ + */ + +/*! Compress a block of data. + * + * \details This function compresses a specified block of data in LZ77 encoding. + * Depending on the size of the input data and speed of the computer, compression + * may take a while to complete. + * + * \param[out] *outBuff Pointer to buffer to store compressed data. + * \param[in] *inBuff Pointer to data to compress. + * \param[in] inSize Size of data to compress in bytes. + * \param[in] level Compression level (see \ref compLevels). + * + * \returns The size of the compressed data in bytes. + */ +int lzCompress(void* outBuff, void* inBuff, int inSize, int level); + +/*! Decompress a compressed block of data. + * + * \details Decompressed a compressed block of data produced by lzCompress(). It cannot + * return the decompressed size of the data ahead of time so you must preserve the decompressed + * size of the data yourself. + * + * \note The decompression algorithm used in this function is completely independent + * of the compression settings set by lzSetHashSizes() before compressing the data with + * lzCompress(). + * + * \param[out] *outBuff Pointer to buffer to store decompressed data. + * \param[in] *inBuff Pointer to compressed data to decompress. + * \param[in] inSize Compressed data size in bytes. + * + * \returns Size of decompressed data in bytes or LZP_ERR_DECOMPRESS if a + * decompression error occurred. + */ +int lzDecompress(void* outBuff, void* inBuff, int inSize); + +int lzDecompressLen(void* outBuff, int outSize, void* inBuff, int inSize); + +/*! Sets the sizes of hash tables for data compression. + * + * \param[in] window Sliding window size. + * \param[in] hash1 Hash table 1 size. + * \param[in] hash2 Hash table 2 size. + */ +void lzSetHashSizes(int window, int hash1, int hash2); + +/*! Reset the sizes of hash tables to their defaults. + */ +void lzResetHashSizes(); + +/*! @} */ + + +/*! \addtogroup crcFuncs CRC Hashing Functions + * \brief Functions to calculate CRC hashes of data. + * @{ + */ + +/*! Calculates a CRC16 hash of the specified buffer. + * + * \param[in] *buff Pointer to buffer to calculate a hash of. + * \param[in] bytes Size of buffer in bytes. + * \param[in] crc CRC remainder (use LZP_CRC16_REMAINDER). + * + * \returns CRC16 hash of specified buffer. + */ +unsigned short lzCRC16(void* buff, int bytes, unsigned short crc); + +/*! Calculates a CRC32 hash of the specified buffer. + * + * \param[in] *buff Pointer to buffer to calculate a hash of. + * \param[in] bytes Size of buffer in bytes. + * \param[in] crc CRC remainder (use LZP_CRC16_REMAINDER). + * + * \returns CRC32 hash of specified buffer. + */ +unsigned int lzCRC32(void* buff, int bytes, unsigned int crc); + +/*! @} */ + + +/*! \addtogroup lzpFunctions LZP Archive Handling Routines + * \brief Functions to index and unpack files from LZP archives. + * @{ + */ + +/*! Searches for a file by name in an LZP archive and returns a file entry number. + * + * \param[in] *fileName String of file to search (must be less than 13 characters). + * \param[in] *lzpack Pointer to LZP archive file. + * + * \returns File index of found file or one of \ref libraryErrorCodes if an error occurred. + */ +int lzpSearchFile(const char* fileName, void* lzpack); + +int lzpFileSize(void* lzpack, int fileNum); + +/*! Get a pointer to a file entry inside of an LZP archive. + * + * \param[in] *lzpack Pointer to LZP archive file. + * \param[in] fileNum File number to get an entry of (you may use lzpSearchFile()). + * + * \returns A pointer to an LZP_FILE struct or NULL if an error occurred. + */ +LZP_FILE* lzpFileEntry(void* lzpack, int fileNum); + +/*! Unpacks a file from an LZP archive to the specified memory buffer. + * + * \param[in] *buff Pointer to buffer to store unpacked file. + * \param[in] *lzpack Pointer to LZP archive file. + * \param[in] fileNum File entry number of file to extract (you may use lzpSearchFile()). + * + * \returns Size of decompressed file in bytes or one of \ref libraryErrorCodes if an error occurred. + */ +int lzpUnpackFile(void* buff, void* lzpack, int fileNum); + +/*! @} */ + + +#ifdef __cplusplus +} +#endif + + +#endif // _LZPACK_H diff --git a/libpsn00b/lzp/lzqlp.h b/libpsn00b/lzp/lzqlp.h new file mode 100644 index 0000000..fae6438 --- /dev/null +++ b/libpsn00b/lzp/lzqlp.h @@ -0,0 +1,26 @@ +#ifndef _QLP_H +#define _QLP_H + +#define PACK_ERR_NONE 0 +#define PACK_ERR_INVALID -1 +#define PACK_ERR_NOTFOUND -2 +#define PACK_ERR_INCOMPLETE -3 +#define PACK_ERR_READ_FAULT -4 + +typedef struct { + char id[3]; + unsigned char numfiles; +} QLP_HEAD; + +typedef struct { + char name[16]; + unsigned int size; + unsigned int offs; +} QLP_FILE; + +int qlpFileCount(void* qlpfile); +QLP_FILE* qlpFileEntry(int index, void* qlpfile); +void* qlpFileAddr(int index, void* qlpfile); +int qlpFindFile(char* fileName, void* qlpfile); + +#endif // _QLP_H
\ No newline at end of file diff --git a/libpsn00b/lzp/makefile b/libpsn00b/lzp/makefile new file mode 100644 index 0000000..cf82872 --- /dev/null +++ b/libpsn00b/lzp/makefile @@ -0,0 +1,28 @@ +PREFIX = mipsel-unknown-elf- + +TARGET = liblzp.a + +CFILES = $(notdir $(wildcard ./*.c)) +OFILES = $(addprefix build/,$(CFILES:.c=.o)) + +INCLUDE = -I../include + +CFLAGS = -O2 -msoft-float -fno-builtin -nostdlib -Wa,--strip-local-absolute +AFLAGS = -msoft-float --strip-local-absolute + +CC = $(PREFIX)gcc +AR = $(PREFIX)ar +RANLIB = $(PREFIX)ranlib + +all: $(TARGET) + +$(TARGET): $(OFILES) + $(AR) cr $(TARGET) $(OFILES) + $(RANLIB) $(TARGET) + +build/%.o: %.c + @mkdir -p build + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +clean: + rm -Rf build $(OFILES) $(TARGET) diff --git a/libpsn00b/lzp/qlp.c b/libpsn00b/lzp/qlp.c new file mode 100644 index 0000000..3be8356 --- /dev/null +++ b/libpsn00b/lzp/qlp.c @@ -0,0 +1,64 @@ +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "lzqlp.h" + +static char* lcase(char* str) { + + while(*str != 0x00) { + *str = tolower(*str); + str++; + } + + return(str); + +} + +int qlpFileCount(void* qlpfile) { + + if (strncmp(((QLP_HEAD*)qlpfile)->id, "QLP", 3) != 0) + return(PACK_ERR_INVALID); + + return(((QLP_HEAD*)qlpfile)->numfiles); + +} + +QLP_FILE* qlpFileEntry(int index, void* qlpfile) { + + if (strncmp(((QLP_HEAD*)qlpfile)->id, "QLP", 3) != 0) + return(NULL); + + if (index > ((QLP_HEAD*)qlpfile)->numfiles) + return(NULL); + + return(&((QLP_FILE*)(qlpfile+4))[index]); + +} + +void* qlpFileAddr(int index, void* qlpfile) { + + return( qlpfile+((QLP_FILE*)(qlpfile+4))[index].offs ); + +} + +int qlpFindFile(char* fileName, void* qlpfile) { + + int i; + char nameBuff[2][16]; + + strcpy(nameBuff[0], fileName); + lcase(nameBuff[0]); + + for(i=0; i<((QLP_HEAD*)qlpfile)->numfiles; i++) { + + strcpy(nameBuff[1], ((QLP_FILE*)(qlpfile+4))[i].name); + lcase(nameBuff[1]); + + if (strcmp(nameBuff[0], nameBuff[1]) == 0) + return(i); + + } + + return(PACK_ERR_NOTFOUND); + +}
\ No newline at end of file diff --git a/libpsn00b/makefile b/libpsn00b/makefile new file mode 100644 index 0000000..bcfc9a5 --- /dev/null +++ b/libpsn00b/makefile @@ -0,0 +1,16 @@ +# Run using make (Linux) or gmake (BSD) +# Part of the PSn00bSDK Project +# 2019 Lameguy64 / Meido-Tek Productions + +TOPTARGETS = all clean + +LIBDIRS = libc lzp psxgpu psxgte psxapi psxetc psxspu + + +$(TOPTARGETS): $(LIBDIRS) +$(LIBDIRS): + @$(MAKE) -C $@ $(MAKECMDGOALS) + +clean: $(LIBDIRS) + +.PHONY: $(TOPTARGETS) $(LIBDIRS) diff --git a/libpsn00b/psxapi/fs/_96_init.s b/libpsn00b/psxapi/fs/_96_init.s new file mode 100644 index 0000000..ac35d6b --- /dev/null +++ b/libpsn00b/psxapi/fs/_96_init.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global _96_init +.type _96_init, @function +_96_init: + addiu $t2, $0 , 0xa0 + jr $t2 + addiu $t1, $0 , 0x71 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/fs/_96_remove.s b/libpsn00b/psxapi/fs/_96_remove.s new file mode 100644 index 0000000..a65c0ba --- /dev/null +++ b/libpsn00b/psxapi/fs/_96_remove.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global _96_remove +.type _96_remove, @function +_96_remove: + addiu $t2, $0 , 0xa0 + jr $t2 + addiu $t1, $0 , 0x72 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/fs/chdir.s b/libpsn00b/psxapi/fs/chdir.s new file mode 100644 index 0000000..83abf70 --- /dev/null +++ b/libpsn00b/psxapi/fs/chdir.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global chdir +.type chdir, @function +chdir: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x40 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/fs/erase.s b/libpsn00b/psxapi/fs/erase.s new file mode 100644 index 0000000..0ddd05f --- /dev/null +++ b/libpsn00b/psxapi/fs/erase.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global erase +.type erase, @function +erase: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x45 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/fs/firstfile.s b/libpsn00b/psxapi/fs/firstfile.s new file mode 100644 index 0000000..2d1c1cd --- /dev/null +++ b/libpsn00b/psxapi/fs/firstfile.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global firstfile +.type firstfile, @function +firstfile: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x42 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/fs/nextfile.s b/libpsn00b/psxapi/fs/nextfile.s new file mode 100644 index 0000000..51a285a --- /dev/null +++ b/libpsn00b/psxapi/fs/nextfile.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global nextfile +.type nextfile, @function +nextfile: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x43 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/fs/rename.s b/libpsn00b/psxapi/fs/rename.s new file mode 100644 index 0000000..5815dba --- /dev/null +++ b/libpsn00b/psxapi/fs/rename.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global rename +.type rename, @function +rename: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x44 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/makefile b/libpsn00b/psxapi/makefile new file mode 100644 index 0000000..30c1522 --- /dev/null +++ b/libpsn00b/psxapi/makefile @@ -0,0 +1,34 @@ +# Run using make (Linux) or gmake (BSD) +# Part of the PSn00bSDK Project +# 2019 Lameguy64 / Meido-Tek Productions + +PREFIX = mipsel-unknown-elf- + +TARGET = ../libpsxapi.a + +SOURCES = stdio fs sys + +AFILES = $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.s)) +OFILES = $(addprefix build/,$(AFILES:.s=.o)) + +INCLUDE = -I../include + +AFLAGS = -msoft-float -Wa,--strip-local-absolute + +CC = $(PREFIX)gcc +AS = $(PREFIX)as +AR = $(PREFIX)ar +RANLIB = $(PREFIX)ranlib + +all: $(TARGET) + +$(TARGET): $(OFILES) + $(AR) cr $(TARGET) $(OFILES) + $(RANLIB) $(TARGET) + +build/%.o: %.s + @mkdir -p $(dir $@) + $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@ + +clean: + rm -Rf build $(TARGET) diff --git a/libpsn00b/psxapi/stdio/close.s b/libpsn00b/psxapi/stdio/close.s new file mode 100644 index 0000000..6d52762 --- /dev/null +++ b/libpsn00b/psxapi/stdio/close.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global close +.type close, @function +close: + addiu $t2, $0, 0xa0 + jr $t2 + addiu $t1, $0, 0x04 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/stdio/getc.s b/libpsn00b/psxapi/stdio/getc.s new file mode 100644 index 0000000..2a93af6 --- /dev/null +++ b/libpsn00b/psxapi/stdio/getc.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global getc +.type getc, @function +getc: + addiu $t2, $0, 0xa0 + jr $t2 + addiu $t1, $0, 0x08 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/stdio/ioctl.s b/libpsn00b/psxapi/stdio/ioctl.s new file mode 100644 index 0000000..9ba17e6 --- /dev/null +++ b/libpsn00b/psxapi/stdio/ioctl.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global ioctl +.type ioctl, @function +ioctl: + addiu $t2, $0, 0xa0 + jr $t2 + addiu $t1, $0, 0x05 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/stdio/open.s b/libpsn00b/psxapi/stdio/open.s new file mode 100644 index 0000000..ce8c684 --- /dev/null +++ b/libpsn00b/psxapi/stdio/open.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global open +.type open, @function +open: + addiu $t2, $0, 0xa0 + jr $t2 + addiu $t1, $0, 0x00 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/stdio/printf.s b/libpsn00b/psxapi/stdio/printf.s new file mode 100644 index 0000000..64f1390 --- /dev/null +++ b/libpsn00b/psxapi/stdio/printf.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global printf +.type printf, @function +printf: + addiu $t2, $0, 0xa0 + jr $t2 + addiu $t1, $0, 0x3f +
\ No newline at end of file diff --git a/libpsn00b/psxapi/stdio/putc.s b/libpsn00b/psxapi/stdio/putc.s new file mode 100644 index 0000000..7c73241 --- /dev/null +++ b/libpsn00b/psxapi/stdio/putc.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global putchar +.type putc, @function +putchar: + addiu $t2, $0, 0xa0 + jr $t2 + addiu $t1, $0, 0x09 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/stdio/read.s b/libpsn00b/psxapi/stdio/read.s new file mode 100644 index 0000000..4209232 --- /dev/null +++ b/libpsn00b/psxapi/stdio/read.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global read +.type read, @function +read: + addiu $t2, $0, 0xa0 + jr $t2 + addiu $t1, $0, 0x02 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/stdio/seek.s b/libpsn00b/psxapi/stdio/seek.s new file mode 100644 index 0000000..944afd9 --- /dev/null +++ b/libpsn00b/psxapi/stdio/seek.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global seek +.type seek, @function +seek: + addiu $t2, $0, 0xA0 + jr $t2 + addiu $t1, $0, 0x01 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/stdio/write.s b/libpsn00b/psxapi/stdio/write.s new file mode 100644 index 0000000..c451952 --- /dev/null +++ b/libpsn00b/psxapi/stdio/write.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global write +.type write, @function +write: + addiu $t2, $0, 0xa0 + jr $t2 + addiu $t1, $0, 0x03 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/adddev.s b/libpsn00b/psxapi/sys/adddev.s new file mode 100644 index 0000000..7fa717d --- /dev/null +++ b/libpsn00b/psxapi/sys/adddev.s @@ -0,0 +1,10 @@ +.set noreorder + +.section .text + +.global AddDev +.type AddDev, @function +AddDev: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x47
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/b_initheap.s b/libpsn00b/psxapi/sys/b_initheap.s new file mode 100644 index 0000000..7411dd6 --- /dev/null +++ b/libpsn00b/psxapi/sys/b_initheap.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global b_InitHeap +.type b_InitHeap, @function +b_InitHeap: + addiu $t2, $0, 0xa0 + jr $t2 + addiu $t1, $0, 0x39 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/changeclearpad.s b/libpsn00b/psxapi/sys/changeclearpad.s new file mode 100644 index 0000000..509b03f --- /dev/null +++ b/libpsn00b/psxapi/sys/changeclearpad.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global ChangeClearPAD +.type ChangeClearPAD, @function +ChangeClearPAD: + addiu $t2, $0 , 0xb0 + jr $t2 + addiu $t1, $0 , 0x5b +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/changeclearrcnt.s b/libpsn00b/psxapi/sys/changeclearrcnt.s new file mode 100644 index 0000000..a65676d --- /dev/null +++ b/libpsn00b/psxapi/sys/changeclearrcnt.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global ChangeClearRCnt +.type ChangeClearRCnt, @function +ChangeClearRCnt: + addiu $t2, $0 , 0xc0 + jr $t2 + addiu $t1, $0 , 0x0a +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/deldev.s b/libpsn00b/psxapi/sys/deldev.s new file mode 100644 index 0000000..185cd32 --- /dev/null +++ b/libpsn00b/psxapi/sys/deldev.s @@ -0,0 +1,10 @@ +.set noreorder + +.section .text + +.global DelDev +.type DelDev, @function +DelDev: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x48
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/disableevent.s b/libpsn00b/psxapi/sys/disableevent.s new file mode 100644 index 0000000..fb60549 --- /dev/null +++ b/libpsn00b/psxapi/sys/disableevent.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global DisableEvent +.type DisableEvent, @function +DisableEvent: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x0d +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/enableevent.s b/libpsn00b/psxapi/sys/enableevent.s new file mode 100644 index 0000000..a95e1fc --- /dev/null +++ b/libpsn00b/psxapi/sys/enableevent.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global EnableEvent +.type EnableEvent, @function +EnableEvent: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x0c +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/entercriticalsection.s b/libpsn00b/psxapi/sys/entercriticalsection.s new file mode 100644 index 0000000..ce9a368 --- /dev/null +++ b/libpsn00b/psxapi/sys/entercriticalsection.s @@ -0,0 +1,11 @@ +.set noreorder +.section .text + +.global EnterCriticalSection +.type EnterCriticalSection, @function +EnterCriticalSection: + addiu $a0, $0, 1 + syscall 0 + jr $ra + nop +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/exitcriticalsection.s b/libpsn00b/psxapi/sys/exitcriticalsection.s new file mode 100644 index 0000000..e2ee060 --- /dev/null +++ b/libpsn00b/psxapi/sys/exitcriticalsection.s @@ -0,0 +1,11 @@ +.set noreorder +.section .text + +.global ExitCriticalSection +.type ExitCriticalSection, @function +ExitCriticalSection: + addiu $a0, $0, 2 + syscall 0 + jr $ra + nop +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/initcard.s b/libpsn00b/psxapi/sys/initcard.s new file mode 100644 index 0000000..e589592 --- /dev/null +++ b/libpsn00b/psxapi/sys/initcard.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global InitCard +.type InitCard, @function +InitCard: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x4a +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/initpad.s b/libpsn00b/psxapi/sys/initpad.s new file mode 100644 index 0000000..b0f1b6f --- /dev/null +++ b/libpsn00b/psxapi/sys/initpad.s @@ -0,0 +1,11 @@ +.set noreorder +.section .text + +.include "hwregs_a.h" + +.global InitPad +.type InitPad, @function +InitPad: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x12 diff --git a/libpsn00b/psxapi/sys/listdev.s b/libpsn00b/psxapi/sys/listdev.s new file mode 100644 index 0000000..fa3afec --- /dev/null +++ b/libpsn00b/psxapi/sys/listdev.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global ListDev +.type ListDev, @function +ListDev: + addiu $t2, $0 , 0xb0 + jr $t2 + addiu $t1, $0 , 0x49 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/openevent.s b/libpsn00b/psxapi/sys/openevent.s new file mode 100644 index 0000000..9be0a3e --- /dev/null +++ b/libpsn00b/psxapi/sys/openevent.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global OpenEvent +.type OpenEvent, @function +OpenEvent: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x08 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/setcustomexitfromexception.s b/libpsn00b/psxapi/sys/setcustomexitfromexception.s new file mode 100644 index 0000000..bcba057 --- /dev/null +++ b/libpsn00b/psxapi/sys/setcustomexitfromexception.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global SetCustomExitFromException +.type SetCustomExitFromException, @function +SetCustomExitFromException: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x19 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/setdefaultexitfromexception.s b/libpsn00b/psxapi/sys/setdefaultexitfromexception.s new file mode 100644 index 0000000..baaf591 --- /dev/null +++ b/libpsn00b/psxapi/sys/setdefaultexitfromexception.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global SetDefaultExitFromException +.type SetDefaultExitFromException, @function +SetDefaultExitFromException: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x18 + diff --git a/libpsn00b/psxapi/sys/startpad.s b/libpsn00b/psxapi/sys/startpad.s new file mode 100644 index 0000000..b15b0c0 --- /dev/null +++ b/libpsn00b/psxapi/sys/startpad.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global StartPad +.type StartPad, @function +StartPad: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x13 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/stoppad.s b/libpsn00b/psxapi/sys/stoppad.s new file mode 100644 index 0000000..562ac0f --- /dev/null +++ b/libpsn00b/psxapi/sys/stoppad.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global StopPad +.type StopPad, @function +StartPad: + addiu $t2, $0, 0xb0 + jr $t2 + addiu $t1, $0, 0x14 +
\ No newline at end of file diff --git a/libpsn00b/psxapi/sys/sysenqintrp.s b/libpsn00b/psxapi/sys/sysenqintrp.s new file mode 100644 index 0000000..b1efe65 --- /dev/null +++ b/libpsn00b/psxapi/sys/sysenqintrp.s @@ -0,0 +1,10 @@ +.set noreorder +.section .text + +.global SysEnqIntRP +.type SysEnqIntRP, @function +SysEnqIntRP: + addiu $t2, $0, 0xc0 + jr $t2 + addiu $t1, $0, 0x02 +
\ No newline at end of file diff --git a/libpsn00b/psxetc/dbugfont.c b/libpsn00b/psxetc/dbugfont.c new file mode 100644 index 0000000..ff21d84 --- /dev/null +++ b/libpsn00b/psxetc/dbugfont.c @@ -0,0 +1,144 @@ +unsigned int dbugfont_size=2112; +unsigned char dbugfont[] = { +0x10,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x00,0xe0, +0x01,0x10,0x00,0x01,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x08,0x00,0x00,0x80,0x02,0x00,0x00, +0x20,0x00,0x20,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x01,0x01, +0x00,0x10,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x11, +0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01, +0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x10,0x00,0x10,0x00,0x10,0x00, +0x01,0x00,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, +0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x00, +0x00,0x00,0x00,0x00,0x00,0x10,0x11,0x11,0x00,0x01,0x01,0x00,0x00,0x11,0x01, +0x01,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x00, +0x10,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x11, +0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x10,0x11, +0x00,0x00,0x10,0x10,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x10, +0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x11,0x00,0x00,0x11,0x11,0x01,0x00, +0x00,0x00,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00, +0x00,0x10,0x10,0x10,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x11, +0x11,0x00,0x00,0x01,0x01,0x00,0x00,0x01,0x01,0x00,0x01,0x10,0x01,0x00,0x00, +0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x01,0x01,0x01,0x00, +0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x01,0x00,0x00,0x10,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x10,0x10,0x11,0x00,0x01, +0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00, +0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x11,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x10,0x11,0x00,0x00,0x01, +0x00,0x01,0x00,0x10,0x01,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00, +0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x11, +0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x01,0x00,0x00, +0x11,0x01,0x00,0x00,0x10,0x01,0x00,0x10,0x11,0x11,0x00,0x00,0x10,0x01,0x00, +0x10,0x11,0x11,0x00,0x00,0x11,0x01,0x00,0x00,0x11,0x01,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x10,0x00, +0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x11,0x11,0x00,0x00,0x11,0x00,0x00,0x10, +0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x01,0x00,0x10,0x00,0x00,0x00, +0x00,0x01,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, +0x00,0x00,0x11,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x10, +0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x01,0x00, +0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10, +0x00,0x10,0x00,0x10,0x00,0x00,0x11,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x01, +0x00,0x00,0x10,0x11,0x11,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x10, +0x10,0x01,0x01,0x00,0x10,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00, +0x10,0x11,0x11,0x00,0x10,0x11,0x01,0x00,0x10,0x11,0x01,0x00,0x00,0x00,0x01, +0x00,0x00,0x11,0x01,0x00,0x00,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, +0x00,0x01,0x00,0x10,0x10,0x01,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00, +0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10, +0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x11,0x11,0x00,0x00, +0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x10,0x11,0x00,0x00,0x10,0x00,0x00, +0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10, +0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00, +0x01,0x00,0x00,0x11,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x10,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00, +0x10,0x11,0x11,0x00,0x10,0x11,0x11,0x00,0x00,0x11,0x01,0x00,0x00,0x00,0x01, +0x00,0x10,0x11,0x01,0x00,0x00,0x11,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x11, +0x01,0x00,0x00,0x11,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x11,0x00,0x00,0x00, +0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x00, +0x00,0x11,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, +0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x11,0x01, +0x00,0x00,0x11,0x01,0x00,0x10,0x11,0x01,0x00,0x10,0x11,0x11,0x00,0x10,0x11, +0x11,0x00,0x00,0x11,0x11,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x11,0x00,0x00, +0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00, +0x10,0x00,0x10,0x00,0x00,0x11,0x01,0x00,0x10,0x11,0x01,0x00,0x00,0x01,0x01, +0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00, +0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00, +0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00, +0x10,0x01,0x11,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, +0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00, +0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10, +0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x01,0x00, +0x10,0x00,0x00,0x00,0x10,0x10,0x10,0x00,0x10,0x01,0x10,0x00,0x10,0x00,0x10, +0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x01,0x00,0x10,0x00, +0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x10, +0x10,0x11,0x00,0x10,0x11,0x11,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00, +0x10,0x11,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x10,0x10, +0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x11,0x00,0x10,0x00, +0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x10, +0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00,0x00, +0x10,0x00,0x10,0x00,0x10,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10, +0x00,0x10,0x00,0x11,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x01,0x00,0x10,0x00, +0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, +0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00, +0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00, +0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00, +0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x01,0x00,0x00,0x11,0x01,0x00,0x10, +0x11,0x01,0x00,0x10,0x11,0x11,0x00,0x10,0x00,0x00,0x00,0x00,0x11,0x01,0x00, +0x10,0x00,0x10,0x00,0x10,0x11,0x11,0x00,0x00,0x11,0x01,0x00,0x10,0x00,0x10, +0x00,0x10,0x11,0x11,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x11, +0x01,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x01,0x00,0x10, +0x11,0x01,0x00,0x00,0x11,0x01,0x00,0x10,0x11,0x11,0x00,0x10,0x00,0x10,0x00, +0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, +0x00,0x10,0x11,0x11,0x00,0x00,0x11,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x11, +0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x10, +0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00,0x00, +0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, +0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x00,0x10,0x00, +0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00, +0x11,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00, +0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, +0x00,0x00,0x01,0x01,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x01, +0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x01,0x11,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x01,0x00, +0x00,0x11,0x01,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, +0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x10, +0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x00, +0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x10, +0x00,0x10,0x00,0x10,0x00,0x10,0x10,0x10,0x00,0x00,0x01,0x01,0x00,0x00,0x10, +0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00, +0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x10,0x00,0x01,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00, +0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x01,0x00,0x10,0x01,0x11,0x00,0x10,0x00, +0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, +0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x11,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x11,0x01, +0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x10,0x00,0x00,0x10,0x00, +0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x11,0x11,0x00,0x00, +0x11,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x11,0x01,0x00,0x00,0x00,0x00,0x00, +0x11,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; diff --git a/libpsn00b/psxetc/dbugfont.tim b/libpsn00b/psxetc/dbugfont.tim Binary files differnew file mode 100644 index 0000000..4e6cce2 --- /dev/null +++ b/libpsn00b/psxetc/dbugfont.tim diff --git a/libpsn00b/psxetc/fntsort.c b/libpsn00b/psxetc/fntsort.c new file mode 100644 index 0000000..29e7de5 --- /dev/null +++ b/libpsn00b/psxetc/fntsort.c @@ -0,0 +1,47 @@ +#include <stdio.h> +#include <ctype.h> +#include <psxgpu.h> + +extern unsigned short _font_tpage; +extern unsigned short _font_clut; + +char *FntSort(unsigned int *ot, char *pri, int x, int y, const char *text) { + + DR_TPAGE *tpage; + SPRT_8 *sprt = (SPRT_8*)pri; + int i; + + while( *text != 0 ) { + + i = toupper( *text )-32; + + if( i > 0 ) { + + i--; + setSprt8( sprt ); + setRGB0( sprt, 128, 128, 128 ); + setXY0( sprt, x, y ); + setUV0( sprt, (i%16)<<3, (i>>4)<<3 ); + sprt->clut = _font_clut; + addPrim( ot, sprt ); + sprt++; + + } + + x += 8; + text++; + + } + + pri = (char*)sprt; + + tpage = (DR_TPAGE*)pri; + setlen( tpage, 1 ); + tpage->code[0] = _font_tpage; + setcode( tpage, 0xe1 ); + addPrim( ot, pri ); + pri += sizeof(DR_TPAGE); + + return pri; + +}
\ No newline at end of file diff --git a/libpsn00b/psxetc/font.c b/libpsn00b/psxetc/font.c new file mode 100644 index 0000000..3b0370b --- /dev/null +++ b/libpsn00b/psxetc/font.c @@ -0,0 +1,37 @@ +#include <stdio.h> +#include <ctype.h> +#include <psxgpu.h> + +extern unsigned char dbugfont[]; + +unsigned short _font_tpage; +unsigned short _font_clut; + +void FntLoad(int x, int y) { + + RECT pos; + TIM_IMAGE tim; + + GetTimInfo( (unsigned int*)dbugfont, &tim ); + + // Load font image + pos = *tim.prect; + pos.x = x; + pos.y = y; + + _font_tpage = getTPage( 0, 0, pos.x, 0 ) | 0x200; + + LoadImage( &pos, tim.paddr ); + DrawSync(); + + // Load font clut + pos = *tim.crect; + pos.x = x; + pos.y = y+tim.prect->h; + + _font_clut = getClut( pos.x, pos.y ); + + LoadImage( &pos, tim.caddr ); + DrawSync(); + +}
\ No newline at end of file diff --git a/libpsn00b/psxetc/makefile b/libpsn00b/psxetc/makefile new file mode 100644 index 0000000..676fc6e --- /dev/null +++ b/libpsn00b/psxetc/makefile @@ -0,0 +1,38 @@ +# Run using make (Linux) or gmake (BSD) +# Part of the PSn00bSDK Project +# 2019 Lameguy64 / Meido-Tek Productions + +PREFIX = mipsel-unknown-elf- + +TARGET = ../libpsxetc.a + +CFILES = $(notdir $(wildcard ./*.c)) +AFILES = $(notdir $(wildcard ./*.s)) +OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) + +INCLUDE = -I../include + +CFLAGS = -O2 -msoft-float -fno-builtin -nostdlib -Wa,--strip-local-absolute +AFLAGS = -msoft-float --strip-local-absolute + +CC = $(PREFIX)gcc +AS = $(PREFIX)as +AR = $(PREFIX)ar +RANLIB = $(PREFIX)ranlib + +all: $(TARGET) + +$(TARGET): $(OFILES) + $(AR) cr $(TARGET) $(OFILES) + $(RANLIB) $(TARGET) + +build/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +build/%.o: %.s + @mkdir -p $(dir $@) + $(AS) $(AFLAGS) $(INCLUDE) $< -o $@ + +clean: + rm -Rf build $(TARGET) diff --git a/libpsn00b/psxetc/readme.txt b/libpsn00b/psxetc/readme.txt new file mode 100644 index 0000000..ba4db50 --- /dev/null +++ b/libpsn00b/psxetc/readme.txt @@ -0,0 +1,22 @@ +PSX Misc library, part of PSn00bSDK +2019 Lameguy64 / Meido-Tek Productions + +Licensed under Mozilla Public License + +Open source implementation of the ETC library. Doesn't really provide much +aside from some debug font stuff at the moment. + + +Library developer(s): + + Lameguy64 + + +Library header(s): + + psxetc.h + + +Changelog: + + None thus far... diff --git a/libpsn00b/psxgpu/addprim.s b/libpsn00b/psxgpu/addprim.s new file mode 100644 index 0000000..1b66274 --- /dev/null +++ b/libpsn00b/psxgpu/addprim.s @@ -0,0 +1,26 @@ +.set noreorder +.set noat + +.section .text + + +.global AddPrim +.type AddPrim, @function +AddPrim: + + lw $v0, 0($a0) # Load OT entry + lw $v1, 0($a1) # Set packet length value (in words) + lui $at, 0x00ff + or $at, 0xffff + and $v0, $at # Mask off the upper 8 bits of OT entry + or $v1, $v0 # OR values together + sw $v1, 0($a1) # Store new address to primitive tag + lw $v0, 0($a0) # Load OT entry + and $a1, $at # Mask off the upper 8 bits of primitive tag + lui $at, 0xff00 + and $v0, $at # Mask off the first 24 bits of OT entry + or $v0, $a1 # OR values together + + jr $ra + sw $v0, 0($a0) # Store result to OT + diff --git a/libpsn00b/psxgpu/clearotagr.s b/libpsn00b/psxgpu/clearotagr.s new file mode 100644 index 0000000..3e888f1 --- /dev/null +++ b/libpsn00b/psxgpu/clearotagr.s @@ -0,0 +1,21 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + + +.global ClearOTagR +.type ClearOTagR, @function +ClearOTagR: + lui $a2, 0x1f80 + addi $v0, $a1, -1 + sll $v0, 2 + addu $a0, $v0 + sw $a0, D6_MADR($a2) + andi $a1, 0xffff + sw $a1, D6_BCR($a2) + lui $v0, 0x1100 + addiu $v0, 2 + jr $ra + sw $v0, D6_CHCR($a2) diff --git a/libpsn00b/psxgpu/drawotag.s b/libpsn00b/psxgpu/drawotag.s new file mode 100644 index 0000000..8a5ff0c --- /dev/null +++ b/libpsn00b/psxgpu/drawotag.s @@ -0,0 +1,38 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + + +.global DrawOTag +.type DrawOTag, @function +DrawOTag: + addiu $sp, -4 + sw $ra, 0($sp) + + lui $a3, 0x1f80 # I/O segment base + +.gpu_wait: # Wait for GPU to be ready for commands & DMA + jal ReadGPUstat + nop + srl $v0, 26 + andi $v0, 1 + beqz $v0, .gpu_wait + nop + + lui $v0, 0x0400 # Set DMA direction to CPUtoGPU + ori $v0, 0x2 + sw $v0, GP1($a3) + + sw $a0, D2_MADR($a3) # Set DMA base address to specified OT + sw $0, D2_BCR($a3) + + lui $v0, 0x0100 # Begin OT transfer! + ori $v0, 0x0401 + sw $v0, D2_CHCR($a3) + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop diff --git a/libpsn00b/psxgpu/drawsync.s b/libpsn00b/psxgpu/drawsync.s new file mode 100644 index 0000000..149519d --- /dev/null +++ b/libpsn00b/psxgpu/drawsync.s @@ -0,0 +1,26 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + + +.global DrawSync +.type DrawSync, @function +DrawSync: + addiu $sp, -4 + sw $ra, 0($sp) + +.gpu_wait: # Wait for GPU to be ready for commands and DMA + jal ReadGPUstat + nop + srl $v0, 0x1a + andi $v0, 0x5 + li $v1, 5 + bne $v0, $v1, .gpu_wait + nop + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop diff --git a/libpsn00b/psxgpu/gettimimage.c b/libpsn00b/psxgpu/gettimimage.c new file mode 100644 index 0000000..49ce8e9 --- /dev/null +++ b/libpsn00b/psxgpu/gettimimage.c @@ -0,0 +1,39 @@ +#include <psxgpu.h> + +int GetTimInfo(unsigned int *tim, TIM_IMAGE *timimg) { + + unsigned int *rtim; + + // Check ID + if( ( tim[0]&0xff ) != 0x10 ) { + return 1; + } + + // Check version + if( ( (tim[0]>>8)&0xff ) != 0x0 ) { + return 2; + } + + timimg->mode = tim[1]; + rtim = tim+2; + + // Clut present? + if( timimg->mode & 0x8 ) { + + timimg->crect = (RECT*)(rtim+1); + timimg->caddr = (unsigned int*)(rtim+3); + + rtim += rtim[0]>>2; + + } else { + + timimg->caddr = 0; + + } + + timimg->prect = (RECT*)(rtim+1); + timimg->paddr = (unsigned int*)(rtim+3); + + return 0; + +} diff --git a/libpsn00b/psxgpu/getvideomode.s b/libpsn00b/psxgpu/getvideomode.s new file mode 100644 index 0000000..6f1613c --- /dev/null +++ b/libpsn00b/psxgpu/getvideomode.s @@ -0,0 +1,14 @@ +.set noreorder + + +.section .text + +.global GetVideoMode +.type GetVideoMode, @function +GetVideoMode: + + la $v0, _gpu_standard + lw $v0, 0($v0) + + jr $ra + nop diff --git a/libpsn00b/psxgpu/loadimage.s b/libpsn00b/psxgpu/loadimage.s new file mode 100644 index 0000000..2376b31 --- /dev/null +++ b/libpsn00b/psxgpu/loadimage.s @@ -0,0 +1,70 @@ +.set noreorder + +.include "hwregs_a.h" + +.set RECT_x, 0 +.set RECT_y, 2 +.set RECT_w, 4 +.set RECT_h, 6 + +.section .text + + +.global LoadImage +.type LoadImage, @function +LoadImage: + addiu $sp, -8 + sw $ra, 0($sp) + sw $s0, 4($sp) + + lui $s0, 0x1f80 # Set I/O segment base address + +.gpu_wait: # Wait for GPU to be ready for commands and DMA + jal ReadGPUstat + nop + srl $v0, 0x1a + andi $v0, 0x5 + li $v1, 5 + #srl $v0, 28 + #andi $v0, 1 + bne $v0, $v1, .gpu_wait + nop + + lui $v0, 0x400 # Set DMA direction to off + sw $v0, GP1($s0) + + lui $v0, 0x0100 # Clear GPU cache + sw $v0, GP0($s0) + + lui $v1, 0xa000 # Load image to VRAM + sw $v1, GP0($s0) + lw $v0, RECT_x($a0) # Set XY and dimensions of image + lw $v1, RECT_w($a0) + sw $v0, GP0($s0) + sw $v1, GP0($s0) + + lui $v0, 0x400 # Set DMA direction to CPUtoVRAM + ori $v0, 0x2 + sw $v0, GP1($s0) + + lhu $v0, RECT_w($a0) # Get rectangle size + lhu $v1, RECT_h($a0) + nop + mult $v0, $v1 # Calculate BCR value + mflo $v1 + srl $v1, 0x4 + sll $v1, 0x10 + ori $v1, 0x8 + + sw $a1, D2_MADR($s0) # Set DMA base address and transfer length + sw $v1, D2_BCR($s0) + + lui $v0, 0x100 # Start DMA transfer + ori $v0, 0x201 + sw $v0, D2_CHCR($s0) + + lw $ra, 0($sp) + lw $s0, 4($sp) + jr $ra + addiu $sp, 8 + diff --git a/libpsn00b/psxgpu/makefile b/libpsn00b/psxgpu/makefile new file mode 100644 index 0000000..5eb6265 --- /dev/null +++ b/libpsn00b/psxgpu/makefile @@ -0,0 +1,38 @@ +# Run using make (Linux) or gmake (BSD) +# Part of the PSn00bSDK Project +# 2019 Lameguy64 / Meido-Tek Productions + +PREFIX = mipsel-unknown-elf- + +TARGET = ../libpsxgpu.a + +CFILES = $(notdir $(wildcard ./*.c)) +AFILES = $(notdir $(wildcard ./*.s)) +OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) + +INCLUDE = -I../include + +CFLAGS = -O2 -msoft-float -fno-builtin -Wa,--strip-local-absolute +AFLAGS = -msoft-float -Wa,--strip-local-absolute + +CC = $(PREFIX)gcc +AS = $(PREFIX)as +AR = $(PREFIX)ar +RANLIB = $(PREFIX)ranlib + +all: $(TARGET) + +$(TARGET): $(OFILES) + $(AR) cr $(TARGET) $(OFILES) + $(RANLIB) $(TARGET) + +build/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +build/%.o: %.s + @mkdir -p $(dir $@) + $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@ + +clean: + rm -Rf build $(TARGET) diff --git a/libpsn00b/psxgpu/putdispenv.s b/libpsn00b/psxgpu/putdispenv.s new file mode 100644 index 0000000..0993e5c --- /dev/null +++ b/libpsn00b/psxgpu/putdispenv.s @@ -0,0 +1,174 @@ +.set noreorder + +.include "hwregs_a.h" + +.set DISP_dx, 0 +.set DISP_dy, 2 +.set DISP_dw, 4 +.set DISP_dh, 6 +.set DISP_sx, 8 +.set DISP_sy, 10 +.set DISP_sw, 12 +.set DISP_sh, 14 +.set DISP_inter, 16 +.set DISP_isrgb24, 17 +.set DISP_reverse, 18 + +.section .text + + +.global PutDispEnv +.type PutDispEnv, @function +PutDispEnv: + + lui $a3, IOBASE + + # Horizontal resolution stuff + + lh $a2, DISP_dw($a0) # Get X resolution + + lh $v0, DISP_sx($a0) + lh $v1, DISP_sw($a0) # Get X screen width + + move $a1, $0 # To use as mode value + + bgt $a2, 560, .mode_640 + nop + bgt $a2, 400, .mode_512 + nop + bgt $a2, 352, .mode_384 + nop + bgt $a2, 280, .mode_320 + nop + + .set noat + +.mode_256: + li $at, 10 + mult $at, $v1 + li $a2, 0x24e + sll $v0, 2 + add $a2, $v0 + b .mode_end + li $v1, 0xa00 +.mode_320: + li $at, 8 + mult $at, $v1 + li $a2, 0x258 + ori $a1, 0x01 + sll $v0, 2 + add $a2, $v0 + b .mode_end + li $v1, 0xa00 +.mode_384: + li $at, 7 + mult $at, $v1 + li $a2, 0x21b + ori $a1, 0x64 + sll $v0, 2 + add $a2, $v0 + b .mode_end + li $v1, 0xa80 +.mode_512: + li $at, 5 + mult $at, $v1 + li $a2, 0x267 + ori $a1, 0x02 + sll $v0, 2 + add $a2, $v0 + b .mode_end + li $v1, 0xa00 +.mode_640: + li $at, 4 + mult $at, $v1 + li $a2, 0x26c + ori $a1, 0x03 + sll $v0, 2 + add $a2, $v0 + li $v1, 0xa00 +.mode_end: + + .set at + + mflo $v0 + bnez $v0, .no_default # Check if screen with is non zero + nop + move $v0, $v1 # Use default if screen width is 0 +.no_default: + + addu $v0, $a2 # Apply horizontal display coordinates + sll $v0, 12 + andi $a2, 0xfff + or $a2, $v0 + lui $v0, 0x0600 + or $v0, $a2 + sw $v0, GP1($a3) + + # Vertical resolution + + lh $v0, DISP_dh($a0) + li $a2, 0x10 + ble $v0, 256, .mode_low + nop + +.mode_high: + ori $a1, 0x04 +.mode_low: + lh $v0, DISP_sy($a0) + lh $v1, DISP_sh($a0) + add $a2, $v0 + bnez $v1, .no_default_vert + nop + li $v1, 0xf0 +.no_default_vert: + add $v1, $a2 + and $a2, 0x3ff + sll $v1, 10 + or $v1, $a2 + lui $v0, 0x0700 + or $v1, $v0 + sw $v1, GP1($a3) + + # Video mode + + la $v0, _gpu_standard + lbu $v0, 0($v0) + nop + beqz $v0, .config_ntsc + nop +.config_pal: + ori $a1, 0x08 +.config_ntsc: + + lbu $v0, DISP_inter($a0) + lbu $v1, DISP_isrgb24($a0) + beqz $v0, .no_inter + nop + or $a1, 0x20 +.no_inter: + beqz $v1, .no_rgb24 + nop + or $a1, 0x10 +.no_rgb24: + lbu $v0, DISP_inter($a0) + nop + beqz $v0, .no_reverse + nop + or $a1, 0x80 +.no_reverse: + + lui $v0, 0x800 # Apply mode + or $a1, $v0 + sw $a1, GP1($a3) + + lhu $v0, DISP_dx($a0) # Set VRAM XY offset + lhu $v1, DISP_dy($a0) + andi $v0, 0x3ff + andi $v1, 0x1ff + sll $v1, 10 + or $v0, $v1 + lui $v1, 0x500 + or $v0, $v1 + + jr $ra + sw $v0, GP1($a3) diff --git a/libpsn00b/psxgpu/putdispenvraw.s b/libpsn00b/psxgpu/putdispenvraw.s new file mode 100644 index 0000000..157150d --- /dev/null +++ b/libpsn00b/psxgpu/putdispenvraw.s @@ -0,0 +1,71 @@ +.set noreorder +.set noat + +.include "hwregs_a.h" + +.set DISP_mode, 0 +.set DISP_vxpos, 4 +.set DISP_vypos, 6 +.set DISP_fbx, 8 +.set DISP_fby, 10 + +.section .text + + +.global PutDispEnvRaw +.type PutDispEnvRaw, @function +PutDispEnvRaw: + addiu $sp, -8 + sw $ra, 0($sp) + sw $s0, 4($sp) + + lui $s0, 0x1f80 + + lh $at, DISP_vxpos($a0) # Set horizontal display range + li $v0, 608 + add $v0, $at + li $v1, 3168 + add $v1, $at + sll $v1, 12 + or $v0, $v1 + lui $v1, 0x600 + or $v1, $v0 + sw $v1, GP1($s0) + + lh $at, DISP_vypos($a0) # Set vertical display range (for NTSC) + li $v1, 120 # (values differet for PAL modes) + sub $v1, $at + li $v0, 136 + sub $v0, $v1 + andi $v0, 0x1ff + li $v1, 120 + add $v1, $at + li $at, 136 + add $at, $v1 + andi $at, 0x1ff + sll $at, 10 + or $v0, $at + lui $at, 0x700 + or $v0, $at + sw $v0, GP1($s0) + + lw $v0, DISP_mode($a0) # Set video mode + lui $at, 0x800 + or $v0, $at + sw $v0, GP1($s0) + + lhu $v0, DISP_fbx($a0) # Set VRAM XY offset + lhu $v1, DISP_fby($a0) + andi $v0, 0x3ff + andi $v1, 0x1ff + sll $v1, 10 + or $v0, $v1 + lui $v1, 0x500 + or $v0, $v1 + sw $v0, GP1($s0) + + lw $ra, 0($sp) + lw $s0, 4($sp) + jr $ra + addiu $sp, 8 + diff --git a/libpsn00b/psxgpu/putdrawenv.s b/libpsn00b/psxgpu/putdrawenv.s new file mode 100644 index 0000000..69af437 --- /dev/null +++ b/libpsn00b/psxgpu/putdrawenv.s @@ -0,0 +1,142 @@ +.set noreorder +.set noat + +.include "hwregs_a.h" + +.set DRAW_x, 0 # Drawing area +.set DRAW_y, 2 +.set DRAW_w, 4 +.set DRAW_h, 6 +.set DRAW_ofx, 8 # Draw offset +.set DRAW_ofy, 10 +.set DRAW_tx, 12 # Texture window +.set DRAW_ty, 14 +.set DRAW_tw, 16 +.set DRAW_th, 18 +.set DRAW_tpage, 20 # TPage values +.set DRAW_dtd, 22 +.set DRAW_dfe, 23 +.set DRAW_isbg, 24 # Clear draw area +.set DRAW_r0, 25 +.set DRAW_g0, 26 +.set DRAW_b0, 27 +.set DRAW_env, 28 + + +.section .text + +.global PutDrawEnv +.type PutDrawEnv, @function +PutDrawEnv: + addiu $sp, -4 + sw $ra, 0($sp) + + addiu $a1, $a0, DRAW_env + + li $v0, 0x04ffffff # Packet header (length+terminator) + sw $v0, 0($a1) + + lhu $v0, DRAW_x($a0) # Set draw area top-left + lhu $v1, DRAW_y($a0) + andi $v0, 0x3ff + andi $v1, 0x1ff + sll $v1, 10 + or $v0, $v1 + lui $v1, 0xe300 + or $v0, $v1 + sw $v0, 4($a1) # 1 + + .set noat + + lhu $v0, DRAW_w($a0) # Set draw area bottom-right + lhu $at, DRAW_x($a0) + addiu $v0, -1 + addu $at, $v0 + andi $at, 0x3ff + lhu $v1, DRAW_h($a0) + lhu $v0, DRAW_y($a0) + addiu $v1, -1 + addu $v0, $v1 + andi $v0, 0x1ff + sll $v0, 10 + or $at, $v0 + lui $v0, 0xe400 + or $at, $v0 + sw $at, 8($a1) # 2 + + lhu $v0, DRAW_x($a0) # Set drawing offset + lhu $v1, DRAW_ofx($a0) + nop + add $v0, $v1 + andi $at, $v0, 0x7ff + lhu $v0, DRAW_y($a0) + lhu $v1, DRAW_ofy($a0) + nop + add $v0, $v1 + andi $v0, 0x7ff + sll $v0, 11 + or $at, $v0 + lui $v0, 0xe500 + or $at, $v0 + sw $at, 12($a1) # 3 + + lhu $at, DRAW_tpage($a0) # Set tpage + lbu $v0, DRAW_dtd($a0) + lbu $v1, DRAW_dfe($a0) + andi $v0, 1 + and $v1, 1 + sll $v0, 9 + sll $v1, 10 + or $at, $v0 + or $at, $v1 + lui $v0, 0xe100 + or $at, $v0 + sw $at, 16($a1) # 4 + + .set at + + lbu $v0, DRAW_isbg($a0) + nop + beqz $v0, .no_fillVRAM + nop + + lw $v0, DRAW_isbg($a0) # FillVRAM + lui $v1, 0x0200 + srl $v0, 8 + or $v0, $v1 + sw $v0, 20($a1) # 5 + lw $v0, DRAW_x($a0) + lw $v1, DRAW_w($a0) + sw $v0, 24($a1) # 6 + + srl $v0, $v1, 16 # Workaround as rectangle primitives + blt $v0, 511, .no_overflow # don't accept a height of 512 + nop + + li $v0, 511 + sll $v0, 16 + andi $v1, 0xffff + or $v1, $v0 + +.no_overflow: + sw $v1, 28($a1) # 7 + li $v0, 0x07ffffff # Packet header (length+terminator) + sw $v0, 0($a1) + +.no_fillVRAM: + +.gpu_wait: # Wait for GPU to become ready for commands and DMA + jal ReadGPUstat + nop + srl $v0, 26 + andi $v0, 1 + beqz $v0, .gpu_wait + nop + + jal DrawOTag + move $a0, $a1 + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop diff --git a/libpsn00b/psxgpu/readgpustat.s b/libpsn00b/psxgpu/readgpustat.s new file mode 100644 index 0000000..c587cfb --- /dev/null +++ b/libpsn00b/psxgpu/readgpustat.s @@ -0,0 +1,14 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + + +.global ReadGPUstat +.type ReadGPUstat, @function +ReadGPUstat: + lui $v0, 0x1f80 + lw $v0, GP1($v0) + jr $ra + nop diff --git a/libpsn00b/psxgpu/readme.txt b/libpsn00b/psxgpu/readme.txt new file mode 100644 index 0000000..55fcb68 --- /dev/null +++ b/libpsn00b/psxgpu/readme.txt @@ -0,0 +1,50 @@ +PSX GPU library, part of PSn00bSDK +2019 Lameguy64 / Meido-Tek Productions + +Licensed under Mozilla Public License + + Open source implementation of the GPU library written mostly in MIPS +assembly. Supports DMA transfers for ordering table draw and transferring +image data to VRAM. The syntax is intentionally made to closely resemble +Sony's syntax for familiarity and to make porting homebrew made using the +official SDK to PSn00bSDK a little easier. + + +Library developer(s): + + Lameguy64 + + +Library header(s): + + hwregs_a.h (GNU assembler port defs) + psxgpu.h + + +Todo list: + + * VSync() and DrawSync() functions lack alternate operating modes such as + getting number of vsyncs elapsed and waiting until a specified number of + vsyncs have passed. + + * VSync interrupt handler should be hooked using BIOS function + SetCustomExitFromException() like the official GPU library instead of + hooking an event handler, but said hook never seems to work. Perhaps + something in the kernel area needs to be patched/set or some event/IRQ + handler needs to be removed as such handlers can skip the custom + exception exit entirely. + + It also appears that all interrupt handling in the official libraries + are done through the GPU library. This would also explain why the + official documentation tells you to always call ResetGraph() at the + very beginning of your programs. + + * ClearOTag() function (non reverse version of ClearOTagR()) yet to be + implemented. + + * StoreImage() equivalent yet to be implemented. + + +Changelog: + + None thus far... diff --git a/libpsn00b/psxgpu/resetgraph.s b/libpsn00b/psxgpu/resetgraph.s new file mode 100644 index 0000000..bc30d3b --- /dev/null +++ b/libpsn00b/psxgpu/resetgraph.s @@ -0,0 +1,223 @@ +.set noreorder +.set noat + +.include "hwregs_a.h" + +.section .text + + +.global ResetGraph # Resets the GPU and installs a +.type ResetGraph, @function # VSync event handler +ResetGraph: + addiu $sp, -0x20 # C style stack allocation (required if + sw $ra, 28($sp) # you call BIOS functions from asm) + sw $a0, 24($sp) + + la $v0, _hooks_installed # Skip installing hooks if this function + lbu $v0, 0($v0) # has already been called before once + nop + bnez $v0, .skip_hook_init + nop + + # Temporary, may help improve compatibility? + jal SetDefaultExitFromException + nop + + jal ChangeClearPAD # Remove pad handler left by the BIOS + move $a0, $0 + + li $a0, 1 + jal ChangeClearRCnt # Remove RCnt handler + move $a1, $0 + + jal _96_remove # Remove CD handling left by the BIOS + nop + + lui $a3, 0x1f80 # Base address for I/O + + lui $v0, 0x3b33 # Enables DMA channel 6 (for ClearOTag) + ori $v0, 0x3b33 # Enables DMA channel 2 + sw $v0, DPCR($a3) + sw $0 , DICR($a3) # Clear DICR (not needed) + + li $v0, 0x9 # Enable IRQ0 (vblank) + sw $v0, IMASK($a3) + + # Set an event handler + + li $a0, 0xf2000003 # RCntCNT3 (vsync class) + li $a1, 0x2 + li $a2, 0x1000 + la $a3, _vsync_func # VSync event handler + + jal OpenEvent # Open a VSync event handler + # (PSXSDK style vsync handler) + nop + + la $v1, _vsync_event_desc # Save event descriptor + sw $v0, 0($v1) + + jal EnableEvent # Enable the opened event + move $a0, $v0 + + la $v0, _hooks_installed # Set installed flag + li $v1, 0x1 + sb $v1, 0($v0) + + la $v0, _vsync_counter # Clear VSync counter + sw $0 , 0($v0) + + la $v0, _vsync_callback_func # Clear callback function + sw $0 , 0($v0) + + jal ExitCriticalSection # Re-enable interrupts + nop + +.skip_hook_init: + + lui $a3, 0x1f80 + + lw $v0, GP1($a3) # Get video standard + lui $v1, 0x0010 + and $v0, $v1 + la $v1, _gpu_standard + beqz $v0, .not_pal + sw $0 , 0($v1) + li $v0, 1 + sw $v0, 0($v1) +.not_pal: + + lw $a0, 24($sp) # Get argument value + + lui $a3, 0x1f80 # Set base I/O again (likely destroyed + # by previous calls) + + li $v0, 0x1d00 # Configure timer 1 as Hblank counter + sw $v0, T1_MODE($a3) # Set timer 1 value + + li $at, 1 + beq $a0, $at, .gpu_init_1 + nop + li $at, 3 + beq $a0, $at, .gpu_init_3 + nop + + sw $0 , GP1($a3) # Reset the GPU + + b .init_done + nop + +.gpu_init_1: + + sw $0 , D2_CHCR($a3) # Stop any DMA + +.gpu_init_3: + + li $v0, 0x1 # Reset the command buffer + sw $v0, GP1($a3) + +.init_done: + + lw $ra, 28($sp) + lw $a0, 24($sp) # Return + jr $ra + addiu $sp, 0x20 + + +.global _vsync_func # VSync event handler, executed on +.type _vsync_func, @function # every VBlank +_vsync_func: + + la $gp, _gp + + lui $at, 0x1f80 # Check if there's a VSync IRQ + lw $v0, IMASK($at) + nop + andi $v0, $v0, 0x1 + beqz $v0, .exit + nop + + lw $v1, ISTAT($at) + nop + andi $v0, $v1, 0x1 + beqz $v0, .exit + nop + xori $v1, $v1, 0x1 # Acknowledge the IRQ + sw $v1, ISTAT($at) + + la $v1, _vsync_counter # Increment VSync counter + lw $v0, 0($v1) + nop + addiu $v0, 1 + sw $v0, 0($v1) + + la $v0, _vsync_callback_func # Check if a callback function is set + lw $v0, 0($v0) + nop + beqz $v0, .exit + nop + + addiu $sp, -0x20 # Save return address + sw $ra, 28($sp) + + jalr $v0 # Execute user function + nop + + lw $ra, 28($sp) # Restore previous return address + addiu $sp, 0x20 + +.exit: + jr $ra + nop + + +.global VSync # VSync function +.type VSync, @function +VSync: + addiu $sp, -4 + sw $ra, 0($sp) + + la $a1, _vsync_counter + lw $v0, 0($a1) + nop +.loop: + lw $v1, 0($a1) + nop + beq $v0, $v1, .loop + nop + + la $v0, _gpu_current_field # Get last field value + lbu $v1, 0($v0) +.wait_field: # Wait for field bit to change + jal ReadGPUstat + nop + srl $v0, 31 + beq $v0, $v1, .wait_field + nop + + la $v1, _gpu_current_field # Store new field value + sb $v0, 0($v1) + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + + +.section .data + +.global library_credits +.type library_credits, @object +library_credits: + .string "psxgpu programs by Lameguy64" + +.type _vsync_counter, @object +_vsync_counter: + .word 0 + +.comm _vsync_callback_func, 4, 4 +.comm _vsync_event_desc, 4, 4 + +.comm _gpu_standard, 4, 4 +.comm _gpu_current_field, 4, 4 +.comm _hooks_installed, 4, 4 diff --git a/libpsn00b/psxgpu/setdefdispenv.c b/libpsn00b/psxgpu/setdefdispenv.c new file mode 100644 index 0000000..6dec49c --- /dev/null +++ b/libpsn00b/psxgpu/setdefdispenv.c @@ -0,0 +1,21 @@ +#include <psxgpu.h> + +DISPENV *SetDefDispEnv(DISPENV *disp, int x, int y, int w, int h) { + + disp->disp.x = x; + disp->disp.y = y; + disp->disp.w = w; + disp->disp.h = h; + + disp->screen.x = 0; + disp->screen.y = 0; + disp->screen.w = 0; + disp->screen.h = 0; + + disp->isinter = 0; + disp->isrgb24 = 0; + disp->reverse = 0; + + return disp; + +} diff --git a/libpsn00b/psxgpu/setdefdrawenv.c b/libpsn00b/psxgpu/setdefdrawenv.c new file mode 100644 index 0000000..bcd93ca --- /dev/null +++ b/libpsn00b/psxgpu/setdefdrawenv.c @@ -0,0 +1,26 @@ +#include <psxgpu.h> + +DRAWENV *SetDefDrawEnv(DRAWENV *draw, int x, int y, int w, int h) { + + draw->clip.x = x; + draw->clip.y = y; + draw->clip.w = w; + draw->clip.h = h; + + draw->ofs[0] = 0; + draw->ofs[1] = 0; + + draw->tw.x = 0; + draw->tw.y = 0; + draw->tw.w = 0; + draw->tw.h = 0; + + draw->tpage = 0x0a; + draw->dtd = 1; + draw->dfe = 0; + draw->isbg = 0; + setRGB0( draw, 0, 0, 0 ); + + return draw; + +} diff --git a/libpsn00b/psxgpu/setdispmask.s b/libpsn00b/psxgpu/setdispmask.s new file mode 100644 index 0000000..77ceb04 --- /dev/null +++ b/libpsn00b/psxgpu/setdispmask.s @@ -0,0 +1,19 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + + +.global SetDispMask +.type SetDispMask, @function +SetDispMask: + lui $v1, 0x1f80 + andi $a0, 0x1 + lui $v0, 0x300 + ori $v0, 0x1 + sub $v0, $a0 + sw $v0, GP1($v1) + jr $ra + nop + diff --git a/libpsn00b/psxgpu/setvideomode.s b/libpsn00b/psxgpu/setvideomode.s new file mode 100644 index 0000000..718a4dd --- /dev/null +++ b/libpsn00b/psxgpu/setvideomode.s @@ -0,0 +1,50 @@ +.set noreorder + +.include "hwregs_a.h" + + +.section .text + +.global SetVideoMode +.type SetVideoMode, @function +SetVideoMode: + addiu $sp, -4 + sw $ra, 0($sp) + + jal ReadGPUstat + nop + + srl $a1, $v0, 17 + andi $a1, 0x1f + + srl $v1, $v0, 14 # Reverse flag + andi $v1, 1 + sll $v1, 6 + or $a1, $v1 + + srl $v1, $v0, 16 # Horizontal resolution 2 + andi $v1, 1 + sll $v1, 6 + or $a1, $v1 + + andi $a1, 0xf7 # Mask off PAL bit + + la $v0, _gpu_standard + beqz $a0, .set_done + sw $0 , 0($v0) + li $v1, 1 + sw $v1, 0($v0) + b .set_done + or $a1, 0x8 +.set_done: + + lui $v0, 0x800 # Apply new mode + or $a1, $v0 + lui $v0, IOBASE + sw $a1, GP1($v0) + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + diff --git a/libpsn00b/psxgpu/vsynccallback.s b/libpsn00b/psxgpu/vsynccallback.s new file mode 100644 index 0000000..1f96bbc --- /dev/null +++ b/libpsn00b/psxgpu/vsynccallback.s @@ -0,0 +1,25 @@ +.set noreorder + +.section .text + +.global VSyncCallback +.type VSyncCallback, @function +VSyncCallback: + addiu $sp, -8 + sw $ra, 0($sp) + + jal EnterCriticalSection + sw $a0, 4($sp) + + lw $a0, 4($sp) + la $v0, _vsync_callback_func + sw $a0, 0($v0) + + jal ExitCriticalSection + nop + + lw $ra, 0($sp) + addiu $sp, 8 + jr $ra + nop + diff --git a/libpsn00b/psxgte/applymatrixlv.s b/libpsn00b/psxgte/applymatrixlv.s new file mode 100644 index 0000000..332a2f8 --- /dev/null +++ b/libpsn00b/psxgte/applymatrixlv.s @@ -0,0 +1,40 @@ +.set noreorder + +.include "gtereg.h" +.include "inline_s.h" + +.section .text + + +.global ApplyMatrixLV +.type ApplyMatrixLV, @function +ApplyMatrixLV: + + # Load matrix to GTE + lw $t0, 0($a0) + lw $t1, 4($a0) + ctc2 $t0, $0 + ctc2 $t1, $1 + lw $t0, 8($a0) + lw $t1, 12($a0) + lhu $t2, 16($a0) + ctc2 $t0, $2 + ctc2 $t1, $3 + ctc2 $t2, $4 + + lw $t0, 0($a1) + lw $t1, 4($a1) + mtc2 $t0, C2_IR1 + lw $t0, 8($a1) + mtc2 $t1, C2_IR2 + mtc2 $t0, C2_IR3 + + nMVMVA(1, 0, 3, 3, 0) + + swc2 C2_IR1, 0($a2) + swc2 C2_IR2, 4($a2) + swc2 C2_IR3, 8($a2) + + jr $ra + move $v0, $a2 +
\ No newline at end of file diff --git a/libpsn00b/psxgte/compmatrixlv.s b/libpsn00b/psxgte/compmatrixlv.s new file mode 100644 index 0000000..95da5e9 --- /dev/null +++ b/libpsn00b/psxgte/compmatrixlv.s @@ -0,0 +1,100 @@ +.set noreorder + +.include "gtereg.h" +.include "inline_s.h" + +.set MATRIX_r11r12, 0 +.set MATRIX_r13r21, 4 +.set MATRIX_r22r23, 8 +.set MATRIX_r31r32, 12 +.set MATRIX_r33, 16 +.set MATRIX_trx, 20 +.set MATRIX_try, 24 +.set MATRIX_trz, 28 + + +.global CompMatrixLV +.type CompMatrixLV, @function +CompMatrixLV: + + # Load matrix v0 to GTE + lw $t0, MATRIX_r11r12($a0) + lw $t1, MATRIX_r13r21($a0) + ctc2 $t0, C2_R11R12 + ctc2 $t1, C2_R13R21 + lw $t0, MATRIX_r22r23($a0) + lw $t1, MATRIX_r31r32($a0) + lhu $t2, MATRIX_r33($a0) + ctc2 $t0, C2_R22R23 + lw $t0, MATRIX_trx($a0) + ctc2 $t1, C2_R31R32 + lw $t1, MATRIX_try($a0) + ctc2 $t2, C2_R33 + lw $t2, MATRIX_trz($a0) + ctc2 $t0, C2_TRX + ctc2 $t1, C2_TRY + ctc2 $t2, C2_TRZ + + lw $t0, MATRIX_trx($a1) + lw $t1, MATRIX_try($a1) + mtc2 $t0, C2_IR1 + lw $t0, MATRIX_trz($a1) + mtc2 $t1, C2_IR2 + mtc2 $t0, C2_IR3 + + nMVMVA(1, 0, 3, 0, 0) + + swc2 C2_IR1, MATRIX_trx($a2) + swc2 C2_IR2, MATRIX_try($a2) + swc2 C2_IR3, MATRIX_trz($a2) + + lhu $t1, 2*(0+(3*1))($a1) # Load values for first + lhu $t0, 2*(0+(3*0))($a1) # R11 R21 R31 + sll $t1, 16 + or $t0, $t1 + lhu $t1, 2*(0+(3*2))($a1) + mtc2 $t0, C2_VXY0 + mtc2 $t1, C2_VZ0 + + lhu $t1, 2*(1+(3*1))($a1) # Load values for second + lhu $t0, 2*(1+(3*0))($a1) # R12 R22 R32 + MVMVA(1, 0, 0, 3, 0) # First multiply + sll $t1, 16 + or $t0, $t1 + lhu $t1, 2*(1+(3*2))($a1) + mtc2 $t0, C2_VXY0 + mtc2 $t1, C2_VZ0 + + mfc2 $t0, C2_IR1 # Store results of first + mfc2 $t1, C2_IR2 + sh $t0, 2*(0+(3*0))($a2) + mfc2 $t0, C2_IR3 + sh $t1, 2*(0+(3*1))($a2) + sh $t0, 2*(0+(3*2))($a2) + + lhu $t1, 2*(2+(3*1))($a1) # Load values for third + lhu $t0, 2*(2+(3*0))($a1) # R13 R23 R33 + MVMVA(1, 0, 0, 3, 0) # Second multiply + sll $t1, 16 + or $t0, $t1 + lhu $t1, 2*(2+(3*2))($a1) + mtc2 $t0, C2_VXY0 + mtc2 $t1, C2_VZ0 + + mfc2 $t0, C2_IR1 # Store results of second + mfc2 $t1, C2_IR2 + sh $t0, 2*(1+(3*0))($a2) + mfc2 $t0, C2_IR3 + sh $t1, 2*(1+(3*1))($a2) + sh $t0, 2*(1+(3*2))($a2) + MVMVA(1, 0, 0, 3, 0) # Third multiply + + mfc2 $t0, C2_IR1 # Store results of third + mfc2 $t1, C2_IR2 + sh $t0, 2*(2+(3*0))($a2) + mfc2 $t0, C2_IR3 + sh $t1, 2*(2+(3*1))($a2) + sh $t0, 2*(2+(3*2))($a2) + + jr $ra + move $v0, $a2
\ No newline at end of file diff --git a/libpsn00b/psxgte/hirotmatrix.c b/libpsn00b/psxgte/hirotmatrix.c new file mode 100644 index 0000000..56516b0 --- /dev/null +++ b/libpsn00b/psxgte/hirotmatrix.c @@ -0,0 +1,35 @@ +#include <psxgte.h> + +MATRIX *HiRotMatrix(VECTOR *r, MATRIX *m) { + + short s[3],c[3]; + MATRIX tm[3]; + + s[0] = hisin(r->vx); s[1] = hisin(r->vy); s[2] = hisin(r->vz); + c[0] = hicos(r->vx); c[1] = hicos(r->vy); c[2] = hicos(r->vz); + + // mX + m->m[0][0] = ONE; m->m[0][1] = 0; m->m[0][2] = 0; + m->m[1][0] = 0; m->m[1][1] = c[0]; m->m[1][2] = -s[0]; + m->m[2][0] = 0; m->m[2][1] = s[0]; m->m[2][2] = c[0]; + + // mY + tm[0].m[0][0] = c[1]; tm[0].m[0][1] = 0; tm[0].m[0][2] = s[1]; + tm[0].m[1][0] = 0; tm[0].m[1][1] = ONE; tm[0].m[1][2] = 0; + tm[0].m[2][0] = -s[1]; tm[0].m[2][1] = 0; tm[0].m[2][2] = c[1]; + + // mZ + tm[1].m[0][0] = c[2]; tm[1].m[0][1] = -s[2]; tm[1].m[0][2] = 0; + tm[1].m[1][0] = s[2]; tm[1].m[1][1] = c[2]; tm[1].m[1][2] = 0; + tm[1].m[2][0] = 0; tm[1].m[2][1] = 0; tm[1].m[2][2] = ONE; + + PushMatrix(); + + MulMatrix0( m, &tm[0], &tm[2] ); + MulMatrix0( &tm[2], &tm[1], m ); + + PopMatrix(); + + return m; + +} diff --git a/libpsn00b/psxgte/hisin.c b/libpsn00b/psxgte/hisin.c new file mode 100644 index 0000000..68d5d28 --- /dev/null +++ b/libpsn00b/psxgte/hisin.c @@ -0,0 +1,33 @@ +/* Based on isin_S4 implementation from coranac: + * http://www.coranac.com/2009/07/sines/ + * + */ + +#define qN 15 +#define qA 12 +#define B 19900 +#define C 3516 + +int hisin(int x) { + + int c, x2, y; + + c= x<<(30-qN); // Semi-circle info into carry. + x -= 1<<qN; // sine -> cosine calc + + x= x<<(31-qN); // Mask with PI + x= x>>(31-qN); // Note: SIGNED shift! (to qN) + x= x*x>>(2*qN-14); // x=x^2 To Q14 + + y= B - (x*C>>14); // B - x^2*C + y= (1<<qA)-(x*y>>16); // A - x^2*(B-x^2*C) + + return c>=0 ? y : -y; + +} + +int hicos(int x) { + + return hisin( x+32768 ); + +} diff --git a/libpsn00b/psxgte/initgeom.s b/libpsn00b/psxgte/initgeom.s new file mode 100644 index 0000000..14ca293 --- /dev/null +++ b/libpsn00b/psxgte/initgeom.s @@ -0,0 +1,45 @@ +.set noreorder + +.include "gtereg.h" + +.section .text + + +.global InitGeom +.type InitGeom, @function +InitGeom: + addiu $sp, -4 + sw $ra, 0($sp) + + jal EnterCriticalSection + nop + + mfc0 $v0, $12 # Get SR + lui $v1, 0x4000 # Set bit to enable cop2 + or $v0, $v1 + mtc0 $v0, $12 # Set new SR + + jal ExitCriticalSection + nop + + ctc2 $0 , $24 # Reset GTE offset + ctc2 $0 , $25 + + li $v0, 320 # Set default projection plane + ctc2 $v0, $26 + + li $v0, 0x155 # Set ZSF3 and ZSF4 defaults + ctc2 $v0, $29 + li $v0, 0x100 + ctc2 $v0, $30 + + li $v0, 0xef9e # DQA and DQB defaults + lui $v1, 0x0140 + ctc2 $v0, C2_DQA + ctc2 $v1, C2_DQB + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + diff --git a/libpsn00b/psxgte/isin.c b/libpsn00b/psxgte/isin.c new file mode 100644 index 0000000..79e2970 --- /dev/null +++ b/libpsn00b/psxgte/isin.c @@ -0,0 +1,34 @@ +/* Based on isin_S4 implementation from coranac: + * http://www.coranac.com/2009/07/sines/ + * + */ + +#define qN 10 +#define qA 12 +#define B 19900 +#define C 3516 + +int isin(int x) { + + int c, x2, y; + + c= x<<(30-qN); // Semi-circle info into carry. + x -= 1<<qN; // sine -> cosine calc + + x= x<<(31-qN); // Mask with PI + x= x>>(31-qN); // Note: SIGNED shift! (to qN) + + x= x*x>>(2*qN-14); // x=x^2 To Q14 + + y= B - (x*C>>14); // B - x^2*C + y= (1<<qA)-(x*y>>16); // A - x^2*(B-x^2*C) + + return c>=0 ? y : -y; + +} + +int icos(int x) { + + return isin( x+1024 ); + +} diff --git a/libpsn00b/psxgte/makefile b/libpsn00b/psxgte/makefile new file mode 100644 index 0000000..6b0cb28 --- /dev/null +++ b/libpsn00b/psxgte/makefile @@ -0,0 +1,38 @@ +# Run using make (Linux) or gmake (BSD) +# Part of the PSn00bSDK Project +# 2019 Lameguy64 / Meido-Tek Productions + +PREFIX = mipsel-unknown-elf- + +TARGET = ../libpsxgte.a + +CFILES = $(notdir $(wildcard ./*.c)) +AFILES = $(notdir $(wildcard ./*.s)) +OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) + +INCLUDE = -I../include + +CFLAGS = -O2 -msoft-float -fno-builtin -fdata-sections -ffunction-sections -Wa,--strip-local-absolute +AFLAGS = -msoft-float --strip-local-absolute + +CC = $(PREFIX)gcc +AS = $(PREFIX)as +AR = $(PREFIX)ar +RANLIB = $(PREFIX)ranlib + +all: $(TARGET) + +$(TARGET): $(OFILES) + $(AR) cr $(TARGET) $(OFILES) + $(RANLIB) $(TARGET) + +build/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +build/%.o: %.s + @mkdir -p $(dir $@) + $(AS) $(AFLAGS) $(INCLUDE) $< -o $@ + +clean: + rm -Rf build $(TARGET) diff --git a/libpsn00b/psxgte/matrix.c b/libpsn00b/psxgte/matrix.c new file mode 100644 index 0000000..b4dea12 --- /dev/null +++ b/libpsn00b/psxgte/matrix.c @@ -0,0 +1,45 @@ +#include <psxgte.h> + +MATRIX *RotMatrix(SVECTOR *r, MATRIX *m) { + + short s[3],c[3]; + MATRIX tm[3]; + + s[0] = isin(r->vx); s[1] = isin(r->vy); s[2] = isin(r->vz); + c[0] = icos(r->vx); c[1] = icos(r->vy); c[2] = icos(r->vz); + + // mX + m->m[0][0] = ONE; m->m[0][1] = 0; m->m[0][2] = 0; + m->m[1][0] = 0; m->m[1][1] = c[0]; m->m[1][2] = -s[0]; + m->m[2][0] = 0; m->m[2][1] = s[0]; m->m[2][2] = c[0]; + + // mY + tm[0].m[0][0] = c[1]; tm[0].m[0][1] = 0; tm[0].m[0][2] = s[1]; + tm[0].m[1][0] = 0; tm[0].m[1][1] = ONE; tm[0].m[1][2] = 0; + tm[0].m[2][0] = -s[1]; tm[0].m[2][1] = 0; tm[0].m[2][2] = c[1]; + + // mZ + tm[1].m[0][0] = c[2]; tm[1].m[0][1] = -s[2]; tm[1].m[0][2] = 0; + tm[1].m[1][0] = s[2]; tm[1].m[1][1] = c[2]; tm[1].m[1][2] = 0; + tm[1].m[2][0] = 0; tm[1].m[2][1] = 0; tm[1].m[2][2] = ONE; + + PushMatrix(); + + MulMatrix0( m, &tm[0], &tm[2] ); + MulMatrix0( &tm[2], &tm[1], m ); + + PopMatrix(); + + return m; + +} + +MATRIX *TransMatrix(MATRIX *m, VECTOR *r) { + + m->t[0] = r->vx; + m->t[1] = r->vy; + m->t[2] = r->vz; + + return m; + +} diff --git a/libpsn00b/psxgte/mulmatrix.s b/libpsn00b/psxgte/mulmatrix.s new file mode 100644 index 0000000..19dabe8 --- /dev/null +++ b/libpsn00b/psxgte/mulmatrix.s @@ -0,0 +1,74 @@ +.set noreorder + +.include "gtereg.h" +.include "inline_s.h" + +.section .text + + +.global MulMatrix +.type MulMatrix, @function +MulMatrix: + + # Load m1 to GTE + lw $t0, 0($a1) + lw $t1, 4($a1) + ctc2 $t0, $0 + ctc2 $t1, $1 + lw $t0, 8($a1) + lw $t1, 12($a1) + lhu $t2, 16($a1) + ctc2 $t0, $2 + ctc2 $t1, $3 + ctc2 $t2, $4 + + lhu $t1, 2*(0+(3*1))($a0) # Load values for first + lhu $t0, 2*(0+(3*0))($a0) # R11 R21 R31 + sll $t1, 16 + or $t0, $t1 + lhu $t1, 2*(0+(3*2))($a0) + mtc2 $t0, C2_VXY0 + mtc2 $t1, C2_VZ0 + + lhu $t1, 2*(1+(3*1))($a0) # Load values for second + lhu $t0, 2*(1+(3*0))($a0) # R12 R22 R32 + MVMVA(1, 0, 0, 3, 0) # First multiply + sll $t1, 16 + or $t0, $t1 + lhu $t1, 2*(1+(3*2))($a0) + mtc2 $t0, C2_VXY0 + mtc2 $t1, C2_VZ0 + + mfc2 $t0, C2_IR1 # Store results of first + mfc2 $t1, C2_IR2 + sh $t0, 2*(0+(3*0))($a0) + mfc2 $t0, C2_IR3 + sh $t1, 2*(0+(3*1))($a0) + sh $t0, 2*(0+(3*2))($a0) + + lhu $t1, 2*(2+(3*1))($a0) # Load values for third + lhu $t0, 2*(2+(3*0))($a0) # R13 R23 R33 + MVMVA(1, 0, 0, 3, 0) # Second multiply + sll $t1, 16 + or $t0, $t1 + lhu $t1, 2*(2+(3*2))($a0) + mtc2 $t0, C2_VXY0 + mtc2 $t1, C2_VZ0 + + mfc2 $t0, C2_IR1 # Store results of second + mfc2 $t1, C2_IR2 + sh $t0, 2*(1+(3*0))($a0) + mfc2 $t0, C2_IR3 + sh $t1, 2*(1+(3*1))($a0) + sh $t0, 2*(1+(3*2))($a0) + MVMVA(1, 0, 0, 3, 0) # Third multiply + + mfc2 $t0, C2_IR1 # Store results of third + mfc2 $t1, C2_IR2 + sh $t0, 2*(2+(3*0))($a0) + mfc2 $t0, C2_IR3 + sh $t1, 2*(2+(3*1))($a0) + sh $t0, 2*(2+(3*2))($a0) + + jr $ra + move $v0, $a0 diff --git a/libpsn00b/psxgte/mulmatrix0.s b/libpsn00b/psxgte/mulmatrix0.s new file mode 100644 index 0000000..874226b --- /dev/null +++ b/libpsn00b/psxgte/mulmatrix0.s @@ -0,0 +1,74 @@ +.set noreorder + +.include "gtereg.h" +.include "inline_s.h" + +.section .text + + +.global MulMatrix0 +.type MulMatrix0, @function +MulMatrix0: + + # Load m1 to GTE + lw $t0, 0($a0) + lw $t1, 4($a0) + ctc2 $t0, $0 + ctc2 $t1, $1 + lw $t0, 8($a0) + lw $t1, 12($a0) + lhu $t2, 16($a0) + ctc2 $t0, $2 + ctc2 $t1, $3 + ctc2 $t2, $4 + + lhu $t1, 2*(0+(3*1))($a1) # Load values for first + lhu $t0, 2*(0+(3*0))($a1) # R11 R21 R31 + sll $t1, 16 + or $t0, $t1 + lhu $t1, 2*(0+(3*2))($a1) + mtc2 $t0, C2_VXY0 + mtc2 $t1, C2_VZ0 + + lhu $t1, 2*(1+(3*1))($a1) # Load values for second + lhu $t0, 2*(1+(3*0))($a1) # R12 R22 R32 + MVMVA(1, 0, 0, 3, 0) # First multiply + sll $t1, 16 + or $t0, $t1 + lhu $t1, 2*(1+(3*2))($a1) + mtc2 $t0, C2_VXY0 + mtc2 $t1, C2_VZ0 + + mfc2 $t0, C2_IR1 # Store results of first + mfc2 $t1, C2_IR2 + sh $t0, 2*(0+(3*0))($a2) + mfc2 $t0, C2_IR3 + sh $t1, 2*(0+(3*1))($a2) + sh $t0, 2*(0+(3*2))($a2) + + lhu $t1, 2*(2+(3*1))($a1) # Load values for third + lhu $t0, 2*(2+(3*0))($a1) # R13 R23 R33 + MVMVA(1, 0, 0, 3, 0) # Second multiply + sll $t1, 16 + or $t0, $t1 + lhu $t1, 2*(2+(3*2))($a1) + mtc2 $t0, C2_VXY0 + mtc2 $t1, C2_VZ0 + + mfc2 $t0, C2_IR1 # Store results of second + mfc2 $t1, C2_IR2 + sh $t0, 2*(1+(3*0))($a2) + mfc2 $t0, C2_IR3 + sh $t1, 2*(1+(3*1))($a2) + sh $t0, 2*(1+(3*2))($a2) + MVMVA(1, 0, 0, 3, 0) # Third multiply + + mfc2 $t0, C2_IR1 # Store results of third + mfc2 $t1, C2_IR2 + sh $t0, 2*(2+(3*0))($a2) + mfc2 $t0, C2_IR3 + sh $t1, 2*(2+(3*1))($a2) + sh $t0, 2*(2+(3*2))($a2) + + jr $ra + move $v0, $a2 diff --git a/libpsn00b/psxgte/pushpopmatrix.s b/libpsn00b/psxgte/pushpopmatrix.s new file mode 100644 index 0000000..d10687a --- /dev/null +++ b/libpsn00b/psxgte/pushpopmatrix.s @@ -0,0 +1,68 @@ +.set noreorder + +.include "gtereg.h" +.include "inline_s.h" + +.section .text + + +.global PushMatrix +.type PushMatrix, @function +PushMatrix: + la $a0, _matrix_stack + cfc2 $v0, C2_R11R12 + cfc2 $v1, C2_R13R21 + sw $v0, 0($a0) + cfc2 $v0, C2_R22R23 + sw $v1, 4($a0) + sw $v0, 8($a0) + cfc2 $v0, C2_R31R32 + cfc2 $v1, C2_R33 + sw $v0, 12($a0) + sw $v1, 16($a0) + cfc2 $v0, C2_TRX + cfc2 $v1, C2_TRY + sw $v0, 20($a0) + cfc2 $v0, C2_TRZ + sw $v1, 24($a0) + jr $ra + sw $v0, 28($a0) + +.global PopMatrix +.type PopMatrix, @function +PopMatrix: + la $a0, _matrix_stack + lw $v0, 0($a0) + lw $v1, 4($a0) + ctc2 $v0, C2_R11R12 + ctc2 $v1, C2_R13R21 + lw $v0, 8($a0) + lw $v1, 12($a0) + ctc2 $v0, C2_R22R23 + lw $v0, 16($a0) + ctc2 $v1, C2_R31R32 + ctc2 $v0, C2_R33 + lw $v0, 20($a0) + lw $v1, 24($a0) + ctc2 $v0, C2_TRX + lw $v0, 28($a0) + ctc2 $v1, C2_TRY + ctc2 $v0, C2_TRZ + jr $ra + nop + + +.section .data + + +.type matrix_stack, @object +_matrix_stack: + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + diff --git a/libpsn00b/psxgte/readme.txt b/libpsn00b/psxgte/readme.txt new file mode 100644 index 0000000..13b92b6 --- /dev/null +++ b/libpsn00b/psxgte/readme.txt @@ -0,0 +1,39 @@ +PSX GTE library, part of PSn00bSDK +2019 Lameguy64 / Meido-Tek Productions + +Licensed under Mozilla Public License + + Open source implementation of the GTE library written mostly in MIPS +assembly. It makes full use of the GTE in complex matrix multiplication +operations. The syntax is intentionally made to closely resemble Sony's syntax +for familiarity and to make porting homebrew made using the official SDK to +PSn00bSDK a little easier. + + Unlike the official GTE libraries using the inline GTE macro functions does +not require running your object file through some stupid tool such as DMPSX. +The GTE macros use the corresponding cop2 opcodes already. + + +Library developer(s): + + Lameguy64 + + +Library header(s): + + gtereg.h + inline_c.h + inline_s.h + psxgte.h + + +Todo list: + + * Alternate RotMatrix() functions with different rotation order are yet to + be implemented. + * Various high level RotTransPersp style functions not yet implemented. + + +Changelog: + + None thus far... diff --git a/libpsn00b/psxgte/scalematrix.s b/libpsn00b/psxgte/scalematrix.s new file mode 100644 index 0000000..3e83800 --- /dev/null +++ b/libpsn00b/psxgte/scalematrix.s @@ -0,0 +1,68 @@ +.set noreorder + +.include "gtereg.h" +.include "inline_s.h" + +.section .text + + +.global ScaleMatrix +.type ScaleMatrix, @function +ScaleMatrix: + + lwc2 C2_IR0, 0($a1) # X + + lh $v0, 2*(0+(3*0))($a0) + lh $v1, 2*(0+(3*1))($a0) + mtc2 $v0, C2_IR1 + lh $v0, 2*(0+(3*2))($a0) + mtc2 $v1, C2_IR2 + mtc2 $v0, C2_IR3 + + nGPF(1) + + mfc2 $v0, C2_IR1 + mfc2 $v1, C2_IR2 + sh $v0, 2*(0+(3*0))($a0) + mfc2 $v0, C2_IR3 + sh $v1, 2*(0+(3*1))($a0) + sh $v0, 2*(0+(3*2))($a0) + + lwc2 C2_IR0, 4($a1) # Y + + lh $v0, 2*(1+(3*0))($a0) + lh $v1, 2*(1+(3*1))($a0) + mtc2 $v0, C2_IR1 + lh $v0, 2*(1+(3*2))($a0) + mtc2 $v1, C2_IR2 + mtc2 $v0, C2_IR3 + + nGPF(1) + + mfc2 $v0, C2_IR1 + mfc2 $v1, C2_IR2 + sh $v0, 2*(1+(3*0))($a0) + mfc2 $v0, C2_IR3 + sh $v1, 2*(1+(3*1))($a0) + sh $v0, 2*(1+(3*2))($a0) + + lwc2 C2_IR0, 8($a1) # Z + + lh $v0, 2*(2+(3*0))($a0) + lh $v1, 2*(2+(3*1))($a0) + mtc2 $v0, C2_IR1 + lh $v0, 2*(2+(3*2))($a0) + mtc2 $v1, C2_IR2 + mtc2 $v0, C2_IR3 + + nGPF(1) + + mfc2 $v0, C2_IR1 + mfc2 $v1, C2_IR2 + sh $v0, 2*(2+(3*0))($a0) + mfc2 $v0, C2_IR3 + sh $v1, 2*(2+(3*1))($a0) + sh $v0, 2*(2+(3*2))($a0) + + jr $ra + move $v0, $a0 diff --git a/libpsn00b/psxgte/square0.s b/libpsn00b/psxgte/square0.s new file mode 100644 index 0000000..d037b7e --- /dev/null +++ b/libpsn00b/psxgte/square0.s @@ -0,0 +1,27 @@ +.set noreorder + +.include "gtereg.h" +.include "inline_s.h" + +.section .text + + +.global Square0 +.type Square0, @function +Square0: + + # a0 - Pointer to input vector (v0) + # a1 - Pointer to output vector (v1) + + lwc2 C2_IR1, 0($a0) + lwc2 C2_IR2, 4($a0) + lwc2 C2_IR3, 8($a0) + + nSQR(0) + + swc2 C2_IR1, 0($a1) + swc2 C2_IR2, 4($a1) + swc2 C2_IR3, 8($a1) + + jr $ra + nop diff --git a/libpsn00b/psxgte/squareroot.s b/libpsn00b/psxgte/squareroot.s new file mode 100644 index 0000000..71f40a9 --- /dev/null +++ b/libpsn00b/psxgte/squareroot.s @@ -0,0 +1,121 @@ +.set noreorder + +.include "gtereg.h" +.include "inline_s.h" + +.section .text + +.global SquareRoot12 +.type SquareRoot12, @function +SquareRoot12: + mtc2 $a0, C2_LZCS + nop + nop + mfc2 $v0, C2_LZCR + beq $v0, 32, $bad_sqr12 + nop + andi $t0, $v0, 0x1 + addiu $v1, $0 , -2 + and $t2, $v0, $v1 + li $t1, 19 + sub $t1, $t2 + sra $t1, 1 + addi $t3, $t2, -24 + bltz $t3, $value_less12 + nop + sllv $t4, $a0, $t3 + b $value_greater12 +$value_less12: + addiu $t3, $0 , 24 + sub $t3, $t2 + srav $t4, $a0, $t3 +$value_greater12: + addi $t4, -64 + sll $t4, 1 + la $t5, sqrt_table + addu $t5, $t4 + lh $t5, 0($t5) + nop + + bltz $t1, $1594c + nop + jr $ra + sllv $v0, $t5, $t1 + +$1594c: + + sub $t1, $0 , $t1 + jr $ra + srl $v0, $t5, $t1 + +$bad_sqr12: + jr $ra + move $v0, $0 + + +.global SquareRoot0 +.type SquareRoot0, @function +SquareRoot0: + mtc2 $a0, C2_LZCS + nop + nop + mfc2 $v0, C2_LZCR + beq $v0, 32, $bad_sqr + nop + andi $t0, $v0, 0x1 + addiu $v1, $0 , -2 + and $t2, $v0, $v1 + li $t1, 31 + sub $t1, $t2 + sra $t1, 1 + addi $t3, $t2, -24 + bltz $t3, $value_less + nop + sllv $t4, $a0, $t3 + b $value_greater +$value_less: + addiu $t3, $0 , 24 + sub $t3, $t2 + srav $t4, $a0, $t3 +$value_greater: + addi $t4, -64 + sll $t4, 1 + la $t5, sqrt_table + addu $t5, $t4 + lh $t5, 0($t5) + nop + sllv $t5, $t5, $t1 + jr $ra + srl $v0, $t5, 12 +$bad_sqr: + jr $ra + move $v0, $0 + + +.section .data + +sqrt_table: + .hword 0x1000,0x101f,0x103f,0x105e,0x107e,0x109c,0x10bb,0x10da + .hword 0x10f8,0x1116,0x1134,0x1152,0x116f,0x118c,0x11a9,0x11c6 + .hword 0x11e3,0x1200,0x121c,0x1238,0x1254,0x1270,0x128c,0x12a7 + .hword 0x12c2,0x12de,0x12f9,0x1314,0x132e,0x1349,0x1364,0x137e + .hword 0x1398,0x13b2,0x13cc,0x13e6,0x1400,0x1419,0x1432,0x144c + .hword 0x1465,0x147e,0x1497,0x14b0,0x14c8,0x14e1,0x14f9,0x1512 + .hword 0x152a,0x1542,0x155a,0x1572,0x158a,0x15a2,0x15b9,0x15d1 + .hword 0x15e8,0x1600,0x1617,0x162e,0x1645,0x165c,0x1673,0x1689 + .hword 0x16a0,0x16b7,0x16cd,0x16e4,0x16fa,0x1710,0x1726,0x173c + .hword 0x1752,0x1768,0x177e,0x1794,0x17aa,0x17bf,0x17d5,0x17ea + .hword 0x1800,0x1815,0x182a,0x183f,0x1854,0x1869,0x187e,0x1893 + .hword 0x18a8,0x18bd,0x18d1,0x18e6,0x18fa,0x190f,0x1923,0x1938 + .hword 0x194c,0x1960,0x1974,0x1988,0x199c,0x19b0,0x19c4,0x19d8 + .hword 0x19ec,0x1a00,0x1a13,0x1a27,0x1a3a,0x1a4e,0x1a61,0x1a75 + .hword 0x1a88,0x1a9b,0x1aae,0x1ac2,0xa1d5,0x1ae8,0x1afb,0x1b0e + .hword 0x1b21,0x1b33,0x1b46,0x1b59,0x1b6c,0x1b7e,0x1b91,0x1ba3 + .hword 0x1bb6,0x1bc8,0x1bdb,0x1bed,0x1c00,0x1c12,0x1c24,0x1c36 + .hword 0x1c48,0x1c5a,0x1c6c,0x1c7e,0x1c90,0x1ca2,0x1cb4,0x1cc6 + .hword 0x1cd8,0x1ce9,0x1cfb,0x1d0d,0x1d1e,0x1d30,0x1d41,0x1d53 + .hword 0x1d64,0x1d76,0x1d87,0x1d98,0x1daa,0x1dbb,0x1dcc,0x1ddd + .hword 0x1dee,0x1e00,0x1e11,0x1e22,0x1e33,0x1e43,0x1e54,0x1e65 + .hword 0x1e76,0x1e87,0x1e98,0x1ea8,0x1eb9,0x1eca,0x1eda,0x1eeb + .hword 0x1efb,0x1f0c,0x1f1c,0x1f2d,0x1f3d,0x1f4e,0x1f5e,0x1f6e + .hword 0x1f7e,0x1f8f,0x1f9f,0x1faf,0x1fbf,0x1fcf,0x1fdf,0x1fef
\ No newline at end of file diff --git a/libpsn00b/psxgte/vectornormals.s b/libpsn00b/psxgte/vectornormals.s new file mode 100644 index 0000000..8907d43 --- /dev/null +++ b/libpsn00b/psxgte/vectornormals.s @@ -0,0 +1,110 @@ +.set noreorder +.set noat + +.include "gtereg.h" +.include "inline_s.h" + +.section .text + + +.global VectorNormalS +.type VectorNormalS, @function +VectorNormalS: + + # Implementation ripped from Sony libs + + lw $t0, 0($a0) + lw $t1, 4($a0) + lw $t2, 8($a0) + + mtc2 $t0, C2_IR1 + mtc2 $t1, C2_IR2 + mtc2 $t2, C2_IR3 + + nSQR(0) + + mfc2 $t3, C2_MAC1 + mfc2 $t4, C2_MAC2 + mfc2 $t5, C2_MAC3 + + add $t3, $t4 + add $v0, $t3, $t5 + mtc2 $v0, C2_LZCS + nop + nop + mfc2 $v1, C2_LZCR + + addiu $at, $0 , -2 + and $v1, $at + + addiu $t6, $0 , 0x1f + sub $t6, $v1 + sra $t6, 1 + addiu $t3, $v1, -24 + + bltz $t3, $value_neg + nop + b $value_pos + sllv $t4, $v0, $t3 +$value_neg: + addiu $t3, $0 , 24 + sub $t3, $v1 + srav $t4, $v0, $t3 +$value_pos: + addi $t4, -64 + sll $t4, 1 + + la $t5, _norm_table + addu $t5, $t4 + lh $t5, 0($t5) + nop + + mtc2 $t5, C2_IR0 + mtc2 $t0, C2_IR1 + mtc2 $t1, C2_IR2 + mtc2 $t2, C2_IR3 + + nGPF(0) + + mfc2 $t0, C2_MAC1 + mfc2 $t1, C2_MAC2 + mfc2 $t2, C2_MAC3 + + sra $t0, $t6 + sra $t1, $t6 + sra $t2, $t6 + + sh $t0, 0($a1) + sh $t1, 2($a1) + jr $ra + sh $t2, 4($a1) + + +.section .data + +_norm_table: + .hword 0x1000, 0x0FE0, 0x0FC1, 0x0FA3, 0x0F85, 0x0F68, 0x0F4C, 0x0F30 + .hword 0x0F15, 0x0EFB, 0x0EE1, 0x0EC7, 0x0EAE, 0x0E96, 0x0E7E, 0x0E66 + .hword 0x0E4F, 0x0E38, 0x0E22, 0x0E0C, 0x0DF7, 0x0DE2, 0x0DCD, 0x0DB9 + .hword 0x0DA5, 0x0D91, 0x0D7E, 0x0D6B, 0x0D58, 0x0D45, 0x0D33, 0x0D21 + .hword 0x0D10, 0x0CFF, 0x0CEE, 0x0CDD, 0x0CCC, 0x0CBC, 0x0CAC, 0x0C9C + .hword 0x0C8D, 0x0C7D, 0x0C6E, 0x0C5F, 0x0C51, 0x0C42, 0x0C34, 0x0C26 + .hword 0x0C18, 0x0C0A, 0x0BFD, 0x0BEF, 0x0BE2, 0x0BD5, 0x0BC8, 0x0BBB + .hword 0x0BAF, 0x0BA2, 0x0B96, 0x0B8A, 0x0B7E, 0x0B72, 0x0B67, 0x0B5B + .hword 0x0B50, 0x0B45, 0x0B39, 0x0B2E, 0x0B24, 0x0B19, 0x0B0E, 0x0B04 + .hword 0x0AF9, 0x0AEF, 0x0AE5, 0x0ADB, 0x0AD1, 0x0AC7, 0x0ABD, 0x0AB4 + .hword 0x0AAA, 0x0AA1, 0x0A97, 0x0A8E, 0x0A85, 0x0A7C, 0x0A73, 0x0A6A + .hword 0x0A61, 0x0A59, 0x0A50, 0x0A47, 0x0A3F, 0x0A37, 0x0A2E, 0x0A26 + .hword 0x0A1E, 0x0A16, 0x0A0E, 0x0A06, 0x09FE, 0x09F6, 0x09EF, 0x09E7 + .hword 0x09E0, 0x09D8, 0x09D1, 0x09C9, 0x09C2, 0x09BB, 0x09B4, 0x09AD + .hword 0x09A5, 0x099E, 0x0998, 0x0991, 0x098A, 0x0983, 0x097C, 0x0976 + .hword 0x096F, 0x0969, 0x0962, 0x095C, 0x0955, 0x094F, 0x0949, 0x0943 + .hword 0x093C, 0x0936, 0x0930, 0x092A, 0x0924, 0x091E, 0x0918, 0x0912 + .hword 0x090D, 0x0907, 0x0901, 0x08FB, 0x08F6, 0x08F0, 0x08EB, 0x08E5 + .hword 0x08E0, 0x08DA, 0x08D5, 0x08CF, 0x08CA, 0x08C5, 0x08BF, 0x08BA + .hword 0x08B5, 0x08B0, 0x08AB, 0x08A6, 0x08A1, 0x089C, 0x0897, 0x0892 + .hword 0x088D, 0x0888, 0x0883, 0x087E, 0x087A, 0x0875, 0x0870, 0x086B + .hword 0x0867, 0x0862, 0x085E, 0x0859, 0x0855, 0x0850, 0x084C, 0x0847 + .hword 0x0843, 0x083E, 0x083A, 0x0836, 0x0831, 0x082D, 0x0829, 0x0824 + .hword 0x0820, 0x081C, 0x0818, 0x0814, 0x0810, 0x080C, 0x0808, 0x0804 +
\ No newline at end of file diff --git a/libpsn00b/psxspu/makefile b/libpsn00b/psxspu/makefile new file mode 100644 index 0000000..d6b3604 --- /dev/null +++ b/libpsn00b/psxspu/makefile @@ -0,0 +1,34 @@ +PREFIX = mipsel-unknown-elf- + +TARGET = ../libpsxspu.a + +CFILES = $(notdir $(wildcard ./*.c)) +AFILES = $(notdir $(wildcard ./*.s)) +OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) + +INCLUDE = -I../include + +CFLAGS = -O2 -g -msoft-float -Wa,--strip-local-absolute +AFLAGS = -g -msoft-float --strip-local-absolute + +CC = $(PREFIX)gcc +AS = $(PREFIX)as +AR = $(PREFIX)ar +RANLIB = $(PREFIX)ranlib + +all: $(TARGET) + +$(TARGET): $(OFILES) + $(AR) cr $(TARGET) $(OFILES) + $(RANLIB) $(TARGET) + +build/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +build/%.o: %.s + @mkdir -p $(dir $@) + $(AS) $(AFLAGS) $(INCLUDE) $< -o $@ + +clean: + rm -Rf build $(TARGET) diff --git a/libpsn00b/psxspu/readme.txt b/libpsn00b/psxspu/readme.txt new file mode 100644 index 0000000..4cac976 --- /dev/null +++ b/libpsn00b/psxspu/readme.txt @@ -0,0 +1,36 @@ +PSX SPU Library, part of PSn00bSDK +2019 Lameguy64 / Meido-Tek Productions + +Licensed under Mozilla Public License + + Open source implementation of the SPU library written mostly in MIPS +assembly. Currently only supports SPU init, uploading sample data using DMA +transfer and basic sample playback but is currently lacking a bunch of +important functions. + + Very work in progress currently. + + +Library developer(s): + + Lameguy64 + + +Library header(s): + + psxspu.h + + +Todo list: + + * SPU RAM allocation routines yet to be implemented (heap must only be + stored in main RAM and not SPU RAM like in the official SDK). + + * SpuKeyOn() is actually not part of the official library. + + * SPU reverb configuration functions yet to be implemented. + + +Changelog: + + None so far... diff --git a/libpsn00b/psxspu/spuinit.s b/libpsn00b/psxspu/spuinit.s new file mode 100644 index 0000000..fa5ec32 --- /dev/null +++ b/libpsn00b/psxspu/spuinit.s @@ -0,0 +1,130 @@ +.set noreorder +.set noat + +.include "hwregs_a.h" + +.section .data + + +.global SpuInit +.type SpuInit, @function +SpuInit: + + addiu $sp, -4 + sw $ra, 0($sp) + + lui $v1, IOBASE + + # Stop and mute everything + + sh $0 , SPUCNT($v1) # Clear control settings + jal SpuCtrlSync + move $a0, $0 + + sh $0 , SPU_MASTER_VOL($v1) # Clear master volume + sh $0 , SPU_MASTER_VOL+2($v1) + + sh $0 , SPU_REVERB_VOL($v1) # Clear reverb volume + sh $0 , SPU_REVERB_VOL+2($v1) + + sh $0 , SPU_CD_VOL($v1) # Clear CD volume + sh $0 , SPU_CD_VOL+2($v1) + + sh $0 , SPU_EXT_VOL($v1) # Clear external audio volume + sh $0 , SPU_EXT_VOL+2($v1) + + sh $0 , SPU_FM_MODE($v1) # Turn off FM modes + sh $0 , SPU_FM_MODE+2($v1) + + sh $0 , SPU_NOISE_MODE($v1) # Turn off noise modes + sh $0 , SPU_NOISE_MODE+2($v1) + + sh $0 , SPU_REVERB_ON($v1) # Turn off reverb modes + sh $0 , SPU_REVERB_ON+2($v1) + + li $v0, 0xfffe + sh $v0, SPU_REVERB_ADDR($v1) + + lui $v0, 0x0200; + ori $v0, 0x3fff; + + # Clear all voices + + addiu $a1, $sp, -20 + sw $0 , 0($a1) + sw $0 , 4($a1) + sw $0 , 8($a1) + sw $0 , 12($a1) + + li $a2, 23 + +.clear_voices: + jal SpuSetVoiceRaw + move $a0, $a2 + addiu $a2, -1 + bgez $a2, .clear_voices + nop + + li $v0, 0xffff # Set all keys to off + sh $v0, SPU_KEY_OFF($v1) + sh $v0, SPU_KEY_OFF+2($v1) + + li $v0, 0x4 # Set SPU data transfer control + sh $v0, SPUDTCNT($v1) # (usually always 0x4) + + lw $v0, DPCR($v1) # Enable DMA channel 4 (SPU DMA) + lui $at, 0xb + or $v0, $at + sw $v0, DPCR($v1) + + li $v0, 0xc000 # Enable SPU + sh $v0, SPUCNT($v1) + jal SpuCtrlSync + move $a0, $v0 + + li $v0, 0x3fff # Activate master volume + sh $v0, SPU_MASTER_VOL($v1) + sh $v0, SPU_MASTER_VOL+2($v1) + + sh $v0, SPU_CD_VOL($v1) # Activate CD volume + sh $v0, SPU_CD_VOL+2($v1) + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + + +# Waits until bits 0-5 of SPUSTAT are equal to SPUCNT +# +# Destroys v0, v1, a0 +# +.global SpuCtrlSync +.type SpuCtrlSync, @function +SpuCtrlSync: + lui $v1, IOBASE + andi $a0, 0x3f +.ctrl_wait: + lhu $v0, SPUSTAT($v1) # Get SPUSTAT value + nop + andi $v0, 0x3f + bne $v0, $a0, .ctrl_wait # Wait until SPUCNT and SPUSTAT are equal + nop + jr $ra + nop + + +# Waits until SPU has finished transfers +# +.global SpuWait +.type SpuWait, @function +SpuWait: + lui $v0, IOBASE + lhu $v0, SPUSTAT($v0) + nop + andi $v0, 0x400 + bnez $v0, SpuWait + nop + jr $ra + nop +
\ No newline at end of file diff --git a/libpsn00b/psxspu/spukeyon.s b/libpsn00b/psxspu/spukeyon.s new file mode 100644 index 0000000..556f976 --- /dev/null +++ b/libpsn00b/psxspu/spukeyon.s @@ -0,0 +1,16 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .data + + +.global SpuKeyOn +.type SpuKeyOn, @function +SpuKeyOn: + lui $v1, IOBASE + li $v0, 1 + sll $v0, $a0 + sh $v0, SPU_KEY_ON($v1) + jr $ra + nop
\ No newline at end of file diff --git a/libpsn00b/psxspu/spureverbon.s b/libpsn00b/psxspu/spureverbon.s new file mode 100644 index 0000000..852bff3 --- /dev/null +++ b/libpsn00b/psxspu/spureverbon.s @@ -0,0 +1,16 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .data + + +.global SpuReverbOn +.type SpuReverbOn, @function +SpuReverbOn: + lui $v1, IOBASE + li $v0, 1 + sll $v0, $a0 + sh $v0, SPU_REVERB_ON($v1) + jr $ra + nop
\ No newline at end of file diff --git a/libpsn00b/psxspu/spusetkey.s b/libpsn00b/psxspu/spusetkey.s new file mode 100644 index 0000000..1270b2a --- /dev/null +++ b/libpsn00b/psxspu/spusetkey.s @@ -0,0 +1,26 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .data + + +.global SpuSetKey +.type SpuSetKey, @function +SpuSetKey: + # a0 - 0: key off, 1: key on + # a1 - Voice bit mask + + lui $a2, IOBASE + + beqz $a0, .key_off + nop + + jr $ra + sh $a1, SPU_KEY_ON($v1) + +.key_off: + + jr $ra + sh $a1, SPU_KEY_OFF($v1) +
\ No newline at end of file diff --git a/libpsn00b/psxspu/spusetreverb.s b/libpsn00b/psxspu/spusetreverb.s new file mode 100644 index 0000000..993b166 --- /dev/null +++ b/libpsn00b/psxspu/spusetreverb.s @@ -0,0 +1,24 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .data + + +.global SpuSetReverb +.type SpuSetReverb, @function +SpuSetReverb: + addiu $sp, -4 + sw $ra, 0($sp) + + lhu $v0, SPUCNT($v1) + nop + ori $v0, 0x80 # Enable reverb + sh $v0, SPUCNT($v1) + jal SpuCtrlSync + move $a0, $v0 + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop
\ No newline at end of file diff --git a/libpsn00b/psxspu/spusetreverbaddr.s b/libpsn00b/psxspu/spusetreverbaddr.s new file mode 100644 index 0000000..6ddbf44 --- /dev/null +++ b/libpsn00b/psxspu/spusetreverbaddr.s @@ -0,0 +1,25 @@ +.set noreorder + +.include "hwregs_a.h" + + +.section .text + +.global SpuSetReverbAddr +.type SpuSetReverbAddr, @function +SpuSetReverbAddr: + lui $a3, 0x1f80 + srl $a0, 3 + sh $a0, SPU_REVERB_ADDR($a3) + jr $ra + nop + + +.global SpuSetReverbVolume +.type SpuSetReverbVolume, @function +SpuSetReverbVolume: + lui $a3, 0x1f80 + sh $a0, SPU_REVERB_VOL($a3) + sh $a1, SPU_REVERB_VOL+2($a3) + jr $ra + nop
\ No newline at end of file diff --git a/libpsn00b/psxspu/spusetvoiceraw.s b/libpsn00b/psxspu/spusetvoiceraw.s new file mode 100644 index 0000000..43450f6 --- /dev/null +++ b/libpsn00b/psxspu/spusetvoiceraw.s @@ -0,0 +1,60 @@ +.set noreorder + +.include "hwregs_a.h" + + +.set PARAM_L, 0 +.set PARAM_R, 2 +.set PARAM_FREQ, 4 +.set PARAM_ADDR, 6 +.set PARAM_LOOP, 8 +.set PARAM_RES, 10 +.set PARAM_ADSR, 12 + + +.section .text + +.global SpuSetVoiceRaw +.type SpuSetVoiceRaw, @function +SpuSetVoiceRaw: + + # a0 - Voice number + # a1 - Address to parameters + + sll $a0, 4 + addiu $a0, SPU_VOICE_BASE + + lui $v1, IOBASE + or $a0, $v1 + + lhu $v0, PARAM_L($a1) + nop + sh $v0, SPU_VOICE_VOL_L($a0) + + lhu $v0, PARAM_R($a1) + nop + sh $v0, SPU_VOICE_VOL_R($a0) + + lhu $v0, PARAM_FREQ($a1) + nop + sh $v0, SPU_VOICE_FREQ($a0) + + lhu $v0, PARAM_ADDR($a1) + nop + sh $v0, SPU_VOICE_ADDR($a0) + + lhu $v0, PARAM_LOOP($a1) + nop + sh $v0, SPU_VOICE_LOOP($a0) + + + lw $v0, PARAM_ADSR($a1) + nop + sh $v0, SPU_VOICE_ADSR_L($a0) + srl $v0, 16 + sh $v0, SPU_VOICE_ADSR_H($a0) + + + jr $ra + nop +
\ No newline at end of file diff --git a/libpsn00b/psxspu/transfer.s b/libpsn00b/psxspu/transfer.s new file mode 100644 index 0000000..aed69dc --- /dev/null +++ b/libpsn00b/psxspu/transfer.s @@ -0,0 +1,107 @@ +.set noreorder + +.include "hwregs_a.h" + + +.section .text + +.global SpuSetTransferMode +.type SpuSetTransferMode, @function +SpuSetTransferMode: + la $v0, _spu_transfer_mode + sb $a0, 0($v0) + jr $ra + move $v0, $a0 + + +.global SpuSetTransferStartAddr +.type SpuSetTransferStartAddr, @function +SpuSetTransferStartAddr: + li $v0, 0x1000 # Check if value is valid + blt $a0, $v0, .bad_value + nop + li $v0, 0xffff + bgt $a0, $v0, .bad_value + nop + + la $v1, _spu_transfer_addr + srl $v0, $a0, 3 # Set transfer destination address + sh $v0, 0($v1) + + jr $ra + move $v0, $a0 + +.bad_value: + jr $ra + move $v0, $0 + + +.global SpuWrite +.type SpuWrite, @function +SpuWrite: + addiu $sp, -8 + sw $ra, 0($sp) + sw $a0, 4($sp) + + lui $a3, IOBASE + + lhu $v0, SPUCNT($a3) # Set transfer mode to Stop + nop + andi $v0, 0xffcf + sh $v0, SPUCNT($a3) + jal SpuCtrlSync + move $a0, $v0 + + la $v1, _spu_transfer_addr # Set SPU write address + lhu $v1, 0($v1) + nop + sh $v1, SPU_ADDR($a3) + + lhu $v0, SPUCNT($a3) # Set transfer mode to DMA write + nop + ori $v0, 0x20 + sh $v0, SPUCNT($a3) + #jal SpuCtrlSync # Locks up on most emulators (bit 5 in + #move $a0, $v0 # SPUSTAT likely not updating, seems to + # be okay to not wait for it on real HW) + + lw $a0, 4($sp) + +.dma_wait: # Wait for SPU to be ready for DMA + lhu $v0, SPUSTAT($a3) + nop + andi $v0, 0x400 # Bit 8 in SPUSTAT never changes to 1 on + bnez $v0, .dma_wait # emulators so use bit 10 instead + nop + + sw $a0, D4_MADR($a3) # Set DMA source address + + li $v0, 0x10 # 16 words per block (64 bytes) + addiu $a1, 63 # Add by 63 to ensure all bytes get sent + srl $a1, 6 # Equivalent to divide by 64 + andi $a1, 0xffff + sll $a1, 16 + or $v0, $a1 + sw $v0, D4_BCR($a3) + + lui $v0, 0x0100 # Commence transfer + ori $v0, 0x0201 + sw $v0, D4_CHCR($a3) + + lw $ra, 0($sp) + addiu $sp, 8 + jr $ra + nop + + +.section .data + +.global _spu_transfer_mode +.type _spu_transfer_mode, @object +_spu_transfer_mode: + .word 0x0 + +.global _spu_transfer_addr +.type _spu_transfer_addr, @object +_spu_transfer_addr: + .word 0x200
\ No newline at end of file diff --git a/libpsn00b/readme.txt b/libpsn00b/readme.txt new file mode 100644 index 0000000..c5fee34 --- /dev/null +++ b/libpsn00b/readme.txt @@ -0,0 +1,101 @@ +LibPSn00b, PSn00bSDK software libraries +2019 Lameguy64 / Meido-Tek Productions + +Licensed under Mozilla Public License + +LibPSn00b make up the majority of PSn00bSDK as it provides the functions +necessary for developing software for the PSX. Most libraries, mainly the +GPU and GTE libraries are written mostly in assembly language. + + +Brief library overview: + + libc - Standard C library. Contains only a small subset of the full + standard C library, mostly string and memory manipulation + functions. + + psxgpu - GPU library for video and graphics control. Most of the + important functions are implemented. + + psxgte - GTE library for GTE accelerated vector transformations. Most + important functions are implemented. + + psxapi - Provides access to most of the BIOS functions calls of the + PSX BIOS. + + psxetc - Provides some misc functions such as debug font. + + psxspu - SPU library. Basic functions such as hardware init, uploading + data to SPU RAM via DMA transfer and playing sound playback + are fully working but is currently lacking a number of + important functions, especially reverb. + + Each library has its own readme file that contains its changelog, todo + list, credits and some additional details of the library. + + +Compiling: + + Compiling the LibPSn00b libraries requires GCC and binutils targetting + mipsel-unknown-elf built with libgcc. The path to those binaries must be + specified in your PATH environment variable and the binaries must be + prefixed by the target architecture (ie. mipsel-unknown-elf-gcc). + + Simply run the Makefile in this directory using make (or gmake if you're + in a BSD environment). The Makefile should parse though each library + directory and run the makefile in it. + + +Documentation: + + Documentation of all the libraries are found in libn00bref.odf and it features + the same formatting as the official library documents. The document can be + exported in PDF format for easier viewing with a web browser or PDF viewer. + + +Contributing: + + Contributions are open for this project. Just obey the following rules + when making a contribution: + + * If you add new functions to libpsn00b make sure you document them in + libn00bref.odf. Documentation using Doxygen is discouraged. + * This project desires functions that interact with hardware registers to + be written in assembly language. If you decide to write your functions + that interact with hardware registers in C make sure you define your + register pointers as volatile and they must work properly when compiled + with -O2 optimization. + * Functions must work flawlessly on both emulators and real hardware. + * Don't forget to put your user name in the readme file of the library + you've made a contribution on and details of what you've added/modified. + * New functions that are not originally in the official SDK must be marked + as original code in both the library headers and the libn00bref document. + + +Library to-do list: + + Since the PSn00bSDK project still a work in progress, essential libraries + for CD and controllers support are not yet created but are high priority. + + libc - Yet to include a complete C standard function + + psxcd - CD library. Not much progress as getting the CD controller to + cooperate has been one heck of a force to be reckoned with. + Gave up with my repeated attempts with no success. Absolutely + huge props to anyone who can figure out how to use the CD + controller properly! -Lameguy64 + + psxpad - Pad/tap/gun library. No work has been done on it currently. + Supporting the Konami Justifier can be ignored as the way how + that lightgun works is pretty crude and likely going to be + awful to implement. Namco's Guncon is a lot simpler to + implement. + + psxpress - MDEC library. No work has been done on it currently. libpress + from the official libraries also contains functions for + encoding SPU compatible ADPCM data from raw PCM samples. + + Before implementing CD and controller support a better interrupt handling + scheme must be implemented as it would save a lot of trouble. Details + regarding this interrupt handler implementation can be found in psxgpu's + readme document.
\ No newline at end of file |
