From f86768fee8aabb448152092b95a0a0b08e59eb63 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Wed, 16 Mar 2005 03:20:32 +0000 Subject: Preliminary support for NES charsets. Colors are wrong and we get glitches caused by too narrow screen. Also text clearing doesn't work. svn-id: r17164 --- scumm/charset.cpp | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++ scumm/charset.h | 17 ++++++ scumm/costume.cpp | 20 +++---- scumm/gfx.cpp | 23 ++++---- scumm/gfx.h | 2 +- scumm/script_v2.cpp | 2 +- scumm/scumm.cpp | 8 ++- scumm/scumm.h | 10 +++- 8 files changed, 207 insertions(+), 28 deletions(-) (limited to 'scumm') diff --git a/scumm/charset.cpp b/scumm/charset.cpp index 52497aef14..8a3ae390f8 100644 --- a/scumm/charset.cpp +++ b/scumm/charset.cpp @@ -1669,6 +1669,159 @@ void CharsetRendererNut::printChar(int chr) { _str.bottom = shadow.bottom; } +static byte trNESEnglishTable[] = { + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x0A, 0x07, 0x00, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x2C, 0x2D, 0x2E, 0x00, 0x00, 0x00, 0x2F, 0x00, + 0x03, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x2C, 0x2D, 0x2E, 0x00, 0x00, 0x00, 0x05, 0x08, + 0x20, 0x20, 0x21, 0x60, 0x27, 0x7E, 0x2C, 0x2E, + 0x7F, 0x3F, 0x2D, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, + 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5E +}; + +static byte trNESFrenchTable[] = { + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x64, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x0A, 0x07, 0x00, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x00, 0x00, 0x15, 0x15, 0x64, 0x09, + 0x00, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x2C, 0x2D, 0x2E, 0x19, 0x19, 0x19, 0x2F, 0x29, + 0x03, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x2C, 0x2D, 0x2E, 0x1D, 0x23, 0x29, 0x05, 0x08, + 0x20, 0x20, 0x21, 0x60, 0x27, 0x7E, 0x2C, 0x2E, + 0x7F, 0x3F, 0x2D, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, + 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5E +}; + +static byte trNESSwedishTable[] = { + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x0A, 0x07, 0x00, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x00, 0x00, 0x61, 0x00, 0x64, 0x09, + 0x00, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x2C, 0x2D, 0x2E, 0x62, 0x63, 0x00, 0x2F, 0x00, + 0x03, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x2C, 0x2D, 0x2E, 0x63, 0x64, 0x61, 0x05, 0x08, + 0x20, 0x20, 0x21, 0x60, 0x27, 0x7E, 0x2C, 0x2E, + 0x7F, 0x3F, 0x2D, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, + 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5E +}; + + +CharsetRendererNES::CharsetRendererNES(ScummEngine *vm, Common::Language language) + : CharsetRendererCommon(vm) { + switch (language) { + case Common::FR_FRA: + _trTable = trNESFrenchTable; + break; + case Common::SE_SWE: + _trTable = trNESSwedishTable; + break; + default: + _trTable = trNESEnglishTable; + break; + } +} + +void CharsetRendererNES::printChar(int chr) { + int width, height, origWidth, origHeight; + VirtScreen *vs; + byte *charPtr, *dst; + + if ((vs = _vm->findVirtScreen(_top)) == NULL) + return; + + if (chr == '@') + return; + + charPtr = _vm->_NESPatTable + _trTable[chr - 32] * 16; + width = getCharWidth(chr); + height = 8; + + origWidth = width; + origHeight = height; + + if (_firstChar) { + _str.left = _left; + _str.top = _top; + _str.right = _left; + _str.bottom = _top; + _firstChar = false; + } + + int drawTop = _top - vs->topline; + + _vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height); + + if (!_ignoreCharsetMask) { + _hasMask = true; + _textScreenID = vs->number; + } + dst = (byte *)_vm->gdi._textSurface.pixels + _top * _vm->gdi._textSurface.pitch + _left; + drawBits1(_vm->gdi._textSurface, dst, charPtr, drawTop, origWidth, origHeight); + + if (_str.left > _left) + _str.left = _left; + + _left += origWidth; + + if (_str.right < _left) { + _str.right = _left; + if (_dropShadow) + _str.right++; + } + + if (_str.bottom < _top + height) + _str.bottom = _top + height; +} + +void CharsetRendererNES::drawChar(int chr, const Graphics::Surface &s, int x, int y) { + byte *charPtr, *dst; + int width, height; + + charPtr = _vm->_NESPatTable + _trTable[chr - 32] * 16; + width = getCharWidth(chr); + height = 8; + + dst = (byte *)s.pixels + y * s.pitch + x; + drawBits1(s, dst, charPtr, y, width, height); +} + +void CharsetRendererNES::drawBits1(const Graphics::Surface &s, byte *dst, const byte *src, int drawTop, int width, int height) { + for (int i = 0; i < 8; i++) { + byte c0 = src[i]; + byte c1 = src[i + 8]; + for (int j = 0; j < 8; j++) + dst[j] = _vm->_NESPalette[((c0 >> (7 - j)) & 1) | (((c1 >> (7 - j)) & 1) << 1)] | _color; + dst += s.pitch; + } +} + } // End of namespace Scumm #ifdef __PALM_OS__ diff --git a/scumm/charset.h b/scumm/charset.h index dbadc1a2c3..e1a023e0d1 100644 --- a/scumm/charset.h +++ b/scumm/charset.h @@ -130,6 +130,23 @@ public: int getCharWidth(byte chr); }; +class CharsetRendererNES : public CharsetRendererCommon { +protected: + byte *_trTable; + + void drawBits1(const Graphics::Surface &s, byte *dst, const byte *src, int drawTop, int width, int height); + +public: + CharsetRendererNES(ScummEngine *vm, Common::Language language); + + void setCurID(byte id) {} + void printChar(int chr); + void drawChar(int chr, const Graphics::Surface &s, int x, int y); + + int getFontHeight() { return 8; } + int getCharWidth(byte chr) { return 8; } +}; + class CharsetRendererV3 : public CharsetRendererCommon { protected: int _numChars; diff --git a/scumm/costume.cpp b/scumm/costume.cpp index d160c27be1..35c7b34e51 100644 --- a/scumm/costume.cpp +++ b/scumm/costume.cpp @@ -598,7 +598,7 @@ void LoadedCostume::loadNEScostume(void) { offset = src[(frameset * 4 + framenum) * 2]; // Lookup & desc - table = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_v1MMNESCostumeSet][0]); + table = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][0]); offset = READ_LE_UINT16(table + v1MMNESLookup[_id] * 2 + 2); if (v1MMNESLookup[_id] * 2 >= READ_LE_UINT16(table)) { @@ -686,17 +686,17 @@ void CostumeRenderer::drawNESCostume(const Actor *a, int limb) { bool flipped = (newDirToOldDir(a->getFacing()) == 1); // Lookup & desc - table = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_v1MMNESCostumeSet][0]) + 2; + table = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][0]) + 2; offset = READ_LE_UINT16(table + v1MMNESLookup[_loaded._id] * 2); // lens - numSpritesTab = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_v1MMNESCostumeSet][1]) + 2 + offset; + numSpritesTab = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][1]) + 2 + offset; // offs - spritesOffsetTab = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_v1MMNESCostumeSet][2]) + 2 + offset*2; + spritesOffsetTab = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][2]) + 2 + offset*2; // data - spritesDefs = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_v1MMNESCostumeSet][3]) + 2; + spritesDefs = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][3]) + 2; // data - spritesPal = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_v1MMNESCostumeSet][5]) + 2; + spritesPal = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][5]) + 2; ptr = spritesDefs + READ_LE_UINT16(spritesOffsetTab + frame*2); numSprites = numSpritesTab[frame] + 1; @@ -717,8 +717,8 @@ void CostumeRenderer::drawNESCostume(const Actor *a, int limb) { } for (int ty = 0; ty < 8; ty++) { - byte c1 = _vm->_v1MMNESCostumeGfx[_vm->_v1MMNESCostumeSet][tile * 16 + ty]; - byte c2 = _vm->_v1MMNESCostumeGfx[_vm->_v1MMNESCostumeSet][tile * 16 + ty + 8]; + byte c1 = _vm->_NESCostumeGfx[_vm->_NESCostumeSet][tile * 16 + ty]; + byte c2 = _vm->_NESCostumeGfx[_vm->_NESCostumeSet][tile * 16 + ty + 8]; for (int tx = 0; tx < 8; tx++) { unsigned char c = ((c1 & mask) ? 1 : 0) | ((c2 & mask) ? 2 : 0) | palette; if (mask == 0x01) { @@ -816,8 +816,8 @@ void ScummEngine::cost_decodeNESCostumeGfx() { int maxSprites = patTable[2]; if (maxSprites == 0) maxSprites = 256; - _v1MMNESCostumeGfx[n] = (byte *)calloc(maxSprites * 16, 1); - decodeNESTileData(patTable,_v1MMNESCostumeGfx[n]); + _NESCostumeGfx[n] = (byte *)calloc(maxSprites * 16, 1); + decodeNESTileData(patTable,_NESCostumeGfx[n]); // We will not need it anymore nukeResource(rtCostume, v1MMNEScostTables[n][4]); } diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp index 99d8fb0859..953927fa7d 100644 --- a/scumm/gfx.cpp +++ b/scumm/gfx.cpp @@ -184,8 +184,6 @@ Gdi::Gdi(ScummEngine *vm) { _roomPalette = vm->_roomPalette; if ((vm->_features & GF_AMIGA) && (vm->_version >= 4)) _roomPalette += 16; - if (vm->_features & GF_NES) - _NESBaseTiles = 0; _compositeBuf = 0; _textSurface.pixels = 0; @@ -1830,21 +1828,22 @@ void decodeNESTileData(const byte *src, byte *dest) { } } +void ScummEngine::decodeNESBaseTiles() { + byte *basetiles = getResourceAddress(rtCostume, 37); + _NESBaseTiles = basetiles[2]; + decodeNESTileData(basetiles, _NESPatTable); +} + void Gdi::decodeNESGfx(const byte *room) { - if (_NESBaseTiles == 0) { - byte *basetiles = _vm->getResourceAddress(rtCostume,37); - _NESBaseTiles = basetiles[2]; - decodeNESTileData(basetiles,_NESPatTable); - } const byte *gdata = room + READ_LE_UINT16(room + 0x0A); int tileset = *gdata++; int width = READ_LE_UINT16(room + 0x04); // int height = READ_LE_UINT16(room + 0x06); int i, j, n; - decodeNESTileData(_vm->getResourceAddress(rtCostume, 37 + tileset), _NESPatTable + _NESBaseTiles * 16); + decodeNESTileData(_vm->getResourceAddress(rtCostume, 37 + tileset), _vm->_NESPatTable + _vm->_NESBaseTiles * 16); for (i = 0; i < 16; i++) - _NESPalette[i] = *gdata++; + _vm->_NESPalette[i] = *gdata++; for (i = 0; i < 16; i++) { _NESNametable[i][0] = _NESNametable[i][1] = 0; n = 0; @@ -1908,10 +1907,10 @@ void Gdi::drawStripNES(byte *dst, int dstPitch, int stripnr, int top, int height int tile = isObject ? _NESNametableObj[y][x] : _NESNametable[y][x]; for (int i = 0; i < 8; i++) { - byte c0 = _NESPatTable[tile * 16 + i]; - byte c1 = _NESPatTable[tile * 16 + i + 8]; + byte c0 = _vm->_NESPatTable[tile * 16 + i]; + byte c1 = _vm->_NESPatTable[tile * 16 + i + 8]; for (int j = 0; j < 8; j++) - dst[j] = _NESPalette[((c0 >> (7 - j)) & 1) | (((c1 >> (7 - j)) & 1) << 1) | (palette << 2)]; + dst[j] = _vm->_NESPalette[((c0 >> (7 - j)) & 1) | (((c1 >> (7 - j)) & 1) << 1) | (palette << 2)]; dst += dstPitch; } } diff --git a/scumm/gfx.h b/scumm/gfx.h index d32682e5bb..5d61c1da40 100644 --- a/scumm/gfx.h +++ b/scumm/gfx.h @@ -229,7 +229,7 @@ protected: byte _C64MaskMap[4096], _C64MaskChar[4096]; bool _C64ObjectMode; - byte _NESPatTable[4096], _NESNametable[16][64], _NESAttributes[64], _NESPalette[16]; + byte _NESNametable[16][64], _NESAttributes[64]; byte _NESBaseTiles; byte _NESNametableObj[16][64]; int _NESObj_x; diff --git a/scumm/script_v2.cpp b/scumm/script_v2.cpp index a509a01f91..1f121d44d7 100644 --- a/scumm/script_v2.cpp +++ b/scumm/script_v2.cpp @@ -1538,7 +1538,7 @@ void ScummEngine_v2::o2_switchCostumeSet() { // NES version of maniac uses this to switch between the two // groups of costumes it has if (_features & GF_NES) - _v1MMNESCostumeSet = fetchScriptByte(); + _NESCostumeSet = fetchScriptByte(); else o2_dummy(); } diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp index a2badf8d68..56da24d0f4 100644 --- a/scumm/scumm.cpp +++ b/scumm/scumm.cpp @@ -1232,7 +1232,9 @@ int ScummEngine::init(GameDetector &detector) { loadCJKFont(); // Create the charset renderer - if (_version <= 2) + if (_features & GF_NES) + _charset = new CharsetRendererNES(this, _language); + else if (_version <= 2) _charset = new CharsetRendererV2(this, _language); else if (_version == 3) _charset = new CharsetRendererV3(this); @@ -1500,8 +1502,10 @@ void ScummEngine::scummInit() { clearDrawObjectQueue(); - if (_features & GF_NES) + if (_features & GF_NES) { + decodeNESBaseTiles(); cost_decodeNESCostumeGfx(); + } for (i = 0; i < 6; i++) { if (_version == 3) { // FIXME - what is this? diff --git a/scumm/scumm.h b/scumm/scumm.h index 4c7fbb6b32..49daf51cc7 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -471,8 +471,12 @@ public: BaseCostumeRenderer* _costumeRenderer; - int _v1MMNESCostumeSet; - byte *_v1MMNESCostumeGfx[2]; + int _NESCostumeSet; + byte *_NESCostumeGfx[2]; + + byte _NESPatTable[4096]; + byte _NESPalette[16]; + byte _NESBaseTiles; char *_audioNames; int32 _numAudioNames; @@ -916,6 +920,8 @@ protected: void initBGBuffers(int height); void initCycl(const byte *ptr); // Color cycle + void decodeNESBaseTiles(); + void drawObject(int obj, int arg); void drawRoomObjects(int arg); void drawRoomObject(int i, int arg); -- cgit v1.2.3