diff options
author | Travis Howell | 2008-04-06 07:05:56 +0000 |
---|---|---|
committer | Travis Howell | 2008-04-06 07:05:56 +0000 |
commit | 27816d8c8bd1c3d4dfbacf5d3973825c9085f349 (patch) | |
tree | 891c57fbbbeb41aa7a07ca42f6c2a4fa026ddf32 | |
parent | 3d1a2e2049d599d88dc834a05dd25978f8a0f8f7 (diff) | |
download | scummvm-rg350-27816d8c8bd1c3d4dfbacf5d3973825c9085f349.tar.gz scummvm-rg350-27816d8c8bd1c3d4dfbacf5d3973825c9085f349.tar.bz2 scummvm-rg350-27816d8c8bd1c3d4dfbacf5d3973825c9085f349.zip |
Add very basic support for Amiga version of BRA.
svn-id: r31416
-rw-r--r-- | engines/parallaction/detection.cpp | 17 | ||||
-rw-r--r-- | engines/parallaction/disk.h | 25 | ||||
-rw-r--r-- | engines/parallaction/disk_br.cpp | 322 | ||||
-rw-r--r-- | engines/parallaction/font.cpp | 23 | ||||
-rw-r--r-- | engines/parallaction/gui_br.cpp | 13 | ||||
-rw-r--r-- | engines/parallaction/parallaction_br.cpp | 35 |
6 files changed, 414 insertions, 21 deletions
diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp index 352c5a2d01..a84601f6f9 100644 --- a/engines/parallaction/detection.cpp +++ b/engines/parallaction/detection.cpp @@ -157,6 +157,23 @@ static const PARALLACTIONGameDescription gameDescriptions[] = { GF_LANG_EN | GF_LANG_FR | GF_LANG_DE | GF_LANG_IT | GF_LANG_MULT }, + // TODO: Base the detection of Amiga BRA on actual data file, not executable file. + { + { + "bra", + "Multi-lingual", + { + { "bigred", 0, "4f1e6bfd974b8ebabaad96d536904477", 95232 }, + { NULL, 0, NULL, 0} + }, + Common::UNK_LANG, + Common::kPlatformAmiga, + Common::ADGF_NO_FLAGS + }, + GType_BRA, + GF_LANG_EN | GF_LANG_FR | GF_LANG_DE | GF_LANG_IT | GF_LANG_MULT + }, + { AD_TABLE_END_MARKER, 0, 0 } }; diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h index 7c24655033..13bdd2a73f 100644 --- a/engines/parallaction/disk.h +++ b/engines/parallaction/disk.h @@ -228,12 +228,35 @@ public: Frames* loadStatic(const char* name); Frames* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); - void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path); + void loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path); Table* loadTable(const char* name); Common::SeekableReadStream* loadMusic(const char* name); Common::ReadStream* loadSound(const char* name); }; +class AmigaDisk_br : public DosDisk_br { + +protected: + BackgroundInfo _backgroundTemp; + + Sprites* createSprites(const char *name); + void unpackFrame(byte *dst, byte *src, uint16 planeSize); + void unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 bytesPerPlane, uint16 height); + Font *createFont(const char *name, Common::SeekableReadStream &stream); + void loadMask(BackgroundInfo& info, const char *name); + void loadBackground(BackgroundInfo& info, const char *name); + +public: + AmigaDisk_br(Parallaction *vm); + virtual ~AmigaDisk_br(); + + Frames* loadTalk(const char *name); + Font* loadFont(const char* name); + Frames* loadStatic(const char* name); + Frames* loadFrames(const char* name); + void loadSlide(BackgroundInfo& info, const char *filename); + void loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path); +}; } // namespace Parallaction diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index ad24b94c9f..fa2658061f 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -23,6 +23,8 @@ * */ +#include "graphics/iff.h" + #include "parallaction/parallaction.h" @@ -394,4 +396,324 @@ Common::ReadStream* DosDisk_br::loadSound(const char* name) { } + + + + +AmigaDisk_br::AmigaDisk_br(Parallaction *vm) : DosDisk_br(vm) { + +} + + +AmigaDisk_br::~AmigaDisk_br() { + +} + +#define NUM_PLANES 5 + +/* + unpackFrame transforms images from 5-bitplanes format to + 8-bit color-index mode +*/ +void AmigaDisk_br::unpackFrame(byte *dst, byte *src, uint16 planeSize) { + + byte s0, s1, s2, s3, s4, mask, t0, t1, t2, t3, t4; + + for (uint32 j = 0; j < planeSize; j++) { + s0 = src[j]; + s1 = src[j+planeSize]; + s2 = src[j+planeSize*2]; + s3 = src[j+planeSize*3]; + s4 = src[j+planeSize*4]; + + for (uint32 k = 0; k < 8; k++) { + mask = 1 << (7 - k); + t0 = (s0 & mask ? 1 << 0 : 0); + t1 = (s1 & mask ? 1 << 1 : 0); + t2 = (s2 & mask ? 1 << 2 : 0); + t3 = (s3 & mask ? 1 << 3 : 0); + t4 = (s4 & mask ? 1 << 4 : 0); + *dst++ = t0 | t1 | t2 | t3 | t4; + } + + } + +} + +// FIXME: no mask is loaded +void AmigaDisk_br::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 bytesPerPlane, uint16 height) { + uint16 planeSize = bytesPerPlane * height; + + for (uint32 i = 0; i < numFrames; i++) { + unpackFrame(dst, src, planeSize); + src += planeSize * NUM_PLANES; + dst += planeSize * 8; + } +} + +#undef NUM_PLANES + +/* + FIXME: mask values are not computed correctly for level 1 and 2 + + NOTE: this routine is only able to build masks for Nippon Safes, since mask widths are hardcoded + into the main loop. +*/ +void buildMask2(byte* buf) { + + byte mask1[16] = { 0, 0x80, 0x20, 0xA0, 8, 0x88, 0x28, 0xA8, 2, 0x82, 0x22, 0xA2, 0xA, 0x8A, 0x2A, 0xAA }; + byte mask0[16] = { 0, 0x40, 0x10, 0x50, 4, 0x44, 0x14, 0x54, 1, 0x41, 0x11, 0x51, 0x5, 0x45, 0x15, 0x55 }; + + byte plane0[40]; + byte plane1[40]; + + for (int32 i = 0; i < _vm->_screenHeight; i++) { + + memcpy(plane0, buf, 40); + memcpy(plane1, buf+40, 40); + + for (uint32 j = 0; j < 40; j++) { + *buf++ = mask0[(plane0[j] & 0xF0) >> 4] | mask1[(plane1[j] & 0xF0) >> 4]; + *buf++ = mask0[plane0[j] & 0xF] | mask1[plane1[j] & 0xF]; + } + + } +} + +class BackgroundDecoder : public Graphics::ILBMDecoder { + + PaletteFxRange *_range; + uint32 _i; + +protected: + void readCRNG(Common::IFFChunk &chunk) { + _range[_i]._timer = chunk.readUint16BE(); + _range[_i]._step = chunk.readUint16BE(); + _range[_i]._flags = chunk.readUint16BE(); + _range[_i]._first = chunk.readByte(); + _range[_i]._last = chunk.readByte(); + + _i++; + } + +public: + BackgroundDecoder(Common::ReadStream &input, Graphics::Surface &surface, byte *&colors, PaletteFxRange *range) : + Graphics::ILBMDecoder(input, surface, colors), _range(range), _i(0) { + } + + void decode() { + Common::IFFChunk *chunk; + while ((chunk = nextChunk()) != 0) { + switch (chunk->id) { + case ID_BMHD: + readBMHD(*chunk); + break; + + case ID_CMAP: + readCMAP(*chunk); + break; + + case ID_BODY: + readBODY(*chunk); + break; + + case ID_CRNG: + readCRNG(*chunk); + break; + } + } + } + + uint32 getNumRanges() { + return _i; + } +}; + + +void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *name) { + + char path[PATH_LEN]; + sprintf(path, "%s", name); + + Common::File s; + + if (!s.open(path)) + errorFileNotFound(path); + + byte *pal; + PaletteFxRange ranges[6]; + + BackgroundDecoder decoder(s, info.bg, pal, ranges); + decoder.decode(); + + uint i; + + info.width = info.bg.w; + info.height = info.bg.h; + + byte *p = pal; + for (i = 0; i < 32; i++) { + byte r = *p >> 2; + p++; + byte g = *p >> 2; + p++; + byte b = *p >> 2; + p++; + info.palette.setEntry(i, r, g, b); + } + + free(pal); + + for (i = 0; i < 6; i++) { + info.setPaletteRange(i, ranges[i]); + } + + return; + +} + +void AmigaDisk_br::loadMask(BackgroundInfo& info, const char *name) { + debugC(5, kDebugDisk, "AmigaDisk_br::loadMask(%s)", name); + + Common::File s; + + if (!s.open(name)) + return; + + s.seek(0x30, SEEK_SET); + + byte r, g, b; + for (uint i = 0; i < 4; i++) { + r = s.readByte(); + g = s.readByte(); + b = s.readByte(); + + info.layers[i] = (((r << 4) & 0xF00) | (g & 0xF0) | (b >> 4)) & 0xFF; + } + + s.seek(0x126, SEEK_SET); // HACK: skipping IFF/ILBM header should be done by analysis, not magic + Graphics::PackBitsReadStream stream(s); + + info.mask.create(info.width, info.height); + stream.read(info.mask.data, info.mask.size); + buildMask2(info.mask.data); + + return; +} + +void AmigaDisk_br::loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path) { + debugC(1, kDebugDisk, "AmigaDisk_br::loadScenery '%s', '%s' '%s'", name, mask, path); + + char filename[PATH_LEN]; + Common::File stream; + + if (name) { + sprintf(filename, "%s/backs/%s.bkg", _partPath, name); + + loadBackground(info, filename); + } + + if (mask) { + sprintf(filename, "%s/msk/%s.msk", _partPath, name); + + loadMask(info, filename); + } + + if (path) { + sprintf(filename, "%s/pth/%s.pth", _partPath, path); + if (!stream.open(filename)) + errorFileNotFound(filename); + + // NOTE: info.width and info.height are only valid if the background graphics + // have already been loaded + info.path.create(info.width, info.height); + stream.read(info.path.data, info.path.size); + stream.close(); + } + + return; +} + +void AmigaDisk_br::loadSlide(BackgroundInfo& info, const char *name) { + debugC(1, kDebugDisk, "AmigaDisk_br::loadSlide '%s'", name); + + char path[PATH_LEN]; + sprintf(path, "backs/%s.bkg", name); + + loadBackground(info, path); + return; +} + +Frames* AmigaDisk_br::loadStatic(const char* name) { + debugC(1, kDebugDisk, "AmigaDisk_br::loadStatic '%s'", name); + + char path[PATH_LEN]; + sprintf(path, "%s/ras/%s", _partPath, name); + Common::File stream; + if (!stream.open(path)) { + errorFileNotFound(path); + } + + loadBackground(_backgroundTemp, path); + return new SurfaceToFrames(&_backgroundTemp.bg); +} + +Sprites* AmigaDisk_br::createSprites(const char *path) { + + Common::File stream; + if (!stream.open(path)) { + errorFileNotFound(path); + } + + uint16 num = stream.readUint16BE(); + + Sprites *sprites = new Sprites(num); + + for (uint i = 0; i < num; i++) { + Sprite *spr = &sprites->_sprites[i]; + spr->size = stream.readUint16BE(); + spr->x = stream.readUint16BE(); + spr->y = stream.readUint16BE(); + spr->w = stream.readUint16BE(); + spr->h = stream.readUint16BE(); + + // TODO: Convert image format + spr->packedData = (byte*)malloc(spr->size); + stream.read(spr->packedData, spr->size); + } + + return sprites; +} + +Frames* AmigaDisk_br::loadFrames(const char* name) { + debugC(1, kDebugDisk, "AmigaDisk_br::loadFrames '%s'", name); + + char path[PATH_LEN]; + sprintf(path, "%s/anims/%s", _partPath, name); + + return createSprites(path); +} + +Frames* AmigaDisk_br::loadTalk(const char *name) { + debugC(1, kDebugDisk, "AmigaDisk_br::loadTalk '%s'", name); + + char path[PATH_LEN]; + sprintf(path, "%s/talks/%s.tal", _partPath, name); + + return createSprites(path); +} + +Font* AmigaDisk_br::loadFont(const char* name) { + debugC(1, kDebugDisk, "AmigaFullDisk::loadFont '%s'", name); + + char path[PATH_LEN]; + sprintf(path, "%s", name); + + Common::File stream; + if (!stream.open(path)) + errorFileNotFound(path); + + return createFont(name, stream); +} + } // namespace Parallaction diff --git a/engines/parallaction/font.cpp b/engines/parallaction/font.cpp index 64d2d170ee..bc67acf644 100644 --- a/engines/parallaction/font.cpp +++ b/engines/parallaction/font.cpp @@ -540,6 +540,11 @@ Font *DosDisk_br::createFont(const char *name, Common::ReadStream &stream) { return new BraFont(stream); } +Font *AmigaDisk_br::createFont(const char *name, Common::SeekableReadStream &stream) { + // TODO: implement AmigaLabelFont for labels + return new AmigaFont(stream); +} + void Parallaction_ns::initFonts() { if (getPlatform() == Common::kPlatformPC) { @@ -557,4 +562,22 @@ void Parallaction_ns::initFonts() { } +void Parallaction_br::initFonts() { + if (getPlatform() == Common::kPlatformPC) { + _menuFont = _disk->loadFont("russia"); + _dialogueFont = _disk->loadFont("comic"); + _labelFont = _menuFont; + } else { + // TODO: Confirm fonts matches + // fonts/natasha/16 + // fonts/sonya/18 + // fonts/vanya/16 + + _menuFont = _disk->loadFont("fonts/natasha/16"); + _dialogueFont = _disk->loadFont("fonts/sonya/18"); + Common::MemoryReadStream stream(_amigaTopazFont, 2600, false); + _labelFont = new AmigaFont(stream); + } +} + } diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp index 592de7bf9b..8ce559e644 100644 --- a/engines/parallaction/gui_br.cpp +++ b/engines/parallaction/gui_br.cpp @@ -60,7 +60,6 @@ void Parallaction_br::guiStart() { _disk->selectArchive(_partNames[_part]); startPart(); } - } void Parallaction_br::guiSplash(const char *name) { @@ -98,7 +97,11 @@ Frames* Parallaction_br::guiRenderMenuItem(const char *text) { surf->create(MENUITEM_WIDTH, MENUITEM_HEIGHT*2, 1); // build first frame to be displayed when item is not selected - _menuFont->setColor(0); + if (getPlatform() == Common::kPlatformPC) { + _menuFont->setColor(0); + } else { + _menuFont->setColor(7); + } _menuFont->drawString((byte*)surf->getBasePtr(5, 2), MENUITEM_WIDTH, text); // build second frame to be displayed when item is selected @@ -141,8 +144,10 @@ int Parallaction_br::guiShowMenu() { _gfx->clearScreen(); _gfx->setBackground(kBackgroundSlide, "tbra", 0, 0); - _gfx->_backgroundInfo.x = 20; - _gfx->_backgroundInfo.y = 50; + if (getPlatform() == Common::kPlatformPC) { + _gfx->_backgroundInfo.x = 20; + _gfx->_backgroundInfo.y = 50; + } int availItems = 4 + _progress; diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index 93174c9d47..34d6868b52 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -57,12 +57,16 @@ int Parallaction_br::init() { if (getPlatform() == Common::kPlatformPC) { _disk = new DosDisk_br(this); _disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters. - } else - error("unsupported platform for Big Red Adventure"); - } else + _soundMan = new DummySoundMan(this); + } else { + _disk = new AmigaDisk_br(this); + _disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters. + _soundMan = new AmigaSoundMan(this); + } + } else { error("unknown game type"); + } - _soundMan = new DummySoundMan(this); initResources(); initFonts(); @@ -119,14 +123,6 @@ int Parallaction_br::go() { -void Parallaction_br::initFonts() { - - _menuFont = _disk->loadFont("russia"); - _dialogueFont = _disk->loadFont("comic"); - _labelFont = _menuFont; - -} - void Parallaction_br::freeFonts() { delete _menuFont; @@ -137,15 +133,22 @@ void Parallaction_br::freeFonts() { void Parallaction_br::initCursors() { - _dinoCursor = _disk->loadPointer("pointer1"); - _dougCursor = _disk->loadPointer("pointer2"); - _donnaCursor = _disk->loadPointer("pointer3"); + if (getPlatform() == Common::kPlatformPC) { + _dinoCursor = _disk->loadPointer("pointer1"); + _dougCursor = _disk->loadPointer("pointer2"); + _donnaCursor = _disk->loadPointer("pointer3"); - _mouseArrow = _donnaCursor; + _mouseArrow = _donnaCursor; + } else { + // TODO: Where are the Amiga cursors? + } } void Parallaction_br::setMousePointer(int16 index) { + // FIXME: Where are the Amiga cursors? + if (getPlatform() == Common::kPlatformAmiga) + return; Common::Rect r; _mouseArrow->getRect(0, r); |