1 #include "gal.h"
2 #include "resnet.h"
3 
4 GalRenderBackground GalRenderBackgroundFunction;
5 GalCalcPalette GalCalcPaletteFunction;
6 GalDrawBullet GalDrawBulletsFunction;
7 GalExtendTileInfo GalExtendTileInfoFunction;
8 GalExtendSpriteInfo GalExtendSpriteInfoFunction;
9 GalRenderFrame GalRenderFrameFunction;
10 
11 INT32 GalScreenUnflipper = 0;
12 
13 UINT8 GalFlipScreenX;
14 UINT8 GalFlipScreenY;
15 UINT8 *GalGfxBank;
16 UINT8 GalPaletteBank;
17 UINT8 GalSpriteClipStart;
18 UINT8 GalSpriteClipEnd;
19 UINT8 FroggerAdjust;
20 UINT8 GalBackgroundRed;
21 UINT8 GalBackgroundGreen;
22 UINT8 GalBackgroundBlue;
23 UINT8 GalBackgroundEnable;
24 UINT8 SfxTilemap;
25 UINT8 GalOrientationFlipX;
26 UINT8 GalColourDepth;
27 UINT8 DarkplntBulletColour;
28 UINT8 DambustrBgColour1;
29 UINT8 DambustrBgColour2;
30 UINT8 DambustrBgPriority;
31 UINT8 DambustrBgSplitLine;
32 UINT8 *RockclimTiles;
33 UINT16 RockclimScrollX;
34 UINT16 RockclimScrollY;
35 
36 // Graphics decode helpers
37 INT32 CharPlaneOffsets[2]   = { 0, 0x4000 };
38 INT32 CharXOffsets[8]       = { 0, 1, 2, 3, 4, 5, 6, 7 };
39 INT32 CharYOffsets[8]       = { 0, 8, 16, 24, 32, 40, 48, 56 };
40 INT32 SpritePlaneOffsets[2] = { 0, 0x4000 };
41 INT32 SpriteXOffsets[16]    = { 0, 1, 2, 3, 4, 5, 6, 7, 64, 65, 66, 67, 68, 69, 70, 71 };
42 INT32 SpriteYOffsets[16]    = { 0, 8, 16, 24, 32, 40, 48, 56, 128, 136, 144, 152, 160, 168, 176, 184 };
43 
44 // Tile extend helpers
UpperExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32,INT32)45 void UpperExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32, INT32)
46 {
47 	*Code += 0x100;
48 }
49 
PiscesExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32,INT32)50 void PiscesExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32, INT32)
51 {
52 	*Code |= GalGfxBank[0] << 8;
53 }
54 
Batman2ExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32,INT32)55 void Batman2ExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32, INT32)
56 {
57 	if (*Code & 0x80) *Code |= GalGfxBank[0] << 8;
58 }
59 
GmgalaxExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32,INT32)60 void GmgalaxExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32, INT32)
61 {
62 	*Code |= GalGfxBank[0] << 9;
63 }
64 
MooncrstExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32,INT32)65 void MooncrstExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32, INT32)
66 {
67 	if (GalGfxBank[2] && (*Code & 0xc0) == 0x80) *Code = (*Code & 0x3f) | (GalGfxBank[0] << 6) | (GalGfxBank[1] << 7) | 0x0100;
68 }
69 
MoonqsrExtendTileInfo(UINT16 * Code,INT32 *,INT32 Attr,INT32,INT32)70 void MoonqsrExtendTileInfo(UINT16 *Code, INT32*, INT32 Attr, INT32, INT32)
71 {
72 	*Code |= (Attr & 0x20) << 3;
73 }
74 
SkybaseExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32,INT32)75 void SkybaseExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32, INT32)
76 {
77 	*Code |= GalGfxBank[2] << 8;
78 }
79 
JumpbugExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32,INT32)80 void JumpbugExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32, INT32)
81 {
82 	if ((*Code & 0xc0) == 0x80 && (GalGfxBank[2] & 0x01)) *Code += 128 + ((GalGfxBank[0] & 0x01) << 6) + ((GalGfxBank[1] & 0x01) << 7) + ((~GalGfxBank[4] & 0x01) << 8);
83 }
84 
FroggerExtendTileInfo(UINT16 *,INT32 * Colour,INT32,INT32,INT32)85 void FroggerExtendTileInfo(UINT16*, INT32 *Colour, INT32, INT32, INT32)
86 {
87 	*Colour = ((*Colour >> 1) & 0x03) | ((*Colour << 2) & 0x04);
88 }
89 
MshuttleExtendTileInfo(UINT16 * Code,INT32 *,INT32 Attr,INT32,INT32)90 void MshuttleExtendTileInfo(UINT16 *Code, INT32*, INT32 Attr, INT32, INT32)
91 {
92 	*Code |= (Attr & 0x30) << 4;
93 }
94 
Fourin1ExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32,INT32)95 void Fourin1ExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32, INT32)
96 {
97 	*Code |= Fourin1Bank << 8;
98 }
99 
MarinerExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32 x,INT32)100 void MarinerExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x, INT32)
101 {
102 	UINT8 *Prom = GalProm + 0x120;
103 
104 	*Code |= (Prom[x] & 0x01) << 8;
105 }
106 
MimonkeyExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32,INT32)107 void MimonkeyExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32, INT32)
108 {
109 	*Code |= (GalGfxBank[0] << 8) | (GalGfxBank[1] << 9);
110 }
111 
DambustrExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32 x,INT32)112 void DambustrExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x, INT32)
113 {
114 	if (GalGfxBank[0] == 0) {
115 		*Code |= 0x300;
116 	} else {
117 		if (x == 28) {
118 			*Code |= 0x300;
119 		} else {
120 			*Code &= 0xff;
121 		}
122 	}
123 }
124 
Ad2083ExtendTileInfo(UINT16 * Code,INT32 * Colour,INT32 Attr,INT32,INT32)125 void Ad2083ExtendTileInfo(UINT16 *Code, INT32 *Colour, INT32 Attr, INT32, INT32)
126 {
127 	INT32 Bank = Attr & 0x30;
128 	*Code |= (Bank << 4);
129 	*Colour |= ((Attr & 0x40) >> 3);
130 }
131 
RacknrolExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32 x,INT32)132 void RacknrolExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x, INT32)
133 {
134 	UINT8 Bank = GalGfxBank[x] & 7;
135 	*Code |= Bank << 8;
136 }
137 
HaremExtendTileInfo(UINT16 * Code,INT32 * color,INT32,INT32 x,INT32)138 void HaremExtendTileInfo(UINT16 *Code, INT32 *color, INT32, INT32 x, INT32)
139 {
140 	UINT8 Bank = (GalGfxBank[1] >> (x / 4)) & 1;
141 	*Code |= Bank * 0x200;
142 	*color |= GAL_TMAP_OPAQUE; // all Opaque
143 }
144 
NamenayoExtendTileInfo(UINT16 * code,INT32 * color,INT32 attr,INT32 x,INT32 y)145 void NamenayoExtendTileInfo(UINT16 *code, INT32 *color, INT32 attr, INT32 x, INT32 y)
146 {
147 	if (~attr & 1) { // pf/hud
148 		INT32 e_at = namenayo_extattr[y & 0x1f];
149 		*code += (e_at & 0x38) << 5;
150 		*color = (e_at & 0x07);
151 		if (x < (0x1f - 8)) *color |= GAL_TMAP_OPAQUE; // pf: opaque, hud: transparent
152 	} else {
153 		// map
154 		*code += ((attr & 0xfe) == 0x20) ? 0x400 : 0;
155 	}
156 }
157 
BagmanmcExtendTileInfo(UINT16 * Code,INT32 *,INT32,INT32,INT32)158 void BagmanmcExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32, INT32)
159 {
160 	*Code |= GalGfxBank[0] << 9;
161 }
162 
163 // Sprite extend helpers
NamenayoExtendSpriteInfo(const UINT8 * base,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * code,UINT8 * color)164 void NamenayoExtendSpriteInfo(const UINT8 *base, INT32*, INT32*, UINT8*, UINT8*, UINT16 *code, UINT8 *color)
165 {
166 	*code += (base[2] & 0x08) << 3;
167 	*color += 0x08;
168 }
169 
PacmanblExtendSpriteInfo(const UINT8 *,INT32 * sx,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)170 void PacmanblExtendSpriteInfo(const UINT8*, INT32 *sx, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
171 {
172 	// Sprites on the topmost row of the maze are ok, everywhere else need
173 	// their x-offset attenuated to keep sprites off of the maze walls. -dink dec.2020
174 	if (*sx >= 18 && *sx <= 24) {
175 		*sx += 1;
176 	}
177 	if (*sx >= 25 && *sx <= 29) {
178 		*sx += 2;
179 	}
180 	if (*sx >= 30) {
181 		*sx += 3;
182 	}
183 }
184 
UpperExtendSpriteInfo(const UINT8 *,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)185 void UpperExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
186 {
187 	*Code += 0x40;
188 }
189 
PiscesExtendSpriteInfo(const UINT8 *,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)190 void PiscesExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
191 {
192 	*Code |= GalGfxBank[0] << 6;
193 }
194 
GmgalaxExtendSpriteInfo(const UINT8 *,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)195 void GmgalaxExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
196 {
197 	*Code |= (GalGfxBank[0] << 7) | 0x40;
198 }
199 
MooncrstExtendSpriteInfo(const UINT8 *,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)200 void MooncrstExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
201 {
202 	if (GalGfxBank[2] && (*Code & 0x30) == 0x20) *Code = (*Code & 0x0f) | (GalGfxBank[0] << 4) | (GalGfxBank[1] << 5) | 0x40;
203 }
204 
MoonqsrExtendSpriteInfo(const UINT8 * Base,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)205 void MoonqsrExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
206 {
207 	*Code |= (Base[2] & 0x20) << 1;
208 }
209 
SkybaseExtendSpriteInfo(const UINT8 *,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)210 void SkybaseExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
211 {
212 	*Code |= GalGfxBank[2] << 6;
213 }
214 
RockclimExtendSpriteInfo(const UINT8 *,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)215 void RockclimExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
216 {
217 	if ((*Code & 0x30) == 0x20) {
218 		if (GalGfxBank[2] & 1) {
219 			INT32 bank = (((GalGfxBank[0] & 1) << 5) | ((GalGfxBank[1] & 1) << 4));
220 			*Code = (0x40 + bank) | (*Code & 0x0f);
221 		}
222 	}
223 }
224 
JumpbugExtendSpriteInfo(const UINT8 *,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)225 void JumpbugExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
226 {
227 	if ((*Code & 0x30) == 0x20 && (GalGfxBank[2] & 0x01) != 0) *Code += 32 + ((GalGfxBank[0] & 0x01) << 4) + ((GalGfxBank[1] & 0x01) << 5) + ((~GalGfxBank[4] & 0x01) << 6);
228 }
229 
FroggerExtendSpriteInfo(const UINT8 *,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 *,UINT8 * Colour)230 void FroggerExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16*, UINT8 *Colour)
231 {
232 	*Colour = ((*Colour >> 1) & 0x03) | ((*Colour << 2) & 0x04);
233 }
234 
CalipsoExtendSpriteInfo(const UINT8 * Base,INT32 *,INT32 *,UINT8 * xFlip,UINT8 * yFlip,UINT16 * Code,UINT8 *)235 void CalipsoExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8 *yFlip, UINT16 *Code, UINT8*)
236 {
237 	*Code = Base[1];
238 	*xFlip = 0;
239 	*yFlip = 0;
240 }
241 
MshuttleExtendSpriteInfo(const UINT8 * Base,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)242 void MshuttleExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
243 {
244 	*Code |= (Base[2] & 0x30) << 2;
245 }
246 
Fourin1ExtendSpriteInfo(const UINT8 *,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)247 void Fourin1ExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
248 {
249 	*Code |= Fourin1Bank << 6;
250 }
251 
DkongjrmExtendSpriteInfo(const UINT8 * Base,INT32 *,INT32 *,UINT8 * xFlip,UINT8 *,UINT16 * Code,UINT8 *)252 void DkongjrmExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8*, UINT16 *Code, UINT8*)
253 {
254 	*Code = (Base[1] & 0x7f) | 0x80;
255 	*xFlip = 0;
256 }
257 
MimonkeyExtendSpriteInfo(const UINT8 *,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)258 void MimonkeyExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
259 {
260 	*Code |= (GalGfxBank[0] << 6) | (GalGfxBank[1] << 7);
261 }
262 
Ad2083ExtendSpriteInfo(const UINT8 * Base,INT32 *,INT32 *,UINT8 * xFlip,UINT8 *,UINT16 * Code,UINT8 *)263 void Ad2083ExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8*, UINT16 *Code, UINT8*)
264 {
265 	*Code = (Base[1] & 0x7f) | ((Base[2] & 0x30) << 2);
266 	*xFlip = 0;
267 }
268 
BagmanmcExtendSpriteInfo(const UINT8 *,INT32 *,INT32 *,UINT8 *,UINT8 *,UINT16 * Code,UINT8 *)269 void BagmanmcExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*)
270 {
271 	*Code |= (GalGfxBank[0] << 7) | 0x40;
272 }
273 
274 // Hardcode a Galaxian PROM for any games that are missing a PROM dump
HardCodeGalaxianPROM()275 void HardCodeGalaxianPROM()
276 {
277 	GalProm[0x00]= 0x00;
278 	GalProm[0x01]= 0x00;
279 	GalProm[0x02]= 0x00;
280 	GalProm[0x03]= 0xf6;
281 	GalProm[0x04]= 0x00;
282 	GalProm[0x05]= 0x16;
283 	GalProm[0x06]= 0xc0;
284 	GalProm[0x07]= 0x3f;
285 	GalProm[0x08]= 0x00;
286 	GalProm[0x09]= 0xd8;
287 	GalProm[0x0a]= 0x07;
288 	GalProm[0x0b]= 0x3f;
289 	GalProm[0x0c]= 0x00;
290 	GalProm[0x0d]= 0xc0;
291 	GalProm[0x0e]= 0xc4;
292 	GalProm[0x0f]= 0x07;
293 	GalProm[0x10]= 0x00;
294 	GalProm[0x11]= 0xc0;
295 	GalProm[0x12]= 0xa0;
296 	GalProm[0x13]= 0x07;
297 	GalProm[0x14]= 0x00;
298 	GalProm[0x15]= 0x00;
299 	GalProm[0x16]= 0x00;
300 	GalProm[0x17]= 0x07;
301 	GalProm[0x18]= 0x00;
302 	GalProm[0x19]= 0xf6;
303 	GalProm[0x1a]= 0x07;
304 	GalProm[0x1b]= 0xf0;
305 	GalProm[0x1c]= 0x00;
306 	GalProm[0x1d]= 0x76;
307 	GalProm[0x1e]= 0x07;
308 	GalProm[0x1f]= 0xc6;
309 }
310 
HardCodeMooncrstPROM()311 void HardCodeMooncrstPROM()
312 {
313 	GalProm[0x00]= 0x00;
314 	GalProm[0x01]= 0x7a;
315 	GalProm[0x02]= 0x36;
316 	GalProm[0x03]= 0x07;
317 	GalProm[0x04]= 0x00;
318 	GalProm[0x05]= 0xf0;
319 	GalProm[0x06]= 0x38;
320 	GalProm[0x07]= 0x1f;
321 	GalProm[0x08]= 0x00;
322 	GalProm[0x09]= 0xc7;
323 	GalProm[0x0a]= 0xf0;
324 	GalProm[0x0b]= 0x3f;
325 	GalProm[0x0c]= 0x00;
326 	GalProm[0x0d]= 0xdb;
327 	GalProm[0x0e]= 0xc6;
328 	GalProm[0x0f]= 0x38;
329 	GalProm[0x10]= 0x00;
330 	GalProm[0x11]= 0x36;
331 	GalProm[0x12]= 0x07;
332 	GalProm[0x13]= 0xf0;
333 	GalProm[0x14]= 0x00;
334 	GalProm[0x15]= 0x33;
335 	GalProm[0x16]= 0x3f;
336 	GalProm[0x17]= 0xdb;
337 	GalProm[0x18]= 0x00;
338 	GalProm[0x19]= 0x3f;
339 	GalProm[0x1a]= 0x57;
340 	GalProm[0x1b]= 0xc6;
341 	GalProm[0x1c]= 0x00;
342 	GalProm[0x1d]= 0xc6;
343 	GalProm[0x1e]= 0x3f;
344 	GalProm[0x1f]= 0xff;
345 }
346 
347 // Palette generation
348 #define RGB_MAXIMUM			224
349 
GalaxianCalcPalette()350 void GalaxianCalcPalette()
351 {
352 	static const INT32 RGBResistances[3] = {1000, 470, 220};
353 	double rWeights[3], gWeights[3], bWeights[2];
354 
355 	compute_resistor_weights(0, RGB_MAXIMUM, -1.0, 3, &RGBResistances[0], rWeights, 470, 0, 3, &RGBResistances[0], gWeights, 470, 0, 2, &RGBResistances[1], bWeights, 470, 0);
356 
357 	// Colour PROM
358 	for (INT32 i = 0; i < 32; i++) {
359 		UINT8 Bit0, Bit1, Bit2, r, g, b;
360 
361 		Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],0);
362 		Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],1);
363 		Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],2);
364 		r = combine_3_weights(rWeights, Bit0, Bit1, Bit2);
365 
366 		Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],3);
367 		Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],4);
368 		Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],5);
369 		g = combine_3_weights(gWeights, Bit0, Bit1, Bit2);
370 
371 		Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],6);
372 		Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],7);
373 		b = combine_2_weights(bWeights, Bit0, Bit1);
374 
375 		GalPalette[i] = BurnHighCol(r, g, b, 0);
376 	}
377 
378 	// Stars
379 	for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_STARS; i++) {
380 		INT32 Bits, r, g, b;
381 		INT32 Map[4] = {0x00, 0x88, 0xcc, 0xff};
382 
383 		Bits = (i >> 0) & 0x03;
384 		r = Map[Bits];
385 		Bits = (i >> 2) & 0x03;
386 		g = Map[Bits];
387 		Bits = (i >> 4) & 0x03;
388 		b = Map[Bits];
389 
390 		GalPalette[i + GAL_PALETTE_STARS_OFFSET] = BurnHighCol(r, g, b, 0);
391 	}
392 
393 	// Bullets
394 	for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_BULLETS - 1; i++) {
395 		GalPalette[i + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0xff, 0);
396 	}
397 	GalPalette[GAL_PALETTE_NUM_COLOURS_BULLETS - 1 + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0x00, 0);
398 }
399 
RockclimCalcPalette()400 void RockclimCalcPalette()
401 {
402 	static const INT32 RGBResistances[3] = {1000, 470, 220};
403 	double rWeights[3], gWeights[3], bWeights[2];
404 
405 	compute_resistor_weights(0, RGB_MAXIMUM, -1.0, 3, &RGBResistances[0], rWeights, 470, 0, 3, &RGBResistances[0], gWeights, 470, 0, 2, &RGBResistances[1], bWeights, 470, 0);
406 
407 	// Colour PROM
408 	for (INT32 i = 0; i < 64; i++) {
409 		UINT8 Bit0, Bit1, Bit2, r, g, b;
410 
411 		Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],0);
412 		Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],1);
413 		Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],2);
414 		r = combine_3_weights(rWeights, Bit0, Bit1, Bit2);
415 
416 		Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],3);
417 		Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],4);
418 		Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],5);
419 		g = combine_3_weights(gWeights, Bit0, Bit1, Bit2);
420 
421 		Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],6);
422 		Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],7);
423 		b = combine_2_weights(bWeights, Bit0, Bit1);
424 
425 		GalPalette[i] = BurnHighCol(r, g, b, 0);
426 	}
427 
428 	// Stars
429 	for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_STARS; i++) {
430 		INT32 Bits, r, g, b;
431 		INT32 Map[4] = {0x00, 0x88, 0xcc, 0xff};
432 
433 		Bits = (i >> 0) & 0x03;
434 		r = Map[Bits];
435 		Bits = (i >> 2) & 0x03;
436 		g = Map[Bits];
437 		Bits = (i >> 4) & 0x03;
438 		b = Map[Bits];
439 
440 		GalPalette[i + GAL_PALETTE_STARS_OFFSET] = BurnHighCol(r, g, b, 0);
441 	}
442 
443 	// Bullets
444 	for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_BULLETS - 1; i++) {
445 		GalPalette[i + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0xff, 0);
446 	}
447 	GalPalette[GAL_PALETTE_NUM_COLOURS_BULLETS - 1 + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0x00, 0);
448 }
449 
MarinerCalcPalette()450 void MarinerCalcPalette()
451 {
452 	GalaxianCalcPalette();
453 
454 	for (INT32 i = 0; i < 16; i++) {
455 		INT32 b = 0x0e * BIT(i, 0) + 0x1f * BIT(i, 1) + 0x43 * BIT(i, 2) + 0x8f * BIT(i, 3);
456 		GalPalette[i + GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(0, 0, b, 0);
457 	}
458 }
459 
StratgyxCalcPalette()460 void StratgyxCalcPalette()
461 {
462 	GalaxianCalcPalette();
463 
464 	for (INT32 i = 0; i < 8; i++) {
465 		INT32 r = BIT(i, 0) * 0x7c;
466 		INT32 g = BIT(i, 1) * 0x3c;
467 		INT32 b = BIT(i, 2) * 0x47;
468 		GalPalette[i + GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(r, g, b, 0);
469 	}
470 }
471 
RescueCalcPalette()472 void RescueCalcPalette()
473 {
474 	GalaxianCalcPalette();
475 
476 	for (INT32 i = 0; i < 128; i++) {
477 		INT32 b = i * 2;
478 		GalPalette[i + GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(0, 0, b, 0);
479 	}
480 }
481 
MinefldCalcPalette()482 void MinefldCalcPalette()
483 {
484 	RescueCalcPalette();
485 
486 	for (INT32 i = 0; i < 128; i++) {
487 		INT32 r = (INT32)(i * 1.5);
488 		INT32 g = (INT32)(i * 0.75);
489 		INT32 b = i / 2;
490 		GalPalette[i + 128 + GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(r, g, b, 0);
491 	}
492 }
493 
DarkplntCalcPalette()494 void DarkplntCalcPalette()
495 {
496 	static const INT32 RGBResistances[3] = {1000, 470, 220};
497 	double rWeights[3], gWeights[3], bWeights[2];
498 
499 	compute_resistor_weights(0, RGB_MAXIMUM, -1.0, 3, &RGBResistances[0], rWeights, 470, 0, 3, &RGBResistances[0], gWeights, 470, 0, 2, &RGBResistances[1], bWeights, 470, 0);
500 
501 	// Colour PROM
502 	for (INT32 i = 0; i < 32; i++) {
503 		UINT8 Bit0, Bit1, Bit2, r, g, b;
504 
505 		Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],0);
506 		Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],1);
507 		Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],2);
508 		r = combine_3_weights(rWeights, Bit0, Bit1, Bit2);
509 
510 		g = 0;
511 
512 		Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],3);
513 		Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],4);
514 		Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],5);
515 		b = combine_2_weights(bWeights, Bit0, Bit1);
516 
517 		GalPalette[i] = BurnHighCol(r, g, b, 0);
518 	}
519 
520 	// Stars
521 	for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_STARS; i++) {
522 		INT32 Bits, r, g, b;
523 		INT32 Map[4] = {0x00, 0x88, 0xcc, 0xff};
524 
525 		Bits = (i >> 0) & 0x03;
526 		r = Map[Bits];
527 		Bits = (i >> 2) & 0x03;
528 		g = Map[Bits];
529 		Bits = (i >> 4) & 0x03;
530 		b = Map[Bits];
531 
532 		GalPalette[i + GAL_PALETTE_STARS_OFFSET] = BurnHighCol(r, g, b, 0);
533 	}
534 
535 	// Bullets
536 	GalPalette[0 + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xef, 0x00, 0x00, 0);
537 	GalPalette[1 + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0x00, 0x00, 0xef, 0);
538 }
539 
DambustrCalcPalette()540 void DambustrCalcPalette()
541 {
542 	static const INT32 RGBResistances[3] = {1000, 470, 220};
543 	double rWeights[3], gWeights[3], bWeights[2];
544 
545 	compute_resistor_weights(0, RGB_MAXIMUM, -1.0, 3, &RGBResistances[0], rWeights, 470, 0, 3, &RGBResistances[0], gWeights, 470, 0, 2, &RGBResistances[1], bWeights, 470, 0);
546 
547 	// Colour PROM
548 	for (INT32 i = 0; i < 32; i++) {
549 		UINT8 Bit0, Bit1, Bit2, r, g, b;
550 
551 		Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],0);
552 		Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],1);
553 		Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],2);
554 		b = combine_3_weights(rWeights, Bit0, Bit1, Bit2);
555 
556 		Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],3);
557 		Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],4);
558 		Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],5);
559 		r = combine_3_weights(gWeights, Bit0, Bit1, Bit2);
560 
561 		Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],6);
562 		Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],7);
563 		g = combine_2_weights(bWeights, Bit0, Bit1);
564 
565 		GalPalette[i] = BurnHighCol(r, g, b, 0);
566 	}
567 
568 	// Stars
569 	for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_STARS; i++) {
570 		INT32 Bits, r, g, b;
571 		INT32 Map[4] = {0x00, 0x88, 0xcc, 0xff};
572 
573 		Bits = (i >> 0) & 0x03;
574 		r = Map[Bits];
575 		Bits = (i >> 2) & 0x03;
576 		g = Map[Bits];
577 		Bits = (i >> 4) & 0x03;
578 		b = Map[Bits];
579 
580 		GalPalette[i + GAL_PALETTE_STARS_OFFSET] = BurnHighCol(r, g, b, 0);
581 	}
582 
583 	// Bullets
584 	for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_BULLETS - 1; i++) {
585 		GalPalette[i + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0xff, 0);
586 	}
587 	GalPalette[GAL_PALETTE_NUM_COLOURS_BULLETS - 1 + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0x00, 0);
588 
589 	for (INT32 i = 0; i < 8; i++) {
590 		INT32 r = BIT(i, 0) * 0x47;
591 		INT32 g = BIT(i, 1) * 0x47;
592 		INT32 b = BIT(i, 2) * 0x4f;
593 		GalPalette[i + GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(r, g, b, 0);
594 	}
595 }
596 
597 #undef RGB_MAXIMUM
598 
599 // Background and Stars rendering
GalaxianDrawBackground()600 void GalaxianDrawBackground()
601 {
602 	if (GalStarsEnable) GalaxianRenderStarLayer();
603 }
604 
RockclimDrawBackground()605 void RockclimDrawBackground()
606 {
607 	INT32 mx, my, Code, Colour, x, y, TileIndex = 0;
608 
609 	for (my = 0; my < 32; my++) {
610 		for (mx = 0; mx < 64; mx++) {
611 			Code = GalVideoRam2[TileIndex];
612 			Colour = 0;
613 
614 			x = 8 * mx;
615 			y = 8 * my;
616 
617 			x -= RockclimScrollX & 0x1ff;
618 			y -= RockclimScrollY & 0xff;
619 
620 			if (x < -8) x += 512;
621 			if (y < -8) y += 256;
622 
623 			y -= 16;
624 
625 			if (GalFlipScreenX) x = nScreenWidth - 8 - x;
626 			if (GalFlipScreenY) y = nScreenHeight - 8 - y;
627 
628 			Draw8x8Tile(pTransDraw, Code, x, y, GalFlipScreenX, GalFlipScreenY, Colour, 4, 32, RockclimTiles);
629 
630 			TileIndex++;
631 		}
632 	}
633 }
634 
JumpbugDrawBackground()635 void JumpbugDrawBackground()
636 {
637 	if (GalStarsEnable) JumpbugRenderStarLayer();
638 }
639 
FroggerDrawBackground()640 void FroggerDrawBackground()
641 {
642 	GalPalette[GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(0, 0, 0x47, 0);
643 
644 	if (GalFlipScreenX) {
645 		for (INT32 y = 0; y < nScreenHeight; y++) {
646 			for (INT32 x = nScreenWidth - 1; x > 128 - 8; x--) {
647 				pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET;
648 			}
649 		}
650 	} else {
651 		for (INT32 y = 0; y < nScreenHeight; y++) {
652 			for (INT32 x = 0; x < 128; x++) {
653 				pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET;
654 			}
655 		}
656 	}
657 }
658 
TurtlesDrawBackground()659 void TurtlesDrawBackground()
660 {
661 	GalPalette[GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(GalBackgroundRed * 0x55, GalBackgroundGreen * 0x47, GalBackgroundBlue * 0x55, 0);
662 
663 	for (INT32 y = 0; y < nScreenHeight; y++) {
664 		for (INT32 x = 0; x < nScreenWidth; x++) {
665 			pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET;
666 		}
667 	}
668 }
669 
ScrambleDrawBackground()670 void ScrambleDrawBackground()
671 {
672 	GalPalette[GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(0, 0, 0x56, 0);
673 
674 	if (GalBackgroundEnable) {
675 		for (INT32 y = 0; y < nScreenHeight; y++) {
676 			for (INT32 x = 0; x < nScreenWidth; x++) {
677 				pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET;
678 			}
679 		}
680 	}
681 
682 	if (GalStarsEnable) ScrambleRenderStarLayer();
683 }
684 
AnteaterDrawBackground()685 void AnteaterDrawBackground()
686 {
687 	GalPalette[GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(0, 0, 0x56, 0);
688 
689 	if (GalBackgroundEnable) {
690 		if (GalFlipScreenX) {
691 			for (INT32 y = 0; y < nScreenHeight; y++) {
692 				for (INT32 x = nScreenWidth - 1; x > 256 - 56; x--) {
693 					pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET;
694 				}
695 			}
696 		} else {
697 			for (INT32 y = 0; y < nScreenHeight; y++) {
698 				for (INT32 x = 0; x < 56; x++) {
699 					pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET;
700 				}
701 			}
702 		}
703 	}
704 }
705 
MarinerDrawBackground()706 void MarinerDrawBackground()
707 {
708 	UINT8 *BgColourProm = GalProm + 0x20;
709 	INT32 x;
710 
711 	if (GalFlipScreenX) {
712 		for (x = 0; x < 32; x++) {
713 			INT32 Colour;
714 
715 			if (x == 0) {
716 				Colour = 0;
717 			} else {
718 				Colour = BgColourProm[0x20 + x - 1];
719 			}
720 
721 			INT32 xStart = 8 * (31 - x);
722 			for (INT32 sy = 0; sy < nScreenHeight; sy++) {
723 				for (INT32 sx = xStart; sx < xStart + 8; sx++) {
724 					pTransDraw[(sy * nScreenWidth) + sx] = GAL_PALETTE_BACKGROUND_OFFSET + Colour;
725 				}
726 			}
727 		}
728 	} else {
729 		for (x = 0; x < 32; x++) {
730 			INT32 Colour;
731 
732 			if (x == 31) {
733 				Colour = 0;
734 			} else {
735 				Colour = BgColourProm[x + 1];
736 			}
737 
738 			INT32 xStart = x * 8;
739 			for (INT32 sy = 0; sy < nScreenHeight; sy++) {
740 				for (INT32 sx = xStart; sx < xStart + 8; sx++) {
741 					pTransDraw[(sy * nScreenWidth) + sx] = GAL_PALETTE_BACKGROUND_OFFSET + Colour;
742 				}
743 			}
744 		}
745 	}
746 
747 	if (GalStarsEnable) MarinerRenderStarLayer();
748 }
749 
StratgyxDrawBackground()750 void StratgyxDrawBackground()
751 {
752 	UINT8 *BgColourProm = GalProm + 0x20;
753 
754 	for (INT32 x = 0; x < 32; x++) {
755 		INT32 xStart, Colour = 0;
756 
757 		if ((~BgColourProm[x] & 0x02) && GalBackgroundRed)   Colour |= 0x01;
758 		if ((~BgColourProm[x] & 0x02) && GalBackgroundGreen) Colour |= 0x02;
759 		if ((~BgColourProm[x] & 0x01) && GalBackgroundBlue)  Colour |= 0x04;
760 
761 		if (GalFlipScreenX) {
762 			xStart = 8 * (31 - x);
763 		} else {
764 			xStart = 8 * x;
765 		}
766 
767 		for (INT32 sy = 0; sy < nScreenHeight; sy++) {
768 			for (INT32 sx = xStart; sx < xStart + 8; sx++) {
769 				pTransDraw[(sy * nScreenWidth) + sx] = GAL_PALETTE_BACKGROUND_OFFSET + Colour;
770 			}
771 		}
772 	}
773 }
774 
RescueDrawBackground()775 void RescueDrawBackground()
776 {
777 	if (GalBackgroundEnable) {
778 		INT32 x;
779 
780 		for (x = 0; x < 128; x++) {
781 			for (INT32 y = 0; y < nScreenHeight; y++) {
782 				pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET + x;
783 			}
784 		}
785 
786 		for (x = 0; x < 120; x++) {
787 			for (INT32 y = 0; y < nScreenHeight; y++) {
788 				pTransDraw[(y * nScreenWidth) + (x + 128)] = GAL_PALETTE_BACKGROUND_OFFSET + x + 8;
789 			}
790 		}
791 
792 		for (x = 0; x < 8; x++) {
793 			for (INT32 y = 0; y < nScreenHeight; y++) {
794 				pTransDraw[(y * nScreenWidth) + (x + 248)] = GAL_PALETTE_BACKGROUND_OFFSET;
795 			}
796 		}
797 	}
798 
799 	if (GalStarsEnable) RescueRenderStarLayer();
800 }
801 
MinefldDrawBackground()802 void MinefldDrawBackground()
803 {
804 	if (GalBackgroundEnable) {
805 		INT32 x;
806 
807 		for (x = 0; x < 128; x++) {
808 			for (INT32 y = 0; y < nScreenHeight; y++) {
809 				pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET + x;
810 			}
811 		}
812 
813 		for (x = 0; x < 120; x++) {
814 			for (INT32 y = 0; y < nScreenHeight; y++) {
815 				pTransDraw[(y * nScreenWidth) + (x + 128)] = GAL_PALETTE_BACKGROUND_OFFSET + x + 128;
816 			}
817 		}
818 
819 		for (x = 0; x < 8; x++) {
820 			for (INT32 y = 0; y < nScreenHeight; y++) {
821 				pTransDraw[(y * nScreenWidth) + (x + 248)] = GAL_PALETTE_BACKGROUND_OFFSET;
822 			}
823 		}
824 	}
825 
826 	if (GalStarsEnable) RescueRenderStarLayer();
827 }
828 
DambustrDrawBackground()829 void DambustrDrawBackground()
830 {
831 	INT32 xClipStart = GalFlipScreenX ? 254 - DambustrBgSplitLine : 0;
832 	INT32 xClipEnd = GalFlipScreenX ? 0 : 254 - DambustrBgSplitLine;
833 
834 	for (INT32 x = 0; x < 256 - DambustrBgSplitLine; x++) {
835 		if (DambustrBgPriority && (x < xClipStart || x > xClipEnd)) continue;
836 		for (INT32 y = 0; y < nScreenHeight; y++) {
837 			pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET + ((GalFlipScreenX) ? DambustrBgColour2 : DambustrBgColour1);
838 		}
839 	}
840 
841 	for (INT32 x = 255; x > 256 - DambustrBgSplitLine; x--) {
842 		if (DambustrBgPriority && (x < xClipStart || x > xClipEnd)) continue;
843 		for (INT32 y = 0; y < nScreenHeight; y++) {
844 			pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET + ((GalFlipScreenX) ? DambustrBgColour1 : DambustrBgColour2);
845 		}
846 	}
847 
848 	if (GalStarsEnable && !DambustrBgPriority) GalaxianRenderStarLayer();
849 }
850 
851 // Char Layer rendering
GalRenderBgLayer(UINT8 * pVideoRam)852 static void GalRenderBgLayer(UINT8 *pVideoRam)
853 {
854 	INT32 mx, my, Attr, Colour, x, y, TileIndex = 0, RamPos, DrawOpaque;
855 	UINT16 Code;
856 
857 	for (my = 0; my < 32; my++) {
858 		for (mx = 0; mx < 32; mx++) {
859 			RamPos = TileIndex & 0x1f;
860 			Code = pVideoRam[TileIndex];
861 			Attr = GalSpriteRam[(RamPos * 2) + 1];
862 			Colour = Attr  & ((GalColourDepth == 3) ? 0x03 : 0x07);
863 
864 			if (GalExtendTileInfoFunction) GalExtendTileInfoFunction(&Code, &Colour, Attr, RamPos, TileIndex >> 5);
865 
866 			DrawOpaque = Colour & GAL_TMAP_OPAQUE; // extended tile info can tag Opaque this way
867 			Colour &= ~GAL_TMAP_OPAQUE;
868 
869 			if (SfxTilemap) {
870 				x = 8 * my;
871 				y = 8 * mx;
872 			} else {
873 				x = 8 * mx;
874 				y = 8 * my;
875 			}
876 
877 			y -= 16;
878 
879 			if (GalFlipScreenX) x = nScreenWidth - 8 - x;
880 			if (GalFlipScreenY) y = nScreenHeight - 8 - y;
881 
882 			INT32 px, py;
883 
884 			UINT32 nPalette = Colour << GalColourDepth;
885 
886 			for (py = 0; py < 8; py++) {
887 				for (px = 0; px < 8; px++) {
888 					UINT8 c = GalChars[(Code * 64) + (py * 8) + px];
889 					if (GalFlipScreenX) c = GalChars[(Code * 64) + (py * 8) + (7 - px)];
890 					if (GalFlipScreenY) c = GalChars[(Code * 64) + ((7 - py) * 8) + px];
891 					if (GalFlipScreenX && GalFlipScreenY) c = GalChars[(Code * 64) + ((7 - py) * 8) + (7 - px)];
892 
893 					if (c || DrawOpaque) { // Harem, Namenayo has no transparency on this layer
894 						INT32 xPos = x + px;
895 						INT32 yPos = y + py;
896 
897 						if (SfxTilemap) {
898 							if (GalFlipScreenX) {
899 								xPos += GalScrollVals[mx];
900 							} else {
901 								xPos -= GalScrollVals[mx];
902 							}
903 
904 							if (xPos < 0) xPos += 256;
905 							if (xPos > 255) xPos -= 256;
906 						} else {
907 							if (GalFlipScreenY) {
908 								yPos += GalScrollVals[mx];
909 							} else {
910 								yPos -= GalScrollVals[mx];
911 							}
912 
913 							if (yPos < 0) yPos += 256;
914 							if (yPos > 255) yPos -= 256;
915 						}
916 
917 						if (GalOrientationFlipX) {
918 							xPos = nScreenWidth - 1 - xPos;
919 						}
920 
921 						if (yPos >= 0 && yPos < nScreenHeight) {
922 							UINT16* pPixel = pTransDraw + (yPos * nScreenWidth);
923 
924 							if (xPos >= 0 && xPos < nScreenWidth) {
925 								pPixel[xPos] = c | nPalette;
926 							}
927 						}
928 					}
929 				}
930 			}
931 
932 			TileIndex++;
933 		}
934 	}
935 }
936 
937 // Sprite Rendering
GalRenderSprites(const UINT8 * SpriteBase)938 static void GalRenderSprites(const UINT8 *SpriteBase)
939 {
940 	INT32 SprNum;
941 	INT32 ClipOfs = GalFlipScreenX ? 16 : 0;
942 	INT32 xMin = GalSpriteClipStart - ClipOfs;
943 	INT32 xMax = GalSpriteClipEnd - ClipOfs + 1;
944 
945 	for (SprNum = 7; SprNum >= 0; SprNum--) {
946 		const UINT8 *Base = &SpriteBase[SprNum * 4];
947 		UINT8 Base0 = FroggerAdjust ? ((Base[0] >> 4) | (Base[0] << 4)) : Base[0];
948 		INT32 sy = 240 - (Base0 - (SprNum < 3));
949 		UINT16 Code = Base[1] & 0x3f;
950 		UINT8 xFlip = Base[1] & 0x40;
951 		UINT8 yFlip = Base[1] & 0x80;
952 		UINT8 Colour = Base[2] & ((GalColourDepth == 3) ? 0x03 : 0x07);
953 		INT32 sx = Base[3];
954 
955 		if (GalExtendSpriteInfoFunction) GalExtendSpriteInfoFunction(Base, &sx, &sy, &xFlip, &yFlip, &Code, &Colour);
956 
957 		if (GalFlipScreenX) {
958 			sx = 242 - sx;
959 			xFlip = !xFlip;
960 		}
961 
962 		if (sx < xMin || sx > xMax) continue;
963 
964 		if (GalFlipScreenY) {
965 			sy = 240 - sy;
966 			yFlip = !yFlip;
967 		}
968 
969 		sy -= 16;
970 
971 		if (GalOrientationFlipX) {
972 			sx = 242 - 1 - sx;
973 			xFlip = !xFlip;
974 		}
975 
976 		Draw16x16MaskTile(pTransDraw, Code, sx, sy, xFlip, yFlip, Colour, GalColourDepth, 0, 0, GalSprites);
977 	}
978 }
979 
980 // Bullet rendering
GalDrawPixel(INT32 x,INT32 y,INT32 Colour)981 static inline void GalDrawPixel(INT32 x, INT32 y, INT32 Colour)
982 {
983 	if (y >= 0 && y < nScreenHeight && x >= 0 && x < nScreenWidth) {
984 		pTransDraw[(y * nScreenWidth) + x] = Colour;
985 	}
986 }
987 
GalaxianDrawBullets(INT32 Offs,INT32 x,INT32 y)988 void GalaxianDrawBullets(INT32 Offs, INT32 x, INT32 y)
989 {
990 	x -= 4;
991 
992 	GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs);
993 	GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs);
994 	GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs);
995 	GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs);
996 }
997 
TheendDrawBullets(INT32 Offs,INT32 x,INT32 y)998 void TheendDrawBullets(INT32 Offs, INT32 x, INT32 y)
999 {
1000 	x -= 4;
1001 
1002 	GalPalette[GAL_PALETTE_BULLETS_OFFSET + 7] = BurnHighCol(0xff, 0x00, 0xff, 0);
1003 
1004 	GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs);
1005 	GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs);
1006 	GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs);
1007 	GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs);
1008 }
1009 
ScrambleDrawBullets(INT32,INT32 x,INT32 y)1010 void ScrambleDrawBullets(INT32, INT32 x, INT32 y)
1011 {
1012 	x -= 6;
1013 
1014 	GalDrawPixel(x, y, GAL_PALETTE_BULLETS_OFFSET + 7);
1015 }
1016 
MoonwarDrawBullets(INT32,INT32 x,INT32 y)1017 void MoonwarDrawBullets(INT32, INT32 x, INT32 y)
1018 {
1019 	x -= 6;
1020 
1021 	GalPalette[GAL_PALETTE_BULLETS_OFFSET + 7] = BurnHighCol(0xef, 0xef, 0x97, 0);
1022 
1023 	GalDrawPixel(x, y, GAL_PALETTE_BULLETS_OFFSET + 7);
1024 }
1025 
MshuttleDrawBullets(INT32,INT32 x,INT32 y)1026 void MshuttleDrawBullets(INT32, INT32 x, INT32 y)
1027 {
1028 	GalPalette[GAL_PALETTE_BULLETS_OFFSET + 0] = BurnHighCol(0xff, 0xff, 0xff, 0);
1029 	GalPalette[GAL_PALETTE_BULLETS_OFFSET + 1] = BurnHighCol(0xff, 0xff, 0x00, 0);
1030 	GalPalette[GAL_PALETTE_BULLETS_OFFSET + 2] = BurnHighCol(0x00, 0xff, 0xff, 0);
1031 	GalPalette[GAL_PALETTE_BULLETS_OFFSET + 3] = BurnHighCol(0x00, 0xff, 0x00, 0);
1032 	GalPalette[GAL_PALETTE_BULLETS_OFFSET + 4] = BurnHighCol(0xff, 0x00, 0xff, 0);
1033 	GalPalette[GAL_PALETTE_BULLETS_OFFSET + 5] = BurnHighCol(0xff, 0x00, 0x00, 0);
1034 	GalPalette[GAL_PALETTE_BULLETS_OFFSET + 6] = BurnHighCol(0x00, 0x00, 0xff, 0);
1035 	GalPalette[GAL_PALETTE_BULLETS_OFFSET + 7] = BurnHighCol(0x00, 0x00, 0x00, 0);
1036 
1037 	--x;
1038 	GalDrawPixel(x, y, ((x & 0x40) == 0) ? GAL_PALETTE_BULLETS_OFFSET +  + ((x >> 2) & 7) : GAL_PALETTE_BULLETS_OFFSET +  + 4);
1039 	--x;
1040 	GalDrawPixel(x, y, ((x & 0x40) == 0) ? GAL_PALETTE_BULLETS_OFFSET +  + ((x >> 2) & 7) : GAL_PALETTE_BULLETS_OFFSET +  + 4);
1041 	--x;
1042 	GalDrawPixel(x, y, ((x & 0x40) == 0) ? GAL_PALETTE_BULLETS_OFFSET +  + ((x >> 2) & 7) : GAL_PALETTE_BULLETS_OFFSET +  + 4);
1043 	--x;
1044 	GalDrawPixel(x, y, ((x & 0x40) == 0) ? GAL_PALETTE_BULLETS_OFFSET +  + ((x >> 2) & 7) : GAL_PALETTE_BULLETS_OFFSET +  + 4);
1045 }
1046 
DarkplntDrawBullets(INT32,INT32 x,INT32 y)1047 void DarkplntDrawBullets(INT32, INT32 x, INT32 y)
1048 {
1049 	if (GalFlipScreenX) x++;
1050 
1051 	x -= 6;
1052 
1053 	GalDrawPixel(x, y, GAL_PALETTE_BULLETS_OFFSET + DarkplntBulletColour);
1054 }
1055 
DambustrDrawBullets(INT32 Offs,INT32 x,INT32 y)1056 void DambustrDrawBullets(INT32 Offs, INT32 x, INT32 y)
1057 {
1058 	INT32 Colour;
1059 
1060 	if (GalFlipScreenX) x++;
1061 
1062 	x -= 6;
1063 
1064 	for (INT32 i = 0; i < 2; i++) {
1065 		if (Offs < 16) {
1066 			Colour = GAL_PALETTE_BULLETS_OFFSET + 7;
1067 			y--;
1068 		} else {
1069 			Colour = GAL_PALETTE_BULLETS_OFFSET;
1070 			x--;
1071 		}
1072 	}
1073 
1074 	GalDrawPixel(x, y, Colour);
1075 }
1076 
GalDrawBullets(const UINT8 * Base)1077 static void GalDrawBullets(const UINT8 *Base)
1078 {
1079 	for (INT32 y = 0; y < nScreenHeight; y++) {
1080 		UINT8 Shell = 0xff;
1081 		UINT8 Missile = 0xff;
1082 		UINT8 yEff;
1083 		INT32 Which;
1084 
1085 		yEff = (GalFlipScreenY) ? (y + 16 - 1) ^ 255 : y + 16 - 1;
1086 
1087 		for (Which = 0; Which < 3; Which++) {
1088 			if ((UINT8)(Base[Which * 4 + 1] + yEff) == 0xff) Shell = Which;
1089 		}
1090 
1091 		yEff = (GalFlipScreenY) ? (y + 16) ^ 255 : y + 16;
1092 
1093 		for (Which = 3; Which < 8; Which++) {
1094 			if ((UINT8)(Base[Which * 4 + 1] + yEff) == 0xff) {
1095 				if (Which != 7) {
1096 					Shell = Which;
1097 				} else {
1098 					Missile = Which;
1099 				}
1100 			}
1101 		}
1102 
1103 		if (Shell != 0xff) GalDrawBulletsFunction(Shell, (GalOrientationFlipX) ? Base[Shell * 4 + 3] : 255 - Base[Shell * 4 + 3], y);
1104 		if (Missile != 0xff) GalDrawBulletsFunction(Missile, (GalOrientationFlipX) ? Base[Missile * 4 + 3] : 255 - Base[Missile * 4 + 3], y);
1105 	}
1106 }
1107 
1108 // Add before BurnTransferCopy(); for the game you want to fix below & GalScreenUnflipper = 1 in game's init.
Coctail_Unflippy()1109 static void Coctail_Unflippy()
1110 {
1111 	if (GalScreenUnflipper) {
1112 		BurnTransferFlip(GalFlipScreenX, GalFlipScreenY);
1113 	}
1114 }
1115 
1116 // Render a frame
GalDraw()1117 INT32 GalDraw()
1118 {
1119 	if (GalRenderFrameFunction) {
1120 		GalRenderFrameFunction();
1121 	} else {
1122 		BurnTransferClear();
1123 		GalCalcPaletteFunction();
1124 
1125 		if (nBurnLayer & 1 && GalRenderBackgroundFunction)
1126 			GalRenderBackgroundFunction();
1127 		if (nBurnLayer & 2)
1128 			GalRenderBgLayer(GalVideoRam);
1129 		if (nSpriteEnable & 1)
1130 			GalRenderSprites(&GalSpriteRam[0x40]);
1131 		if (nSpriteEnable & 2 && GalDrawBulletsFunction)
1132 			GalDrawBullets(&GalSpriteRam[0x60]);
1133 
1134 		Coctail_Unflippy();
1135 		BurnTransferCopy(GalPalette);
1136 	}
1137 
1138 	return 0;
1139 }
1140 
ZigZagRenderFrame()1141 void ZigZagRenderFrame()
1142 {
1143 	BurnTransferClear();
1144 	GalCalcPaletteFunction();
1145 	if (GalRenderBackgroundFunction) GalRenderBackgroundFunction();
1146 	GalRenderBgLayer(GalVideoRam);
1147 	GalRenderSprites(&GalSpriteRam[0x40]);
1148 	GalRenderSprites(&GalSpriteRam[0x40 + 0x20]);
1149 	//if (GalDrawBulletsFunction) GalDrawBullets(&GalSpriteRam[0x60]);
1150 	Coctail_Unflippy();
1151 	BurnTransferCopy(GalPalette);
1152 }
1153 
DkongjrmRenderFrame()1154 void DkongjrmRenderFrame()
1155 {
1156 	BurnTransferClear();
1157 	GalCalcPaletteFunction();
1158 	if (GalRenderBackgroundFunction) GalRenderBackgroundFunction();
1159 	GalRenderBgLayer(GalVideoRam);
1160 	GalRenderSprites(&GalSpriteRam[0x40]);
1161 	GalRenderSprites(&GalSpriteRam[0x60]);
1162 	GalRenderSprites(&GalSpriteRam[0xc0]);
1163 	GalRenderSprites(&GalSpriteRam[0xe0]);
1164 	if (GalDrawBulletsFunction) GalDrawBullets(&GalSpriteRam[0x60]);
1165 	Coctail_Unflippy();
1166 	BurnTransferCopy(GalPalette);
1167 }
1168 
DambustrRenderFrame()1169 void DambustrRenderFrame()
1170 {
1171 	BurnTransferClear();
1172 	GalCalcPaletteFunction();
1173 	if (GalRenderBackgroundFunction) GalRenderBackgroundFunction();
1174 	GalRenderBgLayer(GalVideoRam);
1175 	GalRenderSprites(&GalSpriteRam[0x40]);
1176 	if (GalDrawBulletsFunction) GalDrawBullets(&GalSpriteRam[0x60]);
1177 	if (DambustrBgPriority) {
1178 		if (GalRenderBackgroundFunction) GalRenderBackgroundFunction();
1179 		memset(GalVideoRam2, 0x20, 0x400);
1180 		for (INT32 i = 0; i < 32; i++) {
1181 			INT32 Colour = GalSpriteRam[(i << 1) | 1] & 7;
1182 			if (Colour > 3) {
1183 				for (INT32 j = 0; j < 32; j++) GalVideoRam2[(32 * j) + i] = GalVideoRam[(32 * j) + i];
1184 			}
1185 		}
1186 		GalRenderBgLayer(GalVideoRam2);
1187 	}
1188 	Coctail_Unflippy();
1189 	BurnTransferCopy(GalPalette);
1190 }
1191 
FantastcRenderFrame()1192 void FantastcRenderFrame()
1193 {
1194 	BurnTransferClear();
1195 	GalCalcPaletteFunction();
1196 	if (GalRenderBackgroundFunction) GalRenderBackgroundFunction();
1197 	GalRenderBgLayer(GalVideoRam);
1198 	GalRenderSprites(&GalSpriteRam[0x40]);
1199 	if (GalDrawBulletsFunction) GalDrawBullets(&GalSpriteRam[0xc0]);
1200 	Coctail_Unflippy();
1201 	BurnTransferCopy(GalPalette);
1202 }
1203 
TimefgtrRenderFrame()1204 void TimefgtrRenderFrame()
1205 {
1206 	BurnTransferClear();
1207 	GalCalcPaletteFunction();
1208 	if (GalRenderBackgroundFunction) GalRenderBackgroundFunction();
1209 	GalRenderBgLayer(GalVideoRam);
1210 	GalRenderSprites(&GalSpriteRam[0x040]); // MAME renders different sprite ram areas depending on screen-area - necessary?
1211 	GalRenderSprites(&GalSpriteRam[0x140]);
1212 	GalRenderSprites(&GalSpriteRam[0x240]);
1213 	GalRenderSprites(&GalSpriteRam[0x340]);
1214 	if (GalDrawBulletsFunction) GalDrawBullets(&GalSpriteRam[0xc0]);
1215 	Coctail_Unflippy();
1216 	BurnTransferCopy(GalPalette);
1217 }
1218 
ScramblerRenderFrame()1219 void ScramblerRenderFrame()
1220 {
1221 	BurnTransferClear();
1222 	GalCalcPaletteFunction();
1223 	if (GalRenderBackgroundFunction) GalRenderBackgroundFunction();
1224 	GalRenderBgLayer(GalVideoRam);
1225 	GalRenderSprites(&GalSpriteRam[0xc0]);
1226 	if (GalDrawBulletsFunction) GalDrawBullets(&GalSpriteRam[0xe0]);
1227 	Coctail_Unflippy();
1228 	BurnTransferCopy(GalPalette);
1229 }
1230