/* ;; Twilight Project ;; ;; dumplist to binary converter ;; 1998 Mar.15 Sun. - Sat,12 Feb,2000 ;; Wed,24 Feb,2010 - Thu,25 Feb,2010 ;; Fri,05 Mar,2010 - Sat,06 Mar,2010 ;; Tue,06 Apr,2010 ;; Copyright (C) 1998-2010 G-HAL */ #include #include #include #include #include #if defined(__MSDOS__) # include # ifdef __TURBOC__ # include # endif # define strlcpy(dst,src,len) strcpy(dst,src) # define strlcat(dst,src,len) strcat(dst,src) # define strncasecmp(dst,src,len) strnicmp(dst,src,len) typedef char string; typedef enum { false = 0, true = -1 } bool; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; # define PRIX8 "X" # define PRIX16 "X" # define PRIX32 "lX" # define PRISIZE "lu" typedef unsigned long prisize_t; #else # if !defined(__STDC_LIMIT_MACROS) # define __STDC_LIMIT_MACROS # endif # include # if !defined(__STDC_FORMAT_MACROS) # define __STDC_FORMAT_MACROS # endif # include typedef char string; # define PRISIZE "zu" typedef size_t prisize_t; #endif /* #include "dmputy.h" */ #if !defined(PATH_MAX) # define PATH_MAX 256 #endif enum DmpMode { NONE, d8a, mz, d16, dmp } Mode = NONE; bool DmpOut = false, DmpOutClr = false, LOWER_CASE = false; string InFilename[PATH_MAX]; FILE* InFile; #define InBufSize 256 string InBuf[InBufSize], *InPtr; string OutFilename[PATH_MAX]; FILE *OutFile; #define OutBufSize 1024 uint8_t OutBuf[OutBufSize], *OutPtr; string DmpFilename[PATH_MAX]; FILE *DmpFile; #define DmpBufSize 256 string DmpBuf[DmpBufSize], *DmpPtr; size_t Line, ErrorNum; uint16_t STARTADR, ADR, DATA; uint32_t NEWADR; #define brankskip(){\ while (*InPtr == ' ' || *InPtr == ':' || *InPtr == '-' || *InPtr == '.') \ InPtr++;\ } string itoh( uint8_t DATA ) { DATA &= 0xF; if( DATA <= 9 ) return DATA+'0'; return DATA+'A'-10; } uint8_t htoi( void ) { uint8_t BUF; BUF = (uint8_t)*(InPtr++); BUF -= '0'; if( BUF <= 9 ) return BUF; BUF -= ('A'-'0')-10; if( 10 <= BUF && BUF <= 15 ) return BUF; if( LOWER_CASE ){ BUF -= ('a'-'A'); if( 10 <= BUF && BUF <= 15 ) return BUF; } InPtr--; BUF = 0xFF; return BUF; } uint32_t get4nibble( void ) { uint8_t BUF; uint16_t DATA; brankskip(); BUF = htoi(); if( BUF == 0xFF ) return 0xFFFFFFFFL; DATA = BUF << 4; BUF = htoi(); if( BUF == 0xFF ) return 0xFFFFFFFFL; DATA += BUF; DATA <<= 4; BUF = htoi(); if( BUF == 0xFF ) return 0xFFFFFFFFL; DATA += BUF; DATA <<= 4; BUF = htoi(); if( BUF == 0xFF ) return 0xFFFFFFFFL; DATA += BUF; return DATA; } uint16_t get3nibble( void ) { uint8_t BUF; uint16_t DATA; brankskip(); BUF = htoi(); if( BUF == 0xFF ) return 0xFFFFU; DATA = BUF << 4; BUF = htoi(); if( BUF == 0xFF ) return 0xFFFFU; DATA += BUF; DATA <<= 4; BUF = htoi(); if( BUF == 0xFF ) return 0xFFFFU; DATA += BUF; return DATA; } uint16_t get2nibble( void ) { uint8_t BUF; uint8_t DATA; brankskip(); BUF = htoi(); if( BUF == 0xFF ) return 0xFFFFU; DATA = BUF << 4; BUF = htoi(); if( BUF == 0xFF ) return 0xFFFFU; DATA += BUF; return DATA; } #define GetLine(){\ if( !fgets( InBuf, InBufSize, InFile) )\ break;\ InPtr = InBuf;\ OutPtr = OutBuf;\ Line++;\ if ( ('\0' == (*InPtr)) \ || ('\r' == (*InPtr)) \ || ('\n' == (*InPtr)) \ ) { \ continue;\ }\ } #define AdrCheck(LEN){\ NEWADR = get4nibble();\ ADR += LEN;\ if( NEWADR == 0xFFFFFFFFL ){\ printf("Error %s %"PRISIZE": " \ "Illigal address\n", \ InFilename, (prisize_t)Line );\ OutPtr += LEN;\ goto NEWLINE;\ } else {\ if ((uint32_t)ADR != NEWADR) {\ if( Line != 1 ){\ printf("Warning %s %"PRISIZE": " \ "Address is not continuity\n", \ InFilename, (prisize_t)Line );\ } else {\ STARTADR = ADR = (uint16_t)NEWADR;\ }\ }\ }\ } #define DataCheck(LEN){\ DATA = get2nibble();\ if( DATA == 0xFFFFU ){\ if( *InPtr == '\n' ){\ printf("Error %s %"PRISIZE": " \ "Line is too short\n", \ InFilename, (prisize_t)Line );\ } else {\ printf("Error %s %"PRISIZE": " \ "Illigal data '%c%c%c'\n", \ InFilename, (prisize_t)Line, \ InPtr[-1], InPtr[0], InPtr[1] );\ }\ OutPtr += LEN-i;\ goto NEWLINE;\ }\ *(OutPtr++) = (uint8_t)DATA;\ } #define EndCheck(){\ brankskip();\ if ( ('\0' != *InPtr) \ && ('\r' != *InPtr) \ && ('\n' != *InPtr) \ ) {\ printf("Warning %s %"PRISIZE": " \ "Line is too long\n", \ InFilename, (prisize_t)Line );\ }\ } #define SumCheck(NEWSUM){\ if( NEWSUM == 0xFFFFU ){\ if( *InPtr == '\n' ){\ printf("Error %s %"PRISIZE": " \ "Line is too short\n", \ InFilename, (prisize_t)Line );\ } else {\ printf("Error %s %"PRISIZE": " \ "Illigal checksum\n", \ InFilename, (prisize_t)Line );\ }\ goto NEWLINE;\ }\ } #define SumEqCheck(NEWSUM){\ if( NEWSUM != SUM ){\ printf("Error %s %"PRISIZE": " \ "Checksum mismatch\n", \ InFilename, (prisize_t)Line );\ goto NEWLINE;\ }\ } #define AdrDmpOut(){\ *(DmpPtr++) = itoh( ADR >> 12 );\ *(DmpPtr++) = itoh( ADR >> 8 );\ *(DmpPtr++) = itoh( ADR >> 4 );\ *(DmpPtr++) = itoh( ADR );\ *(DmpPtr++) = ' ';\ } #define DataDmpOut(LEN){\ *(DmpPtr++) = itoh( *(OutPtr -LEN +i) >> 4 );\ *(DmpPtr++) = itoh( *(OutPtr -LEN +i) );\ *(DmpPtr++) = ' ';\ } #define ThroughDmpOut(){\ InPtr = InBuf;\ NEWADR = get4nibble();\ brankskip();\ strcpy( DmpPtr, InPtr);\ DmpPtr += strlen(DmpPtr) -1;\ } #define CRendDmpOut(){\ *(DmpPtr++) = '\r';\ *(DmpPtr++) = '\n';\ *(DmpPtr++) = '\0';\ fputs( DmpBuf, DmpFile);\ } /* CF00 : DD E5 E5 5E 16 00 21 00 - 0B */ void d2b8a(void) { uint8_t SUM; unsigned char i; while (!feof(InFile)) { GetLine(); AdrCheck(8); SUM = (ADR & 0xFF) + (ADR >> 8); for( i = 0; i < 8; i++){ DataCheck(8); SUM += (uint8_t)DATA; } DATA = get2nibble(); SumCheck(DATA); EndCheck(); SumEqCheck(DATA); if( DmpOut ){ DmpPtr = DmpBuf; AdrDmpOut(); *(DmpPtr++) = ':'; *(DmpPtr++) = ' '; for( i = 0; i < 8; i++){ DataDmpOut(8); } *(DmpPtr++) = '-'; *(DmpPtr++) = ' '; *(DmpPtr++) = itoh( SUM >> 4 ); *(DmpPtr++) = itoh( SUM ); CRendDmpOut(); } goto CONT; NEWLINE: ErrorNum++; if( DmpOut ){ DmpPtr = DmpBuf; AdrDmpOut(); *(DmpPtr++) = ':'; *(DmpPtr++) = ' '; if( !DmpOutClr ){ ThroughDmpOut(); } *(DmpPtr++) = ' '; *(DmpPtr++) = '$'; CRendDmpOut(); } CONT: fwrite( OutBuf, 1, 8, OutFile); } ADR += 8; return; } /* 2000 CD 09 00 11 76 31 DF CD : 3A 2008 09 00 3E 5D CD 12 00 AF : 32 2010 32 70 11 CD B3 09 CD CE : D7 2018 0B FE 57 28 6D FE 4E CA : 0B 2020 7F 28 FE 47 CA 24 21 FE : F9 2028 58 CA 3D 24 FE 41 CA 1A : A6 2030 29 FE 44 CA FE 2B FE 4D : A9 2038 28 75 FE 3F CA 7C 2B FE : 49 2040 53 CA 68 23 FE 52 CA A9 : 6B 2048 29 FE 42 CA 8E 26 FE 43 : 28 2050 CA B7 23 FE 48 CA C2 23 : 99 2058 FE 50 CA D5 25 FE 4F CA : 29 2060 01 26 FE 45 CA 3B 25 FE : 92 2068 56 CA 81 24 FE 54 CA C5 : A6 2070 24 FE 49 CA 0B 25 FE 4C : AF 2078 CA CA 23 FE 51 CA 2B 21 : 1C --------------------------------- SUM C4 63 A5 C8 10 14 FF 80 : 37 */ void d2bmz(void) { uint8_t SUM, vSUM[8] = { 0 }; unsigned char i, vSUMline; vSUMline = 0; while (!feof(InFile)) { GetLine(); SUM = 0; if (0 == strncasecmp(InPtr, "----", 4)) { continue; } else if (0 == strncasecmp(InPtr, "SUM ", 4)) { brankskip(); InPtr += 4; for( i = 0; i < 8; i++){ DATA = get2nibble(); if (0xFFFFU == DATA) { if ('\n' == (*InPtr)) { printf("Error %s %"PRISIZE": " "Line is too short\n", InFilename, (prisize_t)Line ); } else { printf("Error %s %"PRISIZE": " "Illigal data '%c%c%c'\n", InFilename, (prisize_t)Line, InPtr[-1], InPtr[0], InPtr[1] ); } continue; } SUM += (uint8_t)DATA; if (vSUM[i] != DATA) { printf("Error %s %"PRISIZE": " "Vertical Checksum[%d] mismatch\n", InFilename, (prisize_t)Line, (int)i ); } } DATA = get2nibble(); if (0xFFFFU == DATA) { if ('\n' == *InPtr) { printf("Error %s %"PRISIZE": " "Line is too short\n", InFilename, (prisize_t)Line ); } else { printf("Error %s %"PRISIZE": " "Illigal checksum\n", InFilename, (prisize_t)Line ); } ErrorNum++; continue; } EndCheck(); if (DATA != SUM) { printf("Error %s %"PRISIZE": " "Checksum mismatch\n", InFilename, (prisize_t)Line ); ErrorNum++; continue; } } else { AdrCheck(8); if (0 == (0xF & vSUMline)) { vSUMline = 0; for (i = 0; i < 8; ++i) { vSUM[i] = 0; } } for( i = 0; i < 8; i++){ DataCheck(8); SUM += (uint8_t)DATA; vSUM[i] += (uint8_t)DATA; } ++ vSUMline; DATA = get2nibble(); SumCheck(DATA); EndCheck(); SumEqCheck(DATA); if( DmpOut ){ DmpPtr = DmpBuf; AdrDmpOut(); *(DmpPtr++) = ':'; *(DmpPtr++) = ' '; for( i = 0; i < 8; i++){ DataDmpOut(8); } *(DmpPtr++) = '-'; *(DmpPtr++) = ' '; *(DmpPtr++) = itoh( SUM >> 4 ); *(DmpPtr++) = itoh( SUM ); CRendDmpOut(); } goto CONT; NEWLINE: ErrorNum++; if( DmpOut ){ DmpPtr = DmpBuf; AdrDmpOut(); *(DmpPtr++) = ':'; *(DmpPtr++) = ' '; if( !DmpOutClr ){ ThroughDmpOut(); } *(DmpPtr++) = ' '; *(DmpPtr++) = '$'; CRendDmpOut(); } CONT: fwrite( OutBuf, 1, 8, OutFile); } } ADR += 8; return; } /* C000 00 C0 00 CC 24 22 22 42 22 22 22 22 22 22 22 22 :346 */ void d2b16(void) { uint16_t SUM; unsigned char i; while (!feof(InFile)) { GetLine(); AdrCheck(16); SUM = 0; for( i = 0; i < 16; i++){ DataCheck(16); SUM += (uint8_t)DATA; } DATA = get3nibble(); SumCheck(DATA); EndCheck(); SumEqCheck(DATA); if( DmpOut ){ DmpPtr = DmpBuf; AdrDmpOut(); for( i = 0; i < 16; i++){ DataDmpOut(16); } *(DmpPtr++) = ' '; *(DmpPtr++) = ':'; *(DmpPtr++) = itoh( SUM >> 8 ); *(DmpPtr++) = itoh( SUM >> 4 ); *(DmpPtr++) = itoh( SUM ); CRendDmpOut(); } goto CONT; NEWLINE: ErrorNum++; if( DmpOut ){ DmpPtr = DmpBuf; AdrDmpOut(); if( !DmpOutClr ){ ThroughDmpOut(); } *(DmpPtr++) = ' '; *(DmpPtr++) = '$'; CRendDmpOut(); } CONT: fwrite( OutBuf, 1, 16, OutFile); } ADR += 16; return; } /* 00000000 4D 5A 19 01 23 00 07 00-20 00 25 01 FF FF BA 04 MZ..#... .%...º. */ void d2bdmp(void) { unsigned char i; const string CHK2[] = " Dump Version "; /* "3.10 " */ const string CHK3[] = " "; do{ GetLine(); if( 1 < strlen(InBuf) ){ goto HD; } GetLine(); if( strncmp(InBuf, CHK2, sizeof(CHK2)) == 0 ){ printf("Error %s %"PRISIZE": " "File format illigal.\n", InFilename, (prisize_t)Line ); return; } GetLine(); if( strcmp(InBuf, CHK3) == 0 ){ printf("Error %s %"PRISIZE": " "File format illigal.\n", InFilename, (prisize_t)Line ); return; } } while (false); Line = 0; while (true) { GetLine(); i = 0; HD: if( get4nibble() != 0 ){ /* printf("Error %s %"PRISIZE": " "Out of address.\n", InFilename, (prisize_t)Line ); */ } AdrCheck(16); for( i = 0; i < 16; i++){ DataCheck(16); } goto CONT; NEWLINE: ErrorNum++; CONT: if( i != 16 ) break; fwrite( OutBuf, 1, 16, OutFile); } if( i != 0 ){ fwrite( OutBuf, 1, i, OutFile); ADR += i-1; } else { ADR += 16-1; } if( !feof(InFile) ){ do{ GetLine(); if( get4nibble() != 0 ){ /* printf("Error %s %"PRISIZE": " "Out of address.\n", InFilename, (prisize_t)Line ); */ } if( get4nibble() != ADR ) printf("Error %s %"PRISIZE": " "HD last address was illigal.\n", InFilename, (prisize_t)Line ); } while (false); } return; } void extcut( string* const STR ) { string* PTR; PTR = strrchr( STR, '\\'); if( !PTR ) PTR = STR; PTR = strchr( PTR, '.'); if( PTR ) *PTR = '\0'; return; } int main( int argc, string *argv[] ) { int i, Argc; fputs( "dumplist to binary converter\n" "\tCopyright (C) 1998-2010 G-HAL\n", stderr); if( argc < 3 ){ fputs( "usage: dmp2bin [option(s)] \n" " \n" "\t8a\t8 bytes, add address to checksum, 2 nibble checksum\n" "\t16\t16 bytes, don't add address to checksum, 3 nibble checksum\n" "\tdmp\tMS-DOS standard dump format\n" "\tmz\t8 bytes with vertical, don't add address to checksum, 2 nibble checksum\n" " [option(s)]\n" "\t/DC\tFormated dumplist output, error line clear\n" "\t/DE\tFormated dumplist output, error line through\n" "\t/L(1|0)\tPermit lower case, or not\n" "\n" "\tOutput filename : *.bin\n" "\tFormated dumplist output filename : *.dd\n" "\n", stderr); return -1; } if (0 == strcmp(argv[1], "8a")) { Mode = d8a; } else if (0 == strcmp(argv[1], "16")) { Mode = d16; } else if (0 == strcmp(argv[1], "dmp")) { Mode = dmp; LOWER_CASE = true; } else if (0 == strcmp(argv[1], "mz")) { Mode = mz; } else { fputs("Unknown ", stderr); fputs("mode\n", stderr); return -1; } Argc = 2; while ('/' == argv[Argc][0]) { switch (toupper(argv[Argc][1])) { case 'D': DmpOut = true; switch (toupper(argv[Argc][2])) { case 'C': DmpOutClr = true; break; case 'E': DmpOutClr = false; break; default: goto UNKNOWN; } break; case 'L': switch (toupper(argv[Argc][2])) { case '0': LOWER_CASE = false; break; case '1': LOWER_CASE = true; break; default: goto UNKNOWN; } break; default: UNKNOWN: fputs("Unknown ", stderr); fputs("option\n", stderr); return -1; } Argc++; } for( i = Argc; i < argc; i++){ Line = 0; ADR = 0; ErrorNum = 0; strlcpy( InFilename, argv[i], sizeof(InFilename) ); strlcpy( OutFilename, InFilename, sizeof(OutFilename) ); extcut( OutFilename ); if( DmpOut ){ strlcpy( DmpFilename, OutFilename, sizeof(DmpFilename) ); strlcat( DmpFilename, ".dd", sizeof(DmpFilename) ); } strlcat( OutFilename, ".bin", sizeof(OutFilename) ); InFile = fopen(InFilename, "rt"); if( !InFile ){ fputs("Input", stderr); fputs(" file open error.\n", stderr); return -1; } OutFile = fopen(OutFilename, "wb"); if( !OutFile ){ fputs("Output", stderr); fputs(" file open error.\n", stderr); return -1; } if( DmpOut ){ DmpFile = fopen(DmpFilename, "wb"); if( !DmpFile ){ fputs("Formated dumplist output", stderr); fputs(" file open error.\n", stderr); return -1; } } switch (Mode) { case d8a: d2b8a(); break; case mz: d2bmz(); break; case d16: d2b16(); break; case dmp: d2bdmp(); break; case NONE: break; } printf( "File %s : " "start %04"PRIX16", end %04"PRIX16", size %04"PRIX16"\n", InFilename, STARTADR, (ADR - 1), ((ADR - 1) - STARTADR + 1) ); if( 0 < ErrorNum ){ printf("\t%"PRISIZE" Error line(s)\n", (prisize_t)ErrorNum ); } fclose( InFile ); fclose( OutFile ); if( DmpOut ) fclose( DmpFile ); } return 0; } /* [ End Of File ] */