aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--actor.cpp7
-rw-r--r--boxes.cpp8
-rw-r--r--costume.cpp4
-rw-r--r--gfx.cpp203
-rw-r--r--object.cpp69
-rw-r--r--resource.cpp197
-rw-r--r--script.cpp22
-rw-r--r--scumm.h21
-rw-r--r--scummvm.cpp104
-rw-r--r--sound/imuse.cpp2
10 files changed, 584 insertions, 53 deletions
diff --git a/actor.cpp b/actor.cpp
index e5c7769731..a4031ca914 100644
--- a/actor.cpp
+++ b/actor.cpp
@@ -449,6 +449,7 @@ int Scumm::getActorXYPos(Actor *a) {
}
AdjustBoxResult Scumm::adjustXYToBeInBox(Actor *a, int x, int y, int pathfrom) {
+ // Yazoo: need to recheck with Loom for the class data flags (0x400000)
AdjustBoxResult abr,tmp;
uint threshold;
uint best;
@@ -461,13 +462,17 @@ AdjustBoxResult Scumm::adjustXYToBeInBox(Actor *a, int x, int y, int pathfrom) {
if (a && a->ignoreBoxes==0) {
threshold = 30;
+
+ if ((_features & GF_SMALL_HEADER) && (_classData[a->number] & 0x200000))
+ return abr;
while(1) {
box = getNumBoxes() - 1;
best = (uint)0xFFFF;
b = 0;
- do {
+ if(((_features & GF_SMALL_HEADER) && box) || !(_features & GF_SMALL_HEADER))
+ do {
flags = getBoxFlags(box);
if (flags&0x80 && (!(flags&0x20) || getClass(a->number, 0x1F)) )
continue;
diff --git a/boxes.cpp b/boxes.cpp
index 2a8c9bf150..72a4c6c9b0 100644
--- a/boxes.cpp
+++ b/boxes.cpp
@@ -43,7 +43,13 @@ byte Scumm::getNumBoxes() {
}
Box *Scumm::getBoxBaseAddr(int box) {
- byte *ptr = getResourceAddress(rtMatrix, 2);
+ byte *ptr;
+
+ if(_features & GF_SMALL_HEADER)
+ ptr = getResourceAddress(rtMatrix, 1);
+ else
+ ptr = getResourceAddress(rtMatrix, 2);
+
checkRange(ptr[0]-1, 0, box, "Illegal box %d");
return (Box*)(ptr + box*SIZEOF_BOX + 2);
}
diff --git a/costume.cpp b/costume.cpp
index c0979d3210..23d677ec0b 100644
--- a/costume.cpp
+++ b/costume.cpp
@@ -674,7 +674,7 @@ void CostumeRenderer::loadCostume(int id) {
if (_vm->_features&GF_AFTER_V6) {
_ptr += 8;
- } else {
+ } else if(!(_features&GF_SMALL_HEADER)) {
_ptr += 2;
}
@@ -753,7 +753,7 @@ void Scumm::loadCostume(LoadedCostume *lc, int costume) {
if (_features&GF_AFTER_V6) {
lc->_ptr += 8;
- } else {
+ } else if (!(_features&GF_SMALL_HEADER)) {
lc->_ptr += 2;
}
diff --git a/gfx.cpp b/gfx.cpp
index 398c5460b7..b6d8ba4ca8 100644
--- a/gfx.cpp
+++ b/gfx.cpp
@@ -337,10 +337,12 @@ void Scumm::initBGBuffers() {
room = getResourceAddress(rtRoom, _roomResource);
- ptr = findResource(MKID('RMIH'), findResource(MKID('RMIM'), room));
-
- gdi._numZBuffer = READ_LE_UINT16(ptr+8) + 1;
-
+ if(_features & GF_SMALL_HEADER) {
+ gdi._numZBuffer = 1;
+ } else {
+ ptr = findResource(MKID('RMIH'), findResource(MKID('RMIM'), room));
+ gdi._numZBuffer = READ_LE_UINT16(ptr+8) + 1;
+ }
assert(gdi._numZBuffer>=1 && gdi._numZBuffer<=4);
itemsize = (_scrHeight + 4) * 40;
@@ -357,7 +359,17 @@ void Scumm::setPaletteFromPtr(byte *ptr) {
byte *dest, *epal;
int numcolor;
- numcolor = getResourceDataSize(ptr) / 3;
+ if( _features & GF_SMALL_HEADER ) {
+ if (_features & GF_OLD256) {
+ numcolor = 256;
+ ptr+=2;
+ } else {
+ numcolor = READ_LE_UINT16(ptr+6) / 3;
+ ptr+=8;
+ }
+ } else {
+ numcolor = getResourceDataSize(ptr) / 3;
+ }
checkRange(256, 0, numcolor, "Too many colors (%d) in Palette");
@@ -531,6 +543,7 @@ void Scumm::unkVirtScreen4(int a) {
// setDirtyRange(0, 0, vs->height);
// updateDirtyScreen(0);
/* XXX: EGA_proc4(0); */
+ warning("EGA_proc4"); /* FIXME */
break;
case 134:
unkScreenEffect5(0);
@@ -611,10 +624,16 @@ void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, int stripnr
byte twobufs;
int numzbuf;
int sx;
-
+
+ if(_vm->_features & GF_16COLOR) /* FIXME */
+ return;
+
CHECK_HEAP
- smap_ptr = findResource(MKID('SMAP'), ptr);
+ if(_vm->_features & GF_SMALL_HEADER)
+ smap_ptr = _smap_ptr = ptr;
+ else
+ smap_ptr = findResource(MKID('SMAP'), ptr);
assert(smap_ptr);
@@ -636,7 +655,10 @@ void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, int stripnr
_numLinesToProcess = h;
do {
- _smap_ptr = smap_ptr + READ_LE_UINT32(smap_ptr + stripnr*4 + 8);
+ if(_vm->_features & GF_SMALL_HEADER)
+ _smap_ptr = smap_ptr + READ_LE_UINT32(smap_ptr + stripnr*4 + 4);
+ else
+ _smap_ptr = smap_ptr + READ_LE_UINT32(smap_ptr + stripnr*4 + 8);
CHECK_HEAP
@@ -723,6 +745,23 @@ void Gdi::decompressBitmap() {
case 1:
unkDecode7();
break;
+
+ case 2:
+ unkDecode8(); /* Ender - Zak256/Indy256 */
+ break;
+
+ case 3:
+ unkDecode9(); /* Ender - Zak256/Indy256 */
+ break;
+
+ case 4:
+ unkDecode10(); /* Ender - Zak256/Indy256 */
+ break;
+
+ case 7:
+ unkDecode11(); /* Ender - Zak256/Indy256 */
+ break;
+
case 14: case 15: case 16: case 17: case 18:
_decomp_shr = code - 10;
_decomp_mask = decompress_table[code - 10];
@@ -1207,6 +1246,149 @@ void Gdi::unkDecode7() {
} while (--height);
}
+/* Ender - Zak256/Indy256 decoders */
+#define READ_256BIT \
+ if ((mask <<= 1) == 256) {buffer = *src++; mask = 1;} \
+ bits = ((buffer & mask) != 0);
+
+#define NEXT_ROW \
+ dst += 320; \
+ if (--h == 0) { \
+ if (!--_currentX) \
+ return; \
+ dst -= _vertStripNextInc; \
+ h = _numLinesToProcess; \
+ }
+
+void Gdi::unkDecode8() {
+ byte *src = _smap_ptr;
+ byte *dst = _bgbak_ptr;
+ int i;
+ uint h = _numLinesToProcess;
+
+ _currentX = 8;
+ for(;;) {
+ uint run = (*src++)+1;
+ byte color = *src++;
+
+ do {
+ *dst = color;
+ NEXT_ROW
+ } while (--run);
+ }
+}
+
+void Gdi::unkDecode9() { /* FIXME: This one doesn't work.. */
+ byte *src = _smap_ptr;
+ byte *dst = _bgbak_ptr;
+ unsigned char c, bits, color, run;
+ int x, y, i, z;
+ uint buffer, mask = 128;
+ int h = _numLinesToProcess;
+ x = y = i = z = run = 0;
+
+ while (x < 8) {
+ c = 0;
+ for (i = 0; i < 4; i++) {READ_256BIT; c+=(bits<<i);}
+ /* printf("%d,", c>>2); */
+ switch ((c>>2)) {
+ case 0:
+ color= 0;
+ for (i=0; i<4; i++) {READ_256BIT; color+=bits<<i;}// color+=getbit(-1)<<i;
+ for (i=0; i<((c&3)+2); i++) {
+ *dst = (run * 16 + color);
+ NEXT_ROW
+ }
+ break;
+
+ case 1:
+ for (i=0; i<((c&3)+1); i++) {
+ color = 0;
+ for (z=0; z < 4; z++) {READ_256BIT; color+=bits<<i;}
+ *dst = (run * 16 + color);
+ NEXT_ROW // y++; if (y>=height) {y=0; x++;}}
+ }
+ break;
+
+ case 2:
+ run = 0;
+ for (i = 0; i < 4; i++) {READ_256BIT; c+=run<<i;}
+ break;
+ }
+ }
+ /* printf("\n"); */
+}
+
+void Gdi::unkDecode10() {
+ byte *src = _smap_ptr;
+ byte *dst = _bgbak_ptr;
+ int i;
+ unsigned char local_palette[256], numcolors = *src++;
+ uint h = _numLinesToProcess;
+
+ for (i=0; i < numcolors; i++)
+ local_palette[i] = *src++;
+
+ _currentX = 8;
+
+ for(;;) {
+ byte color = *src++;
+ if (color < numcolors) {
+ *dst = local_palette[color];
+ NEXT_ROW
+ } else {
+ uint run = color - numcolors + 1;
+ color = *src++;
+ do {
+ *dst = color;
+ NEXT_ROW
+ } while (--run);
+ }
+ }
+}
+
+
+void Gdi::unkDecode11() {
+ byte *src = _smap_ptr;
+ byte *dst = _bgbak_ptr;
+ int bits, i;
+ uint buffer, mask = 128;
+ unsigned char inc = 1, color = *src++;
+
+ _currentX = 8;
+ do {
+ _tempNumLines = _numLinesToProcess;
+ do {
+ *dst = color;
+ dst+=320;
+ for (i=0; i<3; i++) {READ_256BIT if (!bits) break;}
+ switch (i) {
+ case 1:
+ inc=-inc;
+ color-=inc;
+ break;
+
+ case 2:
+ color-=inc;
+ break;
+
+ case 3:
+ color = 0;
+ inc = 1;
+ for (i=0; i<8; i++) {
+ READ_256BIT
+ color+= bits<<i;
+ }
+ break;
+ }
+ } while (--_tempNumLines);
+ dst -= _vertStripNextInc;
+ } while (--_currentX);
+}
+
+
+#undef NEXT_ROW
+#undef READ_256BIT
#undef READ_BIT
#undef FILL_BITS
@@ -1893,7 +2075,10 @@ void Scumm::setCursorHotspot2(int x,int y) {
byte Scumm::isMaskActiveAt(int l, int t, int r, int b, byte *mem) {
int w,h,i;
-
+
+ if(_features & GF_SMALL_HEADER) /* FIXME */
+ return false;
+
l>>=3;
if (l<0) l = 0;
if (t<0) t = 0;
diff --git a/object.cpp b/object.cpp
index 46acf689f2..71cffd06a6 100644
--- a/object.cpp
+++ b/object.cpp
@@ -401,8 +401,75 @@ void Scumm::loadRoomObjects() {
CHECK_HEAP
}
+void Scumm::loadRoomObjectsSmall() {
+ int i,j;
+ ObjectData *od;
+ byte *ptr;
+ uint16 obim_id;
+ byte *room,*searchptr;
+ ImageHeader *imhd;
+ RoomHeader *roomhdr;
+
+ CodeHeader *cdhd;
+
+ CHECK_HEAP
+
+ room = getResourceAddress(rtRoom, _roomResource);
+ roomhdr = (RoomHeader*)findResourceData(MKID('RMHD'), room);
+
+ _numObjectsInRoom = READ_LE_UINT16(&roomhdr->numObjects);
+
+ if (_numObjectsInRoom == 0)
+ return;
+
+ if (_numObjectsInRoom > _numLocalObjects)
+ error("More than %d objects in room %d", _numLocalObjects, _roomResource);
+
+ od = &_objs[1];
+ searchptr = room;
+ for (i=0; i<_numObjectsInRoom; i++,od++) {
+ ptr = findResourceSmall(MKID('OBCD'), searchptr);
+ if (ptr==NULL)
+ error("Room %d missing object code block(s)", _roomResource);
+
+ od->offs_obcd_to_room = ptr - room;
+ od->obj_nr = READ_LE_UINT16(ptr+6);
+
+#ifdef DUMP_SCRIPTS
+ do {
+ char buf[32];
+ sprintf(buf,"roomobj-%d-",_roomResource);
+ dumpResource(buf, od->obj_nr, ptr);
+ } while (0);
+#endif
+ searchptr = NULL;
+ }
+
+ searchptr = room;
+ for (i=0; i<_numObjectsInRoom; i++) {
+ ptr = findResourceSmall(MKID('OBIM'), searchptr);
+ if (ptr==NULL)
+ error("Room %d missing image blocks(s)", _roomResource);
+
+ obim_id = READ_LE_UINT16(ptr+6);
+
+ for(j=1; j<=_numObjectsInRoom; j++) {
+ if (_objs[j].obj_nr==obim_id)
+ _objs[j].offs_obim_to_room = ptr - room;
+ }
+ searchptr = NULL;
+ }
+
+ od = &_objs[1];
+ for (i=1; i<=_numObjectsInRoom; i++,od++) {
+ setupRoomObject(od, room);
+ }
+
+ CHECK_HEAP
+}
+
void Scumm::setupRoomObject(ObjectData *od, byte *room) {
- byte *obcd;
+ byte *obcd;
CodeHeader *cdhd;
ImageHeader *imhd;
diff --git a/resource.cpp b/resource.cpp
index d053f34464..c08b5f90fc 100644
--- a/resource.cpp
+++ b/resource.cpp
@@ -95,7 +95,7 @@ void Scumm::openRoom(int room) {
/* Delete the currently loaded room offsets */
void Scumm::deleteRoomOffsets() {
- if (!_dynamicRoomOffsets)
+ if (!(_features & GF_SMALL_HEADER) && !_dynamicRoomOffsets)
return;
for (int i=0; i<_maxRooms; i++) {
@@ -284,6 +284,127 @@ void Scumm::readIndexFile() {
openRoom(-1);
}
+void Scumm::readIndexFileSmall() {
+ uint16 blocktype;
+ uint32 itemsize;
+ int numblock = 0;
+ int num, i;
+
+ debug(9, "readIndexFile()");
+
+ openRoom(-1);
+ openRoom(0);
+
+ if (!(_features & GF_AFTER_V6)) {
+ while (!fileEof(_fileHandle)) {
+ itemsize = fileReadDwordLE();
+ blocktype = fileReadWordLE();
+ if (fileReadFailed(_fileHandle))
+ break;
+
+ switch(blocktype) {
+ case 0x4E52:
+ fileReadWordLE();
+ break;
+ case 0x5230:
+ _numRooms = fileReadWordLE();
+ break;
+ case 0x5330:
+ _numScripts = fileReadWordLE();
+ break;
+ case 0x4E30:
+ _numSounds = fileReadWordLE();
+ break;
+ case 0x4330:
+ _numCostumes = fileReadWordLE();
+ break;
+ case 0x4F30:
+ _numGlobalObjects = fileReadWordLE();
+ break;
+ }
+ fileSeek(_fileHandle, itemsize-8,SEEK_CUR);
+ }
+ clearFileReadFailed(_fileHandle);
+ fileSeek(_fileHandle, 0, SEEK_SET);
+ }
+
+ /* I'm not sure for those values yet, they will have to be rechecked */
+
+ _numVariables = 800; /* 800 */
+ _numBitVariables = 4096; /* 2048 */
+ _numLocalObjects = 200; /* 200 */
+ _numArray = 50;
+ _numVerbs = 100;
+ _numNewNames = 0;
+ _objectRoomTable = NULL;
+ _numCharsets = 9; /* 9 */
+ _numInventory = 80; /* 80 */
+ _numGlobalScripts = 200;
+
+ _shadowPaletteSize = 256;
+ _shadowPalette = (byte*)alloc(_shadowPaletteSize); // stupid for now. Need to be removed later
+ _numFlObject = 50;
+
+ allocateArrays();
+
+ while (1) {
+ itemsize = fileReadDwordLE();
+
+ if (fileReadFailed(_fileHandle))
+ break;
+
+ blocktype = fileReadWordLE();
+
+ numblock++;
+
+ switch(blocktype) {
+
+ case 0x4E52:
+ fileSeek(_fileHandle, itemsize-6,SEEK_CUR);
+ break;
+
+ case 0x5230:
+ readResTypeList(rtRoom,MKID('ROOM'),"room");
+ break;
+
+ case 0x5330:
+ readResTypeList(rtScript,MKID('SCRP'),"script");
+ break;
+
+ case 0x4E30:
+ readResTypeList(rtSound,MKID('SOUN'),"sound");
+ break;
+
+ case 0x4330:
+ readResTypeList(rtCostume,MKID('COST'),"costume");
+ break;
+
+ case 0x4F30:
+ num = fileReadWordLE();
+ assert(num == _numGlobalObjects);
+ for (i=0; i<num; i++) { /* not too sure about all that */
+ _classData[i] = fileReadWordLE(); //+ fileReadByte();
+ fileReadByte();
+ _objectOwnerTable[i] = fileReadByte();
+ _objectStateTable[i] = _objectOwnerTable[i]>>OF_STATE_SHL;
+ _objectOwnerTable[i] &= OF_OWNER_MASK;
+ }
+
+#if defined(SCUMM_BIG_ENDIAN)
+ for (i=0; i<num; i++) {
+ _classData[i] = FROM_LE_32(_classData[i]);
+ }
+#endif
+ break;
+
+ default:
+ error("Bad ID %c%c found in directory!", blocktype&0xFF, blocktype>>8);
+ return;
+ }
+ }
+
+ openRoom(-1);
+}
void Scumm::readArrayFromIndexFile() {
int num;
@@ -474,7 +595,7 @@ int Scumm::readSoundResource(int type, int index) {
fileSeek(_fileHandle, -8, SEEK_CUR);
fileRead(_fileHandle,createResource(type, index, total_size+8), total_size+8);
return 1;
- }
+ }
#else
best_pri = -1;
while (pos < total_size) {
@@ -658,6 +779,37 @@ StartScan:
return f->ptr;
}
+byte *findResourceSmall(uint32 tag, byte *searchin) {
+ uint32 size;
+ static FindResourceState frs;
+ FindResourceState *f = &frs; /* easier to make it thread safe like this */
+ uint16 smallTag;
+
+ smallTag=newTag2Old(tag);
+
+ if (searchin) {
+ f->size = READ_LE_UINT32(searchin);
+ f->pos = 6;
+ f->ptr = searchin+6;
+ goto StartScan;
+ }
+
+ do {
+ size = READ_LE_UINT32(f->ptr);
+ if ((int32)size <= 0)
+ return NULL;
+
+ f->pos += size;
+ f->ptr += size;
+
+StartScan:
+ if (f->pos >= f->size)
+ return NULL;
+ } while (READ_LE_UINT16(f->ptr+4) != smallTag);
+
+ return f->ptr;
+}
+
byte *findResource(uint32 tag, byte *searchin, int index) {
uint32 maxsize,curpos,totalsize,size;
@@ -952,3 +1104,44 @@ void Scumm::allocateArrays() {
allocResTypeData(rtFlObject, MKID('NONE'),_numFlObject,"flobject", 0);
allocResTypeData(rtMatrix, MKID('NONE'),10,"boxes", 0);
}
+
+uint16 newTag2Old(uint32 oldTag) {
+ switch(oldTag) {
+ case(MKID('RMHD')):
+ return(0x4448);
+ break;
+ case(MKID('IM00')):
+ return(0x4D42);
+ break;
+ case(MKID('EXCD')):
+ return(0x5845);
+ break;
+ case(MKID('ENCD')):
+ return(0x4E45);
+ break;
+ case(MKID('SCAL')):
+ return(0x4153);
+ break;
+ case(MKID('LSCR')):
+ return(0x534C);
+ break;
+ case(MKID('OBCD')):
+ return(0x434F);
+ break;
+ case(MKID('OBIM')):
+ return(0x494F);
+ break;
+ case(MKID('SMAP')):
+ return(0x4D42);
+ break;
+ case(MKID('CLUT')):
+ return(0x4150);
+ break;
+ case(MKID('BOXD')):
+ return(0x5842);
+ break;
+ default:
+ return(0);
+ }
+}
+
diff --git a/script.cpp b/script.cpp
index ae41708a25..6bdaa5bd88 100644
--- a/script.cpp
+++ b/script.cpp
@@ -37,7 +37,10 @@ void Scumm::runScript(int script, int a, int b, int16 *lvarptr) {
if (script < _numGlobalScripts) {
scriptPtr = getResourceAddress(rtScript, script);
- scriptOffs = 8;
+ if(_features & GF_SMALL_HEADER)
+ scriptOffs = 6;
+ else
+ scriptOffs = 8;
scriptType = WIO_GLOBAL;
} else {
scriptOffs = _localScriptList[script - _numGlobalScripts];
@@ -662,7 +665,7 @@ void Scumm::runVerbCode(int object, int entry, int a, int b, int16 *vars) {
slot = getScriptSlot();
offs = getVerbEntrypoint(object, entry);
- if (offs==0)
+ if (offs==0)
return;
vm.slot[slot].number = object;
@@ -700,13 +703,19 @@ int Scumm::getVerbEntrypoint(int obj, int entry) {
objptr = getOBCDFromObject(obj);
assert(objptr);
- verbptr = findResource(MKID('VERB'), objptr);
+ if(_features & GF_SMALL_HEADER)
+ verbptr = objptr+19;
+ else
+ verbptr = findResource(MKID('VERB'), objptr);
+
if (verbptr==NULL)
error("No verb block in object %d", obj);
verboffs = verbptr - objptr;
- verbptr += _resourceHeaderSize;
+ if(!(_features & GF_SMALL_HEADER))
+ verbptr += _resourceHeaderSize;
+
do {
if (!*verbptr)
return 0;
@@ -715,7 +724,10 @@ int Scumm::getVerbEntrypoint(int obj, int entry) {
verbptr += 3;
} while (1);
- return verboffs + READ_LE_UINT16(verbptr+1);
+ if(_features & GF_SMALL_HEADER)
+ return READ_LE_UINT16(verbptr+1);
+ else
+ return verboffs + READ_LE_UINT16(verbptr+1);
}
diff --git a/scumm.h b/scumm.h
index c76cd88f27..84932b1c09 100644
--- a/scumm.h
+++ b/scumm.h
@@ -853,6 +853,10 @@ struct Gdi {
void unkDecode5();
void unkDecode6();
void unkDecode7();
+ void unkDecode8();
+ void unkDecode9();
+ void unkDecode10();
+ void unkDecode11();
void decompressBitmap();
@@ -897,6 +901,11 @@ enum GameId {
GID_INDY4 = 3,
GID_MONKEY = 4,
GID_SAMNMAX = 5,
+ GID_MONKEY_EGA = 6,
+ GID_LOOM256 = 7,
+ GID_ZAK256 = 8,
+ GID_INDY3_256 = 9,
+ GID_LOOM = 10,
};
enum GameFeatures {
@@ -910,6 +919,12 @@ enum GameFeatures {
GF_DRAWOBJ_OTHER_ORDER = 16,
GF_DEFAULT = GF_USE_KEY,
+
+ GF_SMALL_HEADER = 32,
+ GF_SMALL_NAMES = 64,
+ GF_OLD_BUNDLE = 128,
+ GF_16COLOR = 256,
+ GF_OLD256 = 512,
};
struct ScummDebugger;
@@ -1688,6 +1703,7 @@ struct Scumm {
bool isResourceInUse(int type, int i);
void initRoomSubBlocks();
void loadRoomObjects();
+ void loadRoomObjectsSmall();
void setPaletteFromRes();
void initCycl(byte *ptr);
@@ -1897,7 +1913,8 @@ struct Scumm {
void readArrayFromIndexFile();
void readMAXS();
- void readIndexFile();
+ void readIndexFile();
+ void readIndexFileSmall();
int readArray(int array, int index, int base);
void writeArray(int array, int index, int base, int value);
@@ -2227,7 +2244,9 @@ void drawMouse(Scumm *s, int x, int y, int w, int h, byte *buf, bool visible);
void blit(byte *dst, byte *src, int w, int h);
byte *findResource(uint32 tag, byte *searchin, int index);
byte *findResource(uint32 tag, byte *searchin);
+byte *findResourceSmall(uint32 tag, byte *searchin);
void playSfxSound(void *sound, uint32 size, uint rate);
bool isSfxFinished();
void waitForTimer(Scumm *s, int msec_delay);
void setShakePos(Scumm *s, int shake_pos);
+uint16 newTag2Old(uint32 oldTag);
diff --git a/scummvm.cpp b/scummvm.cpp
index 551a524d85..93eb73a3e9 100644
--- a/scummvm.cpp
+++ b/scummvm.cpp
@@ -46,9 +46,14 @@ void Scumm::scummInit() {
debug(9, "scummInit");
- _resourceHeaderSize = 8;
+ if(_features & GF_SMALL_HEADER)
+ _resourceHeaderSize = 6;
+ else
+ _resourceHeaderSize = 8;
+
+ if(!(_features & GF_SMALL_NAMES))
+ loadCharset(1);
- loadCharset(1);
initScreens(0, 16, 320, 144);
setShake(0);
@@ -167,7 +172,7 @@ void Scumm::initScummVars() {
void Scumm::checkRange(int max, int min, int no, const char *str) {
if (no < min || no > max) {
- error("Value %d is out of bounds (%d,%d) msg %s", no, min,max, str);
+ error("Value %d is out of bounds (%d,%d) int script(%d) msg %s", no, min,max, vm.slot[_curExecScript].number, str);
}
}
@@ -205,8 +210,11 @@ void Scumm::scummMain(int argc, char **argv) {
initGraphics(this, _fullScreen);
- readIndexFile();
-
+ if (_features & GF_SMALL_HEADER)
+ readIndexFileSmall();
+ else
+ readIndexFile();
+
initRandSeeds();
if (_features & GF_NEW_OPCODES)
@@ -412,25 +420,46 @@ struct VersionSettings {
uint32 features;
};
+/*
+ This is a list of all known SCUMM games. Commented games are not
+ supported at this time */
+
static const VersionSettings version_settings[] = {
- {"monkey", "Monkey Island 1", GID_MONKEY, 5, 2, 2,
- GF_USE_KEY},
- {"monkey2", "Monkey Island 2: LeChuck's revenge", GID_MONKEY2, 5, 2, 2,
- GF_USE_KEY},
- {"atlantis", "Indiana Jones 4 and the Fate of Atlantis", GID_INDY4, 5, 5, 0,
- GF_USE_KEY},
- {"playfate", "Indiana Jones 4 and the Fate of Atlantis (Demo)", GID_INDY4, 5, 5, 0,
- GF_USE_KEY},
- {"tentacle", "Day Of The Tentacle", GID_TENTACLE, 6, 4, 2,
- GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY},
- {"dottdemo", "Day Of The Tentacle (Demo)", GID_TENTACLE, 6, 3, 2,
- GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY},
- {"samnmax", "Sam & Max", GID_SAMNMAX, 6, 4, 2,
- GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY|GF_DRAWOBJ_OTHER_ORDER},
- {"snmdemo", "Sam & Max (Demo)", GID_SAMNMAX, 6, 3, 0,
- GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY},
- {"ft", "Full Throttle", GID_SAMNMAX, 7, 3, 0,
- GF_NEW_OPCODES|GF_AFTER_V6|GF_AFTER_V7},
+ /* Scumm Version 1 */
+// {"maniac", "Maniac Mansion (C64)", GID_MANIAC64, 1, 0, 0,},
+// {"zak", "Zak McKracken and the Alien Mindbenders (C64)", GID_ZAK64, 1, 0, 0,},
+
+ /* Scumm Version 2 */
+// {"maniac", "Maniac Mansion", GID_MANIAC, 2, 0, 0,},
+// {"zak", "Zak McKracken and the Alien Mindbenders", GID_ZAK, 2, 0, 0,},
+// {"indy3", "Indiana Jones and the Last Crusade", GID_INDY3, 2, 0, 0,},
+
+ /* Scumm Version 3 */
+ {"indy3", "Indiana Jones and the Last Crusade (256)", GID_INDY3_256, 3, 0, 22, GF_SMALL_HEADER|GF_USE_KEY|GF_SMALL_NAMES|GF_OLD256},
+ {"zak256", "Zak McKracken and the Alien Mindbenders (256)",GID_ZAK256, 3, 0, 0, GF_SMALL_HEADER|GF_USE_KEY|GF_SMALL_NAMES|GF_OLD256},
+ {"loom", "Loom", GID_LOOM, 3, 5, 40, GF_SMALL_HEADER|GF_USE_KEY|GF_SMALL_NAMES|GF_OLD_BUNDLE|GF_16COLOR},
+
+ /* Scumm Version 4 */
+ {"monkeyEGA", "Monkey Island 1 (EGA)", GID_MONKEY_EGA, 4, 0, 67, GF_SMALL_HEADER|GF_USE_KEY|GF_16COLOR}, // EGA version
+
+ /* Scumm version 5 */
+ {"loomcd", "Loom (256 color CD version)", GID_LOOM256, 5, 1, 42, GF_SMALL_HEADER|GF_USE_KEY},
+ {"monkey", "Monkey Island 1", GID_MONKEY, 5, 2, 2, GF_USE_KEY},
+ {"monkey2", "Monkey Island 2: LeChuck's revenge", GID_MONKEY2, 5, 2, 2, GF_USE_KEY},
+ {"atlantis", "Indiana Jones 4 and the Fate of Atlantis", GID_INDY4, 5, 5, 0, GF_USE_KEY},
+ {"playfate", "Indiana Jones 4 and the Fate of Atlantis (Demo)", GID_INDY4, 5, 5, 0, GF_USE_KEY},
+
+ /* Scumm Version 6 */
+ {"tentacle", "Day Of The Tentacle", GID_TENTACLE, 6, 4, 2, GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY},
+ {"dottdemo", "Day Of The Tentacle (Demo)", GID_TENTACLE, 6, 3, 2, GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY},
+ {"samnmax", "Sam & Max", GID_SAMNMAX, 6, 4, 2, GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY|GF_DRAWOBJ_OTHER_ORDER},
+ {"snmdemo", "Sam & Max (Demo)", GID_SAMNMAX, 6, 3, 0, GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY},
+
+ /* Scumm Version 7 */
+ {"ft", "Full Throttle", GID_SAMNMAX, 7, 3, 0, GF_NEW_OPCODES|GF_AFTER_V6|GF_AFTER_V7},
+
+ /* Scumm Version 8 */
+// {"curse", "The Curse of Monkey Island", GID_CMI, 8, 1, 0,},
{NULL,NULL}
};
@@ -538,7 +567,10 @@ void Scumm::startScene(int room, Actor *a, int objectNr) {
}
initRoomSubBlocks();
- loadRoomObjects();
+ if(_features & GF_SMALL_HEADER)
+ loadRoomObjectsSmall();
+ else
+ loadRoomObjects();
#if !defined(FULL_THROTTLE)
camera._mode = CM_NORMAL;
@@ -623,8 +655,10 @@ void Scumm::initRoomSubBlocks() {
_scrWidth = READ_LE_UINT16(&rmhd->width);
_scrHeight = READ_LE_UINT16(&rmhd->height);
- _IM00_offs = findResource(MKID('IM00'), findResource(MKID('RMIM'), roomptr))
- - roomptr;
+ if( _features & GF_SMALL_HEADER)
+ _IM00_offs = findResourceData(MKID('IM00'), roomptr) - roomptr;
+ else
+ _IM00_offs = findResource(MKID('IM00'), findResource(MKID('RMIM'), roomptr)) - roomptr;
ptr = findResourceData(MKID('EXCD'), roomptr);
if (ptr) {
@@ -717,8 +751,14 @@ void Scumm::initRoomSubBlocks() {
setPalette(0);
}
}
-
- initCycl(findResourceData(MKID('CYCL'), roomptr));
+
+ if( _features & GF_SMALL_HEADER)
+ ptr = findResourceData(MKID('CYCL'), roomptr);
+ else
+ ptr = findResourceData(MKID('CYCL'), roomptr);
+
+ if (ptr)
+ initCycl(findResourceData(MKID('CYCL'), roomptr));
ptr = findResourceData(MKID('TRNS'), roomptr);
if (ptr)
@@ -756,7 +796,11 @@ void Scumm::dumpResource(char *tag, int index, byte *ptr) {
char buf[256];
FILE *out;
- uint32 size = READ_BE_UINT32_UNALIGNED(ptr+4);
+ uint32 size;
+ if( _features & GF_SMALL_HEADER )
+ size = READ_LE_UINT32(ptr);
+ else
+ size = READ_BE_UINT32_UNALIGNED(ptr+4);
sprintf(buf, "dumps\\%s%d.dmp", tag,index);
@@ -894,7 +938,7 @@ void Scumm::convertKeysToClicks() {
Actor *Scumm::derefActorSafe(int id, const char *errmsg) {
if (id<1 || id>=NUM_ACTORS)
- error("Invalid actor %d in %s", id, errmsg);
+ error("Invalid actor %d in %s (script %d)", id, errmsg, vm.slot[_curExecScript].number);
return derefActor(id);
}
diff --git a/sound/imuse.cpp b/sound/imuse.cpp
index 77edde58c0..54681170c3 100644
--- a/sound/imuse.cpp
+++ b/sound/imuse.cpp
@@ -181,7 +181,7 @@ bool SoundEngine::start_sound(int sound) {
void *mdhd;
mdhd = findTag(sound, MDHD_TAG, 0);
- if (!mdhd)
+ if (!mdhd)
return false;
player = allocate_player(128);