forked from arti/vt1200
91 lines
3.4 KiB
C
91 lines
3.4 KiB
C
/*
|
|
* vidstream.c -- terminal side of the VT1200 video stream (startup skeleton).
|
|
*
|
|
* Task 3 only: claim the working set with ONE malloc at startup and publish
|
|
* where it landed. The receive ring (Task 4) and the blit loop (Task 5) build
|
|
* on the pointer this file leaves behind.
|
|
*
|
|
* Marker layout. The design plan names markers as 0x01810020, 0x01810024,
|
|
* 0x01810030, ... Those cannot be read literally as bit addresses: the
|
|
* TMS34010 is bit-addressed, so 0x01810024 is FOUR BITS after 0x01810020,
|
|
* inside the same 32-bit cell. They are byte offsets into the marker page
|
|
* (bit 0x01810000, byte 0x00302000), which is the only reading under which
|
|
* the plan's 4-byte spacing holds. So a named marker 0x018100NN lives at
|
|
*
|
|
* bit 0x01810000 + NN * 8
|
|
*
|
|
* (POOL_PTR = 0x01810100, POOL_FREE before/after = 0x01810120/0x01810140).
|
|
* vidstream.lua uses the same rule. See the task-3 report.
|
|
*
|
|
* K&R C only: no prototypes, no '//', declarations before statements.
|
|
*/
|
|
#include "romapi.h"
|
|
#include "poolcfg.h" /* POOL_BYTES, written by build-stream.sh */
|
|
|
|
#define MARK_PAGE 0x01810000 /* bit address of the marker page */
|
|
#define POOL_PTR (MARK_PAGE + 0x20 * 8) /* u32 bit pointer to the pool */
|
|
#define POOL_FREEB (MARK_PAGE + 0x24 * 8) /* u32 heap free bytes, before */
|
|
#define POOL_FREEA (MARK_PAGE + 0x28 * 8) /* u32 heap free bytes, after */
|
|
#define VID_ALIVE (MARK_PAGE + 0x2c * 8) /* u32 heartbeat while spinning */
|
|
|
|
#define HEAP_FREE 0x1E8BA0 /* firmware free-byte counter, IN BITS */
|
|
#define MARK 0x01A00000 /* .text must end before this bit address */
|
|
|
|
#define STATIC_BYTES 249856 /* the designed working set, 244 KB */
|
|
|
|
/*
|
|
* Static fallback. pool_static is global so the linker map names it and the
|
|
* MAME check can assert the exact address a failed malloc falls back to.
|
|
* stack_cushion and the five VRAM words below sit between it and ENTRY.ASM's
|
|
* _cstack: TMS34010 pushes grow downward, so the 4 KB stack spills into those
|
|
* 4 KB, never into the pool.
|
|
*/
|
|
unsigned int pool_static[STATIC_BYTES / 4];
|
|
unsigned int stack_cushion[1024];
|
|
|
|
/*
|
|
* VRAM.ASM's externals. vram.asm is linked into every payload in this
|
|
* directory; the C side owns the values. Task 5 fills the blit_* words.
|
|
*/
|
|
unsigned int vram_pattern;
|
|
unsigned int blit_src, blit_sptch, blit_daddr, blit_dydx;
|
|
|
|
/*
|
|
* The firmware's free-space counter is a 32-bit count IN BITS at
|
|
* 0x1E8BA0 (dwt/notes/HEAP.md). POOL_FREE reports bytes, because the
|
|
* marker is for humans and the check compares against POOL_BYTES.
|
|
*/
|
|
static unsigned int heap_bytes()
|
|
{
|
|
return *(unsigned int *)HEAP_FREE / 8;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
unsigned int before, after, ptr;
|
|
|
|
*(unsigned int *)VID_ALIVE = 0;
|
|
*(unsigned int *)POOL_PTR = 0;
|
|
*(unsigned int *)POOL_FREEB = 0;
|
|
*(unsigned int *)POOL_FREEA = 0;
|
|
|
|
before = heap_bytes();
|
|
ptr = malloc_(POOL_BYTES); /* malloc_ takes BYTES, returns BITS */
|
|
after = heap_bytes();
|
|
|
|
if (ptr == 0) {
|
|
/* The fallback is the 244 KB static pool by definition; a larger
|
|
* request still reports the failure through the low-bit flag. */
|
|
ptr = (unsigned int)pool_static;
|
|
*(unsigned int *)POOL_FREEB = before | 1;
|
|
} else {
|
|
*(unsigned int *)POOL_FREEB = before;
|
|
}
|
|
*(unsigned int *)POOL_FREEA = after;
|
|
*(unsigned int *)POOL_PTR = ptr; /* publish last: readers see a complete record */
|
|
|
|
for (;;) {
|
|
*(unsigned int *)VID_ALIVE = *(unsigned int *)VID_ALIVE + 1;
|
|
}
|
|
}
|