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
This commit is contained in:
parent
0fe2ba6a0d
commit
3dda73d9a2
18 changed files with 404 additions and 180 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
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;
|
||||
case 0xC0: // fill with transparent
|
||||
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);
|
||||
|
|
|
@ -7,6 +7,7 @@ MODULE_OBJS := \
|
|||
event.o \
|
||||
resource.o \
|
||||
sci.o \
|
||||
util.o \
|
||||
engine/features.o \
|
||||
engine/game.o \
|
||||
engine/gc.o \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
54
engines/sci/util.cpp
Normal file
54
engines/sci/util.cpp
Normal file
|
@ -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
|
41
engines/sci/util.h
Normal file
41
engines/sci/util.h
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue