aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scumm/intern.h20
-rw-r--r--scumm/script_v6he.cpp188
2 files changed, 189 insertions, 19 deletions
diff --git a/scumm/intern.h b/scumm/intern.h
index 0166ad1a0d..5638d40600 100644
--- a/scumm/intern.h
+++ b/scumm/intern.h
@@ -543,7 +543,17 @@ protected:
OpcodeProcV6he proc;
const char *desc;
};
-
+ struct vsUnpackCtx {
+ uint8 mask;
+ uint8 num;
+ uint8 b;
+ uint8 *ptr;
+ };
+ struct vsPackCtx {
+ int size;
+ uint8 buf[256];
+ };
+
const OpcodeEntryV6he *_opcodesV6he;
File _hFileTable[17];
@@ -559,8 +569,12 @@ protected:
void redimArray(int arrayId, int newX, int newY, int d);
int readFileToArray(int slot, int32 size);
void writeFileFromArray(int slot, int resID);
- int kernelGetFunctions1(byte *addr, int arg1, int arg2, int arg3, int agr4);
- void kernelSetFunctions1(byte *addr);
+ int virtScreenSave(byte *dst, int x1, int y1, int x2, int y2);
+ int virtScreenSavePack(byte *dst, byte *src, int len, int unk);
+ void virtScreenSavePackBuf(vsPackCtx *ctx, uint8 *dst, int len);
+ void virtScreenSavePackByte(vsPackCtx *ctx, uint8 *dst, int len, uint8 b);
+ void virtScreenLoad(int resIdx, int x1, int y1, int x2, int y2);
+ uint8 virtScreenLoadUnpack(vsUnpackCtx *ctx, byte *data);
void seekFilePos(int slot, int offset, int mode);
byte stringLen(byte *);
virtual void decodeParseString(int a, int b);
diff --git a/scumm/script_v6he.cpp b/scumm/script_v6he.cpp
index 5d58307cbf..3aabe6a9f6 100644
--- a/scumm/script_v6he.cpp
+++ b/scumm/script_v6he.cpp
@@ -879,11 +879,7 @@ void ScummEngine_v6he::o6_kernelSetFunctions() {
case 1:
// Used to restore images when decorating cake in
// Fatty Bear's Birthday Surprise
- debug(0, "stub ScummEngine_v6he::o6_kernelSetFunctions(%d, %d, %d, %d, %d, %d)",
- args[0], args[1], args[2], args[3], args[4], args[5]);
- //kernelSetFunctions1(getResourceAddress(rtScreen, args[1]) + 6);
- //if (args[5] >= args[3]) {
- //}
+ virtScreenLoad(args[1], args[2], args[3], args[4], args[5]);
break;
case 3:
case 4:
@@ -896,28 +892,87 @@ void ScummEngine_v6he::o6_kernelSetFunctions() {
}
}
-void ScummEngine_v6he::kernelSetFunctions1(byte *addr) {
- // TODO
+void ScummEngine_v6he::virtScreenLoad(int resIdx, int x1, int y1, int x2, int y2) {
+ debug(0, "ScummEngine_v6he::virtScreenLoad(%d, %d, %d, %d, %d)", resIdx, x1, y1, x2, y2);
+ vsUnpackCtx ctx;
+ memset(&ctx, 0, sizeof(ctx));
+ int vs = 0; // XXX gdi_virtScreen = 0;
+
+ ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, resIdx);
+ for (int i = 0; i < 25; i++)
+ printf("%02x ", ah->data[i]);
+ printf("\n");
+ virtScreenLoadUnpack(&ctx, ah->data);
+ for (int j = y1; j <= y2; ++j) {
+ uint32 yoff = (j - virtscr[kMainVirtScreen].topline) * 320;
+ uint8 *p1 = getResourceAddress(rtBuffer, vs + 1);
+ p1 += yoff + virtscr[kMainVirtScreen].xstart + x1;
+ uint8 *p2 = getResourceAddress(rtBuffer, vs + 5);
+ p2 += yoff + virtscr[kMainVirtScreen].xstart + x1;
+ if (x2 >= x1) {
+ uint32 w = x2 - x1 + 1;
+ while (w--) {
+ uint8 decByte = virtScreenLoadUnpack(&ctx, 0);
+ *p1++ = decByte;
+ *p2++ = decByte;
+ }
+ }
+ }
+ markRectAsDirty(kMainVirtScreen, x1, x2, y1, y2 + 1); // XXX , 0x4000);
}
+uint8 ScummEngine_v6he::virtScreenLoadUnpack(vsUnpackCtx *ctx, byte *data) {
+ uint8 decByte;
+ if (data != 0) {
+ ctx->num = 0;
+ ctx->ptr = data;
+ decByte = 0;
+ } else {
+ uint8 a;
+ if (ctx->num == 0) {
+ a = *(ctx->ptr)++;
+ if (a & 1) {
+ ctx->num = 1;
+ ctx->b = *(ctx->ptr)++;
+ } else {
+ ctx->num = 2;
+ }
+ ctx->mask = a;
+ a = (a >> 1) + 1;
+ } else {
+ a = ctx->mask;
+ }
+ if (ctx->num == 2) {
+ ctx->b = *(ctx->ptr)++;
+ }
+ ctx->mask = a - 1;
+ if (ctx->mask == 0) {
+ ctx->num = 0;
+ }
+ decByte = ctx->b;
+ }
+ return decByte;
+}
void ScummEngine_v6he::o6_kernelGetFunctions() {
int args[29];
int retval;
- byte *addr;
+ ArrayHeader *ah;
getStackList(args, ARRAYSIZE(args));
switch (args[0]) {
case 1:
// Used to store images when decorating cake in
// Fatty Bear's Birthday Surprise
- debug(0, "stub ScummEngine_v6he::o6_kernelGetFunctions(%d, %d, %d, %d, %d)",
- args[0], args[1], args[2], args[3], args[4]);
+ // XXX gdi_virtScreen = 0;
writeVar(0, 0);
- defineArray(0, rtCostume, 0, kernelGetFunctions1(0, args[1], args[2], args[3], args[4]));
+ defineArray(0, rtCostume, 0, virtScreenSave(0, args[1], args[2], args[3], args[4]));
retval = readVar(0);
- addr = getResourceAddress(rtString, retval);
- kernelGetFunctions1(addr + 6, args[1], args[2], args[3], args[4]);
+ ah = (ArrayHeader *)getResourceAddress(rtString, retval);
+ virtScreenSave(ah->data, args[1], args[2], args[3], args[4]);
+ for (int i = 0; i < 25; i++)
+ printf("%02x ", ah->data[i]);
+ printf("\n");
push(retval);
break;
default:
@@ -925,9 +980,110 @@ void ScummEngine_v6he::o6_kernelGetFunctions() {
}
}
-int ScummEngine_v6he::kernelGetFunctions1(byte *addr, int arg1, int arg2, int arg3, int agr4) {
- // TODO
- return 0;
+int ScummEngine_v6he::virtScreenSave(byte *dst, int x1, int y1, int x2, int y2) {
+ debug(0, "ScummEngine_v6he::virtScreenSave(%d, %d, %d, %d)", x1, y1, x2, y2);
+ int packedSize = 0;
+ int vs = 0; // XXX = gdi_virtScreen;
+
+ for (int j = y1; j <= y2; ++j) {
+ uint8 *p = getResourceAddress(rtBuffer, vs + 5);
+ p += virtscr[kMainVirtScreen].xstart;
+ p += (j - virtscr[kMainVirtScreen].topline) * 320 + x1;
+
+ int size = virtScreenSavePack(dst, p, x2 - x1 + 1, 0);
+ if (dst != 0) {
+ dst += size;
+ }
+ packedSize += size;
+ }
+ return packedSize;
+}
+
+int ScummEngine_v6he::virtScreenSavePack(byte *dst, byte *src, int len, int unk) {
+ vsPackCtx ctx;
+ memset(&ctx, 0, sizeof(ctx));
+
+ uint8 prevByte, curByte;
+
+ ctx.buf[0] = prevByte = *src++;
+ int flag = 0;
+ int iend = 1;
+ int ibeg = 0;
+
+ --len;
+ for (; len != 0; --len) {
+ bool pass = false;
+
+ assert(iend < 0x100);
+ ctx.buf[iend] = curByte = *src++;
+ ++iend;
+
+ if (flag == 0) {
+ if (iend > 0x80) {
+ --iend;
+ virtScreenSavePackBuf(&ctx, dst, iend);
+ ctx.buf[0] = curByte;
+ iend = 1;
+ ibeg = 0;
+ } else {
+ if (prevByte != curByte) {
+ ibeg = iend - 1;
+ }
+ if (iend - ibeg < 3) {
+ if (ibeg != 0) pass = true;
+ else flag = 1;
+ }
+ else if (ibeg > 0) {
+ virtScreenSavePackBuf(&ctx, dst, ibeg);
+ flag = 1;
+ }
+ else {
+ flag = 1;
+ }
+ }
+ }
+ if (flag == 1 || pass) {
+ if (prevByte != curByte || iend - ibeg > 0x80) {
+ virtScreenSavePackByte(&ctx, dst, iend - ibeg - 1, prevByte);
+ ctx.buf[0] = curByte;
+ iend = 1;
+ ibeg = 0;
+ flag = 0;
+ }
+ }
+ prevByte = curByte;
+ }
+
+ if (flag == 0) {
+ virtScreenSavePackBuf(&ctx, dst, iend);
+ } else if (flag == 1) {
+ virtScreenSavePackByte(&ctx, dst, iend - ibeg, prevByte);
+ }
+ return ctx.size;
+}
+
+void ScummEngine_v6he::virtScreenSavePackBuf(vsPackCtx *ctx, uint8 *dst, int len) {
+ if (dst) {
+ *dst++ = (len - 1) * 2;
+ }
+ ++ctx->size;
+ if (len > 0) {
+ ctx->size += len;
+ if (dst) {
+ memcpy(dst, ctx->buf, len);
+ }
+ }
+}
+
+void ScummEngine_v6he::virtScreenSavePackByte(vsPackCtx *ctx, uint8 *dst, int len, uint8 b) {
+ if (dst) {
+ *dst++ = ((len - 1) * 2) | 1;
+ }
+ ++ctx->size;
+ if (dst) {
+ *dst++ = b;
+ }
+ ++ctx->size;
}
void ScummEngine_v6he::o6_stampObject() {