start using GTE, rotate triangle with MVMVA cmd 0gte-trirot
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 17 Mar 2024 05:39:50 +0000 (07:39 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 17 Mar 2024 05:39:50 +0000 (07:39 +0200)
14 files changed:
.gitignore
Makefile
src/gpu.h
src/gte.S [new file with mode: 0644]
src/gte.h [new file with mode: 0644]
src/libc/stddef.h [new file with mode: 0644]
src/libc/stdint.h [new file with mode: 0644]
src/libc/string.c [new file with mode: 0644]
src/libc/string.h [new file with mode: 0644]
src/libc/syscall.S [new file with mode: 0644]
src/libc/syscall.h [new file with mode: 0644]
src/main.c
src/sintab.h [new file with mode: 0644]
tools/gensin.c [new file with mode: 0644]

index ccff81e..5f6d04d 100644 (file)
@@ -10,3 +10,6 @@
 license*.dat
 disasm
 *.json
+comport.txt
+sintab.S
+tools/gensin
index dc59471..d0585e2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-csrc = $(wildcard src/*.c)
-ssrc = $(wildcard src/*.S)
+csrc = $(wildcard src/*.c) $(wildcard src/libc/*.c)
+ssrc = $(wildcard src/*.S) $(wildcard src/libc/*.S) sintab.S
 obj = $(csrc:.c=.o) $(ssrc:.S=.o)
 dep = $(csrc:.c=.d) $(ssrc:.S=.d)
 
@@ -16,15 +16,18 @@ AS = $(TCPREFIX)as
 LD = $(TCPREFIX)ld
 
 arch = -march=r3000 -msoft-float -mno-abicalls -mno-shared -fno-pic
+inc = -nostdinc -Isrc/libc
+opt = -O3
+dbg = -g
 
-CFLAGS = $(arch) -pedantic -Wall -g -MMD
+CFLAGS = $(arch) -pedantic -Wall $(dbg) $(opt) $(inc) -fno-strict-aliasing -MMD
 ASFLAGS = $(arch)
 LDFLAGS = -T psx.ld -print-gc-sections
 
 $(bin): $(elf)
        $(TCPREFIX)objcopy -O binary $< $@
 
-$(elf): $(obj)
+$(elf): $(obj) sintab.o
        $(LD) -o $@ $(obj) -Map link.map $(LDFLAGS)
 
 $(iso): cd/cd.xml cd/system.cnf $(bin)
@@ -32,6 +35,9 @@ $(iso): cd/cd.xml cd/system.cnf $(bin)
 
 -include $(dep)
 
+sintab.S: tools/gensin
+       tools/gensin >$@
+
 %.s: %.c
        $(CC) $(CFLAGS) -S -o $@ $<
 
@@ -56,3 +62,10 @@ run: $(bin)
 .PHONY: runiso
 runiso: $(iso)
        mednafen $(cue)
+
+.PHONY: runpsx
+runpsx: $(bin)
+       nops /exe $(bin) /m /dev/ttyUSB0
+
+tools/gensin: tools/gensin.c
+       cc -o $@ $< -lm
index 81d341f..4bfe724 100644 (file)
--- a/src/gpu.h
+++ b/src/gpu.h
@@ -1,8 +1,7 @@
 #ifndef GPU_H_
 #define GPU_H_
 
-typedef short int16_t;
-typedef unsigned long uint32_t;
+#include <stdint.h>
 
 /* flat vertex */
 struct gpu_vert {
diff --git a/src/gte.S b/src/gte.S
new file mode 100644 (file)
index 0000000..d525992
--- /dev/null
+++ b/src/gte.S
@@ -0,0 +1,16 @@
+#include <regdef.h>
+       .text
+       .set noreorder
+
+       .equ C0_SR, $12
+
+       .globl gte_init
+gte_init:
+       mfc0 t0, C0_SR
+       li t1, 0x40000000
+       or t0, t0, t1
+       jr ra
+       mtc0 t0, C0_SR          # bd
+
+
+# vi:ts=8 sts=8 sw=8 ft=mips:
diff --git a/src/gte.h b/src/gte.h
new file mode 100644 (file)
index 0000000..ff97eca
--- /dev/null
+++ b/src/gte.h
@@ -0,0 +1,74 @@
+#ifndef GTE_H_
+#define GTE_H_
+
+#include <stdint.h>
+
+struct gte_svector {
+       int16_t x, y, z, pad;
+};
+
+void gte_init(void);
+
+#define gte_loadrot(mptr)      \
+       asm volatile ( \
+               "lw $8, (%0)\n\t" \
+               "lw $9, 4(%0)\n\t" \
+               "ctc2 $8, $0\n\t" \
+               "ctc2 $9, $1\n\t" \
+               "lw $8, 8(%0)\n\t" \
+               "lw $9, 12(%0)\n\t" \
+               "ctc2 $8, $2\n\t" \
+               "lw $8, 16(%0)\n\t" \
+               "ctc2 $9, $3\n\t" \
+               "ctc2 $8, $4\n\t" \
+               : : "r"(mptr) \
+               : "$8", "$9")
+
+#define gte_loadtrans(vptr) \
+       asm volatile ( \
+               "lw $8, (%0)\n\t" \
+               "lw $9, 4(%0)\n\t" \
+               "lw $10, 8(%0)\n\t" \
+               "ctc2 $8, $5\n\t" \
+               "ctc2 $9, $6\n\t" \
+               "ctc2 $10, $7\n\t" \
+               : : "r"(vptr) \
+               : "$8", "$9", "$10")
+
+#define gte_loadsvec0(svptr) \
+       asm volatile ( \
+               "lwc2 $0, (%0)\n\t" \
+               "lwc2 $1, 4(%0)\n\t" \
+               : : "r"(svptr))
+
+#define gte_loadsvec1(svptr) \
+       asm volatile ( \
+               "lwc2 $2, (%0)\n\t" \
+               "lwc2 $3, 4(%0)\n\t" \
+               : : "r"(svptr))
+
+#define gte_loadsvec2(svptr) \
+       asm volatile ( \
+               "lwc2 $4, (%0)\n\t" \
+               "lwc2 $5, 4(%0)\n\t" \
+               : : "r"(svptr))
+
+#define gte_getvec(vptr) \
+       asm volatile ( \
+               "swc2 $25, (%0)\n\t" \
+               "swc2 $26, 4(%0)\n\t" \
+               "swc2 $27, 8(%0)\n\t" \
+               : : "r"(vptr) \
+               : "memory")
+
+#define gte_cmd_rot() \
+       asm volatile ( \
+               "nop\n\t" \
+               "cop2 0x86012\n\t")
+
+#define gte_cmd_rottrans() \
+       asm volatile ( \
+               "nop\n\t" \
+               "cop2 0x80012\n\t")
+
+#endif /* GTE_H_ */
diff --git a/src/libc/stddef.h b/src/libc/stddef.h
new file mode 100644 (file)
index 0000000..7fa572c
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef LIBC_STDDEF_H_
+#define LIBC_STDDEF_H_
+
+typedef int ssize_t;
+typedef unsigned int size_t;
+
+#endif /* LIBC_STDDEF_H_ */
diff --git a/src/libc/stdint.h b/src/libc/stdint.h
new file mode 100644 (file)
index 0000000..c5bf21d
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef LIBC_STDINT_H_
+#define LIBC_STDINT_H_
+
+typedef signed char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+
+typedef int32_t intptr_t;
+typedef uint32_t uintptr_t;
+
+#endif /* LIBC_STDINT_H_ */
diff --git a/src/libc/string.c b/src/libc/string.c
new file mode 100644 (file)
index 0000000..ac9f950
--- /dev/null
@@ -0,0 +1,68 @@
+#include <string.h>
+#include <stdint.h>
+
+static inline void memcpy_words(uint32_t *dest, const uint32_t *src, size_t n)
+{
+       while(n-- > 0) {
+               *dest++ = *src++;
+       }
+}
+
+static inline void memcpy_bytes(unsigned char *dest, const unsigned char *src, size_t n)
+{
+       while(n-- > 0) {
+               *dest++ = *src++;
+       }
+}
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+       int pre;
+       size_t nwords;
+       int dalign = (uintptr_t)dest & 3;
+       int salign = (uintptr_t)src & 3;
+       unsigned char *bdest;
+       const unsigned char *bsrc;
+       uint32_t *wdest;
+       const uint32_t *wsrc;
+
+       if(n < 4) {
+               memcpy_bytes(dest, src, n);
+               return dest;
+       }
+
+       if(dalign != 0 || salign != 0) {
+               if(dalign != salign) {
+                       /* alignment differs, copy bytes */
+                       memcpy_bytes(dest, src, n);
+                       return dest;
+               }
+
+               /* unaligned but on the same alignment, copy bytes first */
+               pre = ~dalign & 3;
+               bdest = dest;
+               bsrc = src;
+               memcpy_bytes(dest, src, pre);
+
+               wdest = (uint32_t*)((char*)dest + pre);
+               wsrc = (const uint32_t*)((char*)src + pre);
+               n -= pre;
+       } else {
+               /* both aligned */
+               wdest = dest;
+               wsrc = src;
+       }
+
+       nwords = n >> 2;
+       if(nwords) {
+               memcpy_words(wdest, wsrc, nwords);
+       }
+
+       n &= 3;
+       if(n) {
+               bdest = (unsigned char*)(wdest + nwords);
+               bsrc = (const unsigned char*)(wsrc + nwords);
+               memcpy_bytes(bdest, bsrc, n);
+       }
+       return dest;
+}
diff --git a/src/libc/string.h b/src/libc/string.h
new file mode 100644 (file)
index 0000000..642df2f
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef LIBC_STRING_H_
+#define LIBC_STRING_H_
+
+#include <stddef.h>
+
+void *memcpy(void *dest, const void *src, size_t n);
+
+#endif /* LIBC_STRING_H_ */
diff --git a/src/libc/syscall.S b/src/libc/syscall.S
new file mode 100644 (file)
index 0000000..df4ddeb
--- /dev/null
@@ -0,0 +1,22 @@
+#include <regdef.h>
+       .text
+       .set noreorder
+
+       .equ SYS_ENTERCRIT, 1
+       .equ SYS_EXITCRIT, 2
+
+       .globl sys_entercrit
+sys_entercrit:
+       li a0, SYS_ENTERCRIT
+       syscall 0
+       jr ra
+       nop
+
+       .globl sys_exitcrit
+sys_exitcrit:
+       li a0, SYS_EXITCRIT
+       syscall 0
+       jr ra
+       nop
+
+# vi:ts=8 sts=8 sw=8 ft=mips:
diff --git a/src/libc/syscall.h b/src/libc/syscall.h
new file mode 100644 (file)
index 0000000..2ae2d36
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef LIBC_SYSCALL_H_
+#define LIBC_SYSCALL_H_
+
+int sys_entercrit(void);
+void sys_exitcrit(void);
+
+#endif /* LIBC_SYSCALL_H_ */
index c247f3c..073ea1c 100644 (file)
@@ -1,14 +1,26 @@
 #include "gpu.h"
+#include "gte.h"
 #include "psxregs.h"
+#include "sintab.h"
 
-static struct gpu_gvert triangle[] = {
-       {0xff0000, 160, 16}, {0x00ff00, 32, 180}, {0x0000ff, 280, 220}
+static struct gpu_gvert triangle[] = {{0xff0000}, {0x00ff00}, {0x0000ff}};
+
+static struct gte_svector svtri[] = {
+       {-0x1000, -0x800}, {0, 0x1000}, {0x1000, -0x800}
 };
 
 int dbg;
 
 int main(void)
 {
+       int i;
+       unsigned int frame = 0;
+       int16_t rotmat[9] = {0x1000, 0, 0, 0, 0x1000, 0, 0, 0, 0x1000};
+       int trans[3] = {160, 120, 0};
+       int resv[3];
+
+       gte_init();
+
        gpu_reset();
        gpu_setmode(320, 264, 15, 50);
        gpu_display(1);
@@ -18,10 +30,31 @@ int main(void)
        gpu_cliprect(0, 0, 320, 264);
        gpu_origin(0, 0);
 
-       gpu_fillrect(0, 0, 320, 264, 0x003f00);
+       for(;;) {
+               rotmat[0] = rotmat[4] = COS(frame);
+               rotmat[1] = SIN(frame);
+               rotmat[3] = -SIN(frame);
+
+               gte_loadrot(rotmat);
+               //gte_loadtrans(trans);
+               for(i=0; i<3; i++) {
+                       gte_loadsvec0(svtri + i);
+                       gte_cmd_rot();
+                       gte_getvec(resv);
+
+                       triangle[i].x = (resv[0] >> 6) + 160;
+                       triangle[i].y = (resv[1] >> 6) + 130;
+               }
+
+               gpu_fillrect(0, 0, 320, 264, 0x202020);
+
+               gpu_draw_gouraud(GP0_GTRI, triangle, 3);
 
-       gpu_draw_gouraud(GP0_GTRI, triangle, 3);
+               for(i=0; i<100000; i++) {
+                       asm volatile("nop; nop; nop; nop");
+               }
 
-       for(;;);
+               frame++;
+       }
        return 0;
 }
diff --git a/src/sintab.h b/src/sintab.h
new file mode 100644 (file)
index 0000000..6a24b03
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef SINTAB_H_
+#define SINTAB_H_
+
+extern int sintab[];
+
+#define SINTAB_SIZE            1024
+#define SIN(x) sintab[(x) & 0x3ff]
+#define COS(x) sintab[((x) + 256) & 0x3ff]
+
+#endif /* SINTAB_H_ */
diff --git a/tools/gensin.c b/tools/gensin.c
new file mode 100644 (file)
index 0000000..2f8ddba
--- /dev/null
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <math.h>
+
+int main(void)
+{
+       int i, len, val;
+       float theta;
+
+       puts("\t.section .rodata");
+       puts("\t.globl sintab");
+       puts("sintab:");
+       fputs("\t.word ", stdout);
+       len = 14;
+       for(i=0; i<1024; i++) {
+               theta = (float)i * (M_PI * 2.0f) / 1024.0f;
+               val = (int)(sin(theta) * 4096.0f);
+               len += printf("%d", val);
+               if(len >= 75) {
+                       fputs("\n\t.word ", stdout);
+                       len = 14;
+               } else if(i < 1023) {
+                       fputs(", ", stdout);
+                       len += 2;
+               }
+       }
+       putchar('\n');
+
+       return 0;
+}