license*.dat
disasm
*.json
+comport.txt
+sintab.S
+tools/gensin
-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)
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)
-include $(dep)
+sintab.S: tools/gensin
+ tools/gensin >$@
+
%.s: %.c
$(CC) $(CFLAGS) -S -o $@ $<
.PHONY: runiso
runiso: $(iso)
mednafen $(cue)
+
+.PHONY: runpsx
+runpsx: $(bin)
+ nops /exe $(bin) /m /dev/ttyUSB0
+
+tools/gensin: tools/gensin.c
+ cc -o $@ $< -lm
#ifndef GPU_H_
#define GPU_H_
-typedef short int16_t;
-typedef unsigned long uint32_t;
+#include <stdint.h>
/* flat vertex */
struct gpu_vert {
--- /dev/null
+#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:
--- /dev/null
+#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_ */
--- /dev/null
+#ifndef LIBC_STDDEF_H_
+#define LIBC_STDDEF_H_
+
+typedef int ssize_t;
+typedef unsigned int size_t;
+
+#endif /* LIBC_STDDEF_H_ */
--- /dev/null
+#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_ */
--- /dev/null
+#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;
+}
--- /dev/null
+#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_ */
--- /dev/null
+#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:
--- /dev/null
+#ifndef LIBC_SYSCALL_H_
+#define LIBC_SYSCALL_H_
+
+int sys_entercrit(void);
+void sys_exitcrit(void);
+
+#endif /* LIBC_SYSCALL_H_ */
#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);
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;
}
--- /dev/null
+#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_ */
--- /dev/null
+#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;
+}