diff --git a/NitroPaint/ncgr.c b/NitroPaint/ncgr.c index b5d2308..0f5f474 100644 --- a/NitroPaint/ncgr.c +++ b/NitroPaint/ncgr.c @@ -87,49 +87,21 @@ int ChrIsValidNcg(const unsigned char *buffer, unsigned int size) { } static int ChriIsCommonScanFooter(const unsigned char *buffer, unsigned int size, int type) { - if (size < 8) return -1; + //scan for footer with these required blocks + const char *const requiredBlocks[] = { "LINK", "CMNT", "MODE", "SIZE", "VER ", "END " }; + int offs = IscadScanFooter(buffer, size, requiredBlocks, sizeof(requiredBlocks) / sizeof(requiredBlocks[0])); + if (offs == -1) return -1; - //scan for possible locations of the footer - for (unsigned int i = 0; i < size - 8; i++) { - if (buffer[i] != 'L') continue; - if (memcmp(buffer + i, "LINK", 4) != 0) continue; - - //candidate location - int hasLink = 0, hasCmnt = 0, hasMode = 0, hasSize = 0, hasVer = 0, hasEnd = 0; + unsigned int footerSize = size - (unsigned int) offs; + const unsigned char *footer = buffer + offs; - //scan sections - unsigned int offset = i; - while (1) { - const unsigned char *section = buffer + offset; - unsigned int length = *(uint32_t *) (buffer + offset + 4); - offset += 8; + //check blocks + unsigned int verSize; + const unsigned char *verBlock = IscadFindBlockBySignature(footer, footerSize, "VER ", &verSize); - if (memcmp(section, "LINK", 4) == 0) hasLink = 1; - else if (memcmp(section, "CMNT", 4) == 0) hasCmnt = 1; - else if (memcmp(section, "MODE", 4) == 0) hasMode = 1; - else if (memcmp(section, "SIZE", 4) == 0) hasSize = 1; - else if (memcmp(section, "VER ", 4) == 0) hasVer = 1; - else if (memcmp(section, "END ", 4) == 0) hasEnd = 1; - - if (memcmp(section, "VER ", 4) == 0) { - //ACG: ver = "IS-ACG0x" (1-3) - //ICG: ver = "IS-ICG01" - const char *ver = section + 8; - if (type == NCGR_TYPE_AC && (length < 8 || memcmp(ver, "IS-ACG", 6))) return -1; - if (type == NCGR_TYPE_IC && (length < 8 || memcmp(ver, "IS-ICG", 6))) return -1; - } - - offset += length; - if (offset >= size) break; - if (hasEnd) break; - } - - if (hasLink && hasCmnt && hasMode && hasSize && hasVer && hasEnd && offset <= size) { - //candidate found - return i; - } - } - return -1; + if (type == NCGR_TYPE_AC && (verSize < 8 || memcmp(verBlock, "IS-ACG", 6))) return -1; // ASC must have version IS-ACGxx + if (type == NCGR_TYPE_IC && (verSize < 8 || memcmp(verBlock, "IS-ICG", 6))) return -1; // ISC must have version IS-ICGxx + return offs; } int ChrIsValidAcg(const unsigned char *buffer, unsigned int size) { diff --git a/NitroPaint/nns.c b/NitroPaint/nns.c index 8e7a887..5f917f4 100644 --- a/NitroPaint/nns.c +++ b/NitroPaint/nns.c @@ -709,6 +709,9 @@ int IscadIsValidFooter(const unsigned char *footer, unsigned int size) { if ((size - pos) < blockSize) return 0; pos += blockSize; + + //check for 'END ' signature + if (memcmp(hdr, "END ", 4) == 0) break; } return 1; } @@ -728,10 +731,40 @@ unsigned char *IscadFindBlockBySignature(const unsigned char *buffer, unsigned i pos += 8; unsigned int blockSize = *(const uint32_t *) (hdr + 4); pos += blockSize; + + //check for 'END ' signature + if (memcmp(hdr, "END ", 4) == 0) break; } return NULL; } +int IscadScanFooter(const unsigned char *buffer, unsigned int size, const char *const *requiredBlocks, unsigned int nRequiredBlocks) { + //scan for locations, check for required blocks. + for (unsigned int i = 0; i < size; i++) { + //check valid footer data + if (!IscadIsValidFooter(buffer + i, size - i)) continue; + + //check required blocks + int foundAll = 1; + for (unsigned int j = 0; j < nRequiredBlocks; j++) { + unsigned int blockSize; + const unsigned char *block = IscadFindBlockBySignature(buffer + i, size - i, requiredBlocks[j], &blockSize); + if (block == NULL) { + foundAll = 0; + break; + } + } + + //buffer here + if (foundAll) { + return (int) i; + } + } + + //not found + return -1; +} + void IscadStreamCreate(IscadStream *stream) { stream->inFooter = 0; @@ -747,7 +780,7 @@ void IscadStreamStartBlock(IscadStream *stream, const char *signature) { stream->blockStart = stream->stream.pos; uint32_t tmpSize = 0; - bstreamWrite(&stream->stream, signature, 4); + bstreamWrite(&stream->stream, (void *) signature, 4); bstreamWrite(&stream->stream, &tmpSize, sizeof(tmpSize)); } diff --git a/NitroPaint/nns.h b/NitroPaint/nns.h index 71dc157..92df735 100644 --- a/NitroPaint/nns.h +++ b/NitroPaint/nns.h @@ -74,6 +74,7 @@ void NnsStreamFree(NnsStream *stream); // ----- ISCAD stream functions +int IscadScanFooter(const unsigned char *buffer, unsigned int size, const char *const *requiredBlocks, unsigned int nRequiredBlocks); int IscadIsValidFooter(const unsigned char *footer, unsigned int size); unsigned char *IscadFindBlockBySignature(const unsigned char *buffer, unsigned int size, const char *signature, unsigned int *pSize); diff --git a/NitroPaint/nscr.c b/NitroPaint/nscr.c index 9fea478..f475bdb 100644 --- a/NitroPaint/nscr.c +++ b/NitroPaint/nscr.c @@ -210,53 +210,23 @@ int ScrIsValidNsc(const unsigned char *buffer, unsigned int size) { } int ScriIsCommonScanFooter(const unsigned char *buffer, unsigned int size, int type) { - if (size < 8) return -1; + //scan for a footer with the required blocks + const char *requiredBlocks[] = { "CLRF", "LINK", "CMNT", "CLRC", "MODE", "VER ", "END " }; + int offs = IscadScanFooter(buffer, size, requiredBlocks, sizeof(requiredBlocks) / sizeof(requiredBlocks[0])); + if (offs == -1) return -1; - //scan for possible locations of the footer - for (unsigned int i = 0; i < size - 8; i++) { - if (buffer[i] != 'C') continue; - if (memcmp(buffer + i, "CLRF", 4) != 0) continue; + unsigned int footerSize = size - (unsigned int) offs; + const unsigned char *footer = buffer + offs; - //candidate location - int hasClrf = 0, hasLink = 0, hasCmnt = 0, hasClrc = 0, hasMode = 0, hasVer = 0, hasEnd = 0, hasSize = 0; + //check blocks + unsigned int verSize, sizeSize; + const unsigned char *verBlock = IscadFindBlockBySignature(footer, footerSize, "VER ", &verSize); + const unsigned char *sizeBlock = IscadFindBlockBySignature(footer, footerSize, "SIZE", &sizeSize); - //scan sections - unsigned int offset = i; - while (1) { - const char *section = buffer + offset; - unsigned int length = *(unsigned int *) (buffer + offset + 4); - offset += 8; - - if (memcmp(section, "CLRF", 4) == 0) hasClrf = 1; - else if (memcmp(section, "LINK", 4) == 0) hasLink = 1; - else if (memcmp(section, "CMNT", 4) == 0) hasCmnt = 1; - else if (memcmp(section, "CLRC", 4) == 0) hasClrc = 1; - else if (memcmp(section, "MODE", 4) == 0) hasMode = 1; - else if (memcmp(section, "SIZE", 4) == 0) hasSize = 1; - else if (memcmp(section, "VER ", 4) == 0) hasVer = 1; - else if (memcmp(section, "END ", 4) == 0) hasEnd = 1; - - if (memcmp(section, "VER ", 4) == 0) { - //ACG: ver = "IS-ACG0x" (1-3) - //ICG: ver = "IS-ICG01" - const char *ver = section + 8; - if (type == NSCR_TYPE_AC && (length < 8 || memcmp(ver, "IS-ASC", 6))) return -1; - if (type == NSCR_TYPE_IC && (length < 8 || memcmp(ver, "IS-ISC", 6))) return -1; - } - - offset += length; - if (offset >= size) break; - if (hasEnd) break; - } - - //ISC files have a SIZE section, but ASC files do not - int sizeSatisfied = (type == NSCR_TYPE_IC && hasSize) || (type != NSCR_TYPE_IC); - if (hasClrf && hasLink && hasCmnt && hasClrc && hasMode && sizeSatisfied && hasVer && hasEnd && offset <= size) { - //candidate found - return i; - } - } - return -1; + if (type == NSCR_TYPE_AC && (verSize < 8 || memcmp(verBlock, "IS-ASC", 6))) return -1; // ASC must have version IS-ASCxx + if (type == NSCR_TYPE_IC && (verSize < 8 || memcmp(verBlock, "IS-ISC", 6))) return -1; // ISC must have version IS-ISCxx + if (type == NSCR_TYPE_IC && sizeBlock == NULL) return -1; // ISC must have a SIZE block + return offs; } int ScrIsValidAsc(const unsigned char *file, unsigned int size) {