/* -*- mode: c; tab-width: 4; c-basic-offset: 4; c-file-style: "linux" -*- */ // // Copyright (c) 2009-2011, Wei Mingzhi . // Copyright (c) 2011-2017, SDLPAL development team. // All rights reserved. // // This file is part of SDLPAL. // // SDLPAL is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // #include "palcommon.h" #include "map.h" LPPALMAP PAL_LoadMap( INT iMapNum, FILE *fpMapMKF, FILE *fpGopMKF ) /*++ Purpose: Load the specified map from the MKF file, as well as the tile bitmaps. Parameters: [IN] iMapNum - Number of the map to load. [IN] fpMapMKF - Pointer to the fopen'ed map.mkf file, which contains the map tile data. [IN] fpGopMKF - Pointer to the fopen'ed gop.mkf file, which contains the tile bitmaps. The bitmap can be read by PAL_SpriteGetFrame() function. Return value: Pointer to the loaded map. NULL if failed. --*/ { LPBYTE buf; INT size, i, j; LPPALMAP map; // // Check for invalid map number. // if (iMapNum >= PAL_MKFGetChunkCount(fpMapMKF) || iMapNum >= PAL_MKFGetChunkCount(fpGopMKF) || iMapNum <= 0) { return NULL; } // // Load the map tile data. // size = PAL_MKFGetChunkSize(iMapNum, fpMapMKF); // // Allocate a temporary buffer for the compressed data. // buf = (LPBYTE)malloc(size); if (buf == NULL) { return NULL; } // // Create the map instance. // map = (LPPALMAP)malloc(sizeof(PALMAP)); if (map == NULL) { return NULL; } // // Read the map data. // if (PAL_MKFReadChunk(buf, size, iMapNum, fpMapMKF) < 0) { free(buf); free(map); return NULL; } // // Decompress the tile data. // if (Decompress(buf, (LPBYTE)(map->Tiles), sizeof(map->Tiles)) < 0) { free(map); free(buf); return NULL; } // // The compressed data is useless now; delete it. // free(buf); // // Adjust the endianness of the decompressed data. // for (i = 0; i < 128; i++) { for (j = 0; j < 64; j++) { map->Tiles[i][j][0] = SDL_SwapLE32(map->Tiles[i][j][0]); map->Tiles[i][j][1] = SDL_SwapLE32(map->Tiles[i][j][1]); } } // // Load the tile bitmaps. // size = PAL_MKFGetChunkSize(iMapNum, fpGopMKF); if (size <= 0) { free(map); return NULL; } map->pTileSprite = (LPSPRITE)malloc(size); if (map->pTileSprite == NULL) { free(map); return NULL; } if (PAL_MKFReadChunk(map->pTileSprite, size, iMapNum, fpGopMKF) < 0) { free(map); return NULL; } // // Done. // map->iMapNum = iMapNum; return map; } VOID PAL_FreeMap( LPPALMAP lpMap ) /*++ Purpose: Free a loaded map, as well as the tile bitmaps. Parameters: [IN] lpMap - Pointer to the loaded map structure. Return value: None. --*/ { // // Check for NULL pointer. // if (lpMap == NULL) { return; } // // Free the tile bitmaps. // if (lpMap->pTileSprite != NULL) { free(lpMap->pTileSprite); } // // Delete the instance. // free(lpMap); } LPCBITMAPRLE PAL_MapGetTileBitmap( BYTE x, BYTE y, BYTE h, BYTE ucLayer, LPCPALMAP lpMap ) /*++ Purpose: Get the tile bitmap on the specified layer at the location (x, y, h). Parameters: [IN] x - Column number of the tile. [IN] y - Line number in the map. [IN] h - Each line in the map has two lines of tiles, 0 and 1. (See map.h for details.) [IN] ucLayer - The layer. 0 for bottom, 1 for top. [IN] lpMap - Pointer to the loaded map. Return value: Pointer to the bitmap. NULL if failed. --*/ { DWORD d; // // Check for invalid parameters. // if (x >= 64 || y >= 128 || h > 1 || lpMap == NULL) { return NULL; } // // Get the tile data of the specified location. // d = lpMap->Tiles[y][x][h]; if (ucLayer == 0) { // // Bottom layer // return PAL_SpriteGetFrame(lpMap->pTileSprite, (d & 0xFF) | ((d >> 4) & 0x100)); } else { // // Top layer // d >>= 16; return PAL_SpriteGetFrame(lpMap->pTileSprite, ((d & 0xFF) | ((d >> 4) & 0x100)) - 1); } } BOOL PAL_MapTileIsBlocked( BYTE x, BYTE y, BYTE h, LPCPALMAP lpMap ) /*++ Purpose: Check if the tile at the specified location is blocked. Parameters: [IN] x - Column number of the tile. [IN] y - Line number in the map. [IN] h - Each line in the map has two lines of tiles, 0 and 1. (See map.h for details.) [IN] lpMap - Pointer to the loaded map. Return value: TRUE if the tile is blocked, FALSE if not. --*/ { // // Check for invalid parameters. // if (x >= 64 || y >= 128 || h > 1 || lpMap == NULL) { return TRUE; } return (lpMap->Tiles[y][x][h] & 0x2000) >> 13; } BYTE PAL_MapGetTileHeight( BYTE x, BYTE y, BYTE h, BYTE ucLayer, LPCPALMAP lpMap ) /*++ Purpose: Get the logical height value of the specified tile. This value is used to judge whether the tile bitmap should cover the sprites or not. Parameters: [IN] x - Column number of the tile. [IN] y - Line number in the map. [IN] h - Each line in the map has two lines of tiles, 0 and 1. (See map.h for details.) [IN] ucLayer - The layer. 0 for bottom, 1 for top. [IN] lpMap - Pointer to the loaded map. Return value: The logical height value of the specified tile. --*/ { DWORD d; // // Check for invalid parameters. // if (y >= 128 || x >= 64 || h > 1 || lpMap == NULL) { return 0; } d = lpMap->Tiles[y][x][h]; if (ucLayer) { d >>= 16; } d >>= 8; return (BYTE)(d & 0xf); } VOID PAL_MapBlitToSurface( LPCPALMAP lpMap, SDL_Surface *lpSurface, const SDL_Rect *lpSrcRect, BYTE ucLayer ) /*++ Purpose: Blit the specified map area to a SDL Surface. Parameters: [IN] lpMap - Pointer to the map. [OUT] lpSurface - Pointer to the destination surface. [IN] lpSrcRect - Pointer to the source area. [IN] ucLayer - The layer. 0 for bottom, 1 for top. Return value: None. --*/ { int sx, sy, dx, dy, x, y, h, xPos, yPos; LPCBITMAPRLE lpBitmap = NULL; // // Convert the coordinate // sy = lpSrcRect->y / 16 - 1; dy = (lpSrcRect->y + lpSrcRect->h) / 16 + 2; sx = lpSrcRect->x / 32 - 1; dx = (lpSrcRect->x + lpSrcRect->w) / 32 + 2; // // Do the drawing. // yPos = sy * 16 - 8 - lpSrcRect->y; for (y = sy; y < dy; y++) { for (h = 0; h < 2; h++, yPos += 8) { xPos = sx * 32 + h * 16 - 16 - lpSrcRect->x; for (x = sx; x < dx; x++, xPos += 32) { lpBitmap = PAL_MapGetTileBitmap((BYTE)x, (BYTE)y, (BYTE)h, ucLayer, lpMap); if (lpBitmap == NULL) { if (ucLayer) { continue; } lpBitmap = PAL_MapGetTileBitmap(0, 0, 0, ucLayer, lpMap); } PAL_RLEBlitToSurface(lpBitmap, lpSurface, PAL_XY(xPos, yPos)); } } } }