2024-04-20 15:57:49 +00:00
|
|
|
/*
|
|
|
|
* Descent 3
|
|
|
|
* Copyright (C) 2024 Parallax Software
|
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2024-04-16 03:43:29 +00:00
|
|
|
/*
|
|
|
|
* $Logfile: /DescentIII/Main/2dlib/surface.cpp $
|
|
|
|
* $Revision: 7 $
|
|
|
|
* $Date: 11/30/98 5:50p $
|
|
|
|
* $Author: Jason $
|
|
|
|
*
|
|
|
|
* Master Surface class
|
|
|
|
*
|
|
|
|
* $Log: /DescentIII/Main/2dlib/surface.cpp $
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 7 11/30/98 5:50p Jason
|
|
|
|
* added 4444 bitmap support
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 6 4/23/98 6:38p Jason
|
|
|
|
* made bitmaps use 1555 format
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 5 12/19/97 2:26p Jason
|
|
|
|
* more fixes for 2d/3d intergration
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 4 12/19/97 12:32p Samir
|
|
|
|
* lock now calls renderer functions.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 3 11/11/97 1:24p Samir
|
|
|
|
* Fixed problem with clearing using the renderer.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 2 10/15/97 5:20p Jason
|
|
|
|
* did a HUGE overhaul of the bitmap system
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 24 6/12/97 6:29p Samir
|
|
|
|
* DDGR v2.0 Changes in 2d system implemented.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 23 6/06/97 12:18p Samir
|
|
|
|
* OpenGL HACKS to call renderer for some drawing functions. Must fix.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 22 5/19/97 5:10p Jason
|
|
|
|
* changes for our new abstracted renderer code
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 21 4/30/97 3:15p Jason
|
|
|
|
* changes to support both 8bit and 16bit rendering in software
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 20 3/28/97 3:07p Samir
|
|
|
|
* Clear function now takes a color
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 19 3/27/97 11:11a Samir
|
|
|
|
* Moved code from ddgr library to 2dlib because it was ANSI compliant and
|
|
|
|
* should work on all systems
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 18 2/28/97 2:51p Samir
|
|
|
|
* took out __cdecl in atexit function.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 17 2/17/97 2:19p Jason
|
|
|
|
* made blit function scale instead of clip
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 16 2/11/97 3:19p Jason
|
|
|
|
* added displaying of 8bit palettized graphics on 16bit surfaces
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 15 2/04/97 12:49p Samir
|
2024-04-16 18:56:40 +00:00
|
|
|
* Added lock(x,y) for those special cases.
|
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 14 2/03/97 3:01p Samir
|
|
|
|
* Used one memory surface global to grSurface for scratchpad blitting.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 13 1/30/97 6:01p Samir
|
|
|
|
* The partition of memory and os surfaces as well as the change in
|
|
|
|
* ddgr_surface structure and all related changes.
|
|
|
|
*
|
|
|
|
* $NoKeywords: $
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "lib2d.h"
|
|
|
|
#include "pserror.h"
|
|
|
|
#include "bitmap.h"
|
|
|
|
#include "texture.h"
|
|
|
|
#include "renderer.h"
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
inline unsigned XLAT_RGB_TO_16(ddgr_color c) {
|
|
|
|
unsigned char r, g, b;
|
|
|
|
r = (unsigned char)((c & 0x00ff0000) >> 16);
|
|
|
|
g = (unsigned char)((c & 0x0000ff00) >> 8);
|
|
|
|
b = (unsigned char)(c & 0x000000ff);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
return (((r >> 3) << 10) + ((g >> 3) << 5) + (b >> 3));
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
ddgr_surface_node *grSurface::surf_list = NULL; // the surface list
|
|
|
|
ddgr_surface_node *grSurface::surf_list_cur = NULL; // current node on list.
|
2024-04-16 03:43:29 +00:00
|
|
|
ddgr_surface *grSurface::scratch_mem_surf = NULL;
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::init_system() {
|
|
|
|
// allocate our scratch memory surface used in uniblt
|
|
|
|
if (!grSurface::scratch_mem_surf) {
|
|
|
|
grSurface::scratch_mem_surf = new ddgr_surface;
|
|
|
|
memset(grSurface::scratch_mem_surf, 0, sizeof(ddgr_surface));
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
atexit(grSurface::close_system);
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::close_system() {
|
|
|
|
// cleanup our scratch memory surface for blt
|
|
|
|
if (grSurface::scratch_mem_surf) {
|
|
|
|
if (grSurface::scratch_mem_surf->obj != NULL)
|
|
|
|
gr_mem_surf_Destroy(grSurface::scratch_mem_surf);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
delete grSurface::scratch_mem_surf;
|
|
|
|
grSurface::scratch_mem_surf = NULL;
|
|
|
|
}
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// grSurface constructor and destructor
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
grSurface::grSurface() {
|
|
|
|
surf_Locked = 0;
|
|
|
|
m_SurfInit = 0;
|
|
|
|
memset(&ddsfObj, 0, sizeof(ddgr_surface));
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
grSurface::grSurface(int w, int h, int bpp, unsigned type, unsigned flags, const char *name) {
|
|
|
|
surf_Locked = 0;
|
|
|
|
m_SurfInit = 0;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
grSurface::create(w, h, bpp, type, flags, name);
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
grSurface::~grSurface() { grSurface::free(); }
|
|
|
|
|
|
|
|
void grSurface::create(int w, int h, int bpp, unsigned type, unsigned flags, const char *name) {
|
|
|
|
bool grerr;
|
|
|
|
|
|
|
|
if (m_SurfInit)
|
|
|
|
grSurface::free();
|
|
|
|
|
|
|
|
// create new surface: set up surface structure
|
|
|
|
memset(&ddsfObj, 0, sizeof(ddgr_surface));
|
|
|
|
ddsfObj.w = w;
|
|
|
|
ddsfObj.h = h;
|
|
|
|
ddsfObj.bpp = bpp;
|
|
|
|
ddsfObj.type = (ushort)type;
|
|
|
|
ddsfObj.flags = (ushort)flags;
|
|
|
|
|
|
|
|
if (name)
|
|
|
|
strncpy(ddsfObj.name, name, 15);
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case SURFTYPE_VIDEOSCREEN:
|
|
|
|
grerr = ddgr_surf_InitVideo(&ddsfObj);
|
|
|
|
break;
|
|
|
|
case SURFTYPE_GENERIC:
|
|
|
|
grerr = ddgr_surf_Create(&ddsfObj);
|
|
|
|
break;
|
|
|
|
case SURFTYPE_MEMORY:
|
|
|
|
grerr = (bool)gr_mem_surf_Create(&ddsfObj);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Int3(); // Invalid!!
|
|
|
|
}
|
|
|
|
if (!grerr)
|
|
|
|
Int3();
|
|
|
|
|
|
|
|
add_to_list(&ddsfObj);
|
|
|
|
|
|
|
|
m_SurfInit = 1;
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::free() {
|
|
|
|
/* Freeing surface is same regardless of whether it was loaded from a bitmap handle or
|
|
|
|
created ourselves
|
|
|
|
*/
|
|
|
|
if (!m_SurfInit)
|
|
|
|
return;
|
|
|
|
ASSERT(!surf_Locked);
|
|
|
|
|
|
|
|
switch (ddsfObj.type) {
|
|
|
|
case SURFTYPE_VIDEOSCREEN:
|
|
|
|
ddgr_surf_CloseVideo(&ddsfObj);
|
|
|
|
break;
|
|
|
|
case SURFTYPE_GENERIC:
|
|
|
|
ddgr_surf_Destroy(&ddsfObj);
|
|
|
|
break;
|
|
|
|
case SURFTYPE_MEMORY:
|
|
|
|
gr_mem_surf_Destroy(&ddsfObj);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Int3(); // This really shouldn't happen. bad type!
|
|
|
|
}
|
|
|
|
|
|
|
|
remove_from_list(&ddsfObj);
|
|
|
|
|
|
|
|
m_SurfInit = 0;
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::load(int handle) {
|
|
|
|
/* just load the bitmap from the handle info */
|
|
|
|
ASSERT(m_SurfInit);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
grSurface::load((char *)bm_data(handle, 0), bm_w(handle, 0), bm_h(handle, 0), bm_bpp(handle), bm_format(handle));
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::load(char *data, int w, int h, int bpp, int format) {
|
|
|
|
// copy defined bitmap given as arguments to this surface, with correct bpp translation.
|
|
|
|
int rowsize;
|
|
|
|
ASSERT(m_SurfInit);
|
|
|
|
|
|
|
|
/* perform lock, then copy data to this surface, then unlock */
|
|
|
|
grSurface::lock(&rowsize);
|
|
|
|
|
|
|
|
switch (ddsfObj.bpp) {
|
|
|
|
case BPP_16:
|
|
|
|
if (bpp == BPP_16)
|
|
|
|
xlat16_16(data, w, h, format);
|
|
|
|
if (bpp == BPP_24)
|
|
|
|
xlat24_16(data, w, h);
|
|
|
|
if (bpp == BPP_32)
|
|
|
|
xlat32_16(data, w, h);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BPP_24:
|
|
|
|
if (bpp == BPP_16)
|
|
|
|
xlat16_24(data, w, h);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Int3(); // NOT SUPPORTED YET
|
|
|
|
}
|
|
|
|
|
|
|
|
grSurface::unlock();
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// loads 8bit palettized data onto this surface.
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::load(int handle, char *pal) {
|
|
|
|
ASSERT(m_SurfInit);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
grSurface::load((char *)bm_data(handle, 0), bm_w(handle, 0), bm_h(handle, 0), pal);
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// loads 8bit palettized data onto this surface.
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::load(char *data, int w, int h, char *pal) {
|
|
|
|
int rowsize;
|
|
|
|
ASSERT(m_SurfInit);
|
|
|
|
|
|
|
|
/* perform lock, then copy data to this surface, then unlock */
|
|
|
|
grSurface::lock(&rowsize);
|
|
|
|
|
|
|
|
switch (ddsfObj.bpp) {
|
|
|
|
case BPP_16:
|
|
|
|
if (Renderer_type == RENDERER_SOFTWARE_8BIT)
|
|
|
|
xlat8_16(data, w, h, pal);
|
|
|
|
else
|
|
|
|
xlat16_16(data, w, h);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Int3(); // NOT SUPPORTED YET
|
|
|
|
}
|
|
|
|
|
|
|
|
grSurface::unlock();
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// blt functions:: clear
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::clear(ddgr_color col) { grSurface::clear(0, 0, ddsfObj.w, ddsfObj.h, col); }
|
|
|
|
|
|
|
|
void grSurface::clear(int l, int t, int w, int h, ddgr_color col) {
|
|
|
|
ASSERT(m_SurfInit);
|
|
|
|
ASSERT(!surf_Locked);
|
|
|
|
|
|
|
|
switch (ddsfObj.type) {
|
|
|
|
case SURFTYPE_VIDEOSCREEN:
|
|
|
|
case SURFTYPE_GENERIC:
|
|
|
|
// HACK!!!!!!! I MUST CHANGE THIS
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
if (ddsfObj.flags & SURFFLAG_RENDERER) {
|
|
|
|
rend_FillRect(col, l, t, l + w, t + h);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
ddgr_surf_Clear(&ddsfObj, col, l, t, w, h);
|
|
|
|
break;
|
|
|
|
case SURFTYPE_MEMORY:
|
|
|
|
gr_mem_surf_Clear(&ddsfObj, col, l, t, w, h);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Int3();
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// blt functions:
|
|
|
|
// these functions must support memory->os, os->memory, os->os, mem->mem blts.
|
|
|
|
// note that (os) blts and (video) blts use the os library.
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::uniblt(int dx, int dy, grSurface *ssf, int sx, int sy, int sw, int sh) {
|
|
|
|
int rowsize;
|
|
|
|
|
|
|
|
ASSERT(m_SurfInit);
|
|
|
|
|
|
|
|
// mode 11b = dd_to_dd, 01b = mem_to_dd, 10b = dd_to_mem, 00b = mem_to_mem
|
|
|
|
int mode = 0;
|
|
|
|
ddgr_surface *dsfs = &ddsfObj, *ssfs = &ssf->ddsfObj;
|
|
|
|
bool err;
|
|
|
|
|
|
|
|
// setup blitting mode
|
|
|
|
if (ssfs->type == SURFTYPE_GENERIC || ssfs->type == SURFTYPE_VIDEOSCREEN)
|
|
|
|
mode = mode | 0x1;
|
|
|
|
if (dsfs->type == SURFTYPE_GENERIC || dsfs->type == SURFTYPE_VIDEOSCREEN)
|
|
|
|
mode = mode | 0x2;
|
|
|
|
|
|
|
|
/* case 1: os->os
|
|
|
|
just invoke os blitter
|
|
|
|
*/
|
|
|
|
if (mode == 0x3) {
|
|
|
|
ASSERT(!surf_Locked);
|
|
|
|
err = ddgr_surf_Blt(dsfs, dx, dy, ssfs, sx, sy, sw, sh);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* case 2: mem->mem
|
|
|
|
just lock both surfaces and do a memory blt.
|
|
|
|
*/
|
|
|
|
if (mode == 0) {
|
|
|
|
err = gr_mem_surf_Blt(dsfs, dx, dy, ssfs, sx, sy, sw, sh);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* case 3: os->mem
|
|
|
|
This requires locking both surfaces and performing a memory blt.
|
|
|
|
This also means tricking the memory blitter into thinking that the OS surface
|
|
|
|
is a memory surface
|
|
|
|
*/
|
|
|
|
if (mode == 0x1) {
|
|
|
|
char *data = ssf->lock(&rowsize);
|
|
|
|
|
|
|
|
grSurface::scratch_mem_surf->w = ssfs->w;
|
|
|
|
grSurface::scratch_mem_surf->h = ssfs->h;
|
|
|
|
grSurface::scratch_mem_surf->bpp = ssfs->bpp;
|
|
|
|
grSurface::scratch_mem_surf->type = SURFTYPE_MEMORY;
|
|
|
|
grSurface::scratch_mem_surf->flags = ssfs->flags;
|
|
|
|
|
|
|
|
gr_mem_surf_Init(grSurface::scratch_mem_surf, data, rowsize);
|
|
|
|
err = gr_mem_surf_Blt(dsfs, dx, dy, grSurface::scratch_mem_surf, sx, sy, sw, sh);
|
|
|
|
|
|
|
|
ssf->unlock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* case 4: mem->os
|
|
|
|
This requires locking both surfaces and performing a memory blt.
|
|
|
|
This also means tricking the memory blitter into thinking that the OS surface
|
|
|
|
is a memory surface
|
|
|
|
*/
|
|
|
|
if (mode == 0x2) {
|
|
|
|
grSurface::lock(&rowsize);
|
|
|
|
|
|
|
|
grSurface::scratch_mem_surf->w = dsfs->w;
|
|
|
|
grSurface::scratch_mem_surf->h = dsfs->h;
|
|
|
|
grSurface::scratch_mem_surf->bpp = dsfs->bpp;
|
|
|
|
grSurface::scratch_mem_surf->type = SURFTYPE_MEMORY;
|
|
|
|
grSurface::scratch_mem_surf->flags = dsfs->flags;
|
|
|
|
|
|
|
|
gr_mem_surf_Init(grSurface::scratch_mem_surf, m_DataPtr, m_DataRowsize);
|
|
|
|
err = gr_mem_surf_Blt(grSurface::scratch_mem_surf, dx, dy, ssfs, sx, sy, sw, sh);
|
|
|
|
|
|
|
|
grSurface::unlock();
|
|
|
|
return;
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::blt(int dx, int dy, grSurface *ssf) {
|
|
|
|
ASSERT(m_SurfInit);
|
|
|
|
grSurface::uniblt(dx, dy, ssf, 0, 0, ssf->width(), ssf->height());
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::blt(int dx, int dy, grSurface *ssf, int sx, int sy, int sw, int sh) {
|
|
|
|
ASSERT(m_SurfInit);
|
|
|
|
grSurface::uniblt(dx, dy, ssf, sx, sy, sw, sh);
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Helper functions
|
2024-04-16 18:56:40 +00:00
|
|
|
replace_color, simply replaces one color in the surface with another
|
2024-04-16 03:43:29 +00:00
|
|
|
*/
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::replace_color(ddgr_color sc, ddgr_color dc) {
|
|
|
|
int rowsize;
|
|
|
|
ASSERT(m_SurfInit);
|
|
|
|
|
|
|
|
grSurface::lock(&rowsize);
|
|
|
|
|
|
|
|
switch (ddsfObj.bpp) {
|
|
|
|
case BPP_16: {
|
|
|
|
ushort *data = (ushort *)m_DataPtr;
|
|
|
|
int rowsize_w = m_DataRowsize / 2;
|
|
|
|
ushort scc = XLAT_RGB_TO_16(sc), dcc = XLAT_RGB_TO_16(dc);
|
|
|
|
|
|
|
|
for (int y = 0; y < ddsfObj.h; y++) {
|
|
|
|
for (int x = 0; x < ddsfObj.w; x++)
|
|
|
|
if (data[x] == scc)
|
|
|
|
data[x] = dcc;
|
|
|
|
|
|
|
|
data += rowsize_w;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case BPP_32:
|
|
|
|
default:
|
|
|
|
Int3();
|
|
|
|
}
|
|
|
|
|
|
|
|
grSurface::unlock();
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// lock and unlock functions
|
|
|
|
// these handle memory and os locks
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
char *grSurface::lock(int *rowsize) {
|
|
|
|
bool grerr;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
ASSERT(m_SurfInit);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
switch (ddsfObj.type) {
|
|
|
|
case SURFTYPE_VIDEOSCREEN:
|
|
|
|
case SURFTYPE_GENERIC:
|
|
|
|
grerr = ddgr_surf_Lock(&ddsfObj, (void **)&m_OrigDataPtr, &m_DataRowsize);
|
|
|
|
break;
|
|
|
|
case SURFTYPE_MEMORY:
|
|
|
|
grerr = gr_mem_surf_Lock(&ddsfObj, (void **)&m_OrigDataPtr, &m_DataRowsize);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Int3(); // invalid type!!
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
m_DataPtr = m_OrigDataPtr;
|
|
|
|
*rowsize = m_DataRowsize;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
if (!grerr)
|
|
|
|
return NULL;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
surf_Locked++; // increment lock counter for this surface
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
rend_SetSoftwareParameters(ddgr_GetAspectRatio(), ddsfObj.w, ddsfObj.h, m_DataRowsize, (ubyte *)m_OrigDataPtr);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
return m_DataPtr;
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* do lock based off of x,y offsets */
|
2024-04-16 18:56:40 +00:00
|
|
|
char *grSurface::lock(int x, int y, int *rowsize) {
|
2024-04-19 23:42:17 +00:00
|
|
|
bool grerr = false;
|
2024-04-16 18:56:40 +00:00
|
|
|
|
|
|
|
ASSERT(m_SurfInit);
|
|
|
|
|
|
|
|
switch (ddsfObj.type) {
|
|
|
|
case SURFTYPE_VIDEOSCREEN:
|
|
|
|
case SURFTYPE_GENERIC:
|
|
|
|
grerr = ddgr_surf_Lock(&ddsfObj, (void **)&m_OrigDataPtr, &m_DataRowsize);
|
|
|
|
break;
|
|
|
|
case SURFTYPE_MEMORY:
|
|
|
|
grerr = gr_mem_surf_Lock(&ddsfObj, (void **)&m_OrigDataPtr, &m_DataRowsize);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Int3(); // invalid type!!
|
|
|
|
}
|
|
|
|
|
|
|
|
*rowsize = m_DataRowsize;
|
|
|
|
if (!grerr)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* calculate the adjusted data pointer based off of x,y,bpp */
|
|
|
|
char *data = m_OrigDataPtr;
|
|
|
|
|
|
|
|
data += (y * m_DataRowsize);
|
|
|
|
|
|
|
|
switch (ddsfObj.bpp) {
|
|
|
|
case BPP_16:
|
|
|
|
data += (x * 2);
|
|
|
|
break;
|
|
|
|
case BPP_32:
|
|
|
|
data += (x * 4);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Int3();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_DataPtr = data;
|
|
|
|
|
|
|
|
surf_Locked++; // increment lock counter for this surface
|
|
|
|
|
|
|
|
rend_SetSoftwareParameters(ddgr_GetAspectRatio(), ddsfObj.w, ddsfObj.h, m_DataRowsize, (ubyte *)m_OrigDataPtr);
|
|
|
|
|
|
|
|
return m_DataPtr;
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::unlock() {
|
|
|
|
bool grerr;
|
|
|
|
|
|
|
|
ASSERT(m_SurfInit);
|
|
|
|
ASSERT(surf_Locked);
|
|
|
|
|
|
|
|
switch (ddsfObj.type) {
|
|
|
|
case SURFTYPE_VIDEOSCREEN:
|
|
|
|
case SURFTYPE_GENERIC:
|
|
|
|
grerr = ddgr_surf_Unlock(&ddsfObj, m_OrigDataPtr);
|
|
|
|
break;
|
|
|
|
case SURFTYPE_MEMORY:
|
|
|
|
grerr = gr_mem_surf_Unlock(&ddsfObj, m_OrigDataPtr);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Int3(); // invalid type!!
|
|
|
|
}
|
|
|
|
|
|
|
|
surf_Locked--;
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// miscellaneous
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::attach_to_window(unsigned handle) {
|
|
|
|
ASSERT(m_SurfInit);
|
|
|
|
ddgr_surf_AttachHandle(&ddsfObj, handle);
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Private functions
|
|
|
|
// conversion_xlat
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::xlat8_16(char *data, int w, int h, char *pal) {
|
|
|
|
/* copy from 8bit source bitmap to destination surface just created and
|
|
|
|
locked
|
|
|
|
*/
|
|
|
|
ushort *dptr;
|
|
|
|
char *sptr;
|
|
|
|
int row, col;
|
|
|
|
int rowsize_w;
|
|
|
|
int height, width;
|
|
|
|
ubyte *upal = (ubyte *)pal;
|
|
|
|
|
|
|
|
dptr = (ushort *)m_DataPtr;
|
|
|
|
sptr = (char *)data;
|
|
|
|
rowsize_w = m_DataRowsize / 2;
|
|
|
|
|
|
|
|
height = SET_MIN(h, ddsfObj.h);
|
|
|
|
width = SET_MIN(w, ddsfObj.w);
|
|
|
|
|
|
|
|
for (row = 0; row < height; row++) {
|
|
|
|
for (col = 0; col < width; col++) {
|
|
|
|
ubyte spix = sptr[col];
|
|
|
|
if (spix != 0) {
|
|
|
|
int r = upal[spix * 3] >> 3;
|
|
|
|
int g = upal[spix * 3 + 1] >> 2;
|
|
|
|
int b = upal[spix * 3 + 2] >> 3;
|
|
|
|
ushort destpix = (r << 11) | (g << 5) | b;
|
|
|
|
|
|
|
|
dptr[col] = destpix;
|
|
|
|
} else
|
|
|
|
dptr[col] = 0;
|
|
|
|
}
|
|
|
|
sptr += 256;
|
|
|
|
dptr += rowsize_w;
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::xlat16_16(char *data, int w, int h, int format) {
|
|
|
|
/* 16-bit copy from source bitmap to destination surface just created and
|
|
|
|
locked
|
|
|
|
This function performs scaling if the source width and height don't match
|
|
|
|
that of the destinations - JL
|
|
|
|
*/
|
|
|
|
ushort *sptr, *dptr;
|
|
|
|
int row, col;
|
|
|
|
int rowsize_w;
|
|
|
|
int height, width;
|
|
|
|
fix xstep = IntToFix(w) / ddsfObj.w;
|
|
|
|
fix ystep = IntToFix(h) / ddsfObj.h;
|
|
|
|
fix fu = 0, fv = 0;
|
|
|
|
|
|
|
|
dptr = (ushort *)m_DataPtr;
|
|
|
|
sptr = (ushort *)data;
|
|
|
|
rowsize_w = m_DataRowsize / 2;
|
|
|
|
|
|
|
|
height = ddsfObj.h;
|
|
|
|
width = ddsfObj.w;
|
|
|
|
|
|
|
|
// height = SET_MIN(h, ddsfObj.h);
|
|
|
|
// width = SET_MIN(w, ddsfObj.w);
|
|
|
|
|
|
|
|
for (row = 0; row < height; row++, fv += ystep, fu = 0) {
|
|
|
|
for (col = 0; col < width; col++, fu += xstep) {
|
|
|
|
int newpix;
|
|
|
|
|
|
|
|
if (format == BITMAP_FORMAT_1555)
|
|
|
|
newpix = sptr[(FixToInt(fv) * w) + FixToInt(fu)];
|
|
|
|
else {
|
|
|
|
int temp_pix = sptr[(FixToInt(fv) * w) + FixToInt(fu)];
|
|
|
|
int r = (temp_pix >> 8) & 0xf;
|
|
|
|
int g = (temp_pix >> 4) & 0xf;
|
2024-04-16 20:59:11 +00:00
|
|
|
int b = (temp_pix) & 0xf;
|
2024-04-16 18:56:40 +00:00
|
|
|
|
|
|
|
r <<= 4;
|
|
|
|
g <<= 4;
|
|
|
|
b <<= 4;
|
|
|
|
|
|
|
|
newpix = OPAQUE_FLAG | GR_RGB16(r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
dptr[col] = newpix;
|
|
|
|
}
|
|
|
|
|
|
|
|
dptr += rowsize_w;
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::xlat16_24(char *data, int w, int h) {
|
|
|
|
ushort *sptr;
|
|
|
|
char *dptr;
|
|
|
|
int scol, dcol, row;
|
|
|
|
int height, width;
|
|
|
|
|
|
|
|
dptr = (char *)m_DataPtr;
|
|
|
|
sptr = (ushort *)data;
|
|
|
|
height = SET_MIN(h, ddsfObj.h);
|
|
|
|
width = SET_MIN(w, ddsfObj.w);
|
|
|
|
|
|
|
|
for (row = 0; row < height; row++) {
|
|
|
|
dcol = 0;
|
|
|
|
for (scol = 0; scol < width; scol++) {
|
|
|
|
ushort pix;
|
|
|
|
ddgr_color new_color;
|
|
|
|
char r, g, b;
|
|
|
|
pix = sptr[scol];
|
|
|
|
|
|
|
|
new_color = GR_16_TO_COLOR(pix);
|
|
|
|
|
|
|
|
r = GR_COLOR_RED(new_color);
|
|
|
|
g = GR_COLOR_GREEN(new_color);
|
|
|
|
b = GR_COLOR_BLUE(new_color);
|
|
|
|
|
|
|
|
dptr[dcol++] = r;
|
|
|
|
dptr[dcol++] = g;
|
|
|
|
dptr[dcol++] = b;
|
|
|
|
}
|
|
|
|
sptr += w;
|
|
|
|
dptr += m_DataRowsize;
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::xlat24_16(char *data, int w, int h) {
|
|
|
|
char *sptr;
|
|
|
|
ushort *dptr;
|
|
|
|
int scol, dcol, row;
|
|
|
|
int rowsize_w, height, width;
|
|
|
|
|
|
|
|
dptr = (ushort *)m_DataPtr;
|
|
|
|
sptr = (char *)data;
|
|
|
|
rowsize_w = m_DataRowsize / 2;
|
|
|
|
height = SET_MIN(h, ddsfObj.h);
|
|
|
|
width = SET_MIN(w, ddsfObj.w);
|
|
|
|
|
|
|
|
for (row = 0; row < height; row++) {
|
|
|
|
scol = 0;
|
|
|
|
for (dcol = 0; dcol < width; dcol++) {
|
|
|
|
ushort pix;
|
|
|
|
char r, g, b;
|
|
|
|
r = sptr[scol++];
|
|
|
|
g = sptr[scol++];
|
|
|
|
b = sptr[scol++];
|
|
|
|
pix = ((ushort)(r >> 3) << 11) + ((ushort)(g >> 2) << 5) + ((ushort)(b >> 3));
|
|
|
|
dptr[dcol] = pix;
|
|
|
|
}
|
|
|
|
sptr += (w * 3);
|
|
|
|
dptr += m_DataRowsize;
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::xlat32_16(char *data, int w, int h) {
|
|
|
|
unsigned *sptr;
|
|
|
|
ushort *dptr;
|
|
|
|
int col, row;
|
|
|
|
int rowsize_w, height, width;
|
|
|
|
|
|
|
|
ASSERT((w % 4) == 0);
|
|
|
|
|
|
|
|
dptr = (ushort *)m_DataPtr;
|
|
|
|
sptr = (unsigned *)data;
|
|
|
|
rowsize_w = m_DataRowsize / 2;
|
|
|
|
height = SET_MIN(h, ddsfObj.h);
|
|
|
|
width = SET_MIN(w, ddsfObj.w);
|
|
|
|
|
|
|
|
for (row = 0; row < height; row++) {
|
|
|
|
for (col = 0; col < width; col++) {
|
|
|
|
unsigned pix;
|
|
|
|
ushort spix;
|
|
|
|
|
|
|
|
pix = sptr[col];
|
|
|
|
spix = (ushort)(pix & 0x000000f8) >> 3;
|
|
|
|
spix |= (ushort)(pix & 0x0000fc00) >> 5;
|
|
|
|
spix |= (ushort)(pix & 0x00f80000) >> 8;
|
|
|
|
dptr[col] = spix;
|
|
|
|
}
|
|
|
|
sptr += w;
|
|
|
|
dptr += rowsize_w;
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// surface list functions
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::add_to_list(ddgr_surface *sf) {
|
|
|
|
ddgr_surface_node *node;
|
|
|
|
|
|
|
|
ASSERT(sf != NULL);
|
|
|
|
|
|
|
|
if (!grSurface::surf_list_cur) {
|
|
|
|
// first surface on list
|
|
|
|
node = new ddgr_surface_node;
|
|
|
|
node->sf = sf;
|
|
|
|
node->prev = NULL;
|
|
|
|
grSurface::surf_list = grSurface::surf_list_cur = node;
|
|
|
|
} else {
|
|
|
|
// next surface on list.
|
|
|
|
node = new ddgr_surface_node;
|
|
|
|
node->sf = sf;
|
|
|
|
node->prev = grSurface::surf_list_cur;
|
|
|
|
grSurface::surf_list_cur = node;
|
|
|
|
}
|
|
|
|
|
|
|
|
// mprintf((0, "Allocated surface %s [%d].\n", sf->name, DDData.surfs_alloc));
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void grSurface::remove_from_list(ddgr_surface *sf) {
|
|
|
|
ddgr_surface_node *node, *next_node;
|
|
|
|
|
|
|
|
ASSERT(grSurface::surf_list_cur);
|
|
|
|
ASSERT(sf != NULL);
|
|
|
|
|
|
|
|
// node is current node. next node is node after it on the list. since we are
|
|
|
|
// going from end to beginning, this may confuse you.
|
|
|
|
node = grSurface::surf_list_cur;
|
|
|
|
next_node = NULL; // grSurface::surf_list_cur should be at end of list, so no next node
|
|
|
|
|
|
|
|
while (node) {
|
|
|
|
if (node->sf == sf) {
|
|
|
|
if (next_node) { // delete from within list.
|
|
|
|
next_node->prev = node->prev;
|
|
|
|
} else { // delete from end of list. set list tail to deleted node prev.
|
|
|
|
grSurface::surf_list_cur = node->prev;
|
|
|
|
}
|
|
|
|
delete node;
|
|
|
|
|
|
|
|
node = NULL; // break out of loop
|
|
|
|
} else {
|
|
|
|
// go down one node.
|
|
|
|
next_node = node;
|
|
|
|
node = node->prev;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// mprintf((0, "Freed surface %s [%d].\n", sf->name, DDData.surfs_alloc));
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|