byte *Sword2Engine::fetchForegroundParallaxLayer(byte *screenFile, int layer) { if (isPsx()) { byte *psxParallax = _screen->getPsxScrCache(2); // Manage cache for psx parallaxes if (!_screen->getPsxScrCacheStatus(2)) { // This parallax layer is not present return NULL; } else if (psxParallax) { // Parallax layer present and cached return psxParallax; } else { // Present, but still not cached uint32 locNo = _logic->getLocationNum(); // We have a wrong location number at start, fix that locNo = (locNo == 0) ? 3 : locNo; psxParallax = fetchPsxParallax(locNo, 1); _screen->setPsxScrCache(psxParallax, 2); return psxParallax; } } else { MultiScreenHeader mscreenHeader; mscreenHeader.read(screenFile + ResHeader::size()); assert(mscreenHeader.fg_parallax[layer]); return screenFile + ResHeader::size() + mscreenHeader.fg_parallax[layer]; } }
byte *Sword2Engine::fetchBackgroundLayer(byte *screenFile) { if (isPsx()) { byte *psxBackground = _screen->getPsxScrCache(1); // Manage cache for psx backgrounds if (psxBackground) { // Background is cached return psxBackground; } else { // Background not cached uint32 locNo = _logic->getLocationNum(); // We have a wrong location number at start, fix that locNo = (locNo == 0) ? 3 : locNo; psxBackground = fetchPsxBackground(locNo); _screen->setPsxScrCache(psxBackground, 1); return psxBackground; } } else { MultiScreenHeader mscreenHeader; mscreenHeader.read(screenFile + ResHeader::size()); assert(mscreenHeader.screen); return screenFile + ResHeader::size() + mscreenHeader.screen + ScreenHeader::size(); } }
byte *Sword2Engine::fetchBackgroundParallaxLayer(byte *screenFile, int layer) { if (isPsx()) { byte *psxParallax = _screen->getPsxScrCache(0); // Manage cache for background psx parallaxes if (!_screen->getPsxScrCacheStatus(0)) { // This parallax layer is not present return NULL; } else if (psxParallax != NULL) { // Parallax layer present, and already in cache return psxParallax; } else { // Present, but not cached uint32 locNo = _logic->getLocationNum(); // At game startup, we have a wrong location number stored // in game vars (0, instead of 3), work around this. locNo = (locNo == 0) ? 3 : locNo; psxParallax = fetchPsxParallax(locNo, 0); _screen->setPsxScrCache(psxParallax, 0); return psxParallax; } } else { MultiScreenHeader mscreenHeader; mscreenHeader.read(screenFile + ResHeader::size()); assert(mscreenHeader.bg_parallax[layer]); return screenFile + ResHeader::size() + mscreenHeader.bg_parallax[layer]; } }
void Sword2Engine::fetchPalette(byte *screenFile, byte *palBuffer) { byte *palette; if (isPsx()) { // PSX version doesn't have a "MultiScreenHeader", instead there's a ScreenHeader and a tag palette = screenFile + ResHeader::size() + ScreenHeader::size() + 2; } else { MultiScreenHeader mscreenHeader; mscreenHeader.read(screenFile + ResHeader::size()); palette = screenFile + ResHeader::size() + mscreenHeader.palette; } // Always set color 0 to black, because while most background screen // palettes have a bright color 0 it should come out as black in the // game. palBuffer[0] = 0; palBuffer[1] = 0; palBuffer[2] = 0; for (uint i = 4, j = 3; i < 4 * 256; i += 4, j += 3) { palBuffer[j + 0] = palette[i + 0]; palBuffer[j + 1] = palette[i + 1]; palBuffer[j + 2] = palette[i + 2]; } }
byte *Sword2Engine::fetchShadingMask(byte *screenFile) { if (isPsx()) return NULL; MultiScreenHeader mscreenHeader; mscreenHeader.read(screenFile + ResHeader::size()); return screenFile + ResHeader::size() + mscreenHeader.maskOffset; }
byte *Sword2Engine::fetchScreenHeader(byte *screenFile) { if (isPsx()) { // In PSX version there's no MultiScreenHeader, so just skip resource header return screenFile + ResHeader::size(); } else { MultiScreenHeader mscreenHeader; mscreenHeader.read(screenFile + ResHeader::size()); return screenFile + ResHeader::size() + mscreenHeader.screen; } }
byte *Sword2Engine::fetchPaletteMatchTable(byte *screenFile) { if (isPsx()) return NULL; MultiScreenHeader mscreenHeader; mscreenHeader.read(screenFile + ResHeader::size()); return screenFile + ResHeader::size() + mscreenHeader.paletteTable; }
byte *Sword2Engine::fetchLayerHeader(byte *screenFile, uint16 layerNo) { #ifdef SWORD2_DEBUG ScreenHeader screenHead; screenHead.read(fetchScreenHeader(screenFile)); assert(layerNo < screenHead.noLayers); #endif if (isPsx()) { return screenFile + ResHeader::size() + ScreenHeader::size() + 2 + 0x400 + layerNo * LayerHeader::size(); } else { MultiScreenHeader mscreenHeader; mscreenHeader.read(screenFile + ResHeader::size()); return screenFile + ResHeader::size() + mscreenHeader.layers + layerNo * LayerHeader::size(); } }
byte *Sword2Engine::fetchPalette(byte *screenFile) { byte *palette; if(isPsx()) { // PSX version doesn't have a "MultiScreenHeader", instead there's a ScreenHeader and a tag palette = screenFile + ResHeader::size() + ScreenHeader::size() + 2; } else { MultiScreenHeader mscreenHeader; mscreenHeader.read(screenFile + ResHeader::size()); palette = screenFile + ResHeader::size() + mscreenHeader.palette; } // Always set colour 0 to black, because while most background screen // palettes have a bright colour 0 it should come out as black in the // game. palette[0] = 0; palette[1] = 0; palette[2] = 0; palette[3] = 0; return palette; }
void Screen::buildDisplay() { if (_thisScreen.new_palette) { // start the layer palette fading up startNewPalette(); // should be reset to zero at start of each screen change _largestLayerArea = 0; _largestSpriteArea = 0; } // Does this ever happen? if (!_thisScreen.background_layer_id) return; // there is a valid screen to run setScrollTarget(_thisScreen.scroll_offset_x, _thisScreen.scroll_offset_y); _vm->_mouse->animateMouse(); startRenderCycle(); byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id); MultiScreenHeader screenLayerTable; memset(&screenLayerTable, 0, sizeof(screenLayerTable)); if (!Sword2Engine::isPsx()) // On PSX version, there would be nothing to read here screenLayerTable.read(file + ResHeader::size()); // Render at least one frame, but if the screen is scrolling, and if // there is time left, we will render extra frames to smooth out the // scrolling. do { // first background parallax + related anims if (Sword2Engine::isPsx() || screenLayerTable.bg_parallax[0]) { // No need to check on PSX version renderParallax(_vm->fetchBackgroundParallaxLayer(file, 0), 0); drawBackPar0Frames(); } // second background parallax + related anims if (!Sword2Engine::isPsx() && screenLayerTable.bg_parallax[1]) { // Nothing here in PSX version renderParallax(_vm->fetchBackgroundParallaxLayer(file, 1), 1); drawBackPar1Frames(); } // normal backround layer (just the one!) renderParallax(_vm->fetchBackgroundLayer(file), 2); // sprites & layers drawBackFrames(); // background sprites drawSortFrames(file); // sorted sprites & layers drawForeFrames(); // foreground sprites // first foreground parallax + related anims if (Sword2Engine::isPsx() || screenLayerTable.fg_parallax[0]) { renderParallax(_vm->fetchForegroundParallaxLayer(file, 0), 3); drawForePar0Frames(); } // second foreground parallax + related anims if (!Sword2Engine::isPsx() && screenLayerTable.fg_parallax[1]) { renderParallax(_vm->fetchForegroundParallaxLayer(file, 1), 4); drawForePar1Frames(); } _vm->_debugger->drawDebugGraphics(); _vm->_fontRenderer->printTextBlocs(); _vm->_mouse->processMenu(); updateDisplay(); _frameCount++; if (getTick() > _cycleTime) { _fps = _frameCount; _frameCount = 0; _cycleTime = getTick() + 1000; } } while (!endRenderCycle()); _vm->_resman->closeResource(_thisScreen.background_layer_id); }