diff --git a/cutscene.cpp b/cutscene.cpp index de40570..2766961 100644 --- a/cutscene.cpp +++ b/cutscene.cpp @@ -465,7 +465,7 @@ void Cutscene::drawFrame() { _render->clearScreen(); if (_frameCounter != 0) { const int y = (kCutsceneDisplayHeight - _fileHdr.videoFrameHeight) / 2; - _render->copyToOverlayLut(0, y, _frameBuffers[0], _palette, _fileHdr.videoFrameWidth, _fileHdr.videoFrameHeight); + _render->copyToOverlay(0, y, _fileHdr.videoFrameWidth, _fileHdr.videoFrameHeight, _frameBuffers[0], false, _palette); } } diff --git a/game.cpp b/game.cpp index 1c20281..ff41792 100644 --- a/game.cpp +++ b/game.cpp @@ -20,6 +20,8 @@ Game::Game(Render *render, const GameParams *params) memset(&_drawCharBuf, 0, sizeof(_drawCharBuf)); memset(&_drawNumber, 0, sizeof(_drawNumber)); + _displayPsxLevelLoadingScreen = -1; + _ticks = 0; _level = 0; _skillLevel = kSkillNormal; @@ -1153,6 +1155,27 @@ void Game::init() { initLevel(); } +bool Game::displayPsxLevelLoadingScreen() { + switch (_displayPsxLevelLoadingScreen) { + case 1: + _render->resizeOverlay(kVrmLoadingScreenWidth, kVrmLoadingScreenHeight, true); + _displayPsxLevelLoadingScreen = 2; + // fall-through + case 2: + _render->copyToOverlay(0, 0, kVrmLoadingScreenWidth, kVrmLoadingScreenHeight, _resPsx._vrmLoadingBitmap, true); + break; + } + const bool present = !inp.enterKey && !inp.spaceKey; + inp.enterKey = false; + inp.spaceKey = false; + if (!present) { + _render->resizeOverlay(0, 0); + _displayPsxLevelLoadingScreen = 0; + _resPsx.unloadLevelData(kResTypePsx_VRM); + } + return present; +} + void Game::initLevel(bool keepInventoryObjects) { debug(kDebug_GAME, "Game::initLevel() level %d keepInventory %d", _level, keepInventoryObjects); @@ -1168,7 +1191,10 @@ void Game::initLevel(bool keepInventoryObjects) { clearLevelData(); if (g_hasPsx) { - // _resPsx.loadLevelData(_level, kResTypePsx_VRM); + _resPsx.loadLevelData(_level, kResTypePsx_VRM); + if (_resPsx._vrmLoadingBitmap) { + _displayPsxLevelLoadingScreen = 1; + } } if (_params.playDemo) { diff --git a/game.h b/game.h index e8ec225..644825e 100644 --- a/game.h +++ b/game.h @@ -471,6 +471,7 @@ struct Game { bool _changeLevel; int _room, _roomPrev; bool _endGame; + int _displayPsxLevelLoadingScreen; int _mainLoopCurrentMode; int _conradHit; @@ -669,6 +670,7 @@ struct Game { void updateSceneTextures(); void initScene(); void init(); + bool displayPsxLevelLoadingScreen(); void initLevel(bool keepInventoryObjects = false); void setupConradObject(); void changeRoom(int room); diff --git a/render.cpp b/render.cpp index 2c70563..8c69dfa 100644 --- a/render.cpp +++ b/render.cpp @@ -457,8 +457,12 @@ void Render::drawRectangle(int x, int y, int w, int h, int color) { emitQuad2i(x, y, w, h); } -void Render::copyToOverlayLut(int x, int y, const uint8_t *data, const uint8_t *pal, int w, int h) { +void Render::copyToOverlay(int x, int y, int w, int h, const uint8_t *data, bool rgb, const uint8_t *pal) { assert(_overlay.tex); + if (x == 0 && y == 0 && w == _overlay.tex->bitmapW && h == _overlay.tex->bitmapH) { + _textureCache.updateTexture(_overlay.tex, data, w, h, rgb, pal); + return; + } assert(x + w <= _overlay.tex->bitmapW); assert(y + h <= _overlay.tex->bitmapH); const int dstPitch = _overlay.tex->bitmapW; @@ -472,7 +476,7 @@ void Render::copyToOverlayLut(int x, int y, const uint8_t *data, const uint8_t * data += w; } } - _textureCache.updateTexture(_overlay.tex, _overlay.buf, _overlay.tex->bitmapW, _overlay.tex->bitmapH, pal); + _textureCache.updateTexture(_overlay.tex, _overlay.buf, _overlay.tex->bitmapW, _overlay.tex->bitmapH, _overlay.rgb, pal); } void Render::setIgnoreDepth(bool ignoreDepth) { @@ -504,7 +508,7 @@ void Render::setOverlayBlendColor(int r, int g, int b) { _overlay.b = b; } -void Render::resizeOverlay(int w, int h) { +void Render::resizeOverlay(int w, int h, bool rgb) { if (_overlay.tex) { _textureCache.destroyTexture(_overlay.tex); _overlay.tex = 0; @@ -516,9 +520,11 @@ void Render::resizeOverlay(int w, int h) { if (w == 0 || h == 0) { return; } - _overlay.buf = (uint8_t *)calloc(w * h, sizeof(uint8_t)); + const int colorSize = rgb ? 4 * sizeof(uint8_t) : sizeof(uint8_t); + _overlay.rgb = rgb; + _overlay.buf = (uint8_t *)calloc(w * h, colorSize); if (_overlay.buf) { - _overlay.tex = _textureCache.createTexture(_overlay.buf, w, h); + _overlay.tex = _textureCache.createTexture(_overlay.buf, w, h, rgb); } } diff --git a/render.h b/render.h index 8ad906a..8cfd470 100644 --- a/render.h +++ b/render.h @@ -41,6 +41,7 @@ struct Render { uint8_t *_screenshotBuf; struct { uint8_t *buf; + bool rgb; Texture *tex; int r, g, b; } _overlay; @@ -85,8 +86,8 @@ struct Render { void endObjectDraw(); void setOverlayBlendColor(int r, int g, int b); - void resizeOverlay(int w, int h); - void copyToOverlayLut(int x, int y, const uint8_t *data, const uint8_t *clut, int w, int h); + void resizeOverlay(int w, int h, bool rgb = false); + void copyToOverlay(int x, int y, int w, int h, const uint8_t *data, bool rgb = false, const uint8_t *clut = 0); void setPaletteScale(bool greyScale, int rgbScale); void setPalette(const uint8_t *pal, int offset, int count); diff --git a/resourcepsx.cpp b/resourcepsx.cpp index 1a3a87e..930cea5 100644 --- a/resourcepsx.cpp +++ b/resourcepsx.cpp @@ -2,9 +2,13 @@ #include "resourcepsx.h" static const char *_levels[] = { - "1", "2a", "2b", "2c", "3", "4a", "4b", "4c", "5a", "5b", "5c", "6a", "6b", 0 + "1", "2a", "2b", "2c", "3", "4a", "4b", "4c", "5a", "5b", "5c", "6a", "6b" }; +ResourcePsx::ResourcePsx() { + _vrmLoadingBitmap = 0; +} + void ResourcePsx::loadLevelData(int level, int resType) { char name[16]; switch (resType) { @@ -15,14 +19,31 @@ void ResourcePsx::loadLevelData(int level, int resType) { fileReadUint32LE(fp); int count = 0; while (1) { - const int w = fileReadUint16LE(fp); - const int h = fileReadUint16LE(fp); + int w = fileReadUint16LE(fp); + int h = fileReadUint16LE(fp); if (fileEof(fp)) { break; } - debug(kDebug_INFO, "VRAM %d w %d h %d", count, w, h); + debug(kDebug_RESOURCE, "VRAM %d w %d h %d", count, w, h); if (count == 0) { assert(w == 640 && h == 272); + _vrmLoadingBitmap = (uint8_t *)malloc(kVrmLoadingScreenWidth * kVrmLoadingScreenHeight * 4); + if (_vrmLoadingBitmap) { + const int dstPitch = kVrmLoadingScreenWidth * 4; + for (int y = 0; y < kVrmLoadingScreenHeight; ++y) { + uint8_t *dst = _vrmLoadingBitmap + (kVrmLoadingScreenHeight - 1 - y) * dstPitch; + for (int x = 0; x < kVrmLoadingScreenWidth; ++x) { + const uint16_t color = fileReadUint16LE(fp); + *dst++ = ( color & 31) << 3; + *dst++ = ((color >> 5) & 31) << 3; + *dst++ = ((color >> 10) & 31) << 3; + *dst++ = 255; + } + } + h -= kVrmLoadingScreenHeight; + } + } else { + assert(w == 256 && h == 256); } fileSetPos(fp, w * h, kFilePosition_CUR); ++count; @@ -33,3 +54,12 @@ void ResourcePsx::loadLevelData(int level, int resType) { break; } } + +void ResourcePsx::unloadLevelData(int resType) { + switch (resType) { + case kResTypePsx_VRM: + free(_vrmLoadingBitmap); + _vrmLoadingBitmap = 0; + break; + } +} diff --git a/resourcepsx.h b/resourcepsx.h index 965c107..9441e9b 100644 --- a/resourcepsx.h +++ b/resourcepsx.h @@ -9,9 +9,19 @@ enum { kResTypePsx_VRM }; +enum { + kVrmLoadingScreenWidth = 320, + kVrmLoadingScreenHeight = 240 +}; + struct ResourcePsx { + uint8_t *_vrmLoadingBitmap; + + ResourcePsx(); + void loadLevelData(int level, int resType); + void unloadLevelData(int resType); }; #endif // RESOURCEPSX_H__ diff --git a/stub.cpp b/stub.cpp index ec76d18..b90fdad 100644 --- a/stub.cpp +++ b/stub.cpp @@ -513,6 +513,10 @@ struct GameStub_F2B : GameStub { } else if (_g->_endGame) { _g->_endGame = false; _g->initLevel(); + } else if (_g->_displayPsxLevelLoadingScreen) { + if (_g->displayPsxLevelLoadingScreen()) { + break; + } } _g->updateGameInput(); _g->doTick(); diff --git a/texturecache.cpp b/texturecache.cpp index 54f1238..8f158a6 100644 --- a/texturecache.cpp +++ b/texturecache.cpp @@ -281,14 +281,29 @@ void TextureCache::destroyTexture(Texture *texture) { delete texture; } -void TextureCache::updateTexture(Texture *t, const uint8_t *data, int w, int h, const uint8_t *pal) { +void TextureCache::updateTexture(Texture *t, const uint8_t *data, int w, int h, bool rgb, const uint8_t *pal) { assert(t->bitmapW == w && t->bitmapH == h); - memcpy(t->bitmapData, data, w * h); + if (rgb) { + assert(t->bitmapData == 0); + } else { + memcpy(t->bitmapData, data, w * h); + } uint16_t *texData = (uint16_t *)calloc(t->texW * t->texH, sizeof(uint16_t)); if (texData) { - uint16_t clut[256]; - convertPalette(pal, clut); - convertTexture(t->bitmapData, t->bitmapW, t->bitmapH, clut, texData, t->texW); + if (rgb) { + uint16_t *p = texData; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + p[x] = _formats[_fmt].convertColor(data[0], data[1], data[2]); data += 4; + } + p += t->texW; + } + } else { + assert(pal); + uint16_t clut[256]; + convertPalette(pal, clut); + convertTexture(t->bitmapData, t->bitmapW, t->bitmapH, clut, texData, t->texW); + } glBindTexture(GL_TEXTURE_2D, t->id); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, t->texW, t->texH, _formats[_fmt].format, _formats[_fmt].type, texData); free(texData); diff --git a/texturecache.h b/texturecache.h index 6a487cc..fb8b351 100644 --- a/texturecache.h +++ b/texturecache.h @@ -32,7 +32,7 @@ struct TextureCache { void convertTexture(const uint8_t *src, int w, int h, const uint16_t *clut, uint16_t *dst, int dstPitch); Texture *createTexture(const uint8_t *data, int w, int h, bool rgb = false, const uint8_t *pal = 0); void destroyTexture(Texture *); - void updateTexture(Texture *, const uint8_t *data, int w, int h, const uint8_t *pal); + void updateTexture(Texture *, const uint8_t *data, int w, int h, bool rgb = false, const uint8_t *pal = 0); void convertPalette(const uint8_t *src, uint16_t *dst); void setPalette(const uint8_t *pal, bool updateTextures = true);