aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLameguy64 <lameguy64@gmail.com>2021-10-25 10:51:50 +0800
committerLameguy64 <lameguy64@gmail.com>2021-10-25 10:51:50 +0800
commit538f28cfbbbb8163ab8a96de77d6887123856c81 (patch)
treea3108f05c038d0f43f2e96ae4d2d34ce4da225b4
parent7718b576b7aba725455ce510ee9632067a65f0d7 (diff)
downloadpsn00bsdk-538f28cfbbbb8163ab8a96de77d6887123856c81.tar.gz
Added indev directory
-rw-r--r--changelog.txt6
-rw-r--r--indev/README.md28
-rw-r--r--indev/psxmdec/data.s6
-rw-r--r--indev/psxmdec/main.c191
-rw-r--r--indev/psxmdec/makefile41
-rw-r--r--indev/psxmdec/mdec.s185
-rw-r--r--indev/psxmdec/output.bullschitbin0 -> 43200 bytes
-rw-r--r--indev/psxmdec/table.h102
-rw-r--r--indev/psxmdec/vlc.c305
-rw-r--r--indev/psxpad/card.s377
-rw-r--r--indev/psxpad/main.c399
-rw-r--r--indev/psxpad/makefile39
-rw-r--r--indev/psxpad/pad.s264
13 files changed, 1943 insertions, 0 deletions
diff --git a/changelog.txt b/changelog.txt
index 3d7ee97..a7861b9 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -2,6 +2,12 @@ PSn00bSDK changelog
Items that are lower in the log are more recently implemented.
+10-25-2021 by Lameguy64:
+
+* Made a very tiny change in the readme file.
+
+* Included some of the indev directory from the SVN repository.
+
10-17-2021 by spicyjpeg:
diff --git a/indev/README.md b/indev/README.md
new file mode 100644
index 0000000..2064a36
--- /dev/null
+++ b/indev/README.md
@@ -0,0 +1,28 @@
+# The indev directory
+
+This directory is intended to contain work-in-progress SDK components
+(libraries, tools, etc) that are still in prototype stage. These files are
+not to be compiled in a typical SDK installation but is added into the
+main repo as the redundant SVN repo on the Lameguy64 website will soon be
+retired. Contributed components that are in work-in-progress status may
+also go into this directory.
+
+## Lameguy's indev components
+
+* psxmdec: Prototype component for performing BS image decoding using the
+ MDEC. Unfortunately I only got as far as returning garbled pixels from
+ the MDEC, which was pretty bull.
+
+* libpad: The early beginnings of a pad/card library using routines that
+ accesses the pad/card interfaces directly. Ideally PSn00bSDK's pad library
+ should include the functionality of pad/tap/gun peripherals into one
+ library as well as include functions for reading and writing memory card
+ sectors. Routines and callback hooks for directly controlling the pad/card
+ interface should also be provided to support homebrewn peripherals.
+
+ The Github release of this work-in-progress component includes delay
+ corrections for PAL consoles.
+
+Work-in-progress components such as psxcd, interlace-exp, xptest and partest
+are not included, as the former was completed while the remaining latter are
+merely scrap test programs. \ No newline at end of file
diff --git a/indev/psxmdec/data.s b/indev/psxmdec/data.s
new file mode 100644
index 0000000..adf825a
--- /dev/null
+++ b/indev/psxmdec/data.s
@@ -0,0 +1,6 @@
+.section .data
+
+.global bs_data
+.type bs_data, @object
+bs_data:
+ .incbin "output.bullschit"
diff --git a/indev/psxmdec/main.c b/indev/psxmdec/main.c
new file mode 100644
index 0000000..c9fd678
--- /dev/null
+++ b/indev/psxmdec/main.c
@@ -0,0 +1,191 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include <psxgte.h>
+#include <psxgpu.h>
+
+/* mdec.s */
+extern void mdec_reset( void );
+extern void mdec_setscale( void );
+extern void mdec_setquants( void );
+extern void mdec_cmd( unsigned int cmd );
+extern void mdec_in( void *src, int blocks );
+extern void mdec_out( void *dst, int blocks );
+
+/* vlc.c */
+int DecDCTvlc( unsigned short *mdec_bs, unsigned short *mdec_rl );
+
+/* data.s */
+extern unsigned short bs_data[];
+
+DISPENV disp[2];
+DRAWENV draw[2];
+int db;
+
+void memory_browser(unsigned int addr)
+{
+ int i,j,key;
+ unsigned char *ptr,*pptr;
+
+ while(1)
+ {
+ /* Set cursor position to top-left */
+ printf("\033[1;1H");
+ printf("MEMVIEW 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF");
+
+ ptr = (unsigned char*)addr;
+
+ /* Print contents from current location of memory */
+ for(j=0; j<23; j++)
+ {
+ printf("\n%04X: ", (unsigned int)ptr);
+ pptr = ptr;
+ for(i=0; i<16; i++)
+ {
+ printf("%02X ", *ptr);
+ ptr++;
+ }
+ printf(" ");
+ for(i=0; i<16; i++)
+ {
+ if(( *pptr < 32 ) || ( *pptr > 127 ) )
+ {
+ printf(".");
+ }
+ else
+ {
+ printf("%c", *pptr);
+ }
+ pptr++;
+ }
+ }
+
+ /* Parse input */
+ while(1)
+ {
+ key = getchar();
+ if( key == 0x1B )
+ {
+ key = getchar();
+
+ if( key == 0x5B )
+ {
+ key = getchar();
+ if( key == 0x41 ) // Up
+ {
+ addr -= 16;
+ break;
+ }
+ else if( key == 0x42 ) // Down
+ {
+ addr += 16;
+ break;
+ }
+ if( key == 0x35 ) // Page up
+ {
+ addr -= 16*23;
+ break;
+ }
+ else if( key == 0x36 ) // Page down
+ {
+ addr += 16*23;
+ break;
+ }
+ }
+ }
+
+ }
+ }
+
+} /* memory_browser */
+
+void init( void )
+{
+ ResetGraph( 0 );
+
+ SetDefDispEnv( &disp[0], 0, 0, 320, 240 );
+ SetDefDispEnv( &disp[1], 0, 240, 320, 240 );
+
+ SetDefDrawEnv( &draw[0], 0, 240, 320, 240 );
+ SetDefDrawEnv( &draw[1], 0, 0, 320, 240 );
+
+ draw[0].isbg = draw[1].isbg = 1;
+ setRGB0( &draw[0], 0, 63, 0 );
+ setRGB0( &draw[1], 0, 63, 0 );
+
+ PutDispEnv( &disp[1] );
+ PutDrawEnv( &draw[1] );
+ db = 0;
+
+} /* init */
+
+void display( void )
+{
+ DrawSync( 0 );
+ VSync( 0 );
+
+ PutDispEnv( &disp[db] );
+ PutDrawEnv( &draw[db] );
+ SetDispMask( 1 );
+
+ db = !db;
+
+} /* display */
+
+void decode_test( void )
+{
+ unsigned short *out_buff;
+ unsigned short *dec_buff;
+ int dec_len;
+ RECT rect;
+ int xx;
+
+ out_buff = (unsigned short*)malloc( 131072 );
+ dec_buff = (unsigned short*)malloc( 7680 );
+
+ memset( out_buff, 0, 131072 );
+ DecDCTvlc( bs_data, out_buff );
+
+ dec_len = ((unsigned short*)out_buff)[0];
+
+ printf( "out_buff=%p len=%d\n", out_buff, dec_len );
+
+ //memory_browser( (unsigned int)(out_buff+2) );
+ mdec_cmd( 0x38000000|dec_len );
+
+ mdec_in( out_buff+2, 8 );
+
+ rect.x = 320; rect.y = 0;
+ rect.w = 16; rect.h = 240;
+ xx = 0;
+ //while( xx < 320 )
+ {
+ mdec_out( dec_buff, 120 );
+ LoadImage( &rect, (unsigned int*)dec_buff );
+ DrawSync( 0 );
+ xx += 16;
+ rect.x += 16;
+ }
+
+} /* decode_test */
+
+int main( int argc, const char *argv[] )
+{
+ init();
+
+ /* init MDEC */
+ mdec_reset();
+ mdec_setscale();
+ mdec_setquants();
+
+ decode_test();
+
+ while( 1 )
+ {
+ display();
+ }
+
+ return( 0 );
+
+} /* main */
diff --git a/indev/psxmdec/makefile b/indev/psxmdec/makefile
new file mode 100644
index 0000000..3b921e0
--- /dev/null
+++ b/indev/psxmdec/makefile
@@ -0,0 +1,41 @@
+include ../../psn00bsdk-setup.mk
+
+TARGET = mdectest.elf
+
+CFILES = $(notdir $(wildcard *.c))
+CPPFILES = $(notdir $(wildcard *.cpp))
+AFILES = $(notdir $(wildcard *.s))
+
+OFILES = $(addprefix build/,$(CFILES:.c=.o)) \
+ $(addprefix build/,$(CPPFILES:.cpp=.o)) \
+ $(addprefix build/,$(AFILES:.s=.o))
+
+LIBS = -lpsxgpu -lpsxgte -lpsxspu -lpsxetc -lpsxapi -lc
+
+CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections
+
+CPPFLAGS = $(CFLAGS) -fno-exceptions
+
+AFLAGS = -g -msoft-float
+
+LDFLAGS = -g -Ttext=0x80010000 -gc-sections \
+ -T $(GCC_BASE)/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x
+
+all: $(OFILES)
+ $(LD) $(LDFLAGS) $(LIBDIRS) $(OFILES) $(LIBS) -o $(TARGET)
+ elf2x -q $(TARGET)
+
+build/%.o: %.c
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
+
+build/%.o: %.cpp
+ @mkdir -p $(dir $@)
+ $(CXX) $(AFLAGS) $(INCLUDE) -c $< -o $@
+
+build/%.o: %.s
+ @mkdir -p $(dir $@)
+ $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@
+
+clean:
+ rm -rf build $(TARGET) $(TARGET:.elf=.exe) \ No newline at end of file
diff --git a/indev/psxmdec/mdec.s b/indev/psxmdec/mdec.s
new file mode 100644
index 0000000..a7b5094
--- /dev/null
+++ b/indev/psxmdec/mdec.s
@@ -0,0 +1,185 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.section .text
+
+.global mdec_reset # Resets the MDEC
+.type mdec_reset, @function
+mdec_reset:
+
+ lui $a0, IOBASE
+
+ lui $v0, 0xE000 # Reset MDEC
+ sw $v0, MDEC1($a0)
+ nop
+
+ lui $v1, 0x8004 # Wait until reset completes
+.Lreset_wait:
+ lw $v0, MDEC1($a0)
+ nop
+ bne $v0, $v1, .Lreset_wait
+ nop
+
+ jr $ra
+ nop
+
+
+.global mdec_cmd # Sends a MDEC command word
+.type mdec_cmd, @function
+mdec_cmd:
+
+ lui $a1, IOBASE
+
+.Lcmd_ready: # Wait until command busy is zero
+ lw $v0, MDEC1($a1)
+ lui $v1, 0x2000
+ and $v0, $v1
+ bnez $v0, .Lcmd_ready
+ nop
+
+ sw $a0, MDEC0($a1) # Write command word
+
+ jr $ra
+ nop
+
+.global mdec_in # Transmit data to DMA0 (MDEC in)
+.type mdec_in, @function
+mdec_in:
+
+ # a0 - data source address
+ # a1 - blocks to transfer (64 bytes per block)
+
+ lui $a3, IOBASE
+
+.Lmdec_in_wait: # Wait until MDEC is ready for data
+ lw $v0, MDEC1($a3)
+ lui $v1, 0x1000
+ and $v0, $v1
+ beqz $v0, .Lmdec_in_wait
+ nop
+
+ sw $a0, D0_MADR($a3) # Set source address
+
+ andi $v0, $a1, 0xFFFF # Set transfer length
+ sll $v0, 16
+ ori $v0, 0x20 # 32 word block size
+ sw $v0, D0_BCR($a3)
+
+ lui $v0, 0x0100 # Begin transfer
+ ori $v0, 0x0201
+ sw $v0, D0_CHCR($a3)
+
+ jr $ra
+ nop
+
+.global mdec_out # Transmit data to DMA0 (MDEC in)
+.type mdec_out, @function
+mdec_out:
+
+ # a0 - data source address
+ # a1 - blocks to transfer (64 bytes per block)
+
+ lui $a3, IOBASE
+
+.Lmdec_out_ready: # Wait until MDEC is ready for data
+ lw $v0, MDEC1($a3)
+ lui $v1, 0x1000
+ and $v0, $v1
+ beqz $v0, .Lmdec_out_ready
+ nop
+
+ sw $a0, D1_MADR($a3) # Set source address
+
+ andi $v0, $a1, 0xFFFF # Set transfer length
+ sll $v0, 16
+ ori $v0, 0x20 # 32 word block size
+ sw $v0, D1_BCR($a3)
+
+ lui $v0, 0x0100 # Begin transfer
+ ori $v0, 0x0200
+ sw $v0, D1_CHCR($a3)
+
+.Lmdec_out_wait:
+ lw $v0, D1_CHCR($a3)
+ lui $v1, 0x0200
+ and $v0, $v1
+ bnez $v0, .Lmdec_out_wait
+ nop
+
+ jr $ra
+ nop
+
+.global mdec_setscale # Uploads the internal scaletable to MDEC
+.type mdec_setscale, @function
+mdec_setscale:
+
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ lui $a0, 0x6000 # Set scaletable command
+ jal mdec_cmd
+ nop
+
+ la $a0, _mdec_scaletable # Upload scaletable
+ jal mdec_in
+ li $a1, 1 # 64 halfwords
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+.global mdec_setquants # Uploads the internal quant tables
+.type mdec_setquants, @function
+mdec_setquants:
+
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ lui $a0, 0x4000 # Set quant tables command
+ ori $a0, 0x0001 # luma + chroma data
+ jal mdec_cmd
+ nop
+
+ la $a0, _mdec_qtables # Upload quant tables
+ jal mdec_in
+ li $a1, 2 # 128 halfwords
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+.section .data
+
+_mdec_qtables:
+ # taken from CCITT Rec. T.81
+ .hword 16, 11, 10, 16, 24, 40, 51, 61 # Luma table
+ .hword 12, 12, 14, 19, 26, 58, 60, 55
+ .hword 14, 13, 16, 24, 40, 57, 69, 56
+ .hword 14, 17, 22, 29, 51, 87, 80, 62
+ .hword 18, 22, 37, 56, 68, 109, 103, 77
+ .hword 24, 35, 55, 64, 81, 104, 113, 92
+ .hword 49, 64, 78, 87, 103, 121, 120, 101
+ .hword 72, 92, 95, 98, 112, 100, 103, 99
+ .hword 17, 18, 24, 47, 99, 99, 99, 99 # Chroma table
+ .hword 18, 21, 26, 66, 99, 99, 99, 99
+ .hword 24, 26, 56, 99, 99, 99, 99, 99
+ .hword 47, 66, 99, 99, 99, 99, 99, 99
+ .hword 99, 99, 99, 99, 99, 99, 99, 99
+ .hword 99, 99, 99, 99, 99, 99, 99, 99
+ .hword 99, 99, 99, 99, 99, 99, 99, 99
+ .hword 99, 99, 99, 99, 99, 99, 99, 99
+
+_mdec_scaletable:
+ .hword 0x5A82,0x5A82,0x5A82,0x5A82,0x5A82,0x5A82,0x5A82,0x5A82
+ .hword 0x7D8A,0x6A6D,0x471C,0x18F8,0xE707,0xB8E3,0x9592,0x8275
+ .hword 0x7641,0x30FB,0xCF04,0x89BE,0x89BE,0xCF04,0x30FB,0x7641
+ .hword 0x6A6D,0xE707,0x8275,0xB8E3,0x471C,0x7D8A,0x18F8,0x9592
+ .hword 0x5A82,0xA57D,0xA57D,0x5A82,0x5A82,0xA57D,0xA57D,0x5A82
+ .hword 0x471C,0x8275,0x18F8,0x6A6D,0x9592,0xE707,0x7D8A,0xB8E3
+ .hword 0x30FB,0x89BE,0x7641,0xCF04,0xCF04,0x7641,0x89BE,0x30FB
+ .hword 0x18F8,0xB8E3,0x6A6D,0x8275,0x7D8A,0x9592,0x471C,0xE707
diff --git a/indev/psxmdec/output.bullschit b/indev/psxmdec/output.bullschit
new file mode 100644
index 0000000..4229da0
--- /dev/null
+++ b/indev/psxmdec/output.bullschit
Binary files differ
diff --git a/indev/psxmdec/table.h b/indev/psxmdec/table.h
new file mode 100644
index 0000000..3e50b18
--- /dev/null
+++ b/indev/psxmdec/table.h
@@ -0,0 +1,102 @@
+const static huff_t table0[]={
+ {6,3},{8,5},{10,6},{12,8},{76,9},{66,9},{20,11},{58,13},{48,13},{38,13},{32,13},{52,14},{50,14},{48,14},{46,14},{62,15},{60,15},{58,15},{56,15},{54,15},{52,15},{50,15},{48,15},{46,15},{44,15},{42,15},{40,15},{38,15},{36,15},{34,15},{32,15},{48,16},{46,16},{44,16},{42,16},{40,16},{38,16},{36,16},{34,16},{32,16},
+};
+const static huff_t table1[]={
+ {6,4},{12,7},{74,9},{24,11},{54,13},{44,14},{42,14},{62,16},{60,16},{58,16},{56,16},{54,16},{52,16},{50,16},{38,17},{36,17},{34,17},{32,17},
+};
+const static huff_t table2[]={
+ {10,5},{8,8},{22,11},{40,13},{40,14},
+};
+const static huff_t table3[]={
+ {14,6},{72,9},{56,13},{38,14},
+};
+const static huff_t table4[]={
+ {12,6},{30,11},{36,13},
+};
+const static huff_t table5[]={
+ {14,7},{18,11},{36,14},
+};
+const static huff_t table6[]={
+ {10,7},{60,13},{40,17},
+};
+const static huff_t table7[]={
+ {8,7},{42,13},
+};
+const static huff_t table8[]={
+ {14,8},{34,13},
+};
+const static huff_t table9[]={
+ {10,8},{34,14},
+};
+const static huff_t table10[]={
+ {78,9},{32,14},
+};
+const static huff_t table11[]={
+ {70,9},{52,17},
+};
+const static huff_t table12[]={
+ {68,9},{50,17},
+};
+const static huff_t table13[]={
+ {64,9},{48,17},
+};
+const static huff_t table14[]={
+ {28,11},{46,17},
+};
+const static huff_t table15[]={
+ {26,11},{44,17},
+};
+const static huff_t table16[]={
+ {16,11},{42,17},
+};
+const static huff_t table17[]={
+ {62,13},
+};
+const static huff_t table18[]={
+ {52,13},
+};
+const static huff_t table19[]={
+ {50,13},
+};
+const static huff_t table20[]={
+ {46,13},
+};
+const static huff_t table21[]={
+ {44,13},
+};
+const static huff_t table22[]={
+ {62,14},
+};
+const static huff_t table23[]={
+ {60,14},
+};
+const static huff_t table24[]={
+ {58,14},
+};
+const static huff_t table25[]={
+ {56,14},
+};
+const static huff_t table26[]={
+ {54,14},
+};
+const static huff_t table27[]={
+ {62,17},
+};
+const static huff_t table28[]={
+ {60,17},
+};
+const static huff_t table29[]={
+ {58,17},
+};
+const static huff_t table30[]={
+ {56,17},
+};
+const static huff_t table31[]={
+ {54,17},
+};
+const static huff_t *huff_table[]={
+ table0,table1,table2,table3,table4,table5,table6,table7,table8,table9,table10,table11,table12,table13,table14,table15,table16,table17,table18,table19,table20,table21,table22,table23,table24,table25,table26,table27,table28,table29,table30,table31,
+};
+const static int maxlevel[]={
+ 40,18,5,4,3,3,3,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+};
diff --git a/indev/psxmdec/vlc.c b/indev/psxmdec/vlc.c
new file mode 100644
index 0000000..bc64a12
--- /dev/null
+++ b/indev/psxmdec/vlc.c
@@ -0,0 +1,305 @@
+#include <sys/types.h>
+
+typedef unsigned short Uint16;
+typedef unsigned int Uint32;
+
+typedef struct {
+ unsigned int code,nbits;
+} huff_t;
+
+#include "table.h"
+
+#define CODE1(a,b,c) (((a)<<10)|((b)&0x3ff)|((c)<<16))
+/* run, level, bit */
+#define CODE(a,b,c) CODE1(a,b,c+1),CODE1(a,-b,c+1)
+#define CODE0(a,b,c) CODE1(a,b,c),CODE1(a,b,c)
+#define CODE2(a,b,c) CODE1(a,b,c+1),CODE1(a,b,c+1)
+#define RUNOF(a) ((a)>>10)
+#define VALOF(a) ((short)((a)<<6)>>6)
+#define BITOF(a) ((a)>>16)
+#define EOB 0xfe00
+#define ESCAPE_CODE CODE1(63,0,6)
+#define EOB_CODE CODE1(63,512,2)
+
+/*
+ DC code
+ Y U,V
+0 100 00 0
+1 00x 01x -1,1
+2 01xx 10xx -3,-2,2,3
+3 101xxx 110xxx -7..-4,4..7
+4 110xxxx 1110 -15..-8,8..15
+5 1110xxxxx 11110 -31..-16,16..31
+6 11110xxxxxx 111110 -63..-32,32..63
+7 111110 1111110 -127..-64,64..127
+8 1111110 11111110 -255..-128,128..255
+ 7+8 8+8
+*/
+
+/*
+ This table based on MPEG2DEC by MPEG Software Simulation Group
+*/
+
+/* Table B-14, DCT coefficients table zero,
+* codes 0100 ... 1xxx (used for all other coefficients)
+*/
+static const Uint32 VLCtabnext[12*2] = {
+ CODE(0,2,4), CODE(2,1,4), CODE2(1,1,3), CODE2(1,-1,3),
+ CODE0(63,512,2), CODE0(63,512,2), CODE0(63,512,2), CODE0(63,512,2), /*EOB*/
+ CODE2(0,1,2), CODE2(0,1,2), CODE2(0,-1,2), CODE2(0,-1,2)
+};
+
+/* Table B-14, DCT coefficients table zero,
+* codes 000001xx ... 00111xxx
+*/
+static const Uint32 VLCtab0[60*2] = {
+ CODE0(63,0,6), CODE0(63,0,6),CODE0(63,0,6), CODE0(63,0,6), /* ESCAPE */
+ CODE2(2,2,7), CODE2(2,-2,7), CODE2(9,1,7), CODE2(9,-1,7),
+ CODE2(0,4,7), CODE2(0,-4,7), CODE2(8,1,7), CODE2(8,-1,7),
+ CODE2(7,1,6), CODE2(7,1,6), CODE2(7,-1,6), CODE2(7,-1,6),
+ CODE2(6,1,6), CODE2(6,1,6), CODE2(6,-1,6), CODE2(6,-1,6),
+ CODE2(1,2,6), CODE2(1,2,6), CODE2(1,-2,6), CODE2(1,-2,6),
+ CODE2(5,1,6), CODE2(5,1,6), CODE2(5,-1,6), CODE2(5,-1,6),
+ CODE(13,1,8), CODE(0,6,8), CODE(12,1,8), CODE(11,1,8),
+ CODE(3,2,8), CODE(1,3,8), CODE(0,5,8), CODE(10,1,8),
+ CODE2(0,3,5), CODE2(0,3,5), CODE2(0,3,5), CODE2(0,3,5),
+ CODE2(0,-3,5), CODE2(0,-3,5), CODE2(0,-3,5), CODE2(0,-3,5),
+ CODE2(4,1,5), CODE2(4,1,5), CODE2(4,1,5), CODE2(4,1,5),
+ CODE2(4,-1,5), CODE2(4,-1,5), CODE2(4,-1,5), CODE2(4,-1,5),
+ CODE2(3,1,5), CODE2(3,1,5), CODE2(3,1,5), CODE2(3,1,5),
+ CODE2(3,-1,5), CODE2(3,-1,5), CODE2(3,-1,5), CODE2(3,-1,5)
+};
+
+/* Table B-14, DCT coefficients table zero,
+* codes 0000001000 ... 0000001111
+*/
+static const Uint32 VLCtab1[8*2] = {
+ CODE(16,1,10), CODE(5,2,10), CODE(0,7,10), CODE(2,3,10),
+ CODE(1,4,10), CODE(15,1,10), CODE(14,1,10), CODE(4,2,10)
+};
+
+/* Table B-14/15, DCT coefficients table zero / one,
+* codes 000000010000 ... 000000011111
+*/
+static const Uint32 VLCtab2[16*2] = {
+ CODE(0,11,12), CODE(8,2,12), CODE(4,3,12), CODE(0,10,12),
+ CODE(2,4,12), CODE(7,2,12), CODE(21,1,12), CODE(20,1,12),
+ CODE(0,9,12), CODE(19,1,12), CODE(18,1,12), CODE(1,5,12),
+ CODE(3,3,12), CODE(0,8,12), CODE(6,2,12), CODE(17,1,12)
+};
+
+/* Table B-14/15, DCT coefficients table zero / one,
+* codes 0000000010000 ... 0000000011111
+*/
+static const Uint32 VLCtab3[16*2] = {
+ CODE(10,2,13), CODE(9,2,13), CODE(5,3,13), CODE(3,4,13),
+ CODE(2,5,13), CODE(1,7,13), CODE(1,6,13), CODE(0,15,13),
+ CODE(0,14,13), CODE(0,13,13), CODE(0,12,13), CODE(26,1,13),
+ CODE(25,1,13), CODE(24,1,13), CODE(23,1,13), CODE(22,1,13)
+};
+
+/* Table B-14/15, DCT coefficients table zero / one,
+* codes 00000000010000 ... 00000000011111
+*/
+static const Uint32 VLCtab4[16*2] = {
+ CODE(0,31,14), CODE(0,30,14), CODE(0,29,14), CODE(0,28,14),
+ CODE(0,27,14), CODE(0,26,14), CODE(0,25,14), CODE(0,24,14),
+ CODE(0,23,14), CODE(0,22,14), CODE(0,21,14), CODE(0,20,14),
+ CODE(0,19,14), CODE(0,18,14), CODE(0,17,14), CODE(0,16,14)
+};
+
+/* Table B-14/15, DCT coefficients table zero / one,
+* codes 000000000010000 ... 000000000011111
+*/
+static const Uint32 VLCtab5[16*2] = {
+ CODE(0,40,15), CODE(0,39,15), CODE(0,38,15), CODE(0,37,15),
+ CODE(0,36,15), CODE(0,35,15), CODE(0,34,15), CODE(0,33,15),
+ CODE(0,32,15), CODE(1,14,15), CODE(1,13,15), CODE(1,12,15),
+ CODE(1,11,15), CODE(1,10,15), CODE(1,9,15), CODE(1,8,15)
+};
+
+/* Table B-14/15, DCT coefficients table zero / one,
+* codes 0000000000010000 ... 0000000000011111
+*/
+static const Uint32 VLCtab6[16*2] = {
+ CODE(1,18,16), CODE(1,17,16), CODE(1,16,16), CODE(1,15,16),
+ CODE(6,3,16), CODE(16,2,16), CODE(15,2,16), CODE(14,2,16),
+ CODE(13,2,16), CODE(12,2,16), CODE(11,2,16), CODE(31,1,16),
+ CODE(30,1,16), CODE(29,1,16), CODE(28,1,16), CODE(27,1,16)
+};
+
+/*
+ DC code
+ Y U,V
+0 100 00 0
+1 00x 01x -1,1
+2 01xx 10xx -3,-2,2,3
+3 101xxx 110xxx -7..-4,4..7
+4 110xxxx 1110xxxx -15..-8,8..15
+5 1110xxxxx 11110xxxxx -31..-16,16..31
+6 11110xxxxxx 111110xxxxxx -63..-32,32..63
+7 111110xxxxxxx 1111110xxxxxxx -127..-64,64..127
+8 1111110xxxxxxxx 11111110xxxxxxxx -255..-128,128..255
+*/
+
+static const Uint32 DC_Ytab0[48] = {
+ CODE1(0,-1,3),CODE1(0,-1,3),CODE1(0,-1,3),CODE1(0,-1,3),
+ CODE1(0,-1,3),CODE1(0,-1,3),CODE1(0,-1,3),CODE1(0,-1,3),
+ CODE1(0,1,3),CODE1(0,1,3),CODE1(0,1,3),CODE1(0,1,3),
+ CODE1(0,1,3),CODE1(0,1,3),CODE1(0,1,3),CODE1(0,1,3),
+
+ CODE1(0,-3,4),CODE1(0,-3,4),CODE1(0,-3,4),CODE1(0,-3,4),
+ CODE1(0,-2,4),CODE1(0,-2,4),CODE1(0,-2,4),CODE1(0,-2,4),
+ CODE1(0,2,4),CODE1(0,2,4),CODE1(0,2,4),CODE1(0,2,4),
+ CODE1(0,3,4),CODE1(0,3,4),CODE1(0,3,4),CODE1(0,3,4),
+
+ CODE1(0,0,3),CODE1(0,0,3),CODE1(0,0,3),CODE1(0,0,3),
+ CODE1(0,0,3),CODE1(0,0,3),CODE1(0,0,3),CODE1(0,0,3),
+ CODE1(0,-7,6),CODE1(0,-6,6),CODE1(0,-5,6),CODE1(0,-4,6),
+ CODE1(0,4,6),CODE1(0,5,6),CODE1(0,6,6),CODE1(0,7,6),
+
+};
+
+static const Uint32 DC_UVtab0[56] = {
+ CODE1(0,0,2),CODE1(0,0,2),CODE1(0,0,2),CODE1(0,0,2),
+ CODE1(0,0,2),CODE1(0,0,2),CODE1(0,0,2),CODE1(0,0,2),
+ CODE1(0,0,2),CODE1(0,0,2),CODE1(0,0,2),CODE1(0,0,2),
+ CODE1(0,0,2),CODE1(0,0,2),CODE1(0,0,2),CODE1(0,0,2),
+
+ CODE1(0,-1,3),CODE1(0,-1,3),CODE1(0,-1,3),CODE1(0,-1,3),
+ CODE1(0,-1,3),CODE1(0,-1,3),CODE1(0,-1,3),CODE1(0,-1,3),
+ CODE1(0,1,3),CODE1(0,1,3),CODE1(0,1,3),CODE1(0,1,3),
+ CODE1(0,1,3),CODE1(0,1,3),CODE1(0,1,3),CODE1(0,1,3),
+
+ CODE1(0,-3,4),CODE1(0,-3,4),CODE1(0,-3,4),CODE1(0,-3,4),
+ CODE1(0,-2,4),CODE1(0,-2,4),CODE1(0,-2,4),CODE1(0,-2,4),
+ CODE1(0,2,4),CODE1(0,2,4),CODE1(0,2,4),CODE1(0,2,4),
+ CODE1(0,3,4),CODE1(0,3,4),CODE1(0,3,4),CODE1(0,3,4),
+
+ CODE1(0,-7,6),CODE1(0,-6,6),CODE1(0,-5,6),CODE1(0,-4,6),
+ CODE1(0,4,6),CODE1(0,5,6),CODE1(0,6,6),CODE1(0,7,6),
+};
+
+#define DCTSIZE2 64
+
+/* decode one intra coded MPEG-1 block */
+
+#define Show_Bits(N) (bitbuf>>(32-(N)))
+/* 最小有効bit 17 bit*/
+
+#define Flush_Buffer(N) {bitbuf <<=(N);incnt +=(N);while(incnt>=0) {bitbuf |= Get_Word()<<incnt;incnt-=16;}}
+
+#define Init_Buffer() {bitbuf = (mdec_bs[0]<<16)|(mdec_bs[1]);mdec_bs+=2;incnt = -16;}
+
+#define Get_Word() (*mdec_bs++)
+#define Printf printf
+
+int DecDCTvlc(Uint16 *mdec_bs,Uint16 *mdec_rl)
+{
+/* Uint16 *mdec_bs = mdecbs,*mdec_rl = mdecrl */
+ Uint16 *rl_end;
+ Uint32 bitbuf;
+ int incnt; /* 16-有効bit数 x86=char risc = long */
+ int q_code;
+ int type,n;
+ int last_dc[3];
+
+/* BS_HDR Uint16 rlsize,magic,ver,q_scale */
+
+ /* printf("%04x,%04x,",mdec_bs[0],mdec_bs[1]); */
+ *(long*)mdec_rl=*(long*)mdec_bs;
+ mdec_rl+=2;
+ rl_end = mdec_rl+(int)mdec_bs[0]*2;
+ q_code = (mdec_bs[2]<<10); /* code = q */
+ type = mdec_bs[3];
+ mdec_bs+=4;
+
+ Init_Buffer();
+
+ n = 0;
+ last_dc[0]=last_dc[1]=last_dc[2] = 0;
+ while(mdec_rl<rl_end) {
+ Uint32 code2;
+ /* DC */
+ if (type==2) {
+ code2 = Show_Bits(10)|(10<<16); /* DC code */
+ } else {
+ code2 = Show_Bits(6);
+ if (n>=2) {
+ /* Y */
+ if (code2<48) {
+ code2 = DC_Ytab0[code2];
+ code2 = (code2&0xffff0000)|((last_dc[2]+=VALOF(code2)*4)&0x3ff);
+ } else {
+ int nbit,val;
+ int bit = 3;
+ while(Show_Bits(bit)&1) { bit++;}
+ bit++;
+ nbit = bit*2-1;
+ val = Show_Bits(nbit)&((1<<bit)-1);
+ if ((val&(1<<(bit-1)))==0)
+ val -= (1<<bit)-1;
+ val = (last_dc[2]+=val*4);
+ code2 = (nbit<<16) | (val&0x3ff);
+ }
+ /* printf("%d ",last_dc[2]); */
+ } else {
+ /* U,V */
+ if (code2<56) {
+ code2 = DC_UVtab0[code2];
+ code2 = (code2&0xffff0000)|((last_dc[n]+=VALOF(code2)*4)&0x3ff);
+ } else {
+ int nbit,val;
+ int bit = 4;
+ while(Show_Bits(bit)&1) { bit++;}
+ nbit = bit*2;
+ val = Show_Bits(nbit)&((1<<bit)-1);
+ if ((val&(1<<(bit-1)))==0)
+ val -= (1<<bit)-1;
+ val = (last_dc[n]+=val*4);
+ code2 = (nbit<<16) | (val&0x3ff);
+ }
+ /* printf("%d ",last_dc[n]); */
+ }
+ if (++n==6) n=0;
+ }
+ /* printf("%d ",VALOF(code2)); */
+ code2 |= q_code;
+
+ /* AC */
+ while(mdec_rl<rl_end){
+/* Uint32 code; */
+#define code code2
+#define SBIT 17
+ *mdec_rl++=code2;
+ Flush_Buffer(BITOF(code2));
+ code = Show_Bits(SBIT);
+ if (code>=1<<(SBIT- 2)) {
+ code2 = VLCtabnext[(code>>12)-8];
+ if (code2==EOB_CODE) break;
+ }
+ else if (code>=1<<(SBIT- 6)) {
+ code2 = VLCtab0[(code>>8)-8];
+ if (code2==ESCAPE_CODE) {
+ Flush_Buffer(6); /* ESCAPE len */
+ code2 = Show_Bits(16)| (16<<16);
+ }
+ }
+ else if (code>=1<<(SBIT- 7)) code2 = VLCtab1[(code>>6)-16];
+ else if (code>=1<<(SBIT- 8)) code2 = VLCtab2[(code>>4)-32];
+ else if (code>=1<<(SBIT- 9)) code2 = VLCtab3[(code>>3)-32];
+ else if (code>=1<<(SBIT-10)) code2 = VLCtab4[(code>>2)-32];
+ else if (code>=1<<(SBIT-11)) code2 = VLCtab5[(code>>1)-32];
+ else if (code>=1<<(SBIT-12)) code2 = VLCtab6[(code>>0)-32];
+ else {
+ do {
+ *mdec_rl++=EOB;
+ } while(mdec_rl<rl_end);
+ return 0;
+ }
+ }
+ *mdec_rl++=code2; /* EOB code */
+ Flush_Buffer(2); /* EOB bitlen */
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/indev/psxpad/card.s b/indev/psxpad/card.s
new file mode 100644
index 0000000..2732194
--- /dev/null
+++ b/indev/psxpad/card.s
@@ -0,0 +1,377 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.section .text
+
+_CardCSum:
+
+ # a0 - base csum
+ # a1 - data pointer
+ # a2 - length
+
+ lbu $v0, 0($a1)
+ addi $a2, -1
+ xor $a0, $v0
+ bgtz $a2, _CardCSum
+ addiu $a1, 1
+
+ jr $ra
+ move $v0, $a0
+
+
+.global _CardWrite
+.type _CardWrite, @function
+_CardWrite:
+
+ # a0 - port number
+ # a1 - pointer to 128 byte buffer
+ # a2 - sector number
+
+ # return values:
+ # 0 - ok
+ # 1 - no device
+ # 2 - timeout
+ # 3 - bad checksum
+ # 4 - bad sector
+
+ # note: you must wait at least two vsyncs between each sector write
+
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ lui $t0, IOBASE
+
+ li $v0, 0x1003 # TX Enable, Joypad port select
+ andi $a0, 1
+ sll $a0, 13
+ or $v0, $a0 # Select port 2 if a0 is 1
+
+ sh $v0, JOY_CTRL($t0) # Set to Joypad control interface
+
+ jal _wait # Delay for analog pads
+ li $v0, 310 # (needs optimization testing)
+
+# May cause issues with third party adapters such as Brook wireless
+#.Lread_empty_fifo_write: # Flush the RX FIFO just in case
+# lbu $v1, JOY_TXRX($t0)
+# lhu $v0, JOY_STAT($t0)
+# nop
+# andi $v0, 0x2
+# bnez $v0, .Lread_empty_fifo_write
+# nop
+
+ lhu $v1, JOY_CTRL($t0)
+ nop
+ or $v1, 0x10
+ sh $v1, JOY_CTRL($t0)
+
+ jal _CardExchng # Send device check byte
+ li $a0, 0x81
+ andi $v1, $v0, 0x100 # No card if exchange timed out
+ bnez $v1, .Lno_device_write
+ addiu $v0, $0 , 1
+
+ jal _wait # 1st exchange needs 27microsec after ACK
+ li $v0, 190 # (e.g. 7 as usual + an extra 20)
+
+ jal _CardExchng # Send write command
+ li $a0, 0x57
+ andi $v1, $v0, 0x100 # No card if exchange timed out
+ bnez $v1, .Lno_device_write
+ addiu $v0, $0 , 1
+
+ jal _CardExchng # Receive card ID bytes
+ move $a0, $0
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lwrite_timeout
+ addiu $v0, $0 , 2
+ jal _CardExchng
+ move $a0, $0
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lwrite_timeout
+ addiu $v0, $0 , 2
+
+ jal _CardExchng # Send address bytes
+ srl $a0, $a2, 8
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lwrite_timeout
+ addiu $v0, $0 , 2
+ jal _CardExchng
+ andi $a0, $a2, 0xFF
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lwrite_timeout
+ addiu $v0, $0 , 2
+
+ srl $t1, $a2, 8 # Checksum address by MSB xor LSB
+ andi $v0, $a2, 0xFF
+ xor $t1, $v0
+
+ move $a2, $0 # Send data and compute checksum
+.Lwrite_loop:
+ lbu $a0, 0($a1)
+ addiu $a1, 1
+ jal _CardExchng
+ xor $t1, $a0
+ addiu $a2, 1
+ blt $a2, 128, .Lwrite_loop
+ nop
+
+ jal _CardExchng # Send checksum byte
+ move $a0, $t1
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lwrite_timeout
+ addiu $v0, $0 , 2
+
+ jal _CardExchng # Receive card acknowledge bytes
+ move $a0, $0
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lwrite_timeout
+ addiu $v0, $0 , 2
+ jal _CardExchng
+ move $a0, $0
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lwrite_timeout
+ addiu $v0, $0 , 2
+
+ sb $0 , JOY_TXRX($t0) # Gets end byte
+ nop
+.Lsend_wait_end_write:
+ lhu $v0, JOY_STAT($t0)
+ nop
+ andi $v0, 0x6
+ bne $v0, 0x6, .Lsend_wait_end_write
+ nop
+ lbu $v0, JOY_TXRX($t0)
+ nop
+
+ beq $v0, 0x4e, .Lwrite_timeout # Bad checksum
+ addiu $v0, $0 , 3
+ beq $v0, 0xff, .Lwrite_timeout # Bad sector
+ addiu $v0, $0 , 4
+
+ move $v0, $0
+
+.Lwrite_timeout:
+.Lno_device_write:
+
+ sh $0 , JOY_CTRL($t0) # Apparently required
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+.global _CardRead
+.type _CardRead, @function
+_CardRead:
+
+ # a0 - port number
+ # a1 - pointer to 128 byte buffer
+ # a2 - sector number
+
+ addiu $sp, -12
+ sw $ra, 0($sp)
+ sw $a1, 4($sp)
+ sw $a2, 8($sp)
+
+ lui $t0, IOBASE
+
+ li $v0, 0x1003 # TX Enable, Joypad port select
+ andi $a0, 1
+ sll $a0, 13
+ or $v0, $a0 # Select port 2 if a0 is 1
+
+ sh $v0, JOY_CTRL($t0) # Set to Joypad control interface
+
+ jal _wait # Delay for analog pads (needs testing)
+ li $v0, 310
+
+# May cause issues with third party adapters such as Brook wireless
+#.Lread_empty_fifo: # Flush the RX FIFO just in case
+# lbu $v1, JOY_TXRX($t0)
+# lhu $v0, JOY_STAT($t0)
+# nop
+# andi $v0, 0x2
+# bnez $v0, .Lread_empty_fifo
+# nop
+
+ lhu $v1, JOY_CTRL($t0)
+ nop
+ or $v1, 0x10
+ sh $v1, JOY_CTRL($t0)
+
+ jal _CardExchng # Send device check byte
+ li $a0, 0x81
+ andi $v1, $v0, 0x100 # No card if exchange timed out
+ bnez $v1, .Lno_device
+ addiu $v0, $0 , 1
+
+ jal _wait # 1st exchange needs 27microsec after ACK
+ li $v0, 190 # (e.g. 7 as usual + an extra 20)
+
+ jal _CardExchng # Send read command
+ li $a0, 0x52
+ andi $v1, $v0, 0x100 # No card if exchange timed out
+ bnez $v1, .Lno_device
+ addiu $v0, $0 , 2
+
+ jal _CardExchng # Receive card ID bytes
+ move $a0, $0
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lno_device
+ addiu $v0, $0 , 3
+ jal _CardExchng
+ move $a0, $0
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lno_device
+ addiu $v0, $0 , 4
+
+ jal _CardExchng # Send address
+ srl $a0, $a2, 8
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lno_device
+ addiu $v0, $0 , 5
+ jal _CardExchng
+ andi $a0, $a2, 0xFF
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lno_device
+ addiu $v0, $0 , 6
+
+ sb $0 , JOY_TXRX($t0) # Receive command acknowledge 1
+ nop
+.Lsend_wait:
+ lhu $v0, JOY_STAT($t0)
+ nop
+ andi $v0, 0x4
+ beqz $v0, .Lsend_wait
+ nop
+ move $v1, $0
+ lui $a0, 0xBFC0
+.Lwait_ack:
+ bgt $v1, 30000, .Lread_timeout
+ addiu $v0, $0, 10
+ lhu $v0, JOY_STAT($t0)
+ lw $0 , 4($a0)
+ lw $0 , 0($a0)
+ andi $v0, 0x202
+ bne $v0, 0x202, .Lwait_ack
+ addiu $v1, 1
+ lhu $v1, JOY_CTRL($t0)
+ lbu $v0, JOY_TXRX($t0)
+ or $v1, 0x10
+ sh $v1, JOY_CTRL($t0)
+
+ jal _CardExchng # Receive command acknowledge 2
+ move $a0, $0
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lno_device
+ addiu $v0, $0 , 7
+
+ jal _CardExchng # Receive confirmed address MSB
+ move $a0, $0
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lno_device
+ addiu $v0, $0 , 8
+
+ jal _CardExchng # Receive confirmed address LSB
+ move $a0, $0
+ andi $v1, $v0, 0x100
+ bnez $v1, .Lno_device
+ addiu $v0, $0 , 9
+
+ move $a2, $0
+.Ltransfer_loop:
+ jal _CardExchng
+ move $a0, $0
+ sb $v0, 0($a1)
+ addiu $a2, 1
+ blt $a2, 128, .Ltransfer_loop
+ addiu $a1, 1
+
+ jal _CardExchng # Gets checksum byte
+ move $a0, $0
+ move $a3, $v0
+
+ sb $0 , JOY_TXRX($t0) # Gets end byte
+ nop
+.Lsend_wait_end:
+ lhu $v1, JOY_STAT($t0)
+ nop
+ andi $v1, 0x6
+ bne $v1, 0x6, .Lsend_wait_end
+ nop
+ lbu $v1, JOY_TXRX($t0)
+ nop
+
+ lw $a2, 8($sp)
+ lw $a1, 4($sp)
+ andi $v1, $a2, 0xff
+ srl $a2, 8
+ xor $a0, $a2, $v1
+ jal _CardCSum
+ li $a2, 128
+
+ bne $v0, $a3, .Lno_device
+ addiu $v0, $0 , -1
+
+ move $v0, $0
+.Lread_timeout:
+.Lno_device:
+
+ sh $0 , JOY_CTRL($t0) # Apparently required
+
+ lw $ra, 0($sp)
+ addiu $sp, 12
+ jr $ra
+ nop
+
+
+.global _CardExchng
+.type _CardExchng, @function
+_CardExchng:
+
+ lui $t0, IOBASE
+
+ sb $a0, JOY_TXRX($t0)
+ nop
+.Lsend_wait_exchg:
+ lhu $v0, JOY_STAT($t0)
+ nop
+ andi $v0, 0x4
+ beqz $v0, .Lsend_wait_exchg
+ nop
+
+ lui $a0, 0xBFC0
+ move $v1, $0
+.Lwait_ack_exchg:
+ bgt $v1, 500, .Ltimeout
+ lhu $v0, JOY_STAT($t0)
+ lw $0 , 4($a0)
+ lw $0 , 0($a0)
+ andi $v0, 0x202
+ bne $v0, 0x202, .Lwait_ack_exchg
+ addiu $v1, 1
+
+ b .Ldone
+ nop
+
+.Ltimeout:
+
+ lbu $v0, JOY_TXRX($t0)
+ nop
+ b .Lexit_exchg
+ ori $v0, 0x100
+
+.Ldone:
+
+ lhu $v1, JOY_CTRL($t0)
+ lbu $v0, JOY_TXRX($t0)
+ or $v1, 0x10
+ sh $v1, JOY_CTRL($t0)
+
+.Lexit_exchg:
+
+ jr $ra
+ nop
diff --git a/indev/psxpad/main.c b/indev/psxpad/main.c
new file mode 100644
index 0000000..e8a6181
--- /dev/null
+++ b/indev/psxpad/main.c
@@ -0,0 +1,399 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <psxetc.h>
+#include <psxgte.h>
+#include <psxgpu.h>
+#include <psxapi.h>
+#include <siofs.h>
+
+#define OT_LEN 8
+
+#define SCREEN_XRES 320
+#define SCREEN_YRES 240
+
+#define CENTER_X SCREEN_XRES/2
+#define CENTER_Y SCREEN_YRES/2
+
+
+/* Display and drawing environments */
+DISPENV disp[2];
+DRAWENV draw[2];
+
+char pribuff[2][16384]; /* Primitive packet buffers */
+unsigned int ot[2][OT_LEN]; /* Ordering tables */
+char *nextpri; /* Pointer to next packet buffer offset */
+int db = 0; /* Double buffer index */
+
+
+void init() {
+
+ int i;
+
+ /* Reset GPU (also installs event handler for VSync) */
+ printf("Init GPU... ");
+ ResetGraph( 0 );
+ printf("Done.\n");
+
+
+ printf("Set video mode... ");
+
+ /* Set display and draw environment parameters */
+ SetDefDispEnv( &disp[0], 0, 0, SCREEN_XRES, SCREEN_YRES );
+ SetDefDrawEnv( &draw[0], 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES );
+ SetDefDispEnv( &disp[1], 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES );
+ SetDefDrawEnv( &draw[1], 0, 0, SCREEN_XRES, SCREEN_YRES );
+
+ //disp[0].isinter = 1; /* Enable interlace (required for hires) */
+ //disp[1].isinter = 1;
+
+ /* Set clear color, area clear and dither processing */
+ setRGB0( &draw[0], 63, 0, 127 );
+ draw[0].isbg = 1;
+ draw[0].dtd = 1;
+
+ setRGB0( &draw[1], 63, 0, 127 );
+ draw[1].isbg = 1;
+ draw[1].dtd = 1;
+
+ /* Apply the display and drawing environments */
+ PutDispEnv( &disp[1] );
+ PutDrawEnv( &draw[1] );
+
+ /* Enable video output */
+ SetDispMask( 1 );
+
+ printf("Done.\n");
+
+
+ FntLoad( 960, 0 );
+ FntOpen( 8, 16, 304, 216, 0, 100 );
+
+}
+
+extern void _InitPadDirect(void);
+extern int _PadReadDirect(int port, unsigned char *data, int len);
+extern int _CardRead(int port, unsigned char *data, int lba);
+extern int _CardWrite(int port, unsigned char *data, int lba);
+extern int _PadExchng(int byte);
+extern void _PadSetPort(int port);
+
+extern unsigned char _pad_mot_values[];
+
+unsigned char padbuff[2][34];
+
+
+char *hex_tbl = "0123456789ABCDEF";
+
+void byte2str(unsigned char *in, int bytes, char *out)
+{
+ int i;
+
+ for( i=0; i<bytes; i++ )
+ {
+ *out = hex_tbl[in[i]>>4]; out++;
+ *out = hex_tbl[in[i]&0xF]; out++;
+ }
+
+ *out = 0x0;
+}
+
+unsigned char card_buff[128];
+
+void dump_data(unsigned char *buff)
+{
+ int ix,iy;
+
+ for( iy=0; iy<8; iy++ )
+ {
+ for( ix=0; ix<16; ix++ )
+ {
+ printf( "%02x", *buff );
+ buff++;
+ }
+ printf( "\n" );
+ }
+}
+
+void TurnOnVibrators(void)
+{
+ _PadSetPort(0);
+
+ if( _PadExchng(0x01) & 0x100 )
+ {
+ ExitCriticalSection();
+ return;
+ }
+
+ if( _PadExchng(0x43) & 0x100 )
+ {
+ ExitCriticalSection();
+ return;
+ }
+
+ _PadExchng(0x00);
+ _PadExchng(0x01);
+
+ while( !(_PadExchng(0) & 0x100) );
+
+ _PadSetPort(2);
+
+ ExitCriticalSection();
+ VSync(0);
+ EnterCriticalSection();
+
+ // Set analog state
+ _PadSetPort(0);
+
+ _PadExchng(0x01);
+ _PadExchng(0x4D);
+ _PadExchng(0x00);
+
+ _PadExchng(0x00);
+ _PadExchng(0x01);
+ _PadExchng(0xFF);
+ _PadExchng(0xFF);
+ _PadExchng(0xFF);
+ _PadExchng(0xFF);
+
+ _PadSetPort(2);
+
+ ExitCriticalSection();
+ VSync(0);
+ EnterCriticalSection();
+
+ // Exit configuration mode
+ _PadSetPort(0);
+
+ _PadExchng(0x01);
+ _PadExchng(0x43);
+ _PadExchng(0x00);
+ _PadExchng(0x00);
+
+ while( !(_PadExchng(0) & 0x100) );
+
+ _PadSetPort(2);
+
+ ExitCriticalSection();
+ VSync(0);
+}
+
+void TurnOnAnalog(void)
+{
+ EnterCriticalSection();
+
+ // Enter configuration mode
+ _PadSetPort(0);
+
+ if( _PadExchng(0x01) & 0x100 )
+ {
+ ExitCriticalSection();
+ return;
+ }
+
+ if( _PadExchng(0x43) & 0x100 )
+ {
+ ExitCriticalSection();
+ return;
+ }
+
+ _PadExchng(0x00);
+ _PadExchng(0x01);
+
+ while( !(_PadExchng(0) & 0x100) );
+
+ _PadSetPort(2);
+
+ ExitCriticalSection();
+ VSync(0);
+ EnterCriticalSection();
+
+ // Set analog state
+ _PadSetPort(0);
+
+ _PadExchng(0x01);
+ _PadExchng(0x44);
+ _PadExchng(0x00);
+ _PadExchng(0x01); // 0 - analog off, 1 - analog on
+ _PadExchng(0x02);
+
+ while( !(_PadExchng(0) & 0x100) );
+
+ _PadSetPort(2);
+
+ ExitCriticalSection();
+ VSync(0);
+ EnterCriticalSection();
+
+ // Exit configuration mode
+ _PadSetPort(0);
+
+ _PadExchng(0x01);
+ _PadExchng(0x43);
+ _PadExchng(0x00);
+ _PadExchng(0x00);
+
+ while( !(_PadExchng(0) & 0x100) );
+
+ _PadSetPort(2);
+
+ ExitCriticalSection();
+ VSync(0);
+}
+
+int main(int argc, const char* argv[]) {
+
+ DR_TPAGE *tpri;
+
+ int i,j,counter=0,fd;
+ char textbuff[64];
+ char *memcard_image,*p;
+
+ /* Init graphics and stuff before doing anything else */
+ init();
+
+ _InitPadDirect();
+
+
+ /*
+ if( fsInit(115200) >= 0 )
+ {
+ printf("Loading memory card image... ");
+
+ fd = fsOpen("cardimage.bin", FS_READ|FS_BINARY);
+
+ if( fd < 0 )
+ {
+ printf("File not found\n");
+ }
+ else
+ {
+ memcard_image = (char*)malloc(131072);
+
+ fsRead(fd, memcard_image, 131072);
+
+ fsClose(fd);
+
+ printf("Done.\n");
+
+ p = memcard_image;
+ for( j=0; j<1024; j++ )
+ {
+ i = _CardWrite(0, p, j);
+ printf("Writing memory card (%d/1024)... \r", j);
+ if( i )
+ printf("\nError %d at sector %d\n", i, j);
+ p += 128;
+ // Memory cards need at least 2 vsyncs between each write
+ // apparently
+ VSync(2);
+ }
+
+ }
+ }
+ else
+ {
+ fd = -1;
+ memcard_image = NULL;
+ }
+ */
+
+ /*
+ for( j=0; j<1024; j++ )
+ {
+ memset( card_buff, 0xff, 128 );
+ i = _CardRead( 0, card_buff, j );
+
+ printf("Reading memory card (%d/1024)... \r", j);
+
+ if( i != 0 )
+ {
+ printf("\nPotential read error at sector %d\n", j);
+ }
+
+ if( fd >= 0 )
+ fsWrite(fd, (u_char*)card_buff, 128);
+
+ if( i )
+ break;
+ }
+
+ if( fd >= 0 )
+ fsClose(fd);
+
+ printf("\nSuccessfully read entire memory card\n");
+ */
+
+ /*
+ i = _CardRead( 0, card_buff, j );
+ printf("Clearing memory card FAT.\n");
+ memset( card_buff, 0xff, 128 );
+ for(j=0; j<4; j++)
+ {
+ i = _CardWrite( 0, card_buff, 4 );
+ printf("_CardWrite returned %d\n", i);
+ VSync(2);
+ }
+ */
+
+
+ TurnOnAnalog();
+ TurnOnVibrators();
+
+ /* Main loop */
+ printf("Entering loop...\n");
+
+ while(1) {
+
+ /*
+ if((counter>>4)&0x1)
+ {
+ _pad_mot_values[0] = 0xff;
+ }
+ else
+ {
+ _pad_mot_values[0] = 0x0;
+ }
+ */
+
+ i = _PadReadDirect(0, padbuff[0], 34);
+ //_PadReadDirect(1, padbuff[1], 34);
+
+ FntPrint( -1, "HELLO WORLD %d\n", counter );
+
+ byte2str( padbuff[0], i, textbuff );
+ FntPrint( -1, "P1:%s\n", textbuff );
+ //byte2str( padbuff[1], 8, textbuff );
+ //FntPrint( -1, "P2:%s\n", textbuff );
+
+ /* Clear ordering table and set start address of primitive */
+ /* buffer for next frame */
+ ClearOTagR( ot[db], OT_LEN );
+ nextpri = pribuff[db];
+
+
+
+ /* Wait for GPU and VSync */
+ FntFlush(-1);
+ DrawSync( 0 );
+ VSync( 0 );
+
+ /* Since draw.isbg is non-zero this clears the screen */
+ PutDispEnv( &disp[db] );
+ PutDrawEnv( &draw[db] );
+
+ /* Begin drawing the new frame */
+ DrawOTag( ot[db]+(OT_LEN-1) );
+
+ /* Alternate to the next buffer */
+ db = !db;
+
+ /* Increment counter for the snake animation */
+ counter++;
+
+ }
+
+ return 0;
+
+}
diff --git a/indev/psxpad/makefile b/indev/psxpad/makefile
new file mode 100644
index 0000000..ab6a733
--- /dev/null
+++ b/indev/psxpad/makefile
@@ -0,0 +1,39 @@
+include ../../examples/sdk-common.mk
+
+TARGET = libpad.elf
+
+CFILES = $(notdir $(wildcard *.c))
+CPPFILES = $(notdir $(wildcard *.cpp))
+AFILES = $(notdir $(wildcard *.s))
+
+OFILES = $(addprefix build/,$(CFILES:.c=.o) $(CPPFILES:.cpp=.o) $(AFILES:.s=.o))
+
+INCLUDE +=
+LIBDIRS +=
+
+LIBS = -lsiofs -lpsxsio -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lc
+
+CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections
+CPPFLAGS = $(CFLAGS) -fno-exceptions
+AFLAGS = -g -msoft-float
+LDFLAGS = -g -Ttext=0x80010000 -gc-sections -T $(GCC_BASE)/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x
+
+CC = $(PREFIX)gcc
+CXX = $(PREFIX)g++
+AS = $(PREFIX)as
+LD = $(PREFIX)ld
+
+all: $(OFILES)
+ $(LD) $(LDFLAGS) $(LIBDIRS) $(OFILES) $(LIBS) -o $(TARGET)
+ elf2x -q $(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) $(TARGET:.elf=.exe)
diff --git a/indev/psxpad/pad.s b/indev/psxpad/pad.s
new file mode 100644
index 0000000..0fa66aa
--- /dev/null
+++ b/indev/psxpad/pad.s
@@ -0,0 +1,264 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.section .text
+
+.global _InitPadDirect
+.type _InitPadDirect, @function
+_InitPadDirect:
+
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ lui $t0, IOBASE
+
+ # Interface setup
+ li $v0, 0x40 # Interface reset
+ sh $v0, JOY_CTRL($t0)
+ li $v0, 0x88 # 250kHz clock rate
+ sh $v0, JOY_BAUD($t0)
+ li $v0, 0x0d # 8-bit, no parity, x1 multiplier
+ sh $v0, JOY_MODE($t0)
+ li $v0, 0x1003 # JOY1, TX enabled
+ sh $v0, JOY_CTRL($t0)
+
+ jal _wait
+ li $v0, 1000
+
+ # Empty RX fifo
+.Lempty_fifo:
+ lbu $v1, JOY_TXRX($t0)
+ lhu $v0, JOY_STAT($t0)
+ nop
+ andi $v0, 0x2
+ bnez $v0, .Lempty_fifo
+ nop
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+.global _PadSetPort
+.type _PadSetPort, @function
+_PadSetPort:
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ lui $t0, IOBASE
+
+ beq $a0, 2, .Lstop_comms
+ nop
+
+ li $v0, 0x1003 # TX Enable, Joypad port select
+ andi $a0, 1
+ sll $a0, 13
+ or $v0, $a0 # Select port 2 if a0 is 1
+
+ sh $v0, JOY_CTRL($t0) # Set to Joypad control interface
+
+ jal _wait # Delay for analog pads (needs testing)
+ li $v0, 500
+
+.Lread_empty_fifo_set: # Flush the RX FIFO just in case
+ lbu $v1, JOY_TXRX($t0)
+ lhu $v0, JOY_STAT($t0)
+ nop
+ andi $v0, 0x2
+ bnez $v0, .Lread_empty_fifo_set
+ nop
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+.Lstop_comms:
+
+ sh $0 , JOY_CTRL($t0)
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+.global _PadReadDirect
+.type _PadReadDirect, @function
+_PadReadDirect:
+
+ # a0 - port number
+ # a1 - device data buffer
+ # a2 - data max length
+
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ lui $t0, IOBASE
+
+ li $v0, 0x1003 # TX Enable, Joypad port select
+ andi $a0, 1
+ sll $a0, 13
+ or $v0, $a0 # Select port 2 if a0 is 1
+
+ sh $v0, JOY_CTRL($t0) # Set to Joypad control interface
+
+ jal _wait # Delay for analog pads (needs testing)
+ li $v0, 310
+
+# May cause issues with third party adapters such as Brook wireless
+#.Lread_empty_fifo: # Flush the RX FIFO just in case
+# lbu $v1, JOY_TXRX($t0)
+# lhu $v0, JOY_STAT($t0)
+# nop
+# andi $v0, 0x2
+# bnez $v0, .Lread_empty_fifo
+# nop
+
+ jal _PadExchng # Send device check byte
+ li $a0, 0x01
+
+ andi $v1, $v0, 0x100 # No pad if exchange timed out
+ bnez $v1, .Lno_device
+ addiu $v0, $0 , 1
+
+ sb $v0, 0($a1)
+ addiu $a1, 1
+
+ jal _wait # 1st exchange needs 27microsec after ACK
+ li $v0, 190 # (e.g. 7 as usual + an extra 20)
+
+ jal _PadExchng # Send command byte
+ li $a0, 0x42
+
+ sb $v0, 0($a1)
+ addiu $a1, 1
+ addiu $a2, -2
+
+ jal _PadExchng # Send 0 for pads, 1 for multitap
+ move $a0, $0 # Read is usually 0x5A
+
+ addi $a3, $0 , 1
+
+ la $t1, _pad_mot_values
+
+.Lread_loop: # Read until buffer full, or no more data
+
+ lbu $a0, 0($t1)
+ nop
+ beqz $a0, .Lskip_mot
+ nop
+
+ jal _PadExchng
+ nop
+
+ b .Ldone_exchg
+ addiu $t1, 1
+
+.Lskip_mot:
+
+ jal _PadExchng # when ACK is no longer triggered
+ move $a0, $0
+
+.Ldone_exchg:
+
+ sb $v0, 0($a1)
+
+ andi $v0, 0x100
+ bnez $v0, .Lread_end
+ addi $a3, 1
+
+ addiu $a2, -1
+ bgtz $a2, .Lread_loop
+ addiu $a1, 1
+
+.Lread_end:
+
+ b .Lexit
+ move $v0, $a3
+
+.Lno_device:
+
+ addiu $v0, $0 , -1
+ sb $v0, 0($a1)
+
+.Lexit:
+
+ sh $0 , JOY_CTRL($t0)
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+.global _PadExchng
+.type _PadExchng, @function
+_PadExchng:
+
+ lui $t0, IOBASE
+
+ sb $a0, JOY_TXRX($t0)
+ nop
+.Lsend_wait:
+ lhu $v0, JOY_STAT($t0)
+ nop
+ andi $v0, 0x4
+ beqz $v0, .Lsend_wait
+ nop
+
+ move $v1, $0
+.Lwait_ack:
+ bgt $v1, 100, .Ltimeout
+ lhu $v0, JOY_STAT($t0)
+ nop
+ andi $v0, 0x202
+ bne $v0, 0x202, .Lwait_ack
+ addiu $v1, 1
+
+ b .Ldone
+ nop
+
+.Ltimeout:
+
+ lbu $v0, JOY_TXRX($t0)
+ nop
+ b .Lexit_exchg
+ ori $v0, 0x100
+
+.Ldone:
+
+ lhu $v1, JOY_CTRL($t0)
+ lbu $v0, JOY_TXRX($t0)
+ or $v1, 0x10
+ sh $v1, JOY_CTRL($t0)
+
+.Lexit_exchg:
+
+ jr $ra
+ nop
+
+
+.global _wait
+.type _wait, @function
+_wait:
+ addiu $v0, -1
+ bgtz $v0, _wait
+ nop
+ jr $ra
+ nop
+
+
+.section .data
+
+.global _pad_mot_values
+.type _pad_mot_values, @object
+_pad_mot_values:
+ .byte 0 # Small motor
+ .byte 0 # Big motor
+ .byte 0
+ .byte 0
+
+