Lots of MM NES changes from Quietust and me

o Swap palette entries 0x00 and 0x1D in all necessary places. This gets
    rid of gray background
  o added a function NES_loadCostumeSet(int n) in order to do #1 for sprites
  o Widen screen to 256 pixels and center narrow rooms in it
  o Partial fix for subtitle rendering, now at least first line is
    rendered with identation

svn-id: r17212
This commit is contained in:
Eugene Sandulenko 2005-03-24 03:22:32 +00:00
parent b0a1228c43
commit 9ab0962f6d
8 changed files with 116 additions and 77 deletions

View File

@ -1758,7 +1758,7 @@ void CharsetRendererNES::printChar(int chr) {
if (chr == '@')
return;
charPtr = _vm->_NESPatTable + _trTable[chr - 32] * 16;
charPtr = _vm->_NESPatTable[1] + _trTable[chr - 32] * 16;
width = getCharWidth(chr);
height = 8;
@ -1766,6 +1766,7 @@ void CharsetRendererNES::printChar(int chr) {
origHeight = height;
if (_firstChar) {
_left += 16;
_str.left = _left;
_str.top = _top;
_str.right = _left;
@ -1809,7 +1810,7 @@ void CharsetRendererNES::drawChar(int chr, const Graphics::Surface &s, int x, in
byte *charPtr, *dst;
int width, height;
charPtr = _vm->_NESPatTable + _trTable[chr - 32] * 16;
charPtr = _vm->_NESPatTable[1] + _trTable[chr - 32] * 16;
width = getCharWidth(chr);
height = 8;
@ -1822,7 +1823,7 @@ void CharsetRendererNES::drawBits1(const Graphics::Surface &s, byte *dst, const
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) |
dst[j] = _vm->_NESPalette[0][((c0 >> (7 - j)) & 1) | (((c1 >> (7 - j)) & 1) << 1) |
(_color ? 12 : 8)];
dst += s.pitch;
}

View File

@ -572,11 +572,6 @@ static const int v1MMNESLookup[25] = {
0x17, 0x00, 0x01, 0x05, 0x16
};
static const int v1MMNEScostTables[2][6] = {
/* desc lens offs data gfx pal */
{ 25, 27, 29, 31, 33, 35},
{ 26, 28, 30, 32, 34, 36}
};
/**
* costume ID -> v1MMNESLookup[] -> desc -> lens & offs -> data -> Gfx & pal
*/
@ -598,13 +593,13 @@ void LoadedCostume::loadNEScostume(void) {
offset = src[(frameset * 4 + framenum) * 2];
// Lookup & desc
table = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][0]);
offset = READ_LE_UINT16(table + v1MMNESLookup[_id] * 2 + 2);
table = _vm->_NEScostdesc;
offset = READ_LE_UINT16(table + v1MMNESLookup[_id] * 2);
if (v1MMNESLookup[_id] * 2 >= READ_LE_UINT16(table)) {
_numAnim = (READ_LE_UINT16(table) - v1MMNESLookup[_id] * 2) / 2; // should never happen
if (v1MMNESLookup[_id] * 2 + 2 >= READ_LE_UINT16(table - 2)) {
_numAnim = (READ_LE_UINT16(table) - v1MMNESLookup[_id] * 2) / 2;
} else {
_numAnim = (READ_LE_UINT16(table + v1MMNESLookup[_id] * 2 + 4) - offset) / 2;
_numAnim = (READ_LE_UINT16(table + v1MMNESLookup[_id] * 2 + 2) - offset) / 2;
}
}
@ -674,7 +669,7 @@ void LoadedCostume::loadCostume(int id) {
void CostumeRenderer::drawNESCostume(const Actor *a, int limb) {
const byte *src;
int offset, numSprites;
byte *table, *ptr, *spritesDefs, *spritesOffsetTab, *numSpritesTab, *spritesPal;
const byte *table, *ptr, *spritesDefs, *spritesOffsetTab, *numSpritesTab;
const CostumeData &cost = a->_cost;
int anim = cost.frame[limb];
int frameNum = cost.curpos[limb];
@ -686,17 +681,15 @@ void CostumeRenderer::drawNESCostume(const Actor *a, int limb) {
bool flipped = (newDirToOldDir(a->getFacing()) == 1);
// Lookup & desc
table = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][0]) + 2;
table = _vm->_NEScostdesc;
offset = READ_LE_UINT16(table + v1MMNESLookup[_loaded._id] * 2);
// lens
numSpritesTab = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][1]) + 2 + offset;
numSpritesTab = _vm->_NEScostlens + offset;
// offs
spritesOffsetTab = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][2]) + 2 + offset*2;
spritesOffsetTab = _vm->_NEScostoffs + offset*2;
// data
spritesDefs = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][3]) + 2;
// data
spritesPal = _vm->getResourceAddress(rtCostume, v1MMNEScostTables[_vm->_NESCostumeSet][5]) + 2;
spritesDefs = _vm->_NEScostdata;
ptr = spritesDefs + READ_LE_UINT16(spritesOffsetTab + frame*2);
numSprites = numSpritesTab[frame] + 1;
@ -723,8 +716,8 @@ void CostumeRenderer::drawNESCostume(const Actor *a, int limb) {
continue;
for (int ty = 0; ty < 8; ty++) {
byte c1 = _vm->_NESCostumeGfx[_vm->_NESCostumeSet][tile * 16 + ty];
byte c2 = _vm->_NESCostumeGfx[_vm->_NESCostumeSet][tile * 16 + ty + 8];
byte c1 = _vm->_NESPatTable[0][tile * 16 + ty];
byte c2 = _vm->_NESPatTable[0][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) {
@ -736,7 +729,7 @@ void CostumeRenderer::drawNESCostume(const Actor *a, int limb) {
}
if (!(c & 3))
continue;
*((byte *)_out.pixels + (_actorY + y + ty) * _out.pitch + (_actorX + x + tx)) = spritesPal[c];
*((byte *)_out.pixels + (_actorY + y + ty) * _out.pitch + (_actorX + x + tx)) = _vm->_NESPalette[1][c];
}
}
if (left > _actorX + x)
@ -814,21 +807,6 @@ byte CostumeRenderer::drawLimb(const Actor *a, int limb) {
}
extern void decodeNESTileData(const byte *src, byte *dest);
void ScummEngine::cost_decodeNESCostumeGfx() {
for (int n = 0; n < 2; n++) {
byte *patTable = getResourceAddress(rtCostume, v1MMNEScostTables[n][4]);
int maxSprites = patTable[2];
if (maxSprites == 0)
maxSprites = 256;
_NESCostumeGfx[n] = (byte *)calloc(maxSprites * 16, 1);
decodeNESTileData(patTable,_NESCostumeGfx[n]);
// We will not need it anymore
nukeResource(rtCostume, v1MMNEScostTables[n][4]);
}
}
void ScummEngine::cost_decodeData(Actor *a, int frame, uint usemask) {
const byte *r;
uint mask, j;

View File

@ -343,8 +343,8 @@ void ScummEngine_v5::setBuiltinCursor(int idx) {
_cursor.hotspotY = 0;
byte *dst = _grabbedCursor;
byte *src = &_NESCostumeGfx[0][0xfa * 16];
byte *palette = getResourceAddress(rtCostume, 35) + 2;
byte *src = &_NESPatTable[0][0xfa * 16];
byte *palette = _NESPalette[1];
for (i = 0; i < 8; i++) {
byte c0 = src[i];

View File

@ -171,7 +171,7 @@ static const TransitionEffect transitionEffects[6] = {
// Horizontal wipe (a box expands from left to right side). For MM NES
{
14, // Number of iterations
16, // Number of iterations
{
2, 0, 2, 0,
2, 0, 2, 0,
@ -326,7 +326,7 @@ void ScummEngine::initVirtScreen(VirtScreenNumber slot, int number, int top, int
createResource(rtBuffer, slot + 1, size);
vs->pixels = getResourceAddress(rtBuffer, slot + 1);
memset(vs->pixels, 0, size); // reset background
memset(vs->pixels, 0, size); // reset background
if (twobufs) {
vs->backBuf = createResource(rtBuffer, slot + 5, size);
@ -544,7 +544,17 @@ void Gdi::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int botto
Common::kHercW, x + (Common::kHercW - _vm->_screenWidth * 2) / 2, y, width, height);
} else {
// Finally blit the whole thing to the screen
_vm->_system->copyRectToScreen(_compositeBuf + x + y * _vm->_screenWidth, _vm->_screenWidth, x, y, width, height);
int x1 = x;
// HACK: This is dirty hack which renders narrow NES rooms centered
// NES can address negative number sprites and that poses problem for
// our code. So instead adding zillions of fixes and potentially break
// other games we shift it right on rendering stage
if (_vm->_features & GF_NES && _vm->_NESStartStrip > 0 && vs->number == kMainVirtScreen) {
x += _vm->_NESStartStrip * 8;
}
_vm->_system->copyRectToScreen(_compositeBuf + x1 + y * _vm->_screenWidth, _vm->_screenWidth, x, y, width, height);
}
}
@ -878,16 +888,12 @@ void CharsetRenderer::restoreCharsetBg() {
}
} else {
// Clear area
if (_vm->_features & GF_NES)
memset(screenBuf, 0x1d, vs->h * vs->pitch);
else
memset(screenBuf, 0, vs->h * vs->pitch);
memset(screenBuf, 0, vs->h * vs->pitch);
}
if (vs->hasTwoBuffers) {
// Clean out the charset mask
memset(_vm->gdi._textSurface.pixels, (_vm->_features & GF_NES) ? 0x1d :
CHARSET_MASK_TRANSPARENCY, _vm->gdi._textSurface.pitch * _vm->gdi._textSurface.h);
memset(_vm->gdi._textSurface.pixels, CHARSET_MASK_TRANSPARENCY, _vm->gdi._textSurface.pitch * _vm->gdi._textSurface.h);
}
}
}
@ -1371,6 +1377,9 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi
sx = 0;
}
//if (_vm->_NESStartStrip > 0)
// stripnr -= _vm->_NESStartStrip;
// FIXME Still not been calculated correctly
while (numstrip > 0 && sx < _numStrips && x * 8 < MAX(_vm->_roomWidth, (int) vs->w)) {
CHECK_HEAP;
@ -1833,7 +1842,7 @@ void Gdi::decompressMaskImgOr(byte *dst, const byte *src, int height) const {
void decodeNESTileData(const byte *src, byte *dest) {
int len = READ_LE_UINT16(src); src += 2;
const byte *end = src + len;
/* int numtiles = */ *src++;
src++; // skip number-of-tiles byte, assume it is correct
while (src < end) {
byte data = *src++;
for (int j = 0; j < (data & 0x7F); j++)
@ -1846,7 +1855,33 @@ void decodeNESTileData(const byte *src, byte *dest) {
void ScummEngine::decodeNESBaseTiles() {
byte *basetiles = getResourceAddress(rtCostume, 37);
_NESBaseTiles = basetiles[2];
decodeNESTileData(basetiles, _NESPatTable);
decodeNESTileData(basetiles, _NESPatTable[1]);
}
static const int v1MMNEScostTables[2][6] = {
/* desc lens offs data gfx pal */
{ 25, 27, 29, 31, 33, 35},
{ 26, 28, 30, 32, 34, 36}
};
void ScummEngine::NES_loadCostumeSet(int n) {
int i;
_NESCostumeSet = n;
_NEScostdesc = getResourceAddress(rtCostume, v1MMNEScostTables[n][0]) + 2;
_NEScostlens = getResourceAddress(rtCostume, v1MMNEScostTables[n][1]) + 2;
_NEScostoffs = getResourceAddress(rtCostume, v1MMNEScostTables[n][2]) + 2;
_NEScostdata = getResourceAddress(rtCostume, v1MMNEScostTables[n][3]) + 2;
decodeNESTileData(getResourceAddress(rtCostume, v1MMNEScostTables[n][4]), _NESPatTable[0]);
byte *palette = getResourceAddress(rtCostume, v1MMNEScostTables[n][5]) + 2;
for (i = 0; i < 16; i++) {
byte c = *palette++;
//if (c == 0x1D) // HACK - switch around colors 0x00 and 0x1D
// c = 0; // so we don't need a zillion extra checks
//else if (c == 0)// for determining the proper background color
// c = 0x1D;
_NESPalette[1][i] = c;
}
}
void Gdi::decodeNESGfx(const byte *room) {
@ -1856,9 +1891,26 @@ void Gdi::decodeNESGfx(const byte *room) {
// int height = READ_LE_UINT16(room + 0x06);
int i, j, n;
decodeNESTileData(_vm->getResourceAddress(rtCostume, 37 + tileset), _vm->_NESPatTable + _vm->_NESBaseTiles * 16);
for (i = 0; i < 16; i++)
_vm->_NESPalette[i] = *gdata++;
// We have narrow room. so expand it
if (width < 32) {
_vm->_NESStartStrip = (32 - width) >> 1;
} else {
_vm->_NESStartStrip = 0;
}
decodeNESTileData(_vm->getResourceAddress(rtCostume, 37 + tileset), _vm->_NESPatTable[1] + _vm->_NESBaseTiles * 16);
for (i = 0; i < 16; i++) {
byte c = *gdata++;
if (c == 0x0D)
c = 0x1D;
if (c == 0x1D) // HACK - switch around colors 0x00 and 0x1D
c = 0; // so we don't need a zillion extra checks
else if (c == 0) // for determining the proper background color
c = 0x1D;
_vm->_NESPalette[0][i] = c;
}
for (i = 0; i < 16; i++) {
_NESNametable[i][0] = _NESNametable[i][1] = 0;
n = 0;
@ -2001,10 +2053,10 @@ void Gdi::drawStripNES(byte *dst, int dstPitch, int stripnr, int top, int height
int tile = (isObject ? _NESNametableObj : _NESNametable)[y][x];
for (int i = 0; i < 8; i++) {
byte c0 = _vm->_NESPatTable[tile * 16 + i];
byte c1 = _vm->_NESPatTable[tile * 16 + i + 8];
byte c0 = _vm->_NESPatTable[1][tile * 16 + i];
byte c1 = _vm->_NESPatTable[1][tile * 16 + i + 8];
for (int j = 0; j < 8; j++)
dst[j] = _vm->_NESPalette[((c0 >> (7 - j)) & 1) | (((c1 >> (7 - j)) & 1) << 1) | (palette << 2)];
dst[j] = _vm->_NESPalette[0][((c0 >> (7 - j)) & 1) | (((c1 >> (7 - j)) & 1) << 1) | (palette << 2)];
dst += dstPitch;
}
}

View File

@ -30,7 +30,7 @@
namespace Scumm {
void ScummEngine::setupNESPalette() {
setPalColor(0x00,0x6D,0x6D,0x6D);
setPalColor(0x00,0x24,0x24,0x24); // 0x1D
setPalColor(0x01,0x00,0x24,0x92);
setPalColor(0x02,0x00,0x00,0xDB);
setPalColor(0x03,0x6D,0x49,0xDB);
@ -60,7 +60,7 @@ void ScummEngine::setupNESPalette() {
setPalColor(0x1A,0x00,0x92,0x00);
setPalColor(0x1B,0x00,0xB6,0x6D);
setPalColor(0x1C,0x00,0x92,0x92);
setPalColor(0x1D,0x24,0x24,0x24);
setPalColor(0x1D,0x6D,0x6D,0x6D); // 0x00
setPalColor(0x1E,0x00,0x00,0x00);
setPalColor(0x1F,0x00,0x00,0x00);

View File

@ -1060,10 +1060,7 @@ void ScummEngine_v2::o2_drawSentence() {
sentenceline.bottom = virtscr[2].topline + 8;
sentenceline.left = 0;
sentenceline.right = 319;
if (_features & GF_NES)
restoreBG(sentenceline, 0x1d);
else
restoreBG(sentenceline);
restoreBG(sentenceline);
drawString(2, (byte*)sentence);
}
@ -1525,10 +1522,7 @@ void ScummEngine_v2::setUserState(byte state) {
rect.bottom = virtscr[2].topline + 8 * 88;
rect.left = 0;
rect.right = 319;
if (_features & GF_NES)
restoreBG(rect, 0x1d);
else
restoreBG(rect);
restoreBG(rect);
// Draw all verbs and inventory
redrawVerbs();
@ -1552,7 +1546,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)
_NESCostumeSet = fetchScriptByte();
NES_loadCostumeSet(fetchScriptByte());
else
o2_dummy();
}

View File

@ -857,6 +857,7 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS
_costumeRenderer = NULL;
_2byteFontPtr = 0;
_V1TalkingActor = 0;
_NESStartStrip = 0;
_actorClipOverride.top = 0;
_actorClipOverride.bottom = 480;
@ -1109,7 +1110,7 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS
_screenWidth = 640;
_screenHeight = 480;
} else if (_features & GF_NES) {
_screenWidth = 224;
_screenWidth = 256; // 224
_screenHeight = 240;
} else if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
_features |= GF_DEFAULT_TO_1X_SCALER;
@ -1514,10 +1515,8 @@ 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?
@ -1787,6 +1786,13 @@ int ScummEngine::scummLoop(int delta) {
if (_version <= 2) {
VAR(VAR_VIRT_MOUSE_X) = _virtualMouse.x / 8;
VAR(VAR_VIRT_MOUSE_Y) = _virtualMouse.y / 2;
// Adjust mouse coordinates as narrow rooms in NES are centered
if (_features & GF_NES && _virtualMouse.y >= 16 && _virtualMouse.y < 144) {
VAR(VAR_VIRT_MOUSE_X) -= _NESStartStrip;
if (VAR(VAR_VIRT_MOUSE_X) < 0)
VAR(VAR_VIRT_MOUSE_X) = 0;
}
} else {
VAR(VAR_VIRT_MOUSE_X) = _virtualMouse.x;
VAR(VAR_VIRT_MOUSE_Y) = _virtualMouse.y;
@ -2266,6 +2272,12 @@ void ScummEngine::initRoomSubBlocks() {
if (_version == 1) {
if (_features & GF_NES) {
_roomWidth = READ_LE_UINT16(roomptr + 4) * 8;
// HACK: To let our code work normal with narrow rooms we
// adjust width. It will render garbage on right edge but we do
// not render it anyway
if (_roomWidth < 32 * 8)
_roomWidth = 32 * 8;
_roomHeight = READ_LE_UINT16(roomptr + 6) * 8;
} else {
_roomWidth = roomptr[4] * 8;

View File

@ -473,12 +473,14 @@ public:
BaseCostumeRenderer* _costumeRenderer;
int _NESCostumeSet;
byte *_NESCostumeGfx[2];
byte _NESPatTable[4096];
byte _NESPalette[16];
void NES_loadCostumeSet(int n);
byte *_NEScostdesc, *_NEScostlens, *_NEScostoffs, *_NEScostdata;
byte _NESPatTable[2][4096];
byte _NESPalette[2][16];
byte _NESBaseTiles;
int _NESStartStrip;
char *_audioNames;
int32 _numAudioNames;
@ -928,7 +930,7 @@ protected:
void drawRoomObject(int i, int arg);
void drawBox(int x, int y, int x2, int y2, int color);
void restoreBG(Common::Rect rect, byte backColor = 0);
void restoreBG(Common::Rect rect, byte backcolor = 0);
void redrawBGStrip(int start, int num);
virtual void redrawBGAreas();