|
Nugget
Bare-metal libraries and examples for the original PlayStation
|
#include <stdint.h>#include "common/hardware/hwregs.h"#include "common/syscalls/syscalls.h"#include "texture-fixtures.h"#include "exotic/cester.h"
Macros | |
| #define | PCSX_TESTS 0 |
| #define | CESTER_MAYBE_TEST CESTER_TEST |
| #define | CESTER_NO_SIGNAL |
| #define | CESTER_NO_TIME |
| #define | EXIT_SUCCESS 0 |
| #define | EXIT_FAILURE 1 |
| #define | R32(a) (*(volatile uint32_t *)(a)) |
| #define | D2_MADR R32(0xbf8010a0) |
| #define | D2_BCR R32(0xbf8010a4) |
| #define | D2_CHCR R32(0xbf8010a8) |
| #define | D_DPCR R32(0xbf8010f0) |
| #define | D_DICR R32(0xbf8010f4) |
| #define | RING 16 |
| #define | SLOT_WORDS 16 |
| #define | VBLANKS 10 |
| #define | EXIT_LIMIT 2000000 |
| #define | QUAD_WORDS 12 |
| #define | QUAD_TPAGE (TEX15_TX | (2u << 7)) |
Functions | |
| CESTER_BODY (#define R32(a) #define D2_MADR #define D2_BCR #define D2_CHCR #define D_DPCR #define D_DICR #define RING #define SLOT_WORDS #define VBLANKS #define EXIT_LIMIT static uint32_t s_ring[RING *SLOT_WORDS] __attribute__((aligned(64)));struct Arm { uint32_t madr[VBLANKS+1];uint32_t chcr[VBLANKS+1];uint32_t dicr[VBLANKS+1];uint16_t written[VBLANKS+1];uint16_t laps[VBLANKS+1];uint32_t exitPolls;uint32_t exitChcr, exitMadr, exitDicr, exitIstat;};static struct Arm s_high, s_mid;static int s_interruptsWereEnabled;static uint32_t slotAddr(unsigned k) { return(uint32_t)&s_ring[k *SLOT_WORDS] &0xffffff;} #define QUAD_WORDS #define QUAD_TPAGE static void writeQuad(unsigned k, uint32_t seq) { uint32_t *p=&s_ring[k *SLOT_WORDS+1];uint32_t c=(seq *0x0f0b07u) &0x007f7f7fu;p[0]=0x3e000000|c;p[1]=0;p[2]=0;p[3]=c ^ 0x003f003f;p[4]=319;p[5]=(QUAD_TPAGE<< 16)|63;p[6]=c ^ 0x00003f3f;p[7]=239<< 16;p[8]=15<< 8;p[9]=c ^ 0x003f3f00;p[10]=(239<< 16)|319;p[11]=(15<< 8)|63;} static void buildRing(void) { for(unsigned k=0;k< RING;k++) { s_ring[k *SLOT_WORDS]=((uint32_t) QUAD_WORDS<< 24)|slotAddr((k+1) % RING);writeQuad(k, k);} } static int slotOf(uint32_t madr) { uint32_t base=slotAddr(0);madr &=0xffffff;if(madr< base) return -1;uint32_t off=(madr - base)/(SLOT_WORDS *4);return off< RING ?(int) off :-1;} static void setupGpu(void) { GPU_STATUS=0x00000000;GPU_STATUS=0x06000000|0x260|(0xc60<< 12);GPU_STATUS=0x07000000|0x010|(0x100<< 10);GPU_STATUS=0x05000000;GPU_STATUS=0x08000001;GPU_DATA=0xe1000600;GPU_DATA=0xe3000000;GPU_DATA=0xe4000000|319|(239<< 10);GPU_DATA=0xe5000000;GPU_STATUS=0x03000000;GPU_STATUS=0x04000002;} static void run(struct Arm *a, unsigned trail, const char *name) { setupGpu();uploadTex15Masked();waitGPU();buildRing();D_DPCR|=0x00000800;D_DICR=0x00840000|0x7f000000;IREG=~0x8u;D2_MADR=slotAddr(0);D2_BCR=0;D2_CHCR=0x01000401;unsigned prod=(RING - trail) % RING;int last=0;uint32_t seq=RING;unsigned written=0, laps=0;a->madr[0]=D2_MADR;a->chcr[0]=D2_CHCR;a->dicr[0]=D_DICR;a->written[0]=0;a->laps[0]=0;for(int v=1;v<=VBLANKS;v++) { IREG=~1u;while(!(IREG &1)) { int d=slotOf(D2_MADR);if(d< 0) continue;if(d< last) laps++;last=d;unsigned target=(d+RING - trail) % RING;while(prod !=target) { writeQuad(prod, seq++);prod=(prod+1) % RING;written++;} } a->madr[v]=D2_MADR;a->chcr[v]=D2_CHCR;a->dicr[v]=D_DICR;a->written[v]=written;a->laps[v]=laps;written=0;laps=0;} int d=slotOf(D2_MADR);unsigned e=((d< 0 ? 0 :d)+RING/2) % RING;s_ring[e *SLOT_WORDS]=((uint32_t) QUAD_WORDS<< 24)|0xffffff;uint32_t polls=0;while((D2_CHCR &0x01000000) &&polls< EXIT_LIMIT) polls++;a->exitPolls=polls;a->exitChcr=D2_CHCR;a->exitMadr=D2_MADR;a->exitDicr=D_DICR;a->exitIstat=IREG;if(a->exitChcr &0x01000000) D2_CHCR=0x00000401;for(int v=0;v<=VBLANKS;v++) { ramsyscall_printf("%s v=%d madr=%08x slot=%d chcr=%08x dicr=%08x written=%d laps=%d\n", name, v, a->madr[v], slotOf(a->madr[v]), a->chcr[v], a->dicr[v], a->written[v], a->laps[v]);} ramsyscall_printf("%s exit polls=%d chcr=%08x madr=%08x dicr=%08x istat=%08x\n", name, a->exitPolls, a->exitChcr, a->exitMadr, a->exitDicr, a->exitIstat);} static int allBusy(const struct Arm *a) { for(int v=0;v<=VBLANKS;v++) if(!(a->chcr[v] &0x01000000)) return 0;return 1;} static unsigned minWritten(const struct Arm *a) { unsigned m=0xffff;for(int v=2;v<=VBLANKS;v++) if(a->written[v]< m) m=a->written[v];return m;} static unsigned totalLaps(const struct Arm *a) { unsigned n=0;for(int v=1;v<=VBLANKS;v++) n+=a->laps[v];return n;}) CESTER_BEFORE_ALL(gpudmaring | |
| CESTER_AFTER_ALL (CESTER_MAYBE_TEST(gpudmaring, D2_CHCR=0x00000401;GPU_STATUS=0x00000000;if(s_interruptsWereEnabled) leaveCriticalSection();) | |
Variables | |
| s_interruptsWereEnabled = enterCriticalSection() | |
| IMASK = 0 | |
| run & | s_high |
| run & | s_mid |
| #define CESTER_MAYBE_TEST CESTER_TEST |
| #define CESTER_NO_SIGNAL |
| #define CESTER_NO_TIME |
| #define D2_BCR R32(0xbf8010a4) |
| #define D2_CHCR R32(0xbf8010a8) |
| #define D2_MADR R32(0xbf8010a0) |
| #define D_DICR R32(0xbf8010f4) |
| #define D_DPCR R32(0xbf8010f0) |
| #define EXIT_FAILURE 1 |
| #define EXIT_LIMIT 2000000 |
| #define EXIT_SUCCESS 0 |
| #define PCSX_TESTS 0 |
| #define QUAD_TPAGE (TEX15_TX | (2u << 7)) |
| #define QUAD_WORDS 12 |
| #define R32 | ( | a | ) | (*(volatile uint32_t *)(a)) |
| #define RING 16 |
| #define SLOT_WORDS 16 |
| #define VBLANKS 10 |
| CESTER_AFTER_ALL | ( | CESTER_MAYBE_TEST( | gpudmaring, |
| D2_CHCR | = 0x00000401; GPU_STATUS = 0x00000000; if (s_interruptsWereEnabled) leaveCriticalSection(); |
||
| ) |
| CESTER_BODY | ( | #define R32(a) #define D2_MADR #define D2_BCR #define D2_CHCR #define D_DPCR #define D_DICR #define RING #define SLOT_WORDS #define VBLANKS #define EXIT_LIMIT static uint32_t s_ring __attribute__((aligned(64)));struct Arm { uint32_t madr[VBLANKS+1];uint32_t chcr[VBLANKS+1];uint32_t dicr[VBLANKS+1];uint16_t written[VBLANKS+1];uint16_t laps[VBLANKS+1];uint32_t exitPolls;uint32_t exitChcr, exitMadr, exitDicr, exitIstat;};static struct Arm | s_high[RING *SLOT_WORDS], |
| s_mid;static int s_interruptsWereEnabled;static uint32_t slotAddr(unsigned k) { return(uint32_t)&s_ring[k *SLOT_WORDS] &0xffffff;} #define QUAD_WORDS #define QUAD_TPAGE static void writeQuad(unsigned k, uint32_t seq) { uint32_t *p=&s_ring[k *SLOT_WORDS+1];uint32_t c=(seq *0x0f0b07u) &0x007f7f7fu;p[0]=0x3e000000|c;p[1]=0;p[2]=0;p[3]=c ^ 0x003f003f;p[4]=319;p[5]=(QUAD_TPAGE<< 16)|63;p[6]=c ^ 0x00003f3f;p[7]=239<< 16;p[8]=15<< 8;p[9]=c ^ 0x003f3f00;p[10]=(239<< 16)|319;p[11]=(15<< 8)|63;} static void buildRing(void) { for(unsigned k=0;k< RING;k++) { s_ring[k *SLOT_WORDS]=((uint32_t) QUAD_WORDS<< 24)|slotAddr((k+1) % RING);writeQuad(k, k);} } static int slotOf(uint32_t madr) { uint32_t base=slotAddr(0);madr &=0xffffff;if(madr< base) return -1;uint32_t off=(madr - base)/(SLOT_WORDS *4);return off< RING ?(int) off :-1;} static void setupGpu(void) { GPU_STATUS=0x00000000;GPU_STATUS=0x06000000|0x260|(0xc60<< 12);GPU_STATUS=0x07000000|0x010|(0x100<< 10);GPU_STATUS=0x05000000;GPU_STATUS=0x08000001;GPU_DATA=0xe1000600;GPU_DATA=0xe3000000;GPU_DATA=0xe4000000|319|(239<< 10);GPU_DATA=0xe5000000;GPU_STATUS=0x03000000;GPU_STATUS=0x04000002;} static void run(struct Arm *a, unsigned trail, const char *name) { setupGpu();uploadTex15Masked();waitGPU();buildRing();D_DPCR|=0x00000800;D_DICR=0x00840000|0x7f000000;IREG=~0x8u;D2_MADR=slotAddr(0);D2_BCR=0;D2_CHCR=0x01000401;unsigned prod=(RING - trail) % RING;int last=0;uint32_t seq=RING;unsigned written=0, laps=0;a->madr[0]=D2_MADR;a->chcr[0]=D2_CHCR;a->dicr[0]=D_DICR;a->written[0]=0;a->laps[0]=0;for(int v=1;v<=VBLANKS;v++) { IREG=~1u;while(!(IREG &1)) { int d=slotOf(D2_MADR);if(d< 0) continue;if(d< last) laps++;last=d;unsigned target=(d+RING - trail) % RING;while(prod !=target) { writeQuad(prod, seq++);prod=(prod+1) % RING;written++;} } a->madr[v]=D2_MADR;a->chcr[v]=D2_CHCR;a->dicr[v]=D_DICR;a->written[v]=written;a->laps[v]=laps;written=0;laps=0;} int d=slotOf(D2_MADR);unsigned e=((d< 0 ? 0 :d)+RING/2) % RING;s_ring[e *SLOT_WORDS]=((uint32_t) QUAD_WORDS<< 24)|0xffffff;uint32_t polls=0;while((D2_CHCR &0x01000000) &&polls< EXIT_LIMIT) polls++;a->exitPolls=polls;a->exitChcr=D2_CHCR;a->exitMadr=D2_MADR;a->exitDicr=D_DICR;a->exitIstat=IREG;if(a->exitChcr &0x01000000) D2_CHCR=0x00000401;for(int v=0;v<=VBLANKS;v++) { ramsyscall_printf("%s v=%d madr=%08x slot=%d chcr=%08x dicr=%08x written=%d laps=%d\n", name, v, a->madr[v], slotOf(a->madr[v]), a->chcr[v], a->dicr[v], a->written[v], a->laps[v]);} ramsyscall_printf("%s exit polls=%d chcr=%08x madr=%08x dicr=%08x istat=%08x\n", name, a->exitPolls, a->exitChcr, a->exitMadr, a->exitDicr, a->exitIstat);} static int allBusy(const struct Arm *a) { for(int v=0;v<=VBLANKS;v++) if(!(a->chcr[v] &0x01000000)) return 0;return 1;} static unsigned minWritten(const struct Arm *a) { unsigned m=0xffff;for(int v=2;v<=VBLANKS;v++) if(a->written[v]< m) m=a->written[v];return m;} static unsigned totalLaps(const struct Arm *a) { unsigned n=0;for(int v=1;v<=VBLANKS;v++) n+=a->laps[v];return n;} | |||
| ) |
| IMASK = 0 |
| run& s_high |
| s_interruptsWereEnabled = enterCriticalSection() |
| run& s_mid |