diff options
author | Matthew Hoops | 2010-05-18 04:17:58 +0000 |
---|---|---|
committer | Matthew Hoops | 2010-05-18 04:17:58 +0000 |
commit | 3dda73d9a2b65da0dad2d184c52f5ebbee682b59 (patch) | |
tree | b6169db546b692ff9ef889826deda4bfa0b76bf4 | |
parent | 0fe2ba6a0dd1bc7a3edda7ed8deaeba10f39ab9b (diff) | |
download | scummvm-rg350-3dda73d9a2b65da0dad2d184c52f5ebbee682b59.tar.gz scummvm-rg350-3dda73d9a2b65da0dad2d184c52f5ebbee682b59.tar.bz2 scummvm-rg350-3dda73d9a2b65da0dad2d184c52f5ebbee682b59.zip |
Add initial support for KQ6 Mac. Wrapper functions for read/writing to pointers are now used (found in util.*) for code that has different endianness in SCI1.1+ Mac games. Add support for Mac 'snd ' and 'CURS' resources. QFG1 Mac is not yet playable due to script compression.
svn-id: r49070
-rw-r--r-- | engines/sci/engine/kernel.cpp | 18 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 40 | ||||
-rw-r--r-- | engines/sci/engine/kmisc.cpp | 16 | ||||
-rw-r--r-- | engines/sci/engine/message.cpp | 8 | ||||
-rw-r--r-- | engines/sci/engine/script.cpp | 39 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 58 | ||||
-rw-r--r-- | engines/sci/engine/segment.cpp | 22 | ||||
-rw-r--r-- | engines/sci/engine/segment.h | 17 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 8 | ||||
-rw-r--r-- | engines/sci/engine/vm.h | 2 | ||||
-rw-r--r-- | engines/sci/graphics/cursor.cpp | 52 | ||||
-rw-r--r-- | engines/sci/graphics/cursor.h | 1 | ||||
-rw-r--r-- | engines/sci/graphics/view.cpp | 87 | ||||
-rw-r--r-- | engines/sci/module.mk | 1 | ||||
-rw-r--r-- | engines/sci/resource.cpp | 61 | ||||
-rw-r--r-- | engines/sci/sound/audio.cpp | 59 | ||||
-rw-r--r-- | engines/sci/util.cpp | 54 | ||||
-rw-r--r-- | engines/sci/util.h | 41 |
18 files changed, 404 insertions, 180 deletions
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 4700c59597..122af1c36b 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -335,9 +335,9 @@ SciKernelFunction kfunct_mappers[] = { DEFUN("Intersections", kIntersections, "iiiiriiiri"), DEFUN("ResCheck", kResCheck, "iii*"), DEFUN("SetQuitStr", kSetQuitStr, "r"), - DEFUN("ShowMovie", kShowMovie, "..*"), + DEFUN("ShowMovie", kShowMovie, ".*"), DEFUN("SetVideoMode", kSetVideoMode, "i"), - DEFUN("Platform", kPlatform, "i*"), + DEFUN("Platform", kPlatform, "i.*"), DEFUN("TextColors", kTextColors, ".*"), DEFUN("TextFonts", kTextFonts, ".*"), DEFUN("Portrait", kPortrait, ".*"), @@ -757,10 +757,16 @@ void Kernel::setDefaultKernelNames(Common::String gameId) { break; case SCI_VERSION_1_1: - // In KQ6CD, the empty kSetSynonyms function has been replaced - // with kPortrait - if (gameId == "kq6") - _kernelNames[0x26] = "Portrait"; + // In KQ6 CD, the empty kSetSynonyms function has been replaced + // with kPortrait. In KQ6 Mac, kPlayBack has been replaced by + // kShowMovie. + if (gameId == "kq6") { + if (g_sci->getPlatform() == Common::kPlatformMacintosh) + _kernelNames[0x84] = "ShowMovie"; + else + _kernelNames[0x26] = "Portrait"; + } + _kernelNames[0x71] = "PalVary"; _kernelNames[0x7c] = "Message"; break; diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 452f708864..87f51a1a74 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -159,7 +159,10 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) { hotspot = new Common::Point(argv[3].toSint16(), argv[4].toSint16()); // Fallthrough case 3: - g_sci->_gfxCursor->kernelSetView(argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), hotspot); + if (g_sci->getPlatform() == Common::kPlatformMacintosh) + g_sci->_gfxCursor->kernelSetMacCursor(argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), hotspot); + else + g_sci->_gfxCursor->kernelSetView(argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), hotspot); break; default : warning("kSetCursor: Unhandled case: %d arguments given", argc); @@ -1086,22 +1089,29 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { g_sci->_gfxCursor->kernelHide(); if (argv[0].segment != 0) { - // DOS SEQ - // SEQ's are called with no subops, just the string and delay - Common::String filename = s->_segMan->getString(argv[0]); - int delay = argv[1].toUint16(); // Time between frames in ticks - - SeqDecoder *seqDecoder = new SeqDecoder(); - Graphics::VideoPlayer *player = new Graphics::VideoPlayer(seqDecoder); - if (seqDecoder->loadFile(filename.c_str(), delay)) { - player->playVideo(); - playedVideo = true; + if (g_sci->getPlatform() == Common::kPlatformMacintosh) { + // Mac QuickTime + // The only argument is the string for the video + warning("TODO: Play QuickTime movie '%s'", s->_segMan->getString(argv[0]).c_str()); + return s->r_acc; } else { - warning("Failed to open movie file %s", filename.c_str()); + // DOS SEQ + // SEQ's are called with no subops, just the string and delay + Common::String filename = s->_segMan->getString(argv[0]); + int delay = argv[1].toUint16(); // Time between frames in ticks + + SeqDecoder *seqDecoder = new SeqDecoder(); + Graphics::VideoPlayer *player = new Graphics::VideoPlayer(seqDecoder); + if (seqDecoder->loadFile(filename.c_str(), delay)) { + player->playVideo(); + playedVideo = true; + } else { + warning("Failed to open movie file %s", filename.c_str()); + } + seqDecoder->closeFile(); + delete player; + delete seqDecoder; } - seqDecoder->closeFile(); - delete player; - delete seqDecoder; } else { // Windows AVI (Macintosh QuickTime? Need to check KQ6 Macintosh) // TODO: This appears to be some sort of subop. case 0 contains the string diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 96241b8b7c..450dca3770 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -294,6 +294,19 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +// kIconBar is really a subop of kPlatform for SCI1.1 Mac +reg_t kIconBar(EngineState *s, int argc, reg_t *argv) { + // TODO... + + if (argv[0].toUint16() == 4 && argv[1].toUint16() == 0) + for (int i = 0; i < argv[2].toUint16(); i++) + warning("kIconBar: Icon Object %d = %04x:%04x", i, PRINT_REG(argv[i + 3])); + + // Other calls seem to handle selecting/deselecting them + + return NULL_REG; +} + enum kSciPlatforms { kSciPlatformDOS = 1, kSciPlatformWindows = 2 @@ -337,6 +350,9 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) { warning("STUB: kPlatform(CDCheck)"); break; case kPlatformUnk0: + if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() == SCI_VERSION_1_1) + return kIconBar(s, argc - 1, argv + 1); + // Otherwise, fall through case kPlatformGetPlatform: return make_reg(0, (isWindows) ? kSciPlatformWindows : kSciPlatformDOS); case kPlatformUnk5: diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index a4f5da2b4e..07f8792471 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -23,9 +23,11 @@ * */ + #include "sci/engine/message.h" #include "sci/engine/kernel.h" #include "sci/engine/seg_manager.h" +#include "sci/util.h" namespace Sci { @@ -43,7 +45,7 @@ public: return false; // Read message count from last word in header - _messageCount = READ_LE_UINT16(_data + _headerSize - 2); + _messageCount = READ_SCI11ENDIAN_UINT16(_data + _headerSize - 2); if (_messageCount * _recordSize + _headerSize > _size) return false; @@ -124,7 +126,7 @@ public: record.tuple = tuple; record.refTuple = MessageTuple(recordPtr[7], recordPtr[8], recordPtr[9]); record.talker = recordPtr[4]; - record.string = (const char *)_data + READ_LE_UINT16(recordPtr + 5); + record.string = (const char *)_data + READ_SCI11ENDIAN_UINT16(recordPtr + 5); return true; } recordPtr += _recordSize; @@ -143,7 +145,7 @@ bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &re } MessageReader *reader; - int version = READ_LE_UINT16(res->data) / 1000; + int version = READ_SCI11ENDIAN_UINT32(res->data) / 1000; switch (version) { case 2: diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 98fc47e2c0..289140215e 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -25,6 +25,7 @@ #include "sci/sci.h" #include "sci/resource.h" +#include "sci/util.h" #include "sci/engine/features.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" @@ -128,7 +129,7 @@ void SegManager::createClassTable() { _classtable.resize(totalClasses); for (uint16 classNr = 0; classNr < totalClasses; classNr++) { - uint16 scriptNr = READ_LE_UINT16(vocab996->data + classNr * 4 + 2); + uint16 scriptNr = READ_SCI11ENDIAN_UINT16(vocab996->data + classNr * 4 + 2); _classtable[classNr].reg = NULL_REG; _classtable[classNr].script = scriptNr; @@ -150,8 +151,7 @@ reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller getScriptSegment(the_class->script, lock); if (!the_class->reg.segment) { - error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;" - " Entering debugger.", classnr, the_class->script, the_class->script); + error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;", classnr, the_class->script, the_class->script); return NULL_REG; } } else @@ -181,7 +181,7 @@ void SegManager::scriptInitialiseLocals(reg_t location) { VERIFY(location.offset + 1 < (uint16)scr->_bufSize, "Locals beyond end of script\n"); if (getSciVersion() >= SCI_VERSION_1_1) - count = READ_LE_UINT16(scr->_buf + location.offset - 2); + count = READ_SCI11ENDIAN_UINT16(scr->_buf + location.offset - 2); else count = (READ_LE_UINT16(scr->_buf + location.offset - 2) - 4) >> 1; // half block size @@ -199,7 +199,7 @@ void SegManager::scriptInitialiseLocals(reg_t location) { byte *base = (byte *)(scr->_buf + location.offset); for (i = 0; i < count; i++) - locals->_locals[i] = make_reg(0, READ_LE_UINT16(base + i * 2)); + locals->_locals[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(base + i * 2)); } } @@ -209,9 +209,10 @@ void SegManager::scriptRelocateExportsSci11(SegmentId seg) { /* We are forced to use an ugly heuristic here to distinguish function exports from object/class exports. The former kind points into the script resource, the latter into the heap resource. */ - uint16 location = READ_LE_UINT16((byte *)(scr->_exportTable + i)); - if ((location < scr->_heapSize - 1) && (READ_LE_UINT16(scr->_heapStart + location) == SCRIPT_OBJECT_MAGIC_NUMBER)) { - WRITE_LE_UINT16((byte *)(scr->_exportTable + i), location + scr->_heapStart - scr->_buf); + uint16 location = READ_SCI11ENDIAN_UINT16((byte *)(scr->_exportTable + i)); + + if ((location < scr->_heapSize - 1) && (READ_SCI11ENDIAN_UINT16(scr->_heapStart + location) == SCRIPT_OBJECT_MAGIC_NUMBER)) { + WRITE_SCI11ENDIAN_UINT16((byte *)(scr->_exportTable + i), location + scr->_heapStart - scr->_buf); } else { // Otherwise it's probably a function export, // and we don't need to do anything. @@ -221,12 +222,12 @@ void SegManager::scriptRelocateExportsSci11(SegmentId seg) { void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { Script *scr = getScript(seg); - byte *seeker = scr->_heapStart + 4 + READ_LE_UINT16(scr->_heapStart + 2) * 2; + byte *seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; - while (READ_LE_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { - if (READ_LE_UINT16(seeker + 14) & SCRIPT_INFO_CLASS) { + while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { + if (READ_SCI11ENDIAN_UINT16(seeker + 14) & SCRIPT_INFO_CLASS) { int classpos = seeker - scr->_buf; - int species = READ_LE_UINT16(seeker + 10); + int species = READ_SCI11ENDIAN_UINT16(seeker + 10); if (species < 0 || species >= (int)_classtable.size()) { error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d", @@ -237,11 +238,11 @@ void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { _classtable[species].reg.segment = seg; _classtable[species].reg.offset = classpos; } - seeker += READ_LE_UINT16(seeker + 2) * 2; + seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; } - seeker = scr->_heapStart + 4 + READ_LE_UINT16(scr->_heapStart + 2) * 2; - while (READ_LE_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { + seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; + while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { reg_t reg; Object *obj; @@ -270,7 +271,7 @@ void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { // to be sufficient. obj->setClassScriptSelector(make_reg(0, scr->_nr)); - seeker += READ_LE_UINT16(seeker + 2) * 2; + seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; } } @@ -514,12 +515,12 @@ int script_instantiate_sci11(ResourceManager *resMan, SegManager *segMan, int sc _heapStart = script->size; if (script->size & 2) - _heapStart ++; + _heapStart++; scr->mcpyInOut(0, script->data, script->size); scr->mcpyInOut(_heapStart, heap->data, heap->size); - if (READ_LE_UINT16(script->data + 6) > 0) + if (READ_SCI11ENDIAN_UINT16(script->data + 6) > 0) scr->setExportTableOffset(6); reg.segment = seg_id; @@ -529,7 +530,7 @@ int script_instantiate_sci11(ResourceManager *resMan, SegManager *segMan, int sc segMan->scriptRelocateExportsSci11(seg_id); segMan->scriptInitialiseObjectsSci11(seg_id); - reg.offset = READ_LE_UINT16(heap->data); + reg.offset = READ_SCI11ENDIAN_UINT16(heap->data); scr->heapRelocate(reg); return seg_id; diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 57c9f47f24..da8e74e2d1 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -95,7 +95,7 @@ int propertyOffsetToId(SegManager *segMan, int prop_ofs, reg_t objp) { return -1; } - return READ_LE_UINT16(selectoroffset + prop_ofs); + return READ_SCI11ENDIAN_UINT16(selectoroffset + prop_ofs); } // Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered. @@ -164,7 +164,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod case Script_Word: case Script_SWord: - printf(" %04x", 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8))); + printf(" %04x", READ_SCI11ENDIAN_UINT16(&scr[retval.offset])); retval.offset += 2; break; @@ -178,7 +178,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (opsize) param_value = scr[retval.offset++]; else { - param_value = 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8)); + param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.offset]); retval.offset += 2; } @@ -195,7 +195,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (opsize) param_value = scr[retval.offset++]; else { - param_value = 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8)); + param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.offset]); retval.offset += 2; } printf(opsize ? " %02x" : " %04x", param_value); @@ -205,7 +205,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (opsize) param_value = scr[retval.offset++]; else { - param_value = 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8)); + param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.offset]); retval.offset += 2; } printf(opsize ? " %02x [%04x]" : " %04x [%04x]", param_value, (0xffff) & (retval.offset + param_value)); @@ -337,7 +337,7 @@ void script_debug(EngineState *s, bool bp) { int opcode = scriptState.xs->addr.pc.offset >= code_buf_size ? 0 : code_buf[scriptState.xs->addr.pc.offset]; int op = opcode >> 1; int paramb1 = scriptState.xs->addr.pc.offset + 1 >= code_buf_size ? 0 : code_buf[scriptState.xs->addr.pc.offset + 1]; - int paramf1 = (opcode & 1) ? paramb1 : (scriptState.xs->addr.pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_LE_UINT16(code_buf + scriptState.xs->addr.pc.offset + 1)); + int paramf1 = (opcode & 1) ? paramb1 : (scriptState.xs->addr.pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + scriptState.xs->addr.pc.offset + 1)); switch (g_debugState.seeking) { case kDebugSeekSpecialCallk: @@ -397,9 +397,9 @@ void script_debug(EngineState *s, bool bp) { void Kernel::dumpScriptObject(char *data, int seeker, int objsize) { int selectors, overloads, selectorsize; - int species = (int16)READ_LE_UINT16((unsigned char *) data + 8 + seeker); - int superclass = (int16)READ_LE_UINT16((unsigned char *) data + 10 + seeker); - int namepos = (int16)READ_LE_UINT16((unsigned char *) data + 14 + seeker); + int species = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *) data + 8 + seeker); + int superclass = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *) data + 10 + seeker); + int namepos = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *) data + 14 + seeker); int i = 0; printf("Object\n"); @@ -410,28 +410,28 @@ void Kernel::dumpScriptObject(char *data, int seeker, int objsize) { printf("Name: %s\n", namepos ? ((char *)(data + namepos)) : "<unknown>"); printf("Superclass: %x\n", superclass); printf("Species: %x\n", species); - printf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *) data + 12 + seeker) & 0xffff); + printf("-info-:%x\n", (int16)READ_SCI11ENDIAN_UINT16((unsigned char *) data + 12 + seeker) & 0xffff); - printf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *) data + seeker + 4)); - printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *) data + seeker + 6))); + printf("Function area offset: %x\n", (int16)READ_SCI11ENDIAN_UINT16((unsigned char *) data + seeker + 4)); + printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *) data + seeker + 6))); seeker += 8; while (selectors--) { - printf(" [#%03x] = 0x%x\n", i++, (int16)READ_LE_UINT16((unsigned char *)data + seeker) & 0xffff); + printf(" [#%03x] = 0x%x\n", i++, (int16)READ_SCI11ENDIAN_UINT16((unsigned char *)data + seeker) & 0xffff); seeker += 2; } - printf("Overridden functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker)); + printf("Overridden functions: %x\n", selectors = overloads = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *)data + seeker)); seeker += 2; if (overloads < 100) while (overloads--) { - int selector = (int16)READ_LE_UINT16((unsigned char *) data + (seeker)); + int selector = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *) data + (seeker)); printf(" [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>"); - printf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors*2 + 2) & 0xffff); + printf("%04x\n", (int16)READ_SCI11ENDIAN_UINT16((unsigned char *)data + seeker + selectors*2 + 2) & 0xffff); seeker += 2; } @@ -439,9 +439,9 @@ void Kernel::dumpScriptObject(char *data, int seeker, int objsize) { void Kernel::dumpScriptClass(char *data, int seeker, int objsize) { int selectors, overloads, selectorsize; - int species = (int16)READ_LE_UINT16((unsigned char *) data + 8 + seeker); - int superclass = (int16)READ_LE_UINT16((unsigned char *) data + 10 + seeker); - int namepos = (int16)READ_LE_UINT16((unsigned char *) data + 14 + seeker); + int species = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *) data + 8 + seeker); + int superclass = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *) data + 10 + seeker); + int namepos = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *) data + 14 + seeker); printf("Class\n"); @@ -450,35 +450,35 @@ void Kernel::dumpScriptClass(char *data, int seeker, int objsize) { printf("Name: %s\n", namepos ? ((char *)data + namepos) : "<unknown>"); printf("Superclass: %x\n", superclass); printf("Species: %x\n", species); - printf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *)data + 12 + seeker) & 0xffff); + printf("-info-:%x\n", (int16)READ_SCI11ENDIAN_UINT16((unsigned char *)data + 12 + seeker) & 0xffff); - printf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + 4)); - printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *)data + seeker + 6))); + printf("Function area offset: %x\n", (int16)READ_SCI11ENDIAN_UINT16((unsigned char *)data + seeker + 4)); + printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *)data + seeker + 6))); seeker += 8; selectorsize <<= 1; while (selectors--) { - int selector = (int16)READ_LE_UINT16((unsigned char *) data + (seeker) + selectorsize); + int selector = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *) data + (seeker) + selectorsize); printf(" [%03x] %s = 0x%x\n", 0xffff & selector, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>", - (int16)READ_LE_UINT16((unsigned char *)data + seeker) & 0xffff); + (int16)READ_SCI11ENDIAN_UINT16((unsigned char *)data + seeker) & 0xffff); seeker += 2; } seeker += selectorsize; - printf("Overloaded functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker)); + printf("Overloaded functions: %x\n", selectors = overloads = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *)data + seeker)); seeker += 2; while (overloads--) { - int selector = (int16)READ_LE_UINT16((unsigned char *)data + (seeker)); + int selector = (int16)READ_SCI11ENDIAN_UINT16((unsigned char *)data + (seeker)); fprintf(stderr, "selector=%d; selectorNames.size() =%d\n", selector, _selectorNames.size()); printf(" [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>"); - printf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors * 2 + 2) & 0xffff); + printf("%04x\n", (int16)READ_SCI11ENDIAN_UINT16((unsigned char *)data + seeker + selectors * 2 + 2) & 0xffff); seeker += 2; } @@ -495,7 +495,7 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { } while (_seeker < script->size) { - int objtype = (int16)READ_LE_UINT16(script->data + _seeker); + int objtype = (int16)READ_SCI11ENDIAN_UINT16(script->data + _seeker); int objsize; unsigned int seeker = _seeker + 4; @@ -508,7 +508,7 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { printf("\n"); - objsize = (int16)READ_LE_UINT16(script->data + _seeker + 2); + objsize = (int16)READ_SCI11ENDIAN_UINT16(script->data + _seeker + 2); printf("Obj type #%x, size 0x%x: ", objtype, objsize); diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 5804e5823e..0c6bb93aed 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -253,18 +253,18 @@ int Script::relocateObject(Object &obj, SegmentId segment, int location) { void Script::scriptAddCodeBlock(reg_t location) { CodeBlock cb; cb.pos = location; - cb.size = READ_LE_UINT16(_buf + location.offset - 2); + cb.size = READ_SCI11ENDIAN_UINT16(_buf + location.offset - 2); _codeBlocks.push_back(cb); } void Script::scriptRelocate(reg_t block) { - VERIFY(block.offset < (uint16)_bufSize && READ_LE_UINT16(_buf + block.offset) * 2 + block.offset < (uint16)_bufSize, + VERIFY(block.offset < (uint16)_bufSize && READ_SCI11ENDIAN_UINT16(_buf + block.offset) * 2 + block.offset < (uint16)_bufSize, "Relocation block outside of script\n"); - int count = READ_LE_UINT16(_buf + block.offset); + int count = READ_SCI11ENDIAN_UINT16(_buf + block.offset); for (int i = 0; i <= count; i++) { - int pos = READ_LE_UINT16(_buf + block.offset + 2 + (i * 2)); + int pos = READ_SCI11ENDIAN_UINT16(_buf + block.offset + 2 + (i * 2)); if (!pos) continue; // FIXME: A hack pending investigation @@ -302,16 +302,16 @@ void Script::scriptRelocate(reg_t block) { } void Script::heapRelocate(reg_t block) { - VERIFY(block.offset < (uint16)_heapSize && READ_LE_UINT16(_heapStart + block.offset) * 2 + block.offset < (uint16)_bufSize, + VERIFY(block.offset < (uint16)_heapSize && READ_SCI11ENDIAN_UINT16(_heapStart + block.offset) * 2 + block.offset < (uint16)_bufSize, "Relocation block outside of script\n"); if (_relocated) return; _relocated = true; - int count = READ_LE_UINT16(_heapStart + block.offset); + int count = READ_SCI11ENDIAN_UINT16(_heapStart + block.offset); for (int i = 0; i < count; i++) { - int pos = READ_LE_UINT16(_heapStart + block.offset + 2 + (i * 2)) + _scriptSize; + int pos = READ_SCI11ENDIAN_UINT16(_heapStart + block.offset + 2 + (i * 2)) + _scriptSize; if (!relocateLocal(block.segment, pos)) { bool done = false; @@ -359,7 +359,7 @@ void Script::setLockers(int lockers) { void Script::setExportTableOffset(int offset) { if (offset) { _exportTable = (uint16 *)(_buf + offset + 2); - _numExports = READ_LE_UINT16((byte *)(_exportTable - 1)); + _numExports = READ_SCI11ENDIAN_UINT16((byte *)(_exportTable - 1)); } else { _exportTable = NULL; _numExports = 0; @@ -380,7 +380,7 @@ uint16 SegManager::validateExportFunc(int pubfunct, SegmentId seg) { if (_exportsAreWide) pubfunct *= 2; - uint16 offset = READ_LE_UINT16((byte *)(scr->_exportTable + pubfunct)); + uint16 offset = READ_SCI11ENDIAN_UINT16((byte *)(scr->_exportTable + pubfunct)); VERIFY(offset < scr->_bufSize, "invalid export function pointer"); return offset; @@ -413,7 +413,7 @@ void Script::mcpyInOut(int dst, const void *src, size_t n) { int16 Script::getHeap(uint16 offset) const { assert(offset + 1 < (int)_bufSize); - return READ_LE_UINT16(_buf + offset); + return READ_SCI11ENDIAN_UINT16(_buf + offset); // return (_buf[offset] | (_buf[offset+1]) << 8); } @@ -695,7 +695,7 @@ int Object::locateVarSelector(SegManager *segMan, Selector slc) { } for (uint i = 0; i < varnum; i++) - if (READ_LE_UINT16(buf + (i << 1)) == slc) // Found it? + if (READ_SCI11ENDIAN_UINT16(buf + (i << 1)) == slc) // Found it? return i; // report success return -1; // Failed diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 0b60675a6b..28959f087a 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -29,6 +29,7 @@ #include "common/serializer.h" #include "sci/engine/vm.h" #include "sci/engine/vm_types.h" // for reg_t +#include "sci/util.h" namespace Sci { @@ -228,16 +229,16 @@ public: reg_t getClassScriptSelector() { return _variables[4]; } void setClassScriptSelector(reg_t value) { _variables[4] = value; } - Selector getVarSelector(uint16 i) { return *(_baseVars + i); } + Selector getVarSelector(uint16 i) { return READ_SCI11ENDIAN_UINT16(_baseVars + i); } reg_t getFunction(uint16 i) { uint16 offset = (getSciVersion() < SCI_VERSION_1_1) ? _methodCount + 1 + i : i * 2 + 2; - return make_reg(_pos.segment, READ_LE_UINT16((byte *) (_baseMethod + offset))); + return make_reg(_pos.segment, READ_SCI11ENDIAN_UINT16((byte *) (_baseMethod + offset))); } Selector getFuncSelector(uint16 i) { uint16 offset = (getSciVersion() < SCI_VERSION_1_1) ? i : i * 2 + 1; - return READ_LE_UINT16((byte *) (_baseMethod + offset)); + return READ_SCI11ENDIAN_UINT16((byte *) (_baseMethod + offset)); } /** @@ -280,14 +281,14 @@ public: _baseMethod = (uint16 *)(data + READ_LE_UINT16(data + SCRIPT_FUNCTAREAPTR_OFFSET)); _methodCount = READ_LE_UINT16(_baseMethod - 1); } else { - _variables.resize(READ_LE_UINT16(data + 2)); - _baseVars = (uint16 *)(buf + READ_LE_UINT16(data + 4)); - _baseMethod = (uint16 *)(buf + READ_LE_UINT16(data + 6)); - _methodCount = READ_LE_UINT16(_baseMethod); + _variables.resize(READ_SCI11ENDIAN_UINT16(data + 2)); + _baseVars = (uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 4)); + _baseMethod = (uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 6)); + _methodCount = READ_SCI11ENDIAN_UINT16(_baseMethod); } for (uint i = 0; i < _variables.size(); i++) - _variables[i] = make_reg(0, READ_LE_UINT16(data + (i * 2))); + _variables[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(data + (i * 2))); } reg_t getVariable(uint var) { return _variables[var]; } diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 3683795a79..eb12ca4203 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -650,11 +650,11 @@ int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]) break; case Script_Word: - opparams[i] = READ_LE_UINT16(src + offset); + opparams[i] = READ_SCI11ENDIAN_UINT16(src + offset); offset += 2; break; case Script_SWord: - opparams[i] = (int16)READ_LE_UINT16(src + offset); + opparams[i] = (int16)READ_SCI11ENDIAN_UINT16(src + offset); offset += 2; break; @@ -670,7 +670,7 @@ int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]) if (extOpcode & 1) { opparams[i] = src[offset++]; } else { - opparams[i] = READ_LE_UINT16(src + offset); + opparams[i] = READ_SCI11ENDIAN_UINT16(src + offset); offset += 2; } break; @@ -680,7 +680,7 @@ int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]) if (extOpcode & 1) { opparams[i] = (int8)src[offset++]; } else { - opparams[i] = (int16)READ_LE_UINT16(src + offset); + opparams[i] = (int16)READ_SCI11ENDIAN_UINT16(src + offset); offset += 2; } break; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index bc99f529aa..67e7835fb4 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -107,7 +107,7 @@ struct Class { reg_t reg; ///< offset; script-relative offset, segment: 0 if not instantiated }; -#define RAW_IS_OBJECT(datablock) (READ_LE_UINT16(((byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER) +#define RAW_IS_OBJECT(datablock) (READ_SCI11ENDIAN_UINT16(((byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER) /** Contains selector IDs for a few selected selectors */ struct SelectorCache { diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index e756c773ed..2f8393f9ac 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -205,6 +205,58 @@ void GfxCursor::kernelSetView(GuiResourceId viewNum, int loopNum, int celNum, Co delete cursorHotspot; } +void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNum, Common::Point *hotspot) { + // See http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-402.html + // for more information. + + // View 998 seems to be a fake resource used to call for for the Mac CURS resources + // For other resources, they're still in the views, so use them. + if (viewNum != 998) { + kernelSetView(viewNum, loopNum, celNum, hotspot); + return; + } + + // TODO: What about the 2000 resources? Inventory items? How to handle? + // TODO: What games does this work for? At least it does for KQ6. + // TODO: Stop asking rhetorical questions. + + Resource *resource = _resMan->findResource(ResourceId(kResourceTypeCursor, 1000 + celNum), false); + + if (!resource) { + warning("CURS %d not found", 1000 + celNum); + return; + } + + assert(resource); + + byte *cursorBitmap = new byte[16 * 16]; + byte *data = resource->data; + + // Get B&W data + for (byte i = 0; i < 32; i++) { + byte imageByte = *data++; + for (byte b = 0; b < 8; b++) + cursorBitmap[i * 8 + b] = (byte)((imageByte & (0x80 >> b)) > 0 ? 0x00 : 0xFF); + } + + // Apply mask data + for (byte i = 0; i < 32; i++) { + byte imageByte = *data++; + for (byte b = 0; b < 8; b++) + if ((imageByte & (0x80 >> b)) == 0) + cursorBitmap[i * 8 + b] = SCI_CURSOR_SCI0_TRANSPARENCYCOLOR; // Doesn't matter, just is transparent + } + + uint16 hotspotX = READ_BE_UINT16(data); + uint16 hotspotY = READ_BE_UINT16(data + 2); + + CursorMan.replaceCursor(cursorBitmap, 16, 16, hotspotX, hotspotY, SCI_CURSOR_SCI0_TRANSPARENCYCOLOR); + + delete[] cursorBitmap; + + kernelShow(); +} + void GfxCursor::setPosition(Common::Point pos) { if (!_upscaledHires) { g_system->warpMouse(pos.x, pos.y); diff --git a/engines/sci/graphics/cursor.h b/engines/sci/graphics/cursor.h index c0b5f9a478..6d92b3cf5f 100644 --- a/engines/sci/graphics/cursor.h +++ b/engines/sci/graphics/cursor.h @@ -52,6 +52,7 @@ public: bool isVisible(); void kernelSetShape(GuiResourceId resourceId); void kernelSetView(GuiResourceId viewNum, int loopNum, int celNum, Common::Point *hotspot); + void kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNum, Common::Point *hotspot); void setPosition(Common::Point pos); Common::Point getPosition(); void refreshPosition(); diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 5ce323751c..2ba14fbd8f 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -24,6 +24,7 @@ */ #include "sci/sci.h" +#include "sci/util.h" #include "sci/engine/state.h" #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" @@ -168,11 +169,11 @@ void GfxView::initData(GuiResourceId resourceId) { case kViewVga11: // View-format SCI1.1+ // HeaderSize:WORD LoopCount:BYTE Unknown:BYTE Version:WORD Unknown:WORD PaletteOffset:WORD - headerSize = READ_LE_UINT16(_resourceData + 0) + 2; // headerSize is not part of the header, so its added + headerSize = READ_SCI11ENDIAN_UINT16(_resourceData + 0) + 2; // headerSize is not part of the header, so its added assert(headerSize >= 16); _loopCount = _resourceData[2]; assert(_loopCount); - palOffset = READ_LE_UINT32(_resourceData + 8); + palOffset = READ_SCI11ENDIAN_UINT32(_resourceData + 8); // FIXME: After LoopCount there is another byte and its set for view 50 within Laura Bow 2 CD, check what it means loopData = _resourceData + headerSize; @@ -203,22 +204,24 @@ void GfxView::initData(GuiResourceId resourceId) { celCount = loopData[2]; _loop[loopNo].celCount = celCount; - celData = _resourceData + READ_LE_UINT32(loopData + 12); + celData = _resourceData + READ_SCI11ENDIAN_UINT32(loopData + 12); // read cel info _loop[loopNo].cel = new CelInfo[celCount]; for (celNo = 0; celNo < celCount; celNo++) { cel = &_loop[loopNo].cel[celNo]; - cel->width = READ_LE_UINT16(celData); - assert(cel->width); - cel->height = READ_LE_UINT16(celData + 2); - assert(cel->height); - cel->displaceX = READ_LE_UINT16(celData + 4); - cel->displaceY = READ_LE_UINT16(celData + 6); + cel->width = READ_SCI11ENDIAN_UINT16(celData); + cel->height = READ_SCI11ENDIAN_UINT16(celData + 2); + cel->displaceX = READ_SCI11ENDIAN_UINT16(celData + 4); + cel->displaceY = READ_SCI11ENDIAN_UINT16(celData + 6); + + assert(cel->width && cel->height); + cel->clearKey = celData[8]; cel->offsetEGA = 0; - cel->offsetRLE = READ_LE_UINT32(celData + 24); - cel->offsetLiteral = READ_LE_UINT32(celData + 28); + cel->offsetRLE = READ_SCI11ENDIAN_UINT32(celData + 24); + cel->offsetLiteral = READ_SCI11ENDIAN_UINT32(celData + 28); + cel->rawBitmap = 0; if (_loop[loopNo].mirrorFlag) cel->displaceX = -cel->displaceX; @@ -351,39 +354,41 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou } else { literalPtr = _resourceData + celInfo->offsetLiteral; if (celInfo->offsetRLE) { - // decompression for data that has separate rle and literal streams - while (pixelNo < pixelCount) { - pixel = *rlePtr++; - runLength = pixel & 0x3F; - switch (pixel & 0xC0) { - case 0: // copy bytes as-is - while (runLength-- && pixelNo < pixelCount) - outPtr[pixelNo++] = *literalPtr++; - break; - case 0x80: // fill with color - memset(outPtr + pixelNo, *literalPtr++, MIN<uint32>(runLength, pixelCount - pixelNo)); - pixelNo += runLength; - break; - case 0xC0: // fill with transparent + if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) { + // Crazy-Ass compression for SCI1.1+ Mac + while (pixelNo < pixelCount) { + uint32 pixelLine = pixelNo; + runLength = *rlePtr++; pixelNo += runLength; - break; + runLength = *rlePtr++; + while (runLength-- && pixelNo < pixelCount) { + outPtr[pixelNo] = *literalPtr++; + if (outPtr[pixelNo] == 255) + outPtr[pixelNo] = 0; + pixelNo++; + } + pixelNo = pixelLine + celInfo->width; + } + } else { + // decompression for data that has separate rle and literal streams + while (pixelNo < pixelCount) { + pixel = *rlePtr++; + runLength = pixel & 0x3F; + switch (pixel & 0xC0) { + case 0: // copy bytes as-is + while (runLength-- && pixelNo < pixelCount) + outPtr[pixelNo++] = *literalPtr++; + break; + case 0x80: // fill with color + memset(outPtr + pixelNo, *literalPtr++, MIN<uint32>(runLength, pixelCount - pixelNo)); + pixelNo += runLength; + break; + case 0xC0: // fill with transparent + pixelNo += runLength; + break; + } } } - // Crazy-Ass mac compression for clone2727 - // uint32 pixelLine; - // while (pixelNo < pixelCount) { - // pixelLine = pixelNo; - // runLength = *rlePtr++; - // pixelNo += runLength; - // runLength = *rlePtr++; - // while (runLength-- && pixelNo < pixelCount) { - // outPtr[pixelNo] = *literalPtr++; - // if (outPtr[pixelNo] == 255) - // outPtr[pixelNo] = 0; - // pixelNo++; - // } - // pixelNo = pixelLine + celInfo->width; - // } } else { // literal stream only, so no compression memcpy(outPtr, literalPtr, pixelCount); diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 852f97b225..8c4d666ba7 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -7,6 +7,7 @@ MODULE_OBJS := \ event.o \ resource.o \ sci.o \ + util.o \ engine/features.o \ engine/game.o \ engine/gc.o \ diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 42f5d15a2c..4888dbd4cb 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -29,6 +29,7 @@ #include "common/macresman.h" #include "sci/resource.h" +#include "sci/util.h" namespace Sci { @@ -581,6 +582,15 @@ int ResourceManager::addAppropriateSources() { addSource(0, kSourceMacResourceFork, filename.c_str(), atoi(filename.c_str() + 4)); } #ifdef ENABLE_SCI32 + // Mac SCI32 games have extra folders for patches + addPatchDir("Robot Folder"); + addPatchDir("Sound Folder"); + addPatchDir("Voices Folder"); + //addPatchDir("VMD Folder"); + + // There can also be a "Patches" resource fork with patches + if (Common::File::exists("Patches")) + addSource(0, kSourceMacResourceFork, "Patches", 100); } else { // SCI2.1-SCI3 file naming scheme Common::ArchiveMemberList mapFiles; @@ -750,11 +760,8 @@ void ResourceManager::scanNewSources() { } void ResourceManager::freeResourceSources() { - for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) { - if ((*it)->source_type == kSourceMacResourceFork) - (*it)->macResMan.close(); + for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) delete *it; - } _sources.clear(); } @@ -1452,18 +1459,32 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { return 0; } -static const uint32 resourceTypeMacTags[] = { - 'V56 ', 'P56 ', 'SCR ', 'TEX ', 'SND ', - 0, 'VOC ', 'FON ', 0, 'Pat ', // 'CURS is a mac cursor, not sure if it goes in - 0, 'PAL ', 0, 0, 0, - 'MSG ', 0, 'HEP ' +struct { + uint32 tag; + ResourceType type; +} static const macResTagMap[] = { + { MKID_BE('V56 '), kResourceTypeView }, + { MKID_BE('P56 '), kResourceTypePic }, + { MKID_BE('SCR '), kResourceTypeScript }, + { MKID_BE('TEX '), kResourceTypeText }, + { MKID_BE('SND '), kResourceTypeSound }, + { MKID_BE('VOC '), kResourceTypeVocab }, + { MKID_BE('FON '), kResourceTypeFont }, + { MKID_BE('CURS'), kResourceTypeCursor }, + { MKID_BE('crsr'), kResourceTypeCursor }, + { MKID_BE('Pat '), kResourceTypePatch }, + { MKID_BE('PAL '), kResourceTypePalette }, + { MKID_BE('snd '), kResourceTypeAudio }, + { MKID_BE('MSG '), kResourceTypeMessage }, + { MKID_BE('HEP '), kResourceTypeHeap } }; static uint32 resTypeToMacTag(ResourceType type) { - if (type >= ARRAYSIZE(resourceTypeMacTags)) - return 0; + for (uint32 i = 0; i < ARRAYSIZE(macResTagMap); i++) + if (macResTagMap[i].type == type) + return macResTagMap[i].tag; - return resourceTypeMacTags[type]; + return 0; } int ResourceManager::readMacResourceFork(ResourceSource *source) { @@ -1476,9 +1497,9 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) { ResourceType type = kResourceTypeInvalid; // Map the Mac tags to our ResourceType - for (uint32 j = 0; j < ARRAYSIZE(resourceTypeMacTags); j++) - if (tagArray[i] == resourceTypeMacTags[j]) { - type = (ResourceType)j; + for (uint32 j = 0; j < ARRAYSIZE(macResTagMap); j++) + if (tagArray[i] == macResTagMap[j].tag) { + type = macResTagMap[j].type; break; } @@ -1492,7 +1513,7 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) { Resource *newrsc = NULL; - // Prepare destination, if neccessary + // Prepare destination, if neccessary. Resource forks may contain patches. if (!_resMap.contains(resId)) { newrsc = new Resource; _resMap.setVal(resId, newrsc); @@ -1500,11 +1521,11 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) { newrsc = _resMap.getVal(resId); // Get the size of the file - Common::SeekableReadStream *stream = source->macResMan.getResource(tagArray[i], idArray[j]);; + Common::SeekableReadStream *stream = source->macResMan.getResource(tagArray[i], idArray[j]); uint32 fileSize = stream->size(); delete stream; - // Overwrite everything, because we're patching + // Overwrite everything newrsc->_id = resId; newrsc->_status = kResStatusNoMalloc; newrsc->_source = source; @@ -2045,7 +2066,7 @@ void ResourceManager::detectSciVersion() { // Set view type if (viewCompression == kCompDCL || _volVersion == kResVersionSci11 // pq4demo - || _volVersion == kResVersionSci11Mac // FIXME: Is this right? + || _volVersion == kResVersionSci11Mac #ifdef ENABLE_SCI32 || viewCompression == kCompSTACpack || _volVersion == kResVersionSci32 // kq7 @@ -2064,6 +2085,8 @@ void ResourceManager::detectSciVersion() { // TODO: Decide between SCI2 and SCI2.1 if (Common::File::exists("resource.cfg")) s_sciVersion = SCI_VERSION_1_1; + else if (Common::File::exists("Patches")) + s_sciVersion = SCI_VERSION_2_1; else s_sciVersion = SCI_VERSION_2; return; diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index b162667890..331561eea4 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -271,31 +271,42 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 Common::MemoryReadStream dataStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); data = readSOLAudio(&dataStream, size, audioFlags, flags); } + } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKID_BE('RIFF')) { + // WAVE detected + Common::MemoryReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); + + // Calculate samplelen from WAVE header + int waveSize = 0, waveRate = 0; + byte waveFlags = 0; + Audio::loadWAVFromStream(*waveStream, waveSize, waveRate, waveFlags); + *sampleLen = (waveFlags & Audio::FLAG_16BITS ? waveSize >> 1 : waveSize) * 60 / waveRate; + + waveStream->seek(0, SEEK_SET); + audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES); + } else if (audioRes->size > 14 && READ_BE_UINT16(audioRes->data) == 1 && READ_BE_UINT16(audioRes->data + 2) == 1 + && READ_BE_UINT16(audioRes->data + 4) == 5 && READ_BE_UINT32(audioRes->data + 10) == 0x00018051) { + // Mac snd detected + // See http://developer.apple.com/legacy/mac/library/documentation/mac/Sound/Sound-60.html#HEADING60-15 for more details + + uint32 soundHeaderOffset = READ_BE_UINT32(audioRes->data + 16); + assert(READ_BE_UINT32(audioRes->data + soundHeaderOffset) == 0); + size = READ_BE_UINT32(audioRes->data + soundHeaderOffset + 4); + _audioRate = READ_BE_UINT16(audioRes->data + soundHeaderOffset + 8); // Really floating point, but we're just truncating + + if (*(audioRes->data + soundHeaderOffset + 20) != 0) + error("Unhandled Mac snd extended/compressed header"); + + data = (byte *)malloc(size); + memcpy(data, audioRes->data + soundHeaderOffset + 22, size); + flags = Audio::FLAG_UNSIGNED; } else { - // SCI1 or WAVE file - if (audioRes->size > 4) { - if (memcmp(audioRes->data, "RIFF", 4) == 0) { - // WAVE detected - Common::MemoryReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); - - // Calculate samplelen from WAVE header - int waveSize = 0, waveRate = 0; - byte waveFlags = 0; - Audio::loadWAVFromStream(*waveStream, waveSize, waveRate, waveFlags); - *sampleLen = (waveFlags & Audio::FLAG_16BITS ? waveSize >> 1 : waveSize) * 60 / waveRate; - - waveStream->seek(0, SEEK_SET); - audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES); - } - } - if (!audioStream) { - // SCI1 raw audio - size = audioRes->size; - data = (byte *)malloc(size); - assert(data); - memcpy(data, audioRes->data, size); - flags = Audio::FLAG_UNSIGNED; - } + // SCI1 raw audio + size = audioRes->size; + data = (byte *)malloc(size); + assert(data); + memcpy(data, audioRes->data, size); + flags = Audio::FLAG_UNSIGNED; + _audioRate = 11025; } if (data) diff --git a/engines/sci/util.cpp b/engines/sci/util.cpp new file mode 100644 index 0000000000..9bda73ae4a --- /dev/null +++ b/engines/sci/util.cpp @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/endian.h" + +#include "sci/util.h" +#include "sci/sci.h" + +namespace Sci { + +uint16 READ_SCI11ENDIAN_UINT16(const void *ptr) { + if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) + return READ_BE_UINT16(ptr); + + return READ_LE_UINT16(ptr); +} + +uint32 READ_SCI11ENDIAN_UINT32(const void *ptr) { + if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) + return READ_BE_UINT32(ptr); + + return READ_LE_UINT32(ptr); +} + +void WRITE_SCI11ENDIAN_UINT16(void *ptr, uint16 val) { + if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) + WRITE_BE_UINT16(ptr, val); + else + WRITE_LE_UINT16(ptr, val); +} + +} // End of namespace Sci diff --git a/engines/sci/util.h b/engines/sci/util.h new file mode 100644 index 0000000000..5c4b95b8c4 --- /dev/null +++ b/engines/sci/util.h @@ -0,0 +1,41 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SCI_UTIL_H +#define SCI_UTIL_H + +#include "common/scummsys.h" + +namespace Sci { + +// Wrappers for reading integer values for SCI1.1+. +// Mac versions have big endian data for some fields. +uint16 READ_SCI11ENDIAN_UINT16(const void *ptr); +uint32 READ_SCI11ENDIAN_UINT32(const void *ptr); +void WRITE_SCI11ENDIAN_UINT16(void *ptr, uint16 val); + +} // End of namespace Sci + +#endif |