1 // SONIC ROBO BLAST 2
2 //-----------------------------------------------------------------------------
3 // Copyright (C) 2020 by Jaime "Lactozilla" Passos.
4 //
5 // This program is free software distributed under the
6 // terms of the GNU General Public License, version 2.
7 // See the 'LICENSE' file for more details.
8 //-----------------------------------------------------------------------------
9 /// \file  r_patch.c
10 /// \brief Patch generation.
11 
12 #include "doomdef.h"
13 #include "r_patch.h"
14 #include "r_picformats.h"
15 #include "r_defs.h"
16 #include "z_zone.h"
17 
18 #ifdef HWRENDER
19 #include "hardware/hw_glob.h"
20 #endif
21 
22 //
23 // Creates a patch.
24 // Assumes a PU_PATCH zone memory tag and no user, but can always be set later
25 //
26 
Patch_Create(softwarepatch_t * source,size_t srcsize,void * dest)27 patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest)
28 {
29 	patch_t *patch = (dest == NULL) ? Z_Calloc(sizeof(patch_t), PU_PATCH, NULL) : (patch_t *)(dest);
30 
31 	if (source)
32 	{
33 		INT32 col, colsize;
34 		size_t size = sizeof(INT32) * SHORT(source->width);
35 		size_t offs = (sizeof(INT16) * 4) + size;
36 
37 		patch->width      = SHORT(source->width);
38 		patch->height     = SHORT(source->height);
39 		patch->leftoffset = SHORT(source->leftoffset);
40 		patch->topoffset  = SHORT(source->topoffset);
41 		patch->columnofs  = Z_Calloc(size, PU_PATCH_DATA, NULL);
42 
43 		for (col = 0; col < source->width; col++)
44 		{
45 			// This makes the column offsets relative to the column data itself,
46 			// instead of the entire patch data
47 			patch->columnofs[col] = LONG(source->columnofs[col]) - offs;
48 		}
49 
50 		if (!srcsize)
51 			I_Error("Patch_Create: no source size!");
52 
53 		colsize = (INT32)(srcsize) - (INT32)offs;
54 		if (colsize <= 0)
55 			I_Error("Patch_Create: no column data!");
56 
57 		patch->columns = Z_Calloc(colsize, PU_PATCH_DATA, NULL);
58 		M_Memcpy(patch->columns, ((UINT8 *)source + LONG(source->columnofs[0])), colsize);
59 	}
60 
61 	return patch;
62 }
63 
64 //
65 // Frees a patch from memory.
66 //
67 
Patch_FreeData(patch_t * patch)68 static void Patch_FreeData(patch_t *patch)
69 {
70 	INT32 i;
71 
72 #ifdef HWRENDER
73 	if (patch->hardware)
74 		HWR_FreeTexture(patch);
75 #endif
76 
77 	for (i = 0; i < 4; i++)
78 	{
79 		if (patch->flats[i])
80 			Z_Free(patch->flats[i]);
81 	}
82 
83 #ifdef ROTSPRITE
84 	if (patch->rotated)
85 	{
86 		rotsprite_t *rotsprite = patch->rotated;
87 
88 		for (i = 0; i < rotsprite->angles; i++)
89 		{
90 			if (rotsprite->patches[i])
91 				Patch_Free(rotsprite->patches[i]);
92 		}
93 
94 		Z_Free(rotsprite->patches);
95 		Z_Free(rotsprite);
96 	}
97 #endif
98 
99 	if (patch->columnofs)
100 		Z_Free(patch->columnofs);
101 	if (patch->columns)
102 		Z_Free(patch->columns);
103 }
104 
Patch_Free(patch_t * patch)105 void Patch_Free(patch_t *patch)
106 {
107 	Patch_FreeData(patch);
108 	Z_Free(patch);
109 }
110 
111 //
112 // Frees patches with a tag range.
113 //
114 
Patch_FreeTagsCallback(void * mem)115 static boolean Patch_FreeTagsCallback(void *mem)
116 {
117 	patch_t *patch = (patch_t *)mem;
118 	Patch_FreeData(patch);
119 	return true;
120 }
121 
Patch_FreeTags(INT32 lowtag,INT32 hightag)122 void Patch_FreeTags(INT32 lowtag, INT32 hightag)
123 {
124 	Z_IterateTags(lowtag, hightag, Patch_FreeTagsCallback);
125 }
126 
Patch_GenerateFlat(patch_t * patch,pictureflags_t flags)127 void Patch_GenerateFlat(patch_t *patch, pictureflags_t flags)
128 {
129 	UINT8 flip = (flags & (PICFLAGS_XFLIP | PICFLAGS_YFLIP));
130 	if (patch->flats[flip] == NULL)
131 		patch->flats[flip] = Picture_Convert(PICFMT_PATCH, patch, PICFMT_FLAT16, 0, NULL, 0, 0, 0, 0, flags);
132 }
133 
134 #ifdef HWRENDER
135 //
136 // Allocates a hardware patch.
137 //
138 
Patch_AllocateHardwarePatch(patch_t * patch)139 void *Patch_AllocateHardwarePatch(patch_t *patch)
140 {
141 	if (!patch->hardware)
142 	{
143 		GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, &patch->hardware);
144 		grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, &grPatch->mipmap);
145 	}
146 	return (void *)(patch->hardware);
147 }
148 
149 //
150 // Creates a hardware patch.
151 //
152 
Patch_CreateGL(patch_t * patch)153 void *Patch_CreateGL(patch_t *patch)
154 {
155 	GLPatch_t *grPatch = (GLPatch_t *)Patch_AllocateHardwarePatch(patch);
156 	if (!grPatch->mipmap->data) // Run HWR_MakePatch in all cases, to recalculate some things
157 		HWR_MakePatch(patch, grPatch, grPatch->mipmap, false);
158 	return grPatch;
159 }
160 #endif // HWRENDER
161