Ticket #8965: brokensword_psx_patch.diff
File brokensword_psx_patch.diff, 70.2 KB (added by , 16 years ago) |
---|
-
scummvm-bspsx/common/util.h
201 201 kPlatformApple2GS, 202 202 kPlatformPC98, 203 203 kPlatformWii, 204 kPlatformPSX, 204 205 205 206 kPlatformUnknown = -1 206 207 }; -
scummvm-bspsx/common/util.cpp
271 271 {"nes", "nes", "nes", "NES", kPlatformNES}, 272 272 {"segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD}, 273 273 {"windows", "win", "win", "Windows", kPlatformWindows}, 274 {"playstation", "psx", "PSX", "Playstation", kPlatformPSX}, 274 275 275 276 276 277 {0, 0, 0, "Default", kPlatformUnknown} -
scummvm-bspsx/engines/sword1/module.mk
18 18 sound.o \ 19 19 staticres.o \ 20 20 sword1.o \ 21 text.o 21 text.o \ 22 vag.o 22 23 23 24 # This module can be built as a plugin 24 25 ifeq ($(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 28 namespace Sword1 { 29 30 VagStream::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 38 VagStream::~VagStream() { 39 } 40 41 double 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 47 int 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 107 void 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
45 45 {"sword1mac", "Broken Sword 1: The Shadow of the Templars (Mac)"}; 46 46 static const PlainGameDescriptor sword1MacDemoSettings = 47 47 {"sword1macdemo", "Broken Sword 1: The Shadow of the Templars (Mac demo)"}; 48 static const PlainGameDescriptor sword1PSXSettings = 49 {"sword1psx", "Broken Sword 1: The Shadow of the Templars (PlayStation)"}; 48 50 49 51 // check these subdirectories (if present) 50 52 static const char *g_dirNames[] = { "clusters", "speech" }; … … 52 54 #define NUM_COMMON_FILES_TO_CHECK 1 53 55 #define NUM_PC_FILES_TO_CHECK 3 54 56 #define NUM_MAC_FILES_TO_CHECK 4 57 #define NUM_PSX_FILES_TO_CHECK 2 55 58 #define NUM_DEMO_FILES_TO_CHECK 1 56 59 #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_CHECK60 #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 58 61 static const char *g_filesToCheck[NUM_FILES_TO_CHECK] = { // these files have to be found 59 "swordres.rif", // Mac and PCversion60 "general.clu", // PC version only61 "compacts.clu", // PC version only62 "scripts.clu", // PC version only62 "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 63 66 "general.clm", // Mac version only 64 67 "compacts.clm", // Mac version only 65 68 "scripts.clm", // Mac version only 66 69 "paris2.clm", // Mac version (full game only) 67 70 "cows.mad", // this one should only exist in the demo version 68 71 "scripts.clm", // Mac version both demo and full game 72 "speech.dat", // PSX version only 73 "tunes.dat", // PSX version only 69 74 // the engine needs several more files to work, but checking these should be sufficient 70 75 }; 71 76 … … 123 128 return sword1MacFullSettings; 124 129 if (0 == scumm_stricmp(gameid, sword1MacDemoSettings.gameid)) 125 130 return sword1MacDemoSettings; 131 if (0 == scumm_stricmp(gameid, sword1PSXSettings.gameid)) 132 return sword1PSXSettings; 126 133 return GameDescriptor(); 127 134 } 128 135 … … 157 164 bool macFilesFound = true; 158 165 bool demoFilesFound = true; 159 166 bool macDemoFilesFound = true; 167 bool psxFilesFound = true; 160 168 for (i = 0; i < NUM_COMMON_FILES_TO_CHECK; i++) 161 169 if (!filesFound[i]) 162 170 mainFilesFound = false; … … 172 180 for (j = 0; j < NUM_DEMO_FILES_TO_CHECK; i++, j++) 173 181 if (!filesFound[i]) 174 182 macDemoFilesFound = false; 183 for (j = 0; j < NUM_PSX_FILES_TO_CHECK; i++, j++) 184 if (!filesFound[i]) 185 psxFilesFound = false; 175 186 176 187 if (mainFilesFound && pcFilesFound && demoFilesFound) 177 188 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) 179 192 detectedGames.push_back(sword1FullSettings); 180 193 else if (mainFilesFound && macFilesFound) 181 194 detectedGames.push_back(sword1MacFullSettings); -
scummvm-bspsx/engines/sword1/sword1.cpp
84 84 85 85 if ( 0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1mac") || 86 86 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; 88 90 else 89 _systemVars. isMac = false;91 _systemVars.platform = Common::kPlatformWindows; 90 92 91 93 checkCdFiles(); 92 94 93 95 debug(5, "Starting resource manager"); 94 _resMan = new ResMan("swordres.rif", _systemVars. isMac);96 _resMan = new ResMan("swordres.rif", _systemVars.platform == Common::kPlatformMacintosh); 95 97 debug(5, "Starting object manager"); 96 98 _objectMan = new ObjectMan(_resMan); 97 99 _mouse = new Mouse(_system, _resMan, _objectMan); … … 308 310 #endif 309 311 }; 310 312 313 const 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 }; 311 335 312 336 void SwordEngine::showFileErrorMsg(uint8 type, bool *fileExists) { 313 337 char msg[1024]; 314 338 int missCnt = 0, missNum = 0; 315 339 316 if ( _systemVars.isMac) {340 if (SwordEngine::isMac()) { 317 341 for (int i = 0; i < ARRAYSIZE(_macCdFileList); i++) 318 342 if (!fileExists[i]) { 319 343 missCnt++; … … 335 359 pos += sprintf(pos, "\"%s\" (CD %d)\n", _macCdFileList[i].name, (_macCdFileList[i].flags & FLAG_CD2) ? 2 : 1); 336 360 } 337 361 } 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 } 338 383 } else { 339 384 for (int i = 0; i < ARRAYSIZE(_pcCdFileList); i++) 340 385 if (!fileExists[i]) { … … 374 419 _systemVars.playSpeech = true; 375 420 376 421 // 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()) { 378 423 for (int fcnt = 0; fcnt < ARRAYSIZE(_macCdFileList); fcnt++) { 379 424 if (Common::File::exists(_macCdFileList[fcnt].name)) { 380 425 fileExists[fcnt] = true; … … 388 433 fileExists[fcnt] = false; 389 434 } 390 435 } 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 } 391 448 } else { 392 449 for (int fcnt = 0; fcnt < ARRAYSIZE(_pcCdFileList); fcnt++) { 393 450 if (Common::File::exists(_pcCdFileList[fcnt].name)) { … … 422 479 somethingMissing |= missingTypes[i]; 423 480 if (somethingMissing) { // okay, there *are* files missing 424 481 // first, update the fileExists[] array depending on our changed missingTypes 425 if ( _systemVars.isMac) {482 if (SwordEngine::isMac()) { 426 483 for (int fileCnt = 0; fileCnt < ARRAYSIZE(_macCdFileList); fileCnt++) 427 484 if (!fileExists[fileCnt]) { 428 485 fileExists[fileCnt] = true; … … 430 487 if (missingTypes[flagCnt] && ((_macCdFileList[fileCnt].flags & (1 << flagCnt)) != 0)) 431 488 fileExists[fileCnt] = false; // this is one of the files we were looking for 432 489 } 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 } 433 498 } else { 434 499 for (int fileCnt = 0; fileCnt < ARRAYSIZE(_pcCdFileList); fileCnt++) 435 500 if (!fileExists[fileCnt]) { -
scummvm-bspsx/engines/sword1/music.cpp
29 29 #include "common/util.h" 30 30 #include "common/system.h" 31 31 32 #include "sword1/sword1.h" 32 33 #include "sword1/music.h" 34 #include "sword1/vag.h" 35 33 36 #include "sound/aiff.h" 34 37 #include "sound/flac.h" 35 38 #include "sound/mixer.h" … … 252 255 return true; 253 256 } 254 257 258 bool 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 255 287 void MusicHandle::fadeDown() { 256 288 if (streaming()) { 257 289 if (_fading < 0) … … 276 308 return !streaming(); 277 309 } 278 310 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. 281 312 bool MusicHandle::streaming(void) const { 282 313 return (_audioSource) ? (!_audioSource->endOfStream()) : false; 283 314 } … … 411 442 /* The handle will load the music file now. It can take a while, so unlock 412 443 the mutex before, to have the soundthread playing normally. 413 444 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)) { 415 452 _mutex.lock(); 416 453 _converter[newStream] = Audio::makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), false); 417 454 _mutex.unlock(); -
scummvm-bspsx/engines/sword1/screen.h
96 96 void fnFlash(uint8 color); 97 97 void fnBorder(uint8 color); 98 98 99 static void decompressHIF(uint8 *src, uint8 *dest); 100 99 101 #ifdef BACKEND_8BIT 100 102 void plotYUV(byte *lut, int width, int height, byte *const *dat); 101 103 #endif … … 116 118 void processImage(uint32 id); 117 119 void spriteClipAndSet(uint16 *pSprX, uint16 *pSprY, uint16 *sprWidth, uint16 *sprHeight, uint16 *incr); 118 120 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); 119 126 void decompressRLE7(uint8 *src, uint32 compSize, uint8 *dest); 120 127 void decompressRLE0(uint8 *src, uint32 compSize, uint8 *dest); 121 128 void decompressTony(uint8 *src, uint32 compSize, uint8 *dest); … … 160 167 161 168 #endif //BSSCREEN_H 162 169 170 171 -
scummvm-bspsx/engines/sword1/mouse.cpp
37 37 #include "sword1/sworddefs.h" 38 38 #include "sword1/swordres.h" 39 39 #include "sword1/menu.h" 40 #include "sword1/sword1.h" 40 41 41 42 namespace Sword1 { 42 43 … … 201 202 if (ptrId) { 202 203 MousePtr *lugg = NULL; 203 204 MousePtr *ptr = (MousePtr*)_resMan->openFetchRes(ptrId); 204 uint16 resSizeX = _resMan->getLEUint16(ptr->sizeX);205 uint16 resSizeY = _resMan->getLEUint16(ptr->sizeY);206 205 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 207 216 if (luggageId) { 208 217 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; 211 229 } 212 230 _currentPtr = (MousePtr*)malloc(sizeof(MousePtr) + resSizeX * resSizeY * noFrames); 213 231 _currentPtr->hotSpotX = _resMan->getLEUint16(ptr->hotSpotX); … … 218 236 uint8 *ptrData = (uint8*)_currentPtr + sizeof(MousePtr); 219 237 memset(ptrData, 255, resSizeX * resSizeY * noFrames); 220 238 if (luggageId) { 221 uint8 *dstData = ptrData + resSizeX - _resMan->getLEUint16(lugg->sizeX);239 uint8 *dstData = ptrData + resSizeX - luggSizeX; 222 240 for (uint32 frameCnt = 0; frameCnt < noFrames; frameCnt++) { 223 241 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++) 227 245 if (luggSrc[cntx]) 228 246 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 229 255 dstData += resSizeX; 230 luggSrc += _resMan->getLEUint16(lugg->sizeX);256 luggSrc += luggSizeX; 231 257 } 232 258 } 233 259 _resMan->resClose(luggageId); 234 260 } 261 235 262 uint8 *dstData = ptrData; 236 263 uint8 *srcData = (uint8*)ptr + sizeof(MousePtr); 237 264 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++) 240 267 if (srcData[cntx]) 241 268 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; 243 278 dstData += resSizeX; 244 279 } 245 dstData += (resSizeY - _resMan->getLEUint16(ptr->sizeY)) * resSizeX;280 dstData += (resSizeY - ptrSizeY) * resSizeX; 246 281 } 247 282 _resMan->resClose(ptrId); 248 283 } -
scummvm-bspsx/engines/sword1/text.h
34 34 #define MAX_TEXT_OBS 3 35 35 36 36 #define BORDER_COL 200 37 #define BORDER_COL_PSX 199 37 38 #define LETTER_COL 193 38 39 #define NO_COL 0 // sprite background - 0 for transparency 39 40 -
scummvm-bspsx/engines/sword1/sound.h
69 69 CowFlac, 70 70 CowVorbis, 71 71 CowMp3, 72 CowDemo 72 CowDemo, 73 CowPSX 73 74 }; 74 75 75 76 class Sound { -
scummvm-bspsx/engines/sword1/screen.cpp
34 34 #include "sword1/resman.h" 35 35 #include "sword1/objectman.h" 36 36 #include "sword1/menu.h" 37 #include "sword1/swordres.h" 37 38 #include "sword1/sword1.h" 38 39 39 40 #ifdef BACKEND_8BIT … … 137 138 if (start == 0) // force color 0 to black 138 139 palData[0] = palData[1] = palData[2] = 0; 139 140 140 if (SwordEngine:: _systemVars.isMac) { // see bug #1701058141 if (SwordEngine::isMac()) { // see bug #1701058 141 142 if (start != 0 && start + length == 256) // and force color 255 to black as well 142 143 palData[(length-1)*3+0] = palData[(length-1)*3+1] = palData[(length-1)*3+2] = 0; 143 144 } … … 358 359 359 360 void Screen::draw(void) { 360 361 uint8 cnt; 362 363 debug(8, "Screen::draw() -> _currentScreen %u", _currentScreen); 364 361 365 if (_currentScreen == 54) { 362 366 // 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 364 368 renderParallax(_parallax[0]); 365 369 uint8 *src = _layerBlocks[0]; 366 370 uint8 *dest = _screenBuf; 371 uint8 *indxScreen = NULL; 367 372 373 if(SwordEngine::isPsx()) { 374 indxScreen = psxShrinkedBackgroundToIndexed(_layerBlocks[0], _scrnSizeX, _scrnSizeY); 375 src = indxScreen; 376 } 377 368 378 for (uint16 cnty = 0; cnty < _scrnSizeY; cnty++) 369 379 for (uint16 cntx = 0; cntx < _scrnSizeX; cntx++) { 370 380 if (*src) 371 if (! SwordEngine::_systemVars.isMac|| *src != 255) // see bug #1701058381 if (!(SwordEngine::isMac()) || *src != 255) // see bug #1701058 372 382 *dest = *src; 373 383 dest++; 374 384 src++; 375 385 } 376 386 377 } else 387 free(indxScreen); 388 389 } else if (!(SwordEngine::isPsx())) { 378 390 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 } 379 401 380 402 for (cnt = 0; cnt < _backLength; cnt++) 381 403 processImage(_backList[cnt]); … … 393 415 if (_parallax[1]) 394 416 renderParallax(_parallax[1]); 395 417 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 396 430 for (cnt = 0; cnt < _foreLength; cnt++) 397 431 processImage(_foreList[cnt]); 398 432 … … 403 437 Object *compact; 404 438 FrameHeader *frameHead; 405 439 int scale; 406 440 407 441 compact = _objMan->fetchObject(id); 442 408 443 if (compact->o_type == TYPE_TEXT) 409 444 frameHead = _textMan->giveSpriteData((uint8)compact->o_target); 410 445 else … … 414 449 415 450 uint16 spriteX = compact->o_anim_x; 416 451 uint16 spriteY = compact->o_anim_y; 452 417 453 if (compact->o_status & STAT_SHRINK) { 418 454 scale = (compact->o_scale_a * compact->o_ycoord + compact->o_scale_b) / 256; 419 455 spriteX += ((int16)_resMan->readUint16(&frameHead->offsetX) * scale) / 256; … … 425 461 } 426 462 427 463 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? 429 471 decompressRLE7(sprData, _resMan->readUint32(&frameHead->compSize), _rleBuffer); 430 472 sprData = _rleBuffer; 431 473 } else if (frameHead->runTimeComp[3] == '0') { // RLE0 encoded? … … 439 481 440 482 uint16 sprSizeX, sprSizeY; 441 483 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 } 445 498 sprData = _shrinkBuffer; 446 499 } else { 447 500 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)); 449 505 } 506 450 507 if (!(compact->o_status & STAT_OVERRIDE)) { 451 508 //mouse size linked to exact size & coordinates of sprite box - shrink friendly 452 509 if (_resMan->readUint16(&frameHead->offsetX) || _resMan->readUint16(&frameHead->offsetY)) { … … 463 520 compact->o_mouse_y2 = spriteY + sprSizeY; 464 521 } 465 522 } 523 466 524 uint16 sprPitch = sprSizeX; 467 525 uint16 incr; 468 526 spriteClipAndSet(&spriteX, &spriteY, &sprSizeX, &sprSizeY, &incr); 527 469 528 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 472 540 verticalMask(spriteX, spriteY, sprSizeX, sprSizeY); 473 541 } 542 474 543 if (compact->o_type != TYPE_TEXT) 475 544 _resMan->resClose(compact->o_resource); 545 476 546 if (tonyBuf) 477 547 free(tonyBuf); 548 549 if (hifBuf) 550 free(hifBuf); 478 551 } 479 552 480 553 void Screen::verticalMask(uint16 x, uint16 y, uint16 bWidth, uint16 bHeight) { 481 554 if (_roomDefTable[_currentScreen].totalLayers <= 1) 482 555 return; 483 556 557 if (SwordEngine::isPsx()) { // PSX sprites are vertical shrinked, and some width shrinked 558 bHeight *= 2; 559 bWidth *= 2; 560 } 561 484 562 bWidth = (bWidth + (x & (SCRNGRID_X - 1)) + (SCRNGRID_X - 1)) / SCRNGRID_X; 485 563 bHeight = (bHeight + (y & (SCRNGRID_Y - 1)) + (SCRNGRID_Y - 1)) / SCRNGRID_Y; 486 564 … … 504 582 uint16 *grid = _layerGrid[level] + gridX + blkx + gridY * lGridSizeX; 505 583 for (int16 blky = bHeight - 1; blky >= 0; blky--) { 506 584 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; 508 590 blitBlockClear(x + blkx, y + blky, blkData); 509 591 } else 510 592 break; … … 517 599 518 600 void Screen::blitBlockClear(uint16 x, uint16 y, uint8 *data) { 519 601 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++) { 521 604 for (uint8 cntx = 0; cntx < SCRNGRID_X; cntx++) 522 605 if (data[cntx]) 523 606 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 524 615 data += SCRNGRID_X; 525 616 dest += _scrnSizeX; 526 617 } 527 618 } 528 619 529 620 void 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 534 621 uint16 paraScrlX, paraScrlY; 535 622 uint16 scrnScrlX, scrnScrlY; 536 623 uint16 scrnWidth, scrnHeight; 624 uint16 paraSizeX, paraSizeY; 625 uint8 *psxPlx = NULL; 626 ParallaxHeader *header = NULL; 627 uint32 *lineIndexes = NULL; 537 628 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 538 642 // we have to render more than the visible screen part for displaying scroll frames 539 643 scrnScrlX = MIN((uint32)_oldScrollX, Logic::_scriptVars[SCROLL_OFFSET_X]); 540 644 scrnWidth = SCREEN_WIDTH + ABS((int32)_oldScrollX - (int32)Logic::_scriptVars[SCROLL_OFFSET_X]); 541 645 scrnScrlY = MIN((uint32)_oldScrollY, Logic::_scriptVars[SCROLL_OFFSET_Y]); 542 646 scrnHeight = SCREEN_DEPTH + ABS((int32)_oldScrollY - (int32)Logic::_scriptVars[SCROLL_OFFSET_Y]); 543 647 648 544 649 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)); 546 651 paraScrlX = (uint16)(scrnScrlX * scrlfx); 547 652 } else 548 653 paraScrlX = 0; 549 654 550 655 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)); 552 657 paraScrlY = (uint16)(scrnScrlY * scrlfy); 553 658 } else 554 659 paraScrlY = 0; 555 660 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; 582 669 } 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; 595 688 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; 596 696 } 597 697 } 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 } 598 714 } 599 } 715 716 if (psxPlx) 717 free(psxPlx); 600 718 } 601 719 602 720 void Screen::drawSprite(uint8 *sprData, uint16 sprX, uint16 sprY, uint16 sprWidth, uint16 sprHeight, uint16 sprPitch) { 603 721 uint8 *dest = _screenBuf + (sprY * _scrnSizeX) + sprX; 604 722 605 723 for (uint16 cnty = 0; cnty < sprHeight; cnty++) { 606 724 for (uint16 cntx = 0; cntx < sprWidth; cntx++) 607 725 if (sprData[cntx]) 608 726 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 609 735 sprData += sprPitch; 610 736 dest += _scrnSizeX; 611 737 } 612 738 } 613 739 740 // Used to draw psx sprites which are 1/2 of original width 741 void 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 764 void 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 614 788 // nearest neighbor filter: 615 789 void Screen::fastShrink(uint8 *src, uint32 width, uint32 height, uint32 scale, uint8 *dest) { 616 790 uint32 resHeight = (height * scale) >> 8; … … 618 792 uint32 step = 0x10000 / scale; 619 793 uint8 columnTab[160]; 620 794 uint32 res = step >> 1; 795 621 796 for (uint16 cnt = 0; cnt < resWidth; cnt++) { 622 797 columnTab[cnt] = (uint8)(res >> 8); 623 798 res += step; … … 675 850 } 676 851 } 677 852 853 uint8* 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 904 uint8* 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 993 uint8* 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 678 1035 void Screen::decompressTony(uint8 *src, uint32 compSize, uint8 *dest) { 679 1036 uint8 *endOfData = src + compSize; 680 1037 while (src < endOfData) { … … 721 1078 } 722 1079 } 723 1080 1081 void 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 724 1105 void Screen::fadePalette(void) { 725 1106 if (_fadingStep == 16) 726 1107 memcpy(_currentPalette, _targetPalette, 256 * 4); … … 773 1154 *pSprWidth = 0; 774 1155 else 775 1156 *pSprWidth = (uint16)sprW; 1157 776 1158 *pSprX = (uint16)sprX; 777 1159 *pSprY = (uint16)sprY; 778 1160 … … 780 1162 // sprite will be drawn, so mark it in the grid buffer 781 1163 uint16 gridH = (*pSprHeight + (sprY & (SCRNGRID_Y - 1)) + (SCRNGRID_Y - 1)) / SCRNGRID_Y; 782 1164 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 783 1178 uint16 gridX = sprX / SCRNGRID_X; 784 1179 uint16 gridY = sprY / SCRNGRID_Y; 785 1180 uint8 *gridBuf = _screenGrid + gridX + gridY * _gridSizeX; … … 806 1201 uint8 frame[40 * 40]; 807 1202 int i, j; 808 1203 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 810 1208 811 1209 if (resId != 0xffffffff) { 812 1210 FrameHeader *frameHead = _resMan->fetchFrame(_resMan->openFetchRes(resId), frameNo); 813 1211 uint8 *frameData = ((uint8*)frameHead) + sizeof(FrameHeader); 814 1212 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 } 818 1223 } 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]; 819 1230 } 820 1231 821 1232 _resMan->resClose(resId); -
scummvm-bspsx/engines/sword1/control.cpp
45 45 #include "sword1/sword1.h" 46 46 #include "sword1/sworddefs.h" 47 47 #include "sword1/swordres.h" 48 #include "sword1/screen.h" 48 49 49 50 namespace Sword1 { 50 51 … … 120 121 _resMan->resOpen(_resId); 121 122 FrameHeader *tmp = _resMan->fetchFrame(_resMan->fetchRes(_resId), 0); 122 123 _width = _resMan->getUint16(tmp->width); 124 _width = (_width > SCREEN_WIDTH) ? SCREEN_WIDTH : _width; 123 125 _height = _resMan->getUint16(tmp->height); 124 126 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); 127 129 } 128 130 _dstBuf = screenBuf + _y * SCREEN_WIDTH + _x; 129 131 _system = system; … … 141 143 FrameHeader *fHead = _resMan->fetchFrame(_resMan->fetchRes(_resId), _frameIdx); 142 144 uint8 *src = (uint8*)fHead + sizeof(FrameHeader); 143 145 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 151 218 _system->copyRectToScreen(_dstBuf, SCREEN_WIDTH, _x, _y, _width, _height); 152 219 } 153 220 … … 940 1007 941 1008 FrameHeader *chSpr = _resMan->fetchFrame(font, *str - 32); 942 1009 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 943 1019 for (uint16 cnty = 0; cnty < _resMan->getUint16(chSpr->height); cnty++) { 944 1020 for (uint16 cntx = 0; cntx < _resMan->getUint16(chSpr->width); cntx++) { 945 1021 if (sprData[cntx]) 946 1022 dst[cntx] = sprData[cntx]; 947 1023 } 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 948 1032 sprData += _resMan->getUint16(chSpr->width); 949 1033 dst += SCREEN_WIDTH; 950 1034 } 951 1035 destX += _resMan->getUint16(chSpr->width) - 3; 952 1036 str++; 1037 1038 free(HIFbuf); 953 1039 } 1040 954 1041 _system->copyRectToScreen(_screenBuf + y * SCREEN_WIDTH + x, SCREEN_WIDTH, x, y, (destX - x) + 3, 28); 955 1042 } 956 1043 … … 963 1050 FrameHeader *frHead = _resMan->fetchFrame(_resMan->openFetchRes(SR_VLIGHT), (vol + 15) >> 4); 964 1051 uint8 *destMem = _screenBuf + destY * SCREEN_WIDTH + destX; 965 1052 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++) { 967 1065 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 968 1072 srcMem += _resMan->getUint16(frHead->width); 969 1073 destMem += SCREEN_WIDTH; 970 1074 } 1075 971 1076 _system->copyRectToScreen(_screenBuf + destY * SCREEN_WIDTH + destX, SCREEN_WIDTH, destX, destY, _resMan->getUint16(frHead->width), _resMan->getUint16(frHead->height)); 972 1077 _resMan->resClose(SR_VLIGHT); 973 1078 destX += 32; 1079 1080 free(psxVolBuf); 974 1081 } 975 1082 } 976 1083 -
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 32 namespace Sword1 { 33 34 class VagStream : public Audio::AudioStream { 35 public: 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 46 private: 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
66 66 uint8 showText; 67 67 uint8 language; 68 68 bool isDemo; 69 bool isMac;69 Common::Platform platform; 70 70 }; 71 71 72 72 class SwordEngine : public Engine { … … 79 79 uint32 _features; 80 80 81 81 bool mouseIsActive(); 82 83 static bool isMac() { return _systemVars.platform == Common::kPlatformMacintosh; } 84 static bool isPsx() { return _systemVars.platform == Common::kPlatformPSX; } 82 85 83 86 protected: 84 87 // Engine APIs … … 119 122 static const uint8 _cdList[TOTAL_SECTIONS]; 120 123 static const CdFile _pcCdFileList[]; 121 124 static const CdFile _macCdFileList[]; 125 static const CdFile _psxCdFileList[]; 122 126 }; 123 127 124 128 } // End of namespace Sword1 -
scummvm-bspsx/engines/sword1/text.cpp
32 32 #include "sword1/objectman.h" 33 33 #include "sword1/swordres.h" 34 34 #include "sword1/sworddefs.h" 35 #include "sword1/screen.h" 36 #include "sword1/sword1.h" 35 37 36 38 namespace Sword1 { 37 39 … … 78 80 void Text::makeTextSprite(uint8 slot, uint8 *text, uint16 maxWidth, uint8 pen) { 79 81 LineInfo lines[MAX_LINES]; 80 82 uint16 numLines = analyzeSentence(text, maxWidth, lines); 81 83 82 84 uint16 sprWidth = 0; 83 85 uint16 lineCnt; 84 86 for (lineCnt = 0; lineCnt < numLines; lineCnt++) 85 87 if (lines[lineCnt].width > sprWidth) 86 88 sprWidth = lines[lineCnt].width; 89 87 90 uint16 sprHeight = _charHeight * numLines; 88 91 uint32 sprSize = sprWidth * sprHeight; 89 92 assert(!_textBlocks[slot]); // if this triggers, the speechDriver failed to call Text::releaseText. … … 100 103 memset(linePtr, NO_COL, sprSize); 101 104 for (lineCnt = 0; lineCnt < numLines; lineCnt++) { 102 105 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++) 104 107 sprPtr += copyChar(*text++, sprPtr, sprWidth, pen) - OVERLAP; 105 108 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; 107 113 } 108 114 } 109 115 … … 157 163 FrameHeader *chFrame = _resMan->fetchFrame(_font, ch - SPACE); 158 164 uint8 *chData = ((uint8*)chFrame) + sizeof(FrameHeader); 159 165 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++) { 161 184 for (uint16 cntx = 0; cntx < _resMan->getUint16(chFrame->width); cntx++) { 162 if (* chData== LETTER_COL)185 if (*decChr == LETTER_COL) 163 186 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) 165 188 dest[cntx] = BORDER_COL; 166 chData++;189 decChr++; 167 190 } 168 191 dest += sprWidth; 169 192 } 193 free(decBuf); 170 194 return _resMan->getUint16(chFrame->width); 171 195 } 172 196 -
scummvm-bspsx/engines/sword1/music.h
47 47 MusicHandle() : _fading(0), _audioSource(NULL) {} 48 48 virtual int readBuffer(int16 *buffer, const int numSamples); 49 49 bool play(const char *filename, bool loop); 50 bool playPSX(uint16 id, bool loop); 50 51 void stop(); 51 52 void fadeUp(); 52 53 void fadeDown(); -
scummvm-bspsx/engines/sword1/sound.cpp
34 34 #include "sword1/resman.h" 35 35 #include "sword1/logic.h" 36 36 #include "sword1/sword1.h" 37 #include "sword1/vag.h" 37 38 38 39 #include "sound/flac.h" 39 40 #include "sound/mp3.h" … … 160 161 if (_fxList[elem->id].roomVolList[cnt].roomNo) { 161 162 if ((_fxList[elem->id].roomVolList[cnt].roomNo == (int)Logic::_scriptVars[SCREEN]) || 162 163 (_fxList[elem->id].roomVolList[cnt].roomNo == -1)) { 163 164 164 165 uint8 volL = (_fxList[elem->id].roomVolList[cnt].leftVol * 10 * _sfxVolL) / 255; 165 166 uint8 volR = (_fxList[elem->id].roomVolList[cnt].rightVol * 10 * _sfxVolR) / 255; 166 167 int8 pan = (volR - volL) / 2; 167 168 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 } 179 187 } 180 188 } else 181 189 break; … … 187 195 warning("Sound::startSpeech: COW file isn't open"); 188 196 return false; 189 197 } 198 199 uint32 locIndex = 0xFFFFFFFF; 200 uint32 sampleSize = 0; 201 uint32 index = 0; 190 202 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 194 259 debug(6, "startSpeech(%d, %d): locIndex %d, sampleSize %d, index %d", roomNo, localNo, locIndex, sampleSize, index); 260 195 261 if (sampleSize) { 196 262 uint8 speechVol = (_speechVolR + _speechVolL) / 2; 197 263 int8 speechPan = (_speechVolR - _speechVolL) / 2; … … 200 266 int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size); 201 267 if (data) 202 268 _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; 203 277 } 204 278 #ifdef USE_FLAC 205 279 else if (_cowMode == CowFlac) { … … 419 493 debug(1, "Using uncompressed Speech Cluster"); 420 494 _cowMode = CowWave; 421 495 } 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 422 507 if (!_cowFile.isOpen()) 423 508 _cowFile.open("speech.clu"); 509 424 510 if (!_cowFile.isOpen()) { 425 511 _cowFile.open("cows.mad"); 426 512 if (_cowFile.isOpen()) 427 513 _cowMode = CowDemo; 428 514 } 515 429 516 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 } 437 537 } else 438 538 warning("Sound::initCowSystem: Can't open SPEECH%d.CLU", SwordEngine::_systemVars.currentCD); 439 539 } -
scummvm-bspsx/engines/sword1/logic.cpp
112 112 fnFullSetFrame(cpt, SAND_25, IMPPLSCDT, IMPPLS, 0, 0, 0, 0); // impression filled with plaster 113 113 } 114 114 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 115 119 if (SwordEngine::_systemVars.justRestoredGame) { // if we've just restored a game - we want George to be exactly as saved 116 120 fnAddHuman(NULL, 0, 0, 0, 0, 0, 0, 0); 117 121 if (_scriptVars[GEORGE_WALKING]) { // except that if George was walking when we saveed the game