Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Graphics/Drawing.cpp
1163 views
1
#include "RSDK/Core/RetroEngine.hpp"
2
3
using namespace RSDK;
4
5
#if RETRO_REV0U
6
#include "Legacy/DrawingLegacy.cpp"
7
#endif
8
9
// all render devices need to access the initial vertex buffer :skull:
10
11
// clang-format off
12
#if RETRO_REV02
13
const RenderVertex rsdkVertexBuffer[60] = {
14
// 1 Screen (0)
15
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
16
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
17
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
18
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
19
{ { 1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
20
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
21
22
// 2 Screens - Bordered (Top Screen) (6)
23
{ { -0.5, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
24
{ { -0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
25
{ { 0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
26
{ { -0.5, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
27
{ { 0.5, 1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
28
{ { 0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
29
30
// 2 Screens - Bordered (Bottom Screen) (12)
31
{ { -0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
32
{ { -0.5, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
33
{ { 0.5, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
34
{ { -0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
35
{ { 0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
36
{ { 0.5, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
37
38
// 2 Screens - Stretched (Top Screen) (18)
39
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
40
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
41
{ { 1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
42
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
43
{ { 1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
44
{ { 1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
45
46
// 2 Screens - Stretched (Bottom Screen) (24)
47
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
48
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
49
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
50
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
51
{ { 1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
52
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
53
54
// 4 Screens (Top-Left) (30)
55
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
56
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
57
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
58
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
59
{ { 0.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
60
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
61
62
// 4 Screens (Top-Right) (36)
63
{ { 0.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
64
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
65
{ { 1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
66
{ { 0.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
67
{ { 1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
68
{ { 1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
69
70
// 4 Screens (Bottom-Right) (42)
71
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
72
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
73
{ { 0.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
74
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
75
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
76
{ { 0.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
77
78
// 4 Screens (Bottom-Left) (48)
79
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
80
{ { 0.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
81
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
82
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
83
{ { 1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
84
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
85
86
// Image/Video (54)
87
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
88
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
89
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
90
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
91
{ { 1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
92
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } }
93
};
94
#else
95
const RenderVertex rsdkVertexBuffer[24] =
96
{
97
// 1 Screen (0)
98
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
99
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
100
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
101
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
102
{ { 1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
103
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
104
105
// 2 Screens - Stretched (Top Screen) (6)
106
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
107
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
108
{ { 1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
109
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
110
{ { 1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
111
{ { 1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
112
113
// 2 Screens - Stretched (Bottom Screen) (12)
114
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
115
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.9375 } },
116
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
117
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
118
{ { 1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.0 } },
119
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.625, 0.9375 } },
120
121
// Image/Video (18)
122
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
123
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
124
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
125
{ { -1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
126
{ { 1.0, 1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
127
{ { 1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } }
128
};
129
#endif
130
// clang-format on
131
132
#if RETRO_RENDERDEVICE_DIRECTX9
133
#include "DX9/DX9RenderDevice.cpp"
134
#elif RETRO_RENDERDEVICE_DIRECTX11
135
#include "DX11/DX11RenderDevice.cpp"
136
#elif RETRO_RENDERDEVICE_SDL2
137
#include "SDL2/SDL2RenderDevice.cpp"
138
#elif RETRO_RENDERDEVICE_GLFW
139
#include "GLFW/GLFWRenderDevice.cpp"
140
#elif RETRO_RENDERDEVICE_VK
141
#include "Vulkan/VulkanRenderDevice.cpp"
142
#elif RETRO_RENDERDEVICE_EGL
143
#include "EGL/EGLRenderDevice.cpp"
144
#endif
145
146
RenderDevice::WindowInfo RenderDevice::displayInfo;
147
148
DrawList RSDK::drawGroups[DRAWGROUP_COUNT];
149
150
uint16 RSDK::blendLookupTable[0x20 * 0x100];
151
uint16 RSDK::subtractLookupTable[0x20 * 0x100];
152
153
GFXSurface RSDK::gfxSurface[SURFACE_COUNT];
154
155
float RSDK::dpi = 1;
156
int32 RSDK::cameraCount = 0;
157
ScreenInfo RSDK::screens[SCREEN_COUNT];
158
CameraInfo RSDK::cameras[CAMERA_COUNT];
159
ScreenInfo *RSDK::currentScreen = NULL;
160
161
int32 RSDK::shaderCount = 0;
162
ShaderEntry RSDK::shaderList[SHADER_COUNT];
163
164
bool32 RSDK::changedVideoSettings = false;
165
VideoSettings RSDK::videoSettings;
166
VideoSettings RSDK::videoSettingsBackup;
167
168
#if RETRO_USE_MOD_LOADER
169
int32 RSDK::userShaderCount = 0;
170
#endif
171
172
bool32 RenderDeviceBase::isRunning = false;
173
int32 RenderDeviceBase::windowRefreshDelay = 0;
174
175
#if RETRO_REV02
176
uint8 RenderDeviceBase::startVertex_2P[] = { 18, 24 };
177
uint8 RenderDeviceBase::startVertex_3P[] = { 30, 36, 12 };
178
#endif
179
180
float2 RenderDeviceBase::pixelSize = { DEFAULT_PIXWIDTH, SCREEN_YSIZE };
181
float2 RenderDeviceBase::textureSize = { 512.0, 256.0 };
182
float2 RenderDeviceBase::viewSize = { 0, 0 };
183
184
int32 RenderDeviceBase::displayWidth[16];
185
int32 RenderDeviceBase::displayHeight[16];
186
int32 RenderDeviceBase::displayCount = 0;
187
188
int32 RenderDeviceBase::lastShaderID = -1;
189
190
char RSDK::drawGroupNames[0x10][0x10] = {
191
"Draw Group 0", "Draw Group 1", "Draw Group 2", "Draw Group 3", "Draw Group 4", "Draw Group 5", "Draw Group 6", "Draw Group 7",
192
"Draw Group 8", "Draw Group 9", "Draw Group 10", "Draw Group 11", "Draw Group 12", "Draw Group 13", "Draw Group 14", "Draw Group 15",
193
};
194
195
#include "RSDK/Dev/DevFont.hpp"
196
197
// 50% alpha, but way faster
198
#define setPixelBlend(pixel, frameBufferClr) frameBufferClr = ((pixel >> 1) & 0x7BEF) + ((frameBufferClr >> 1) & 0x7BEF)
199
200
// Alpha blending
201
#define setPixelAlpha(pixel, frameBufferClr, alpha) \
202
int32 R = (fbufferBlend[(frameBufferClr & 0xF800) >> 11] + pixelBlend[(pixel & 0xF800) >> 11]) << 11; \
203
int32 G = (fbufferBlend[(frameBufferClr & 0x7E0) >> 6] + pixelBlend[(pixel & 0x7E0) >> 6]) << 6; \
204
int32 B = fbufferBlend[frameBufferClr & 0x1F] + pixelBlend[pixel & 0x1F]; \
205
\
206
frameBufferClr = R | G | B;
207
208
// Additive Blending
209
#define setPixelAdditive(pixel, frameBufferClr) \
210
int32 R = MIN((blendTablePtr[(pixel & 0xF800) >> 11] << 11) + (frameBufferClr & 0xF800), 0xF800); \
211
int32 G = MIN((blendTablePtr[(pixel & 0x7E0) >> 6] << 6) + (frameBufferClr & 0x7E0), 0x7E0); \
212
int32 B = MIN(blendTablePtr[pixel & 0x1F] + (frameBufferClr & 0x1F), 0x1F); \
213
\
214
frameBufferClr = R | G | B;
215
216
// Subtractive Blending
217
#define setPixelSubtractive(pixel, frameBufferClr) \
218
int32 R = MAX((frameBufferClr & 0xF800) - (subBlendTable[(pixel & 0xF800) >> 11] << 11), 0); \
219
int32 G = MAX((frameBufferClr & 0x7E0) - (subBlendTable[(pixel & 0x7E0) >> 6] << 6), 0); \
220
int32 B = MAX((frameBufferClr & 0x1F) - subBlendTable[pixel & 0x1F], 0); \
221
\
222
frameBufferClr = R | G | B;
223
224
// Only draw if framebuffer clr IS maskColor
225
#define setPixelMasked(pixel, frameBufferClr) \
226
if (frameBufferClr == maskColor) \
227
frameBufferClr = pixel;
228
229
// Only draw if framebuffer clr is NOT maskColor
230
#define setPixelUnmasked(pixel, frameBufferClr) \
231
if (frameBufferClr != maskColor) \
232
frameBufferClr = pixel;
233
234
void RSDK::RenderDeviceBase::ProcessDimming()
235
{
236
// Bug Details:
237
// if you've ever used debug mode before the first frame of v5 executes you may've seen how the game starts dimmed
238
// this is because dimLimit hasn't been initialized yet, so it starts at 0. Likewise, the timer also starts at 0
239
// this leads the game to immediately begin dimming when it shouldn't be
240
// Fix:
241
// initialize dimLimit before ProcessStage(), maybe in RenderDevice::SetupRendering() or something
242
243
if (videoSettings.dimTimer < videoSettings.dimLimit) {
244
if (videoSettings.dimPercent < 1.0f) {
245
videoSettings.dimPercent += 0.05f;
246
247
if (videoSettings.dimPercent > 1.0f)
248
videoSettings.dimPercent = 1.0f;
249
}
250
}
251
else {
252
if (videoSettings.dimPercent > 0.25f)
253
videoSettings.dimPercent *= 0.9f;
254
}
255
}
256
257
void RSDK::GenerateBlendLookupTable()
258
{
259
for (int32 y = 0; y < 0x100; y++) {
260
for (int32 x = 0; x < 0x20; x++) {
261
blendLookupTable[x + (y * 0x20)] = y * x >> 8;
262
subtractLookupTable[x + (y * 0x20)] = y * (0x1F - x) >> 8;
263
}
264
}
265
266
#if !RETRO_REV02
267
for (int32 i = 0; i < 0x10000; ++i) {
268
int32 tintValue = (((uint32)i & 0x1F) + ((i >> 6) & 0x1F) + (((uint16)i >> 11) & 0x1F)) / 3 + 6;
269
tintLookupTable[i] = 0x841 * MIN(0x1F, tintValue);
270
}
271
#endif
272
273
for (int32 c = 0; c < 0x100; ++c) {
274
rgb32To16_R[c] = (c & 0xFFF8) << 8;
275
rgb32To16_G[c] = (c & 0xFFFC) << 3;
276
rgb32To16_B[c] = c >> 3;
277
}
278
}
279
280
void RSDK::InitSystemSurfaces()
281
{
282
GEN_HASH_MD5("TileBuffer", gfxSurface[0].hash);
283
gfxSurface[0].scope = SCOPE_GLOBAL;
284
gfxSurface[0].width = TILE_SIZE;
285
gfxSurface[0].height = TILE_COUNT * TILE_SIZE;
286
gfxSurface[0].lineSize = 4; // 16px
287
gfxSurface[0].pixels = tilesetPixels;
288
289
#if RETRO_REV02
290
GEN_HASH_MD5("EngineText", gfxSurface[1].hash);
291
gfxSurface[1].scope = SCOPE_GLOBAL;
292
gfxSurface[1].width = 8;
293
gfxSurface[1].height = 128 * 8;
294
gfxSurface[1].lineSize = 3; // 8px
295
gfxSurface[1].pixels = devTextStencil;
296
#endif
297
}
298
299
void RSDK::UpdateGameWindow() { RenderDevice::RefreshWindow(); }
300
301
void RSDK::GetDisplayInfo(int32 *displayID, int32 *width, int32 *height, int32 *refreshRate, char *text)
302
{
303
if (!displayID)
304
return;
305
306
int32 prevDisplay = *displayID;
307
int32 display = 0;
308
309
if (*displayID == -2) { // -2 == "get FS size display"
310
if (videoSettings.fsWidth && videoSettings.fsHeight) {
311
for (display = 0; display < RenderDevice::displayCount; ++display) {
312
#if RETRO_RENDERDEVICE_DIRECTX11
313
int32 refresh = RenderDevice::displayInfo.displays[display].refresh_rate.Numerator
314
/ RenderDevice::displayInfo.displays[display].refresh_rate.Denominator;
315
#else
316
int32 refresh = RenderDevice::displayInfo.displays[display].refresh_rate;
317
#endif
318
319
if (RenderDevice::displayInfo.displays[display].width == videoSettings.fsWidth
320
&& RenderDevice::displayInfo.displays[display].height == videoSettings.fsHeight && refresh == videoSettings.refreshRate) {
321
break;
322
}
323
}
324
325
display++;
326
}
327
}
328
else {
329
display = *displayID;
330
if (prevDisplay < 0)
331
display = RenderDevice::displayCount;
332
else if (prevDisplay > RenderDevice::displayCount)
333
display = 0;
334
}
335
336
*displayID = display;
337
if (display) {
338
int32 d = display - 1;
339
340
#if RETRO_RENDERDEVICE_DIRECTX11
341
int32 refresh = RenderDevice::displayInfo.displays[d].refresh_rate.Numerator / RenderDevice::displayInfo.displays[d].refresh_rate.Denominator;
342
#else
343
int32 refresh = RenderDevice::displayInfo.displays[d].refresh_rate;
344
#endif
345
346
int32 displayWidth = RenderDevice::displayInfo.displays[d].width;
347
int32 displayHeight = RenderDevice::displayInfo.displays[d].height;
348
int32 displayRefresh = refresh;
349
350
if (width)
351
*width = displayWidth;
352
353
if (height)
354
*height = displayHeight;
355
356
if (refreshRate)
357
*refreshRate = displayRefresh;
358
359
if (text)
360
sprintf(text, "%ix%i @%iHz", displayWidth, displayHeight, displayRefresh);
361
}
362
else { // displayID 0 == "default fullscreen size"
363
if (width)
364
*width = 0;
365
366
if (height)
367
*height = 0;
368
369
if (refreshRate)
370
*refreshRate = 0;
371
372
if (text)
373
sprintf(text, "%s", "DEFAULT");
374
}
375
}
376
377
void RSDK::GetWindowSize(int32 *width, int32 *height) { RenderDevice::GetWindowSize(width, height); }
378
379
void RSDK::SetScreenSize(uint8 screenID, uint16 width, uint16 height)
380
{
381
if (screenID < SCREEN_COUNT) {
382
ScreenInfo *screen = &screens[screenID];
383
384
screen->size.x = width;
385
screen->size.y = height & 0xFFF0;
386
screen->pitch = (screen->size.x + 15) & 0xFFFFFFF0;
387
screen->center.x = screen->size.x >> 1;
388
screen->center.y = screen->size.y >> 1;
389
390
screen->clipBound_X1 = 0;
391
screen->clipBound_X2 = screen->size.x;
392
screen->clipBound_Y1 = 0;
393
screen->clipBound_Y2 = screen->size.y;
394
395
screen->waterDrawPos = screen->size.y;
396
397
#if RETRO_REV0U
398
RSDK::Legacy::SCREEN_XSIZE = width;
399
RSDK::Legacy::SCREEN_CENTERX = width / 2;
400
RSDK::Legacy::SCREEN_SCROLL_LEFT = RSDK::Legacy::SCREEN_CENTERX - 8;
401
RSDK::Legacy::SCREEN_SCROLL_RIGHT = RSDK::Legacy::SCREEN_CENTERX + 8;
402
RSDK::Legacy::OBJECT_BORDER_X2 = width + 0x80;
403
RSDK::Legacy::OBJECT_BORDER_X4 = width + 0x20;
404
405
RSDK::Legacy::GFX_LINESIZE = screen->pitch;
406
RSDK::Legacy::GFX_LINESIZE_MINUSONE = screen->pitch - 1;
407
RSDK::Legacy::GFX_LINESIZE_DOUBLE = 2 * screen->pitch;
408
RSDK::Legacy::GFX_FRAMEBUFFERSIZE = SCREEN_YSIZE * screen->pitch;
409
RSDK::Legacy::GFX_FBUFFERMINUSONE = SCREEN_YSIZE * screen->pitch - 1;
410
#endif
411
}
412
}
413
414
int32 RSDK::GetVideoSetting(int32 id)
415
{
416
switch (id) {
417
case VIDEOSETTING_WINDOWED: return videoSettings.windowed;
418
case VIDEOSETTING_BORDERED: return videoSettings.bordered;
419
case VIDEOSETTING_EXCLUSIVEFS: return videoSettings.exclusiveFS;
420
case VIDEOSETTING_VSYNC: return videoSettings.vsync;
421
case VIDEOSETTING_TRIPLEBUFFERED: return videoSettings.tripleBuffered;
422
case VIDEOSETTING_WINDOW_WIDTH: return videoSettings.windowWidth;
423
case VIDEOSETTING_WINDOW_HEIGHT: return videoSettings.windowHeight;
424
case VIDEOSETTING_FSWIDTH: return videoSettings.fsWidth;
425
case VIDEOSETTING_FSHEIGHT: return videoSettings.fsHeight;
426
case VIDEOSETTING_REFRESHRATE: return videoSettings.refreshRate;
427
case VIDEOSETTING_SHADERSUPPORT: return videoSettings.shaderSupport;
428
case VIDEOSETTING_SHADERID: return videoSettings.shaderID;
429
case VIDEOSETTING_SCREENCOUNT: return videoSettings.screenCount;
430
#if RETRO_REV02
431
case VIDEOSETTING_DIMTIMER: return videoSettings.dimTimer;
432
#endif
433
case VIDEOSETTING_STREAMSENABLED: return engine.streamsEnabled;
434
case VIDEOSETTING_STREAM_VOL: return (int32)(engine.streamVolume * 1024.0);
435
case VIDEOSETTING_SFX_VOL: return (int32)(engine.soundFXVolume * 1024.0);
436
case VIDEOSETTING_LANGUAGE:
437
#if RETRO_REV02
438
return SKU::curSKU.language;
439
#else
440
return gameVerInfo.language;
441
#endif
442
case VIDEOSETTING_CHANGED: return changedVideoSettings;
443
444
default: break;
445
}
446
447
return 0;
448
}
449
450
void RSDK::SetVideoSetting(int32 id, int32 value)
451
{
452
bool32 boolVal = value;
453
switch (id) {
454
case VIDEOSETTING_WINDOWED:
455
if (videoSettings.windowed != boolVal) {
456
videoSettings.windowed = boolVal;
457
changedVideoSettings = true;
458
}
459
break;
460
461
case VIDEOSETTING_BORDERED:
462
if (videoSettings.bordered != boolVal) {
463
videoSettings.bordered = boolVal;
464
changedVideoSettings = true;
465
}
466
break;
467
468
case VIDEOSETTING_EXCLUSIVEFS:
469
if (videoSettings.exclusiveFS != boolVal) {
470
videoSettings.exclusiveFS = boolVal;
471
changedVideoSettings = true;
472
}
473
break;
474
475
case VIDEOSETTING_VSYNC:
476
if (videoSettings.vsync != boolVal) {
477
videoSettings.vsync = boolVal;
478
changedVideoSettings = true;
479
}
480
break;
481
482
case VIDEOSETTING_TRIPLEBUFFERED:
483
if (videoSettings.tripleBuffered != boolVal) {
484
videoSettings.tripleBuffered = boolVal;
485
changedVideoSettings = true;
486
}
487
break;
488
489
case VIDEOSETTING_WINDOW_WIDTH:
490
if (videoSettings.windowWidth != value) {
491
videoSettings.windowWidth = value;
492
changedVideoSettings = true;
493
}
494
break;
495
496
case VIDEOSETTING_WINDOW_HEIGHT:
497
if (videoSettings.windowHeight != value) {
498
videoSettings.windowHeight = value;
499
changedVideoSettings = true;
500
}
501
break;
502
503
case VIDEOSETTING_FSWIDTH: videoSettings.fsWidth = value; break;
504
case VIDEOSETTING_FSHEIGHT: videoSettings.fsHeight = value; break;
505
case VIDEOSETTING_REFRESHRATE: videoSettings.refreshRate = value; break;
506
case VIDEOSETTING_SHADERSUPPORT: videoSettings.shaderSupport = value; break;
507
case VIDEOSETTING_SHADERID:
508
if (videoSettings.shaderID != value) {
509
videoSettings.shaderID = value;
510
changedVideoSettings = true;
511
}
512
break;
513
514
case VIDEOSETTING_SCREENCOUNT: videoSettings.screenCount = value; break;
515
#if RETRO_REV02
516
case VIDEOSETTING_DIMTIMER: videoSettings.dimLimit = value; break;
517
#endif
518
case VIDEOSETTING_STREAMSENABLED:
519
if (engine.streamsEnabled != boolVal)
520
changedVideoSettings = true;
521
522
engine.streamsEnabled = boolVal;
523
break;
524
525
case VIDEOSETTING_STREAM_VOL:
526
if (engine.streamVolume != (value / 1024.0f)) {
527
engine.streamVolume = (float)value / 1024.0f;
528
changedVideoSettings = true;
529
}
530
break;
531
532
case VIDEOSETTING_SFX_VOL:
533
if (engine.soundFXVolume != ((float)value / 1024.0f)) {
534
engine.soundFXVolume = (float)value / 1024.0f;
535
changedVideoSettings = true;
536
}
537
break;
538
539
case VIDEOSETTING_LANGUAGE:
540
#if RETRO_REV02
541
SKU::curSKU.language = value;
542
#else
543
gameVerInfo.language = value;
544
#endif
545
break;
546
547
case VIDEOSETTING_STORE: memcpy(&videoSettingsBackup, &videoSettings, sizeof(videoSettings)); break;
548
549
case VIDEOSETTING_RELOAD:
550
changedVideoSettings = true;
551
memcpy(&videoSettings, &videoSettingsBackup, sizeof(videoSettingsBackup));
552
break;
553
554
case VIDEOSETTING_CHANGED: changedVideoSettings = boolVal; break;
555
556
case VIDEOSETTING_WRITE: SaveSettingsINI(value); break;
557
558
default: break;
559
}
560
}
561
562
void RSDK::SwapDrawListEntries(uint8 drawGroup, uint16 slot1, uint16 slot2, uint16 count)
563
{
564
if (drawGroup < DRAWGROUP_COUNT) {
565
DrawList *group = &drawGroups[drawGroup];
566
if (count <= 0 || count > group->entityCount)
567
count = group->entityCount;
568
569
int32 index1 = -1;
570
int32 index2 = -1;
571
for (int32 i = 0; i < count; ++i) {
572
if (group->entries[i] == slot1)
573
index1 = i;
574
if (group->entries[i] == slot2)
575
index2 = i;
576
}
577
578
if (index1 > -1 && index2 > -1 && index1 < index2) {
579
int32 temp = group->entries[index2];
580
group->entries[index2] = group->entries[index1];
581
group->entries[index1] = temp;
582
}
583
}
584
}
585
586
void RSDK::FillScreen(uint32 color, int32 alphaR, int32 alphaG, int32 alphaB)
587
{
588
alphaR = CLAMP(alphaR, 0x00, 0xFF);
589
alphaG = CLAMP(alphaG, 0x00, 0xFF);
590
alphaB = CLAMP(alphaB, 0x00, 0xFF);
591
592
if (alphaR + alphaG + alphaB) {
593
validDraw = true;
594
uint16 clrBlendR = blendLookupTable[0x20 * alphaR + rgb32To16_B[(color >> 0x10) & 0xFF]];
595
uint16 clrBlendG = blendLookupTable[0x20 * alphaG + rgb32To16_B[(color >> 0x08) & 0xFF]];
596
uint16 clrBlendB = blendLookupTable[0x20 * alphaB + rgb32To16_B[(color >> 0x00) & 0xFF]];
597
598
uint16 *fbBlendR = &blendLookupTable[0x20 * (0xFF - alphaR)];
599
uint16 *fbBlendG = &blendLookupTable[0x20 * (0xFF - alphaG)];
600
uint16 *fbBlendB = &blendLookupTable[0x20 * (0xFF - alphaB)];
601
602
int32 cnt = currentScreen->size.y * currentScreen->pitch;
603
for (int32 id = 0; cnt > 0; --cnt, ++id) {
604
uint16 px = currentScreen->frameBuffer[id];
605
606
int32 R = fbBlendR[(px & 0xF800) >> 11] + clrBlendR;
607
int32 G = fbBlendG[(px & 0x7E0) >> 6] + clrBlendG;
608
int32 B = fbBlendB[px & 0x1F] + clrBlendB;
609
610
currentScreen->frameBuffer[id] = (B) | (G << 6) | (R << 11);
611
}
612
}
613
}
614
615
void RSDK::DrawLine(int32 x1, int32 y1, int32 x2, int32 y2, uint32 color, int32 alpha, int32 inkEffect, bool32 screenRelative)
616
{
617
switch (inkEffect) {
618
default: break;
619
620
case INK_ALPHA:
621
if (alpha > 0xFF)
622
inkEffect = INK_NONE;
623
else if (alpha <= 0)
624
return;
625
break;
626
627
case INK_ADD:
628
case INK_SUB:
629
if (alpha > 0xFF)
630
alpha = 0xFF;
631
else if (alpha <= 0)
632
return;
633
break;
634
635
case INK_TINT:
636
if (!tintLookupTable)
637
return;
638
break;
639
}
640
641
int32 drawY1 = y1;
642
int32 drawX1 = x1;
643
int32 drawY2 = y2;
644
int32 drawX2 = x2;
645
646
if (!screenRelative) {
647
drawX1 = FROM_FIXED(x1) - currentScreen->position.x;
648
drawY1 = FROM_FIXED(y1) - currentScreen->position.y;
649
drawX2 = FROM_FIXED(x2) - currentScreen->position.x;
650
drawY2 = FROM_FIXED(y2) - currentScreen->position.y;
651
}
652
653
int32 flags1 = 0;
654
if (drawX1 >= currentScreen->clipBound_X2)
655
flags1 = 2;
656
else if (drawX1 < currentScreen->clipBound_X1)
657
flags1 = 1;
658
659
if (drawY1 >= currentScreen->clipBound_Y2)
660
flags1 |= 8;
661
else if (drawY1 < currentScreen->clipBound_Y1)
662
flags1 |= 4;
663
664
int32 flags2 = 0;
665
if (drawX2 >= currentScreen->clipBound_X2)
666
flags2 = 2;
667
else if (drawX2 < currentScreen->clipBound_X1)
668
flags2 = 1;
669
670
if (drawY2 >= currentScreen->clipBound_Y2)
671
flags2 |= 8;
672
else if (drawY2 < currentScreen->clipBound_Y1)
673
flags2 |= 4;
674
675
while (flags1 || flags2) {
676
if (flags1 & flags2)
677
return;
678
679
int32 curFlags = flags2;
680
if (flags1)
681
curFlags = flags1;
682
683
int32 x = 0;
684
int32 y = 0;
685
if (curFlags & 8) {
686
int32 div = (drawY2 - drawY1);
687
if (!div)
688
div = 1;
689
x = drawX1 + ((drawX2 - drawX1) * (((currentScreen->clipBound_Y2 - drawY1) << 8) / div) >> 8);
690
y = currentScreen->clipBound_Y2;
691
}
692
else if (curFlags & 4) {
693
int32 div = (drawY2 - drawY1);
694
if (!div)
695
div = 1;
696
x = drawX1 + ((drawX2 - drawX1) * (((currentScreen->clipBound_Y1 - drawY1) << 8) / div) >> 8);
697
y = currentScreen->clipBound_Y1;
698
}
699
else if (curFlags & 2) {
700
int32 div = (drawX2 - drawX1);
701
if (!div)
702
div = 1;
703
x = currentScreen->clipBound_X2;
704
y = drawY1 + ((drawY2 - drawY1) * (((currentScreen->clipBound_X2 - drawX1) << 8) / div) >> 8);
705
}
706
else if (curFlags & 1) {
707
int32 div = (drawX2 - drawX1);
708
if (!div)
709
div = 1;
710
x = currentScreen->clipBound_X1;
711
y = drawY1 + ((drawY2 - drawY1) * (((currentScreen->clipBound_X1 - drawX1) << 8) / div) >> 8);
712
}
713
714
if (curFlags == flags1) {
715
drawX1 = x;
716
drawY1 = y;
717
flags1 = 0;
718
if (x > currentScreen->clipBound_X2) {
719
flags1 = 2;
720
}
721
else if (x < currentScreen->clipBound_X1) {
722
flags1 = 1;
723
}
724
725
if (y < currentScreen->clipBound_Y1) {
726
flags1 |= 4;
727
}
728
else if (y > currentScreen->clipBound_Y2) {
729
flags1 |= 8;
730
}
731
}
732
else {
733
drawX2 = x;
734
drawY2 = y;
735
flags2 = 0;
736
if (x > currentScreen->clipBound_X2) {
737
flags2 = 2;
738
}
739
else if (x < currentScreen->clipBound_X1) {
740
flags2 = 1;
741
}
742
743
if (y < currentScreen->clipBound_Y1) {
744
flags2 |= 4;
745
}
746
else if (y > currentScreen->clipBound_Y2) {
747
flags2 |= 8;
748
}
749
}
750
}
751
752
if (drawX1 > currentScreen->clipBound_X2)
753
drawX1 = currentScreen->clipBound_X2;
754
else if (drawX1 < currentScreen->clipBound_X1)
755
drawX1 = currentScreen->clipBound_X1;
756
757
if (drawY1 > currentScreen->clipBound_Y2)
758
drawY1 = currentScreen->clipBound_Y2;
759
else if (drawY1 < currentScreen->clipBound_Y1)
760
drawY1 = currentScreen->clipBound_Y1;
761
762
if (drawX2 > currentScreen->clipBound_X2)
763
drawX2 = currentScreen->clipBound_X2;
764
else if (drawX2 < currentScreen->clipBound_X1)
765
drawX2 = currentScreen->clipBound_X1;
766
767
if (drawY2 > currentScreen->clipBound_Y2)
768
drawY2 = currentScreen->clipBound_Y2;
769
else if (drawY2 < currentScreen->clipBound_Y1)
770
drawY2 = currentScreen->clipBound_Y1;
771
772
int32 sizeX = abs(drawX2 - drawX1);
773
int32 sizeY = abs(drawY2 - drawY1);
774
int32 max = sizeY;
775
int32 hSize = sizeX >> 2;
776
if (sizeX <= sizeY)
777
hSize = -sizeY >> 2;
778
779
if (drawX2 < drawX1) {
780
int32 v = drawX1;
781
drawX1 = drawX2;
782
drawX2 = v;
783
784
v = drawY1;
785
drawY1 = drawY2;
786
drawY2 = v;
787
}
788
789
uint16 color16 = rgb32To16_B[(color >> 0) & 0xFF] | rgb32To16_G[(color >> 8) & 0xFF] | rgb32To16_R[(color >> 16) & 0xFF];
790
uint16 *frameBuffer = &currentScreen->frameBuffer[drawX1 + drawY1 * currentScreen->pitch];
791
792
switch (inkEffect) {
793
case INK_NONE:
794
if (drawY1 > drawY2) {
795
while (drawX1 < drawX2 || drawY1 >= drawY2) {
796
*frameBuffer = color16;
797
798
if (hSize > -sizeX) {
799
hSize -= max;
800
++drawX1;
801
++frameBuffer;
802
}
803
804
if (hSize < max) {
805
--drawY1;
806
hSize += sizeX;
807
frameBuffer -= currentScreen->pitch;
808
}
809
}
810
}
811
else {
812
while (true) {
813
*frameBuffer = color16;
814
815
if (drawX1 < drawX2 || drawY1 < drawY2) {
816
if (hSize > -sizeX) {
817
hSize -= max;
818
++drawX1;
819
++frameBuffer;
820
}
821
822
if (hSize < max) {
823
hSize += sizeX;
824
++drawY1;
825
frameBuffer += currentScreen->pitch;
826
}
827
}
828
else {
829
break;
830
}
831
}
832
}
833
break;
834
835
case INK_BLEND:
836
if (drawY1 > drawY2) {
837
while (drawX1 < drawX2 || drawY1 >= drawY2) {
838
setPixelBlend(color16, *frameBuffer);
839
840
if (hSize > -sizeX) {
841
hSize -= max;
842
++drawX1;
843
++frameBuffer;
844
}
845
846
if (hSize < max) {
847
--drawY1;
848
hSize += sizeX;
849
frameBuffer -= currentScreen->pitch;
850
}
851
}
852
}
853
else {
854
while (true) {
855
setPixelBlend(color16, *frameBuffer);
856
857
if (drawX1 < drawX2 || drawY1 < drawY2) {
858
if (hSize > -sizeX) {
859
hSize -= max;
860
++drawX1;
861
++frameBuffer;
862
}
863
864
if (hSize < max) {
865
hSize += sizeX;
866
++drawY1;
867
frameBuffer += currentScreen->pitch;
868
}
869
}
870
else {
871
break;
872
}
873
}
874
}
875
break;
876
877
case INK_ALPHA:
878
if (drawY1 > drawY2) {
879
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
880
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
881
882
while (drawX1 < drawX2 || drawY1 >= drawY2) {
883
setPixelAlpha(color16, *frameBuffer, alpha);
884
885
if (hSize > -sizeX) {
886
hSize -= max;
887
++drawX1;
888
++frameBuffer;
889
}
890
891
if (hSize < max) {
892
--drawY1;
893
hSize += sizeX;
894
frameBuffer -= currentScreen->pitch;
895
}
896
}
897
}
898
else {
899
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
900
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
901
902
while (true) {
903
setPixelAlpha(color16, *frameBuffer, alpha);
904
905
if (drawX1 < drawX2 || drawY1 < drawY2) {
906
if (hSize > -sizeX) {
907
hSize -= max;
908
++drawX1;
909
++frameBuffer;
910
}
911
if (hSize < max) {
912
hSize += sizeX;
913
++drawY1;
914
frameBuffer += currentScreen->pitch;
915
}
916
}
917
else {
918
break;
919
}
920
}
921
}
922
break;
923
924
case INK_ADD:
925
if (drawY1 > drawY2) {
926
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
927
928
while (drawX1 < drawX2 || drawY1 >= drawY2) {
929
setPixelAdditive(color16, *frameBuffer);
930
931
if (hSize > -sizeX) {
932
hSize -= max;
933
++drawX1;
934
++frameBuffer;
935
}
936
937
if (hSize < max) {
938
--drawY1;
939
hSize += sizeX;
940
frameBuffer -= currentScreen->pitch;
941
}
942
}
943
}
944
else {
945
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
946
947
while (true) {
948
setPixelAdditive(color16, *frameBuffer);
949
if (drawX1 < drawX2 || drawY1 < drawY2) {
950
if (hSize > -sizeX) {
951
hSize -= max;
952
++drawX1;
953
++frameBuffer;
954
}
955
956
if (hSize < max) {
957
hSize += sizeX;
958
++drawY1;
959
frameBuffer += currentScreen->pitch;
960
}
961
}
962
else {
963
break;
964
}
965
}
966
}
967
break;
968
969
case INK_SUB:
970
if (drawY1 > drawY2) {
971
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
972
while (drawX1 < drawX2 || drawY1 >= drawY2) {
973
setPixelSubtractive(color16, *frameBuffer);
974
975
if (hSize > -sizeX) {
976
hSize -= max;
977
++drawX1;
978
++frameBuffer;
979
}
980
981
if (hSize < max) {
982
--drawY1;
983
hSize += sizeX;
984
frameBuffer -= currentScreen->pitch;
985
}
986
}
987
}
988
else {
989
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
990
while (true) {
991
setPixelSubtractive(color16, *frameBuffer);
992
993
if (drawX1 < drawX2 || drawY1 < drawY2) {
994
if (hSize > -sizeX) {
995
hSize -= max;
996
++drawX1;
997
++frameBuffer;
998
}
999
1000
if (hSize < max) {
1001
hSize += sizeX;
1002
++drawY1;
1003
frameBuffer += currentScreen->pitch;
1004
}
1005
}
1006
else {
1007
break;
1008
}
1009
}
1010
}
1011
break;
1012
1013
case INK_TINT:
1014
if (drawY1 > drawY2) {
1015
while (drawX1 < drawX2 || drawY1 >= drawY2) {
1016
*frameBuffer = tintLookupTable[*frameBuffer];
1017
1018
if (hSize > -sizeX) {
1019
hSize -= max;
1020
++drawX1;
1021
++frameBuffer;
1022
}
1023
1024
if (hSize < max) {
1025
--drawY1;
1026
hSize += sizeX;
1027
frameBuffer -= currentScreen->pitch;
1028
}
1029
}
1030
}
1031
else {
1032
while (true) {
1033
*frameBuffer = tintLookupTable[*frameBuffer];
1034
1035
if (drawX1 < drawX2 || drawY1 < drawY2) {
1036
if (hSize > -sizeX) {
1037
hSize -= max;
1038
++drawX1;
1039
++frameBuffer;
1040
}
1041
1042
if (hSize < max) {
1043
hSize += sizeX;
1044
++drawY1;
1045
frameBuffer += currentScreen->pitch;
1046
}
1047
}
1048
else {
1049
break;
1050
}
1051
}
1052
}
1053
break;
1054
1055
case INK_MASKED:
1056
if (drawY1 > drawY2) {
1057
while (drawX1 < drawX2 || drawY1 >= drawY2) {
1058
if (*frameBuffer == maskColor)
1059
*frameBuffer = color16;
1060
1061
if (hSize > -sizeX) {
1062
hSize -= max;
1063
++drawX1;
1064
++frameBuffer;
1065
}
1066
1067
if (hSize < max) {
1068
--drawY1;
1069
hSize += sizeX;
1070
frameBuffer -= currentScreen->pitch;
1071
}
1072
}
1073
}
1074
else {
1075
while (true) {
1076
if (*frameBuffer == maskColor)
1077
*frameBuffer = color16;
1078
1079
if (drawX1 < drawX2 || drawY1 < drawY2) {
1080
if (hSize > -sizeX) {
1081
hSize -= max;
1082
++drawX1;
1083
++frameBuffer;
1084
}
1085
1086
if (hSize < max) {
1087
hSize += sizeX;
1088
++drawY1;
1089
frameBuffer += currentScreen->pitch;
1090
}
1091
}
1092
else {
1093
break;
1094
}
1095
}
1096
}
1097
break;
1098
1099
case INK_UNMASKED:
1100
if (drawY1 > drawY2) {
1101
while (drawX1 < drawX2 || drawY1 >= drawY2) {
1102
if (*frameBuffer != maskColor)
1103
*frameBuffer = color16;
1104
1105
if (hSize > -sizeX) {
1106
hSize -= max;
1107
++drawX1;
1108
++frameBuffer;
1109
}
1110
1111
if (hSize < max) {
1112
--drawY1;
1113
hSize += sizeX;
1114
frameBuffer -= currentScreen->pitch;
1115
}
1116
}
1117
}
1118
else {
1119
while (true) {
1120
if (*frameBuffer != maskColor)
1121
*frameBuffer = color16;
1122
1123
if (drawX1 < drawX2 || drawY1 < drawY2) {
1124
if (hSize > -sizeX) {
1125
hSize -= max;
1126
++drawX1;
1127
++frameBuffer;
1128
}
1129
1130
if (hSize < max) {
1131
hSize += sizeX;
1132
++drawY1;
1133
frameBuffer += currentScreen->pitch;
1134
}
1135
}
1136
else {
1137
break;
1138
}
1139
}
1140
}
1141
break;
1142
}
1143
}
1144
void RSDK::DrawRectangle(int32 x, int32 y, int32 width, int32 height, uint32 color, int32 alpha, int32 inkEffect, bool32 screenRelative)
1145
{
1146
switch (inkEffect) {
1147
default: break;
1148
case INK_ALPHA:
1149
if (alpha > 0xFF)
1150
inkEffect = INK_NONE;
1151
else if (alpha <= 0)
1152
return;
1153
break;
1154
1155
case INK_ADD:
1156
case INK_SUB:
1157
if (alpha > 0xFF)
1158
alpha = 0xFF;
1159
else if (alpha <= 0)
1160
return;
1161
break;
1162
1163
case INK_TINT:
1164
if (!tintLookupTable)
1165
return;
1166
break;
1167
}
1168
1169
if (!screenRelative) {
1170
x = FROM_FIXED(x) - currentScreen->position.x;
1171
y = FROM_FIXED(y) - currentScreen->position.y;
1172
width = FROM_FIXED(width);
1173
height = FROM_FIXED(height);
1174
}
1175
1176
if (width + x > currentScreen->clipBound_X2)
1177
width = currentScreen->clipBound_X2 - x;
1178
1179
if (x < currentScreen->clipBound_X1) {
1180
width += x - currentScreen->clipBound_X1;
1181
x = currentScreen->clipBound_X1;
1182
}
1183
1184
if (height + y > currentScreen->clipBound_Y2)
1185
height = currentScreen->clipBound_Y2 - y;
1186
1187
if (y < currentScreen->clipBound_Y1) {
1188
height += y - currentScreen->clipBound_Y1;
1189
y = currentScreen->clipBound_Y1;
1190
}
1191
1192
if (width <= 0 || height <= 0)
1193
return;
1194
1195
int32 pitch = currentScreen->pitch - width;
1196
validDraw = true;
1197
uint16 *frameBuffer = &currentScreen->frameBuffer[x + (y * currentScreen->pitch)];
1198
uint16 color16 = rgb32To16_B[(color >> 0) & 0xFF] | rgb32To16_G[(color >> 8) & 0xFF] | rgb32To16_R[(color >> 16) & 0xFF];
1199
1200
switch (inkEffect) {
1201
case INK_NONE: {
1202
int32 h = height;
1203
while (h--) {
1204
int32 w = width;
1205
while (w--) {
1206
*frameBuffer = color16;
1207
++frameBuffer;
1208
}
1209
1210
frameBuffer += pitch;
1211
}
1212
break;
1213
}
1214
1215
case INK_BLEND: {
1216
int32 h = height;
1217
while (h--) {
1218
int32 w = width;
1219
while (w--) {
1220
setPixelBlend(color16, *frameBuffer);
1221
++frameBuffer;
1222
}
1223
frameBuffer += pitch;
1224
}
1225
break;
1226
}
1227
1228
case INK_ALPHA: {
1229
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
1230
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
1231
1232
int32 h = height;
1233
while (h--) {
1234
int32 w = width;
1235
while (w--) {
1236
setPixelAlpha(color16, *frameBuffer, alpha);
1237
++frameBuffer;
1238
}
1239
frameBuffer += pitch;
1240
}
1241
break;
1242
}
1243
1244
case INK_ADD: {
1245
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
1246
int32 h = height;
1247
while (h--) {
1248
int32 w = width;
1249
while (w--) {
1250
setPixelAdditive(color16, *frameBuffer);
1251
++frameBuffer;
1252
}
1253
frameBuffer += pitch;
1254
}
1255
break;
1256
}
1257
1258
case INK_SUB: {
1259
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
1260
int32 h = height;
1261
while (h--) {
1262
int32 w = width;
1263
while (w--) {
1264
setPixelSubtractive(color16, *frameBuffer);
1265
++frameBuffer;
1266
}
1267
frameBuffer += pitch;
1268
}
1269
break;
1270
}
1271
1272
case INK_TINT: {
1273
int32 h = height;
1274
while (h--) {
1275
int32 w = width;
1276
while (w--) {
1277
*frameBuffer = tintLookupTable[*frameBuffer];
1278
++frameBuffer;
1279
}
1280
frameBuffer += pitch;
1281
}
1282
break;
1283
}
1284
1285
case INK_MASKED: {
1286
int32 h = height;
1287
while (h--) {
1288
int32 w = width;
1289
while (w--) {
1290
if (*frameBuffer == maskColor)
1291
*frameBuffer = color16;
1292
++frameBuffer;
1293
}
1294
frameBuffer += pitch;
1295
}
1296
break;
1297
}
1298
1299
case INK_UNMASKED: {
1300
int32 h = height;
1301
while (h--) {
1302
int32 w = width;
1303
while (w--) {
1304
if (*frameBuffer != maskColor)
1305
*frameBuffer = color16;
1306
++frameBuffer;
1307
}
1308
frameBuffer += pitch;
1309
}
1310
break;
1311
}
1312
}
1313
}
1314
void RSDK::DrawCircle(int32 x, int32 y, int32 radius, uint32 color, int32 alpha, int32 inkEffect, bool32 screenRelative)
1315
{
1316
if (radius > 0) {
1317
switch (inkEffect) {
1318
default: break;
1319
case INK_ALPHA:
1320
if (alpha > 0xFF)
1321
inkEffect = INK_NONE;
1322
else if (alpha <= 0)
1323
return;
1324
break;
1325
1326
case INK_ADD:
1327
case INK_SUB:
1328
if (alpha > 0xFF)
1329
alpha = 0xFF;
1330
else if (alpha <= 0)
1331
return;
1332
break;
1333
1334
case INK_TINT:
1335
if (!tintLookupTable)
1336
return;
1337
break;
1338
}
1339
1340
if (!screenRelative) {
1341
x = FROM_FIXED(x) - currentScreen->position.x;
1342
y = FROM_FIXED(y) - currentScreen->position.y;
1343
}
1344
1345
int32 yRadiusBottom = y + radius;
1346
int32 bottom = yRadiusBottom + 1;
1347
int32 yRadiusTop = y - radius;
1348
int32 top = yRadiusTop;
1349
1350
if (top < currentScreen->clipBound_Y1)
1351
top = currentScreen->clipBound_Y1;
1352
else if (top > currentScreen->clipBound_Y2)
1353
top = currentScreen->clipBound_Y2;
1354
1355
if (bottom < currentScreen->clipBound_Y1)
1356
bottom = currentScreen->clipBound_Y1;
1357
else if (bottom > currentScreen->clipBound_Y2)
1358
bottom = currentScreen->clipBound_Y2;
1359
1360
if (top != bottom) {
1361
for (int32 i = top; i < bottom; ++i) {
1362
scanEdgeBuffer[i].start = 0x7FFF;
1363
scanEdgeBuffer[i].end = -1;
1364
}
1365
1366
int32 r = 3 - 2 * radius;
1367
int32 xRad = x - radius;
1368
int32 curY = y;
1369
int32 curX = x;
1370
int32 dist = x - y;
1371
1372
for (int32 i = 0; i <= radius; ++i) {
1373
int32 scanX = i + curX;
1374
1375
if (yRadiusBottom >= top && yRadiusBottom <= bottom && scanX > scanEdgeBuffer[yRadiusBottom].end)
1376
scanEdgeBuffer[yRadiusBottom].end = scanX;
1377
1378
if (yRadiusTop >= top && yRadiusTop <= bottom && scanX > scanEdgeBuffer[yRadiusTop].end)
1379
scanEdgeBuffer[yRadiusTop].end = scanX;
1380
1381
int32 scanY = i + y;
1382
if (scanY >= top && scanY <= bottom) {
1383
ScanEdge *edge = &scanEdgeBuffer[scanY];
1384
if (yRadiusBottom + dist > edge->end)
1385
edge->end = yRadiusBottom + dist;
1386
}
1387
1388
if (curY >= top && curY <= bottom && yRadiusBottom + dist > scanEdgeBuffer[curY].end)
1389
scanEdgeBuffer[curY].end = yRadiusBottom + dist;
1390
1391
if (yRadiusBottom >= top && yRadiusBottom <= bottom && x < scanEdgeBuffer[yRadiusBottom].start)
1392
scanEdgeBuffer[yRadiusBottom].start = x;
1393
1394
if (yRadiusTop >= top && yRadiusTop <= bottom && x < scanEdgeBuffer[yRadiusTop].start)
1395
scanEdgeBuffer[yRadiusTop].start = x;
1396
1397
if (scanY >= top && scanY <= bottom) {
1398
ScanEdge *edge = &scanEdgeBuffer[scanY];
1399
if (xRad < edge->start)
1400
edge->start = xRad;
1401
}
1402
1403
if (curY >= top && curY <= bottom && xRad < scanEdgeBuffer[curY].start)
1404
scanEdgeBuffer[curY].start = xRad;
1405
1406
if (r >= 0) {
1407
--yRadiusBottom;
1408
++yRadiusTop;
1409
r += 4 * (i - radius) + 10;
1410
--radius;
1411
++xRad;
1412
}
1413
else {
1414
r += 4 * i + 6;
1415
}
1416
--curY;
1417
--x;
1418
}
1419
1420
// validDraw = true;
1421
uint16 *frameBuffer = &currentScreen->frameBuffer[top * currentScreen->pitch];
1422
uint16 color16 = rgb32To16_B[(color >> 0) & 0xFF] | rgb32To16_G[(color >> 8) & 0xFF] | rgb32To16_R[(color >> 16) & 0xFF];
1423
1424
switch (inkEffect) {
1425
default: break;
1426
case INK_NONE:
1427
if (top <= bottom) {
1428
ScanEdge *edge = &scanEdgeBuffer[top];
1429
int32 sizeY = bottom - top;
1430
1431
for (int32 y = 0; y < sizeY; ++y) {
1432
if (edge->start < currentScreen->clipBound_X1)
1433
edge->start = currentScreen->clipBound_X1;
1434
if (edge->start > currentScreen->clipBound_X2)
1435
edge->start = currentScreen->clipBound_X2;
1436
1437
if (edge->end < currentScreen->clipBound_X1)
1438
edge->end = currentScreen->clipBound_X1;
1439
if (edge->end > currentScreen->clipBound_X2)
1440
edge->end = currentScreen->clipBound_X2;
1441
1442
int32 count = edge->end - edge->start;
1443
for (int32 x = 0; x < count; ++x) {
1444
frameBuffer[edge->start + x] = color16;
1445
}
1446
++edge;
1447
frameBuffer += currentScreen->pitch;
1448
}
1449
}
1450
break;
1451
1452
case INK_BLEND:
1453
if (top <= bottom) {
1454
ScanEdge *edge = &scanEdgeBuffer[top];
1455
int32 sizeY = bottom - top;
1456
1457
for (int32 y = 0; y < sizeY; ++y) {
1458
if (edge->start < currentScreen->clipBound_X1)
1459
edge->start = currentScreen->clipBound_X1;
1460
if (edge->start > currentScreen->clipBound_X2)
1461
edge->start = currentScreen->clipBound_X2;
1462
1463
if (edge->end < currentScreen->clipBound_X1)
1464
edge->end = currentScreen->clipBound_X1;
1465
if (edge->end > currentScreen->clipBound_X2)
1466
edge->end = currentScreen->clipBound_X2;
1467
1468
int32 count = edge->end - edge->start;
1469
for (int32 x = 0; x < count; ++x) {
1470
setPixelBlend(color16, frameBuffer[edge->start + x]);
1471
}
1472
1473
++edge;
1474
frameBuffer += currentScreen->pitch;
1475
}
1476
}
1477
break;
1478
1479
case INK_ALPHA:
1480
if (top <= bottom) {
1481
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
1482
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
1483
1484
ScanEdge *edge = &scanEdgeBuffer[top];
1485
int32 sizeY = bottom - top;
1486
1487
for (int32 y = 0; y < sizeY; ++y) {
1488
if (edge->start < currentScreen->clipBound_X1)
1489
edge->start = currentScreen->clipBound_X1;
1490
if (edge->start > currentScreen->clipBound_X2)
1491
edge->start = currentScreen->clipBound_X2;
1492
1493
if (edge->end < currentScreen->clipBound_X1)
1494
edge->end = currentScreen->clipBound_X1;
1495
if (edge->end > currentScreen->clipBound_X2)
1496
edge->end = currentScreen->clipBound_X2;
1497
1498
int32 count = edge->end - edge->start;
1499
for (int32 x = 0; x < count; ++x) {
1500
setPixelAlpha(color16, frameBuffer[edge->start + x], alpha);
1501
}
1502
++edge;
1503
frameBuffer += currentScreen->pitch;
1504
}
1505
}
1506
break;
1507
1508
case INK_ADD: {
1509
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
1510
if (top <= bottom) {
1511
ScanEdge *edge = &scanEdgeBuffer[top];
1512
int32 sizeY = bottom - top;
1513
1514
for (int32 y = 0; y < sizeY; ++y) {
1515
if (edge->start < currentScreen->clipBound_X1)
1516
edge->start = currentScreen->clipBound_X1;
1517
if (edge->start > currentScreen->clipBound_X2)
1518
edge->start = currentScreen->clipBound_X2;
1519
1520
if (edge->end < currentScreen->clipBound_X1)
1521
edge->end = currentScreen->clipBound_X1;
1522
if (edge->end > currentScreen->clipBound_X2)
1523
edge->end = currentScreen->clipBound_X2;
1524
1525
int32 count = edge->end - edge->start;
1526
for (int32 x = 0; x < count; ++x) {
1527
setPixelAdditive(color16, frameBuffer[edge->start + x]);
1528
}
1529
++edge;
1530
frameBuffer += currentScreen->pitch;
1531
}
1532
}
1533
break;
1534
}
1535
1536
case INK_SUB: {
1537
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
1538
if (top <= bottom) {
1539
ScanEdge *edge = &scanEdgeBuffer[top];
1540
int32 sizeY = bottom - top;
1541
1542
for (int32 y = 0; y < sizeY; ++y) {
1543
if (edge->start < currentScreen->clipBound_X1)
1544
edge->start = currentScreen->clipBound_X1;
1545
if (edge->start > currentScreen->clipBound_X2)
1546
edge->start = currentScreen->clipBound_X2;
1547
1548
if (edge->end < currentScreen->clipBound_X1)
1549
edge->end = currentScreen->clipBound_X1;
1550
if (edge->end > currentScreen->clipBound_X2)
1551
edge->end = currentScreen->clipBound_X2;
1552
1553
int32 count = edge->end - edge->start;
1554
for (int32 x = 0; x < count; ++x) {
1555
setPixelSubtractive(color16, frameBuffer[edge->start + x]);
1556
}
1557
++edge;
1558
frameBuffer += currentScreen->pitch;
1559
}
1560
}
1561
break;
1562
}
1563
1564
case INK_TINT:
1565
if (top <= bottom) {
1566
ScanEdge *edge = &scanEdgeBuffer[top];
1567
int32 sizeY = bottom - top;
1568
1569
for (int32 y = 0; y < sizeY; ++y) {
1570
if (edge->start < currentScreen->clipBound_X1)
1571
edge->start = currentScreen->clipBound_X1;
1572
if (edge->start > currentScreen->clipBound_X2)
1573
edge->start = currentScreen->clipBound_X2;
1574
1575
if (edge->end < currentScreen->clipBound_X1)
1576
edge->end = currentScreen->clipBound_X1;
1577
if (edge->end > currentScreen->clipBound_X2)
1578
edge->end = currentScreen->clipBound_X2;
1579
1580
int32 count = edge->end - edge->start;
1581
for (int32 x = 0; x < count; ++x) {
1582
frameBuffer[edge->start + x] = tintLookupTable[frameBuffer[edge->start + x]];
1583
}
1584
++edge;
1585
frameBuffer += currentScreen->pitch;
1586
}
1587
}
1588
break;
1589
1590
case INK_MASKED:
1591
if (top <= bottom) {
1592
ScanEdge *edge = &scanEdgeBuffer[top];
1593
int32 sizeY = bottom - top;
1594
1595
for (int32 y = 0; y < sizeY; ++y) {
1596
if (edge->start < currentScreen->clipBound_X1)
1597
edge->start = currentScreen->clipBound_X1;
1598
if (edge->start > currentScreen->clipBound_X2)
1599
edge->start = currentScreen->clipBound_X2;
1600
1601
if (edge->end < currentScreen->clipBound_X1)
1602
edge->end = currentScreen->clipBound_X1;
1603
if (edge->end > currentScreen->clipBound_X2)
1604
edge->end = currentScreen->clipBound_X2;
1605
1606
int32 count = edge->end - edge->start;
1607
for (int32 x = 0; x < count; ++x) {
1608
if (frameBuffer[edge->start + x] == maskColor)
1609
frameBuffer[edge->start + x] = color16;
1610
}
1611
++edge;
1612
frameBuffer += currentScreen->pitch;
1613
}
1614
}
1615
break;
1616
1617
case INK_UNMASKED:
1618
if (top <= bottom) {
1619
ScanEdge *edge = &scanEdgeBuffer[top];
1620
int32 sizeY = bottom - top;
1621
1622
for (int32 y = 0; y < sizeY; ++y) {
1623
if (edge->start < currentScreen->clipBound_X1)
1624
edge->start = currentScreen->clipBound_X1;
1625
if (edge->start > currentScreen->clipBound_X2)
1626
edge->start = currentScreen->clipBound_X2;
1627
1628
if (edge->end < currentScreen->clipBound_X1)
1629
edge->end = currentScreen->clipBound_X1;
1630
if (edge->end > currentScreen->clipBound_X2)
1631
edge->end = currentScreen->clipBound_X2;
1632
1633
int32 count = edge->end - edge->start;
1634
for (int32 x = 0; x < count; ++x) {
1635
if (frameBuffer[edge->start + x] != maskColor)
1636
frameBuffer[edge->start + x] = color16;
1637
}
1638
++edge;
1639
frameBuffer += currentScreen->pitch;
1640
}
1641
}
1642
break;
1643
}
1644
}
1645
}
1646
}
1647
void RSDK::DrawCircleOutline(int32 x, int32 y, int32 innerRadius, int32 outerRadius, uint32 color, int32 alpha, int32 inkEffect,
1648
bool32 screenRelative)
1649
{
1650
switch (inkEffect) {
1651
default: break;
1652
case INK_ALPHA:
1653
if (alpha > 0xFF)
1654
inkEffect = INK_NONE;
1655
else if (alpha <= 0)
1656
return;
1657
break;
1658
1659
case INK_ADD:
1660
case INK_SUB:
1661
if (alpha > 0xFF)
1662
alpha = 0xFF;
1663
else if (alpha <= 0)
1664
return;
1665
break;
1666
1667
case INK_TINT:
1668
if (!tintLookupTable)
1669
return;
1670
break;
1671
}
1672
1673
if (!screenRelative) {
1674
x = FROM_FIXED(x) - currentScreen->position.x;
1675
y = FROM_FIXED(y) - currentScreen->position.y;
1676
}
1677
1678
if (outerRadius > 0 && innerRadius < outerRadius) {
1679
int32 top = y - outerRadius;
1680
int32 left = x - outerRadius;
1681
int32 right = x + outerRadius;
1682
int32 bottom = y + outerRadius;
1683
1684
if (left < currentScreen->clipBound_X1)
1685
left = currentScreen->clipBound_X1;
1686
if (left > currentScreen->clipBound_X2)
1687
left = currentScreen->clipBound_X2;
1688
1689
if (right < currentScreen->clipBound_X1)
1690
right = currentScreen->clipBound_X1;
1691
if (right > currentScreen->clipBound_X2)
1692
right = currentScreen->clipBound_X2;
1693
1694
if (top < currentScreen->clipBound_Y1)
1695
top = currentScreen->clipBound_Y1;
1696
if (top > currentScreen->clipBound_Y1)
1697
top = currentScreen->clipBound_Y1;
1698
1699
if (bottom < currentScreen->clipBound_Y2)
1700
bottom = currentScreen->clipBound_Y2;
1701
if (bottom > currentScreen->clipBound_Y2)
1702
bottom = currentScreen->clipBound_Y2;
1703
1704
if (left != right && top != bottom) {
1705
int32 ir2 = innerRadius * innerRadius;
1706
int32 or2 = outerRadius * outerRadius;
1707
validDraw = true;
1708
uint16 *frameBuffer = &currentScreen->frameBuffer[left + top * currentScreen->pitch];
1709
uint16 color16 = rgb32To16_B[(color >> 0) & 0xFF] | rgb32To16_G[(color >> 8) & 0xFF] | rgb32To16_R[(color >> 16) & 0xFF];
1710
int32 pitch = (left + currentScreen->pitch - right);
1711
1712
switch (inkEffect) {
1713
default: break;
1714
case INK_NONE:
1715
if (top < bottom) {
1716
int32 distY1 = top - y;
1717
int32 distY2 = bottom - top;
1718
do {
1719
int32 y2 = distY1 * distY1;
1720
if (left < right) {
1721
int32 distX1 = left - x;
1722
int32 distX2 = right - left;
1723
do {
1724
int32 r2 = y2 + distX1 * distX1;
1725
if (r2 >= ir2 && r2 < or2)
1726
*frameBuffer = color16;
1727
++frameBuffer;
1728
++distX1;
1729
--distX2;
1730
} while (distX2);
1731
}
1732
frameBuffer += pitch;
1733
--distY2;
1734
++distY1;
1735
} while (distY2);
1736
}
1737
break;
1738
1739
case INK_BLEND:
1740
if (top < bottom) {
1741
int32 distY1 = top - y;
1742
int32 distY2 = bottom - top;
1743
do {
1744
int32 y2 = distY1 * distY1;
1745
if (left < right) {
1746
int32 distX1 = left - x;
1747
int32 distX2 = right - left;
1748
do {
1749
int32 r2 = y2 + distX1 * distX1;
1750
if (r2 >= ir2 && r2 < or2)
1751
setPixelBlend(color16, *frameBuffer);
1752
++frameBuffer;
1753
++distX1;
1754
--distX2;
1755
} while (distX2);
1756
}
1757
frameBuffer += pitch;
1758
--distY2;
1759
++distY1;
1760
} while (distY2);
1761
}
1762
break;
1763
1764
case INK_ALPHA:
1765
if (top < bottom) {
1766
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
1767
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
1768
1769
int32 distY1 = top - y;
1770
int32 distY2 = bottom - top;
1771
do {
1772
int32 y2 = distY1 * distY1;
1773
if (left < right) {
1774
int32 distX1 = left - x;
1775
int32 distX2 = right - left;
1776
do {
1777
int32 r2 = y2 + distX1 * distX1;
1778
if (r2 >= ir2 && r2 < or2) {
1779
setPixelAlpha(color16, *frameBuffer, alpha);
1780
}
1781
++frameBuffer;
1782
++distX1;
1783
--distX2;
1784
} while (distX2);
1785
}
1786
frameBuffer += pitch;
1787
--distY2;
1788
++distY1;
1789
} while (distY2);
1790
}
1791
break;
1792
1793
case INK_ADD: {
1794
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
1795
if (top < bottom) {
1796
int32 distY1 = top - y;
1797
int32 distY2 = bottom - top;
1798
do {
1799
int32 y2 = distY1 * distY1;
1800
if (left < right) {
1801
int32 distX1 = left - x;
1802
int32 distX2 = right - left;
1803
do {
1804
int32 r2 = y2 + distX1 * distX1;
1805
if (r2 >= ir2 && r2 < or2) {
1806
setPixelAdditive(color16, *frameBuffer);
1807
}
1808
++frameBuffer;
1809
++distX1;
1810
--distX2;
1811
} while (distX2);
1812
}
1813
frameBuffer += pitch;
1814
--distY2;
1815
++distY1;
1816
} while (distY2);
1817
}
1818
break;
1819
}
1820
1821
case INK_SUB: {
1822
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
1823
if (top < bottom) {
1824
int32 distY1 = top - y;
1825
int32 distY2 = bottom - top;
1826
do {
1827
int32 y2 = distY1 * distY1;
1828
if (left < right) {
1829
int32 distX1 = left - x;
1830
int32 distX2 = right - left;
1831
do {
1832
int32 r2 = y2 + distX1 * distX1;
1833
if (r2 >= ir2 && r2 < or2) {
1834
setPixelSubtractive(color16, *frameBuffer);
1835
}
1836
++frameBuffer;
1837
++distX1;
1838
--distX2;
1839
} while (distX2);
1840
}
1841
frameBuffer += pitch;
1842
--distY2;
1843
++distY1;
1844
} while (distY2);
1845
}
1846
break;
1847
}
1848
1849
case INK_TINT:
1850
if (top < bottom) {
1851
int32 distY1 = top - y;
1852
int32 distY2 = bottom - top;
1853
do {
1854
int32 y2 = distY1 * distY1;
1855
if (left < right) {
1856
int32 distX1 = left - x;
1857
int32 distX2 = right - left;
1858
do {
1859
int32 r2 = y2 + distX1 * distX1;
1860
if (r2 >= ir2 && r2 < or2)
1861
*frameBuffer = tintLookupTable[*frameBuffer];
1862
++frameBuffer;
1863
++distX1;
1864
--distX2;
1865
} while (distX2);
1866
}
1867
frameBuffer += pitch;
1868
--distY2;
1869
++distY1;
1870
} while (distY2);
1871
}
1872
break;
1873
1874
case INK_MASKED:
1875
if (top < bottom) {
1876
int32 distY1 = top - y;
1877
int32 distY2 = bottom - top;
1878
do {
1879
int32 y2 = distY1 * distY1;
1880
if (left < right) {
1881
int32 distX1 = left - x;
1882
int32 distX2 = right - left;
1883
do {
1884
int32 r2 = y2 + distX1 * distX1;
1885
if (r2 >= ir2 && r2 < or2 && *frameBuffer == maskColor)
1886
*frameBuffer = color16;
1887
++frameBuffer;
1888
++distX1;
1889
--distX2;
1890
} while (distX2);
1891
}
1892
frameBuffer += pitch;
1893
--distY2;
1894
++distY1;
1895
} while (distY2);
1896
}
1897
break;
1898
1899
case INK_UNMASKED:
1900
if (top < bottom) {
1901
int32 distY1 = top - y;
1902
int32 distY2 = bottom - top;
1903
do {
1904
int32 y2 = distY1 * distY1;
1905
if (left < right) {
1906
int32 distX1 = left - x;
1907
int32 distX2 = right - left;
1908
do {
1909
int32 r2 = y2 + distX1 * distX1;
1910
if (r2 >= ir2 && r2 < or2 && *frameBuffer != maskColor)
1911
*frameBuffer = color16;
1912
++frameBuffer;
1913
++distX1;
1914
--distX2;
1915
} while (distX2);
1916
}
1917
frameBuffer += pitch;
1918
--distY2;
1919
++distY1;
1920
} while (distY2);
1921
}
1922
break;
1923
}
1924
}
1925
}
1926
}
1927
1928
void RSDK::DrawFace(Vector2 *vertices, int32 vertCount, int32 r, int32 g, int32 b, int32 alpha, int32 inkEffect)
1929
{
1930
switch (inkEffect) {
1931
default: break;
1932
case INK_ALPHA:
1933
if (alpha > 0xFF)
1934
inkEffect = INK_NONE;
1935
else if (alpha <= 0)
1936
return;
1937
break;
1938
1939
case INK_ADD:
1940
case INK_SUB:
1941
if (alpha > 0xFF)
1942
alpha = 0xFF;
1943
else if (alpha <= 0)
1944
return;
1945
break;
1946
1947
case INK_TINT:
1948
if (!tintLookupTable)
1949
return;
1950
break;
1951
}
1952
1953
int32 top = 0x7FFFFFFF;
1954
int32 bottom = -0x10000;
1955
for (int32 v = 0; v < vertCount; ++v) {
1956
if (vertices[v].y < top)
1957
top = vertices[v].y;
1958
if (vertices[v].y > bottom)
1959
bottom = vertices[v].y;
1960
}
1961
1962
int32 topScreen = FROM_FIXED(top);
1963
int32 bottomScreen = FROM_FIXED(bottom);
1964
1965
if (topScreen < currentScreen->clipBound_Y1)
1966
topScreen = currentScreen->clipBound_Y1;
1967
if (topScreen > currentScreen->clipBound_Y2)
1968
topScreen = currentScreen->clipBound_Y2;
1969
1970
if (bottomScreen < currentScreen->clipBound_Y1)
1971
bottomScreen = currentScreen->clipBound_Y1;
1972
if (bottomScreen > currentScreen->clipBound_Y2)
1973
bottomScreen = currentScreen->clipBound_Y2;
1974
1975
if (topScreen != bottomScreen) {
1976
ScanEdge *edge = &scanEdgeBuffer[topScreen];
1977
for (int32 s = topScreen; s <= bottomScreen; ++s) {
1978
edge->start = 0x7FFF;
1979
edge->end = -1;
1980
++edge;
1981
}
1982
1983
for (int32 v = 0; v < vertCount - 1; ++v) {
1984
ProcessScanEdge(vertices[v + 0].x, vertices[v + 0].y, vertices[v + 1].x, vertices[v + 1].y);
1985
}
1986
ProcessScanEdge(vertices[0].x, vertices[0].y, vertices[vertCount - 1].x, vertices[vertCount - 1].y);
1987
1988
uint16 *frameBuffer = &currentScreen->frameBuffer[topScreen * currentScreen->pitch];
1989
uint16 color16 = rgb32To16_B[b] | rgb32To16_G[g] | rgb32To16_R[r];
1990
1991
edge = &scanEdgeBuffer[topScreen];
1992
switch (inkEffect) {
1993
default: break;
1994
1995
case INK_NONE:
1996
for (int32 s = topScreen; s <= bottomScreen; ++s) {
1997
if (edge->start < currentScreen->clipBound_X1)
1998
edge->start = currentScreen->clipBound_X1;
1999
if (edge->start > currentScreen->clipBound_X2)
2000
edge->start = currentScreen->clipBound_X2;
2001
2002
if (edge->end < currentScreen->clipBound_X1)
2003
edge->end = currentScreen->clipBound_X1;
2004
if (edge->end > currentScreen->clipBound_X2)
2005
edge->end = currentScreen->clipBound_X2;
2006
2007
int32 count = edge->end - edge->start;
2008
for (int32 x = 0; x < count; ++x) {
2009
frameBuffer[edge->start + x] = color16;
2010
}
2011
++edge;
2012
frameBuffer += currentScreen->pitch;
2013
}
2014
break;
2015
2016
case INK_BLEND:
2017
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2018
if (edge->start < currentScreen->clipBound_X1)
2019
edge->start = currentScreen->clipBound_X1;
2020
if (edge->start > currentScreen->clipBound_X2)
2021
edge->start = currentScreen->clipBound_X2;
2022
2023
if (edge->end < currentScreen->clipBound_X1)
2024
edge->end = currentScreen->clipBound_X1;
2025
if (edge->end > currentScreen->clipBound_X2)
2026
edge->end = currentScreen->clipBound_X2;
2027
2028
int32 count = edge->end - edge->start;
2029
for (int32 x = 0; x < count; ++x) {
2030
setPixelBlend(color16, frameBuffer[edge->start + x]);
2031
}
2032
++edge;
2033
frameBuffer += currentScreen->pitch;
2034
}
2035
break;
2036
2037
case INK_ALPHA: {
2038
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
2039
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
2040
2041
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2042
if (edge->start < currentScreen->clipBound_X1)
2043
edge->start = currentScreen->clipBound_X1;
2044
if (edge->start > currentScreen->clipBound_X2)
2045
edge->start = currentScreen->clipBound_X2;
2046
2047
if (edge->end < currentScreen->clipBound_X1)
2048
edge->end = currentScreen->clipBound_X1;
2049
if (edge->end > currentScreen->clipBound_X2)
2050
edge->end = currentScreen->clipBound_X2;
2051
2052
int32 count = edge->end - edge->start;
2053
for (int32 x = 0; x < count; ++x) {
2054
setPixelAlpha(color16, frameBuffer[edge->start + x], alpha);
2055
}
2056
++edge;
2057
frameBuffer += currentScreen->pitch;
2058
}
2059
break;
2060
}
2061
2062
case INK_ADD: {
2063
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
2064
2065
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2066
if (edge->start < currentScreen->clipBound_X1)
2067
edge->start = currentScreen->clipBound_X1;
2068
if (edge->start > currentScreen->clipBound_X2)
2069
edge->start = currentScreen->clipBound_X2;
2070
2071
if (edge->end < currentScreen->clipBound_X1)
2072
edge->end = currentScreen->clipBound_X1;
2073
if (edge->end > currentScreen->clipBound_X2)
2074
edge->end = currentScreen->clipBound_X2;
2075
2076
int32 count = edge->end - edge->start;
2077
for (int32 x = 0; x < count; ++x) {
2078
setPixelAdditive(color16, frameBuffer[edge->start + x]);
2079
}
2080
2081
++edge;
2082
frameBuffer += currentScreen->pitch;
2083
}
2084
break;
2085
}
2086
2087
case INK_SUB: {
2088
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
2089
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2090
if (edge->start < currentScreen->clipBound_X1)
2091
edge->start = currentScreen->clipBound_X1;
2092
if (edge->start > currentScreen->clipBound_X2)
2093
edge->start = currentScreen->clipBound_X2;
2094
2095
if (edge->end < currentScreen->clipBound_X1)
2096
edge->end = currentScreen->clipBound_X1;
2097
if (edge->end > currentScreen->clipBound_X2)
2098
edge->end = currentScreen->clipBound_X2;
2099
2100
int32 count = edge->end - edge->start;
2101
for (int32 x = 0; x < count; ++x) {
2102
setPixelSubtractive(color16, frameBuffer[edge->start + x]);
2103
}
2104
2105
++edge;
2106
frameBuffer += currentScreen->pitch;
2107
}
2108
break;
2109
}
2110
2111
case INK_TINT:
2112
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2113
if (edge->start < currentScreen->clipBound_X1)
2114
edge->start = currentScreen->clipBound_X1;
2115
if (edge->start > currentScreen->clipBound_X2)
2116
edge->start = currentScreen->clipBound_X2;
2117
2118
if (edge->end < currentScreen->clipBound_X1)
2119
edge->end = currentScreen->clipBound_X1;
2120
if (edge->end > currentScreen->clipBound_X2)
2121
edge->end = currentScreen->clipBound_X2;
2122
2123
int32 count = edge->end - edge->start;
2124
for (int32 x = 0; x < count; ++x) {
2125
frameBuffer[edge->start + x] = tintLookupTable[frameBuffer[edge->start + x]];
2126
}
2127
2128
++edge;
2129
frameBuffer += currentScreen->pitch;
2130
}
2131
break;
2132
2133
case INK_MASKED:
2134
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2135
if (edge->start < currentScreen->clipBound_X1)
2136
edge->start = currentScreen->clipBound_X1;
2137
if (edge->start > currentScreen->clipBound_X2)
2138
edge->start = currentScreen->clipBound_X2;
2139
2140
if (edge->end < currentScreen->clipBound_X1)
2141
edge->end = currentScreen->clipBound_X1;
2142
if (edge->end > currentScreen->clipBound_X2)
2143
edge->end = currentScreen->clipBound_X2;
2144
2145
int32 count = edge->end - edge->start;
2146
for (int32 x = 0; x < count; ++x) {
2147
if (frameBuffer[edge->start + x] == maskColor)
2148
frameBuffer[edge->start + x] = color16;
2149
}
2150
2151
++edge;
2152
frameBuffer += currentScreen->pitch;
2153
}
2154
break;
2155
2156
case INK_UNMASKED:
2157
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2158
if (edge->start < currentScreen->clipBound_X1)
2159
edge->start = currentScreen->clipBound_X1;
2160
if (edge->start > currentScreen->clipBound_X2)
2161
edge->start = currentScreen->clipBound_X2;
2162
2163
if (edge->end < currentScreen->clipBound_X1)
2164
edge->end = currentScreen->clipBound_X1;
2165
if (edge->end > currentScreen->clipBound_X2)
2166
edge->end = currentScreen->clipBound_X2;
2167
2168
int32 count = edge->end - edge->start;
2169
for (int32 x = 0; x < count; ++x) {
2170
if (frameBuffer[edge->start + x] != maskColor)
2171
frameBuffer[edge->start + x] = color16;
2172
}
2173
2174
++edge;
2175
frameBuffer += currentScreen->pitch;
2176
}
2177
break;
2178
}
2179
}
2180
}
2181
void RSDK::DrawBlendedFace(Vector2 *vertices, uint32 *colors, int32 vertCount, int32 alpha, int32 inkEffect)
2182
{
2183
switch (inkEffect) {
2184
default: break;
2185
case INK_ALPHA:
2186
if (alpha > 0xFF)
2187
inkEffect = INK_NONE;
2188
else if (alpha <= 0)
2189
return;
2190
break;
2191
2192
case INK_ADD:
2193
case INK_SUB:
2194
if (alpha > 0xFF)
2195
alpha = 0xFF;
2196
else if (alpha <= 0)
2197
return;
2198
break;
2199
2200
case INK_TINT:
2201
if (!tintLookupTable)
2202
return;
2203
break;
2204
}
2205
2206
int32 top = 0x7FFFFFFF;
2207
int32 bottom = -0x10000;
2208
for (int32 v = 0; v < vertCount; ++v) {
2209
if (vertices[v].y < top)
2210
top = vertices[v].y;
2211
if (vertices[v].y > bottom)
2212
bottom = vertices[v].y;
2213
}
2214
2215
int32 topScreen = FROM_FIXED(top);
2216
int32 bottomScreen = FROM_FIXED(bottom);
2217
2218
if (topScreen < currentScreen->clipBound_Y1)
2219
topScreen = currentScreen->clipBound_Y1;
2220
if (topScreen > currentScreen->clipBound_Y2)
2221
topScreen = currentScreen->clipBound_Y2;
2222
2223
if (bottomScreen < currentScreen->clipBound_Y1)
2224
bottomScreen = currentScreen->clipBound_Y1;
2225
if (bottomScreen > currentScreen->clipBound_Y2)
2226
bottomScreen = currentScreen->clipBound_Y2;
2227
2228
if (topScreen != bottomScreen) {
2229
ScanEdge *edge = &scanEdgeBuffer[topScreen];
2230
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2231
edge->start = 0x7FFF;
2232
edge->end = -1;
2233
++edge;
2234
}
2235
2236
for (int32 v = 0; v < vertCount - 1; ++v) {
2237
ProcessScanEdgeClr(colors[v + 0], colors[v + 1], vertices[v + 0].x, vertices[v + 0].y, vertices[v + 1].x, vertices[v + 1].y);
2238
}
2239
ProcessScanEdgeClr(colors[vertCount - 1], colors[0], vertices[vertCount - 1].x, vertices[vertCount - 1].y, vertices[0].x, vertices[0].y);
2240
2241
uint16 *frameBuffer = &currentScreen->frameBuffer[topScreen * currentScreen->pitch];
2242
2243
edge = &scanEdgeBuffer[topScreen];
2244
switch (inkEffect) {
2245
default: break;
2246
case INK_NONE:
2247
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2248
int32 count = edge->end - edge->start;
2249
int32 deltaR = 0;
2250
int32 deltaG = 0;
2251
int32 deltaB = 0;
2252
if (count > 0) {
2253
deltaR = (edge->endR - edge->startR) / count;
2254
deltaG = (edge->endG - edge->startG) / count;
2255
deltaB = (edge->endB - edge->startB) / count;
2256
}
2257
int32 startR = edge->startR;
2258
int32 startG = edge->startG;
2259
int32 startB = edge->startB;
2260
2261
if (edge->start > currentScreen->clipBound_X2) {
2262
edge->start = currentScreen->clipBound_X2;
2263
}
2264
else if (edge->start < currentScreen->clipBound_X1) {
2265
int32 dist = (currentScreen->clipBound_X1 - edge->start);
2266
startR += deltaR * dist;
2267
startG += deltaG * dist;
2268
startB += deltaB * dist;
2269
count -= dist;
2270
edge->start = currentScreen->clipBound_X1;
2271
}
2272
2273
if (edge->end < currentScreen->clipBound_X1) {
2274
edge->end = currentScreen->clipBound_X1;
2275
count = currentScreen->clipBound_X1 - edge->start;
2276
}
2277
2278
if (edge->end > currentScreen->clipBound_X2) {
2279
edge->end = currentScreen->clipBound_X2;
2280
count = currentScreen->clipBound_X2 - edge->start;
2281
}
2282
2283
for (int32 x = 0; x < count; ++x) {
2284
frameBuffer[edge->start + x] = (startB >> 19) + ((startG >> 13) & 0x7E0) + ((startR >> 8) & 0xF800);
2285
2286
startR += deltaR;
2287
startG += deltaG;
2288
startB += deltaB;
2289
}
2290
++edge;
2291
frameBuffer += currentScreen->pitch;
2292
}
2293
break;
2294
2295
case INK_BLEND:
2296
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2297
int32 start = edge->start;
2298
int32 count = edge->end - edge->start;
2299
int32 deltaR = 0;
2300
int32 deltaG = 0;
2301
int32 deltaB = 0;
2302
if (count > 0) {
2303
deltaR = (edge->endR - edge->startR) / count;
2304
deltaG = (edge->endG - edge->startG) / count;
2305
deltaB = (edge->endB - edge->startB) / count;
2306
}
2307
int32 startR = edge->startR;
2308
int32 startG = edge->startG;
2309
int32 startB = edge->startB;
2310
2311
if (start > currentScreen->clipBound_X2) {
2312
edge->start = currentScreen->clipBound_X2;
2313
}
2314
2315
if (start < currentScreen->clipBound_X1) {
2316
startR += deltaR * (currentScreen->clipBound_X1 - edge->start);
2317
startG += deltaG * (currentScreen->clipBound_X1 - edge->start);
2318
startB += deltaB * (currentScreen->clipBound_X1 - edge->start);
2319
count -= (currentScreen->clipBound_X1 - edge->start);
2320
edge->start = currentScreen->clipBound_X1;
2321
}
2322
2323
if (edge->end < currentScreen->clipBound_X1) {
2324
edge->end = currentScreen->clipBound_X1;
2325
}
2326
2327
if (edge->end > currentScreen->clipBound_X2) {
2328
edge->end = currentScreen->clipBound_X2;
2329
count = currentScreen->clipBound_X2 - edge->start;
2330
}
2331
2332
for (int32 x = 0; x < count; ++x) {
2333
uint16 color = (startB >> 19) + ((startG >> 13) & 0x7E0) + ((startR >> 8) & 0xF800);
2334
setPixelBlend(color, frameBuffer[edge->start + x]);
2335
2336
startR += deltaR;
2337
startG += deltaG;
2338
startB += deltaB;
2339
}
2340
2341
++edge;
2342
frameBuffer += currentScreen->pitch;
2343
}
2344
break;
2345
2346
case INK_ALPHA: {
2347
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
2348
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
2349
2350
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2351
int32 start = edge->start;
2352
int32 count = edge->end - edge->start;
2353
int32 deltaR = 0;
2354
int32 deltaG = 0;
2355
int32 deltaB = 0;
2356
if (count > 0) {
2357
deltaR = (edge->endR - edge->startR) / count;
2358
deltaG = (edge->endG - edge->startG) / count;
2359
deltaB = (edge->endB - edge->startB) / count;
2360
}
2361
int32 startR = edge->startR;
2362
int32 startG = edge->startG;
2363
int32 startB = edge->startB;
2364
2365
if (start > currentScreen->clipBound_X2) {
2366
edge->start = currentScreen->clipBound_X2;
2367
}
2368
2369
if (start < currentScreen->clipBound_X1) {
2370
startR += deltaR * (currentScreen->clipBound_X1 - edge->start);
2371
startG += deltaG * (currentScreen->clipBound_X1 - edge->start);
2372
startB += deltaB * (currentScreen->clipBound_X1 - edge->start);
2373
count -= (currentScreen->clipBound_X1 - edge->start);
2374
edge->start = currentScreen->clipBound_X1;
2375
}
2376
2377
if (edge->end < currentScreen->clipBound_X1) {
2378
edge->end = currentScreen->clipBound_X1;
2379
}
2380
2381
if (edge->end > currentScreen->clipBound_X2) {
2382
edge->end = currentScreen->clipBound_X2;
2383
count = currentScreen->clipBound_X2 - edge->start;
2384
}
2385
2386
for (int32 x = 0; x < count; ++x) {
2387
uint16 color = (startB >> 19) + ((startG >> 13) & 0x7E0) + ((startR >> 8) & 0xF800);
2388
setPixelAlpha(color, frameBuffer[edge->start + x], alpha);
2389
2390
startR += deltaR;
2391
startG += deltaG;
2392
startB += deltaB;
2393
}
2394
++edge;
2395
frameBuffer += currentScreen->pitch;
2396
}
2397
break;
2398
}
2399
2400
case INK_ADD: {
2401
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
2402
2403
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2404
int32 start = edge->start;
2405
int32 count = edge->end - edge->start;
2406
int32 deltaR = 0;
2407
int32 deltaG = 0;
2408
int32 deltaB = 0;
2409
if (count > 0) {
2410
deltaR = (edge->endR - edge->startR) / count;
2411
deltaG = (edge->endG - edge->startG) / count;
2412
deltaB = (edge->endB - edge->startB) / count;
2413
}
2414
int32 startR = edge->startR;
2415
int32 startG = edge->startG;
2416
int32 startB = edge->startB;
2417
2418
if (start > currentScreen->clipBound_X2) {
2419
edge->start = currentScreen->clipBound_X2;
2420
}
2421
2422
if (start < currentScreen->clipBound_X1) {
2423
startR += deltaR * (currentScreen->clipBound_X1 - edge->start);
2424
startG += deltaG * (currentScreen->clipBound_X1 - edge->start);
2425
startB += deltaB * (currentScreen->clipBound_X1 - edge->start);
2426
count -= (currentScreen->clipBound_X1 - edge->start);
2427
edge->start = currentScreen->clipBound_X1;
2428
}
2429
2430
if (edge->end < currentScreen->clipBound_X1) {
2431
edge->end = currentScreen->clipBound_X1;
2432
}
2433
2434
if (edge->end > currentScreen->clipBound_X2) {
2435
edge->end = currentScreen->clipBound_X2;
2436
count = currentScreen->clipBound_X2 - edge->start;
2437
}
2438
2439
for (int32 x = 0; x < count; ++x) {
2440
uint16 color = (startB >> 19) + ((startG >> 13) & 0x7E0) + ((startR >> 8) & 0xF800);
2441
setPixelAdditive(color, frameBuffer[edge->start + x]);
2442
2443
startR += deltaR;
2444
startG += deltaG;
2445
startB += deltaB;
2446
}
2447
2448
++edge;
2449
frameBuffer += currentScreen->pitch;
2450
}
2451
break;
2452
}
2453
2454
case INK_SUB: {
2455
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
2456
2457
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2458
int32 start = edge->start;
2459
int32 count = edge->end - edge->start;
2460
int32 deltaR = 0;
2461
int32 deltaG = 0;
2462
int32 deltaB = 0;
2463
if (count > 0) {
2464
deltaR = (edge->endR - edge->startR) / count;
2465
deltaG = (edge->endG - edge->startG) / count;
2466
deltaB = (edge->endB - edge->startB) / count;
2467
}
2468
int32 startR = edge->startR;
2469
int32 startG = edge->startG;
2470
int32 startB = edge->startB;
2471
2472
if (start > currentScreen->clipBound_X2) {
2473
edge->start = currentScreen->clipBound_X2;
2474
}
2475
2476
if (start < currentScreen->clipBound_X1) {
2477
startR += deltaR * (currentScreen->clipBound_X1 - edge->start);
2478
startG += deltaG * (currentScreen->clipBound_X1 - edge->start);
2479
startB += deltaB * (currentScreen->clipBound_X1 - edge->start);
2480
count -= (currentScreen->clipBound_X1 - edge->start);
2481
edge->start = currentScreen->clipBound_X1;
2482
}
2483
2484
if (edge->end < currentScreen->clipBound_X1) {
2485
edge->end = currentScreen->clipBound_X1;
2486
}
2487
2488
if (edge->end > currentScreen->clipBound_X2) {
2489
edge->end = currentScreen->clipBound_X2;
2490
count = currentScreen->clipBound_X2 - edge->start;
2491
}
2492
2493
for (int32 x = 0; x < count; ++x) {
2494
uint16 color = (startB >> 19) + ((startG >> 13) & 0x7E0) + ((startR >> 8) & 0xF800);
2495
setPixelSubtractive(color, frameBuffer[edge->start + x]);
2496
2497
startR += deltaR;
2498
startG += deltaG;
2499
startB += deltaB;
2500
}
2501
2502
++edge;
2503
frameBuffer += currentScreen->pitch;
2504
}
2505
break;
2506
}
2507
2508
case INK_TINT:
2509
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2510
int32 start = edge->start;
2511
int32 count = edge->end - edge->start;
2512
2513
#if RETRO_USE_ORIGINAL_CODE
2514
// Unused, ifdef'd out to help out ports for weaker hardware
2515
int32 deltaR = 0;
2516
int32 deltaG = 0;
2517
int32 deltaB = 0;
2518
if (count > 0) {
2519
deltaR = (edge->endR - edge->startR) / count;
2520
deltaG = (edge->endG - edge->startG) / count;
2521
deltaB = (edge->endB - edge->startB) / count;
2522
}
2523
int32 startR = edge->startR;
2524
int32 startG = edge->startG;
2525
int32 startB = edge->startB;
2526
#endif
2527
2528
if (start > currentScreen->clipBound_X2) {
2529
edge->start = currentScreen->clipBound_X2;
2530
}
2531
2532
if (start < currentScreen->clipBound_X1) {
2533
#if RETRO_USE_ORIGINAL_CODE
2534
// Unused, ifdef'd out to help out ports for weaker hardware
2535
startR += deltaR * (currentScreen->clipBound_X1 - edge->start);
2536
startG += deltaG * (currentScreen->clipBound_X1 - edge->start);
2537
startB += deltaB * (currentScreen->clipBound_X1 - edge->start);
2538
#endif
2539
2540
count -= (currentScreen->clipBound_X1 - edge->start);
2541
edge->start = currentScreen->clipBound_X1;
2542
}
2543
2544
if (edge->end < currentScreen->clipBound_X1) {
2545
edge->end = currentScreen->clipBound_X1;
2546
}
2547
2548
if (edge->end > currentScreen->clipBound_X2) {
2549
edge->end = currentScreen->clipBound_X2;
2550
count = currentScreen->clipBound_X2 - edge->start;
2551
}
2552
2553
for (int32 x = 0; x < count; ++x) {
2554
frameBuffer[edge->start + x] = tintLookupTable[frameBuffer[edge->start + x]];
2555
2556
#if RETRO_USE_ORIGINAL_CODE
2557
// Unused, ifdef'd out to help out ports for weaker hardware
2558
startR += deltaR;
2559
startG += deltaG;
2560
startB += deltaB;
2561
#endif
2562
}
2563
2564
++edge;
2565
frameBuffer += currentScreen->pitch;
2566
}
2567
break;
2568
2569
case INK_MASKED:
2570
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2571
int32 start = edge->start;
2572
int32 count = edge->end - edge->start;
2573
int32 deltaR = 0;
2574
int32 deltaG = 0;
2575
int32 deltaB = 0;
2576
if (count > 0) {
2577
deltaR = (edge->endR - edge->startR) / count;
2578
deltaG = (edge->endG - edge->startG) / count;
2579
deltaB = (edge->endB - edge->startB) / count;
2580
}
2581
int32 startR = edge->startR;
2582
int32 startG = edge->startG;
2583
int32 startB = edge->startB;
2584
2585
if (start > currentScreen->clipBound_X2) {
2586
edge->start = currentScreen->clipBound_X2;
2587
}
2588
2589
if (start < currentScreen->clipBound_X1) {
2590
startR += deltaR * (currentScreen->clipBound_X1 - edge->start);
2591
startG += deltaG * (currentScreen->clipBound_X1 - edge->start);
2592
startB += deltaB * (currentScreen->clipBound_X1 - edge->start);
2593
count -= (currentScreen->clipBound_X1 - edge->start);
2594
edge->start = currentScreen->clipBound_X1;
2595
}
2596
2597
if (edge->end < currentScreen->clipBound_X1 || edge->end > currentScreen->clipBound_X2) {
2598
edge->end = currentScreen->clipBound_X2;
2599
count = currentScreen->clipBound_X2 - edge->start;
2600
}
2601
2602
for (int32 x = 0; x < count; ++x) {
2603
if (frameBuffer[edge->start + x] == maskColor)
2604
frameBuffer[edge->start + x] = (startB >> 19) + ((startG >> 13) & 0x7E0) + ((startR >> 8) & 0xF800);
2605
2606
startR += deltaR;
2607
startG += deltaG;
2608
startB += deltaB;
2609
}
2610
2611
++edge;
2612
frameBuffer += currentScreen->pitch;
2613
}
2614
break;
2615
2616
case INK_UNMASKED:
2617
for (int32 s = topScreen; s <= bottomScreen; ++s) {
2618
int32 start = edge->start;
2619
int32 count = edge->end - edge->start;
2620
int32 deltaR = 0;
2621
int32 deltaG = 0;
2622
int32 deltaB = 0;
2623
if (count > 0) {
2624
deltaR = (edge->endR - edge->startR) / count;
2625
deltaG = (edge->endG - edge->startG) / count;
2626
deltaB = (edge->endB - edge->startB) / count;
2627
}
2628
int32 startR = edge->startR;
2629
int32 startG = edge->startG;
2630
int32 startB = edge->startB;
2631
2632
if (start > currentScreen->clipBound_X2) {
2633
edge->start = currentScreen->clipBound_X2;
2634
}
2635
2636
if (start < currentScreen->clipBound_X1) {
2637
startR += deltaR * (currentScreen->clipBound_X1 - edge->start);
2638
startG += deltaG * (currentScreen->clipBound_X1 - edge->start);
2639
startB += deltaB * (currentScreen->clipBound_X1 - edge->start);
2640
count -= (currentScreen->clipBound_X1 - edge->start);
2641
edge->start = currentScreen->clipBound_X1;
2642
}
2643
2644
if (edge->end < currentScreen->clipBound_X1) {
2645
edge->end = currentScreen->clipBound_X1;
2646
}
2647
2648
if (edge->end > currentScreen->clipBound_X2) {
2649
edge->end = currentScreen->clipBound_X2;
2650
count = currentScreen->clipBound_X2 - edge->start;
2651
}
2652
2653
for (int32 x = 0; x < count; ++x) {
2654
if (frameBuffer[edge->start + x] != maskColor)
2655
frameBuffer[edge->start + x] = (startB >> 19) + ((startG >> 13) & 0x7E0) + ((startR >> 8) & 0xF800);
2656
2657
startR += deltaR;
2658
startG += deltaG;
2659
startB += deltaB;
2660
}
2661
2662
++edge;
2663
frameBuffer += currentScreen->pitch;
2664
}
2665
break;
2666
}
2667
}
2668
}
2669
2670
void RSDK::DrawSprite(Animator *animator, Vector2 *position, bool32 screenRelative)
2671
{
2672
if (animator && animator->frames) {
2673
SpriteFrame *frame = &animator->frames[animator->frameID];
2674
Vector2 pos;
2675
if (!position)
2676
pos = sceneInfo.entity->position;
2677
else
2678
pos = *position;
2679
2680
pos.x >>= 0x10;
2681
pos.y >>= 0x10;
2682
if (!screenRelative) {
2683
pos.x -= currentScreen->position.x;
2684
pos.y -= currentScreen->position.y;
2685
}
2686
2687
int32 rotation = sceneInfo.entity->rotation;
2688
int32 drawFX = sceneInfo.entity->drawFX;
2689
if (sceneInfo.entity->drawFX & FX_ROTATE) {
2690
switch (animator->rotationStyle) {
2691
case ROTSTYLE_NONE:
2692
rotation = 0;
2693
if ((sceneInfo.entity->drawFX & FX_ROTATE) != FX_NONE)
2694
drawFX ^= FX_ROTATE;
2695
break;
2696
2697
case ROTSTYLE_FULL:
2698
rotation = sceneInfo.entity->rotation & 0x1FF;
2699
if (rotation == 0)
2700
drawFX ^= FX_ROTATE;
2701
break;
2702
2703
case ROTSTYLE_45DEG: // 0x00, 0x40, 0x80, 0xC0, 0x100, 0x140, 0x180, 0x1C0
2704
rotation = (sceneInfo.entity->rotation + 0x20) & 0x1C0;
2705
if (rotation == 0)
2706
drawFX ^= FX_ROTATE;
2707
break;
2708
2709
case ROTSTYLE_90DEG: // 0x00, 0x80, 0x100, 0x180
2710
rotation = (sceneInfo.entity->rotation + 0x40) & 0x180;
2711
if (rotation == 0)
2712
drawFX ^= FX_ROTATE;
2713
break;
2714
2715
case ROTSTYLE_180DEG: // 0x00, 0x100
2716
rotation = (sceneInfo.entity->rotation + 0x80) & 0x100;
2717
if (rotation == 0)
2718
drawFX ^= FX_ROTATE;
2719
break;
2720
2721
case ROTSTYLE_STATICFRAMES:
2722
if (sceneInfo.entity->rotation >= 0x100)
2723
rotation = 0x08 - ((0x214 - sceneInfo.entity->rotation) >> 6);
2724
else
2725
rotation = (sceneInfo.entity->rotation + 20) >> 6;
2726
2727
switch (rotation) {
2728
case 0: // 0 deg
2729
case 8: // 360 deg
2730
rotation = 0x00;
2731
if ((sceneInfo.entity->drawFX & FX_SCALE) != FX_NONE)
2732
drawFX ^= FX_ROTATE;
2733
break;
2734
2735
case 1: // 45 deg
2736
rotation = 0x80;
2737
frame += animator->frameCount;
2738
if (sceneInfo.entity->direction)
2739
rotation = 0x00;
2740
break;
2741
2742
case 2: // 90 deg
2743
rotation = 0x80;
2744
break;
2745
2746
case 3: // 135 deg
2747
rotation = 0x100;
2748
frame += animator->frameCount;
2749
if (sceneInfo.entity->direction)
2750
rotation = 0x80;
2751
break;
2752
2753
case 4: // 180 deg
2754
rotation = 0x100;
2755
break;
2756
2757
case 5: // 225 deg
2758
rotation = 0x180;
2759
frame += animator->frameCount;
2760
if (sceneInfo.entity->direction)
2761
rotation = 0x100;
2762
break;
2763
2764
case 6: // 270 deg
2765
rotation = 0x180;
2766
break;
2767
2768
case 7: // 315 deg
2769
rotation = 0x180;
2770
frame += animator->frameCount;
2771
if (!sceneInfo.entity->direction)
2772
rotation = 0;
2773
break;
2774
2775
default: break;
2776
}
2777
break;
2778
2779
default: break;
2780
}
2781
}
2782
2783
switch (drawFX) {
2784
case FX_NONE:
2785
DrawSpriteFlipped(pos.x + frame->pivotX, pos.y + frame->pivotY, frame->width, frame->height, frame->sprX, frame->sprY, FLIP_NONE,
2786
sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, frame->sheetID);
2787
break;
2788
2789
case FX_FLIP:
2790
switch (sceneInfo.entity->direction) {
2791
case FLIP_NONE:
2792
DrawSpriteFlipped(pos.x + frame->pivotX, pos.y + frame->pivotY, frame->width, frame->height, frame->sprX, frame->sprY,
2793
FLIP_NONE, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, frame->sheetID);
2794
break;
2795
2796
case FLIP_X:
2797
DrawSpriteFlipped(pos.x - frame->width - frame->pivotX, pos.y + frame->pivotY, frame->width, frame->height, frame->sprX,
2798
frame->sprY, FLIP_X, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, frame->sheetID);
2799
break;
2800
2801
case FLIP_Y:
2802
DrawSpriteFlipped(pos.x + frame->pivotX, pos.y - frame->height - frame->pivotY, frame->width, frame->height, frame->sprX,
2803
frame->sprY, FLIP_Y, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, frame->sheetID);
2804
break;
2805
2806
case FLIP_XY:
2807
DrawSpriteFlipped(pos.x - frame->width - frame->pivotX, pos.y - frame->height - frame->pivotY, frame->width, frame->height,
2808
frame->sprX, frame->sprY, FLIP_XY, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, frame->sheetID);
2809
break;
2810
2811
default: break;
2812
}
2813
break;
2814
2815
case FX_ROTATE:
2816
DrawSpriteRotozoom(pos.x, pos.y, frame->pivotX, frame->pivotY, frame->width, frame->height, frame->sprX, frame->sprY, 0x200, 0x200,
2817
FLIP_NONE, rotation, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, frame->sheetID);
2818
break;
2819
2820
case FX_ROTATE | FX_FLIP:
2821
DrawSpriteRotozoom(pos.x, pos.y, frame->pivotX, frame->pivotY, frame->width, frame->height, frame->sprX, frame->sprY, 0x200, 0x200,
2822
sceneInfo.entity->direction & FLIP_X, rotation, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha,
2823
frame->sheetID);
2824
break;
2825
2826
case FX_SCALE:
2827
DrawSpriteRotozoom(pos.x, pos.y, frame->pivotX, frame->pivotY, frame->width, frame->height, frame->sprX, frame->sprY,
2828
sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, FLIP_NONE, 0, sceneInfo.entity->inkEffect,
2829
sceneInfo.entity->alpha, frame->sheetID);
2830
break;
2831
2832
case FX_SCALE | FX_FLIP:
2833
DrawSpriteRotozoom(pos.x, pos.y, frame->pivotX, frame->pivotY, frame->width, frame->height, frame->sprX, frame->sprY,
2834
sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, sceneInfo.entity->direction & FLIP_X, 0,
2835
sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, frame->sheetID);
2836
break;
2837
2838
case FX_SCALE | FX_ROTATE:
2839
DrawSpriteRotozoom(pos.x, pos.y, frame->pivotX, frame->pivotY, frame->width, frame->height, frame->sprX, frame->sprY,
2840
sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, FLIP_NONE, rotation, sceneInfo.entity->inkEffect,
2841
sceneInfo.entity->alpha, frame->sheetID);
2842
break;
2843
2844
case FX_SCALE | FX_ROTATE | FX_FLIP:
2845
DrawSpriteRotozoom(pos.x, pos.y, frame->pivotX, frame->pivotY, frame->width, frame->height, frame->sprX, frame->sprY,
2846
sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, sceneInfo.entity->direction & FLIP_X, rotation,
2847
sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, frame->sheetID);
2848
break;
2849
2850
default: break;
2851
}
2852
}
2853
}
2854
void RSDK::DrawSpriteFlipped(int32 x, int32 y, int32 width, int32 height, int32 sprX, int32 sprY, int32 direction, int32 inkEffect, int32 alpha,
2855
int32 sheetID)
2856
{
2857
switch (inkEffect) {
2858
default: break;
2859
case INK_ALPHA:
2860
if (alpha > 0xFF)
2861
inkEffect = INK_NONE;
2862
else if (alpha <= 0)
2863
return;
2864
break;
2865
2866
case INK_ADD:
2867
case INK_SUB:
2868
if (alpha > 0xFF)
2869
alpha = 0xFF;
2870
else if (alpha <= 0)
2871
return;
2872
break;
2873
2874
case INK_TINT:
2875
if (!tintLookupTable)
2876
return;
2877
break;
2878
}
2879
int32 widthFlip = width;
2880
int32 heightFlip = height;
2881
2882
if (width + x > currentScreen->clipBound_X2)
2883
width = currentScreen->clipBound_X2 - x;
2884
2885
if (x < currentScreen->clipBound_X1) {
2886
int32 val = x - currentScreen->clipBound_X1;
2887
sprX -= val;
2888
width += val;
2889
widthFlip += 2 * val;
2890
x = currentScreen->clipBound_X1;
2891
}
2892
2893
if (height + y > currentScreen->clipBound_Y2)
2894
height = currentScreen->clipBound_Y2 - y;
2895
2896
if (y < currentScreen->clipBound_Y1) {
2897
int32 val = y - currentScreen->clipBound_Y1;
2898
sprY -= val;
2899
height += val;
2900
heightFlip += 2 * val;
2901
y = currentScreen->clipBound_Y1;
2902
}
2903
2904
if (width <= 0 || height <= 0)
2905
return;
2906
2907
GFXSurface *surface = &gfxSurface[sheetID];
2908
validDraw = true;
2909
int32 pitch = currentScreen->pitch - width;
2910
int32 gfxPitch = 0;
2911
uint8 *lineBuffer = NULL;
2912
uint8 *pixels = NULL;
2913
uint16 *frameBuffer = NULL;
2914
2915
switch (direction) {
2916
default: break;
2917
2918
case FLIP_NONE:
2919
gfxPitch = surface->width - width;
2920
lineBuffer = &gfxLineBuffer[y];
2921
pixels = &surface->pixels[sprX + surface->width * sprY];
2922
frameBuffer = &currentScreen->frameBuffer[x + currentScreen->pitch * y];
2923
switch (inkEffect) {
2924
case INK_NONE:
2925
while (height--) {
2926
uint16 *activePalette = fullPalette[*lineBuffer];
2927
lineBuffer++;
2928
int32 w = width;
2929
while (w--) {
2930
if (*pixels > 0)
2931
*frameBuffer = activePalette[*pixels];
2932
++pixels;
2933
++frameBuffer;
2934
}
2935
frameBuffer += pitch;
2936
pixels += gfxPitch;
2937
}
2938
break;
2939
2940
case INK_BLEND:
2941
while (height--) {
2942
uint16 *activePalette = fullPalette[*lineBuffer];
2943
lineBuffer++;
2944
int32 w = width;
2945
while (w--) {
2946
if (*pixels > 0)
2947
setPixelBlend(activePalette[*pixels], *frameBuffer);
2948
++pixels;
2949
++frameBuffer;
2950
}
2951
frameBuffer += pitch;
2952
pixels += gfxPitch;
2953
}
2954
break;
2955
2956
case INK_ALPHA: {
2957
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
2958
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
2959
2960
while (height--) {
2961
uint16 *activePalette = fullPalette[*lineBuffer];
2962
lineBuffer++;
2963
int32 w = width;
2964
while (w--) {
2965
if (*pixels > 0) {
2966
uint16 color = activePalette[*pixels];
2967
setPixelAlpha(color, *frameBuffer, alpha);
2968
}
2969
++pixels;
2970
++frameBuffer;
2971
}
2972
frameBuffer += pitch;
2973
pixels += gfxPitch;
2974
}
2975
break;
2976
}
2977
2978
case INK_ADD: {
2979
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
2980
while (height--) {
2981
uint16 *activePalette = fullPalette[*lineBuffer];
2982
lineBuffer++;
2983
int32 w = width;
2984
while (w--) {
2985
if (*pixels > 0) {
2986
uint16 color = activePalette[*pixels];
2987
setPixelAdditive(color, *frameBuffer);
2988
}
2989
++pixels;
2990
++frameBuffer;
2991
}
2992
frameBuffer += pitch;
2993
pixels += gfxPitch;
2994
}
2995
break;
2996
}
2997
2998
case INK_SUB: {
2999
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
3000
while (height--) {
3001
uint16 *activePalette = fullPalette[*lineBuffer];
3002
lineBuffer++;
3003
int32 w = width;
3004
while (w--) {
3005
if (*pixels > 0) {
3006
uint16 color = activePalette[*pixels];
3007
setPixelSubtractive(color, *frameBuffer);
3008
}
3009
++pixels;
3010
++frameBuffer;
3011
}
3012
frameBuffer += pitch;
3013
pixels += gfxPitch;
3014
}
3015
break;
3016
}
3017
3018
case INK_TINT:
3019
while (height--) {
3020
lineBuffer++;
3021
int32 w = width;
3022
while (w--) {
3023
if (*pixels > 0)
3024
*frameBuffer = tintLookupTable[*frameBuffer];
3025
++pixels;
3026
++frameBuffer;
3027
}
3028
frameBuffer += pitch;
3029
pixels += gfxPitch;
3030
}
3031
break;
3032
3033
case INK_MASKED:
3034
while (height--) {
3035
uint16 *activePalette = fullPalette[*lineBuffer];
3036
lineBuffer++;
3037
int32 w = width;
3038
while (w--) {
3039
if (*pixels > 0 && *frameBuffer == maskColor)
3040
*frameBuffer = activePalette[*pixels];
3041
++pixels;
3042
++frameBuffer;
3043
}
3044
frameBuffer += pitch;
3045
pixels += gfxPitch;
3046
}
3047
break;
3048
3049
case INK_UNMASKED:
3050
while (height--) {
3051
uint16 *activePalette = fullPalette[*lineBuffer];
3052
lineBuffer++;
3053
int32 w = width;
3054
while (w--) {
3055
if (*pixels > 0 && *frameBuffer != maskColor)
3056
*frameBuffer = activePalette[*pixels];
3057
++pixels;
3058
++frameBuffer;
3059
}
3060
frameBuffer += pitch;
3061
pixels += gfxPitch;
3062
}
3063
break;
3064
}
3065
break;
3066
3067
case FLIP_X:
3068
gfxPitch = width + surface->width;
3069
lineBuffer = &gfxLineBuffer[y];
3070
pixels = &surface->pixels[widthFlip - 1 + sprX + surface->width * sprY];
3071
frameBuffer = &currentScreen->frameBuffer[x + currentScreen->pitch * y];
3072
switch (inkEffect) {
3073
case INK_NONE:
3074
while (height--) {
3075
uint16 *activePalette = fullPalette[*lineBuffer];
3076
lineBuffer++;
3077
int32 w = width;
3078
while (w--) {
3079
if (*pixels > 0)
3080
*frameBuffer = activePalette[*pixels];
3081
--pixels;
3082
++frameBuffer;
3083
}
3084
frameBuffer += pitch;
3085
pixels += gfxPitch;
3086
}
3087
break;
3088
3089
case INK_BLEND:
3090
while (height--) {
3091
uint16 *activePalette = fullPalette[*lineBuffer];
3092
lineBuffer++;
3093
int32 w = width;
3094
while (w--) {
3095
if (*pixels > 0)
3096
setPixelBlend(activePalette[*pixels], *frameBuffer);
3097
--pixels;
3098
++frameBuffer;
3099
}
3100
frameBuffer += pitch;
3101
pixels += gfxPitch;
3102
}
3103
break;
3104
3105
case INK_ALPHA: {
3106
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
3107
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
3108
3109
while (height--) {
3110
uint16 *activePalette = fullPalette[*lineBuffer];
3111
lineBuffer++;
3112
int32 w = width;
3113
while (w--) {
3114
if (*pixels > 0) {
3115
uint16 color = activePalette[*pixels];
3116
setPixelAlpha(color, *frameBuffer, alpha);
3117
}
3118
--pixels;
3119
++frameBuffer;
3120
}
3121
frameBuffer += pitch;
3122
pixels += gfxPitch;
3123
}
3124
break;
3125
}
3126
3127
case INK_ADD: {
3128
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
3129
while (height--) {
3130
uint16 *activePalette = fullPalette[*lineBuffer];
3131
lineBuffer++;
3132
int32 w = width;
3133
while (w--) {
3134
if (*pixels > 0) {
3135
uint16 color = activePalette[*pixels];
3136
setPixelAdditive(color, *frameBuffer);
3137
}
3138
--pixels;
3139
++frameBuffer;
3140
}
3141
frameBuffer += pitch;
3142
pixels += gfxPitch;
3143
}
3144
break;
3145
}
3146
3147
case INK_SUB: {
3148
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
3149
while (height--) {
3150
uint16 *activePalette = fullPalette[*lineBuffer];
3151
lineBuffer++;
3152
int32 w = width;
3153
while (w--) {
3154
if (*pixels > 0) {
3155
uint16 color = activePalette[*pixels];
3156
setPixelSubtractive(color, *frameBuffer);
3157
}
3158
--pixels;
3159
++frameBuffer;
3160
}
3161
frameBuffer += pitch;
3162
pixels += gfxPitch;
3163
}
3164
break;
3165
}
3166
3167
case INK_TINT:
3168
while (height--) {
3169
lineBuffer++;
3170
int32 w = width;
3171
while (w--) {
3172
if (*pixels > 0)
3173
*frameBuffer = tintLookupTable[*frameBuffer];
3174
--pixels;
3175
++frameBuffer;
3176
}
3177
frameBuffer += pitch;
3178
pixels += gfxPitch;
3179
}
3180
break;
3181
3182
case INK_MASKED:
3183
while (height--) {
3184
uint16 *activePalette = fullPalette[*lineBuffer];
3185
lineBuffer++;
3186
int32 w = width;
3187
while (w--) {
3188
if (*pixels > 0 && *frameBuffer == maskColor)
3189
*frameBuffer = activePalette[*pixels];
3190
--pixels;
3191
++frameBuffer;
3192
}
3193
frameBuffer += pitch;
3194
pixels += gfxPitch;
3195
}
3196
break;
3197
3198
case INK_UNMASKED:
3199
while (height--) {
3200
uint16 *activePalette = fullPalette[*lineBuffer];
3201
lineBuffer++;
3202
int32 w = width;
3203
while (w--) {
3204
if (*pixels > 0 && *frameBuffer != maskColor)
3205
*frameBuffer = activePalette[*pixels];
3206
--pixels;
3207
++frameBuffer;
3208
}
3209
frameBuffer += pitch;
3210
pixels += gfxPitch;
3211
}
3212
break;
3213
}
3214
break;
3215
3216
case FLIP_Y:
3217
gfxPitch = width + surface->width;
3218
lineBuffer = &gfxLineBuffer[y];
3219
pixels = &surface->pixels[sprX + surface->width * (sprY + heightFlip - 1)];
3220
frameBuffer = &currentScreen->frameBuffer[x + currentScreen->pitch * y];
3221
switch (inkEffect) {
3222
case INK_NONE:
3223
while (height--) {
3224
uint16 *activePalette = fullPalette[*lineBuffer];
3225
lineBuffer++;
3226
int32 w = width;
3227
while (w--) {
3228
if (*pixels > 0)
3229
*frameBuffer = activePalette[*pixels];
3230
++pixels;
3231
++frameBuffer;
3232
}
3233
frameBuffer += pitch;
3234
pixels -= gfxPitch;
3235
}
3236
break;
3237
3238
case INK_BLEND:
3239
while (height--) {
3240
uint16 *activePalette = fullPalette[*lineBuffer];
3241
lineBuffer++;
3242
int32 w = width;
3243
while (w--) {
3244
if (*pixels > 0)
3245
setPixelBlend(activePalette[*pixels], *frameBuffer);
3246
++pixels;
3247
++frameBuffer;
3248
}
3249
frameBuffer += pitch;
3250
pixels -= gfxPitch;
3251
}
3252
break;
3253
3254
case INK_ALPHA: {
3255
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
3256
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
3257
3258
while (height--) {
3259
uint16 *activePalette = fullPalette[*lineBuffer];
3260
lineBuffer++;
3261
int32 w = width;
3262
while (w--) {
3263
if (*pixels > 0) {
3264
uint16 color = activePalette[*pixels];
3265
setPixelAlpha(color, *frameBuffer, alpha);
3266
}
3267
++pixels;
3268
++frameBuffer;
3269
}
3270
frameBuffer += pitch;
3271
pixels -= gfxPitch;
3272
}
3273
break;
3274
}
3275
3276
case INK_ADD: {
3277
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
3278
while (height--) {
3279
uint16 *activePalette = fullPalette[*lineBuffer];
3280
lineBuffer++;
3281
int32 w = width;
3282
while (w--) {
3283
if (*pixels > 0) {
3284
uint16 color = activePalette[*pixels];
3285
setPixelAdditive(color, *frameBuffer);
3286
}
3287
++pixels;
3288
++frameBuffer;
3289
}
3290
frameBuffer += pitch;
3291
pixels -= gfxPitch;
3292
}
3293
break;
3294
}
3295
3296
case INK_SUB: {
3297
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
3298
while (height--) {
3299
uint16 *activePalette = fullPalette[*lineBuffer];
3300
lineBuffer++;
3301
int32 w = width;
3302
while (w--) {
3303
if (*pixels > 0) {
3304
uint16 color = activePalette[*pixels];
3305
setPixelSubtractive(color, *frameBuffer);
3306
}
3307
++pixels;
3308
++frameBuffer;
3309
}
3310
frameBuffer += pitch;
3311
pixels -= gfxPitch;
3312
}
3313
break;
3314
}
3315
3316
case INK_TINT:
3317
while (height--) {
3318
lineBuffer++;
3319
int32 w = width;
3320
while (w--) {
3321
if (*pixels > 0)
3322
*frameBuffer = tintLookupTable[*frameBuffer];
3323
++pixels;
3324
++frameBuffer;
3325
}
3326
frameBuffer += pitch;
3327
pixels -= gfxPitch;
3328
}
3329
break;
3330
3331
case INK_MASKED:
3332
while (height--) {
3333
uint16 *activePalette = fullPalette[*lineBuffer];
3334
lineBuffer++;
3335
int32 w = width;
3336
while (w--) {
3337
if (*pixels > 0 && *frameBuffer == maskColor)
3338
*frameBuffer = activePalette[*pixels];
3339
++pixels;
3340
++frameBuffer;
3341
}
3342
frameBuffer += pitch;
3343
pixels -= gfxPitch;
3344
}
3345
break;
3346
3347
case INK_UNMASKED:
3348
while (height--) {
3349
uint16 *activePalette = fullPalette[*lineBuffer];
3350
lineBuffer++;
3351
int32 w = width;
3352
while (w--) {
3353
if (*pixels > 0 && *frameBuffer != maskColor)
3354
*frameBuffer = activePalette[*pixels];
3355
++pixels;
3356
++frameBuffer;
3357
}
3358
frameBuffer += pitch;
3359
pixels -= gfxPitch;
3360
}
3361
break;
3362
}
3363
break;
3364
3365
case FLIP_XY:
3366
gfxPitch = surface->width - width;
3367
lineBuffer = &gfxLineBuffer[y];
3368
pixels = &surface->pixels[widthFlip - 1 + sprX + surface->width * (sprY + heightFlip - 1)];
3369
frameBuffer = &currentScreen->frameBuffer[x + currentScreen->pitch * y];
3370
switch (inkEffect) {
3371
case INK_NONE:
3372
while (height--) {
3373
uint16 *activePalette = fullPalette[*lineBuffer];
3374
lineBuffer++;
3375
int32 w = width;
3376
while (w--) {
3377
if (*pixels > 0)
3378
*frameBuffer = activePalette[*pixels];
3379
--pixels;
3380
++frameBuffer;
3381
}
3382
frameBuffer += pitch;
3383
pixels -= gfxPitch;
3384
}
3385
break;
3386
3387
case INK_BLEND:
3388
while (height--) {
3389
uint16 *activePalette = fullPalette[*lineBuffer];
3390
lineBuffer++;
3391
int32 w = width;
3392
while (w--) {
3393
if (*pixels > 0)
3394
setPixelBlend(activePalette[*pixels], *frameBuffer);
3395
--pixels;
3396
++frameBuffer;
3397
}
3398
frameBuffer += pitch;
3399
pixels -= gfxPitch;
3400
}
3401
break;
3402
3403
case INK_ALPHA: {
3404
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
3405
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
3406
3407
while (height--) {
3408
uint16 *activePalette = fullPalette[*lineBuffer];
3409
lineBuffer++;
3410
int32 w = width;
3411
while (w--) {
3412
if (*pixels > 0) {
3413
uint16 color = activePalette[*pixels];
3414
setPixelAlpha(color, *frameBuffer, alpha);
3415
}
3416
--pixels;
3417
++frameBuffer;
3418
}
3419
frameBuffer += pitch;
3420
pixels -= gfxPitch;
3421
}
3422
break;
3423
}
3424
3425
case INK_ADD: {
3426
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
3427
while (height--) {
3428
uint16 *activePalette = fullPalette[*lineBuffer];
3429
lineBuffer++;
3430
int32 w = width;
3431
while (w--) {
3432
if (*pixels > 0) {
3433
uint16 color = activePalette[*pixels];
3434
setPixelAdditive(color, *frameBuffer);
3435
}
3436
--pixels;
3437
++frameBuffer;
3438
}
3439
frameBuffer += pitch;
3440
pixels -= gfxPitch;
3441
}
3442
break;
3443
}
3444
3445
case INK_SUB: {
3446
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
3447
while (height--) {
3448
uint16 *activePalette = fullPalette[*lineBuffer];
3449
lineBuffer++;
3450
int32 w = width;
3451
while (w--) {
3452
if (*pixels > 0) {
3453
uint16 color = activePalette[*pixels];
3454
setPixelSubtractive(color, *frameBuffer);
3455
}
3456
--pixels;
3457
++frameBuffer;
3458
}
3459
frameBuffer += pitch;
3460
pixels -= gfxPitch;
3461
}
3462
break;
3463
}
3464
3465
case INK_TINT:
3466
while (height--) {
3467
lineBuffer++;
3468
int32 w = width;
3469
while (w--) {
3470
if (*pixels > 0)
3471
*frameBuffer = tintLookupTable[*frameBuffer];
3472
--pixels;
3473
++frameBuffer;
3474
}
3475
frameBuffer += pitch;
3476
pixels -= gfxPitch;
3477
}
3478
break;
3479
3480
case INK_MASKED:
3481
while (height--) {
3482
uint16 *activePalette = fullPalette[*lineBuffer];
3483
lineBuffer++;
3484
int32 w = width;
3485
while (w--) {
3486
if (*pixels > 0 && *frameBuffer == maskColor)
3487
*frameBuffer = activePalette[*pixels];
3488
--pixels;
3489
++frameBuffer;
3490
}
3491
frameBuffer += pitch;
3492
pixels -= gfxPitch;
3493
}
3494
break;
3495
3496
case INK_UNMASKED:
3497
while (height--) {
3498
uint16 *activePalette = fullPalette[*lineBuffer];
3499
lineBuffer++;
3500
int32 w = width;
3501
while (w--) {
3502
if (*pixels > 0 && *frameBuffer != maskColor)
3503
*frameBuffer = activePalette[*pixels];
3504
--pixels;
3505
++frameBuffer;
3506
}
3507
frameBuffer += pitch;
3508
pixels -= gfxPitch;
3509
}
3510
break;
3511
}
3512
break;
3513
}
3514
}
3515
void RSDK::DrawSpriteRotozoom(int32 x, int32 y, int32 pivotX, int32 pivotY, int32 width, int32 height, int32 sprX, int32 sprY, int32 scaleX,
3516
int32 scaleY, int32 direction, int16 rotation, int32 inkEffect, int32 alpha, int32 sheetID)
3517
{
3518
switch (inkEffect) {
3519
default: break;
3520
case INK_ALPHA:
3521
if (alpha > 0xFF)
3522
inkEffect = INK_NONE;
3523
else if (alpha <= 0)
3524
return;
3525
break;
3526
3527
case INK_ADD:
3528
case INK_SUB:
3529
if (alpha > 0xFF)
3530
alpha = 0xFF;
3531
else if (alpha <= 0)
3532
return;
3533
break;
3534
3535
case INK_TINT:
3536
if (!tintLookupTable)
3537
return;
3538
break;
3539
}
3540
3541
int32 angle = 0x200 - (rotation & 0x1FF);
3542
if (!(rotation & 0x1FF))
3543
angle = rotation & 0x1FF;
3544
3545
int32 sine = sin512LookupTable[angle];
3546
int32 cosine = cos512LookupTable[angle];
3547
int32 fullScaleXS = scaleX * sine >> 9;
3548
int32 fullScaleXC = scaleX * cosine >> 9;
3549
int32 fullScaleYS = scaleY * sine >> 9;
3550
int32 fullScaleYC = scaleY * cosine >> 9;
3551
3552
int32 posX[4];
3553
int32 posY[4];
3554
int32 sprXPos = TO_FIXED(sprX - pivotX);
3555
int32 sprYPos = TO_FIXED(sprY - pivotY);
3556
3557
int32 xMax = 0;
3558
int32 scaledX1 = 0;
3559
int32 scaledX2 = 0;
3560
int32 scaledY1 = 0;
3561
int32 scaledY2 = 0;
3562
switch (direction) {
3563
default:
3564
case FLIP_NONE: {
3565
scaledX1 = fullScaleXS * (pivotX - 2);
3566
scaledX2 = fullScaleXC * (pivotX - 2);
3567
scaledY1 = fullScaleYS * (pivotY - 2);
3568
scaledY2 = fullScaleYC * (pivotY - 2);
3569
xMax = pivotX + 2 + width;
3570
posX[0] = x + ((scaledX2 + scaledY1) >> 9);
3571
posY[0] = y + ((fullScaleYC * (pivotY - 2) - scaledX1) >> 9);
3572
break;
3573
}
3574
3575
case FLIP_X: {
3576
scaledX1 = fullScaleXS * (2 - pivotX);
3577
scaledX2 = fullScaleXC * (2 - pivotX);
3578
scaledY1 = fullScaleYS * (pivotY - 2);
3579
scaledY2 = fullScaleYC * (pivotY - 2);
3580
xMax = -2 - pivotX - width;
3581
posX[0] = x + ((scaledX2 + scaledY1) >> 9);
3582
posY[0] = y + ((fullScaleYC * (pivotY - 2) - scaledX1) >> 9);
3583
break;
3584
}
3585
3586
case FLIP_Y:
3587
case FLIP_XY: break;
3588
}
3589
3590
int32 scaledXMaxS = fullScaleXS * xMax;
3591
int32 scaledXMaxC = fullScaleXC * xMax;
3592
int32 scaledYMaxC = fullScaleYC * (pivotY + 2 + height);
3593
int32 scaledYMaxS = fullScaleYS * (pivotY + 2 + height);
3594
posX[1] = x + ((scaledXMaxC + scaledY1) >> 9);
3595
posY[1] = y + ((scaledY2 - scaledXMaxS) >> 9);
3596
posX[2] = x + ((scaledYMaxS + scaledX2) >> 9);
3597
posY[2] = y + ((scaledYMaxC - scaledX1) >> 9);
3598
posX[3] = x + ((scaledXMaxC + scaledYMaxS) >> 9);
3599
posY[3] = y + ((scaledYMaxC - scaledXMaxS) >> 9);
3600
3601
int32 left = currentScreen->pitch;
3602
for (int32 i = 0; i < 4; ++i) {
3603
if (posX[i] < left)
3604
left = posX[i];
3605
}
3606
if (left < currentScreen->clipBound_X1)
3607
left = currentScreen->clipBound_X1;
3608
3609
int32 right = 0;
3610
for (int32 i = 0; i < 4; ++i) {
3611
if (posX[i] > right)
3612
right = posX[i];
3613
}
3614
if (right > currentScreen->clipBound_X2)
3615
right = currentScreen->clipBound_X2;
3616
3617
int32 top = currentScreen->size.y;
3618
for (int32 i = 0; i < 4; ++i) {
3619
if (posY[i] < top)
3620
top = posY[i];
3621
}
3622
if (top < currentScreen->clipBound_Y1)
3623
top = currentScreen->clipBound_Y1;
3624
3625
int32 bottom = 0;
3626
for (int32 i = 0; i < 4; ++i) {
3627
if (posY[i] > bottom)
3628
bottom = posY[i];
3629
}
3630
if (bottom > currentScreen->clipBound_Y2)
3631
bottom = currentScreen->clipBound_Y2;
3632
3633
int32 xSize = right - left;
3634
int32 ySize = bottom - top;
3635
if (xSize >= 1 && ySize >= 1) {
3636
GFXSurface *surface = &gfxSurface[sheetID];
3637
3638
int32 fullX = TO_FIXED(sprX + width);
3639
int32 fullY = TO_FIXED(sprY + height);
3640
validDraw = true;
3641
int32 fullScaleX = (int32)((512.0 / (float)scaleX) * 512.0);
3642
int32 fullScaleY = (int32)((512.0 / (float)scaleY) * 512.0);
3643
int32 deltaXLen = fullScaleX * sine >> 2;
3644
int32 deltaX = fullScaleX * cosine >> 2;
3645
int32 pitch = currentScreen->pitch - xSize;
3646
int32 deltaYLen = fullScaleY * cosine >> 2;
3647
int32 deltaY = fullScaleY * sine >> 2;
3648
int32 lineSize = surface->lineSize;
3649
uint8 *lineBuffer = &gfxLineBuffer[top];
3650
int32 xLen = left - x;
3651
int32 yLen = top - y;
3652
uint8 *pixels = surface->pixels;
3653
uint16 *frameBuffer = &currentScreen->frameBuffer[left + (top * currentScreen->pitch)];
3654
int32 fullSprX = TO_FIXED(sprX) - 1;
3655
int32 fullSprY = TO_FIXED(sprY) - 1;
3656
3657
int32 drawX = 0, drawY = 0;
3658
if (direction == FLIP_X) {
3659
drawX = sprXPos + deltaXLen * yLen - deltaX * xLen - (fullScaleX >> 1);
3660
drawY = sprYPos + deltaYLen * yLen + deltaY * xLen;
3661
deltaX = -deltaX;
3662
deltaXLen = -deltaXLen;
3663
}
3664
else if (!direction) {
3665
drawX = sprXPos + deltaX * xLen - deltaXLen * yLen;
3666
drawY = sprYPos + deltaYLen * yLen + deltaY * xLen;
3667
}
3668
3669
switch (inkEffect) {
3670
case INK_NONE:
3671
for (int32 y = 0; y < ySize; ++y) {
3672
uint16 *activePalette = fullPalette[*lineBuffer++];
3673
int32 drawXPos = drawX;
3674
int32 drawYPos = drawY;
3675
for (int32 x = 0; x < xSize; ++x) {
3676
if (drawXPos >= fullSprX && drawXPos < fullX && drawYPos >= fullSprY && drawYPos < fullY) {
3677
uint8 index = pixels[(FROM_FIXED(drawYPos) << lineSize) + FROM_FIXED(drawXPos)];
3678
if (index)
3679
*frameBuffer = activePalette[index];
3680
}
3681
3682
++frameBuffer;
3683
drawXPos += deltaX;
3684
drawYPos += deltaY;
3685
}
3686
3687
drawX -= deltaXLen;
3688
drawY += deltaYLen;
3689
frameBuffer += pitch;
3690
}
3691
break;
3692
3693
case INK_BLEND:
3694
for (int32 y = 0; y < ySize; ++y) {
3695
uint16 *activePalette = fullPalette[*lineBuffer++];
3696
int32 drawXPos = drawX;
3697
int32 drawYPos = drawY;
3698
for (int32 x = 0; x < xSize; ++x) {
3699
if (drawXPos >= fullSprX && drawXPos < fullX && drawYPos >= fullSprY && drawYPos < fullY) {
3700
uint8 index = pixels[(FROM_FIXED(drawYPos) << lineSize) + FROM_FIXED(drawXPos)];
3701
if (index)
3702
setPixelBlend(activePalette[index], *frameBuffer);
3703
}
3704
3705
++frameBuffer;
3706
drawXPos += deltaX;
3707
drawYPos += deltaY;
3708
}
3709
3710
drawX -= deltaXLen;
3711
drawY += deltaYLen;
3712
frameBuffer += pitch;
3713
}
3714
break;
3715
3716
case INK_ALPHA: {
3717
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
3718
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
3719
3720
for (int32 y = 0; y < ySize; ++y) {
3721
uint16 *activePalette = fullPalette[*lineBuffer++];
3722
int32 drawXPos = drawX;
3723
int32 drawYPos = drawY;
3724
for (int32 x = 0; x < xSize; ++x) {
3725
if (drawXPos >= fullSprX && drawXPos < fullX && drawYPos >= fullSprY && drawYPos < fullY) {
3726
uint8 index = pixels[(FROM_FIXED(drawYPos) << lineSize) + FROM_FIXED(drawXPos)];
3727
if (index) {
3728
setPixelAlpha(activePalette[index], *frameBuffer, alpha);
3729
}
3730
}
3731
3732
++frameBuffer;
3733
drawXPos += deltaX;
3734
drawYPos += deltaY;
3735
}
3736
3737
drawX -= deltaXLen;
3738
drawY += deltaYLen;
3739
frameBuffer += pitch;
3740
}
3741
break;
3742
}
3743
3744
case INK_ADD: {
3745
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
3746
for (int32 y = 0; y < ySize; ++y) {
3747
uint16 *activePalette = fullPalette[*lineBuffer++];
3748
int32 drawXPos = drawX;
3749
int32 drawYPos = drawY;
3750
for (int32 x = 0; x < xSize; ++x) {
3751
if (drawXPos >= fullSprX && drawXPos < fullX && drawYPos >= fullSprY && drawYPos < fullY) {
3752
uint8 index = pixels[(FROM_FIXED(drawYPos) << lineSize) + FROM_FIXED(drawXPos)];
3753
if (index) {
3754
setPixelAdditive(activePalette[index], *frameBuffer);
3755
}
3756
}
3757
3758
++frameBuffer;
3759
drawXPos += deltaX;
3760
drawYPos += deltaY;
3761
}
3762
3763
drawX -= deltaXLen;
3764
drawY += deltaYLen;
3765
frameBuffer += pitch;
3766
}
3767
break;
3768
}
3769
3770
case INK_SUB: {
3771
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
3772
for (int32 y = 0; y < ySize; ++y) {
3773
uint16 *activePalette = fullPalette[*lineBuffer++];
3774
int32 drawXPos = drawX;
3775
int32 drawYPos = drawY;
3776
for (int32 x = 0; x < xSize; ++x) {
3777
if (drawXPos >= fullSprX && drawXPos < fullX && drawYPos >= fullSprY && drawYPos < fullY) {
3778
uint8 index = pixels[(FROM_FIXED(drawYPos) << lineSize) + FROM_FIXED(drawXPos)];
3779
if (index) {
3780
setPixelSubtractive(activePalette[index], *frameBuffer);
3781
}
3782
}
3783
3784
++frameBuffer;
3785
drawXPos += deltaX;
3786
drawYPos += deltaY;
3787
}
3788
3789
drawX -= deltaXLen;
3790
drawY += deltaYLen;
3791
frameBuffer += pitch;
3792
}
3793
break;
3794
}
3795
3796
case INK_TINT:
3797
for (int32 y = 0; y < ySize; ++y) {
3798
int32 drawXPos = drawX;
3799
int32 drawYPos = drawY;
3800
for (int32 x = 0; x < xSize; ++x) {
3801
if (drawXPos >= fullSprX && drawXPos < fullX && drawYPos >= fullSprY && drawYPos < fullY) {
3802
uint8 index = pixels[(FROM_FIXED(drawYPos) << lineSize) + FROM_FIXED(drawXPos)];
3803
if (index)
3804
*frameBuffer = tintLookupTable[*frameBuffer];
3805
}
3806
3807
++frameBuffer;
3808
drawXPos += deltaX;
3809
drawYPos += deltaY;
3810
}
3811
3812
drawX -= deltaXLen;
3813
drawY += deltaYLen;
3814
frameBuffer += pitch;
3815
}
3816
break;
3817
3818
case INK_MASKED:
3819
for (int32 y = 0; y < ySize; ++y) {
3820
uint16 *activePalette = fullPalette[*lineBuffer++];
3821
int32 drawXPos = drawX;
3822
int32 drawYPos = drawY;
3823
for (int32 x = 0; x < xSize; ++x) {
3824
if (drawXPos >= fullSprX && drawXPos < fullX && drawYPos >= fullSprY && drawYPos < fullY) {
3825
uint8 index = pixels[(FROM_FIXED(drawYPos) << lineSize) + FROM_FIXED(drawXPos)];
3826
if (index && *frameBuffer == maskColor)
3827
*frameBuffer = activePalette[index];
3828
}
3829
3830
++frameBuffer;
3831
drawXPos += deltaX;
3832
drawYPos += deltaY;
3833
}
3834
3835
drawX -= deltaXLen;
3836
drawY += deltaYLen;
3837
frameBuffer += pitch;
3838
}
3839
break;
3840
3841
case INK_UNMASKED:
3842
for (int32 y = 0; y < ySize; ++y) {
3843
uint16 *activePalette = fullPalette[*lineBuffer++];
3844
int32 drawXPos = drawX;
3845
int32 drawYPos = drawY;
3846
for (int32 x = 0; x < xSize; ++x) {
3847
if (drawXPos >= fullSprX && drawXPos < fullX && drawYPos >= fullSprY && drawYPos < fullY) {
3848
uint8 index = pixels[(FROM_FIXED(drawYPos) << lineSize) + FROM_FIXED(drawXPos)];
3849
if (index && *frameBuffer != maskColor)
3850
*frameBuffer = activePalette[index];
3851
}
3852
3853
++frameBuffer;
3854
drawXPos += deltaX;
3855
drawYPos += deltaY;
3856
}
3857
3858
drawX -= deltaXLen;
3859
drawY += deltaYLen;
3860
frameBuffer += pitch;
3861
}
3862
break;
3863
}
3864
}
3865
}
3866
3867
void RSDK::DrawDeformedSprite(uint16 sheetID, int32 inkEffect, int32 alpha)
3868
{
3869
switch (inkEffect) {
3870
default: break;
3871
case INK_ALPHA:
3872
if (alpha > 0xFF)
3873
inkEffect = INK_NONE;
3874
else if (alpha <= 0)
3875
return;
3876
break;
3877
3878
case INK_ADD:
3879
case INK_SUB:
3880
if (alpha > 0xFF)
3881
alpha = 0xFF;
3882
else if (alpha <= 0)
3883
return;
3884
break;
3885
3886
case INK_TINT:
3887
if (!tintLookupTable)
3888
return;
3889
break;
3890
}
3891
3892
validDraw = true;
3893
GFXSurface *surface = &gfxSurface[sheetID];
3894
uint8 *pixels = surface->pixels;
3895
int32 clipY1 = currentScreen->clipBound_Y1;
3896
ScanlineInfo *scanline = &scanlines[clipY1];
3897
uint16 *frameBuffer = &currentScreen->frameBuffer[clipY1 * currentScreen->pitch];
3898
uint8 *lineBuffer = &gfxLineBuffer[clipY1];
3899
int32 width = surface->width - 1;
3900
int32 height = surface->height - 1;
3901
int32 lineSize = surface->lineSize;
3902
3903
switch (inkEffect) {
3904
case INK_NONE:
3905
for (; clipY1 < currentScreen->clipBound_Y2; ++clipY1) {
3906
uint16 *activePalette = fullPalette[*lineBuffer++];
3907
int32 lx = scanline->position.x;
3908
int32 ly = scanline->position.y;
3909
int32 dx = scanline->deform.x;
3910
int32 dy = scanline->deform.y;
3911
for (int32 i = 0; i < currentScreen->pitch; ++i) {
3912
uint8 palIndex = pixels[((FROM_FIXED(ly) & height) << lineSize) + (FROM_FIXED(lx) & width)];
3913
if (palIndex)
3914
*frameBuffer = activePalette[palIndex];
3915
3916
lx += dx;
3917
ly += dy;
3918
++frameBuffer;
3919
}
3920
++scanline;
3921
}
3922
break;
3923
3924
case INK_BLEND:
3925
for (; clipY1 < currentScreen->clipBound_Y2; ++clipY1) {
3926
uint16 *activePalette = fullPalette[*lineBuffer++];
3927
int32 lx = scanline->position.x;
3928
int32 ly = scanline->position.y;
3929
int32 dx = scanline->deform.x;
3930
int32 dy = scanline->deform.y;
3931
for (int32 i = 0; i < currentScreen->pitch; ++i) {
3932
uint8 palIndex = pixels[((FROM_FIXED(ly) & height) << lineSize) + (FROM_FIXED(lx) & width)];
3933
if (palIndex)
3934
setPixelBlend(activePalette[palIndex], *frameBuffer);
3935
3936
lx += dx;
3937
ly += dy;
3938
++frameBuffer;
3939
}
3940
++scanline;
3941
}
3942
break;
3943
3944
case INK_ALPHA: {
3945
uint16 *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
3946
uint16 *pixelBlend = &blendLookupTable[0x20 * alpha];
3947
3948
for (; clipY1 < currentScreen->clipBound_Y2; ++clipY1) {
3949
uint16 *activePalette = fullPalette[*lineBuffer++];
3950
int32 lx = scanline->position.x;
3951
int32 ly = scanline->position.y;
3952
int32 dx = scanline->deform.x;
3953
int32 dy = scanline->deform.y;
3954
for (int32 i = 0; i < currentScreen->pitch; ++i) {
3955
uint8 palIndex = pixels[((FROM_FIXED(ly) & height) << lineSize) + (FROM_FIXED(lx) & width)];
3956
if (palIndex) {
3957
setPixelAlpha(activePalette[palIndex], *frameBuffer, alpha);
3958
}
3959
3960
lx += dx;
3961
ly += dy;
3962
++frameBuffer;
3963
}
3964
++scanline;
3965
}
3966
break;
3967
}
3968
3969
case INK_ADD: {
3970
uint16 *blendTablePtr = &blendLookupTable[0x20 * alpha];
3971
3972
for (; clipY1 < currentScreen->clipBound_Y2; ++clipY1) {
3973
uint16 *activePalette = fullPalette[*lineBuffer++];
3974
int32 lx = scanline->position.x;
3975
int32 ly = scanline->position.y;
3976
int32 dx = scanline->deform.x;
3977
int32 dy = scanline->deform.y;
3978
for (int32 i = 0; i < currentScreen->pitch; ++i) {
3979
uint8 palIndex = pixels[((FROM_FIXED(ly) & height) << lineSize) + (FROM_FIXED(lx) & width)];
3980
if (palIndex) {
3981
setPixelAdditive(activePalette[palIndex], *frameBuffer);
3982
}
3983
3984
lx += dx;
3985
ly += dy;
3986
++frameBuffer;
3987
}
3988
++scanline;
3989
}
3990
break;
3991
}
3992
3993
case INK_SUB: {
3994
uint16 *subBlendTable = &subtractLookupTable[0x20 * alpha];
3995
3996
for (; clipY1 < currentScreen->clipBound_Y2; ++clipY1) {
3997
uint16 *activePalette = fullPalette[*lineBuffer++];
3998
int32 lx = scanline->position.x;
3999
int32 ly = scanline->position.y;
4000
int32 dx = scanline->deform.x;
4001
int32 dy = scanline->deform.y;
4002
for (int32 i = 0; i < currentScreen->pitch; ++i) {
4003
uint8 palIndex = pixels[((FROM_FIXED(ly) & height) << lineSize) + (FROM_FIXED(lx) & width)];
4004
if (palIndex) {
4005
setPixelSubtractive(activePalette[palIndex], *frameBuffer);
4006
}
4007
lx += dx;
4008
ly += dy;
4009
++frameBuffer;
4010
}
4011
++scanline;
4012
}
4013
break;
4014
}
4015
4016
case INK_TINT:
4017
for (; clipY1 < currentScreen->clipBound_Y2; ++clipY1) {
4018
int32 lx = scanline->position.x;
4019
int32 ly = scanline->position.y;
4020
int32 dx = scanline->deform.x;
4021
int32 dy = scanline->deform.y;
4022
for (int32 i = 0; i < currentScreen->pitch; ++i) {
4023
uint8 palIndex = pixels[((FROM_FIXED(ly) & height) << lineSize) + (FROM_FIXED(lx) & width)];
4024
if (palIndex)
4025
*frameBuffer = tintLookupTable[*frameBuffer];
4026
lx += dx;
4027
ly += dy;
4028
++frameBuffer;
4029
}
4030
++scanline;
4031
}
4032
break;
4033
4034
case INK_MASKED:
4035
for (; clipY1 < currentScreen->clipBound_Y2; ++clipY1) {
4036
uint16 *activePalette = fullPalette[*lineBuffer++];
4037
int32 lx = scanline->position.x;
4038
int32 ly = scanline->position.y;
4039
int32 dx = scanline->deform.x;
4040
int32 dy = scanline->deform.y;
4041
for (int32 i = 0; i < currentScreen->pitch; ++i) {
4042
uint8 palIndex = pixels[((FROM_FIXED(ly) & height) << lineSize) + (FROM_FIXED(lx) & width)];
4043
if (palIndex && *frameBuffer == maskColor)
4044
*frameBuffer = activePalette[palIndex];
4045
lx += dx;
4046
ly += dy;
4047
++frameBuffer;
4048
}
4049
++scanline;
4050
}
4051
break;
4052
4053
case INK_UNMASKED:
4054
for (; clipY1 < currentScreen->clipBound_Y2; ++clipY1) {
4055
uint16 *activePalette = fullPalette[*lineBuffer++];
4056
int32 lx = scanline->position.x;
4057
int32 ly = scanline->position.y;
4058
int32 dx = scanline->deform.x;
4059
int32 dy = scanline->deform.y;
4060
for (int32 i = 0; i < currentScreen->pitch; ++i) {
4061
uint8 palIndex = pixels[((FROM_FIXED(ly) & height) << lineSize) + (FROM_FIXED(lx) & width)];
4062
if (palIndex && *frameBuffer != maskColor)
4063
*frameBuffer = activePalette[palIndex];
4064
lx += dx;
4065
ly += dy;
4066
++frameBuffer;
4067
}
4068
++scanline;
4069
}
4070
break;
4071
}
4072
}
4073
4074
void RSDK::DrawTile(uint16 *tiles, int32 countX, int32 countY, Vector2 *position, Vector2 *offset, bool32 screenRelative)
4075
{
4076
if (tiles) {
4077
if (!position)
4078
position = &sceneInfo.entity->position;
4079
4080
int32 x = FROM_FIXED(position->x);
4081
int32 y = FROM_FIXED(position->y);
4082
if (!screenRelative) {
4083
x -= currentScreen->position.x;
4084
y -= currentScreen->position.y;
4085
}
4086
4087
int32 pivotX = 0;
4088
int32 pivotY = 0;
4089
switch (sceneInfo.entity->drawFX) {
4090
case FX_NONE:
4091
case FX_FLIP:
4092
if (offset) {
4093
pivotX = x - (offset->x >> 17);
4094
pivotY = y - (offset->y >> 17);
4095
}
4096
else {
4097
pivotX = x - (countX * (TILE_SIZE >> 1));
4098
pivotY = y - (countY * (TILE_SIZE >> 1));
4099
}
4100
4101
for (int32 ty = 0; ty < countY; ++ty) {
4102
for (int32 tx = 0; tx < countX; ++tx) {
4103
uint16 tile = tiles[tx + (ty * countX)];
4104
if (tile < 0xFFFF) {
4105
DrawSpriteFlipped((tx * TILE_SIZE) + pivotX, (ty * TILE_SIZE) + pivotY, TILE_SIZE, TILE_SIZE, 0,
4106
TILE_SIZE * (tile & 0xFFF), FLIP_NONE, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4107
}
4108
}
4109
}
4110
break;
4111
4112
case FX_ROTATE: // Flip
4113
case FX_ROTATE | FX_FLIP:
4114
if (offset) {
4115
pivotX = -(offset->x >> 17);
4116
pivotY = -(offset->y >> 17);
4117
}
4118
else {
4119
pivotX = -(countX * (TILE_SIZE >> 1));
4120
pivotY = -(countY * (TILE_SIZE >> 1));
4121
}
4122
4123
for (int32 ty = 0; ty < countY; ++ty) {
4124
for (int32 tx = 0; tx < countX; ++tx) {
4125
uint16 tile = tiles[tx + (ty * countX)];
4126
if (tile < 0xFFFF) {
4127
switch ((tile >> 10) & 3) {
4128
case FLIP_NONE:
4129
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4130
TILE_SIZE * (tile & 0x3FF), 0x200, 0x200, FLIP_NONE, sceneInfo.entity->rotation,
4131
sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4132
break;
4133
4134
case FLIP_X:
4135
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4136
TILE_SIZE * (tile & 0x3FF), 0x200, 0x200, FLIP_X, sceneInfo.entity->rotation,
4137
sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4138
break;
4139
4140
case FLIP_Y:
4141
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4142
TILE_SIZE * (tile & 0x3FF), 0x200, 0x200, FLIP_X, sceneInfo.entity->rotation + 0x100,
4143
sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4144
break;
4145
4146
case FLIP_XY:
4147
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4148
TILE_SIZE * (tile & 0x3FF), 0x200, 0x200, FLIP_NONE, sceneInfo.entity->rotation + 0x100,
4149
sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4150
break;
4151
}
4152
}
4153
}
4154
}
4155
break;
4156
4157
case FX_SCALE: // Scale
4158
case FX_SCALE | FX_FLIP:
4159
if (offset) {
4160
pivotX = -(offset->x >> 17);
4161
pivotY = -(offset->y >> 17);
4162
}
4163
else {
4164
pivotX = -(countX * (TILE_SIZE >> 1));
4165
pivotY = -(countY * (TILE_SIZE >> 1));
4166
}
4167
4168
for (int32 ty = 0; ty < countY; ++ty) {
4169
for (int32 tx = 0; tx < countX; ++tx) {
4170
uint16 tile = tiles[tx + (ty * countX)];
4171
if (tile < 0xFFFF) {
4172
switch ((tile >> 10) & 3) {
4173
case FLIP_NONE:
4174
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4175
TILE_SIZE * (tile & 0x3FF), sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, FLIP_NONE,
4176
0x000, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4177
break;
4178
4179
case FLIP_X:
4180
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4181
TILE_SIZE * (tile & 0x3FF), sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, FLIP_X,
4182
0x000, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4183
break;
4184
4185
case FLIP_Y:
4186
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4187
TILE_SIZE * (tile & 0x3FF), sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, FLIP_X,
4188
0x100, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4189
break;
4190
4191
case FLIP_XY:
4192
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4193
TILE_SIZE * (tile & 0x3FF), sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, FLIP_NONE,
4194
0x100, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4195
break;
4196
}
4197
}
4198
}
4199
}
4200
break;
4201
4202
case FX_SCALE | FX_ROTATE: // Flip + Scale + Rotation
4203
case FX_SCALE | FX_ROTATE | FX_FLIP:
4204
if (offset) {
4205
pivotX = -(offset->x >> 17);
4206
pivotY = -(offset->y >> 17);
4207
}
4208
else {
4209
pivotX = -(countX * (TILE_SIZE >> 1));
4210
pivotY = -(countY * (TILE_SIZE >> 1));
4211
}
4212
4213
for (int32 ty = 0; ty < countY; ++ty) {
4214
for (int32 tx = 0; tx < countX; ++tx) {
4215
uint16 tile = tiles[tx + (ty * countX)];
4216
if (tile < 0xFFFF) {
4217
switch ((tile >> 10) & 3) {
4218
case FLIP_NONE:
4219
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4220
TILE_SIZE * (tile & 0x3FF), sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, FLIP_NONE,
4221
sceneInfo.entity->rotation, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4222
break;
4223
4224
case FLIP_X:
4225
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4226
TILE_SIZE * (tile & 0x3FF), sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, FLIP_X,
4227
sceneInfo.entity->rotation, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4228
break;
4229
4230
case FLIP_Y:
4231
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4232
TILE_SIZE * (tile & 0x3FF), sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, FLIP_X,
4233
sceneInfo.entity->rotation + 0x100, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4234
break;
4235
4236
case FLIP_XY:
4237
DrawSpriteRotozoom(x + (tx * TILE_SIZE), y + (ty * TILE_SIZE), pivotX, pivotY, TILE_SIZE, TILE_SIZE, 0,
4238
TILE_SIZE * (tile & 0x3FF), sceneInfo.entity->scale.x, sceneInfo.entity->scale.y, FLIP_NONE,
4239
sceneInfo.entity->rotation + 0x100, sceneInfo.entity->inkEffect, sceneInfo.entity->alpha, 0);
4240
break;
4241
}
4242
}
4243
}
4244
}
4245
break;
4246
}
4247
}
4248
}
4249
void RSDK::DrawAniTile(uint16 sheetID, uint16 tileIndex, uint16 srcX, uint16 srcY, uint16 width, uint16 height)
4250
{
4251
4252
if (sheetID < SURFACE_COUNT && tileIndex < TILE_COUNT) {
4253
GFXSurface *surface = &gfxSurface[sheetID];
4254
4255
// FLIP_NONE
4256
uint8 *tilePixels = &tilesetPixels[tileIndex << 8];
4257
int32 cnt = 0;
4258
for (int32 fy = 0; fy < height; fy += TILE_SIZE) {
4259
uint8 *pixels = &surface->pixels[((fy + srcY) << surface->lineSize) + srcX];
4260
cnt += ((width - 1) / TILE_SIZE) + 1;
4261
for (int32 fx = 0; fx < width; fx += TILE_SIZE) {
4262
uint8 *pixelsPtr = &pixels[fx];
4263
for (int32 ty = 0; ty < TILE_SIZE; ++ty) {
4264
for (int32 tx = 0; tx < TILE_SIZE; ++tx) *tilePixels++ = *pixelsPtr++;
4265
4266
pixelsPtr += surface->width - TILE_SIZE;
4267
}
4268
}
4269
}
4270
4271
// FLIP_X
4272
uint8 *srcTilePixels = &tilesetPixels[tileIndex << 8];
4273
if (cnt * TILE_SIZE > 0) {
4274
tilePixels = &tilesetPixels[(tileIndex << 8) + (FLIP_X * TILESET_SIZE) + (TILE_SIZE - 1)];
4275
4276
for (int32 i = 0; i < cnt * TILE_SIZE; ++i) {
4277
for (int32 p = 0; p < TILE_SIZE; ++p) *tilePixels-- = *srcTilePixels++;
4278
4279
tilePixels += (TILE_SIZE * 2);
4280
}
4281
}
4282
4283
// FLIP_Y
4284
srcTilePixels = &tilesetPixels[tileIndex << 8];
4285
if (cnt * TILE_SIZE > 0) {
4286
int32 index = tileIndex;
4287
for (int32 i = 0; i < cnt; ++i) {
4288
tilePixels = &tilesetPixels[(index << 8) + (FLIP_Y * TILESET_SIZE) + (TILE_DATASIZE - TILE_SIZE)];
4289
for (int32 y = 0; y < TILE_SIZE; ++y) {
4290
for (int32 x = 0; x < TILE_SIZE; ++x) *tilePixels++ = *srcTilePixels++;
4291
4292
tilePixels -= (TILE_SIZE * 2);
4293
}
4294
++index;
4295
}
4296
}
4297
4298
// FLIP_XY
4299
srcTilePixels = &tilesetPixels[(tileIndex << 8) + (FLIP_Y * TILESET_SIZE)];
4300
if (cnt * TILE_SIZE > 0) {
4301
tilePixels = &tilesetPixels[(tileIndex << 8) + (FLIP_XY * TILESET_SIZE) + (TILE_SIZE - 1)];
4302
4303
for (int32 i = 0; i < cnt * TILE_SIZE; ++i) {
4304
for (int32 p = 0; p < TILE_SIZE; ++p) *tilePixels-- = *srcTilePixels++;
4305
4306
tilePixels += (TILE_SIZE * 2);
4307
}
4308
}
4309
}
4310
}
4311
4312
void RSDK::DrawString(Animator *animator, Vector2 *position, String *string, int32 startFrame, int32 endFrame, int32 align, int32 spacing,
4313
void *unused, Vector2 *charOffsets, bool32 screenRelative)
4314
{
4315
if (animator && string && animator->frames) {
4316
if (!position)
4317
position = &sceneInfo.entity->position;
4318
4319
Entity *entity = sceneInfo.entity;
4320
4321
int32 x = FROM_FIXED(position->x);
4322
int32 y = FROM_FIXED(position->y);
4323
if (!screenRelative) {
4324
x -= currentScreen->position.x;
4325
y -= currentScreen->position.y;
4326
}
4327
4328
startFrame = CLAMP(startFrame, 0, string->length - 1);
4329
4330
if (endFrame <= 0 || endFrame > string->length)
4331
endFrame = string->length;
4332
4333
switch (align) {
4334
case ALIGN_LEFT:
4335
if (charOffsets) {
4336
for (; startFrame < endFrame; ++startFrame) {
4337
uint16 curChar = string->chars[startFrame];
4338
if (curChar < animator->frameCount) {
4339
SpriteFrame *frame = &animator->frames[curChar];
4340
DrawSpriteFlipped(x + FROM_FIXED(charOffsets->x), y + frame->pivotY + FROM_FIXED(charOffsets->y), frame->width,
4341
frame->height, frame->sprX, frame->sprY, FLIP_NONE, entity->inkEffect, entity->alpha, frame->sheetID);
4342
x += spacing + frame->width;
4343
++charOffsets;
4344
}
4345
}
4346
}
4347
else {
4348
for (; startFrame < endFrame; ++startFrame) {
4349
uint16 curChar = string->chars[startFrame];
4350
if (curChar < animator->frameCount) {
4351
SpriteFrame *frame = &animator->frames[curChar];
4352
DrawSpriteFlipped(x, y + frame->pivotY, frame->width, frame->height, frame->sprX, frame->sprY, FLIP_NONE,
4353
entity->inkEffect, entity->alpha, frame->sheetID);
4354
x += spacing + frame->width;
4355
}
4356
}
4357
}
4358
break;
4359
4360
case ALIGN_RIGHT: break;
4361
4362
case ALIGN_CENTER:
4363
--endFrame;
4364
if (charOffsets) {
4365
for (Vector2 *charOffset = &charOffsets[endFrame]; endFrame >= startFrame; --endFrame) {
4366
uint16 curChar = string->chars[endFrame];
4367
if (curChar < animator->frameCount) {
4368
SpriteFrame *frame = &animator->frames[curChar];
4369
DrawSpriteFlipped(x - frame->width + FROM_FIXED(charOffset->x), y + frame->pivotY + FROM_FIXED(charOffset->y),
4370
frame->width, frame->height, frame->sprX, frame->sprY, FLIP_NONE, entity->inkEffect, entity->alpha,
4371
frame->sheetID);
4372
x = (x - frame->width) - spacing;
4373
--charOffset;
4374
}
4375
}
4376
}
4377
else {
4378
for (; endFrame >= startFrame; --endFrame) {
4379
uint16 curChar = string->chars[endFrame];
4380
if (curChar < animator->frameCount) {
4381
SpriteFrame *frame = &animator->frames[curChar];
4382
DrawSpriteFlipped(x - frame->width, y + frame->pivotY, frame->width, frame->height, frame->sprX, frame->sprY, FLIP_NONE,
4383
entity->inkEffect, entity->alpha, frame->sheetID);
4384
x = (x - frame->width) - spacing;
4385
}
4386
}
4387
}
4388
break;
4389
}
4390
}
4391
}
4392
void RSDK::DrawDevString(const char *string, int32 x, int32 y, int32 align, uint32 color)
4393
{
4394
uint16 color16 = rgb32To16_B[(color >> 0) & 0xFF] | rgb32To16_G[(color >> 8) & 0xFF] | rgb32To16_R[(color >> 16) & 0xFF];
4395
4396
int32 charOffset = 0;
4397
bool32 linesRemain = true;
4398
while (linesRemain) {
4399
linesRemain = false;
4400
4401
int32 lineSize = 0;
4402
char cur = string[charOffset];
4403
if (cur != '\n') {
4404
while (cur) {
4405
cur = string[++charOffset];
4406
lineSize++;
4407
if (cur == '\n') {
4408
linesRemain = true;
4409
break;
4410
}
4411
}
4412
}
4413
4414
if (y >= 0 && y < currentScreen->size.y - 7) {
4415
int32 offset = 0;
4416
switch (align) {
4417
default:
4418
case ALIGN_LEFT: offset = 0; break;
4419
4420
case ALIGN_CENTER: offset = 4 * lineSize; break;
4421
4422
case ALIGN_RIGHT: offset = 8 * lineSize; break;
4423
}
4424
int32 drawX = x - offset;
4425
4426
const char *curChar = &string[charOffset++ - lineSize];
4427
4428
for (int32 c = 0; c < lineSize; ++c) {
4429
if (drawX >= 0 && drawX < currentScreen->size.x - 7) {
4430
uint16 *frameBuffer = &currentScreen->frameBuffer[drawX + y * currentScreen->pitch];
4431
4432
if ((*curChar < '\t' || *curChar > '\n') && *curChar != ' ') {
4433
uint8 *textStencilPtr = &devTextStencil[0x40 * *curChar];
4434
4435
for (int32 h = 0; h < 8; ++h) {
4436
for (int32 w = 0; w < 8; ++w) {
4437
if (*textStencilPtr)
4438
*frameBuffer = color16;
4439
4440
++textStencilPtr;
4441
++frameBuffer;
4442
}
4443
4444
frameBuffer += currentScreen->pitch - 8;
4445
}
4446
}
4447
4448
++curChar;
4449
drawX += 8;
4450
}
4451
}
4452
}
4453
4454
y += 8;
4455
}
4456
}
4457
4458