29#define PROGRAM_AT 0x2000u
30#define RESULT_AT 0x2100u
35static void fail(
const char* what,
unsigned wanted,
unsigned got)
38 printf(
" FAIL %s: want %04x got %04x\n", what, wanted, got);
41static void regWrite(uint8_t reg, uint8_t value)
47static void unlock(
void)
61static void loadProgram(
void)
63 static const uint8_t program[] = {0x02, 0x00, 0xbe, 0xef, 0xc8, 0x00,
64 0x21, 0x00, 0x02, 0xc3, 0x03, 0x40};
66 for (
unsigned i = 0; i <
sizeof(program); ++i) tms9918->vram.bytes[PROGRAM_AT + i] = program[i];
68 tms9918->vram.bytes[RESULT_AT] = 0;
69 tms9918->vram.bytes[RESULT_AT + 1] = 0;
72static uint16_t result(
void)
74 return (uint16_t)((tms9918->vram.bytes[RESULT_AT] << 8) | tms9918->vram.bytes[RESULT_AT + 1]);
80 regWrite(0x36, (uint8_t)(PROGRAM_AT >> 8));
81 regWrite(0x37, (uint8_t)(PROGRAM_AT & 0xff));
93static void loadDmaProgram(
void)
95 static const uint8_t program[] = {0x02, 0x01, 0x80, 0x08, 0x02, 0x02,
96 0x01, 0x00, 0xc4, 0x42, 0x03, 0x40};
98 for (
unsigned i = 0; i <
sizeof(program); ++i) tms9918->vram.bytes[PROGRAM_AT + i] = program[i];
101#define DMA_SRC 0x1000u
102#define DMA_DST 0x1800u
106static void dma(uint32_t src, uint32_t dst, uint8_t width, uint8_t height, uint8_t stride,
109 for (
unsigned i = 0; i < 0x400; ++i)
111 tms9918->vram.bytes[DMA_SRC + i] = (uint8_t)(0x40 + i);
112 tms9918->vram.bytes[DMA_DST + i] = 0;
115 tms9918->vram.bytes[0x8000] = (uint8_t)(src >> 8);
116 tms9918->vram.bytes[0x8001] = (uint8_t)src;
117 tms9918->vram.bytes[0x8002] = (uint8_t)(dst >> 8);
118 tms9918->vram.bytes[0x8003] = (uint8_t)dst;
119 tms9918->vram.bytes[0x8004] = width;
120 tms9918->vram.bytes[0x8005] = height;
121 tms9918->vram.bytes[0x8006] = stride;
122 tms9918->vram.bytes[0x8007] = params;
128static void expect(
const char* what, uint32_t at, uint8_t wanted)
130 if (tms9918->vram.bytes[at] != wanted) fail(what, wanted, tms9918->vram.bytes[at]);
144 if (result() != 0) fail(
"no-rate-ran", 0, result());
155 tms9918->vram.bytes[0x4100] = 0x5a;
166 if (result() != MARKER) fail(
"host-driven", MARKER, result());
173 tms9918->vram.map.wrksp[0] = 0x12;
174 tms9918->vram.map.wrksp[1] = 0x34;
197 if (result() != MARKER) fail(
"armed-not-run", MARKER, result());
205 if (result() != 0) fail(
"r56-early-run", 0, result());
209 if (result() != MARKER) fail(
"r56-not-run", MARKER, result());
224 if (result() != 0) fail(
"locked-ran", 0, result());
234 if (result() != MARKER) fail(
"relocked", MARKER, result());
240 if (result() != 0) fail(
"cleared-rate-ran", 0, result());
248 dma(DMA_SRC, DMA_DST, 4, 3, 4, 0x00);
249 expect(
"dma-run-first", DMA_DST, 0x40);
250 expect(
"dma-run-last", DMA_DST + 11, 0x4b);
251 expect(
"dma-run-past", DMA_DST + 12, 0x00);
253 dma(DMA_SRC, DMA_DST, 4, 3, 16, 0x00);
254 expect(
"dma-stride-row0", DMA_DST, 0x40);
255 expect(
"dma-stride-gap", DMA_DST + 4, 0x00);
256 expect(
"dma-stride-row1", DMA_DST + 16, 0x50);
257 expect(
"dma-stride-row2", DMA_DST + 32, 0x60);
260 dma(DMA_SRC, DMA_DST, 4, 3, 0, 0x00);
261 expect(
"dma-stride0-row0", DMA_DST, 0x40);
262 expect(
"dma-stride0-end", DMA_DST + 4, 0x00);
263 expect(
"dma-stride0-not256", DMA_DST + 256, 0x00);
267 dma(0x1100, 0x1900, 8, 2, 200, 0x00);
268 expect(
"dma-back-row0", 0x1900, 0x40);
269 expect(
"dma-back-row1", 0x18c8, 0x08);
270 expect(
"dma-back-not-forward", 0x19c8, 0x00);
273 dma(0x1100, 0x1900, 8, 2, 134, 0x00);
274 expect(
"dma-edge-fwd-row1", 0x1986, 0xc6);
275 expect(
"dma-edge-fwd-gap", 0x1985, 0x00);
277 dma(0x1100, 0x1900, 8, 2, 135, 0x00);
278 expect(
"dma-edge-back-row1", 0x1887, 0xc7);
279 expect(
"dma-edge-back-not-forward", 0x1987, 0x00);
282 dma(DMA_SRC, DMA_DST, 0, 1, 0, 0x00);
283 expect(
"dma-width256-first", DMA_DST, 0x40);
284 expect(
"dma-width256-last", DMA_DST + 255, 0x3f);
285 expect(
"dma-width256-past", DMA_DST + 256, 0x00);
288 dma(DMA_SRC, DMA_DST, 1, 0, 1, 0x00);
289 expect(
"dma-height256-first", DMA_DST, 0x40);
290 expect(
"dma-height256-last", DMA_DST + 255, 0x3f);
291 expect(
"dma-height256-past", DMA_DST + 256, 0x00);
294 dma(DMA_SRC, DMA_DST, 255, 1, 255, 0x00);
295 expect(
"dma-width255-first", DMA_DST, 0x40);
296 expect(
"dma-width255-last", DMA_DST + 254, 0x3e);
297 expect(
"dma-width255-past", DMA_DST + 255, 0x00);
299 dma(DMA_SRC, DMA_DST, 1, 255, 1, 0x00);
300 expect(
"dma-height255-first", DMA_DST, 0x40);
301 expect(
"dma-height255-last", DMA_DST + 254, 0x3e);
302 expect(
"dma-height255-past", DMA_DST + 255, 0x00);
305 dma(DMA_SRC, DMA_DST, 8, 2, 4, 0x00);
306 expect(
"dma-narrow-kept", DMA_DST + 3, 0x43);
307 expect(
"dma-narrow-rewritten", DMA_DST + 4, 0x44);
308 expect(
"dma-narrow-last", DMA_DST + 11, 0x4b);
309 expect(
"dma-narrow-past", DMA_DST + 12, 0x00);
312 dma(DMA_SRC, DMA_DST, 4, 3, 4, 0xfc);
313 expect(
"dma-params-spare-first", DMA_DST, 0x40);
314 expect(
"dma-params-spare-last", DMA_DST + 11, 0x4b);
315 expect(
"dma-params-spare-past", DMA_DST + 12, 0x00);
318 dma(0x1100, 0x1900, 4, 2, 4, 0x03);
319 expect(
"dma-fill-dec-first", 0x1900, 0x40);
320 expect(
"dma-fill-dec-row0", 0x18fd, 0x40);
321 expect(
"dma-fill-dec-row1", 0x18f9, 0x40);
322 expect(
"dma-fill-dec-past", 0x18f8, 0x00);
327 dma(DMA_SRC, DMA_SRC + 2, 8, 1, 8, 0x00);
328 expect(
"dma-overlap-0", DMA_SRC + 2, 0x40);
329 expect(
"dma-overlap-2", DMA_SRC + 4, 0x40);
330 expect(
"dma-overlap-7", DMA_SRC + 9, 0x41);
333 dma(DMA_SRC, 0xfffe, 4, 1, 4, 0x00);
334 expect(
"dma-dst-wrap-before", 0xffff, 0x41);
335 expect(
"dma-dst-wrap-after", 0x0000, 0x42);
336 expect(
"dma-dst-wrap-last", 0x0001, 0x43);
338 tms9918->vram.bytes[0xfffe] = 0x11;
339 tms9918->vram.bytes[0xffff] = 0x22;
340 tms9918->vram.bytes[0x0000] = 0x33;
341 tms9918->vram.bytes[0x0001] = 0x44;
342 dma(0xfffe, DMA_DST, 4, 1, 4, 0x00);
343 expect(
"dma-src-wrap-before", DMA_DST + 1, 0x22);
344 expect(
"dma-src-wrap-after", DMA_DST + 2, 0x33);
345 expect(
"dma-src-wrap-last", DMA_DST + 3, 0x44);
348 dma(DMA_SRC, DMA_DST, 4, 3, 16, 0x01);
349 expect(
"dma-fill-row0", DMA_DST + 3, 0x40);
350 expect(
"dma-fill-gap", DMA_DST + 4, 0x00);
351 expect(
"dma-fill-row2", DMA_DST + 32, 0x40);
354 dma(0x1100, 0x1900, 4, 2, 4, 0x02);
355 expect(
"dma-dec-row0-first", 0x1900, 0x40);
356 expect(
"dma-dec-row0-last", 0x18fd, 0x3d);
357 expect(
"dma-dec-row1-first", 0x18fc, 0x3c);
358 expect(
"dma-dec-row1-last", 0x18f9, 0x39);
359 expect(
"dma-dec-past", 0x1901, 0x00);
362 dma(0x1100, 0x1900, 4, 3, 0, 0x02);
363 expect(
"dma-dec-stride0-first", 0x1900, 0x40);
364 expect(
"dma-dec-stride0-last", 0x18fd, 0x3d);
365 expect(
"dma-dec-stride0-end", 0x18fc, 0x00);
366 expect(
"dma-dec-stride0-past", 0x1901, 0x00);
372 dma(0x1100, 0x1900, 8, 2, 200, 0x02);
373 expect(
"dma-dec-fwd-row0-first", 0x1900, 0x40);
374 expect(
"dma-dec-fwd-row0-last", 0x18f9, 0x39);
375 expect(
"dma-dec-fwd-row1-first", 0x1938, 0x78);
376 expect(
"dma-dec-fwd-row1-last", 0x1931, 0x71);
377 expect(
"dma-dec-fwd-gap", 0x1901, 0x00);
378 expect(
"dma-dec-fwd-not-back", 0x18c8, 0x00);
382 dma(0x1100, 0x1900, 8, 2, 135, 0x02);
383 expect(
"dma-dec-edge-back-row1", 0x1879, 0xb9);
384 expect(
"dma-dec-edge-back-not-forward", 0x1979, 0x00);
386 dma(0x1100, 0x1900, 8, 2, 136, 0x02);
387 expect(
"dma-dec-edge-fwd-row1", 0x1978, 0xb8);
388 expect(
"dma-dec-edge-fwd-not-back", 0x1878, 0x00);
390 printf(
"%s: library-paced GPU, %d failure(s)\n", failures ?
"FAIL" :
"PASS", failures);
391 return failures != 0;
uint16_t pico9918_gpu_status(pico9918_t *tms9918)
see the header.
uint16_t pico9918_gpu_pc(pico9918_t *tms9918)
see the header.
void pico9918_gpu_init(pico9918_t *tms9918)
Initialize the TMS9900 GPU.
uint32_t pico9918_gpu_mem_size(void)
see the header.
uint8_t pico9918_gpu_mem_value(pico9918_t *tms9918, uint32_t addr)
see the header.
uint16_t pico9918_gpu_reg_value(pico9918_t *tms9918, uint8_t reg)
see the header.
bool pico9918_gpu_step_n(pico9918_t *tms9918, uint32_t instructions)
The same pass, capped at instructions, returning true while the program still has work left.
void pico9918_gpu_set_clock(pico9918_t *tms9918, uint32_t instructionsPerSecond)
Hand GPU execution to the library, at this many instructions a second.
pico9918-core - GPU Interface
#define PICO9918_GPU_IPS_PRO
PICO9918 PRO, RP2350 at 352MHz.
#define PICO9918_GPU_ST_LGT
ST0, logical greater than.
uint8_t pico9918_vram_value(pico9918_t *tms9918, uint16_t addr)
return a value from vram
void pico9918_reset(pico9918_t *tms9918)
reset the new TMS9918
#define PICO9918_INST_ONLY
pass the instance as the only argument
#define PICO9918_INST
pass the instance ahead of other arguments
pico9918-core - the private instance layout
void pico9918_write_reg_value_impl(pico9918_t *tms9918, uint8_t regSelect, uint8_t value)
set a register from the second byte of a host register write