Files
TeslaRel410/sda4/DPL3/VRENDER/DNC.C
T
CydandClaude Fable 5 db7745fcd0 sda4: commit the Glaze developer hard-drive dump
Un-ignored: the dev drive is the ground truth the restoration and
emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer
source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio
content). Kept in-repo for the pod-owner community.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 19:41:15 -05:00

767 lines
17 KiB
C++

/*{{{ header*/
/****************************************************************************/
/* */
/* DIVISION */
/* -------- */
/* */
/* (C) Copyright 1990 DIVISION Limited */
/* */
/****************************************************************************/
/*
PROJECT: --
SUBSYSTEM: TTM100 860 RPC KERNEL
MODULE: dnet
FILE: dnc.c
AUTHOR: PJA
DATE: 8th feb 1991
*/
/*}}} */
/*{{{ function*/
/*
FUNCTION:- dNet communications support for i860
*/
/*}}} */
/*{{{ includes and externs*/
extern void _lockCCB(void);
extern void _freeCCB(void);
/* extern int command_no; */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dpltypes.h"
#include "cm200io.h"
extern Set();
extern dnc_Wait_count(void *, int);
#define start_transaction(t,n) \
_lockCCB(); \
Wait (&output_ccb->lock ); \
output_ccb->command_type = t; \
output_ccb->command_no = n; \
output_ccb->ack = 1
#define end_transaction() \
Wait (&output_ccb->ack); \
bla(100); \
_freeCCB()
/* #define end_transaction() dnc_Wait_count (&output_ccb->ack, 500) */
#define event() Set(&ioc->tevent,1)
/*}}} */
int *uncached_input_block=(int *) 0;
int *uncached_output_block=(int *) 0;
int *uncached_general_block=(int *) 0;
/* NOTE under velocirender, all data packets are <= 256 bytes */
/*{{{ void dN_send (int Dnode, int size, char *block, int sync)*/
void dN_send (int Dnode, int size, char *block, int sync)
{
/* i860 sends a block to transputer for DIVNET */
int *dptr = (int *) &output_ccb->data[0];
memcpy ( uncached_output_block, block, size );
start_transaction(IO_DNC_SEND, size);
*dptr++ = Dnode;
*dptr = (int) uncached_output_block; /* address of outgoing block */
event();
if (sync) end_transaction(); /* Wait for Ack from TP */
}
/*}}} */
/*{{{ void dN_receive (int *Fnode, int *size, char *block, int sync )*/
void dN_receive (int *Fnode, int *size, char *block, int sync )
{
/* i860 wants a block off transputer from DIVNET */
int *dptr = (int *) &output_ccb->data[0];
start_transaction(IO_DNC_RECEIVE, *size);
/* direct input to ccb then memcpy but N O C A C H E F L U S H ! */
dptr[0] = *Fnode;
dptr[1] = (int) uncached_input_block; /* address of block */
event();
if (sync) {
end_transaction();
*size = input_ccb->command_no;
memcpy ( block, uncached_input_block, *size );
if (*Fnode == 0) {
*Fnode = input_ccb->ack;
input_ccb->ack=0;
}
}
}
/*}}} */
/*{{{ void dN_mynode (int *mynode)*/
void dN_mynode (int *mynode)
{
/* ENDHACK */
start_transaction(IO_DNC_MYID, 0);
event();
end_transaction();
*mynode = input_ccb->command_no;
}
/*}}} */
/*{{{ void dN_nodes (int *nodecnt)*/
void dN_nodes (int *nodecnt)
{
start_transaction(IO_DNC_NODES, 0);
event();
end_transaction();
*nodecnt = input_ccb->command_no;
}
/*}}} */
/*{{{ void dN_poll (int *nodecnt)*/
void dN_poll (int *ready)
{
start_transaction(IO_DNC_POLL, 0);
event();
end_transaction();
*ready = input_ccb->command_no;
}
/*}}} */
/*{{{ void dN_timer (int *tranny_clk)*/
void dN_timer (int *tranny_clk)
{
int *dptr = (int *) &input_ccb->data[0];
start_transaction(IO_TIMER, 0);
event();
end_transaction();
*tranny_clk=*dptr;
}
/*}}} */
/*{{{ void dN_wait ( int *Fnode, int *size )*/
void dN_wait ( int *Fnode, int *size )
{
end_transaction();
*size = input_ccb->command_no;
if (*Fnode == 0) {
*Fnode = input_ccb->ack;
input_ccb->ack=0;
}
}
/*}}} */
/*{{{ void dN_wait_ack ()*/
void dN_wait_ack ()
{
end_transaction();
}
/*}}} */
/*{{{ void dN_ld_run (int linkno)*/
void dN_ld_run (int linkno)
{
start_transaction(IO_LD_RUN_DRIVER, linkno);
flush();
event();
end_transaction();
}
/*}}} */
/*{{{ void dN_ld_out_noflush (int linkno, char *data, int size)*/
void dN_ld_out_noflush (int linkno, char *data, int size)
{
int *dptr = (int *) &output_ccb->data[0];
start_transaction(IO_LD_LINK_OUT, linkno);
*dptr++=(int) data;
*dptr++=size;
event();
end_transaction();
}
/*}}} */
/*{{{ void dN_ld_out (int linkno, char *data, int size)*/
void dN_ld_out (int linkno, char *data, int size)
{
int *dptr = (int *) &output_ccb->data[0];
start_transaction(IO_LD_LINK_OUT, linkno);
*dptr++=(int) data;
*dptr++=size;
flush();
event();
end_transaction();
}
/*}}} */
/*{{{ void dN_ld_ccb_out (int linkno, char *data, int size)*/
void dN_ld_ccb_out (int linkno, char *data, int size)
{
int i, ndbl=(size+7)>>3;
double *ds=(double *) data, *dd=(double *) &output_ccb->data[0];
start_transaction(IO_LD_CCB_LINK_OUT, linkno|(size<<8));
for (i=0; i<ndbl; i++ ) {
*dd++=*ds++;
}
event();
end_transaction();
}
/*}}} */
/*{{{ void dN_ld_ccb_in (int linkno, char *data, int size)*/
void dN_ld_ccb_in (int linkno, char *data, int size)
{
int *dptr = (int *) &output_ccb->data[0];
start_transaction(IO_LD_LINK_IN, linkno);
*dptr++=(int) data;
*dptr++=size;
event();
end_transaction();
}
/*}}} */
/*{{{ void dN_ld_in (int linkno, char *data, int size)*/
void dN_ld_in (int linkno, char *data, int size)
{
int *dptr = (int *) &output_ccb->data[0];
start_transaction(IO_LD_LINK_IN, linkno);
*dptr++=(int) data;
*dptr++=size;
flush();
event();
end_transaction();
}
/*}}} */
/*{{{ void dN_ld_out_2D (int linkno, char *data, int width, int stride, int length )*/
void dN_ld_out_2D (int linkno, char *data, int width, int stride, int length )
{
int *dptr = (int *) &output_ccb->data[0];
start_transaction(IO_LD_LINK_OUT_2D, linkno);
*dptr++=(int) data;
*dptr++=width;
*dptr++=stride;
*dptr++=length;
flush();
event();
end_transaction();
}
/*}}} */
/*{{{ void dN_ld_in_2D (int linkno, char *data, int width, int stride, int length )*/
void dN_ld_in_2D (int linkno, char *data, int width, int stride, int length )
{
int *dptr = (int *) &output_ccb->data[0];
start_transaction(IO_LD_LINK_IN_2D, linkno);
*dptr++=(int) data;
*dptr++=width;
*dptr++=stride;
*dptr++=length;
flush();
event();
end_transaction();
}
/*}}} */
/*{{{ int dN_ld_stat (int linkno)*/
int dN_ld_stat (int linkno)
{
int *dptr = (int *) &input_ccb->data[0];
start_transaction(IO_LD_LINK_STATUS, linkno );
event();
end_transaction();
return(*dptr);
}
/*}}} */
/*{{{ int stat ( int link )*/
static int stat ( int link )
{
return ( dN_ld_stat(link));
}
/*}}} */
/*{{{ void spin( int link )*/
void spin( int link )
{
int tries=0;
while (stat(link)!=0) {
tries++;
}
}
/*}}} */
/* pxpl5 support pja august 1993 */
#define pxpl5_init 0
#define pxpl5_dma 1
#define pxpl5_texels 2
#define pxpl5_microwords 3
#define pxpl5_microload 4
#define pxpl5_pixels 5
#define pxpl5_fx_texels 6
static int *peek_addr=NULL;
/*{{{ void dN_pxpl5_readpixels ( int *data, int x, int y, int pixels )*/
void dN_pxpl5_readpixels ( int *data, int x, int y, int pixels )
{
/*
implemented as a copy from texel store to ccb->data[5], then interrupt
tranny, pointing it at ccb->data[5], from where it copies into the texture
FIFO
*/
int *src, *dst, i, *dptr=(int *) (&output_ccb->data[0]);
/* printf ("dN_pixels waiting for ccb->lock\n" ); */
start_transaction ( IO_PXPL5, 0 );
dptr[0]=pxpl5_pixels;
dptr[1]=x;
dptr[2]=y;
dptr[3]=pixels;
dptr[4]=(int) (&dptr[5]);
Set (&ioc->tevent, 1);
end_transaction();
memcpy ( data, (char *) (&dptr[5]), 4*pixels );
}
/*}}} */
/*{{{ void dN_pxpl5_init ( int magicL, int magicR, int clk_speed )*/
void dN_pxpl5_init ( int magicL, int magicR )
{
int *dptr=(int *) (&output_ccb->data[0]);
start_transaction ( IO_PXPL5, 0 );
dptr[0]=pxpl5_init;
dptr[1]=(int) uncached_general_block;
dptr[2]=magicL;
dptr[3]=magicR;
setpxpl5VideoMode ( magicL );
Set (&ioc->tevent, 1);
end_transaction();
}
/*}}} */
/*{{{ int dN_pxpl5_dma_done ()*/
int dN_pxpl5_dma_done ()
{
int t=1;
if (peek_addr) {
t=i860_locked_read(peek_addr);
}
return t;
}
/*}}} */
/*{{{ void dN_pxpl5_dma ( int address, int *ack_address, int *end_of_texture_seq )*/
int dN_pxpl5_dma ( int address, int *ack_address,
int *end_of_texture_seq,
vfptr pre_dma )
{
int *dptr=(int *) (&output_ccb->data[0]);
int t, then, now;
/*
printf ("dN_pxpl5_dma 0x%x ack_address 0x%x\n", address, ack_address );
*/
/* hits ram every 250 blas, around 5uS */
dN_timer ( &then );
if (peek_addr)
wait_locked_nonzero ( peek_addr, 300 );
dN_timer ( &now );
peek_addr=ack_address;
if (pre_dma)
(*pre_dma)();
ack_address[0]=0;
ack_address[2]=(int) end_of_texture_seq;
/*
printf ("dN_pxpl5_dma Wait on lock\n" );
*/
start_transaction ( IO_PXPL5, 0 );
*peek_addr=0x0;
dptr[0]=pxpl5_dma;
dptr[1]=address;
dptr[2]=(int) ack_address;
Set (&ioc->tevent, 1);
end_transaction();
return (now-then);
/*
printf ("dN_pxpl5_dma got ack\n" );
*/
}
/*}}} */
/*{{{ void dN_pxpl5_texels ( int pxpl5_address, int *texelptr, int texels )*/
void dN_pxpl5_texels ( int pxpl5_address, int *texelptr, int texels )
{
/*
implemented as a copy from texel store to ccb->data[5], then interrupt
tranny, pointing it at ccb->data[5], from where it copies into the texture
FIFO
*/
int *src, *dst, i, *dptr=(int *) (&output_ccb->data[0]);
/* printf ("dN_texels waiting for ccb->lock\n" ); */
start_transaction ( IO_PXPL5, 0 );
src=texelptr;
dst=&dptr[5];
/* convert to pxpl5 algnment */
for (i=0; i<texels; i++ ) {
unsigned char *csrc=(unsigned char *) src, r, g, b;
r=0xff & csrc[3];
g=0xff & csrc[2];
b=0xff & csrc[1];
*dst++=(int) r | ((int) g) << 8 | ((int) b) << 16;
src++;
}
dptr[0]=pxpl5_texels;
dptr[1]=pxpl5_address;
dptr[2]=(int) (&dptr[5]);
dptr[3]=texels;
Set (&ioc->tevent, 1);
end_transaction();
}
/*}}} */
/*{{{ void dN_pxpl5_texture24 ( int *texture, int pxpl5_address, int edge )*/
void dN_pxpl5_texture24 ( int *texture, int pxpl5_address, int edge )
{
int texels=edge*edge;
while (texels) {
if (peek_addr)
wait_locked_nonzero ( peek_addr, 800 );
if (peek_addr)
wait_locked_nonzero ( peek_addr, 800 );
dN_pxpl5_texels ( pxpl5_address, texture, 32 );
texels-=32;
pxpl5_address+=32;
texture+=32;
}
if (peek_addr)
wait_locked_nonzero ( peek_addr, 800 );
if (peek_addr)
wait_locked_nonzero ( peek_addr, 800 );
dN_pxpl5_texels ( pxpl5_address-32, texture-32, 32 );
}
/*}}} */
/*{{{ void dN_pxpl5_fx_texels ( int pxpl5_address, int *texelptr, int texels )*/
void dN_pxpl5_fx_texels ( int pxpl5_address, int *texelptr, int texels )
{
/*
implemented as a copy from texel store to ccb->data[5], then interrupt
tranny, pointing it at ccb->data[5], from where it copies into the texture
FIFO
*/
int *src, *dst, i, *dptr=(int *) (&output_ccb->data[0]);
start_transaction ( IO_PXPL5, 0 );
src=texelptr;
dst=&dptr[5];
/* convert to pxpl5 algnment */
for (i=0; i<texels; i++ ) {
unsigned char *csrc=(unsigned char *) src, r, g, b;
r=0xff & csrc[3];
g=0xff & csrc[2];
b=0xff & csrc[1];
*dst++=(int) r | ((int) g) << 8 | ((int) b) << 16;
src++;
}
dptr[0]=pxpl5_fx_texels;
dptr[1]=pxpl5_address;
dptr[2]=(int) (&dptr[5]);
dptr[3]=texels;
Set (&ioc->tevent, 1);
end_transaction();
}
/*}}} */
/*{{{ void dN_pxpl5_fx_texture24 ( int *texture, int pxpl5_address, int edge )*/
void dN_pxpl5_fx_texture24 ( int *texture, int pxpl5_address, int edge )
{
int texels=edge*edge;
while (texels) {
if (peek_addr)
wait_locked_nonzero ( peek_addr, 800 );
if (peek_addr)
wait_locked_nonzero ( peek_addr, 800 );
dN_pxpl5_fx_texels ( pxpl5_address, texture, 32 );
texels-=32;
pxpl5_address+=32;
texture+=32;
}
if (peek_addr)
wait_locked_nonzero ( peek_addr, 800 );
}
/*}}} */
/*{{{ static void pxpl5_texels_8 ( int pxpl5_address, int *texelptr, int texels )*/
static void pxpl5_texels_8 ( int pxpl5_address, int *texelptr, int texels )
{
int *src, *dst, *dptr=(int *) (&output_ccb->data[0]);
start_transaction ( IO_PXPL5, 0 );
src=texelptr;
dst=&dptr[5];
memcpy ( dst, src, texels*sizeof(int));
dptr[0]=pxpl5_texels;
dptr[1]=pxpl5_address;
dptr[2]=(int) dst;
dptr[3]=texels;
Set (&ioc->tevent, 1);
end_transaction();
}
/*}}} */
/*{{{ static int luminize ( int texel )*/
static int luminize ( int texel )
{
/* returns a 6-bit luminance value from a 24-bit texel */
int r, g, b;
r=(texel>>24) & 0xff;
g=(texel>>16) & 0xff;
b=(texel>>8) & 0xfe;
r = ((r*13) + (b*7) + (g*44)) >> 8;
if (r > 63) r=63;
return r;
}
/*}}} */
/*{{{ void dN_pxpl5_texture8 ( int *texture, int pxpl5_address, int edge, int wrap )*/
void dN_pxpl5_texture8 ( int *texture, int pxpl5_address, int edge, int wrap )
{
int texels=0, t, s;
int *scratch=malloc(64*sizeof(int));
int *thisRow, *nextRow;
for (t=0; t<edge; t++ ) {
/*{{{ set up pointers to rows*/
thisRow = texture + (t * edge);
nextRow = thisRow + edge;
texels = 0;
if (t==(edge-1)) {
if (wrap)
nextRow=texture;
else
nextRow=thisRow;
}
/*}}} */
for (s=0; s<edge; s++ ) {
/*{{{ locals*/
int lower_left,
lower_right,
upper_left,
upper_right, t;
/*}}} */
lower_left =luminize (thisRow[s]);
lower_right=luminize (thisRow[s+1]);
upper_left =luminize (nextRow[s]);
upper_right=luminize (nextRow[s+1]);
if (s==(edge-1)) {
if (wrap) {
lower_right=luminize(thisRow[0]);
upper_right=luminize(nextRow[0]);
}
else {
lower_right=lower_left;
upper_right=upper_left;
}
}
t = lower_left;
t |= (lower_right << 6);
t |= (upper_left << 12);
t |= (upper_right << 18);
scratch[texels]=t;
texels++;
if (texels == 32) {
/*{{{ */
if (peek_addr)
wait_locked_nonzero ( peek_addr, 800 );
if (peek_addr)
wait_locked_nonzero ( peek_addr, 800 );
/*}}} */
pxpl5_texels_8 ( pxpl5_address, scratch, 32 );
pxpl5_address+=32;
texels=0;
}
}
}
/* re-send last few to flush fifo */
if (peek_addr)
wait_locked_nonzero ( peek_addr, 800 );
if (peek_addr)
wait_locked_nonzero ( peek_addr, 800 );
pxpl5_texels_8 ( pxpl5_address-32, scratch, 32 );
free(scratch);
}
/*}}} */
/*{{{ void dN_pxpl5_microwords ( int *ucode, int baseWord, int uwords )*/
void dN_pxpl5_microwords ( int *ucode, int baseWord, int uwords )
{
/*
implemented as a copy from ucode store to ccb->data[5], then interrupt
tranny, pointing it at ccb->data[5], from where it copies into the ucode
store
*/
int *dptr=(int *) (&output_ccb->data[0]);
start_transaction ( IO_PXPL5, 0 );
memcpy ( &dptr[5], ucode, uwords*sizeof(int));
dptr[0]=pxpl5_microwords;
dptr[1]=(int) (&dptr[5]);
dptr[2]=baseWord;
dptr[3]=uwords;
Set (&ioc->tevent, 1);
end_transaction();
}
/*}}} */
/*{{{ void dN_pxpl5_microcode ( int *ucode, int uwords )*/
void dN_pxpl5_microcode ( int *ucode, int uwords )
{
/* firstly send texels in 64-chunks */
int baseWord=0;
while (dN_pxpl5_dma_done() == 0)
;
while (uwords > 32) {
dN_pxpl5_microwords ( ucode, baseWord, 32 );
ucode+=32;
uwords-=32;
baseWord+=32;
}
if (uwords)
dN_pxpl5_microwords ( ucode, baseWord, uwords );
/* now tell tranny to load microcode store */
{
int *dptr=(int *) (&output_ccb->data[0]);
start_transaction ( IO_PXPL5, 0 );
dptr[0]=pxpl5_microload;
Set (&ioc->tevent, 1);
end_transaction();
}
}
/*}}} */