Simplify IS-CAD file output code

This commit is contained in:
Garhoogin 2025-06-02 14:51:00 -05:00 committed by GitHub
parent 3c9fc49df4
commit 5a120b2f44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 151 additions and 76 deletions

View File

@ -809,12 +809,13 @@ int ChrWriteNcg(NCGR *ncgr, BSTREAM *stream) {
}
static int ChriIsCommonWrite(NCGR *ncgr, BSTREAM *stream) {
int attrSize = ncgr->tilesX * ncgr->tilesY;
ChrWriteChars(ncgr, stream);
IscadStream cadStream;
IscadStreamCreate(&cadStream);
ChrWriteChars(ncgr, &cadStream.stream);
//write attribute for ACG
for (int i = 0; i < attrSize; i++) {
unsigned int attrSize = ncgr->tilesX * ncgr->tilesY;
for (unsigned int i = 0; i < attrSize; i++) {
unsigned char a = 0;
if (ncgr->attr != NULL) {
a = ncgr->attr[i];
@ -825,17 +826,9 @@ static int ChriIsCommonWrite(NCGR *ncgr, BSTREAM *stream) {
a |= (ncgr->nBits == 8) ? 0x10 : 0x00;
}
bstreamWrite(stream, &a, sizeof(a));
IscadStreamWrite(&cadStream, &a, sizeof(a));
}
//footer
unsigned char linkFooter[] = { 'L', 'I', 'N', 'K', 2, 0, 0, 0, 1, 0 };
unsigned char cmntFooter[] = { 'C', 'M', 'N', 'T', 2, 0, 0, 0, 1, 0 };
unsigned char modeFooter[] = { 'M', 'O', 'D', 'E', 4, 0, 0, 0, 1, 0, 0, 0 };
unsigned char sizeFooter[] = { 'S', 'I', 'Z', 'E', 4, 0, 0, 0, 0, 0, 0, 0 };
unsigned char verFooter[] = { 'V', 'E', 'R', ' ', 0, 0, 0, 0 };
unsigned char endFooter[] = { 'E', 'N', 'D', ' ', 0, 0, 0, 0 };
char *version = "";
switch (ncgr->header.format) {
case NCGR_TYPE_AC:
@ -844,10 +837,7 @@ static int ChriIsCommonWrite(NCGR *ncgr, BSTREAM *stream) {
version = "IS-ICG01"; break;
}
int linkLen = (ncgr->header.fileLink == NULL) ? 0 : strlen(ncgr->header.fileLink);
int commentLen = (ncgr->header.comment == NULL) ? 0 : strlen(ncgr->header.comment);
int mode = 0;
uint32_t mode = 0;
if (ncgr->header.format == NCGR_TYPE_AC) {
//3: 8bpp, 1: 4bpp
if (ncgr->nBits == 8) mode = 3;
@ -859,24 +849,26 @@ static int ChriIsCommonWrite(NCGR *ncgr, BSTREAM *stream) {
else mode = 8;
}
*(uint32_t *) (linkFooter + 4) = linkLen + 2;
linkFooter[9] = (unsigned char) linkLen;
*(uint32_t *) (cmntFooter + 4) = commentLen + 2;
cmntFooter[9] = (unsigned char) commentLen;
*(uint32_t *) (modeFooter + 8) = mode;
*(uint16_t *) (sizeFooter + 8) = ncgr->tilesX;
*(uint16_t *) (sizeFooter + 10) = ncgr->tilesY;
*(uint32_t *) (verFooter + 4) = strlen(version);
uint16_t sizeFooter[2];
sizeFooter[0] = ncgr->tilesX;
sizeFooter[1] = ncgr->tilesY;
bstreamWrite(stream, linkFooter, sizeof(linkFooter));
bstreamWrite(stream, ncgr->header.fileLink, linkLen);
bstreamWrite(stream, cmntFooter, sizeof(cmntFooter));
bstreamWrite(stream, ncgr->header.comment, commentLen);
bstreamWrite(stream, modeFooter, sizeof(modeFooter));
bstreamWrite(stream, sizeFooter, sizeof(sizeFooter));
bstreamWrite(stream, verFooter, sizeof(verFooter));
bstreamWrite(stream, version, strlen(version));
bstreamWrite(stream, endFooter, sizeof(endFooter));
IscadStreamStartBlock(&cadStream, "LINK");
IscadStreamWriteCountedString(&cadStream, ncgr->header.fileLink);
IscadStreamEndBlock(&cadStream);
IscadStreamStartBlock(&cadStream, "CMNT");
IscadStreamWriteCountedString(&cadStream, ncgr->header.comment);
IscadStreamEndBlock(&cadStream);
IscadWriteBlock(&cadStream, "MODE", &mode, sizeof(mode));
IscadWriteBlock(&cadStream, "SIZE", sizeFooter, sizeof(sizeFooter));
IscadWriteBlock(&cadStream, "VER ", version, strlen(version));
IscadWriteBlock(&cadStream, "END ", NULL, 0);
IscadStreamFinalize(&cadStream);
IscadStreamFlushOut(&cadStream, stream);
IscadStreamFree(&cadStream);
return 0;
}

View File

@ -690,3 +690,60 @@ void NnsStreamFree(NnsStream *stream) {
bstreamFree(&stream->blockStream);
bstreamFree(&stream->currentStream);
}
// ----- ISCAD functions
void IscadStreamCreate(IscadStream *stream) {
stream->inFooter = 0;
bstreamCreate(&stream->stream, NULL, 0);
}
void IscadStreamFree(IscadStream *stream) {
bstreamFree(&stream->stream);
}
void IscadStreamStartBlock(IscadStream *stream, const char *signature) {
stream->inFooter = 1;
stream->blockStart = stream->stream.pos;
uint32_t tmpSize = 0;
bstreamWrite(&stream->stream, signature, 4);
bstreamWrite(&stream->stream, &tmpSize, sizeof(tmpSize));
}
void IscadStreamEndBlock(IscadStream *stream) {
unsigned int blockSize = stream->stream.pos - stream->blockStart;
blockSize -= 8; // block header size
*(uint32_t *) (stream->stream.buffer + stream->blockStart + 4) = blockSize;
}
void IscadStreamFinalize(IscadStream *stream) {
//tbd
(void) stream;
}
void IscadStreamWrite(IscadStream *stream, const void *data, unsigned int len) {
bstreamWrite(&stream->stream, (void *) data, len);
}
void IscadStreamWriteCountedString(IscadStream *stream, const char *str) {
unsigned char header[2];
unsigned int len = 0;
if (str != NULL) len = strlen(str);
header[0] = 1;
header[1] = len;
IscadStreamWrite(stream, header, sizeof(header));
IscadStreamWrite(stream, str, len);
}
void IscadWriteBlock(IscadStream *stream, const char *signature, const void *data, unsigned int len) {
IscadStreamStartBlock(stream, signature);
IscadStreamWrite(stream, data, len);
IscadStreamEndBlock(stream);
}
void IscadStreamFlushOut(IscadStream *stream, BSTREAM *out) {
bstreamWrite(out, stream->stream.buffer, stream->stream.size);
}

View File

@ -70,3 +70,22 @@ void NnsStreamFinalize(NnsStream *stream);
void NnsStreamFlushOut(NnsStream *stream, BSTREAM *out);
void NnsStreamFree(NnsStream *stream);
// ----- ISCAD stream functions
typedef struct IscadStream_ {
BSTREAM stream; // file stream
int inFooter; // in footer
unsigned int blockStart; // current block starting offset
} IscadStream;
void IscadStreamCreate(IscadStream *stream);
void IscadStreamFree(IscadStream *stream);
void IscadStreamStartBlock(IscadStream *stream, const char *signature);
void IscadStreamEndBlock(IscadStream *stream);
void IscadStreamFinalize(IscadStream *stream);
void IscadStreamWrite(IscadStream *stream, const void *data, unsigned int len);
void IscadStreamWriteCountedString(IscadStream *stream, const char *str);
void IscadWriteBlock(IscadStream *stream, const char *signature, const void *data, unsigned int len);
void IscadStreamFlushOut(IscadStream *stream, BSTREAM *out);

View File

@ -713,23 +713,20 @@ int ScrWriteNsc(NSCR *nscr, BSTREAM *stream) {
return 0;
}
static int ScriIsCommonWrite(NSCR *nscr, BSTREAM *stream) {
bstreamWrite(stream, nscr->data, nscr->dataSize);
unsigned char clrfFooter[] = { 'C', 'L', 'R', 'F', 0, 0, 0, 0 };
unsigned char linkFooter[] = { 'L', 'I', 'N', 'K', 0, 0, 0, 0 };
unsigned char cmntFooter[] = { 'C', 'M', 'N', 'T', 0, 0, 0, 0, 1, 0 };
unsigned char clrcFooter[] = { 'C', 'L', 'R', 'C', 2, 0, 0, 0, 0, 0 };
unsigned char modeFooter[] = { 'M', 'O', 'D', 'E', 4, 0, 0, 0, 0, 0, 0, 0 };
unsigned char sizeFooter[] = { 'S', 'I', 'Z', 'E', 4, 0, 0, 0, 0, 0, 0, 0 };
unsigned char verFooter[] = { 'V', 'E', 'R', ' ', 0, 0, 0, 0 };
unsigned char endFooter[] = { 'E', 'N', 'D', ' ', 0, 0, 0, 0 };
static int ScriIsCommonWrite(NSCR *nscr, BSTREAM *stream) {
IscadStream cadStream;
IscadStreamCreate(&cadStream);
IscadStreamWrite(&cadStream, nscr->data, nscr->dataSize);
unsigned char clrcFooter[2];
unsigned char modeFooter[4];
//expects null terminated for ISC/ASC LINK specifically (not the others for some reason)
int linkLen = (nscr->header.fileLink == NULL) ? 0 : (strlen(nscr->header.fileLink) + 1);
int commentLen = (nscr->header.comment == NULL) ? 0 : strlen(nscr->header.comment);
char *ver = "";
const char *ver = "";
switch (nscr->header.format) {
case NSCR_TYPE_AC:
ver = "IS-ASC03"; break;
@ -737,43 +734,53 @@ static int ScriIsCommonWrite(NSCR *nscr, BSTREAM *stream) {
ver = "IS-ISC01"; break;
}
*(uint32_t *) (clrfFooter + 0x4) = (nscr->dataSize + 15) / 16;
*(uint32_t *) (linkFooter + 0x4) = linkLen;
*(uint32_t *) (cmntFooter + 0x4) = commentLen + 2;
*(uint16_t *) (clrcFooter + 0x8) = nscr->clearValue;
*(uint16_t *) (sizeFooter + 0x8) = nscr->tilesX;
*(uint16_t *) (sizeFooter + 0xA) = nscr->tilesY;
cmntFooter[0x09] = commentLen;
modeFooter[0x8] = nscr->tilesX;
modeFooter[0x9] = nscr->tilesY;
modeFooter[0xA] = (nscr->fmt == SCREENFORMAT_AFFINE) ? 1 : 0;
modeFooter[0xB] = 0x02 | (nscr->colorMode = SCREENCOLORMODE_256x1 || nscr->colorMode == SCREENCOLORMODE_256x16);
*(uint32_t *) (verFooter + 0x4) = strlen(ver);
*(uint16_t *) (clrcFooter + 0x0) = nscr->clearValue;
bstreamWrite(stream, clrfFooter, sizeof(clrfFooter));
for (unsigned int i = 0; i < (nscr->dataSize + 15) / 16; i++) {
unsigned char f = 0x00; //not clear character
bstreamWrite(stream, &f, sizeof(f));
modeFooter[0] = nscr->tilesX;
modeFooter[1] = nscr->tilesY;
modeFooter[2] = (nscr->fmt == SCREENFORMAT_AFFINE) ? 1 : 0;
modeFooter[3] = 0x02 | (nscr->colorMode = SCREENCOLORMODE_256x1 || nscr->colorMode == SCREENCOLORMODE_256x16);
IscadStreamStartBlock(&cadStream, "CLRF");
{
//write zeroed CLRF (no tile marked "unused")
unsigned int clrfSize = (nscr->dataSize + 15) / 16;
unsigned char *clrf = (unsigned char *) calloc(clrfSize, 1);
IscadStreamWrite(&cadStream, clrf, clrfSize);
free(clrf);
}
bstreamWrite(stream, linkFooter, sizeof(linkFooter));
bstreamWrite(stream, nscr->header.fileLink, linkLen);
bstreamWrite(stream, cmntFooter, sizeof(cmntFooter));
bstreamWrite(stream, nscr->header.comment, commentLen);
bstreamWrite(stream, clrcFooter, sizeof(clrcFooter));
IscadStreamEndBlock(&cadStream);
IscadWriteBlock(&cadStream, "LINK", nscr->header.fileLink, linkLen);
IscadStreamStartBlock(&cadStream, "CMNT");
IscadStreamWriteCountedString(&cadStream, nscr->header.comment);
IscadStreamEndBlock(&cadStream);
IscadWriteBlock(&cadStream, "CLRC", clrcFooter, sizeof(clrcFooter));
if (nscr->header.format == NSCR_TYPE_AC) {
//ASC: MODE footer contains the size
bstreamWrite(stream, modeFooter, sizeof(modeFooter));
IscadWriteBlock(&cadStream, "MODE", modeFooter, sizeof(modeFooter));
} else if (nscr->header.format == NSCR_TYPE_IC) {
//ISC: MODE footer does not contain the size, has separate SIZE footer
unsigned char iscModeFooter[] = { 'M', 'O', 'D', 'E', 2, 0, 0, 0, 0, 0 };
iscModeFooter[0x8] = (nscr->fmt == SCREENFORMAT_AFFINE) ? 1 : 0;
bstreamWrite(stream, iscModeFooter, sizeof(iscModeFooter));
bstreamWrite(stream, sizeFooter, sizeof(sizeFooter));
}
bstreamWrite(stream, verFooter, sizeof(verFooter));
bstreamWrite(stream, ver, strlen(ver));
bstreamWrite(stream, endFooter, sizeof(endFooter));
unsigned char iscModeFooter[] = { 0, 0 };
iscModeFooter[0] = (nscr->fmt == SCREENFORMAT_AFFINE) ? 1 : 0;
unsigned char sizeFooter[] = { 0, 0, 0, 0 };
*(uint16_t *) (sizeFooter + 0x0) = nscr->tilesX;
*(uint16_t *) (sizeFooter + 0x2) = nscr->tilesY;
IscadWriteBlock(&cadStream, "MODE", iscModeFooter, sizeof(iscModeFooter));
IscadWriteBlock(&cadStream, "SIZE", sizeFooter, sizeof(sizeFooter));
}
IscadWriteBlock(&cadStream, "VER ", ver, strlen(ver));
IscadWriteBlock(&cadStream, "END ", NULL, 0);
IscadStreamFinalize(&cadStream);
IscadStreamFlushOut(&cadStream, stream);
IscadStreamFree(&cadStream);
return 0;
}