Ticket #8965: brokensword_psx_patch.diff

File brokensword_psx_patch.diff, 70.2 KB (added by hkzlab, 15 years ago)

Broken Sword PSX support patch

  • scummvm-bspsx/common/util.h

     
    201201        kPlatformApple2GS,
    202202        kPlatformPC98,
    203203        kPlatformWii,
     204        kPlatformPSX,
    204205
    205206        kPlatformUnknown = -1
    206207};
  • scummvm-bspsx/common/util.cpp

     
    271271        {"nes", "nes", "nes", "NES", kPlatformNES},
    272272        {"segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD},
    273273        {"windows", "win", "win", "Windows", kPlatformWindows},
     274        {"playstation", "psx", "PSX", "Playstation", kPlatformPSX},
    274275
    275276
    276277        {0, 0, 0, "Default", kPlatformUnknown}
  • scummvm-bspsx/engines/sword1/module.mk

     
    1818        sound.o \
    1919        staticres.o \
    2020        sword1.o \
    21         text.o
     21        text.o \
     22        vag.o
    2223
    2324# This module can be built as a plugin
    2425ifeq ($(ENABLE_SWORD1), DYNAMIC_PLUGIN)
  • scummvm-bspsx/engines/sword1/vag.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25 
     26#include "sword1/vag.h"
     27
     28namespace Sword1 {
     29
     30VagStream::VagStream(Common::SeekableReadStream *stream, bool loop) : _stream(stream) {
     31        _samplesRemaining = 0;
     32        _predictor = 0;
     33        _s1 = _s2 = 0.0;
     34        _loop = loop;
     35}
     36
     37
     38VagStream::~VagStream() {
     39}
     40
     41double f[5][2] = { { 0.0, 0.0 },
     42                    {  60.0 / 64.0,  0.0 },
     43                    {  115.0 / 64.0, -52.0 / 64.0 },
     44                    {  98.0 / 64.0, -55.0 / 64.0 },
     45                    {  122.0 / 64.0, -60.0 / 64.0 } };
     46
     47int VagStream::readBuffer(int16 *buffer, const int numSamples) {
     48        int32 samplesDecoded = 0;
     49       
     50        if (_samplesRemaining) {
     51                byte i = 0;
     52               
     53                for (i = 28 - _samplesRemaining; i < 28 && samplesDecoded < numSamples; i++) {
     54                        _samples[i] = _samples[i] + _s1 * f[_predictor][0] + _s2 * f[_predictor][1];
     55                        _s2 = _s1;
     56                        _s1 = _samples[i];
     57                        int16 d = (int) (_samples[i] + 0.5);
     58                        buffer[samplesDecoded] = d;
     59                        samplesDecoded++;
     60                }
     61               
     62                assert(i == 28); // We're screwed if this fails :P
     63                _samplesRemaining = 0;
     64        }
     65       
     66        while (samplesDecoded < numSamples) {
     67                byte i = 0;
     68       
     69                _predictor = _stream->readByte();
     70                byte shift = _predictor & 0xf;
     71                _predictor >>= 4;
     72       
     73                if (_stream->readByte() == 7)
     74                        return samplesDecoded;
     75       
     76                for (i = 0; i < 28; i += 2) {
     77                        byte d = _stream->readByte();
     78                        int16 s = (d & 0xf) << 12;
     79                        if (s & 0x8000)
     80                                s |= 0xffff0000;
     81                        _samples[i] = (double)(s >> shift);
     82                        s = (d & 0xf0) << 8;
     83                        if (s & 0x8000)
     84                                s |= 0xffff0000;
     85                        _samples[i + 1] = (double)(s >> shift);
     86                }
     87       
     88                for (i = 0; i < 28 && samplesDecoded < numSamples; i++) {
     89                        _samples[i] = _samples[i] + _s1 * f[_predictor][0] + _s2 * f[_predictor][1];
     90                        _s2 = _s1;
     91                        _s1 = _samples[i];
     92                        int16 d = (int) (_samples[i] + 0.5);
     93                        buffer[samplesDecoded] = d;
     94                        samplesDecoded++;
     95                }
     96               
     97                if (i != 27)
     98                        _samplesRemaining = 28 - i;
     99        }
     100
     101        if(_loop && _stream->eos())
     102                rewind();
     103
     104        return samplesDecoded;
     105}
     106
     107void VagStream::rewind() {
     108        _stream->seek(0);
     109        _samplesRemaining = 0;
     110        _predictor = 0;
     111        _s1 = _s2 = 0.0;
     112}
     113
     114}
  • scummvm-bspsx/engines/sword1/detection.cpp

     
    4545        {"sword1mac", "Broken Sword 1: The Shadow of the Templars (Mac)"};
    4646static const PlainGameDescriptor sword1MacDemoSettings =
    4747        {"sword1macdemo", "Broken Sword 1: The Shadow of the Templars (Mac demo)"};
     48static const PlainGameDescriptor sword1PSXSettings =
     49        {"sword1psx", "Broken Sword 1: The Shadow of the Templars (PlayStation)"};
    4850
    4951// check these subdirectories (if present)
    5052static const char *g_dirNames[] = {     "clusters",     "speech" };
     
    5254#define NUM_COMMON_FILES_TO_CHECK 1
    5355#define NUM_PC_FILES_TO_CHECK 3
    5456#define NUM_MAC_FILES_TO_CHECK 4
     57#define NUM_PSX_FILES_TO_CHECK 2
    5558#define NUM_DEMO_FILES_TO_CHECK 1
    5659#define NUM_MAC_DEMO_FILES_TO_CHECK 1
    57 #define NUM_FILES_TO_CHECK NUM_COMMON_FILES_TO_CHECK + NUM_PC_FILES_TO_CHECK + NUM_MAC_FILES_TO_CHECK + NUM_DEMO_FILES_TO_CHECK + NUM_MAC_DEMO_FILES_TO_CHECK
     60#define NUM_FILES_TO_CHECK NUM_COMMON_FILES_TO_CHECK + NUM_PC_FILES_TO_CHECK + NUM_MAC_FILES_TO_CHECK + NUM_PSX_FILES_TO_CHECK + NUM_DEMO_FILES_TO_CHECK + NUM_MAC_DEMO_FILES_TO_CHECK
    5861static const char *g_filesToCheck[NUM_FILES_TO_CHECK] = { // these files have to be found
    59         "swordres.rif", // Mac and PC version
    60         "general.clu", // PC version only
    61         "compacts.clu", // PC version only
    62         "scripts.clu", // PC version only
     62        "swordres.rif", // Mac, PC and PSX version
     63        "general.clu", // PC and PSX version
     64        "compacts.clu", // PC and PSX version
     65        "scripts.clu", // PC and PSX version
    6366        "general.clm", // Mac version only
    6467        "compacts.clm", // Mac version only
    6568        "scripts.clm", // Mac version only
    6669        "paris2.clm", // Mac version (full game only)
    6770        "cows.mad",     // this one should only exist in the demo version
    6871        "scripts.clm", // Mac version both demo and full game
     72        "speech.dat", // PSX version only
     73        "tunes.dat", // PSX version only
    6974        // the engine needs several more files to work, but checking these should be sufficient
    7075};
    7176
     
    123128                return sword1MacFullSettings;
    124129        if (0 == scumm_stricmp(gameid, sword1MacDemoSettings.gameid))
    125130                return sword1MacDemoSettings;
     131        if (0 == scumm_stricmp(gameid, sword1PSXSettings.gameid))
     132                return sword1PSXSettings;
    126133        return GameDescriptor();
    127134}
    128135
     
    157164        bool macFilesFound = true;
    158165        bool demoFilesFound = true;
    159166        bool macDemoFilesFound = true;
     167        bool psxFilesFound = true;
    160168        for (i = 0; i < NUM_COMMON_FILES_TO_CHECK; i++)
    161169                if (!filesFound[i])
    162170                        mainFilesFound = false;
     
    172180        for (j = 0; j < NUM_DEMO_FILES_TO_CHECK; i++, j++)
    173181                if (!filesFound[i])
    174182                        macDemoFilesFound = false;
     183        for (j = 0; j < NUM_PSX_FILES_TO_CHECK; i++, j++)
     184                if (!filesFound[i])
     185                        psxFilesFound = false;
    175186
    176187        if (mainFilesFound && pcFilesFound && demoFilesFound)
    177188                detectedGames.push_back(sword1DemoSettings);
    178         else if (mainFilesFound && pcFilesFound)
     189        else if (mainFilesFound && pcFilesFound && psxFilesFound)
     190                detectedGames.push_back(sword1PSXSettings);
     191        else if (mainFilesFound && pcFilesFound && !psxFilesFound)
    179192                detectedGames.push_back(sword1FullSettings);
    180193        else if (mainFilesFound && macFilesFound)
    181194                detectedGames.push_back(sword1MacFullSettings);
  • scummvm-bspsx/engines/sword1/sword1.cpp

     
    8484
    8585        if ( 0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1mac") ||
    8686             0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1macdemo") )
    87                 _systemVars.isMac = true;
     87                _systemVars.platform = Common::kPlatformMacintosh;
     88        else if (0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1psx"))
     89                _systemVars.platform = Common::kPlatformPSX;
    8890        else
    89                 _systemVars.isMac = false;
     91                _systemVars.platform = Common::kPlatformWindows;
    9092
    9193        checkCdFiles();
    9294
    9395        debug(5, "Starting resource manager");
    94         _resMan = new ResMan("swordres.rif", _systemVars.isMac);
     96        _resMan = new ResMan("swordres.rif", _systemVars.platform == Common::kPlatformMacintosh);
    9597        debug(5, "Starting object manager");
    9698        _objectMan = new ObjectMan(_resMan);
    9799        _mouse = new Mouse(_system, _resMan, _objectMan);
     
    308310#endif
    309311};
    310312
     313const CdFile SwordEngine::_psxCdFileList[] = { // PSX edition has only one cd
     314        { "paris2.clu", FLAG_CD1 },
     315        { "ireland.clu", FLAG_CD1 },
     316        { "paris3.clu", FLAG_CD1 },
     317        { "paris4.clu", FLAG_CD1 },
     318        { "scotland.clu", FLAG_CD1 },
     319        { "spain.clu", FLAG_CD1 },
     320        { "syria.clu", FLAG_CD1 },
     321        { "train.clu", FLAG_CD1 },
     322        { "train.plx", FLAG_CD1 },
     323        { "compacts.clu", FLAG_CD1 | FLAG_IMMED },
     324        { "general.clu", FLAG_CD1 | FLAG_IMMED },
     325        { "maps.clu", FLAG_CD1 },
     326        { "paris1.clu", FLAG_CD1 },
     327        { "scripts.clu", FLAG_CD1 | FLAG_IMMED },
     328        { "swordres.rif", FLAG_CD1 | FLAG_IMMED },
     329        { "text.clu", FLAG_CD1 },
     330        { "speech.dat", FLAG_SPEECH1 },
     331        { "speech.tab", FLAG_SPEECH1 },
     332        { "speech.inf", FLAG_SPEECH1 },
     333        { "speech.lis", FLAG_SPEECH1 }
     334};
    311335
    312336void SwordEngine::showFileErrorMsg(uint8 type, bool *fileExists) {
    313337        char msg[1024];
    314338        int missCnt = 0, missNum = 0;
    315339
    316         if (_systemVars.isMac) {
     340        if (SwordEngine::isMac()) {
    317341                for (int i = 0; i < ARRAYSIZE(_macCdFileList); i++)
    318342                        if (!fileExists[i]) {
    319343                                missCnt++;
     
    335359                                        pos += sprintf(pos, "\"%s\" (CD %d)\n", _macCdFileList[i].name, (_macCdFileList[i].flags & FLAG_CD2) ? 2 : 1);
    336360                                }
    337361                }
     362        } else if (SwordEngine::isPsx()) {
     363                for (int i = 0; i < ARRAYSIZE(_psxCdFileList); i++)
     364                        if (!fileExists[i]) {
     365                                missCnt++;
     366                                missNum = i;
     367                        }
     368                assert(missCnt > 0); // this function shouldn't get called if there's nothing missing.
     369                warning("%d files missing", missCnt);
     370                int msgId = (type == TYPE_IMMED) ? 0 : 2;
     371                if (missCnt == 1) {
     372                        sprintf(msg, errorMsgs[msgId], _psxCdFileList[missNum].name, 1);
     373                        warning("%s", msg);
     374                } else {
     375                        char *pos = msg + sprintf(msg, errorMsgs[msgId + 1], missCnt);
     376                        warning("%s", msg);
     377                        for (int i = 0; i < ARRAYSIZE(_psxCdFileList); i++)
     378                                if (!fileExists[i]) {
     379                                        warning("\"%s\"", _macCdFileList[i].name);
     380                                        pos += sprintf(pos, "\"%s\"\n", _macCdFileList[i].name);
     381                                }
     382                }
    338383        } else {
    339384                for (int i = 0; i < ARRAYSIZE(_pcCdFileList); i++)
    340385                        if (!fileExists[i]) {
     
    374419        _systemVars.playSpeech = true;
    375420
    376421        // check all files and look out if we can find a file that wouldn't exist if this was the demo version
    377         if (_systemVars.isMac) {
     422        if (SwordEngine::isMac()) {
    378423                for (int fcnt = 0; fcnt < ARRAYSIZE(_macCdFileList); fcnt++) {
    379424                        if (Common::File::exists(_macCdFileList[fcnt].name)) {
    380425                                fileExists[fcnt] = true;
     
    388433                                fileExists[fcnt] = false;
    389434                        }
    390435                }
     436        } else if (SwordEngine::isPsx()) {
     437                for (int fcnt = 0; fcnt < ARRAYSIZE(_psxCdFileList); fcnt++) {
     438                        if (Common::File::exists(_psxCdFileList[fcnt].name)) {
     439                                fileExists[fcnt] = true;
     440                                flagsToBool(foundTypes, _psxCdFileList[fcnt].flags);
     441                                isFullVersion = true;
     442                                cd2FilesFound = true;
     443                        } else {
     444                                flagsToBool(missingTypes, _psxCdFileList[fcnt].flags);
     445                                fileExists[fcnt] = false;
     446                        }
     447                }
    391448        } else {
    392449                for (int fcnt = 0; fcnt < ARRAYSIZE(_pcCdFileList); fcnt++) {
    393450                        if (Common::File::exists(_pcCdFileList[fcnt].name)) {
     
    422479                somethingMissing |= missingTypes[i];
    423480        if (somethingMissing) { // okay, there *are* files missing
    424481                // first, update the fileExists[] array depending on our changed missingTypes
    425                 if (_systemVars.isMac) {
     482                if (SwordEngine::isMac()) {
    426483                        for (int fileCnt = 0; fileCnt < ARRAYSIZE(_macCdFileList); fileCnt++)
    427484                                if (!fileExists[fileCnt]) {
    428485                                        fileExists[fileCnt] = true;
     
    430487                                                if (missingTypes[flagCnt] && ((_macCdFileList[fileCnt].flags & (1 << flagCnt)) != 0))
    431488                                                        fileExists[fileCnt] = false; // this is one of the files we were looking for
    432489                                }
     490                } else if (SwordEngine::isPsx()) {
     491                        for (int fileCnt = 0; fileCnt < ARRAYSIZE(_psxCdFileList); fileCnt++)
     492                                if (!fileExists[fileCnt]) {
     493                                        fileExists[fileCnt] = true;
     494                                        for (int flagCnt = 0; flagCnt < 8; flagCnt++)
     495                                                if (missingTypes[flagCnt] && ((_psxCdFileList[fileCnt].flags & (1 << flagCnt)) != 0))
     496                                                        fileExists[fileCnt] = false; // this is one of the files we were looking for
     497                                }
    433498                } else {
    434499                        for (int fileCnt = 0; fileCnt < ARRAYSIZE(_pcCdFileList); fileCnt++)
    435500                                if (!fileExists[fileCnt]) {
  • scummvm-bspsx/engines/sword1/music.cpp

     
    2929#include "common/util.h"
    3030#include "common/system.h"
    3131
     32#include "sword1/sword1.h"
    3233#include "sword1/music.h"
     34#include "sword1/vag.h"
     35
    3336#include "sound/aiff.h"
    3437#include "sound/flac.h"
    3538#include "sound/mixer.h"
     
    252255        return true;
    253256}
    254257
     258bool MusicHandle::playPSX(uint16 id, bool loop) {
     259        stop();
     260
     261        if (!_file.isOpen())
     262                if (!_file.open("tunes.dat"))
     263                        return false;
     264               
     265        Common::File tableFile;
     266        if (!tableFile.open("tunes.tab"))
     267                return false;
     268
     269        tableFile.seek((id - 1) * 8, SEEK_SET);
     270        uint32 offset = tableFile.readUint32LE() * 0x800;
     271        uint32 size = tableFile.readUint32LE();
     272
     273        tableFile.close();
     274
     275        if (size != 0xffffffff) {
     276                _file.seek(offset, SEEK_SET);
     277                _audioSource = new VagStream(_file.readStream(size), loop);
     278                fadeUp();
     279        } else {
     280                _audioSource = NULL;
     281                return false;
     282        }
     283       
     284        return true;
     285}
     286
    255287void MusicHandle::fadeDown() {
    256288        if (streaming()) {
    257289                if (_fading < 0)
     
    276308        return !streaming();
    277309}
    278310
    279 // is we don't have an audiosource, return some dummy values.
    280 // shouldn't happen anyways.
     311// if we don't have an audiosource, return some dummy values.
    281312bool MusicHandle::streaming(void) const {
    282313        return (_audioSource) ? (!_audioSource->endOfStream()) : false;
    283314}
     
    411442                /* The handle will load the music file now. It can take a while, so unlock
    412443                   the mutex before, to have the soundthread playing normally.
    413444                   As the corresponding _converter is NULL, the handle will be ignored by the playing thread */
    414                 if (_handles[newStream].play(_tuneList[tuneId], loopFlag != 0)) {
     445                if (SwordEngine::isPsx()) { ;
     446                        if (_handles[newStream].playPSX(tuneId, loopFlag != 0)) {
     447                                _mutex.lock();
     448                                _converter[newStream] = Audio::makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), false);
     449                                _mutex.unlock();
     450                        }
     451                } else if (_handles[newStream].play(_tuneList[tuneId], loopFlag != 0)) {
    415452                        _mutex.lock();
    416453                        _converter[newStream] = Audio::makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), false);
    417454                        _mutex.unlock();
  • scummvm-bspsx/engines/sword1/screen.h

     
    9696        void fnFlash(uint8 color);
    9797        void fnBorder(uint8 color);
    9898
     99        static void decompressHIF(uint8 *src, uint8 *dest);
     100
    99101#ifdef BACKEND_8BIT
    100102        void plotYUV(byte *lut, int width, int height, byte *const *dat);
    101103#endif
     
    116118        void processImage(uint32 id);
    117119        void spriteClipAndSet(uint16 *pSprX, uint16 *pSprY, uint16 *sprWidth, uint16 *sprHeight, uint16 *incr);
    118120        void drawSprite(uint8 *sprData, uint16 sprX, uint16 sprY, uint16 sprWidth, uint16 sprHeight, uint16 sprPitch);
     121        void drawPsxHalfShrinkedSprite(uint8 *sprData, uint16 sprX, uint16 sprY, uint16 sprWidth, uint16 sprHeight, uint16 sprPitch);
     122        void drawPsxFullShrinkedSprite(uint8 *sprData, uint16 sprX, uint16 sprY, uint16 sprWidth, uint16 sprHeight, uint16 sprPitch);
     123        uint8* psxBackgroundToIndexed(uint8* psxBackground, uint32 bakXres, uint32 bakYres);
     124        uint8* psxShrinkedBackgroundToIndexed(uint8* psxBackground, uint32 bakXres, uint32 bakYres);
     125        uint8* psxParallaxToIndexed(uint8* psxParallax);
    119126        void decompressRLE7(uint8 *src, uint32 compSize, uint8 *dest);
    120127        void decompressRLE0(uint8 *src, uint32 compSize, uint8 *dest);
    121128        void decompressTony(uint8 *src, uint32 compSize, uint8 *dest);
     
    160167
    161168#endif //BSSCREEN_H
    162169
     170
     171
  • scummvm-bspsx/engines/sword1/mouse.cpp

     
    3737#include "sword1/sworddefs.h"
    3838#include "sword1/swordres.h"
    3939#include "sword1/menu.h"
     40#include "sword1/sword1.h"
    4041
    4142namespace Sword1 {
    4243
     
    201202        if (ptrId) {
    202203                MousePtr *lugg = NULL;
    203204                MousePtr *ptr = (MousePtr*)_resMan->openFetchRes(ptrId);
    204                 uint16 resSizeX = _resMan->getLEUint16(ptr->sizeX);
    205                 uint16 resSizeY = _resMan->getLEUint16(ptr->sizeY);
    206205                uint16 noFrames = _resMan->getLEUint16(ptr->numFrames);
     206                uint16 ptrSizeX = _resMan->getLEUint16(ptr->sizeX);
     207                uint16 ptrSizeY = _resMan->getLEUint16(ptr->sizeY);
     208                uint16 luggSizeX;
     209                uint16 luggSizeY;
     210                uint16 resSizeX;
     211                uint16 resSizeY;
     212
     213                if (SwordEngine::isPsx()) //PSX pointers are half height       
     214                        ptrSizeY *= 2;
     215
    207216                if (luggageId) {
    208217                        lugg = (MousePtr*)_resMan->openFetchRes(luggageId);
    209                         resSizeX = MAX(resSizeX, (uint16)((resSizeX / 2) + _resMan->getLEUint16(lugg->sizeX)));
    210                         resSizeY = MAX(resSizeY, (uint16)((resSizeY / 2) + _resMan->getLEUint16(lugg->sizeY)));
     218                        luggSizeX = _resMan->getLEUint16(lugg->sizeX);
     219                        luggSizeY = _resMan->getLEUint16(lugg->sizeY);
     220
     221                        if (SwordEngine::isPsx())
     222                                luggSizeY *= 2;
     223
     224                        resSizeX = MAX(ptrSizeX, (uint16)((ptrSizeX / 2) + luggSizeX));
     225                        resSizeY = MAX(ptrSizeY, (uint16)((ptrSizeY / 2) + luggSizeY));
     226                } else {
     227                        resSizeX = ptrSizeX;
     228                        resSizeY = ptrSizeY;
    211229                }
    212230                _currentPtr = (MousePtr*)malloc(sizeof(MousePtr) + resSizeX * resSizeY * noFrames);
    213231                _currentPtr->hotSpotX = _resMan->getLEUint16(ptr->hotSpotX);
     
    218236                uint8 *ptrData = (uint8*)_currentPtr + sizeof(MousePtr);
    219237                memset(ptrData, 255, resSizeX * resSizeY * noFrames);
    220238                if (luggageId) {
    221                         uint8 *dstData = ptrData + resSizeX - _resMan->getLEUint16(lugg->sizeX);
     239                        uint8 *dstData = ptrData + resSizeX - luggSizeX;
    222240                        for (uint32 frameCnt = 0; frameCnt < noFrames; frameCnt++) {
    223241                                uint8 *luggSrc = (uint8*)lugg + sizeof(MousePtr);
    224                                 dstData += (resSizeY - _resMan->getLEUint16(lugg->sizeY)) * resSizeX;
    225                                 for (uint32 cnty = 0; cnty < _resMan->getLEUint16(lugg->sizeY); cnty++) {
    226                                         for (uint32 cntx = 0; cntx < _resMan->getLEUint16(lugg->sizeX); cntx++)
     242                                dstData += (resSizeY - luggSizeY) * resSizeX;
     243                                for (uint32 cnty = 0; cnty < (SwordEngine::isPsx() ? luggSizeY / 2 : luggSizeY); cnty++) {
     244                                        for (uint32 cntx = 0; cntx < luggSizeX; cntx++)
    227245                                                if (luggSrc[cntx])
    228246                                                        dstData[cntx] = luggSrc[cntx];
     247                                       
     248                                        if(SwordEngine::isPsx()) {
     249                                                dstData += resSizeX;
     250                                                for (uint32 cntx = 0; cntx < luggSizeX; cntx++)
     251                                                        if (luggSrc[cntx])
     252                                                                dstData[cntx] = luggSrc[cntx];
     253                                        }
     254
    229255                                        dstData += resSizeX;
    230                                         luggSrc += _resMan->getLEUint16(lugg->sizeX);
     256                                        luggSrc += luggSizeX;
    231257                                }
    232258                        }
    233259                        _resMan->resClose(luggageId);
    234260                }
     261               
    235262                uint8 *dstData = ptrData;
    236263                uint8 *srcData = (uint8*)ptr + sizeof(MousePtr);
    237264                for (uint32 frameCnt = 0; frameCnt < noFrames; frameCnt++) {
    238                         for (uint32 cnty = 0; cnty < _resMan->getLEUint16(ptr->sizeY); cnty++) {
    239                                 for (uint32 cntx = 0; cntx < _resMan->getLEUint16(ptr->sizeX); cntx++)
     265                        for (uint32 cnty = 0; cnty < (SwordEngine::isPsx() ? ptrSizeY / 2 : ptrSizeY); cnty++) {
     266                                for (uint32 cntx = 0; cntx < ptrSizeX; cntx++)
    240267                                        if (srcData[cntx])
    241268                                                dstData[cntx] = srcData[cntx];
    242                                 srcData += _resMan->getLEUint16(ptr->sizeX);
     269
     270                                if(SwordEngine::isPsx()) {             
     271                                        dstData +=resSizeX;
     272                                        for (uint32 cntx = 0; cntx < ptrSizeX; cntx++)
     273                                                if (srcData[cntx])
     274                                                        dstData[cntx] = srcData[cntx];
     275                                }
     276
     277                                srcData += ptrSizeX;
    243278                                dstData += resSizeX;
    244279                        }
    245                         dstData += (resSizeY - _resMan->getLEUint16(ptr->sizeY)) * resSizeX;
     280                        dstData += (resSizeY - ptrSizeY) * resSizeX;
    246281                }
    247282                _resMan->resClose(ptrId);
    248283        }
  • scummvm-bspsx/engines/sword1/text.h

     
    3434#define MAX_TEXT_OBS 3
    3535
    3636#define BORDER_COL      200
     37#define BORDER_COL_PSX 199
    3738#define LETTER_COL      193
    3839#define NO_COL          0       // sprite background - 0 for transparency
    3940
  • scummvm-bspsx/engines/sword1/sound.h

     
    6969        CowFlac,
    7070        CowVorbis,
    7171        CowMp3,
    72         CowDemo
     72        CowDemo,
     73        CowPSX
    7374};
    7475
    7576class Sound {
  • scummvm-bspsx/engines/sword1/screen.cpp

     
    3434#include "sword1/resman.h"
    3535#include "sword1/objectman.h"
    3636#include "sword1/menu.h"
     37#include "sword1/swordres.h"
    3738#include "sword1/sword1.h"
    3839
    3940#ifdef BACKEND_8BIT
     
    137138        if (start == 0) // force color 0 to black
    138139                palData[0] = palData[1] = palData[2] = 0;
    139140
    140         if (SwordEngine::_systemVars.isMac) {  // see bug #1701058
     141        if (SwordEngine::isMac()) {  // see bug #1701058
    141142                if (start != 0 && start + length == 256) // and force color 255 to black as well
    142143                        palData[(length-1)*3+0] = palData[(length-1)*3+1] = palData[(length-1)*3+2] = 0;
    143144        }
     
    358359
    359360void Screen::draw(void) {
    360361        uint8 cnt;
     362       
     363        debug(8, "Screen::draw() -> _currentScreen %u", _currentScreen);
     364       
    361365        if (_currentScreen == 54) {
    362366                // rm54 has a BACKGROUND parallax layer in parallax[0]
    363                 if (_parallax[0])
     367                if (_parallax[0] && !SwordEngine::isPsx() ) //Avoid drawing this parallax on PSX edition, it gets occluded by background
    364368                        renderParallax(_parallax[0]);
    365369                uint8 *src = _layerBlocks[0];
    366370                uint8 *dest = _screenBuf;
     371                uint8 *indxScreen = NULL;
    367372
     373                if(SwordEngine::isPsx()) {
     374                        indxScreen = psxShrinkedBackgroundToIndexed(_layerBlocks[0], _scrnSizeX, _scrnSizeY);
     375                        src = indxScreen;
     376                }
     377
    368378                for (uint16 cnty = 0; cnty < _scrnSizeY; cnty++)
    369379                        for (uint16 cntx = 0; cntx < _scrnSizeX; cntx++) {
    370380                                if (*src)
    371                                         if (!SwordEngine::_systemVars.isMac || *src != 255) // see bug #1701058
     381                                        if (!(SwordEngine::isMac()) || *src != 255) // see bug #1701058
    372382                                                *dest = *src;
    373383                                dest++;
    374384                                src++;
    375385                        }
    376386
    377         } else
     387                free(indxScreen);
     388
     389        } else if (!(SwordEngine::isPsx())) {
    378390                memcpy(_screenBuf, _layerBlocks[0], _scrnSizeX * _scrnSizeY);
     391        } else { //We are using PSX version
     392                uint8 *indxScreen;             
     393                if(_currentScreen == 45 || _currentScreen == 55 ||
     394                   _currentScreen == 57 || _currentScreen == 63 || _currentScreen == 71) // Width shrinked backgrounds
     395                        indxScreen = psxShrinkedBackgroundToIndexed(_layerBlocks[0], _scrnSizeX, _scrnSizeY);
     396                else
     397                        indxScreen = psxBackgroundToIndexed(_layerBlocks[0], _scrnSizeX, _scrnSizeY);
     398                memcpy(_screenBuf, indxScreen, _scrnSizeX * _scrnSizeY);
     399                free(indxScreen);
     400        }
    379401
    380402        for (cnt = 0; cnt < _backLength; cnt++)
    381403                processImage(_backList[cnt]);
     
    393415        if (_parallax[1])
    394416                renderParallax(_parallax[1]);
    395417
     418        // PSX version has parallax layer for this room in an external file (TRAIN.PLX)
     419        if(SwordEngine::isPsx() && _currentScreen == 63) {
     420                Common::File parallax;
     421                uint8 *trainPLX = NULL;
     422                parallax.open("TRAIN.PLX");
     423                trainPLX = (uint8*) malloc(parallax.size());
     424                parallax.read(trainPLX, parallax.size());
     425                parallax.close();
     426                renderParallax(trainPLX);
     427                free(trainPLX);
     428        }
     429
    396430        for (cnt = 0; cnt < _foreLength; cnt++)
    397431                processImage(_foreList[cnt]);
    398432
     
    403437        Object *compact;
    404438        FrameHeader *frameHead;
    405439        int scale;
    406 
     440       
    407441        compact = _objMan->fetchObject(id);
     442       
    408443        if (compact->o_type == TYPE_TEXT)
    409444                frameHead = _textMan->giveSpriteData((uint8)compact->o_target);
    410445        else
     
    414449
    415450        uint16 spriteX = compact->o_anim_x;
    416451        uint16 spriteY = compact->o_anim_y;
     452       
    417453        if (compact->o_status & STAT_SHRINK) {
    418454                scale = (compact->o_scale_a * compact->o_ycoord + compact->o_scale_b) / 256;
    419455                spriteX += ((int16)_resMan->readUint16(&frameHead->offsetX) * scale) / 256;
     
    425461        }
    426462
    427463        uint8 *tonyBuf = NULL;
    428         if (frameHead->runTimeComp[3] == '7') { // RLE7 encoded?
     464        uint8 *hifBuf = NULL;
     465        if (SwordEngine::isPsx() && compact->o_type != TYPE_TEXT) { // PSX sprites are compressed with HIF
     466                hifBuf = (uint8*)malloc(_resMan->readUint16(&frameHead->width) * _resMan->readUint16(&frameHead->height)/2);
     467                memset(hifBuf, 0x00, (_resMan->readUint16(&frameHead->width) * _resMan->readUint16(&frameHead->height)/2));
     468                decompressHIF(sprData, hifBuf);
     469                sprData = hifBuf;
     470        } else if (frameHead->runTimeComp[3] == '7') { // RLE7 encoded?
    429471                decompressRLE7(sprData, _resMan->readUint32(&frameHead->compSize), _rleBuffer);
    430472                sprData = _rleBuffer;
    431473        } else if (frameHead->runTimeComp[3] == '0') { // RLE0 encoded?
     
    439481
    440482        uint16 sprSizeX, sprSizeY;
    441483        if (compact->o_status & STAT_SHRINK) {
    442                 sprSizeX = (scale * _resMan->readUint16(&frameHead->width)) / 256;
    443                 sprSizeY = (scale * _resMan->readUint16(&frameHead->height)) / 256;
    444                 fastShrink(sprData, _resMan->readUint16(&frameHead->width), _resMan->readUint16(&frameHead->height), scale, _shrinkBuffer);
     484                memset(_shrinkBuffer, 0, SHRINK_BUFFER_SIZE); //Clean shrink buffer to avoid corruption
     485                if( SwordEngine::isPsx() && (compact->o_resource != GEORGE_MEGA)) { //PSX Height shrinked sprites
     486                        sprSizeX = (scale * _resMan->readUint16(&frameHead->width)) / 256;
     487                        sprSizeY = (scale * (_resMan->readUint16(&frameHead->height))) / 256 / 2;
     488                        fastShrink(sprData, _resMan->readUint16(&frameHead->width), (_resMan->readUint16(&frameHead->height)) / 2, scale, _shrinkBuffer);
     489                } else if (SwordEngine::isPsx()) { //PSX width/height shrinked sprites
     490                        sprSizeX = (scale * _resMan->readUint16(&frameHead->width)) / 256 / 2;
     491                        sprSizeY = (scale * _resMan->readUint16(&frameHead->height)) / 256 / 2;
     492                        fastShrink(sprData, _resMan->readUint16(&frameHead->width) / 2, _resMan->readUint16(&frameHead->height) / 2, scale, _shrinkBuffer);
     493                } else {
     494                        sprSizeX = (scale * _resMan->readUint16(&frameHead->width)) / 256;
     495                        sprSizeY = (scale * _resMan->readUint16(&frameHead->height)) / 256;
     496                        fastShrink(sprData, _resMan->readUint16(&frameHead->width), _resMan->readUint16(&frameHead->height), scale, _shrinkBuffer);
     497                }
    445498                sprData = _shrinkBuffer;
    446499        } else {
    447500                sprSizeX = _resMan->readUint16(&frameHead->width);
    448                 sprSizeY = _resMan->readUint16(&frameHead->height);
     501                if(SwordEngine::isPsx()) { //PSX sprites are half height
     502                        sprSizeY = _resMan->readUint16(&frameHead->height) / 2;
     503                } else
     504                        sprSizeY = (_resMan->readUint16(&frameHead->height));
    449505        }
     506       
    450507        if (!(compact->o_status & STAT_OVERRIDE)) {
    451508                //mouse size linked to exact size & coordinates of sprite box - shrink friendly
    452509                if (_resMan->readUint16(&frameHead->offsetX) || _resMan->readUint16(&frameHead->offsetY)) {
     
    463520                        compact->o_mouse_y2 = spriteY + sprSizeY;
    464521                }
    465522        }
     523
    466524        uint16 sprPitch = sprSizeX;
    467525        uint16 incr;
    468526        spriteClipAndSet(&spriteX, &spriteY, &sprSizeX, &sprSizeY, &incr);
     527
    469528        if ((sprSizeX > 0) && (sprSizeY > 0)) {
    470                 drawSprite(sprData + incr, spriteX, spriteY, sprSizeX, sprSizeY, sprPitch);
    471                 if (!(compact->o_status&STAT_FORE))
     529                if( (!(SwordEngine::isPsx()) || (compact->o_type == TYPE_TEXT)
     530                || (compact->o_resource == LVSFLY) || !(compact->o_resource == GEORGE_MEGA) && (sprSizeX < 260)))
     531                        drawSprite(sprData + incr, spriteX, spriteY, sprSizeX, sprSizeY, sprPitch);
     532                else if (((sprSizeX >= 260) && (sprSizeX < 450)) || ((compact->o_resource == GMWRITH) && (sprSizeX < 515))  // a psx shrinked sprite (1/2 width)
     533                                || ((compact->o_resource == GMPOWER) && (sprSizeX < 515)) )                                         // some needs to be hardcoded, headers don't give useful infos
     534                        drawPsxHalfShrinkedSprite(sprData + incr, spriteX, spriteY, sprSizeX / 2, sprSizeY, sprPitch / 2);
     535                else if (sprSizeX >= 450) // A PSX double shrinked sprite (1/3 width)
     536                        drawPsxFullShrinkedSprite(sprData + incr, spriteX, spriteY, sprSizeX / 3, sprSizeY, sprPitch / 3);
     537                else // This is for psx half shrinked, walking george and remaining sprites
     538                        drawPsxHalfShrinkedSprite(sprData + incr, spriteX, spriteY, sprSizeX, sprSizeY, sprPitch);
     539                if (!(compact->o_status&STAT_FORE) && !(SwordEngine::isPsx() && (compact->o_resource == MOUBUSY))) // Check fixes moue sprite being masked by layer, happens only on psx
    472540                        verticalMask(spriteX, spriteY, sprSizeX, sprSizeY);
    473541        }
     542       
    474543        if (compact->o_type != TYPE_TEXT)
    475544                _resMan->resClose(compact->o_resource);
     545       
    476546        if (tonyBuf)
    477547                free(tonyBuf);
     548               
     549        if (hifBuf)
     550                free(hifBuf);
    478551}
    479552
    480553void Screen::verticalMask(uint16 x, uint16 y, uint16 bWidth, uint16 bHeight) {
    481554        if (_roomDefTable[_currentScreen].totalLayers <= 1)
    482555                return;
    483556
     557        if (SwordEngine::isPsx()) { // PSX sprites are vertical shrinked, and some width shrinked
     558                bHeight *= 2;
     559                bWidth *= 2;
     560        }
     561               
    484562        bWidth = (bWidth + (x & (SCRNGRID_X - 1)) + (SCRNGRID_X - 1)) / SCRNGRID_X;
    485563        bHeight = (bHeight + (y & (SCRNGRID_Y - 1)) + (SCRNGRID_Y - 1)) / SCRNGRID_Y;
    486564
     
    504582                                uint16 *grid = _layerGrid[level] + gridX + blkx + gridY * lGridSizeX;
    505583                                for (int16 blky = bHeight - 1; blky >= 0; blky--) {
    506584                                        if (*grid) {
    507                                                 uint8 *blkData = _layerBlocks[level + 1] + (_resMan->readUint16(grid) - 1) * 128;
     585                                                uint8 *blkData;
     586                                                if (SwordEngine::isPsx())
     587                                                        blkData = _layerBlocks[level + 1] + (_resMan->readUint16(grid) - 1) * 64; //PSX layers are half height too...
     588                                                else
     589                                                        blkData = _layerBlocks[level + 1] + (_resMan->readUint16(grid) - 1) * 128;
    508590                                                blitBlockClear(x + blkx, y + blky, blkData);
    509591                                        } else
    510592                                                break;
     
    517599
    518600void Screen::blitBlockClear(uint16 x, uint16 y, uint8 *data) {
    519601        uint8 *dest = _screenBuf + (y * SCRNGRID_Y) * _scrnSizeX + (x * SCRNGRID_X);
    520         for (uint8 cnty = 0; cnty < SCRNGRID_Y; cnty++) {
     602
     603        for (uint8 cnty = 0; cnty < (SwordEngine::isPsx() ? SCRNGRID_Y / 2 : SCRNGRID_Y); cnty++) {
    521604                for (uint8 cntx = 0; cntx < SCRNGRID_X; cntx++)
    522605                        if (data[cntx])
    523606                                dest[cntx] = data[cntx];
     607                               
     608                if (SwordEngine::isPsx()) {
     609                        dest += _scrnSizeX;
     610                        for (uint8 cntx = 0; cntx < SCRNGRID_X; cntx++)
     611                                if (data[cntx])
     612                                        dest[cntx] = data[cntx];
     613                }       
     614                       
    524615                data += SCRNGRID_X;
    525616                dest += _scrnSizeX;
    526617        }
    527618}
    528619
    529620void Screen::renderParallax(uint8 *data) {
    530         ParallaxHeader *header = (ParallaxHeader*)data;
    531         uint32 *lineIndexes = (uint32*)(data + sizeof(ParallaxHeader));
    532         assert((_resMan->getUint16(header->sizeX) >= SCREEN_WIDTH) && (_resMan->getUint16(header->sizeY) >= SCREEN_DEPTH));
    533 
    534621        uint16 paraScrlX, paraScrlY;
    535622        uint16 scrnScrlX, scrnScrlY;
    536623        uint16 scrnWidth, scrnHeight;
     624        uint16 paraSizeX, paraSizeY;
     625        uint8 *psxPlx = NULL;
     626        ParallaxHeader *header = NULL;
     627        uint32 *lineIndexes = NULL;
    537628
     629        if (SwordEngine::isPsx()) { //Parallax headers are different in PSX version
     630                psxPlx = psxParallaxToIndexed(data);
     631                paraSizeX = READ_LE_UINT16(psxPlx);
     632                paraSizeY = READ_LE_UINT16(psxPlx+2);
     633        } else {
     634                header = (ParallaxHeader*)data;
     635                lineIndexes = (uint32*)(data + sizeof(ParallaxHeader));
     636                paraSizeX = _resMan->getUint16(header->sizeX);
     637                paraSizeY = _resMan->getUint16(header->sizeY);
     638        }
     639
     640        assert((paraSizeX >= SCREEN_WIDTH) && (paraSizeY >= SCREEN_DEPTH));
     641
    538642        // we have to render more than the visible screen part for displaying scroll frames
    539643        scrnScrlX = MIN((uint32)_oldScrollX, Logic::_scriptVars[SCROLL_OFFSET_X]);
    540644        scrnWidth = SCREEN_WIDTH + ABS((int32)_oldScrollX - (int32)Logic::_scriptVars[SCROLL_OFFSET_X]);
    541645        scrnScrlY = MIN((uint32)_oldScrollY, Logic::_scriptVars[SCROLL_OFFSET_Y]);
    542646        scrnHeight = SCREEN_DEPTH + ABS((int32)_oldScrollY - (int32)Logic::_scriptVars[SCROLL_OFFSET_Y]);
    543647
     648
    544649        if (_scrnSizeX != SCREEN_WIDTH) {
    545                 double scrlfx = (_resMan->getUint16(header->sizeX) - SCREEN_WIDTH) / ((double)(_scrnSizeX - SCREEN_WIDTH));
     650                double scrlfx = (paraSizeX - SCREEN_WIDTH) / ((double)(_scrnSizeX - SCREEN_WIDTH));
    546651                paraScrlX = (uint16)(scrnScrlX * scrlfx);
    547652        } else
    548653                paraScrlX = 0;
    549654
    550655        if (_scrnSizeY != SCREEN_DEPTH) {
    551                 double scrlfy = (_resMan->getUint16(header->sizeY) - SCREEN_DEPTH) / ((double)(_scrnSizeY - SCREEN_DEPTH));
     656                double scrlfy = (paraSizeY - SCREEN_DEPTH) / ((double)(_scrnSizeY - SCREEN_DEPTH));
    552657                paraScrlY = (uint16)(scrnScrlY * scrlfy);
    553658        } else
    554659                paraScrlY = 0;
    555660
    556         for (uint16 cnty = 0; cnty < scrnHeight; cnty++) {
    557                 uint8 *src = data + _resMan->readUint32(lineIndexes + cnty + paraScrlY);
    558                 uint8 *dest = _screenBuf + scrnScrlX + (cnty + scrnScrlY) * _scrnSizeX;
    559                 uint16 remain = paraScrlX;
    560                 uint16 xPos = 0;
    561                 while (remain) { // skip past the first part of the parallax to get to the right scrolling position
    562                         uint8 doSkip = *src++;
    563                         if (doSkip <= remain)
    564                                 remain -= doSkip;
    565                         else {
    566                                 xPos = doSkip - remain;
    567                                 dest += xPos;
    568                                 remain = 0;
    569                         }
    570                         uint8 doCopy = *src++;
    571                         if (doCopy <= remain) {
    572                                 remain -= doCopy;
    573                                 src += doCopy;
    574                         } else {
    575                                 uint16 remCopy = doCopy - remain;
    576                                 memcpy(dest, src + remain, remCopy);
    577                                 dest += remCopy;
    578                                 src += doCopy;
    579                                 xPos = remCopy;
    580                                 remain = 0;
    581                         }
     661        if(SwordEngine::isPsx())
     662                for (uint16 cnty = 0; (cnty < SCREEN_DEPTH) && (cnty < paraSizeY); cnty++) {
     663                        uint8 *src = psxPlx + 4 + paraScrlY * paraSizeX + cnty * paraSizeX + paraScrlX;
     664                        uint8 *dest = _screenBuf + scrnScrlX + (cnty + scrnScrlY) * _scrnSizeX/* * 2*/;
     665                        uint8 pix;
     666                        for (uint16 idx = 0; (idx < SCREEN_WIDTH) && (idx < paraSizeX); idx++) // make sure we don't write outside screen
     667                                if (pix = *(src + idx)) //If data is 0x00, don't write (transparency)
     668                                        *(dest + idx) = pix;
    582669                }
    583                 while (xPos < scrnWidth) {
    584                         if (uint8 skip = *src++) {
    585                                 dest += skip;
    586                                 xPos += skip;
    587                         }
    588                         if (xPos < scrnWidth) {
    589                                 if (uint8 doCopy = *src++) {
    590                                         if (xPos + doCopy > scrnWidth)
    591                                                 doCopy = scrnWidth - xPos;
    592                                         memcpy(dest, src, doCopy);
    593                                         dest += doCopy;
    594                                         xPos += doCopy;
     670        else
     671                for (uint16 cnty = 0; cnty < scrnHeight; cnty++) {
     672                        uint8 *src = data + _resMan->readUint32(lineIndexes + cnty + paraScrlY);
     673                        uint8 *dest = _screenBuf + scrnScrlX + (cnty + scrnScrlY) * _scrnSizeX;
     674                        uint16 remain = paraScrlX;
     675                        uint16 xPos = 0;
     676                        while (remain) { // skip past the first part of the parallax to get to the right scrolling position
     677                                uint8 doSkip = *src++;
     678                                if (doSkip <= remain)
     679                                        remain -= doSkip;
     680                                else {
     681                                        xPos = doSkip - remain;
     682                                        dest += xPos;
     683                                        remain = 0;
     684                                }
     685                                uint8 doCopy = *src++;
     686                                if (doCopy <= remain) {
     687                                        remain -= doCopy;
    595688                                        src += doCopy;
     689                                } else {
     690                                        uint16 remCopy = doCopy - remain;
     691                                        memcpy(dest, src + remain, remCopy);
     692                                        dest += remCopy;
     693                                        src += doCopy;
     694                                        xPos = remCopy;
     695                                        remain = 0;
    596696                                }
    597697                        }
     698                        while (xPos < scrnWidth) {
     699                                if (uint8 skip = *src++) {
     700                                        dest += skip;
     701                                        xPos += skip;
     702                                }
     703                                if (xPos < scrnWidth) {
     704                                        if (uint8 doCopy = *src++) {
     705                                                if (xPos + doCopy > scrnWidth)
     706                                                        doCopy = scrnWidth - xPos;
     707                                                memcpy(dest, src, doCopy);
     708                                                dest += doCopy;
     709                                                xPos += doCopy;
     710                                                src += doCopy;
     711                                        }
     712                                }
     713                        }
    598714                }
    599         }
     715
     716        if (psxPlx)
     717                free(psxPlx);
    600718}
    601719
    602720void Screen::drawSprite(uint8 *sprData, uint16 sprX, uint16 sprY, uint16 sprWidth, uint16 sprHeight, uint16 sprPitch) {
    603721        uint8 *dest = _screenBuf + (sprY * _scrnSizeX) + sprX;
    604 
     722       
    605723        for (uint16 cnty = 0; cnty < sprHeight; cnty++) {
    606724                for (uint16 cntx = 0; cntx < sprWidth; cntx++)
    607725                        if (sprData[cntx])
    608726                                dest[cntx] = sprData[cntx];
     727                               
     728                if (SwordEngine::isPsx()) { //On PSX version we need to double horizontal lines
     729                        dest += _scrnSizeX;
     730                        for (uint16 cntx = 0; cntx < sprWidth; cntx++)
     731                                if (sprData[cntx])
     732                                        dest[cntx] = sprData[cntx];
     733                }
     734                       
    609735                sprData += sprPitch;
    610736                dest += _scrnSizeX;
    611737        }
    612738}
    613739
     740// Used to draw psx sprites which are 1/2 of original width
     741void Screen::drawPsxHalfShrinkedSprite(uint8 *sprData, uint16 sprX, uint16 sprY, uint16 sprWidth, uint16 sprHeight, uint16 sprPitch) {
     742        uint8 *dest = _screenBuf + (sprY * _scrnSizeX) + sprX;
     743       
     744        for (uint16 cnty = 0; cnty < sprHeight; cnty++) {
     745                for (uint16 cntx = 0; cntx < sprWidth; cntx++)
     746                        if (sprData[cntx]) {
     747                                dest[cntx * 2] = sprData[cntx]; //In these sprites we need to double vetical lines too...
     748                                dest[cntx * 2 + 1] = sprData[cntx];
     749                        }
     750                               
     751                dest += _scrnSizeX;
     752                for (uint16 cntx = 0; cntx < sprWidth; cntx++)
     753                        if (sprData[cntx]) {
     754                                dest[cntx * 2] = sprData[cntx];
     755                                dest[cntx * 2 + 1] = sprData[cntx];
     756                        }
     757
     758                sprData += sprPitch;
     759                dest += _scrnSizeX;
     760        }
     761}
     762
     763// Used to draw psx sprites which are 1/3 of original width
     764void Screen::drawPsxFullShrinkedSprite(uint8 *sprData, uint16 sprX, uint16 sprY, uint16 sprWidth, uint16 sprHeight, uint16 sprPitch) {
     765        uint8 *dest = _screenBuf + (sprY * _scrnSizeX) + sprX;
     766
     767        for (uint16 cnty = 0; cnty < sprHeight; cnty++) {
     768                for (uint16 cntx = 0; cntx < sprWidth ; cntx++)
     769                        if (sprData[cntx]) {
     770                                dest[cntx * 3] = sprData[cntx]; //In these sprites we need to double vertical lines too...
     771                                dest[cntx * 3 + 1] = sprData[cntx];
     772                                dest[cntx * 3 + 2] = sprData[cntx];
     773                        }
     774                               
     775                dest += _scrnSizeX;
     776                for (uint16 cntx = 0; cntx < sprWidth; cntx++)
     777                        if (sprData[cntx]) {
     778                                dest[cntx * 3] = sprData[cntx];
     779                                dest[cntx * 3 + 1] = sprData[cntx];
     780                                dest[cntx * 3 + 2] = sprData[cntx];
     781                        }
     782               
     783                sprData += sprPitch;
     784                dest += _scrnSizeX;
     785        }
     786}
     787
    614788// nearest neighbor filter:
    615789void Screen::fastShrink(uint8 *src, uint32 width, uint32 height, uint32 scale, uint8 *dest) {
    616790        uint32 resHeight = (height * scale) >> 8;
     
    618792        uint32 step = 0x10000 / scale;
    619793        uint8 columnTab[160];
    620794        uint32 res = step >> 1;
     795       
    621796        for (uint16 cnt = 0; cnt < resWidth; cnt++) {
    622797                columnTab[cnt] = (uint8)(res >> 8);
    623798                res += step;
     
    675850        }
    676851}
    677852
     853uint8* Screen::psxBackgroundToIndexed(uint8* psxBackground, uint32 bakXres, uint32 bakYres) {
     854        uint32 xresInTiles = bakXres / 16;
     855        uint32 yresInTiles = ((bakYres / 2) % 16) ? (bakYres / 32) + 1 : (bakYres / 32);
     856        uint32 totTiles = xresInTiles * yresInTiles;
     857        uint32 tileYpos = 0; //tile position in a virtual xresInTiles * yresInTiles grid
     858        uint32 tileXpos = 0;
     859        uint32 tag = READ_LE_UINT32(psxBackground);
     860
     861        uint8 *decomp_tile = (uint8 *)malloc(16 * 16); //Tiles are always 16 * 16
     862        uint8 *halfres_buffer = (uint8 *)malloc(totTiles * 16 * 16); //This buffer will contain the half vertical res image
     863
     864        bool isCompressed = (tag == 0x434F4D50);
     865
     866        psxBackground += 4; //We skip the id tag
     867
     868        for (uint32 currentTile = 0; currentTile < totTiles; currentTile++) {
     869                uint32 tileOffset = READ_LE_UINT32(psxBackground + 4 * currentTile);
     870               
     871                if(isCompressed)
     872                        decompressHIF(psxBackground + tileOffset - 4, decomp_tile); //Decompress the tile into decomp_tile
     873                else
     874                        memcpy(decomp_tile, psxBackground + tileOffset - 4, 16*16);
     875
     876                if (currentTile > 0 && !(currentTile % xresInTiles)) { //Finished a line of tiles, going down
     877                        tileYpos++;
     878                        tileXpos = 0;
     879                }
     880               
     881                for (byte tileLine=0; tileLine<16; tileLine++)
     882                        memcpy(halfres_buffer + tileLine * bakXres + tileXpos * 16 + tileYpos * bakXres * 16, decomp_tile + tileLine * 16, 16); //Copy data to destination buffer
     883               
     884                tileXpos++;
     885        }
     886
     887        free(decomp_tile);
     888
     889        uint8 *fullres_buffer = (uint8 *)malloc(bakXres * yresInTiles * 32);
     890        memset(fullres_buffer, 0x00, bakXres * yresInTiles * 32);
     891
     892        //Let's linedouble the image (to keep correct aspect ratio)
     893        for (uint32 currentLine = 0; currentLine < (bakYres/2); currentLine++) {
     894                memcpy(fullres_buffer + currentLine * bakXres * 2, halfres_buffer + currentLine * bakXres, bakXres);        // destination_line is 2*original_line
     895                memcpy(fullres_buffer + currentLine * bakXres * 2 + bakXres, halfres_buffer + currentLine * bakXres, bakXres); // destination_line+1
     896        }
     897       
     898        free(halfres_buffer);
     899
     900        return fullres_buffer;
     901}
     902
     903// needed because some psx backgrounds are half width and half height
     904uint8* Screen::psxShrinkedBackgroundToIndexed(uint8* psxBackground, uint32 bakXres, uint32 bakYres) {
     905        uint32 xresInTiles = (bakXres / 2) % 16 ? (bakXres / 32) + 1 : (bakXres / 32);
     906        uint32 yresInTiles =  (bakYres / 2) % 16 ? (bakYres / 32) + 1 : (bakYres / 32);
     907        uint32 totTiles = xresInTiles * yresInTiles;
     908        uint32 tileYpos = 0; //tile position in a virtual xresInTiles * yresInTiles grid
     909        uint32 tileXpos = 0;
     910        uint32 dataBegin = READ_LE_UINT32(psxBackground + 4);
     911        uint32 realWidth = xresInTiles * 16;
     912
     913        uint8 *decomp_tile = (uint8 *)malloc(16 * 16); //Tiles are always 16 * 16
     914        uint8 *halfres_buffer = (uint8*) malloc(totTiles * 16 * 16); //This buffer will contain the half vertical res image
     915        memset(halfres_buffer, 0, totTiles * 16 * 16);
     916
     917        bool isCompressed = (READ_LE_UINT32(psxBackground) == MKID_BE('COMP'));
     918
     919        totTiles -= xresInTiles;
     920        psxBackground += 4; //We skip the id tag
     921
     922        uint32 currentTile;
     923        for (currentTile = 0; currentTile < totTiles; currentTile++) {
     924                uint32 tileOffset = READ_LE_UINT32(psxBackground + 4 * currentTile);
     925               
     926                if(isCompressed)
     927                        decompressHIF(psxBackground + tileOffset - 4, decomp_tile); //Decompress the tile into decomp_tile
     928                else
     929                        memcpy(decomp_tile, psxBackground + tileOffset - 4, 16 * 16);
     930
     931                if (currentTile > 0 && !(currentTile % xresInTiles)) { //Finished a line of tiles, going down
     932                        tileYpos++;
     933                        tileXpos = 0;
     934                }
     935       
     936                for (byte tileLine = 0; tileLine < 16; tileLine++)
     937                        memcpy(halfres_buffer + (tileLine * realWidth) + (tileXpos * 16) + (tileYpos * realWidth * 16), decomp_tile + (tileLine * 16), 16); //Copy data to destination buffer
     938
     939                tileXpos++;
     940        }
     941
     942        uint8 *fullres_buffer = (uint8 *)malloc(bakXres * (yresInTiles + 1) * 32);
     943        memset(fullres_buffer, 0x00, bakXres * (yresInTiles + 1) * 32);
     944
     945        for (uint32 currentLine = 0; currentLine < ((yresInTiles - 1) * 16); currentLine++) {
     946                for (uint32 cntx = 0; cntx < realWidth; cntx++) {
     947                        fullres_buffer[currentLine * 2 * bakXres + cntx * 2] = halfres_buffer[currentLine * realWidth + cntx];
     948                        fullres_buffer[currentLine * 2 * bakXres + cntx * 2 + 1] = halfres_buffer[currentLine * realWidth + cntx];
     949                }
     950                for (uint32 cntx = 0; cntx < realWidth; cntx++) {
     951                        fullres_buffer[(currentLine * 2 + 1) * bakXres + cntx * 2] = halfres_buffer[currentLine * realWidth + cntx];
     952                        fullres_buffer[(currentLine * 2 + 1) * bakXres + cntx * 2 + 1] = halfres_buffer[currentLine * realWidth + cntx];
     953                }
     954        }
     955        free(halfres_buffer);
     956
     957        //Calculate number of remaining tiles
     958        uint32 remainingTiles = (dataBegin - (currentTile * 4 + 4)) / 4;
     959
     960        // Last line of tiles is FULL WIDTH!
     961        uint32 tileHeight = (remainingTiles == xresInTiles * 2) ? 16 : 8;
     962
     963        halfres_buffer = (uint8*) malloc(bakXres * 16 * 2);
     964        memset(halfres_buffer, 0, bakXres * 16 * 2);
     965
     966        tileXpos = 0;
     967        for (; currentTile < totTiles + remainingTiles; currentTile++) {
     968                uint32 tileOffset = READ_LE_UINT32(psxBackground + 4 * currentTile);
     969
     970                if(isCompressed)
     971                        decompressHIF(psxBackground + tileOffset - 4, decomp_tile); //Decompress the tile into decomp_tile
     972                else
     973                        memcpy(decomp_tile, psxBackground + tileOffset - 4, 256);
     974
     975                for (byte tileLine = 0; tileLine < tileHeight; tileLine++)
     976                        memcpy(halfres_buffer + tileLine * bakXres * 2 + tileXpos * 16, decomp_tile + tileLine * 16, 16);
     977
     978                tileXpos++;
     979        }
     980
     981        free(decomp_tile);
     982
     983        for (uint32 currentLine = 0; currentLine < tileHeight; currentLine++) {
     984                memcpy(fullres_buffer + (currentLine + (yresInTiles - 1) * 16) * bakXres * 2, halfres_buffer + currentLine * bakXres * 2, bakXres * 2);
     985                memcpy(fullres_buffer + (currentLine + (yresInTiles - 1) * 16) * bakXres * 2 + bakXres, halfres_buffer + currentLine * bakXres * 2, bakXres * 2);
     986        }
     987
     988        free(halfres_buffer);
     989       
     990        return fullres_buffer;
     991}
     992
     993uint8* Screen::psxParallaxToIndexed(uint8* psxParallax) {
     994        uint16 xresInTiles = READ_LE_UINT16(psxParallax + 10);
     995        uint16 yresInTiles = READ_LE_UINT16(psxParallax + 12);
     996        uint16 totTiles = READ_LE_UINT16(psxParallax + 14);
     997        uint32 plxXres = xresInTiles * 16;
     998        uint32 plxYres = yresInTiles * 16;
     999
     1000        uint8 *plxPos = psxParallax + 16;
     1001        uint8 *plxOff = psxParallax + 16 + totTiles * 2;
     1002        uint8 *plxData = psxParallax + 16 + totTiles * 2 + totTiles * 4;
     1003
     1004        uint8 *decomp_tile = (uint8 *)malloc(16 * 16); // Tiles are always 16 * 16
     1005        uint8 *halfres_buffer = (uint8 *)malloc(4 + yresInTiles * xresInTiles * 16 * 16); //This buffer will contain the half vertical res image
     1006        memset(halfres_buffer, 0, 4 + yresInTiles * xresInTiles * 16 * 16); //Clean the buffer
     1007
     1008        for (uint16 currentTile = 0; currentTile < totTiles - 1; currentTile++) {
     1009                uint32 tileOffset = READ_LE_UINT32(plxOff + 4 * currentTile);
     1010                uint8 tileXpos = *(plxPos + 2 * currentTile); //Fetch tile position in grid
     1011                uint8 tileYpos = *(plxPos + 2 * currentTile + 1);
     1012                decompressHIF(plxData + tileOffset, decomp_tile); //Decompress the tile into decomp_tile
     1013
     1014                for (byte tileLine = 0; tileLine < 16; tileLine++)
     1015                        memcpy(halfres_buffer + tileLine * plxXres + tileXpos * 16 + tileYpos * plxXres * 16, decomp_tile + tileLine * 16, 16); //Copy data to destination buffer
     1016        }
     1017       
     1018        free(decomp_tile);
     1019
     1020        uint8 *dest_buffer = (uint8*) malloc (plxXres * plxYres * 2 + 4);
     1021        WRITE_LE_UINT16(dest_buffer, plxXres);      //Insert resolution information
     1022        WRITE_LE_UINT16(dest_buffer + 2, plxYres*2);
     1023
     1024        //Let's linedouble the image (to keep correct aspect ratio)
     1025        for (uint32 currentLine = 0; currentLine < plxYres; currentLine++) {
     1026                memcpy(dest_buffer + 4 + currentLine * plxXres * 2, halfres_buffer + currentLine * plxXres, plxXres); // destination_line is 2*original_line
     1027                memcpy(dest_buffer + 4 + currentLine * plxXres * 2 + plxXres, halfres_buffer + currentLine * plxXres, plxXres); // destination_line+1
     1028        }
     1029       
     1030        free(halfres_buffer);
     1031
     1032        return dest_buffer;
     1033}
     1034
    6781035void Screen::decompressTony(uint8 *src, uint32 compSize, uint8 *dest) {
    6791036        uint8 *endOfData = src + compSize;
    6801037        while (src < endOfData) {
     
    7211078        }
    7221079}
    7231080
     1081void Screen::decompressHIF(uint8 *src, uint8 *dest) {
     1082        for (;;) { //Main loop
     1083                byte control_byte = *src++;
     1084                uint32 byte_count = 0;
     1085                while (byte_count < 8) {
     1086                        if (control_byte & 0x80) {
     1087                                uint16 info_word = READ_BE_UINT16(src); //Read the info word
     1088                                src += 2;
     1089                                if (info_word == 0xFFFF) return; //Got 0xFFFF code, finished.
     1090
     1091                                int32 repeat_count = (info_word >> 12) + 2; //How many time data needs to be refetched
     1092                                while(repeat_count >= 0) {
     1093                                        uint8 *old_data_src = dest - ((info_word & 0xFFF) + 1);
     1094                                        *dest++ = *old_data_src;
     1095                                        repeat_count--;
     1096                                }
     1097                        } else
     1098                                *dest++ = *src++;
     1099                        byte_count++;
     1100                        control_byte <<= 1; //Shifting left the control code one bit
     1101                }
     1102        }
     1103}
     1104
    7241105void Screen::fadePalette(void) {
    7251106        if (_fadingStep == 16)
    7261107                memcpy(_currentPalette, _targetPalette, 256 * 4);
     
    7731154                *pSprWidth = 0;
    7741155        else
    7751156                *pSprWidth = (uint16)sprW;
     1157       
    7761158        *pSprX = (uint16)sprX;
    7771159        *pSprY = (uint16)sprY;
    7781160
     
    7801162                // sprite will be drawn, so mark it in the grid buffer
    7811163                uint16 gridH = (*pSprHeight + (sprY & (SCRNGRID_Y - 1)) + (SCRNGRID_Y - 1)) / SCRNGRID_Y;
    7821164                uint16 gridW = (*pSprWidth +  (sprX & (SCRNGRID_X - 1)) + (SCRNGRID_X - 1)) / SCRNGRID_X;
     1165               
     1166                if(SwordEngine::isPsx()) {
     1167                        gridH *= 2; // This will correct the PSX sprite being cut at half height
     1168                        gridW *= 2; // and masking problems when sprites are stretched in width
     1169                       
     1170                        uint16 bottomSprPos = (*pSprY + (*pSprHeight) * 2); //Position of bottom line of sprite
     1171                        if ( bottomSprPos > _scrnSizeY ) { //Check that resized psx sprite isn't drawn outside of screen boundaries
     1172                                uint16 outScreen = bottomSprPos - _scrnSizeY;
     1173                                *pSprHeight -= (outScreen % 2) ? (outScreen + 1) / 2 : outScreen / 2;
     1174                        }
     1175
     1176                }               
     1177
    7831178                uint16 gridX = sprX / SCRNGRID_X;
    7841179                uint16 gridY = sprY / SCRNGRID_Y;
    7851180                uint8 *gridBuf = _screenGrid + gridX + gridY * _gridSizeX;
     
    8061201        uint8 frame[40 * 40];
    8071202        int i, j;
    8081203
    809         memset(frame, 199, sizeof(frame));      // Dark gray background
     1204        if(SwordEngine::isPsx())
     1205                memset(frame, 0, sizeof(frame)); // PSX top menu is black       
     1206        else
     1207                memset(frame, 199, sizeof(frame)); // Dark gray background
    8101208
    8111209        if (resId != 0xffffffff) {
    8121210                FrameHeader *frameHead = _resMan->fetchFrame(_resMan->openFetchRes(resId), frameNo);
    8131211                uint8 *frameData = ((uint8*)frameHead) + sizeof(FrameHeader);
    8141212
    815                 for (i = 0; i < _resMan->getUint16(frameHead->height); i++) {
    816                         for (j = 0; j < _resMan->getUint16(frameHead->height); j++) {
    817                                 frame[(i + 4) * 40 + j + 2] = frameData[i * _resMan->getUint16(frameHead->width) + j];
     1213                if (SwordEngine::isPsx()) { //We need to decompress PSX frames
     1214                        uint8 *frameBufferPSX = (uint8 *)malloc(_resMan->getUint16(frameHead->width) *  _resMan->getUint16(frameHead->height)/2);
     1215                        decompressHIF(frameData, frameBufferPSX);
     1216
     1217                        for (i = 0; i < _resMan->getUint16(frameHead->height) / 2; i++) {
     1218                                for (j = 0; j < _resMan->getUint16(frameHead->width); j++) {
     1219                                        uint8 data = frameBufferPSX[i * _resMan->getUint16(frameHead->width) + j];
     1220                                        frame[(i * 2 + 4) * 40 + j + 2] = data;
     1221                                        frame[(i * 2 + 1 + 4) * 40 + j + 2] = data; //Linedoubling the sprite
     1222                                }
    8181223                        }
     1224                       
     1225                        free(frameBufferPSX);
     1226                } else {
     1227                        for (i = 0; i < _resMan->getUint16(frameHead->height); i++)
     1228                                for (j = 0; j < _resMan->getUint16(frameHead->height); j++)
     1229                                        frame[(i + 4) * 40 + j + 2] = frameData[i * _resMan->getUint16(frameHead->width) + j];
    8191230                }
    8201231
    8211232                _resMan->resClose(resId);
  • scummvm-bspsx/engines/sword1/control.cpp

     
    4545#include "sword1/sword1.h"
    4646#include "sword1/sworddefs.h"
    4747#include "sword1/swordres.h"
     48#include "sword1/screen.h"
    4849
    4950namespace Sword1 {
    5051
     
    120121        _resMan->resOpen(_resId);
    121122        FrameHeader *tmp = _resMan->fetchFrame(_resMan->fetchRes(_resId), 0);
    122123        _width = _resMan->getUint16(tmp->width);
     124        _width = (_width > SCREEN_WIDTH) ? SCREEN_WIDTH : _width;
    123125        _height = _resMan->getUint16(tmp->height);
    124126        if ((x == 0) && (y == 0)) { // center the frame (used for panels);
    125                 _x = (640 - _width) / 2;
    126                 _y = (480 - _height) / 2;
     127                _x = (((640 - _width) / 2) < 0)? 0 : ((640 - _width) / 2) ;
     128                _y = (((480 - _height) / 2) < 0)? 0 : ((480 - _height) / 2);
    127129        }
    128130        _dstBuf = screenBuf + _y * SCREEN_WIDTH + _x;
    129131        _system = system;
     
    141143        FrameHeader *fHead = _resMan->fetchFrame(_resMan->fetchRes(_resId), _frameIdx);
    142144        uint8 *src = (uint8*)fHead + sizeof(FrameHeader);
    143145        uint8 *dst = _dstBuf;
    144         for (uint16 cnt = 0; cnt < _resMan->readUint16(&fHead->height); cnt++) {
    145                 for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width); cntx++)
    146                         if (src[cntx])
    147                                 dst[cntx] = src[cntx];
    148                 dst += SCREEN_WIDTH;
    149                 src += _resMan->readUint16(&fHead->width);
    150         }
     146
     147        if (SwordEngine::isPsx() && _resId) {
     148                uint8 *HIFbuf = (uint8*)malloc(_resMan->readUint16(&fHead->height) * _resMan->readUint16(&fHead->width));
     149                memset(HIFbuf, 0, _resMan->readUint16(&fHead->height) * _resMan->readUint16(&fHead->width));
     150                Screen::decompressHIF(src, HIFbuf);
     151                src = HIFbuf;
     152       
     153                if (_resMan->readUint16(&fHead->width) < 300)
     154                        for (uint16 cnt = 0; cnt < _resMan->readUint16(&fHead->height); cnt++) {
     155                                for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width); cntx++)
     156                                        if (src[cntx])
     157                                                dst[cntx] = src[cntx];
     158                               
     159                                dst += SCREEN_WIDTH;
     160                                for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width); cntx++)
     161                                        if (src[cntx])
     162                                                dst[cntx] = src[cntx];
     163
     164                                dst += SCREEN_WIDTH;
     165                                src += _resMan->readUint16(&fHead->width);
     166                        }
     167                else if (_resId == SR_DEATHPANEL) { //Hardcoded goodness for death panel psx version
     168                        for (uint16 cnt = 0; cnt < _resMan->readUint16(&fHead->height)/2; cnt++) {
     169                                //Stretched panel is bigger than 640px, check we don't draw outside screen
     170                                for (uint16 cntx = 0; (cntx < (_resMan->readUint16(&fHead->width))/3) && (cntx < (SCREEN_WIDTH-3) ); cntx++)
     171                                        if (src[cntx]) {
     172                                                dst[cntx * 3] = src[cntx];
     173                                                dst[cntx * 3 + 1] = src[cntx];
     174                                                dst[cntx * 3 + 2] = src[cntx];
     175                                        }
     176                                dst+= SCREEN_WIDTH;
     177
     178                                for (uint16 cntx = 0; cntx < (_resMan->readUint16(&fHead->width))/3; cntx++)
     179                                        if (src[cntx]) {
     180                                                dst[cntx * 3] = src[cntx];
     181                                                dst[cntx * 3 + 1] = src[cntx];
     182                                                dst[cntx * 3 + 2] = src[cntx];
     183                                        }
     184                                dst += SCREEN_WIDTH;
     185                                src += _resMan->readUint16(&fHead->width)/3;
     186                        }
     187                } else { //NASTY HACK, save slots needs to be multiplied my 4 in height... need a better way to identify these images
     188                        for (uint16 cnt = 0; cnt < _resMan->readUint16(&fHead->height); cnt++) {
     189                                for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width) / 2; cntx++)
     190                                        if (src[cntx]) {
     191                                                dst[cntx * 2] = src[cntx];
     192                                                dst[cntx * 2 + 1] = src[cntx];
     193                                        }
     194                               
     195                                dst += SCREEN_WIDTH;
     196                                for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width) / 2; cntx++)
     197                                        if (src[cntx]) {
     198                                                dst[cntx * 2] = src[cntx];
     199                                                dst[cntx * 2 + 1] = src[cntx];
     200                                        }
     201                       
     202                                dst += SCREEN_WIDTH;
     203                                src += _resMan->readUint16(&fHead->width)/2;
     204                        }
     205                }
     206
     207                free(HIFbuf);
     208        } else
     209                for (uint16 cnt = 0; cnt < _resMan->readUint16(&fHead->height); cnt++) {
     210                        for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width); cntx++)
     211                                if (src[cntx])
     212                                        dst[cntx] = src[cntx];
     213
     214                        dst += SCREEN_WIDTH;
     215                        src += _resMan->readUint16(&fHead->width);
     216                }
     217       
    151218        _system->copyRectToScreen(_dstBuf, SCREEN_WIDTH, _x, _y, _width, _height);
    152219}
    153220
     
    9401007
    9411008                FrameHeader *chSpr = _resMan->fetchFrame(font, *str - 32);
    9421009                uint8 *sprData = (uint8*)chSpr + sizeof(FrameHeader);
     1010                uint8 *HIFbuf = NULL;
     1011
     1012                if (SwordEngine::isPsx()) { //Text fonts are compressed in psx version
     1013                        HIFbuf = (uint8 *)malloc(_resMan->getUint16(chSpr->height) * _resMan->getUint16(chSpr->width));
     1014                        memset(HIFbuf, 0, _resMan->getUint16(chSpr->height) * _resMan->getUint16(chSpr->width));
     1015                        Screen::decompressHIF(sprData, HIFbuf);
     1016                        sprData = HIFbuf;
     1017                }
     1018               
    9431019                for (uint16 cnty = 0; cnty < _resMan->getUint16(chSpr->height); cnty++) {
    9441020                        for (uint16 cntx = 0; cntx < _resMan->getUint16(chSpr->width); cntx++) {
    9451021                                if (sprData[cntx])
    9461022                                        dst[cntx] = sprData[cntx];
    9471023                        }
     1024                       
     1025                        if(SwordEngine::isPsx()) { //On PSX version we need to double horizontal lines
     1026                                dst += SCREEN_WIDTH;
     1027                                for (uint16 cntx = 0; cntx < _resMan->getUint16(chSpr->width); cntx++)
     1028                                        if (sprData[cntx])
     1029                                                dst[cntx] = sprData[cntx];
     1030                        }
     1031
    9481032                        sprData += _resMan->getUint16(chSpr->width);
    9491033                        dst += SCREEN_WIDTH;
    9501034                }
    9511035                destX += _resMan->getUint16(chSpr->width) - 3;
    9521036                str++;
     1037               
     1038                free(HIFbuf);
    9531039        }
     1040       
    9541041        _system->copyRectToScreen(_screenBuf + y * SCREEN_WIDTH + x, SCREEN_WIDTH, x, y, (destX - x) + 3, 28);
    9551042}
    9561043
     
    9631050                FrameHeader *frHead = _resMan->fetchFrame(_resMan->openFetchRes(SR_VLIGHT), (vol + 15) >> 4);
    9641051                uint8 *destMem = _screenBuf + destY * SCREEN_WIDTH + destX;
    9651052                uint8 *srcMem = (uint8*)frHead + sizeof(FrameHeader);
    966                 for (uint16 cnty = 0; cnty < _resMan->getUint16(frHead->height); cnty++) {
     1053                uint16 barHeight = _resMan->getUint16(frHead->height);
     1054                uint8 *psxVolBuf = NULL;
     1055
     1056                if (SwordEngine::isPsx()) {
     1057                        psxVolBuf = (uint8 *)malloc(_resMan->getUint16(frHead->height) / 2 * _resMan->getUint16(frHead->width));
     1058                        memset(psxVolBuf, 0, _resMan->getUint16(frHead->height) / 2 * _resMan->getUint16(frHead->width));
     1059                        Screen::decompressHIF(srcMem, psxVolBuf);
     1060                        srcMem = psxVolBuf;
     1061                        barHeight /= 2;
     1062                }
     1063
     1064                for (uint16 cnty = 0; cnty < barHeight; cnty++) {
    9671065                        memcpy(destMem, srcMem, _resMan->getUint16(frHead->width));
     1066                       
     1067                        if(SwordEngine::isPsx()) { //linedoubling
     1068                                destMem += SCREEN_WIDTH;
     1069                                memcpy(destMem, srcMem, _resMan->getUint16(frHead->width));
     1070                        }
     1071
    9681072                        srcMem += _resMan->getUint16(frHead->width);
    9691073                        destMem += SCREEN_WIDTH;
    9701074                }
     1075               
    9711076                _system->copyRectToScreen(_screenBuf + destY * SCREEN_WIDTH + destX, SCREEN_WIDTH, destX, destY, _resMan->getUint16(frHead->width), _resMan->getUint16(frHead->height));
    9721077                _resMan->resClose(SR_VLIGHT);
    9731078                destX += 32;
     1079
     1080                free(psxVolBuf);
    9741081        }
    9751082}
    9761083
  • scummvm-bspsx/engines/sword1/vag.h

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25 
     26#ifndef SWORD1_VAG_H
     27#define SWORD1_VAG_H
     28
     29#include "sound/audiostream.h"
     30#include "common/stream.h"
     31 
     32namespace Sword1 {
     33
     34class VagStream : public Audio::AudioStream {
     35public:
     36        VagStream(Common::SeekableReadStream *stream, bool loop = false);
     37        ~VagStream();
     38       
     39        bool isStereo() const { return false; }
     40        bool endOfData() const { return _stream->pos() == _stream->size(); }
     41        int getRate() const { return 11025; }
     42        int readBuffer(int16 *buffer, const int numSamples);
     43
     44        void rewind(); 
     45
     46private:
     47        Common::SeekableReadStream *_stream;
     48
     49        bool _loop;
     50        byte _predictor;
     51        double _samples[28];
     52        byte _samplesRemaining;
     53        double _s1, _s2;
     54};
     55
     56} // End of namespace Sword1
     57
     58#endif
  • scummvm-bspsx/engines/sword1/sword1.h

     
    6666        uint8   showText;
    6767        uint8   language;
    6868        bool    isDemo;
    69         bool    isMac;
     69        Common::Platform platform;
    7070};
    7171
    7272class SwordEngine : public Engine {
     
    7979        uint32 _features;
    8080
    8181        bool mouseIsActive();
     82       
     83        static bool isMac() { return _systemVars.platform == Common::kPlatformMacintosh; }
     84        static bool isPsx() { return _systemVars.platform == Common::kPlatformPSX; }
    8285
    8386protected:
    8487        // Engine APIs
     
    119122        static const uint8  _cdList[TOTAL_SECTIONS];
    120123        static const CdFile     _pcCdFileList[];
    121124        static const CdFile     _macCdFileList[];
     125        static const CdFile _psxCdFileList[];
    122126};
    123127
    124128} // End of namespace Sword1
  • scummvm-bspsx/engines/sword1/text.cpp

     
    3232#include "sword1/objectman.h"
    3333#include "sword1/swordres.h"
    3434#include "sword1/sworddefs.h"
     35#include "sword1/screen.h"
     36#include "sword1/sword1.h"
    3537
    3638namespace Sword1 {
    3739
     
    7880void Text::makeTextSprite(uint8 slot, uint8 *text, uint16 maxWidth, uint8 pen) {
    7981        LineInfo lines[MAX_LINES];
    8082        uint16 numLines = analyzeSentence(text, maxWidth, lines);
    81 
     83       
    8284        uint16 sprWidth = 0;
    8385        uint16 lineCnt;
    8486        for (lineCnt = 0; lineCnt < numLines; lineCnt++)
    8587                if (lines[lineCnt].width > sprWidth)
    8688                        sprWidth = lines[lineCnt].width;
     89
    8790        uint16 sprHeight = _charHeight * numLines;
    8891        uint32 sprSize = sprWidth * sprHeight;
    8992        assert(!_textBlocks[slot]); // if this triggers, the speechDriver failed to call Text::releaseText.
     
    100103        memset(linePtr, NO_COL, sprSize);
    101104        for (lineCnt = 0; lineCnt < numLines; lineCnt++) {
    102105                uint8 *sprPtr = linePtr + (sprWidth - lines[lineCnt].width) / 2; // center the text
    103                 for (uint16 pos = 0; pos < lines[lineCnt].length; pos++)
     106                for (uint16 pos = 0; pos < lines[lineCnt].length; pos++) 
    104107                        sprPtr += copyChar(*text++, sprPtr, sprWidth, pen) - OVERLAP;
    105108                text++; // skip space at the end of the line
    106                 linePtr += _charHeight * sprWidth;
     109                if(SwordEngine::isPsx()) //Chars are half height in psx version
     110                        linePtr += (_charHeight / 2) * sprWidth;
     111                else
     112                        linePtr += _charHeight * sprWidth;
    107113        }
    108114}
    109115
     
    157163        FrameHeader *chFrame = _resMan->fetchFrame(_font, ch - SPACE);
    158164        uint8 *chData = ((uint8*)chFrame) + sizeof(FrameHeader);
    159165        uint8 *dest = sprPtr;
    160         for (uint16 cnty = 0; cnty < _resMan->getUint16(chFrame->height); cnty++) {
     166        uint8 *decBuf = NULL;
     167        uint8 *decChr;
     168        uint16 frameHeight = 0;
     169       
     170        if(SwordEngine::isPsx()) {
     171                frameHeight =  _resMan->getUint16(chFrame->height)/2;
     172                if(_fontId == CZECH_GAME_FONT) { //Czech game fonts are compressed
     173                        decBuf = (uint8*) malloc((_resMan->getUint16(chFrame->width))*(_resMan->getUint16(chFrame->height)/2));
     174                        Screen::decompressHIF(chData, decBuf);
     175                        decChr = decBuf;
     176                } else //Normal game fonts are not compressed
     177                        decChr = chData;
     178        } else {
     179                frameHeight =  _resMan->getUint16(chFrame->height);
     180                decChr = chData;
     181        }
     182       
     183        for (uint16 cnty = 0; cnty < frameHeight; cnty++) {
    161184                for (uint16 cntx = 0; cntx < _resMan->getUint16(chFrame->width); cntx++) {
    162                         if (*chData == LETTER_COL)
     185                        if (*decChr == LETTER_COL)
    163186                                dest[cntx] = pen;
    164                         else if ((*chData == BORDER_COL) && (!dest[cntx])) // don't do a border if there's already a color underneath (chars can overlap)
     187                        else if (((*decChr == BORDER_COL) || (*decChr == BORDER_COL_PSX)) && (!dest[cntx])) // don't do a border if there's already a color underneath (chars can overlap)
    165188                                dest[cntx] = BORDER_COL;
    166                         chData++;
     189                        decChr++;
    167190                }
    168191                dest += sprWidth;
    169192        }
     193        free(decBuf);
    170194        return _resMan->getUint16(chFrame->width);
    171195}
    172196
  • scummvm-bspsx/engines/sword1/music.h

     
    4747        MusicHandle() : _fading(0), _audioSource(NULL) {}
    4848        virtual int readBuffer(int16 *buffer, const int numSamples);
    4949        bool play(const char *filename, bool loop);
     50        bool playPSX(uint16 id, bool loop);
    5051        void stop();
    5152        void fadeUp();
    5253        void fadeDown();
  • scummvm-bspsx/engines/sword1/sound.cpp

     
    3434#include "sword1/resman.h"
    3535#include "sword1/logic.h"
    3636#include "sword1/sword1.h"
     37#include "sword1/vag.h"
    3738
    3839#include "sound/flac.h"
    3940#include "sound/mp3.h"
     
    160161                if (_fxList[elem->id].roomVolList[cnt].roomNo) {
    161162                        if ((_fxList[elem->id].roomVolList[cnt].roomNo == (int)Logic::_scriptVars[SCREEN]) ||
    162163                                (_fxList[elem->id].roomVolList[cnt].roomNo == -1)) {
    163 
     164                                               
    164165                                        uint8 volL = (_fxList[elem->id].roomVolList[cnt].leftVol * 10 * _sfxVolL) / 255;
    165166                                        uint8 volR = (_fxList[elem->id].roomVolList[cnt].rightVol * 10 * _sfxVolR) / 255;
    166167                                        int8 pan = (volR - volL) / 2;
    167168                                        uint8 volume = (volR + volL) / 2;
    168                                         uint32 size = READ_LE_UINT32(sampleData + 0x28);
    169                                         uint8 flags;
    170                                         if (READ_LE_UINT16(sampleData + 0x22) == 16)
    171                                                 flags = Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN;
    172                                         else
    173                                                 flags = Audio::Mixer::FLAG_UNSIGNED;
    174                                         if (READ_LE_UINT16(sampleData + 0x16) == 2)
    175                                                 flags |= Audio::Mixer::FLAG_STEREO;
    176                                         if (_fxList[elem->id].type == FX_LOOP)
    177                                                 flags |= Audio::Mixer::FLAG_LOOP;
    178                                         _mixer->playRaw(Audio::Mixer::kSFXSoundType, &elem->handle, sampleData + 0x2C, size, 11025, flags, elem->id, volume, pan);
     169                                               
     170                                        if (SwordEngine::isPsx()) { ;
     171                                                uint32 size = READ_LE_UINT32(sampleData);
     172                                                Audio::AudioStream *audStream = new VagStream(new Common::MemoryReadStream(sampleData + 4, size-4), _fxList[elem->id].type == FX_LOOP);
     173                                                _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &elem->handle, audStream, elem->id, volume, pan, false, false, false);
     174                                        } else {
     175                                                uint32 size = READ_LE_UINT32(sampleData + 0x28);
     176                                                uint8 flags;
     177                                                if (READ_LE_UINT16(sampleData + 0x22) == 16)
     178                                                        flags = Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN;
     179                                                else
     180                                                        flags = Audio::Mixer::FLAG_UNSIGNED;
     181                                                if (READ_LE_UINT16(sampleData + 0x16) == 2)
     182                                                        flags |= Audio::Mixer::FLAG_STEREO;
     183                                                if (_fxList[elem->id].type == FX_LOOP)
     184                                                        flags |= Audio::Mixer::FLAG_LOOP;
     185                                                _mixer->playRaw(Audio::Mixer::kSFXSoundType, &elem->handle, sampleData + 0x2C, size, 11025, flags, elem->id, volume, pan);
     186                                        }
    179187                        }
    180188                } else
    181189                        break;
     
    187195                warning("Sound::startSpeech: COW file isn't open");
    188196                return false;
    189197        }
     198       
     199        uint32 locIndex = 0xFFFFFFFF;
     200        uint32 sampleSize = 0;
     201        uint32 index = 0;
    190202
    191         uint32 locIndex = _cowHeader[roomNo] >> 2;
    192         uint32 sampleSize = _cowHeader[locIndex + (localNo * 2)];
    193         uint32 index = _cowHeader[locIndex + (localNo * 2) - 1];
     203        if (_cowMode == CowPSX) {
     204                Common::File file;
     205                uint16 i;
     206               
     207                if (!file.open("speech.lis")) {
     208                        warning ("Could not open speech.lis");
     209                        return false;
     210                }
     211
     212                for (i = 0; !file.eos() && !file.err(); i++)
     213                        if (file.readUint16LE() == roomNo) {
     214                                locIndex = i;
     215                                break;
     216                        }
     217                file.close();
     218               
     219                if (locIndex == 0xFFFFFFFF) {
     220                        warning ("Could not find room %d in speech.lis", roomNo);
     221                        return false;
     222                }
     223               
     224                if (!file.open("speech.inf")) {
     225                        warning ("Could not open speech.inf");
     226                        return false;
     227                }
     228       
     229                file.seek(locIndex * 4 + 2); // 4 bytes per room, skip first 2 bytes
     230               
     231                uint16 numLines = file.readUint16LE();
     232                uint16 roomOffset = file.readUint16LE();
     233
     234                file.seek(0x112 + roomOffset * 2); // The offset is in terms of uint16's, so multiply by 2. Skip the 0x112 byte header too.
     235               
     236                locIndex = 0xFFFFFFFF;
     237               
     238                for (i = 0; i < numLines; i++)
     239                        if (file.readUint16LE() == localNo) {
     240                                locIndex = i;
     241                                break;
     242                        }
     243                               
     244                if (locIndex == 0xFFFFFFFF) {
     245                        warning ("Could not find local number %d in room %d in speech.inf", roomNo, localNo);
     246                        return false;
     247                }
     248               
     249                file.close();
     250
     251                index = _cowHeader[(roomOffset + locIndex) * 2];
     252                sampleSize = _cowHeader[(roomOffset + locIndex) * 2 + 1];
     253        } else {
     254                locIndex = _cowHeader[roomNo] >> 2;
     255                sampleSize = _cowHeader[locIndex + (localNo * 2)];
     256                index = _cowHeader[locIndex + (localNo * 2) - 1];
     257        }
     258       
    194259        debug(6, "startSpeech(%d, %d): locIndex %d, sampleSize %d, index %d", roomNo, localNo, locIndex, sampleSize, index);
     260       
    195261        if (sampleSize) {
    196262                uint8 speechVol = (_speechVolR + _speechVolL) / 2;
    197263                int8 speechPan = (_speechVolR - _speechVolL) / 2;
     
    200266                        int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
    201267                        if (data)
    202268                                _mixer->playRaw(Audio::Mixer::kSpeechSoundType, &_speechHandle, data, size, 11025, SPEECH_FLAGS, SOUND_SPEECH_ID, speechVol, speechPan);
     269                } else if (_cowMode == CowPSX && sampleSize != 0xffffffff) {
     270                        _cowFile.seek(index * 2048);
     271                        _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, new VagStream(_cowFile.readStream(sampleSize)), SOUND_SPEECH_ID, speechVol, speechPan);
     272                        // with compressed audio, we can't calculate the wave volume.
     273                        // so default to talking.
     274                        for (int cnt = 0; cnt < 480; cnt++)
     275                                _waveVolume[cnt] = true;
     276                        _waveVolPos = 0;
    203277                }
    204278#ifdef USE_FLAC
    205279                else if (_cowMode == CowFlac) {
     
    419493                debug(1, "Using uncompressed Speech Cluster");
    420494                _cowMode = CowWave;
    421495        }
     496       
     497        if (SwordEngine::isPsx()) {
     498                // There's only one file on the PSX, so set it to the current disc.
     499                _currentCowFile = SwordEngine::_systemVars.currentCD;
     500                if (!_cowFile.isOpen()) {
     501                        if (!_cowFile.open("speech.dat"))
     502                                error ("Could not open speech.dat");
     503                        _cowMode = CowPSX;
     504                }
     505        }
     506       
    422507        if (!_cowFile.isOpen())
    423508                _cowFile.open("speech.clu");
     509               
    424510        if (!_cowFile.isOpen()) {
    425511                _cowFile.open("cows.mad");
    426512                if (_cowFile.isOpen())
    427513                        _cowMode = CowDemo;
    428514        }
     515       
    429516        if (_cowFile.isOpen()) {
    430                 _cowHeaderSize = _cowFile.readUint32LE();
    431                 _cowHeader = (uint32*)malloc(_cowHeaderSize);
    432                 if (_cowHeaderSize & 3)
    433                         error("Unexpected cow header size %d", _cowHeaderSize);
    434                 for (uint32 cnt = 0; cnt < (_cowHeaderSize / 4) - 1; cnt++)
    435                         _cowHeader[cnt] = _cowFile.readUint32LE();
    436                 _currentCowFile = SwordEngine::_systemVars.currentCD;
     517                if (SwordEngine::isPsx()) {
     518                        // Get data from the external table file
     519                        Common::File tableFile;
     520                        if (!tableFile.open("speech.tab"))
     521                                error ("Could not open speech.tab");
     522                        _cowHeaderSize = tableFile.size();
     523                        _cowHeader = (uint32 *)malloc(_cowHeaderSize);
     524                        if (_cowHeaderSize & 3)
     525                                error("Unexpected cow header size %d", _cowHeaderSize);
     526                        for (uint32 cnt = 0; cnt < _cowHeaderSize / 4; cnt++)
     527                                _cowHeader[cnt] = tableFile.readUint32LE();
     528                } else {
     529                        _cowHeaderSize = _cowFile.readUint32LE();
     530                        _cowHeader = (uint32*)malloc(_cowHeaderSize);
     531                        if (_cowHeaderSize & 3)
     532                                error("Unexpected cow header size %d", _cowHeaderSize);
     533                        for (uint32 cnt = 0; cnt < (_cowHeaderSize / 4) - 1; cnt++)
     534                                _cowHeader[cnt] = _cowFile.readUint32LE();
     535                        _currentCowFile = SwordEngine::_systemVars.currentCD;
     536                }
    437537        } else
    438538                warning("Sound::initCowSystem: Can't open SPEECH%d.CLU", SwordEngine::_systemVars.currentCD);
    439539}
  • scummvm-bspsx/engines/sword1/logic.cpp

     
    112112                        fnFullSetFrame(cpt, SAND_25, IMPPLSCDT, IMPPLS, 0, 0, 0, 0); // impression filled with plaster
    113113        }
    114114
     115        // work around, at screen 69 in psx version TOP menu gets stuck at disabled, fix it at next screen (71)
     116        if( (screen == 71) && (SwordEngine::isPsx()))
     117                _scriptVars[TOP_MENU_DISABLED] = 0;
     118
    115119        if (SwordEngine::_systemVars.justRestoredGame) { // if we've just restored a game - we want George to be exactly as saved
    116120                fnAddHuman(NULL, 0, 0, 0, 0, 0, 0, 0);
    117121                if (_scriptVars[GEORGE_WALKING]) { // except that if George was walking when we saveed the game