Ticket #8993: bs2psx-RC2.diff
File bs2psx-RC2.diff, 86.3 KB (added by , 16 years ago) |
---|
-
scummvm-bs2psx/engines/sword2/protocol.cpp
25 25 * $Id$ 26 26 */ 27 27 28 #include "common/file.h" 29 #include "common/endian.h" 28 30 29 30 31 #include "sword2/sword2.h" 31 32 #include "sword2/header.h" 32 33 #include "sword2/resman.h" 34 #include "sword2/logic.h" 33 35 34 36 namespace Sword2 { 35 37 … … 39 41 */ 40 42 41 43 byte *Sword2Engine::fetchPalette(byte *screenFile) { 42 MultiScreenHeader mscreenHeader;44 byte *palette; 43 45 44 mscreenHeader.read(screenFile + ResHeader::size()); 46 if(isPsx()) { // PSX version doesn't have a "MultiScreenHeader", instead there's a ScreenHeader and a tag 47 palette = screenFile + ResHeader::size() + ScreenHeader::size() + 2; 48 } else { 49 MultiScreenHeader mscreenHeader; 45 50 46 byte *palette = screenFile + ResHeader::size() + mscreenHeader.palette; 51 mscreenHeader.read(screenFile + ResHeader::size()); 52 palette = screenFile + ResHeader::size() + mscreenHeader.palette; 53 } 47 54 48 55 // Always set colour 0 to black, because while most background screen 49 56 // palettes have a bright colour 0 it should come out as black in the … … 60 67 /** 61 68 * Returns a pointer to the start of the palette match table, given the pointer 62 69 * to the start of the screen file. 70 * It returns NULL when used with PSX version, as there are no palette match tables in 71 * the resource files. 63 72 */ 64 73 65 74 byte *Sword2Engine::fetchPaletteMatchTable(byte *screenFile) { 75 76 if (isPsx()) return NULL; 77 66 78 MultiScreenHeader mscreenHeader; 67 79 68 80 mscreenHeader.read(screenFile + ResHeader::size()); … … 76 88 */ 77 89 78 90 byte *Sword2Engine::fetchScreenHeader(byte *screenFile) { 79 MultiScreenHeader mscreenHeader; 91 if (isPsx()) { // In PSX version there's no MultiScreenHeader, so just skip resource header 92 return screenFile + ResHeader::size(); 93 } else { 94 MultiScreenHeader mscreenHeader; 80 95 81 mscreenHeader.read(screenFile + ResHeader::size());82 83 return screenFile + ResHeader::size() + mscreenHeader.screen;96 mscreenHeader.read(screenFile + ResHeader::size()); 97 return screenFile + ResHeader::size() + mscreenHeader.screen; 98 } 84 99 } 85 100 86 101 /** … … 97 112 assert(layerNo < screenHead.noLayers); 98 113 #endif 99 114 100 MultiScreenHeader mscreenHeader; 101 102 mscreenHeader.read(screenFile + ResHeader::size()); 103 104 return screenFile + ResHeader::size() + mscreenHeader.layers + layerNo * LayerHeader::size(); 115 if (isPsx()) { 116 return screenFile + ResHeader::size() + ScreenHeader::size() + 2 + 0x400 + layerNo * LayerHeader::size(); 117 } else { 118 MultiScreenHeader mscreenHeader; 119 120 mscreenHeader.read(screenFile + ResHeader::size()); 121 return screenFile + ResHeader::size() + mscreenHeader.layers + layerNo * LayerHeader::size(); 122 } 105 123 } 106 124 107 125 /** 108 126 * Returns a pointer to the start of the shading mask, given the pointer to the 109 127 * start of the screen file. 128 * If we are non PSX, this will return NULL, as we don't have shading masks. 110 129 */ 111 130 112 131 byte *Sword2Engine::fetchShadingMask(byte *screenFile) { 132 if (isPsx()) return NULL; 133 113 134 MultiScreenHeader mscreenHeader; 114 135 115 136 mscreenHeader.read(screenFile + ResHeader::size()); … … 139 160 animHead.read(fetchAnimHeader(animFile)); 140 161 141 162 if (frameNo > animHead->noAnimFrames - 1) 142 error("fetchCdtEntry(animFile,%d) - anim only %d frames", frameNo, animHead .noAnimFrames);163 error("fetchCdtEntry(animFile,%d) - anim only %d frames", frameNo, animHead->noAnimFrames); 143 164 #endif 144 165 145 166 return fetchAnimHeader(animFile) + AnimHeader::size() + frameNo * CdtEntry::size(); … … 153 174 154 175 byte *Sword2Engine::fetchFrameHeader(byte *animFile, uint16 frameNo) { 155 176 // required address = (address of the start of the anim header) + frameOffset 177 156 178 CdtEntry cdt; 157 179 158 180 cdt.read(fetchCdtEntry(animFile, frameNo)); … … 165 187 */ 166 188 167 189 byte *Sword2Engine::fetchBackgroundParallaxLayer(byte *screenFile, int layer) { 168 MultiScreenHeader mscreenHeader; 190 if (isPsx()) { 191 byte *psxParallax = _screen->getPsxScrCache(0); 169 192 170 mscreenHeader.read(screenFile + ResHeader::size()); 171 assert(mscreenHeader.bg_parallax[layer]); 193 // Manage cache for background psx parallaxes 194 if (!_screen->getPsxScrCacheStatus(0)) { // This parallax layer is not present 195 return NULL; 196 } else if (psxParallax != NULL) { // Parallax layer present, and already in cache 197 return psxParallax; 198 } else { // Present, but not cached 199 uint32 locNo = _logic->getLocationNum(); 172 200 173 return screenFile + ResHeader::size() + mscreenHeader.bg_parallax[layer]; 201 // At game startup, we have a wrong location number stored 202 // in game vars (0, instead of 3), work around this. 203 locNo = (locNo == 0) ? 3 : locNo; 204 205 psxParallax = fetchPsxParallax(locNo, 0); 206 _screen->setPsxScrCache(psxParallax, 0); 207 return psxParallax; 208 } 209 } else { 210 MultiScreenHeader mscreenHeader; 211 212 mscreenHeader.read(screenFile + ResHeader::size()); 213 assert(mscreenHeader.bg_parallax[layer]); 214 return screenFile + ResHeader::size() + mscreenHeader.bg_parallax[layer]; 215 } 174 216 } 175 217 176 218 byte *Sword2Engine::fetchBackgroundLayer(byte *screenFile) { 177 MultiScreenHeader mscreenHeader; 219 if (isPsx()) { 220 byte *psxBackground = _screen->getPsxScrCache(1); 178 221 179 mscreenHeader.read(screenFile + ResHeader::size()); 180 assert(mscreenHeader.screen); 222 // Manage cache for psx backgrounds 223 if (psxBackground) { // Background is cached 224 return psxBackground; 225 } else { // Background not cached 226 uint32 locNo = _logic->getLocationNum(); 181 227 182 return screenFile + ResHeader::size() + mscreenHeader.screen + ScreenHeader::size(); 228 // We have a wrong location number at start, fix that 229 locNo = (locNo == 0) ? 3 : locNo; 230 231 psxBackground = fetchPsxBackground(locNo); 232 _screen->setPsxScrCache(psxBackground, 1); 233 return psxBackground; 234 } 235 } else { 236 MultiScreenHeader mscreenHeader; 237 238 mscreenHeader.read(screenFile + ResHeader::size()); 239 assert(mscreenHeader.screen); 240 return screenFile + ResHeader::size() + mscreenHeader.screen + ScreenHeader::size(); 241 } 183 242 } 184 243 185 244 byte *Sword2Engine::fetchForegroundParallaxLayer(byte *screenFile, int layer) { 186 MultiScreenHeader mscreenHeader; 245 if (isPsx()) { 246 byte *psxParallax = _screen->getPsxScrCache(2); 187 247 188 mscreenHeader.read(screenFile + ResHeader::size()); 189 assert(mscreenHeader.fg_parallax[layer]); 248 // Manage cache for psx parallaxes 249 if (!_screen->getPsxScrCacheStatus(2)) { // This parallax layer is not present 250 return NULL; 251 } else if (psxParallax) { // Parallax layer present and cached 252 return psxParallax; 253 } else { // Present, but still not cached 254 uint32 locNo = _logic->getLocationNum(); 190 255 191 return screenFile + ResHeader::size() + mscreenHeader.fg_parallax[layer]; 256 // We have a wrong location number at start, fix that 257 locNo = (locNo == 0) ? 3 : locNo; 258 259 psxParallax = fetchPsxParallax(locNo, 1); 260 _screen->setPsxScrCache(psxParallax, 2); 261 return psxParallax; 262 } 263 } else { 264 MultiScreenHeader mscreenHeader; 265 266 mscreenHeader.read(screenFile + ResHeader::size()); 267 assert(mscreenHeader.fg_parallax[layer]); 268 return screenFile + ResHeader::size() + mscreenHeader.fg_parallax[layer]; 269 } 192 270 } 193 271 194 272 byte *Sword2Engine::fetchTextLine(byte *file, uint32 text_line) { … … 211 289 return file + READ_LE_UINT32(file + ResHeader::size() + 4 + 4 * text_line); 212 290 } 213 291 292 /** 293 * Returns a pointer to psx background data for passed location number 294 * At the beginning of the passed data there's an artificial header composed by 295 * uint16: background X resolution 296 * uint16: background Y resolution 297 * uint32: offset to subtract from offset table entries 298 */ 299 300 byte *Sword2Engine::fetchPsxBackground(uint32 location) { 301 Common::File file; 302 PSXScreensEntry header; 303 uint32 screenOffset, dataOffset; 304 uint32 totSize; // Total size of background, counting data, offset table and additional header 305 byte *buffer; 306 307 if (!file.open("screens.clu")) { 308 GUIErrorMessage("Broken Sword 2: Cannot open screens.clu"); 309 return NULL; 310 } 311 312 file.seek(location * 4, SEEK_SET); 313 screenOffset = file.readUint32LE(); 314 315 if (screenOffset == 0) { // We don't have screen data for this location number. 316 file.close(); 317 return NULL; 318 } 319 320 // Get to the beginning of PSXScreensEntry 321 file.seek(screenOffset + ResHeader::size(), SEEK_SET); 322 323 buffer = (byte *)malloc(PSXScreensEntry::size()); 324 file.read(buffer, PSXScreensEntry::size()); 325 326 // Prepare the header 327 header.read(buffer); 328 free(buffer); 329 330 file.seek(screenOffset + header.bgOffset + 4, SEEK_SET); 331 dataOffset = file.readUint32LE(); 332 333 file.seek(screenOffset + header.bgOffset, SEEK_SET); 334 335 totSize = header.bgSize + (dataOffset - header.bgOffset) + 8; 336 buffer = (byte *)malloc(totSize); 337 338 // Write some informations before background data 339 WRITE_LE_UINT16(buffer, header.bgXres); 340 WRITE_LE_UINT16(buffer + 2, header.bgYres); 341 WRITE_LE_UINT32(buffer + 4, header.bgOffset); 342 343 file.read(buffer + 8, totSize - 8); // Do not write on the header 344 file.close(); 345 346 return buffer; 347 } 348 349 /** 350 * Returns a pointer to selected psx parallax data for passed location number 351 * At the beginning of the passed data there's an artificial header composed by 352 * uint16: parallax X resolution 353 * uint16: parallax Y resolution 354 * uint16: width in 64x16 tiles of parallax 355 * uint16: height in 64x16 tiles of parallax 356 */ 357 358 byte *Sword2Engine::fetchPsxParallax(uint32 location, uint8 level) { 359 Common::File file; 360 PSXScreensEntry header; 361 uint32 screenOffset; 362 uint16 horTiles; // Number of horizontal tiles in the parallax grid 363 uint16 verTiles; // Number of vertical tiles in parallax grid 364 uint32 totSize; // Total size of parallax, counting data, grid, and additional header 365 byte *buffer; 366 367 uint16 plxXres; 368 uint16 plxYres; 369 uint32 plxOffset; 370 uint32 plxSize; 371 372 if (level > 1) 373 return NULL; 374 375 if (!file.open("screens.clu")) { 376 GUIErrorMessage("Broken Sword 2: Cannot open screens.clu"); 377 return NULL; 378 } 379 380 file.seek(location * 4, SEEK_SET); 381 screenOffset = file.readUint32LE(); 382 383 if (screenOffset == 0) // There is no screen here 384 return NULL; 385 386 // Get to the beginning of PSXScreensEntry 387 file.seek(screenOffset + ResHeader::size(), SEEK_SET); 388 389 buffer = (byte *)malloc(PSXScreensEntry::size()); 390 file.read(buffer, PSXScreensEntry::size()); 391 392 // Initialize the header 393 header.read(buffer); 394 free(buffer); 395 396 // We are fetching... 397 if (level == 0) { // a background parallax 398 plxXres = header.bgPlxXres; 399 plxYres = header.bgPlxYres; 400 plxOffset = header.bgPlxOffset; 401 plxSize = header.bgPlxSize; 402 } else { // a foreground parallax 403 plxXres = header.fgPlxXres; 404 plxYres = header.fgPlxYres; 405 plxOffset = header.fgPlxOffset; 406 plxSize = header.fgPlxSize; 407 } 408 409 if (plxXres == 0 || plxYres == 0 || plxSize == 0) // This screen has no parallax data. 410 return NULL; 411 412 debug(2, "fetchPsxParallax() -> %s parallax, xRes: %u, yRes: %u", (level == 0) ? "Background" : "Foreground", plxXres, plxYres); 413 414 // Calculate the number of tiles which compose the parallax grid. 415 horTiles = plxXres % 64 ? (plxXres / 64) + 1 : plxXres / 64; 416 verTiles = plxYres % 16 ? (plxYres / 16) + 1 : plxYres / 16; 417 418 totSize = plxSize + horTiles * verTiles * 4 + 8; 419 420 file.seek(screenOffset + plxOffset, SEEK_SET); 421 buffer = (byte *)malloc(totSize); 422 423 // Insert parallax resolution information in the buffer, 424 // preceding parallax data. 425 WRITE_LE_UINT16(buffer, plxXres); 426 WRITE_LE_UINT16(buffer + 2, plxYres); 427 WRITE_LE_UINT16(buffer + 4, horTiles); 428 WRITE_LE_UINT16(buffer + 6, verTiles); 429 430 // Read parallax data from file and store it inside the buffer, 431 // skipping the generated header. 432 file.read(buffer + 8, totSize - 8); 433 file.close(); 434 435 return buffer; 436 } 437 214 438 // Used for testing text & speech (see fnISpeak in speech.cpp) 215 439 216 440 bool Sword2Engine::checkTextLine(byte *file, uint32 text_line) { -
scummvm-bs2psx/engines/sword2/controls.cpp
268 268 269 269 // Usually the mouse pointer will already be "normal", but not always. 270 270 _vm->_mouse->setMouse(NORMAL_MOUSE_ID); 271 272 // Force mouse mode as system menu: normally not needed, 273 // but value is not correct in case of game start dialog 274 // (when asking to restart or load a game). 275 // This is forced to avoid GMM loading/saving being enabled 276 // during initial dialog. 277 _vm->_mouse->setMouseMode(MOUSE_system_menu); 271 278 } 272 279 273 280 Dialog::~Dialog() { -
scummvm-bs2psx/engines/sword2/menu.cpp
42 42 void Mouse::clearIconArea(int menu, int pocket, Common::Rect *r) { 43 43 byte *buf = _vm->_screen->getScreen(); 44 44 int16 screenWide = _vm->_screen->getScreenWide(); 45 byte menuIconWidth; 46 47 // Initialize menu icon width at correct size 48 // depending if we are using pc or psx version. 49 if (Sword2Engine::isPsx()) 50 menuIconWidth = RDMENU_PSXICONWIDE; 51 else 52 menuIconWidth = RDMENU_ICONWIDE; 45 53 54 46 55 r->top = menu * (RENDERDEEP + MENUDEEP) + (MENUDEEP - RDMENU_ICONDEEP) / 2; 47 56 r->bottom = r->top + RDMENU_ICONDEEP; 48 r->left = RDMENU_ICONSTART + pocket * ( RDMENU_ICONWIDE+ RDMENU_ICONSPACING);49 r->right = r->left + RDMENU_ICONWIDE;57 r->left = RDMENU_ICONSTART + pocket * (menuIconWidth + RDMENU_ICONSPACING); 58 r->right = r->left + menuIconWidth; 50 59 51 60 byte *dst = buf + r->top * screenWide + r->left; 52 61 53 62 for (int i = 0; i < RDMENU_ICONDEEP; i++) { 54 memset(dst, 0, RDMENU_ICONWIDE);63 memset(dst, 0, menuIconWidth); 55 64 dst += screenWide; 56 65 } 57 66 } … … 71 80 72 81 byte *buf = _vm->_screen->getScreen(); 73 82 int16 screenWide = _vm->_screen->getScreenWide(); 83 byte menuIconWidth; 84 85 if (Sword2Engine::isPsx()) 86 menuIconWidth = RDMENU_PSXICONWIDE; 87 else 88 menuIconWidth = RDMENU_ICONWIDE; 74 89 90 75 91 if (lastTime == 0) { 76 92 lastTime = _vm->getMillis(); 77 93 frameCount = 1; … … 141 157 _menuStatus[menu] = RDMENU_HIDDEN; 142 158 143 159 // Draw the menu here. 144 int32 curx = RDMENU_ICONSTART + RDMENU_ICONWIDE/ 2;160 int32 curx = RDMENU_ICONSTART + menuIconWidth / 2; 145 161 int32 cury = (MENUDEEP / 2) + (RENDERDEEP + MENUDEEP) * menu; 146 162 147 163 for (i = 0; i < RDMENU_MAXPOCKETS; i++) { … … 154 170 clearIconArea(menu, i, &r1); 155 171 156 172 if (_pocketStatus[menu][i] == MAXMENUANIMS) { 157 xoff = ( RDMENU_ICONWIDE/ 2);173 xoff = (menuIconWidth / 2); 158 174 r2.left = curx - xoff; 159 r2.right = r2.left + RDMENU_ICONWIDE;175 r2.right = r2.left + menuIconWidth; 160 176 yoff = (RDMENU_ICONDEEP / 2); 161 177 r2.top = cury - yoff; 162 178 r2.bottom = r2.top + RDMENU_ICONDEEP; 163 179 } else { 164 xoff = ( RDMENU_ICONWIDE/ 2) * _pocketStatus[menu][i] / MAXMENUANIMS;180 xoff = (menuIconWidth / 2) * _pocketStatus[menu][i] / MAXMENUANIMS; 165 181 r2.left = curx - xoff; 166 182 r2.right = curx + xoff; 167 183 yoff = (RDMENU_ICONDEEP / 2) * _pocketStatus[menu][i] / MAXMENUANIMS; … … 176 192 if (_pocketStatus[menu][i] != MAXMENUANIMS) { 177 193 _vm->_screen->scaleImageFast( 178 194 dst, screenWide, r2.right - r2.left, r2.bottom - r2.top, 179 src, RDMENU_ICONWIDE, RDMENU_ICONWIDE, RDMENU_ICONDEEP);195 src, menuIconWidth, menuIconWidth, RDMENU_ICONDEEP); 180 196 } else { 181 197 for (j = 0; j < RDMENU_ICONDEEP; j++) { 182 memcpy(dst, src, RDMENU_ICONWIDE);183 src += RDMENU_ICONWIDE;198 memcpy(dst, src, menuIconWidth); 199 src += menuIconWidth; 184 200 dst += screenWide; 185 201 } 186 202 } 187 203 } 188 204 _vm->_screen->updateRect(&r1); 189 205 } 190 curx += (RDMENU_ICONSPACING + RDMENU_ICONWIDE);206 curx += (RDMENU_ICONSPACING + menuIconWidth); 191 207 } 192 208 } 193 209 } … … 199 215 */ 200 216 201 217 int32 Mouse::showMenu(uint8 menu) { 218 219 // Do not show menu in PSX version, as there was really 220 // nothing similar in the original game (menu was started 221 // using SELECT button in psx pad) 222 if (Sword2Engine::isPsx() && menu == RDMENU_TOP) 223 return RD_OK; 224 202 225 // Check for invalid menu parameter 203 226 if (menu > RDMENU_BOTTOM) 204 227 return RDERR_INVALIDMENU; … … 219 242 */ 220 243 221 244 int32 Mouse::hideMenu(uint8 menu) { 245 246 // In PSX version, do nothing. There is no such menu. 247 if (Sword2Engine::isPsx() && menu == RDMENU_TOP) 248 return RD_OK; 249 222 250 // Check for invalid menu parameter 223 251 if (menu > RDMENU_BOTTOM) 224 252 return RDERR_INVALIDMENU; … … 267 295 268 296 int32 Mouse::setMenuIcon(uint8 menu, uint8 pocket, byte *icon) { 269 297 Common::Rect r; 298 byte menuIconWidth; 299 300 if (Sword2Engine::isPsx()) 301 menuIconWidth = RDMENU_PSXICONWIDE; 302 else 303 menuIconWidth = RDMENU_ICONWIDE; 270 304 271 305 // Check for invalid menu parameter. 272 306 if (menu > RDMENU_BOTTOM) … … 288 322 // Only put the icon in the pocket if it is not NULL 289 323 if (icon != NULL) { 290 324 _iconCount++; 291 _icons[menu][pocket] = (byte *)malloc( RDMENU_ICONWIDE* RDMENU_ICONDEEP);325 _icons[menu][pocket] = (byte *)malloc(menuIconWidth * RDMENU_ICONDEEP); 292 326 if (_icons[menu][pocket] == NULL) 293 327 return RDERR_OUTOFMEMORY; 294 memcpy(_icons[menu][pocket], icon, RDMENU_ICONWIDE* RDMENU_ICONDEEP);328 memcpy(_icons[menu][pocket], icon, menuIconWidth * RDMENU_ICONDEEP); 295 329 } 296 330 297 331 return RD_OK; -
scummvm-bs2psx/engines/sword2/render.cpp
252 252 */ 253 253 254 254 void Screen::renderParallax(byte *ptr, int16 l) { 255 Parallax p;256 255 int16 x, y; 256 uint16 xRes, yRes; 257 257 Common::Rect r; 258 258 259 p.read(ptr); 259 if (!ptr) 260 return; 260 261 262 // Fetch resolution data from parallax 263 264 if (Sword2Engine::isPsx()) { 265 xRes = READ_LE_UINT16(ptr); 266 yRes = READ_LE_UINT16(ptr + 2) * 2; 267 } else { 268 Parallax p; 269 270 p.read(ptr); 271 xRes = p.w; 272 yRes = p.h; 273 } 274 261 275 if (_locationWide == _screenWide) 262 276 x = 0; 263 277 else 264 x = ((int32)(( p.w- _screenWide) * _scrollX) / (int32)(_locationWide - _screenWide));278 x = ((int32)((xRes - _screenWide) * _scrollX) / (int32)(_locationWide - _screenWide)); 265 279 266 280 if (_locationDeep == _screenDeep - MENUDEEP * 2) 267 281 y = 0; 268 282 else 269 y = ((int32)(( p.h- (_screenDeep - MENUDEEP * 2)) * _scrollY) / (int32)(_locationDeep - (_screenDeep - MENUDEEP * 2)));283 y = ((int32)((yRes - (_screenDeep - MENUDEEP * 2)) * _scrollY) / (int32)(_locationDeep - (_screenDeep - MENUDEEP * 2))); 270 284 271 285 Common::Rect clipRect; 272 286 … … 537 551 } 538 552 539 553 /** 554 * This converts PSX format background data into a format that 555 * can be understood by renderParallax functions. 556 * PSX Backgrounds are divided into tiles of 64x32 (with aspect 557 * ratio correction), while PC backgrounds are in tiles of 64x64. 558 */ 559 560 int32 Screen::initialisePsxBackgroundLayer(byte *parallax) { 561 uint16 bgXres, bgYres; 562 uint16 trueXres, stripeNumber, totStripes; 563 uint32 baseAddress, stripePos; 564 uint16 i, j; 565 byte *dst; 566 567 debug(2, "initialisePsxBackgroundLayer"); 568 569 assert(_layer < MAXLAYERS); 570 571 if (!parallax) { 572 _layer++; 573 return RD_OK; 574 } 575 576 // Fetch data from buffer 577 578 bgXres = READ_LE_UINT16(parallax); 579 bgYres = READ_LE_UINT16(parallax + 2) * 2; 580 baseAddress = READ_LE_UINT32(parallax + 4); 581 parallax += 8; 582 583 // Calculate TRUE resolution of background, must be 584 // a multiple of 64 585 586 trueXres = (bgXres % 64) ? ((bgXres/64) + 1) * 64 : bgXres; 587 totStripes = trueXres / 64; 588 589 _xBlocks[_layer] = (bgXres + BLOCKWIDTH - 1) / BLOCKWIDTH; 590 _yBlocks[_layer] = (bgYres + BLOCKHEIGHT - 1) / BLOCKHEIGHT; 591 592 uint16 remLines = bgYres % 64; 593 594 byte *tileChunk = (byte *)malloc(BLOCKHEIGHT * BLOCKWIDTH); 595 if (!tileChunk) 596 return RDERR_OUTOFMEMORY; 597 598 _blockSurfaces[_layer] = (BlockSurface **)calloc(_xBlocks[_layer] * _yBlocks[_layer], sizeof(BlockSurface *)); 599 if (!_blockSurfaces[_layer]) 600 return RDERR_OUTOFMEMORY; 601 602 // Group PSX background (64x32, when stretched vertically) tiles together, 603 // to make them compatible with pc version (composed by 64x64 tiles) 604 605 stripeNumber = 0; 606 stripePos = 0; 607 for (i = 0; i < _xBlocks[_layer] * _yBlocks[_layer]; i++) { 608 bool block_has_data = false; 609 bool block_is_transparent = false; 610 611 int posX = i / _yBlocks[_layer]; 612 int posY = i % _yBlocks[_layer]; 613 614 uint32 stripeOffset = READ_LE_UINT32(parallax + stripeNumber * 8 + 4) + stripePos - baseAddress; 615 616 memset(tileChunk, 1, BLOCKHEIGHT * BLOCKWIDTH); 617 618 if (!(remLines && posY == _yBlocks[_layer] - 1)) 619 remLines = 32; 620 621 for(j = 0; j < remLines; j++) { 622 memcpy(tileChunk + j * BLOCKWIDTH * 2, parallax + stripeOffset + j * BLOCKWIDTH, BLOCKWIDTH); 623 memcpy(tileChunk + j * BLOCKWIDTH * 2 + BLOCKWIDTH, parallax + stripeOffset + j * BLOCKWIDTH, BLOCKWIDTH); 624 } 625 626 for (j = 0; j < BLOCKHEIGHT * BLOCKWIDTH; j++) { 627 if (tileChunk[j]) 628 block_has_data = true; 629 else 630 block_is_transparent = true; 631 } 632 633 int tileIndex = totStripes * posY + posX; 634 635 // Only assign a surface to the block if it contains data. 636 637 if (block_has_data) { 638 _blockSurfaces[_layer][tileIndex] = (BlockSurface *)malloc(sizeof(BlockSurface)); 639 640 // Copy the data into the surfaces. 641 dst = _blockSurfaces[_layer][tileIndex]->data; 642 memcpy(dst, tileChunk, BLOCKWIDTH * BLOCKHEIGHT); 643 644 _blockSurfaces[_layer][tileIndex]->transparent = block_is_transparent; 645 646 } else 647 _blockSurfaces[_layer][tileIndex] = NULL; 648 649 if (posY == _yBlocks[_layer] - 1) { 650 stripeNumber++; 651 stripePos = 0; 652 } else { 653 stripePos += 0x800; 654 } 655 } 656 657 free(tileChunk); 658 _layer++; 659 660 return RD_OK; 661 } 662 663 /** 664 * This converts PSX format parallax data into a format that 665 * can be understood by renderParallax functions. 666 */ 667 668 int32 Screen::initialisePsxParallaxLayer(byte *parallax) { 669 uint16 plxXres, plxYres; 670 uint16 xTiles, yTiles; 671 uint16 i, j, k; 672 byte *data; 673 byte *dst; 674 675 debug(2, "initialisePsxParallaxLayer"); 676 677 assert(_layer < MAXLAYERS); 678 679 if (!parallax) { 680 _layer++; 681 return RD_OK; 682 } 683 684 plxXres = READ_LE_UINT16(parallax); 685 plxYres = READ_LE_UINT16(parallax + 2); 686 xTiles = READ_LE_UINT16(parallax + 4); 687 yTiles = READ_LE_UINT16(parallax + 6); 688 689 // Beginning of parallax table composed by uint32, 690 // if word is 0, corresponding tile contains no data and must be skipped, 691 // if word is 0x400 tile contains data. 692 parallax += 8; 693 694 // Beginning if tiles data. 695 data = parallax + xTiles * yTiles * 4; 696 697 _xBlocks[_layer] = xTiles; 698 _yBlocks[_layer] = (yTiles / 2) + (yTiles % 2 ? 1 : 0); 699 bool oddTiles = (yTiles % 2 ? true : false); 700 701 _blockSurfaces[_layer] = (BlockSurface **)calloc(_xBlocks[_layer] * _yBlocks[_layer], sizeof(BlockSurface *)); 702 if (!_blockSurfaces[_layer]) 703 return RDERR_OUTOFMEMORY; 704 705 // We have to check two tiles for every block in PSX version, if one of those 706 // has data in it, the whole block has data. Also, tiles must be doublelined to 707 // get correct aspect ratio. 708 for (i = 0; i < _xBlocks[_layer] * _yBlocks[_layer]; i++) { 709 bool block_has_data = false; 710 bool block_is_transparent = false; 711 bool firstTilePresent, secondTilePresent; 712 713 int posX = i / _yBlocks[_layer]; 714 int posY = i % _yBlocks[_layer]; 715 716 if (oddTiles && posY == _yBlocks[_layer] - 1) { 717 firstTilePresent = READ_LE_UINT32(parallax) == 0x400; 718 secondTilePresent = false; 719 parallax += 4; 720 } else { 721 firstTilePresent = READ_LE_UINT32(parallax) == 0x400; 722 secondTilePresent = READ_LE_UINT32(parallax + 4) == 0x400; 723 parallax += 8; 724 } 725 726 // If one of the two grouped tiles has data, then the whole block has data 727 if (firstTilePresent || secondTilePresent) { 728 block_has_data = true; 729 730 // If one of the two grouped blocks is without data, then we also have transparency 731 if(!firstTilePresent || !secondTilePresent) 732 block_is_transparent = true; 733 } 734 735 // Now do a second check to see if we have a partially transparent block 736 if (block_has_data && !block_is_transparent) { 737 byte *block = data; 738 if (firstTilePresent) { 739 for (k = 0; k < 0x400; k++) { 740 if ( *(block + k) == 0) { 741 block_is_transparent = true; 742 break; 743 } 744 } 745 block += 0x400; // On to next block... 746 } 747 748 // If we didn't find transparency in first block and we have 749 // a second tile, check it 750 if (secondTilePresent && !block_is_transparent) { 751 for (k = 0; k < 0x400; k++) { 752 if ( *(block + k) == 0) { 753 block_is_transparent = true; 754 break; 755 } 756 } 757 } 758 } 759 760 int tileIndex = xTiles * posY + posX; 761 762 // Only assign a surface to the block if it contains data. 763 764 if (block_has_data) { 765 _blockSurfaces[_layer][tileIndex] = (BlockSurface *)malloc(sizeof(BlockSurface)); 766 memset(_blockSurfaces[_layer][tileIndex], 0, BLOCKHEIGHT * BLOCKWIDTH); 767 768 // Copy the data into the surfaces. 769 dst = _blockSurfaces[_layer][tileIndex]->data; 770 771 if (firstTilePresent) { //There is data in the first tile 772 for (j = 0; j < 16; j++) { 773 memcpy(dst, data, BLOCKWIDTH); 774 dst += BLOCKWIDTH; 775 memcpy(dst, data, BLOCKWIDTH); 776 dst += BLOCKWIDTH; 777 data += BLOCKWIDTH; 778 } 779 } else { 780 dst += 0x800; 781 } 782 783 if (secondTilePresent) { 784 for (j = 0; j < 16; j++) { 785 memcpy(dst, data, BLOCKWIDTH); 786 dst += BLOCKWIDTH; 787 memcpy(dst, data, BLOCKWIDTH); 788 dst += BLOCKWIDTH; 789 data += BLOCKWIDTH; 790 } 791 } 792 793 _blockSurfaces[_layer][tileIndex]->transparent = block_is_transparent; 794 } else 795 _blockSurfaces[_layer][tileIndex] = NULL; 796 } 797 798 _layer++; 799 800 return RD_OK; 801 } 802 803 /** 540 804 * Should be called once after leaving the room to free up memory. 541 805 */ 542 806 543 807 void Screen::closeBackgroundLayer() { 544 808 debug(2, "CloseBackgroundLayer"); 545 809 810 if (Sword2Engine::isPsx()) 811 flushPsxScrCache(); 812 546 813 for (int i = 0; i < MAXLAYERS; i++) { 547 814 if (_blockSurfaces[i]) { 548 815 for (int j = 0; j < _xBlocks[i] * _yBlocks[i]; j++) -
scummvm-bs2psx/engines/sword2/sword2.cpp
51 51 #include "sword2/router.h" 52 52 #include "sword2/screen.h" 53 53 #include "sword2/sound.h" 54 #include "sword2/saveload.h" 54 55 55 56 namespace Sword2 { 56 57 … … 104 105 bool Sword2::Sword2Engine::hasFeature(EngineFeature f) const { 105 106 return 106 107 (f == kSupportsRTL) || 107 (f == kSupportsSubtitleOptions); 108 (f == kSupportsSubtitleOptions) || 109 (f == kSupportsSavingDuringRuntime) || 110 (f == kSupportsLoadingDuringRuntime); 108 111 } 109 112 110 113 GameList Sword2MetaEngine::getSupportedGames() const { … … 299 302 _gameCycle = 0; 300 303 _gameSpeed = 1; 301 304 305 _gmmLoadSlot = -1; // Used to manage GMM Loading 306 302 307 syst->getEventManager()->registerRandomSource(_rnd, "sword2"); 303 308 } 304 309 … … 429 434 if (!dialog.runModal()) 430 435 startGame(); 431 436 } 432 } else if (!_bootParam && saveExists() ) {433 int32 pars[2] = { 221, FX_LOOP }; 437 } else if (!_bootParam && saveExists() && !isPsx()) { // Initial load/restart panel disabled in PSX 438 int32 pars[2] = { 221, FX_LOOP }; // version because of missing panel resources 434 439 bool result; 435 440 436 441 _mouse->setMouse(NORMAL_MOUSE_ID); … … 465 470 } 466 471 #endif 467 472 473 // Handle GMM Loading 474 if (_gmmLoadSlot != -1) { 475 476 // Hide mouse cursor and fade screen 477 _mouse->hideMouse(); 478 _screen->fadeDown(); 479 480 // Clean up and load game 481 _logic->_router->freeAllRouteMem(); 482 483 // TODO: manage error handling 484 restoreGame(_gmmLoadSlot); 485 486 // Reset load slot 487 _gmmLoadSlot = -1; 488 489 // Show mouse 490 _mouse->addHuman(); 491 } 492 468 493 KeyboardEvent *ke = keyboardEvent(); 469 494 470 495 if (ke) { … … 805 830 return _system->getMillis(); 806 831 } 807 832 833 Common::Error Sword2Engine::saveGameState(int slot, const char *desc) { 834 uint32 saveVal = saveGame(slot, (byte *)desc); 835 836 if (saveVal == SR_OK) 837 return Common::kNoError; 838 else if (saveVal == SR_ERR_WRITEFAIL || saveVal == SR_ERR_FILEOPEN) 839 return Common::kWritingFailed; 840 else 841 return Common::kUnknownError; 842 } 843 844 bool Sword2Engine::canSaveGameStateCurrently() { 845 bool canSave = true; 846 847 // No save if dead 848 if (_logic->readVar(DEAD)) 849 canSave = false; 850 851 // No save if mouse not shown 852 else if (_mouse->getMouseStatus()) 853 canSave = false; 854 // No save if inside a menu 855 else if (_mouse->getMouseMode() == MOUSE_system_menu) 856 canSave = false; 857 858 // No save if fading 859 else if (_screen->getFadeStatus()) 860 canSave = false; 861 862 return canSave; 863 } 864 865 Common::Error Sword2Engine::loadGameState(int slot) { 866 867 // Prepare the game to load through GMM 868 _gmmLoadSlot = slot; 869 870 // TODO: error handling. 871 return Common::kNoError; 872 } 873 874 bool Sword2Engine::canLoadGameStateCurrently() { 875 bool canLoad = true; 876 877 // No load if mouse is disabled 878 if (_mouse->getMouseStatus()) 879 canLoad = false; 880 // No load if mouse is in system menu 881 else if (_mouse->getMouseMode() == MOUSE_system_menu) 882 canLoad = false; 883 // No load if we are fading 884 else if (_screen->getFadeStatus()) 885 canLoad = false; 886 887 // But if we are dead, ignore previous conditions 888 if (_logic->readVar(DEAD)) 889 canLoad = true; 890 891 return canLoad; 892 } 893 808 894 } // End of namespace Sword2 -
scummvm-bs2psx/engines/sword2/music.cpp
40 40 #include "sound/flac.h" 41 41 #include "sound/rate.h" 42 42 #include "sound/wave.h" 43 #include "sound/vag.h" 43 44 44 45 #include "sword2/sword2.h" 45 46 #include "sword2/defs.h" … … 83 84 } 84 85 85 86 static Audio::AudioStream *makeCLUStream(Common::File *fp, int size); 87 static Audio::AudioStream *makePSXCLUStream(Common::File *fp, int size); 86 88 87 89 static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, int cd, uint32 id, uint32 *numSamples) { 88 90 bool alreadyOpen; … … 189 191 190 192 switch (fh->fileType) { 191 193 case kCLUMode: 192 return makeCLUStream(&fh->file, enc_len); 194 if (Sword2Engine::isPsx()) 195 return makePSXCLUStream(&fh->file, enc_len); 196 else 197 return makeCLUStream(&fh->file, enc_len); 193 198 #ifdef USE_MAD 194 199 case kMP3Mode: 195 200 tmp = new SafeSubReadStream(&fh->file, pos, pos + enc_len, false); … … 289 294 return new CLUInputStream(file, size); 290 295 } 291 296 297 Audio::AudioStream *makePSXCLUStream(Common::File *file, int size) { 298 299 // Buffer audio file data, and ask MemoryReadStream to dispose of it 300 // when not needed anymore. 301 302 byte *buffer = (byte *)malloc(size); 303 file->read(buffer, size); 304 return new Audio::VagStream(new Common::MemoryReadStream(buffer, size, true)); 305 } 306 292 307 // ---------------------------------------------------------------------------- 293 308 // Another custom AudioStream class, to wrap around the various AudioStream 294 309 // classes used for music decompression, and to add looping, fading, etc. -
scummvm-bs2psx/engines/sword2/maketext.cpp
59 59 #define MAX_LINES 30 // max character lines in output sprite 60 60 61 61 #define BORDER_COL 200 // source colour for character border (only 62 // needed for remapping colours) 62 // needed for remapping colours) 63 63 64 #define LETTER_COL 193 // source colour for bulk of character ( " ) 65 #define LETTER_COL_PSX1 33 66 #define LETTER_COL_PSX2 34 64 67 #define SPACE ' ' 65 68 #define FIRST_CHAR SPACE // first character in character set 66 69 #define LAST_CHAR 255 // last character in character set … … 91 94 // of the resource. 92 95 93 96 if (fontRes == _vm->_speechFontId) { 94 _lineSpacing = -6; 97 if (Sword2Engine::isPsx()) 98 _lineSpacing = -4; // Text would be unreadable with psx font if linespacing is higher 99 else 100 _lineSpacing = -6; 95 101 _charSpacing = -3; 96 102 } else if (fontRes == CONSOLE_FONT_ID) { 97 103 _lineSpacing = 0; … … 214 220 if (line[i].width > spriteWidth) 215 221 spriteWidth = line[i].width; 216 222 223 224 // Check that text sprite has even horizontal resolution in PSX version 225 // (needed to work around a problem in some sprites, which reports an odd 226 // number as horiz resolution, but then have the next even number as true width) 227 if (Sword2Engine::isPsx()) 228 spriteWidth = (spriteWidth % 2) ? spriteWidth + 1 : spriteWidth; 229 217 230 // Find the total height of the text sprite: the total height of the 218 231 // text lines, plus the total height of the spacing between them. 219 232 … … 234 247 frame_head.width = spriteWidth; 235 248 frame_head.height = spriteHeight; 236 249 250 // Normally for PSX frame header we double the height 251 // of the sprite artificially to regain correct aspect 252 // ratio, but this is an "artificially generated" text 253 // sprite, which gets created with correct aspect, so 254 // fix the height. 255 if (Sword2Engine::isPsx()) 256 frame_head.height /= 2; 257 237 258 frame_head.write(textSprite); 238 259 239 260 debug(4, "Text sprite size: %ux%u", spriteWidth, spriteHeight); … … 264 285 265 286 assert(frame_head.height == char_height); 266 287 copyChar(charPtr, spritePtr, spriteWidth, pen); 288 289 // We must remember to free memory for generated character in psx, 290 // as it is extracted differently than pc version (copyed from a 291 // char atlas). 292 if (Sword2Engine::isPsx()) 293 free(charPtr); 294 267 295 spritePtr += frame_head.width + _charSpacing; 268 296 } 269 297 270 298 // Skip space at end of last word in this line 271 299 pos++; 272 273 linePtr += (char_height + _lineSpacing) * spriteWidth; 300 301 if (Sword2Engine::isPsx()) 302 linePtr += (char_height / 2 + _lineSpacing) * spriteWidth; 303 else 304 linePtr += (char_height + _lineSpacing) * spriteWidth; 274 305 } 275 306 276 307 _vm->_resman->closeResource(fontRes); … … 286 317 287 318 uint16 FontRenderer::charWidth(byte ch, uint32 fontRes) { 288 319 byte *charSet = _vm->_resman->openResource(fontRes); 320 byte *charBuf; 289 321 290 322 FrameHeader frame_head; 291 323 292 frame_head.read(findChar(ch, charSet)); 324 charBuf = findChar(ch, charSet); 325 326 frame_head.read(charBuf); 327 328 if(Sword2Engine::isPsx()) 329 free(charBuf); 330 293 331 _vm->_resman->closeResource(fontRes); 294 332 295 333 return frame_head.width; … … 307 345 308 346 uint16 FontRenderer::charHeight(uint32 fontRes) { 309 347 byte *charSet = _vm->_resman->openResource(fontRes); 348 byte *charbuf; 310 349 311 350 FrameHeader frame_head; 312 351 313 frame_head.read(findChar(FIRST_CHAR, charSet)); 352 charbuf = findChar(FIRST_CHAR, charSet); 353 354 frame_head.read(charbuf); 355 356 if(Sword2Engine::isPsx()) 357 free(charbuf); 358 314 359 _vm->_resman->closeResource(fontRes); 315 360 316 361 return frame_head.height; … … 324 369 */ 325 370 326 371 byte *FontRenderer::findChar(byte ch, byte *charSet) { 327 if (ch < FIRST_CHAR) 328 ch = DUD; 329 return _vm->fetchFrameHeader(charSet, ch - FIRST_CHAR); 372 373 // PSX version doesn't use an animation table to keep all letters, 374 // instead a big sprite (char atlas) is used, and the single char 375 // must be extracted from that. 376 377 if (Sword2Engine::isPsx()) { 378 byte *buffer; 379 PSXFontEntry header; 380 FrameHeader bogusHeader; 381 382 charSet += ResHeader::size() + 2; 383 384 if (ch < FIRST_CHAR) 385 ch = DUD; 386 387 // Read font entry of the corresponding char. 388 header.read(charSet + PSXFontEntry::size() * (ch - 32)); 389 390 // We have no such character, generate an empty one 391 // on the fly, size 6x12. 392 if (header.charWidth == 0) { 393 394 // Prepare a "bogus" FrameHeader to be returned with 395 // "empty" character data. 396 bogusHeader.compSize = 0; 397 bogusHeader.width = 6; 398 bogusHeader.height = 12; 399 400 buffer = (byte *)malloc(24 * 3 + FrameHeader::size()); 401 memset(buffer, 0, 24 * 3 + FrameHeader::size()); 402 bogusHeader.write(buffer); 403 404 return buffer; 405 } 406 407 buffer = (byte *)malloc(FrameHeader::size() + header.charWidth * header.charHeight * 4); 408 byte *tempchar = (byte *)malloc(header.charWidth * header.charHeight); 409 410 // Prepare the "bogus" header to be returned with character 411 bogusHeader.compSize = 0; 412 bogusHeader.width = header.charWidth * 2; 413 bogusHeader.height = header.charHeight; 414 415 // Go to the beginning of char atlas 416 charSet += 2062; 417 418 memset(buffer, 0, FrameHeader::size() + header.charWidth * header.charHeight * 4); 419 420 bogusHeader.write(buffer); 421 422 // Copy and stretch the char into destination buffer 423 for (int idx = 0; idx < header.charHeight; idx++) { 424 memcpy(tempchar + header.charWidth * idx, charSet + header.offset + 128 * (header.skipLines + idx), header.charWidth); 425 } 426 427 for (int line = 0; line < header.charHeight; line++) { 428 for (int col = 0; col < header.charWidth; col++) { 429 *(buffer + FrameHeader::size() + line * bogusHeader.width + col * 2) = *(tempchar + line * header.charWidth + col); 430 *(buffer + FrameHeader::size() + line * bogusHeader.width + col * 2 + 1) = *(tempchar + line * header.charWidth + col); 431 } 432 } 433 434 free(tempchar); 435 436 return buffer; 437 438 } else { 439 if (ch < FIRST_CHAR) 440 ch = DUD; 441 return _vm->fetchFrameHeader(charSet, ch - FIRST_CHAR); 442 } 330 443 } 331 444 332 445 /** … … 354 467 // Use the specified colours 355 468 for (uint j = 0; j < frame.width; j++) { 356 469 switch (*source++) { 470 case 0: 471 // Do nothing if source pixel is zero, 472 // ie. transparent 473 break; 474 case LETTER_COL_PSX1: // Values for colored zone 475 case LETTER_COL_PSX2: 357 476 case LETTER_COL: 358 477 *dest = pen; 359 478 break; 360 479 case BORDER_COL: 480 default: 361 481 // Don't do a border pixel if there's 362 482 // already a bit of another character 363 483 // underneath (for overlapping!) 364 484 if (!*dest) 365 485 *dest = _borderPen; 366 486 break; 367 default:368 // Do nothing if source pixel is zero,369 // ie. transparent370 break;371 487 } 372 488 dest++; 373 489 } … … 400 516 assert(i < MAX_text_blocs); 401 517 402 518 // Create and position the sprite 403 519 404 520 _blocList[i].text_mem = makeTextSprite(ascii, width, pen, fontRes); 405 521 406 522 // 'NO_JUSTIFICATION' means print sprite with top-left at (x,y) … … 498 614 spriteInfo.blend = 0; 499 615 spriteInfo.data = _blocList[i].text_mem + FrameHeader::size(); 500 616 spriteInfo.colourTable = 0; 617 spriteInfo.isText = true; 501 618 502 619 uint32 rv = _vm->_screen->drawSprite(&spriteInfo); 503 620 if (rv) -
scummvm-bs2psx/engines/sword2/screen.h
173 173 uint16 blend; // holds the blending values. 174 174 byte *data; // pointer to the sprite data 175 175 byte *colourTable; // pointer to 16-byte colour table, only applicable to 16-col compression type 176 bool isText; // It is a engine-generated sprite containing text 176 177 }; 177 178 178 179 struct BlockSurface { … … 214 215 // positions, etc. 215 216 216 217 ScreenInfo _thisScreen; 217 218 218 219 int32 _renderCaps; 219 220 int8 _renderLevel; 220 221 … … 330 331 331 332 void mirrorSprite(byte *dst, byte *src, int16 w, int16 h); 332 333 int32 decompressRLE256(byte *dst, byte *src, int32 decompSize); 333 void unwindRaw16(byte *dst, byte *src, uint 8blockSize, byte *colTable);334 void unwindRaw16(byte *dst, byte *src, uint16 blockSize, byte *colTable); 334 335 int32 decompressRLE16(byte *dst, byte *src, int32 decompSize, byte *colTable); 335 336 void renderParallax(byte *ptr, int16 layer); 336 337 338 337 339 void markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1); 338 340 339 341 uint8 _xBlocks[MAXLAYERS]; 340 342 uint8 _yBlocks[MAXLAYERS]; 341 343 344 // This is used to cache PSX backgrounds and parallaxes 345 // data, as they are kept in a file unmanageable from 346 // resource manager. These gets freed everytime an user 347 // exits from a room. 348 byte *_psxScrCache[3]; 349 bool _psxCacheEnabled[3]; 350 342 351 // An array of sub-blocks, one for each of the parallax layers. 343 352 344 353 BlockSurface **_blockSurfaces[MAXLAYERS]; … … 396 405 397 406 void setLocationMetrics(uint16 w, uint16 h); 398 407 int32 initialiseBackgroundLayer(byte *parallax); 408 int32 initialisePsxParallaxLayer(byte *parallax); // These are used to initialize psx backgrounds and 409 int32 initialisePsxBackgroundLayer(byte *parallax); // parallaxes, which are different from pc counterparts. 399 410 void closeBackgroundLayer(); 400 411 401 412 void initialiseRenderCycle(); 402 413 403 414 void initBackground(int32 res, int32 new_palette); 415 void initPsxBackground(int32 res, int32 new_palette); 404 416 void registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega); 405 417 406 418 void setScrollFraction(uint8 f) { _scrollFraction = f; } … … 446 458 447 459 void rollCredits(); 448 460 void splashScreen(); 461 462 // Some sprites are compressed in HIF format 463 static uint32 decompressHIF(byte *src, byte *dst, uint32 *skipData = NULL); 464 // This is used to resize psx sprites back to original resolution 465 static void resizePsxSprite(byte *dst, byte *src, uint16 destW, uint16 destH); 466 // Some sprites are divided into 254 pixel wide stripes, this recomposes them 467 // and generates a "normal" sprite. 468 static void recomposePsxSprite(SpriteInfo *s); 469 static void recomposeCompPsxSprite(SpriteInfo *s); 470 471 // These functions manage the PSX screen cache 472 void setPsxScrCache(byte *psxScrCache, uint8 level); 473 byte *getPsxScrCache(uint8 level); 474 bool getPsxScrCacheStatus(uint8 level); 475 void flushPsxScrCache(); 476 449 477 }; 450 478 451 479 } // End of namespace Sword2 -
scummvm-bs2psx/engines/sword2/mouse.cpp
280 280 281 281 int Mouse::menuClick(int menu_items) { 282 282 int x = getX(); 283 byte menuIconWidth; 283 284 285 if (Sword2Engine::isPsx()) 286 menuIconWidth = RDMENU_PSXICONWIDE; 287 else 288 menuIconWidth = RDMENU_ICONWIDE; 289 290 284 291 if (x < RDMENU_ICONSTART) 285 292 return -1; 286 293 287 if (x > RDMENU_ICONSTART + menu_items * ( RDMENU_ICONWIDE+ RDMENU_ICONSPACING) - RDMENU_ICONSPACING)294 if (x > RDMENU_ICONSTART + menu_items * (menuIconWidth + RDMENU_ICONSPACING) - RDMENU_ICONSPACING) 288 295 return -1; 289 296 290 return (x - RDMENU_ICONSTART) / ( RDMENU_ICONWIDE+ RDMENU_ICONSPACING);297 return (x - RDMENU_ICONSTART) / (menuIconWidth + RDMENU_ICONSPACING); 291 298 } 292 299 293 300 void Mouse::systemMenuMouse() { … … 330 337 if (hit < 0) 331 338 return; 332 339 340 // Do nothing if using PSX version and are on TOP menu. 341 342 if ((icon_list[hit] == OPTIONS_ICON || icon_list[hit] == QUIT_ICON 343 || icon_list[hit] == SAVE_ICON || icon_list[hit] == RESTORE_ICON 344 || icon_list[hit] == RESTART_ICON ) && Sword2Engine::isPsx() ) 345 return; 346 333 347 // No save when dead 334 348 335 349 if (icon_list[hit] == SAVE_ICON && _vm->_logic->readVar(DEAD)) … … 857 871 // Unlike the other mouse "engines", this one is called directly by the 858 872 // fnChoose() opcode. 859 873 874 byte menuIconWidth; 875 876 if (Sword2Engine::isPsx()) 877 menuIconWidth = RDMENU_PSXICONWIDE; 878 else 879 menuIconWidth = RDMENU_ICONWIDE; 880 881 860 882 uint i; 861 883 862 884 _vm->_logic->writeVar(AUTO_SELECTED, 0); … … 912 934 error("fnChoose with no subjects"); 913 935 914 936 for (i = 0; i < in_subject; i++) { 915 icon = _vm->_resman->openResource(_subjectList[i].res) + ResHeader::size() + RDMENU_ICONWIDE* RDMENU_ICONDEEP;937 icon = _vm->_resman->openResource(_subjectList[i].res) + ResHeader::size() + menuIconWidth * RDMENU_ICONDEEP; 916 938 setMenuIcon(RDMENU_BOTTOM, i, icon); 917 939 _vm->_resman->closeResource(_subjectList[i].res); 918 940 } … … 1485 1507 int x = 0; 1486 1508 int y = 0; 1487 1509 1488 comp = comp + READ_LE_UINT32(comp + frame * 4) - MOUSE_ANIM_HEADER_SIZE; 1510 if (Sword2Engine::isPsx()) { 1511 comp = comp + READ_LE_UINT32(comp + 2 + frame * 4) - MOUSE_ANIM_HEADER_SIZE; 1489 1512 1490 while (i < size) { 1491 if (*comp > 183) { 1492 decomp[(y + yOff) * pitch + x + xOff] = *comp++; 1493 if (++x >= width) { 1494 x = 0; 1495 y++; 1513 yOff /= 2; // Without this, distance of object from cursor is too big. 1514 1515 byte *buffer; 1516 1517 buffer = (byte *)malloc(size); 1518 Screen::decompressHIF(comp, buffer); 1519 1520 for (int line = 0; line < height; line++) { 1521 memcpy(decomp + (line + yOff) * pitch + xOff, buffer + line * width, width); 1522 } 1523 1524 free(buffer); 1525 1526 } else { 1527 comp = comp + READ_LE_UINT32(comp + frame * 4) - MOUSE_ANIM_HEADER_SIZE; 1528 1529 while (i < size) { 1530 if (*comp > 183) { 1531 decomp[(y + yOff) * pitch + x + xOff] = *comp++; 1532 if (++x >= width) { 1533 x = 0; 1534 y++; 1535 } 1536 i++; 1537 } else { 1538 x += *comp; 1539 while (x >= width) { 1540 y++; 1541 x -= width; 1542 } 1543 i += *comp++; 1496 1544 } 1497 i++;1498 } else {1499 x += *comp;1500 while (x >= width) {1501 y++;1502 x -= width;1503 }1504 i += *comp++;1505 1545 } 1506 1546 } 1507 1547 } … … 1563 1603 decompressMouse(mouseData, _mouseAnim.data, _mouseFrame, 1564 1604 _mouseAnim.mousew, _mouseAnim.mouseh, mouse_width); 1565 1605 1606 // Fix height for mouse sprite in PSX version 1607 if (Sword2Engine::isPsx()) { 1608 mouse_height *= 2; 1609 1610 byte *buffer = (byte *)malloc(mouse_width * mouse_height); 1611 Screen::resizePsxSprite(buffer, mouseData, mouse_width, mouse_height); 1612 1613 free(mouseData); 1614 mouseData = buffer; 1615 } 1616 1566 1617 CursorMan.replaceCursor(mouseData, mouse_width, mouse_height, hotspot_x, hotspot_y, 0); 1567 1618 1568 1619 free(mouseData); … … 1675 1726 return RD_OK; 1676 1727 } 1677 1728 1729 int Mouse::getMouseMode() { 1730 return _mouseMode; 1731 } 1732 1733 void Mouse::setMouseMode(int mouseMode) { 1734 _mouseMode = mouseMode; 1735 } 1736 1678 1737 } // End of namespace Sword2 -
scummvm-bs2psx/engines/sword2/resman.h
64 64 void removeFromCacheList(Resource *res); 65 65 void addToCacheList(Resource *res); 66 66 void checkMemUsage(); 67 67 68 68 Sword2Engine *_vm; 69 69 70 70 int _curCD; … … 96 96 97 97 bool checkValid(uint32 res); 98 98 uint32 fetchLen(uint32 res); 99 uint8 fetchType(byte *ptr); 99 100 uint8 fetchType(uint32 res) { 100 101 byte *ptr = openResource(res); 101 uint8 type = ptr[0];102 uint8 type = fetchType(ptr); 102 103 closeResource(res); 103 104 104 105 return type; 105 106 } 106 107 107 uint8 fetchType(byte *ptr) {108 return ptr[0];109 }110 111 108 byte *fetchName(uint32 res, byte *buf = NULL) { 112 109 static byte tempbuf[NAME_LEN]; 113 110 -
scummvm-bs2psx/engines/sword2/sound.h
231 231 int readBuffer(int16 *buffer, const int numSamples); 232 232 bool isStereo() const { return false; } 233 233 bool endOfData() const; 234 int getRate() const { return 22050; }234 int getRate() const { return Sword2Engine::isPsx() ? 11025 : 22050; } 235 235 236 236 // End of AudioStream API 237 237 -
scummvm-bs2psx/engines/sword2/palette.cpp
48 48 49 49 byte *screenFile = _vm->_resman->openResource(_thisScreen.background_layer_id); 50 50 51 memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(screenFile), PALTABLESIZE); 51 // Don't fetch palette match table while using PSX version, 52 // because it is not present. 53 if(!Sword2Engine::isPsx()) 54 memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(screenFile), PALTABLESIZE); 55 52 56 setPalette(0, 256, _vm->fetchPalette(screenFile), RDPAL_FADE); 53 57 54 58 // Indicating that it's a screen palette … … 116 120 } else { 117 121 if (_thisScreen.background_layer_id) { 118 122 byte *data = _vm->_resman->openResource(_thisScreen.background_layer_id); 119 memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(data), PALTABLESIZE); 123 124 // Do not fetch palette match table when using PSX version, 125 // because it is not present. 126 if (!Sword2Engine::isPsx()) 127 memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(data), PALTABLESIZE); 128 120 129 setPalette(0, 256, _vm->fetchPalette(data), RDPAL_INSTANT); 121 130 _vm->_resman->closeResource(_thisScreen.background_layer_id); 122 131 } else -
scummvm-bs2psx/engines/sword2/layers.cpp
179 179 } 180 180 181 181 // Background parallax layers 182 182 183 183 for (i = 0; i < 2; i++) { 184 184 if (screenLayerTable.bg_parallax[i]) 185 185 initialiseBackgroundLayer(_vm->fetchBackgroundParallaxLayer(file, i)); … … 188 188 } 189 189 190 190 // Normal backround layer 191 191 192 192 initialiseBackgroundLayer(_vm->fetchBackgroundLayer(file)); 193 193 194 194 // Foreground parallax layers 195 195 196 196 for (i = 0; i < 2; i++) { 197 197 if (screenLayerTable.fg_parallax[i]) 198 198 initialiseBackgroundLayer(_vm->fetchForegroundParallaxLayer(file, i)); … … 203 203 _vm->_resman->closeResource(_thisScreen.background_layer_id); 204 204 } 205 205 206 /** 207 * This function is called when entering a new room, PSX edition 208 * @param res resource id of the normal background layer 209 * @param new_palette 1 for new palette, otherwise 0 210 */ 211 212 void Screen::initPsxBackground(int32 res, int32 new_palette) { 213 int i; 214 215 assert(res); 216 217 _vm->_sound->clearFxQueue(false); 218 waitForFade(); 219 220 debug(1, "CHANGED TO LOCATION \"%s\"", _vm->_resman->fetchName(res)); 221 222 _vm->_logic->writeVar(EXIT_CLICK_ID, 0); 223 224 // Close the previous screen, if one is open 225 if (_thisScreen.background_layer_id) 226 closeBackgroundLayer(); 227 228 _thisScreen.background_layer_id = res; 229 _thisScreen.new_palette = new_palette; 230 231 // ok, now read the resource and pull out all the normal sort layer 232 // info/and set them up at the beginning of the sort list - why do it 233 // each cycle 234 235 byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id); 236 ScreenHeader screen_head; 237 238 screen_head.read(_vm->fetchScreenHeader(file)); 239 screen_head.height *= 2; 240 241 // set number of special sort layers 242 _thisScreen.number_of_layers = screen_head.noLayers; 243 _thisScreen.screen_wide = screen_head.width; 244 _thisScreen.screen_deep = screen_head.height; 245 246 debug(2, "layers=%d width=%d depth=%d", screen_head.noLayers, screen_head.width, screen_head.height); 247 248 // initialise the driver back buffer 249 setLocationMetrics(screen_head.width, screen_head.height); 250 251 for (i = 0; i < screen_head.noLayers; i++) { 252 debug(3, "init layer %d", i); 253 254 LayerHeader layer; 255 256 layer.read(_vm->fetchLayerHeader(file, i)); 257 _sortList[i].layer_number = i + 1; 258 _sortList[i].sort_y = layer.y + layer.height; 259 } 260 261 // reset scroll offsets 262 _thisScreen.scroll_offset_x = 0; 263 _thisScreen.scroll_offset_y = 0; 264 265 if (screen_head.width > _screenWide || screen_head.height > _screenDeep) { 266 _thisScreen.scroll_flag = 2; 267 268 _thisScreen.max_scroll_offset_x = screen_head.width - _screenWide; 269 _thisScreen.max_scroll_offset_y = screen_head.height - (_screenDeep - (MENUDEEP * 2)); 270 } else { 271 // The later fits on the phyiscal screen. Switch off scrolling. 272 _thisScreen.scroll_flag = 0; 273 } 274 275 resetRenderEngine(); 276 277 // These are the physical screen coords where the system will try to 278 // maintain George's actual feet coords. 279 280 _thisScreen.feet_x = 320; 281 _thisScreen.feet_y = 340; 282 283 // Background parallax layers 284 initialisePsxParallaxLayer(_vm->fetchBackgroundParallaxLayer(file, 0)); 285 initialisePsxParallaxLayer(NULL); 286 287 // Normal backround layer 288 initialisePsxBackgroundLayer(_vm->fetchBackgroundLayer(file)); 289 290 // Foreground parallax layers 291 initialisePsxParallaxLayer(_vm->fetchForegroundParallaxLayer(file, 1)); 292 initialisePsxParallaxLayer(NULL); 293 294 _vm->_resman->closeResource(_thisScreen.background_layer_id); 295 296 } 297 206 298 } // End of namespace Sword2 -
scummvm-bs2psx/engines/sword2/console.cpp
274 274 275 275 bool Debugger::Cmd_ResList(int argc, const char **argv) { 276 276 // By default, list only resources that are being held open. 277 uint minCount = 1;277 uint32 minCount = 1; 278 278 279 279 if (argc > 1) 280 280 minCount = atoi(argv[1]); -
scummvm-bs2psx/engines/sword2/logic.h
314 314 void resetKillList(); 315 315 316 316 void pauseMovie(bool pause); 317 318 // Read location number from script vars 319 uint32 getLocationNum(); 317 320 }; 318 321 319 322 } // End of namespace Sword2 -
scummvm-bs2psx/engines/sword2/sprite.cpp
25 25 * $Id$ 26 26 */ 27 27 28 #include "common/endian.h" 28 29 29 30 30 #include "sword2/sword2.h" 31 31 #include "sword2/defs.h" 32 32 #include "sword2/screen.h" … … 138 138 * Unwinds a run of 16-colour data into 256-colour palette data. 139 139 */ 140 140 141 void Screen::unwindRaw16(byte *dst, byte *src, uint 8blockSize, byte *colTable) {141 void Screen::unwindRaw16(byte *dst, byte *src, uint16 blockSize, byte *colTable) { 142 142 // for each pair of pixels 143 143 while (blockSize > 1) { 144 // 1st colour = number in table at position given by upper 145 // nibble of source byte 146 *dst++ = colTable[(*src) >> 4]; 144 145 if (Sword2Engine::isPsx()) { 146 // 1st colour = number in table at position given by upper 147 // nibble of source byte 148 *dst++ = colTable[(*src) & 0x0f]; 147 149 148 // 2nd colour = number in table at position given by lower 149 // nibble of source byte 150 *dst++ = colTable[(*src) & 0x0f]; 150 // 2nd colour = number in table at position given by lower 151 // nibble of source byte 152 *dst++ = colTable[(*src) >> 4]; 153 } else { 154 *dst++ = colTable[(*src) >> 4]; 155 *dst++ = colTable[(*src) & 0x0f]; 156 } 151 157 158 152 159 // point to next source byte 153 160 src++; 154 161 … … 245 252 } 246 253 247 254 /** 255 * This function takes a compressed HIF image and decompresses it. 256 * Used for PSX version sprites. 257 * @param dst destination buffer 258 * @param src source buffer 259 * @param skipData if pointer != NULL, value of pointed var 260 * is set to number of bytes composing the compressed data. 261 */ 262 263 uint32 Screen::decompressHIF(byte *src, byte *dst, uint32 *skipData) { 264 uint32 decompSize = 0; 265 uint32 readByte = 0; 266 267 for (;;) { // Main loop 268 byte control_byte = *src++; 269 readByte++; 270 uint32 byte_count = 0; 271 while (byte_count < 8) { 272 if (control_byte & 0x80) { 273 uint16 info_word = READ_BE_UINT16(src); // Read the info word 274 src += 2; 275 readByte += 2; 276 if (info_word == 0xFFFF) { // Got 0xFFFF code, finished. 277 if (skipData != NULL) *(skipData) = readByte; 278 return decompSize; 279 } 280 281 int32 repeat_count = (info_word >> 12) + 2; // How many time data needs to be refetched 282 while(repeat_count >= 0) { 283 uint16 refetchData = (info_word & 0xFFF) + 1; 284 if (refetchData > decompSize) return 0; // We have a problem here... 285 uint8 *old_data_src = dst - refetchData; 286 *dst++ = *old_data_src; 287 decompSize++; 288 repeat_count--; 289 } 290 } else { 291 *dst++ = *src++; 292 readByte++; 293 decompSize++; 294 } 295 byte_count++; 296 control_byte <<= 1; // Shifting left the control code one bit 297 } 298 } 299 } 300 301 // Double line image to keep aspect ratio. 302 // Used in PSX version. 303 void Screen::resizePsxSprite(byte *dst, byte *src, uint16 destW, uint16 destH) { 304 for (int i = 0; i < destH / 2; i++) { 305 memcpy(dst + i * destW * 2, src + i * destW, destW); 306 memcpy(dst + i * destW * 2 + destW, src + i * destW, destW); 307 } 308 } 309 310 // Sprites wider than 254px in PSX version are divided 311 // into slices, this recomposes the image. 312 void Screen::recomposePsxSprite(SpriteInfo *s) { 313 if (!s) 314 return; 315 316 uint16 noStripes = (s->w / 254) + ((s->w % 254) ? 1 : 0); 317 uint16 lastStripeSize = (s->w % 254) ? s->w % 254 : 254; 318 byte *buffer = (byte *)malloc(s->w * s->h / 2); 319 320 memset(buffer, 0, s->w * s->h / 2); 321 322 for (int idx = 0; idx < noStripes; idx++) { 323 uint16 stripeSize = (idx == noStripes - 1) ? lastStripeSize : 254; 324 for (int line = 0; line < s->h / 2; line++) { 325 memcpy(buffer + idx * 254 + line * s->w, s->data, stripeSize); 326 s->data += stripeSize; 327 } 328 } 329 330 s->data = buffer; 331 332 } 333 334 // Recomposes sprites wider than 254 pixels but also 335 // compressed with HIF. 336 // Used in PSX version. 337 void Screen::recomposeCompPsxSprite(SpriteInfo *s) { 338 if (!s) 339 return; 340 341 uint16 noStripes = (s->w / 254) + ((s->w % 254) ? 1 : 0); 342 uint16 lastStripeSize = (s->w % 254) ? s->w % 254 : 254; 343 byte *buffer = (byte *)malloc(s->w * s->h / 2); 344 byte *stripeBuffer = (byte *)malloc(254 * s->h);; 345 346 memset(buffer, 0, s->w * s->h / 2); 347 uint32 skipData = 0; 348 uint32 compBytes = 0; 349 350 for (int idx = 0; idx < noStripes; idx++) { 351 uint16 stripeSize = (idx == noStripes - 1) ? lastStripeSize : 254; 352 353 decompressHIF((s->data) + skipData, stripeBuffer, &compBytes); 354 skipData += compBytes; 355 356 for (int line = 0; line < s->h / 2; line++) { 357 memcpy(buffer + idx * 254 + line * s->w, stripeBuffer + line * stripeSize, stripeSize); 358 } 359 } 360 361 free(stripeBuffer); 362 s->data = buffer; 363 364 } 365 366 /** 248 367 * Creates a sprite surface. Sprite surfaces are used by the in-game dialogs 249 368 * and for displaying cutscene subtitles, which makes them much easier to draw 250 369 * than standard sprites. … … 378 497 // ----------------------------------------------------------------- 379 498 // Decompression and mirroring 380 499 // ----------------------------------------------------------------- 500 if (s->type & RDSPR_NOCOMPRESSION) { 501 if(Sword2Engine::isPsx()) { // PSX Uncompressed sprites 502 if (s->w > 254 && !s->isText) { // We need to recompose these frames 503 recomposePsxSprite(s); 504 } 381 505 382 if (s->type & RDSPR_NOCOMPRESSION) 383 sprite = s->data; 384 else { 385 sprite = (byte *)malloc(s->w * s->h); 506 freeSprite = true; 507 byte *tempBuf = (byte *)malloc(s->w * s->h * 2); 508 memset(tempBuf, 0, s->w * s->h * 2); 509 resizePsxSprite(tempBuf, s->data, s->w, s->h); 510 511 if (s->w > 254 && !s->isText) { 512 free(s->data); 513 } 514 515 sprite = tempBuf; 516 } else { // PC Uncompressed sprites 517 sprite = s->data; 518 } 519 } else { 386 520 freeSprite = true; 387 if (!sprite) 388 return RDERR_OUTOFMEMORY; 521 389 522 if ((s->type & 0xff00) == RDSPR_RLE16) { 390 if (decompressRLE16(sprite, s->data, s->w * s->h, s->colourTable)) { 391 free(sprite); 392 return RDERR_DECOMPRESSION; 523 if (Sword2Engine::isPsx()) { // PSX HIF16 sprites 524 uint32 decompData; 525 byte *tempBuf = (byte *)malloc(s->w * s->h); 526 memset(tempBuf, 0, s->w * s->h); 527 528 decompData = decompressHIF(s->data, tempBuf); 529 530 s->w = (decompData / (s->h / 2)) * 2; 531 byte *tempBuf2 = (byte *)malloc(s->w * s->h * 10); 532 memset(tempBuf2, 0, s->w * s->h * 2); 533 534 unwindRaw16(tempBuf2, tempBuf, (s->w * (s->h / 2)), s->colourTable); 535 sprite = (byte *)malloc(s->w * s->h); 536 537 if (!sprite) 538 return RDERR_OUTOFMEMORY; 539 540 resizePsxSprite(sprite, tempBuf2, s->w, s->h); 541 542 free(tempBuf2); 543 free(tempBuf); 544 } else { // PC RLE16 sprites 545 sprite = (byte *)malloc(s->w * s->h); 546 547 if (!sprite) 548 return RDERR_OUTOFMEMORY; 549 550 if (decompressRLE16(sprite, s->data, s->w * s->h, s->colourTable)) { 551 free(sprite); 552 return RDERR_DECOMPRESSION; 553 } 393 554 } 394 555 } else { 395 if (decompressRLE256(sprite, s->data, s->w * s->h)) { 396 free(sprite); 397 return RDERR_DECOMPRESSION; 556 if (Sword2Engine::isPsx()) { // PSX HIF256 sprites 557 if (s->w > 255) { 558 sprite = (byte *)malloc(s->w * s->h); 559 recomposeCompPsxSprite(s); 560 resizePsxSprite(sprite, s->data, s->w, s->h); 561 free(s->data); 562 } else { 563 byte *tempBuf = (byte *)malloc(s->w * s->h); 564 uint32 decompData = decompressHIF(s->data, tempBuf); 565 s->w = (decompData / (s->h / 2)); 566 sprite = (byte *)malloc(s->w * s->h); 567 568 if (!sprite) 569 return RDERR_OUTOFMEMORY; 570 571 resizePsxSprite(sprite, tempBuf, s->w, s->h); 572 free(tempBuf); 573 } 574 } else { // PC RLE256 sprites 575 sprite = (byte *)malloc(s->w * s->h); 576 577 if (!sprite) 578 return RDERR_OUTOFMEMORY; 579 580 if (decompressRLE256(sprite, s->data, s->w * s->h)) { 581 free(sprite); 582 return RDERR_DECOMPRESSION; 583 } 398 584 } 399 585 } 400 586 } … … 500 686 return RDERR_OUTOFMEMORY; 501 687 } 502 688 503 if (_renderCaps & RDBLTFX_EDGEBLEND) 689 // We cannot use good scaling for PSX version, as we are missing 690 // some required data. 691 if (_renderCaps & RDBLTFX_EDGEBLEND && !Sword2Engine::isPsx()) 504 692 scaleImageGood(newSprite, s->scaledWidth, s->scaledWidth, s->scaledHeight, sprite, s->w, s->w, s->h, _buffer + _screenWide * rd.top + rd.left); 505 693 else 506 694 scaleImageFast(newSprite, s->scaledWidth, s->scaledWidth, s->scaledHeight, sprite, s->w, s->w, s->h); … … 518 706 // The light mask is an optional layer that covers the entire room 519 707 // and which is used to simulate light and shadows. Scaled sprites 520 708 // (actors, presumably) are always affected. 709 // Light masking makes use of palette match table, so it's unavailable 710 // in PSX version. 521 711 522 if ((_renderCaps & RDBLTFX_SHADOWBLEND) && _lightMask && (scale != 256 || ( s->type & RDSPR_SHADOW))) {712 if ((_renderCaps & RDBLTFX_SHADOWBLEND) && _lightMask && (scale != 256 || ((s->type & RDSPR_SHADOW) && !Sword2Engine::isPsx()) )) { 523 713 byte *lightMap; 524 714 525 715 // Make sure that we never apply the shadow to the original … … 557 747 src = sprite + rs.top * srcPitch + rs.left; 558 748 dst = _buffer + _screenWide * rd.top + rd.left; 559 749 560 if (s->type & RDSPR_BLEND ) {750 if (s->type & RDSPR_BLEND && !Sword2Engine::isPsx()) { // Blending is unavailable in PSX version 561 751 // The original code had two different blending cases. One for 562 752 // s->blend & 0x01 and one for s->blend & 0x02. However, the 563 753 // only values that actually appear in the cluster files are … … 639 829 if (!_lightMask) 640 830 return RDERR_OUTOFMEMORY; 641 831 832 if (s->data == NULL) // Check, as there's no mask in psx version 833 return RDERR_NOTOPEN; 834 642 835 if (decompressRLE256(_lightMask, s->data, s->w * s->h)) 643 836 return RDERR_DECOMPRESSION; 644 837 -
scummvm-bs2psx/engines/sword2/anims.cpp
103 103 104 104 // point to anim header 105 105 anim_head.read(_vm->fetchAnimHeader(anim_file)); 106 106 107 107 // now running an anim, looping back to this call again 108 108 obLogic.setLooping(1); 109 109 obGraph.setAnimResource(animRes); -
scummvm-bs2psx/engines/sword2/icons.cpp
77 77 78 78 void Mouse::buildMenu() { 79 79 uint32 i, j; 80 byte menuIconWidth; 80 81 82 if (Sword2Engine::isPsx()) 83 menuIconWidth = RDMENU_PSXICONWIDE; 84 else 85 menuIconWidth = RDMENU_ICONWIDE; 86 81 87 // Clear the temporary inventory list, since we are going to build a 82 88 // new one from scratch. 83 89 … … 178 184 // greyed out one. 179 185 180 186 if (icon_coloured) 181 icon += ( RDMENU_ICONWIDE* RDMENU_ICONDEEP);187 icon += (menuIconWidth * RDMENU_ICONDEEP); 182 188 } 183 189 184 190 setMenuIcon(RDMENU_BOTTOM, i, icon); … … 203 209 RESTART_ICON 204 210 }; 205 211 212 byte menuIconWidth; 213 214 if (Sword2Engine::isPsx()) 215 menuIconWidth = RDMENU_PSXICONWIDE; 216 else 217 menuIconWidth = RDMENU_ICONWIDE; 218 206 219 // Build them all high in full colour - when one is clicked on all the 207 220 // rest will grey out. 208 221 … … 213 226 // is dead. Then SAVE is not available. 214 227 215 228 if (!_vm->_logic->readVar(DEAD) || icon_list[i] != SAVE_ICON) 216 icon += ( RDMENU_ICONWIDE* RDMENU_ICONDEEP);229 icon += (menuIconWidth * RDMENU_ICONDEEP); 217 230 218 231 setMenuIcon(RDMENU_TOP, i, icon); 219 232 _vm->_resman->closeResource(icon_list[i]); -
scummvm-bs2psx/engines/sword2/animation.cpp
35 35 #include "sword2/maketext.h" 36 36 #include "sword2/resman.h" 37 37 #include "sword2/sound.h" 38 #include "sword2/screen.h" 38 39 #include "sword2/animation.h" 39 40 40 41 #include "gui/message.h" … … 207 208 text->_textSprite.h = frame.height; 208 209 text->_textSprite.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION; 209 210 text->_textSprite.data = text->_textMem + FrameHeader::size(); 211 text->_textSprite.isText = true; 210 212 _vm->_screen->createSurface(&text->_textSprite, &_textSurface); 211 213 212 214 _textX = 320 - text->_textSprite.w / 2; … … 239 241 uint16 width = text->_textSprite.w; 240 242 uint16 height = text->_textSprite.h; 241 243 244 // Resize text sprites for PSX version 245 if (Sword2Engine::isPsx()) { 246 height *= 2; 247 byte *buffer = (byte *)malloc(width * height); 248 Screen::resizePsxSprite(buffer, src, width, height); 249 src = buffer; 250 } 251 242 252 byte *dst = screen + _textY * _decoder->getWidth() + _textX; 243 253 244 254 for (int y = 0; y < height; y++) { -
scummvm-bs2psx/engines/sword2/screen.cpp
76 76 _needFullRedraw = false; 77 77 78 78 memset(&_thisScreen, 0, sizeof(_thisScreen)); 79 79 80 80 _fps = 0; 81 81 _frameCount = 0; 82 82 _cycleTime = 0; … … 100 100 101 101 _pauseTicks = 0; 102 102 _pauseStartTick = 0; 103 104 // Clean the cache for PSX version SCREENS.CLU 105 _psxScrCache[0] = NULL; 106 _psxScrCache[1] = NULL; 107 _psxScrCache[2] = NULL; 108 _psxCacheEnabled[0] = true; 109 _psxCacheEnabled[1] = true; 110 _psxCacheEnabled[2] = true; 103 111 } 104 112 105 113 Screen::~Screen() { 114 flushPsxScrCache(); 106 115 free(_buffer); 107 116 free(_dirtyGrid); 108 117 closeBackgroundLayer(); … … 277 286 278 287 MultiScreenHeader screenLayerTable; 279 288 280 screenLayerTable.read(file + ResHeader::size()); 289 if (!Sword2Engine::isPsx()) // On PSX version, there would be nothing to read here 290 screenLayerTable.read(file + ResHeader::size()); 281 291 282 292 // Render at least one frame, but if the screen is scrolling, and if 283 293 // there is time left, we will render extra frames to smooth out the … … 285 295 286 296 do { 287 297 // first background parallax + related anims 288 if ( screenLayerTable.bg_parallax[0]) {298 if (Sword2Engine::isPsx() || screenLayerTable.bg_parallax[0]) { // No need to check on PSX version 289 299 renderParallax(_vm->fetchBackgroundParallaxLayer(file, 0), 0); 290 300 drawBackPar0Frames(); 291 301 } 292 302 293 303 // second background parallax + related anims 294 if ( screenLayerTable.bg_parallax[1]) {304 if (!Sword2Engine::isPsx() && screenLayerTable.bg_parallax[1]) { // Nothing here in PSX version 295 305 renderParallax(_vm->fetchBackgroundParallaxLayer(file, 1), 1); 296 306 drawBackPar1Frames(); 297 307 } … … 306 316 307 317 // first foreground parallax + related anims 308 318 309 if ( screenLayerTable.fg_parallax[0]) {319 if (Sword2Engine::isPsx() || screenLayerTable.fg_parallax[0]) { 310 320 renderParallax(_vm->fetchForegroundParallaxLayer(file, 0), 3); 311 321 drawForePar0Frames(); 312 322 } 313 323 314 324 // second foreground parallax + related anims 315 325 316 if ( screenLayerTable.fg_parallax[1]) {326 if (!Sword2Engine::isPsx() && screenLayerTable.fg_parallax[1]) { 317 327 renderParallax(_vm->fetchForegroundParallaxLayer(file, 1), 4); 318 328 drawForePar1Frames(); 319 329 } … … 333 343 } while (!endRenderCycle()); 334 344 335 345 _vm->_resman->closeResource(_thisScreen.background_layer_id); 346 336 347 } 337 348 338 349 /** … … 381 392 spriteInfo.blend = 0; 382 393 spriteInfo.data = text_spr + FrameHeader::size(); 383 394 spriteInfo.colourTable = 0; 395 spriteInfo.isText = true; 384 396 385 397 uint32 rv = drawSprite(&spriteInfo); 386 398 if (rv) … … 490 502 } 491 503 492 504 void Screen::processLayer(byte *file, uint32 layer_number) { 505 493 506 LayerHeader layer_head; 494 507 495 508 layer_head.read(_vm->fetchLayerHeader(file, layer_number)); … … 503 516 spriteInfo.scaledWidth = 0; 504 517 spriteInfo.scaledHeight = 0; 505 518 spriteInfo.h = layer_head.height; 506 spriteInfo.type = RDSPR_TRANS | RDSPR_RLE256FAST; 519 spriteInfo.isText = false; 520 521 // Layers are uncompressed in PSX version, RLE256 compressed 522 // in PC version. 523 if (Sword2Engine::isPsx()) { 524 spriteInfo.type = RDSPR_TRANS | RDSPR_NOCOMPRESSION; 525 spriteInfo.data = file + layer_head.offset; 526 } else { 527 spriteInfo.type = RDSPR_TRANS | RDSPR_RLE256FAST; 528 spriteInfo.data = file + ResHeader::size() + layer_head.offset; 529 } 530 507 531 spriteInfo.blend = 0; 508 spriteInfo.data = file + ResHeader::size() + layer_head.offset;509 532 spriteInfo.colourTable = 0; 510 533 511 534 // check for largest layer for debug info … … 575 598 // points to just after last cdt_entry, ie. 576 599 // start of colour table 577 600 colTablePtr = _vm->fetchAnimHeader(file) + AnimHeader::size() + anim_head.noAnimFrames * CdtEntry::size(); 601 if (Sword2Engine::isPsx()) 602 colTablePtr++; // There is one additional byte to skip before the table in psx version 578 603 break; 579 604 } 580 605 } … … 598 623 // points to just after frame header, ie. start of sprite data 599 624 spriteInfo.data = frame + FrameHeader::size(); 600 625 spriteInfo.colourTable = colTablePtr; 626 spriteInfo.isText = false; 601 627 602 628 // check for largest layer for debug info 603 629 uint32 current_sprite_area = frame_head.width * frame_head.height; … … 864 890 // that this is a coincidence, but let's use the image palette 865 891 // directly anyway, just to be safe. 866 892 // 867 // credits.clu - The credits text 893 // credits.clu - The credits text (credits.txt in PSX version) 868 894 // 869 895 // This is simply a text file with CRLF line endings. 870 896 // '^' is not shown, but used to mark the center of the line. … … 883 909 Common::File f; 884 910 int i; 885 911 912 spriteInfo.isText = false; 913 886 914 // Read the "Smacker" logo 887 915 888 916 uint16 logoWidth = 0; … … 925 953 int paragraphStart = 0; 926 954 bool hasCenterMark = false; 927 955 928 if (!f.open("credits.clu")) { 929 warning("Can't find credits.clu"); 930 return; 956 if (Sword2Engine::isPsx()) { 957 if (!f.open("credits.txt")) { 958 warning("Can't find credits.txt"); 959 return; 960 } 961 } else { 962 if (!f.open("credits.clu")) { 963 warning("Can't find credits.clu"); 964 return; 965 } 931 966 } 932 967 933 968 while (1) { … … 1088 1123 spriteInfo.w = frame.width; 1089 1124 spriteInfo.h = frame.height; 1090 1125 spriteInfo.data = creditsLines[i]->sprite + FrameHeader::size(); 1126 spriteInfo.isText = true; 1091 1127 1092 1128 switch (creditsLines[i]->type) { 1093 1129 case LINE_LEFT: … … 1214 1250 barSprite.blend = 0; 1215 1251 barSprite.colourTable = 0; 1216 1252 barSprite.data = frame + FrameHeader::size(); 1253 barSprite.isText = false; 1217 1254 1218 1255 drawSprite(&barSprite); 1219 1256 … … 1234 1271 waitForFade(); 1235 1272 } 1236 1273 1274 // Following functions are used to manage screen cache for psx version. 1275 1276 void Screen::setPsxScrCache(byte *psxScrCache, uint8 level) { 1277 if (level < 3) { 1278 if (psxScrCache) 1279 _psxCacheEnabled[level] = true; 1280 else 1281 _psxCacheEnabled[level] = false; 1282 1283 _psxScrCache[level] = psxScrCache; 1284 } 1285 } 1286 1287 byte *Screen::getPsxScrCache(uint8 level) { 1288 if (level > 3) { 1289 level = 0; 1290 } 1291 1292 if (_psxCacheEnabled[level]) 1293 return _psxScrCache[level]; 1294 else 1295 return NULL; 1296 } 1297 1298 bool Screen::getPsxScrCacheStatus(uint8 level) { 1299 if (level > 3) { 1300 level = 0; 1301 } 1302 1303 return _psxCacheEnabled[level]; 1304 } 1305 1306 void Screen::flushPsxScrCache() { 1307 for (uint8 i = 0; i < 3; i++) { 1308 free(_psxScrCache[i]); 1309 _psxScrCache[i] = NULL; 1310 _psxCacheEnabled[i] = true; 1311 } 1312 } 1313 1237 1314 } // End of namespace Sword2 -
scummvm-bs2psx/engines/sword2/function.cpp
71 71 72 72 // params: 0 res id of normal background layer - cannot be 0 73 73 // 1 1 yes 0 no for a new palette 74 75 _vm->_screen->initBackground(params[0], params[1]); 74 75 if (Sword2Engine::isPsx()) 76 _vm->_screen->initPsxBackground(params[0], params[1]); 77 else 78 _vm->_screen->initBackground(params[0], params[1]); 76 79 return IR_CONT; 77 80 } 78 81 … … 392 395 assert(_vm->_resman->fetchType(res) == ANIMATION_FILE); 393 396 394 397 // set up pointer to the animation header 395 AnimHeader anim_head; 396 398 AnimHeader anim_head; 399 397 400 anim_head.read(_vm->fetchAnimHeader(anim_file)); 398 401 399 402 // set up anim resource in graphic object 400 403 ObjectGraphic obGraph(decodePtr(params[0])); 401 404 402 405 obGraph.setAnimResource(res); 403 406 obGraph.setAnimPc(params[2] ? anim_head.noAnimFrames - 1 : 0); 404 407 -
scummvm-bs2psx/engines/sword2/resman.cpp
159 159 160 160 file.close(); 161 161 162 if (!file.open("cd.inf")) { 162 // Check that we have cd.inf file, unless we are running PSX 163 // version, which has all files on one disc. 164 165 if (!file.open("cd.inf") && !Sword2Engine::isPsx()) { 163 166 GUIErrorMessage("Broken Sword 2: Cannot open cd.inf"); 164 167 return false; 165 168 } … … 167 170 CdInf *cdInf = new CdInf[_totalClusters]; 168 171 169 172 for (i = 0; i < _totalClusters; i++) { 170 file.read(cdInf[i].clusterName, sizeof(cdInf[i].clusterName));171 173 172 cdInf[i].cd = file.readByte(); 174 if (Sword2Engine::isPsx()) { // We are running PSX version, artificially fill CdInf structure 175 cdInf[i].cd = CD1; 176 } else { // We are running PC version, read cd.inf file 177 file.read(cdInf[i].clusterName, sizeof(cdInf[i].clusterName)); 173 178 174 if (file.ioFailed()) { 175 delete cdInf; 176 file.close(); 177 GUIErrorMessage("Broken Sword 2: Cannot read cd.inf"); 178 return false; 179 cdInf[i].cd = file.readByte(); 180 181 if (file.ioFailed()) { 182 delete cdInf; 183 file.close(); 184 GUIErrorMessage("Broken Sword 2: Cannot read cd.inf"); 185 return false; 186 } 187 179 188 } 180 189 181 190 // It has been reported that there are two different versions … … 208 217 209 218 file.close(); 210 219 211 for (i = 0; i < _totalClusters; i++) { 212 for (j = 0; j < _totalClusters; j++) { 213 if (scumm_stricmp((char *)cdInf[j].clusterName, _resFiles[i].fileName) == 0) 214 break; 215 } 220 // We check the presence of resource files in cd.inf 221 // This is ok in PC version, but in PSX version we don't 222 // have cd.inf so we'll have to skip this. 223 if (!Sword2Engine::isPsx()) { 224 for (i = 0; i < _totalClusters; i++) { 225 for (j = 0; j < _totalClusters; j++) { 226 if (scumm_stricmp((char *)cdInf[j].clusterName, _resFiles[i].fileName) == 0) 227 break; 228 } 216 229 217 if (j == _totalClusters) { 218 delete[] cdInf; 219 GUIErrorMessage(Common::String(_resFiles[i].fileName) + " is not in cd.inf"); 220 return false; 230 if (j == _totalClusters) { 231 delete[] cdInf; 232 GUIErrorMessage(Common::String(_resFiles[i].fileName) + " is not in cd.inf"); 233 return false; 234 } 235 236 _resFiles[i].cd = cdInf[j].cd; 221 237 } 222 223 _resFiles[i].cd = cdInf[j].cd;224 238 } 225 239 226 240 delete[] cdInf; … … 247 261 byte *ResourceManager::openResource(uint32 res, bool dump) { 248 262 assert(res < _totalResFiles); 249 263 264 265 // FIXME: In PSX edition, not all top menu icons are present (TOP menu is not used). 266 // Though, at present state, the engine still ask for the resources. 267 if (Sword2Engine::isPsx()) { // We need to "rewire" missing icons 268 if (res == 342) res = 364; // Rewire RESTORE ICON to SAVE ICON 269 } 270 250 271 // Is the resource in memory already? If not, load it. 251 272 252 273 if (!_resList[res].ptr) { 253 274 // Fetch the correct file and read in the correct portion. 254 275 uint16 cluFileNum = _resConvTable[res * 2]; // points to the number of the ascii filename 276 255 277 assert(cluFileNum != 0xffff); 256 278 257 279 // Relative resource within the file … … 264 286 // of the CDs, remember which one so that we can play the 265 287 // correct speech and music. 266 288 267 setCD(_resFiles[cluFileNum].cd); 289 if (Sword2Engine::isPsx()) // We have only one disk in PSX version 290 setCD(CD1); 291 else 292 setCD(_resFiles[cluFileNum].cd); 268 293 269 294 // Actually, as long as the file can be found we don't really 270 295 // care which CD it's on. But if we can't find it, keep asking … … 481 506 } 482 507 483 508 /** 509 * Fetch resource type 510 */ 511 512 uint8 ResourceManager::fetchType(byte *ptr) { 513 if (!Sword2Engine::isPsx()) { 514 return ptr[0]; 515 } else { // in PSX version, some files got a "garbled" resource header, with type stored in ninth byte 516 if (ptr[0]) { 517 return ptr[0]; 518 } else if (ptr[8]) { 519 return ptr[8]; 520 } else { // In PSX version there is no resource header for audio files, 521 return WAV_FILE; // but hopefully all audio files got first 16 bytes zeroed, 522 } // Allowing us to check for this condition. 523 524 } 525 } 526 527 /** 484 528 * Returns the total file length of a resource - i.e. all headers are included 485 529 * too. 486 530 */ -
scummvm-bs2psx/engines/sword2/sword2.h
120 120 bool _useSubtitles; 121 121 int _gameSpeed; 122 122 123 // Used to trigger GMM Loading 124 int _gmmLoadSlot; 125 123 126 StartUp _startList[MAX_starts]; 124 127 128 // We need these to fetch data from SCREENS.CLU, which is 129 // a resource file with custom format keeping background and 130 // parallax data (which is removed from multiscreen files). 131 byte *fetchPsxBackground(uint32 location); 132 byte *fetchPsxParallax(uint32 location, uint8 level); // level: 0 -> bg, 1 -> fg 133 125 134 // Original game platform (PC/PSX) 126 135 static Common::Platform _platform; 127 136 … … 150 159 bool getSubtitles() { return _useSubtitles; } 151 160 void setSubtitles(bool b) { _useSubtitles = b; } 152 161 162 // GMM Loading/Saving 163 Common::Error saveGameState(int slot, const char *desc); 164 bool canSaveGameStateCurrently(); 165 Common::Error loadGameState(int slot); 166 bool canLoadGameStateCurrently(); 167 153 168 uint32 _features; 154 169 155 170 MemoryManager *_memory; … … 203 218 byte *fetchTextLine(byte *file, uint32 text_line); 204 219 bool checkTextLine(byte *file, uint32 text_line); 205 220 byte *fetchPaletteMatchTable(byte *screenFile); 206 221 207 222 uint32 saveGame(uint16 slotNo, byte *description); 208 223 uint32 restoreGame(uint16 slotNo); 209 224 uint32 getSaveDescription(uint16 slotNo, byte *description); -
scummvm-bs2psx/engines/sword2/sound.cpp
47 47 #include "sword2/sound.h" 48 48 49 49 #include "sound/wave.h" 50 #include "sound/vag.h" 50 51 51 52 namespace Sword2 { 52 53 … … 209 210 } 210 211 211 212 byte *data = _vm->_resman->openResource(res); 212 uint32 len = _vm->_resman->fetchLen(res) - ResHeader::size();213 213 uint32 len = _vm->_resman->fetchLen(res); 214 214 215 assert(_vm->_resman->fetchType(data) == WAV_FILE); 215 data += ResHeader::size(); 216 217 // In PSX version we have nothing to skip here, as data starts right away 218 if (!Sword2Engine::isPsx()) { 219 data += ResHeader::size(); 220 len -= ResHeader::size(); 221 } 216 222 217 223 _vm->_sound->playFx(handle, data, len, Audio::Mixer::kMaxChannelVolume, 0, false, Audio::Mixer::kMusicSoundType); 218 224 } … … 263 269 264 270 assert(_vm->_resman->fetchType(data) == WAV_FILE); 265 271 266 uint32 len = _vm->_resman->fetchLen(res) - ResHeader::size();272 uint32 len = _vm->_resman->fetchLen(res); 267 273 274 // Skip the header if using PC version 275 if (!Sword2Engine::isPsx()) 276 len -= ResHeader::size(); 277 268 278 if (type == FX_RANDOM) { 269 279 // For spot effects and loops the delay is the 270 280 // number of frames to wait. For random … … 281 291 pan = -pan; 282 292 283 293 _fxQueue[i].resource = res; 284 _fxQueue[i].data = data + ResHeader::size(); 294 295 if (Sword2Engine::isPsx()) 296 _fxQueue[i].data = data; 297 else 298 _fxQueue[i].data = data + ResHeader::size(); 299 285 300 _fxQueue[i].len = len; 286 301 _fxQueue[i].delay = delay; 287 302 _fxQueue[i].volume = volume; … … 311 326 if (_vm->_mixer->isSoundHandleActive(*handle)) 312 327 return RDERR_FXALREADYOPEN; 313 328 314 Common::MemoryReadStream stream(data, len);329 Common::MemoryReadStream *stream = new Common::MemoryReadStream(data, len); 315 330 int rate, size; 316 331 byte flags; 317 332 318 if (!Audio::loadWAVFromStream(stream, size, rate, flags)) { 319 warning("playFX: Not a valid WAV file"); 320 return RDERR_INVALIDWAV; 321 } 333 if (Sword2Engine::isPsx()) { 334 _vm->_mixer->playInputStream(soundType, handle, new Audio::VagStream(stream, loop), -1, vol, pan, true, false, isReverseStereo()); 335 } else { 336 if (!Audio::loadWAVFromStream(*stream, size, rate, flags)) { 337 warning("playFX: Not a valid WAV file"); 338 return RDERR_INVALIDWAV; 339 } 322 340 323 if (isReverseStereo())324 flags |= Audio::Mixer::FLAG_REVERSE_STEREO;341 if (isReverseStereo()) 342 flags |= Audio::Mixer::FLAG_REVERSE_STEREO; 325 343 326 if (loop)327 flags |= Audio::Mixer::FLAG_LOOP;344 if (loop) 345 flags |= Audio::Mixer::FLAG_LOOP; 328 346 329 _vm->_mixer->playRaw(soundType, handle, data + stream.pos(), size, rate, flags, -1, vol, pan, 0, 0); 347 _vm->_mixer->playRaw(soundType, handle, data + stream->pos(), size, rate, flags, -1, vol, pan, 0, 0); 348 } 349 330 350 return RD_OK; 331 351 } 332 352 -
scummvm-bs2psx/engines/sword2/mouse.h
70 70 }; 71 71 72 72 #define RDMENU_ICONWIDE 35 73 #define RDMENU_PSXICONWIDE 36 73 74 #define RDMENU_ICONDEEP 30 74 75 #define RDMENU_ICONSTART 24 75 76 #define RDMENU_ICONSPACING 5 … … 269 270 uint32 chooseMouse(); 270 271 271 272 int menuClick(int menu_items); 273 274 int getMouseMode(); 275 276 void setMouseMode(int mouseMode); // Used to force mouse mode 272 277 }; 273 278 274 279 } // End of namespace Sword2 -
scummvm-bs2psx/engines/sword2/logic.cpp
284 284 _moviePlayer->pauseMovie(pause); 285 285 } 286 286 287 /** 288 * Read current location number from script vars 289 */ 290 291 uint32 Logic::getLocationNum() { 292 return readVar(LOCATION); 293 } 294 287 295 } // End of namespace Sword2 -
scummvm-bs2psx/engines/sword2/header.h
159 159 void read(byte *addr) { 160 160 Common::MemoryReadStream readS(addr, size()); 161 161 162 runTimeComp = readS.readByte(); 163 noAnimFrames = readS.readUint16LE(); 164 feetStartX = readS.readUint16LE(); 165 feetStartY = readS.readUint16LE(); 166 feetStartDir = readS.readByte(); 167 feetEndX = readS.readUint16LE(); 168 feetEndY = readS.readUint16LE(); 169 feetEndDir = readS.readByte(); 170 blend = readS.readUint16LE(); 162 if (Sword2Engine::isPsx()) { 163 noAnimFrames = readS.readUint16LE(); 164 feetStartX = readS.readUint16LE(); 165 feetStartY = readS.readUint16LE(); 166 feetEndX = readS.readUint16LE(); 167 feetEndY = readS.readUint16LE(); 168 blend = readS.readUint16LE(); 169 runTimeComp = readS.readByte(); 170 feetStartDir = readS.readByte(); 171 feetEndDir = readS.readByte(); 172 } else { 173 runTimeComp = readS.readByte(); 174 noAnimFrames = readS.readUint16LE(); 175 feetStartX = readS.readUint16LE(); 176 feetStartY = readS.readUint16LE(); 177 feetStartDir = readS.readByte(); 178 feetEndX = readS.readUint16LE(); 179 feetEndY = readS.readUint16LE(); 180 feetEndDir = readS.readByte(); 181 blend = readS.readUint16LE(); 182 } 171 183 } 172 184 173 185 void write(byte *addr) { … … 210 222 // corner at (x,y), otherwise see below... 211 223 212 224 static int size() { 213 return 9; 225 if (Sword2Engine::isPsx()) 226 return 12; 227 else 228 return 9; 214 229 } 215 230 216 231 void read(byte *addr) { 217 232 Common::MemoryReadStream readS(addr, size()); 218 233 219 x = readS.readUint16LE(); 220 y = readS.readUint16LE(); 221 frameOffset = readS.readUint32LE(); 222 frameType = readS.readByte(); 234 if (Sword2Engine::isPsx()) { 235 readS.readByte(); // Skip a byte in psx version 236 x = readS.readUint16LE(); 237 y = readS.readUint16LE(); 238 frameOffset = readS.readUint32LE(); 239 frameType = readS.readByte(); 240 } else { 241 x = readS.readUint16LE(); 242 y = readS.readUint16LE(); 243 frameOffset = readS.readUint32LE(); 244 frameType = readS.readByte(); 245 } 223 246 } 224 247 225 248 void write(byte *addr) { … … 260 283 compSize = readS.readUint32LE(); 261 284 width = readS.readUint16LE(); 262 285 height = readS.readUint16LE(); 286 287 if (Sword2Engine::isPsx()) { // In PSX version, frames are half height 288 height *= 2; 289 width = (width % 2) ? width + 1 : width; 290 } 263 291 } 264 292 265 293 void write(byte *addr) { … … 504 532 // line of text,0 505 533 // line of text,0 506 534 535 //---------------------------------------------------------- 536 // SCREENS.CLU file 537 //---------------------------------------------------------- 538 // This file is present in PSX version of the game only. 539 // It keeps parallax and background images, aligned at 1024 bytes 540 // for faster access by the psx cd drive. 541 // 542 // SCREENS.CLU structure: 543 // In first 2048 Bytes there's an offset table. Each entry is an 544 // 32bit offset for a background/parallax group. If entry is 0, screen 545 // does not exist. 546 // To find matching screen for the location, you must count LOCATION_NO 547 // words and then go to the corresponding offset indicated by last 32bit 548 // word. 549 // Each screen then begins with a PSXScreensEntry entry: 550 551 struct PSXScreensEntry { 552 uint16 fgPlxXres; // If these values are 0, subsequent fgPlx* values must be 553 uint16 fgPlxYres; // ignored, as this means foreground parallax is not present. 554 uint32 fgPlxOffset; // This offset is relative, counting from the beginning of Resource Header 555 uint32 fgPlxSize; // Size of parallax, the size is aligned at 1024 bytes. 556 // fgPlxSize/1024 gives number of sector the parallax is divided into. 557 uint16 bgXres; 558 uint16 bgYres; 559 uint32 bgOffset; // relative 560 uint32 bgSize; 561 uint16 bgPlxXres; // same considerations for fg parallaxes apply 562 uint16 bgPlxYres; 563 uint32 bgPlxOffset; // relative 564 uint32 bgPlxSize; 565 566 static int size() { 567 return 36; 568 } 569 570 void read(byte *addr) { 571 Common::MemoryReadStream readS(addr, size()); 572 573 bgPlxXres = readS.readUint16LE(); 574 bgPlxYres = readS.readUint16LE(); 575 bgPlxOffset = readS.readUint32LE(); 576 bgPlxSize = readS.readUint32LE(); 577 bgXres = readS.readUint16LE(); 578 bgYres = readS.readUint16LE(); 579 bgOffset = readS.readUint32LE(); 580 bgSize = readS.readUint32LE(); 581 fgPlxXres = readS.readUint16LE(); 582 fgPlxYres = readS.readUint16LE(); 583 fgPlxOffset = readS.readUint32LE(); 584 fgPlxSize = readS.readUint32LE(); 585 } 586 587 void write(byte *addr) { 588 Common::MemoryWriteStream writeS(addr, size()); 589 590 writeS.writeUint16LE(bgPlxXres); 591 writeS.writeUint16LE(bgPlxYres); 592 writeS.writeUint32LE(bgPlxOffset); 593 writeS.writeUint32LE(bgPlxSize); 594 writeS.writeUint16LE(bgXres); 595 writeS.writeUint16LE(bgYres); 596 writeS.writeUint32LE(bgOffset); 597 writeS.writeUint32LE(bgSize); 598 writeS.writeUint16LE(fgPlxXres); 599 writeS.writeUint16LE(fgPlxYres); 600 writeS.writeUint32LE(fgPlxOffset); 601 writeS.writeUint32LE(fgPlxSize); 602 } 603 }; 604 605 // PSXFontEntry is present in font resource file, it is used 606 // to address a single char in the character atlas image. 607 608 struct PSXFontEntry { 609 uint16 offset; 610 uint16 skipLines; 611 uint16 charWidth; 612 uint16 charHeight; 613 614 static int size() { 615 return 8; 616 } 617 618 void read(byte *addr) { 619 Common::MemoryReadStream readS(addr, size()); 620 621 offset = readS.readUint16LE() / 2; 622 skipLines = readS.readUint16LE(); 623 charWidth = readS.readUint16LE() / 2; 624 charHeight = readS.readUint16LE(); 625 } 626 627 void write(byte *addr) { 628 Common::MemoryWriteStream writeS(addr, size()); 629 630 writeS.writeUint16LE(offset); 631 writeS.writeUint16LE(skipLines); 632 writeS.writeUint16LE(charWidth); 633 writeS.writeUint16LE(charHeight); 634 } 635 }; 636 507 637 } // End of namespace Sword2 508 638 509 639 #endif