scummvm/engines/icb/gfx/psx_tman.cpp
2021-12-26 21:19:38 +01:00

274 lines
6.7 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* Additional copyright for this file:
* Copyright (C) 1999-2000 Revolution Software Ltd.
* This code is based on source code created by Revolution Software,
* used with permission.
*
* This program 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 <http://www.gnu.org/licenses/>.
*
*/
#include "engines/icb/common/px_common.h"
#include "engines/icb/debug.h"
#include "engines/icb/gfx/psx_tman.h"
#include "engines/icb/gfx/psx_clut.h"
namespace ICB {
TextureManager::TextureManager() { Init(0, 0, 0, 0); }
TextureManager::TextureManager(short nx0, short ny0, short nx1, short ny1) { Init(nx0, ny0, nx1, ny1); }
void TextureManager::Init(short nx0, short ny0, short nx1, short ny1) {
x0 = nx0;
y0 = ny0;
x1 = nx1;
y1 = ny1;
tileW = (int16)((x1 - x0) / N_TILES_X);
tileH = (int16)((y1 - y0) / N_TILES_Y);
nSlotsUsed = 0;
nPalettesUsed = 0;
int32 t;
for (t = 0; t < MAX_NUMBER_TILES; t++) {
inuse[t] = 0;
}
int32 s;
for (s = 0; s < MAX_NUMBER_SLOTS; s++) {
tSlots[s].id = 0;
tSlots[s].age = 0;
}
for (s = 0; s < MAX_NUMBER_PALETTES; s++) {
pSlots[s].id = 0;
pSlots[s].age = 0;
}
}
TextureManager::~TextureManager() {}
TextureInfo *TextureManager::FindTexture(uint32 id, uint32 age) {
uint32 s;
TextureInfo *slot = tSlots;
for (s = 0; s < MAX_NUMBER_SLOTS; s++) {
if (slot->id == id) {
slot->age = age;
return slot;
}
slot++;
}
// printf( "Texture %X not found", id );
return nullptr;
}
TextureInfo *TextureManager::AddTexture(uint32 * /*tim_ptr*/, uint32 id, uint32 age, uint16 imgW, uint16 imgH) {
// printf( "Adding Texture %X", id );
if (id == 0) {
Message_box("AddTexture 0 ID");
return nullptr;
}
// Try to find a slot for it
uint32 t = 0;
uint32 s = 0;
uint32 purges = 0;
uint32 oldest;
uint32 fitted = 0;
TextureInfo *slot;
uint32 xt = 0;
uint32 yt = 0;
uint32 ntx0 = (imgW + tileW - 1) / tileW;
uint32 nty0 = (imgH + tileH - 1) / tileH;
uint32 x, y;
uint32 xend, yend;
uint32 dy = N_TILES_X;
uint32 place0, place;
while (fitted == 0) {
xt = 0;
yt = 0;
for (t = 0; t < MAX_NUMBER_TILES; t++) {
if (inuse[t] == 0) {
// Found a slot which isn't in use
// Does it fit into a single tile
if ((imgW <= tileW) && (imgH <= tileH)) {
fitted = 1;
inuse[t] = 1;
break;
} else {
// Covers more than one tile
// Can it physically fit in ?
xend = xt + ntx0;
yend = yt + nty0;
if ((xend <= N_TILES_X) && (yend <= N_TILES_Y)) {
// so need to check all the tiles that would be occupied
place0 = xt + yt * dy;
for (y = yt; y < yend; y++) {
place = place0;
for (x = xt; x < xend; x++) {
if (inuse[place] == 1) {
// printf("x %d y %d place %d NOTOK", x, y, place );
break;
}
place++;
}
if (x != xend)
break;
place0 += dy;
}
if (y == yend) {
// Hey its ok
fitted = 1;
// Mark the tiles as being used
place0 = xt + yt * dy;
for (y = yt; y < yend; y++) {
place = place0;
for (x = xt; x < xend; x++) {
inuse[place] = 1;
place++;
}
place0 += dy;
}
break;
}
}
}
}
xt++;
if (xt == N_TILES_X) {
xt = 0;
yt++;
// ERROR
if (yt > N_TILES_Y) {
Message_box("BAD yt");
yt = N_TILES_Y - 1;
}
}
}
// Oh dear couldn't find a slot for it
// Have to purge out the oldest resource
if (t == MAX_NUMBER_TILES) {
slot = tSlots;
purges = MAX_NUMBER_SLOTS;
oldest = 0xFFFFFFFF;
for (s = 0; s < MAX_NUMBER_SLOTS; s++) {
// Only look at slots with id != 0
if (slot->id != 0) {
if (slot->age < oldest) {
oldest = slot->age;
purges = s;
}
}
slot++;
}
// ERROR
if (purges == MAX_NUMBER_SLOTS) {
Message_box("bad purges");
purges = 0;
}
// Purge
tSlots[purges].id = 0;
tSlots[purges].age = 0;
// Now more tricky reset the inuse flags
RECT16 *pr = &(tSlots[purges].r);
uint32 tx = (pr->x - x0) / tileW;
uint32 ty = (pr->y - y0) / tileH;
uint32 ntx = pr->w / tileW;
uint32 nty = pr->h / tileH;
if (ntx == 0)
ntx = 1;
if (nty == 0)
nty = 1;
// printf( "tx %d ty %d ntx %d nty %d", tx, ty, ntx, nty );
place0 = tx + ty * dy;
for (y = ty; y < (ty + nty); y++) {
place = place0;
for (x = tx; x < (tx + ntx); x++) {
inuse[place] = 0;
place++;
}
place0 += dy;
}
}
}
// A slot has been found for it : hooray
slot = tSlots;
for (s = 0; s < MAX_NUMBER_SLOTS; s++) {
// Find the first slot with id 0
if (slot->id == 0)
break;
slot++;
}
if (s == MAX_NUMBER_SLOTS) {
Message_box("BAD slot");
slot = tSlots;
s = 0;
}
slot->id = id;
slot->age = age;
if (xt > N_TILES_X) {
Message_box("bad xt %d", xt);
}
if (yt > N_TILES_Y) {
Message_box("bad yt %d", yt);
}
slot->r.x = (int16)(xt * tileW + x0);
slot->r.y = (int16)(yt * tileH + y0);
slot->r.w = imgW;
slot->r.h = imgH;
slot->tsb = (int16)getTPage(1, 0, slot->r.x, slot->r.y); // 8-bit, b+f
slot->cba = (int16)getClut(CHARACTER_CLUT_X, (CHARACTER_CLUT_Y + s));
slot->uoffset = (uint8)(slot->r.x - ((slot->tsb & 0xF) << 6));
slot->voffset = (uint8)(slot->r.y - (((slot->tsb >> 4) & 0x1) << 8));
return slot;
}
void TextureManager::PurgeAll(void) { Init(x0, y0, x1, y1); }
PaletteInfo *TextureManager::FindPalette(uint32 id, uint32 age) {
uint32 s;
PaletteInfo *slot = pSlots;
for (s = 0; s < MAX_NUMBER_SLOTS; s++) {
if (slot->id == id) {
slot->age = age;
return slot;
}
slot++;
}
return nullptr;
}
PaletteInfo *TextureManager::AddPalette(uint32 * /*clut_ptr*/, uint32 id, uint32 age) {
if (nPalettesUsed < MAX_NUMBER_PALETTES) {
PaletteInfo *slot = &(pSlots[nPalettesUsed]);
slot->x = CHARACTER_ALTERNATE_CLUT_X;
slot->y = (int16)(CHARACTER_ALTERNATE_CLUT_Y + nPalettesUsed);
slot->cba = (int16)getClut(slot->x, slot->y);
slot->id = id;
slot->age = age;
nPalettesUsed++;
return slot;
}
return nullptr;
}
} // End of namespace ICB