comparison tools/lib64fmts.c @ 2150:b4fbb90937f7

Fix Cosmos Designs Hires Manager unpacker. What a mess. Ugh.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 04 Jun 2019 15:00:58 +0300
parents 810fc98d9003
children 0a7ebb7198e3
comparison
equal deleted inserted replaced
2149:810fc98d9003 2150:b4fbb90937f7
979 979
980 980
981 static int fmtDecodeCosmosDesignsHiresManagerPacked(DMC64Image *img, const DMGrowBuf *psrc, const DMC64ImageFormat *fmt) 981 static int fmtDecodeCosmosDesignsHiresManagerPacked(DMC64Image *img, const DMGrowBuf *psrc, const DMC64ImageFormat *fmt)
982 { 982 {
983 int res; 983 int res;
984 DMGrowBuf src, tmp; 984 DMGrowBuf tmp;
985 DMCompParams cfg; 985 Uint8 data, *dstBuf;
986 Uint8 data, count, *dstBuf; 986 const size_t baseAddr = 0x4000;
987 const size_t dstSize = 0x7ff2 - 0x4000; 987 const size_t dstSize = 0x8000 - baseAddr;
988 size_t dstOffs; 988 size_t dstOffs, srcOffs;
989 BOOL getByte = TRUE;
990
991 // Setup the RLE config, only for input
992 cfg.func = fmt->name;
993 cfg.type = DM_COMP_RLE_MARKER;
994 cfg.flags = DM_RLE_BACKWARDS_INPUT;
995 989
996 // Allocate output buffer 990 // Allocate output buffer
997 if ((dstBuf = dmMalloc0(dstSize)) == NULL) 991 if ((dstBuf = dmMalloc0(dstSize)) == NULL)
998 { 992 {
999 return dmError(DMERR_MALLOC, 993 return dmError(DMERR_MALLOC,
1000 "%s: Could not allocate memory for RLE decoding buffer.\n", 994 "Could not allocate memory for RLE decoding buffer.\n");
1001 cfg.func);
1002 } 995 }
1003 996
1004 // Setup input buffer 997 // Setup input buffer
1005 dmGrowBufConstCopy(&src, psrc); 998 dstOffs = 0x7ff2 - baseAddr - 1;
1006 dmSetupRLEBuffers(NULL, &src, &cfg); 999 srcOffs = psrc->len - 1;
1007 dstOffs = dstSize; 1000
1008 1001 while (dstOffs > 0 && srcOffs > 0)
1009 while (dstOffs > 0 && src.offs > 0) 1002 {
1010 { 1003 data = psrc->data[srcOffs];
1011 if (getByte && !dmGrowBufGetU8(&src, &data)) 1004
1012 { 1005
1013 res = dmError(DMERR_INVALID_DATA, 1006 // Current data byte tells us the mode
1014 "%s: RLE: Invalid data/out of data for literal sequence.\n",
1015 cfg.func);
1016 goto out;
1017 }
1018
1019 // A simple marker byte RLE variant: [Marker] [count] [data]
1020 if (data == 0) 1007 if (data == 0)
1021 { 1008 {
1022 if (!dmGrowBufGetU8(&src, &count) || 1009 // RLE run
1023 !dmGrowBufGetU8(&src, &data)) 1010 if (srcOffs < 3)
1024 { 1011 {
1025 res = dmError(DMERR_INVALID_DATA, 1012 res = dmError(DMERR_INVALID_DATA,
1026 "%s: RLE: Invalid data/out of data for run sequence.\n", 1013 "RLE: Invalid data/out of data for run sequence.\n");
1027 cfg.func);
1028 goto out; 1014 goto out;
1029 } 1015 }
1030 1016
1031 int ncount = (int) count; 1017 size_t ncount = psrc->data[--srcOffs];
1032 for (int n = 1; n < ncount && dstOffs > 0; n++) 1018 data = psrc->data[--srcOffs];
1033 dstBuf[--dstOffs] = data; 1019
1034 1020 srcOffs--;
1035 getByte = TRUE; 1021
1022 if (dstOffs < ncount)
1023 goto finish;
1024
1025 dstOffs -= ncount;
1026 ncount++;
1027 for (size_t n = 0; n < ncount; n++)
1028 dstBuf[dstOffs + n] = data;
1036 } 1029 }
1037 else 1030 else
1038 // Literal run of data bytes 1031 {
1039 { 1032 // Literal run of data bytes
1040 int ncount = (int) data; 1033 size_t ncount = data;
1041 for (int n = 0; n < ncount; n++) 1034 if (srcOffs < ncount)
1042 { 1035 ncount = srcOffs;
1043 if (!dmGrowBufGetU8(&src, &data)) 1036
1044 goto finish; 1037 if (dstOffs < ncount)
1045 1038 ncount = dstOffs;
1046 if (dstOffs > 0) 1039
1047 dstBuf[--dstOffs] = data; 1040 srcOffs -= ncount;
1048 else 1041 dstOffs -= ncount - 1;
1049 goto finish; 1042
1043 for (size_t n = 0; n < ncount; n++)
1044 {
1045 data = psrc->data[srcOffs + n];
1046 dstBuf[dstOffs + n] = data;
1050 } 1047 }
1051 getByte = FALSE;
1052 } 1048 }
1053 } 1049 }
1054 1050
1055 finish: 1051 finish:
1056 1052
1057 dmGrowBufConstCreateFrom(&tmp, dstBuf, 0x3fff); 1053 dmGrowBufConstCreateFrom(&tmp, dstBuf, dstSize);
1058 res = dmC64DecodeGenericBMP(img, &tmp, fmt); 1054 res = dmC64DecodeGenericBMP(img, &tmp, fmt);
1059 1055
1060 out: 1056 out:
1061 dmGrowBufFree(&src);
1062 dmFree(dstBuf); 1057 dmFree(dstBuf);
1063 return res; 1058 return res;
1064 } 1059 }
1065 1060
1066 1061