]> git.bts.cx Git - benzene.git/blob - src_platform/sdl/bz/gfx/gfx_platform.c
Sprites
[benzene.git] / src_platform / sdl / bz / gfx / gfx_platform.c
1 #include <bz/gfx/gfx_platform.h>
2
3 #include <bz/gfx/gfx_internal.h>
4 #include <bz/math/math.h>
5 #include <bz/renderer/palette_internal.h>
6 #include <bz/renderer/render_pass_internal.h>
7
8 static void gfxRender(BZRendererPaletteID palette, uint32_t *output, size_t width, size_t height, size_t pixelWidth, size_t pixelHeight);
9
10 static BZRenderPass renderPass = {
11 .softwareHook = gfxRender,
12 };
13 BZRenderPassID bzGFXRenderPass = &renderPass;
14
15 #define bzGenerateColor(r, g, b) ((r)&0xFF) << 0 | ((g)&0xFF) << 8 | ((b)&0xFF) << 16 | (0xFF) << 24
16 uint32_t paletteColors[] = {
17 /* 00: */ bzGenerateColor(13, 2, 33), // black
18 /* 01: */ bzGenerateColor(36, 23, 52), // grey
19 /* 02: */ bzGenerateColor(46, 33, 86), // grey
20 /* 03: */ bzGenerateColor(45, 226, 230), // white
21 /* 04: */ bzGenerateColor(253, 55, 119), // red
22 /* 05: */ bzGenerateColor(255, 56, 100), // red
23 /* 06: */ bzGenerateColor(255, 67, 101), // orange
24 /* 07: */ bzGenerateColor(255, 108, 17), // orange
25 /* 08: */ bzGenerateColor(181, 181, 40), // yellow
26 /* 09: */ bzGenerateColor(249, 200, 14), // yellow
27 /* 10: */ bzGenerateColor(31, 105, 75), // green
28 /* 11: */ bzGenerateColor(106, 190, 48), // green
29 /* 12: */ bzGenerateColor(48, 96, 130), // blue
30 /* 13: */ bzGenerateColor(99, 155, 255), // blue
31 /* 14: */ bzGenerateColor(118, 66, 138), // purple
32 /* 15: */ bzGenerateColor(246, 1, 157), // purple
33
34 #if 0 // Vector16
35 /* 00: */ bzGenerateColor(0, 0, 0), // black
36 /* 01: */ bzGenerateColor(92, 92, 92), // grey
37 /* 02: */ bzGenerateColor(150, 150, 150), // grey
38 /* 03: */ bzGenerateColor(255, 255, 255), // white
39 /* 04: */ bzGenerateColor(172, 50, 50), // red
40 /* 05: */ bzGenerateColor(217, 87, 99), // red
41 /* 06: */ bzGenerateColor(143, 78, 30), // orange
42 /* 07: */ bzGenerateColor(223, 113, 38), // orange
43 /* 08: */ bzGenerateColor(181, 181, 40), // yellow
44 /* 09: */ bzGenerateColor(251, 242, 54), // yellow
45 /* 10: */ bzGenerateColor(31, 105, 75), // green
46 /* 11: */ bzGenerateColor(106, 190, 48), // green
47 /* 12: */ bzGenerateColor(48, 96, 130), // blue
48 /* 13: */ bzGenerateColor(99, 155, 255), // blue
49 /* 14: */ bzGenerateColor(118, 66, 138), // purple
50 /* 15: */ bzGenerateColor(215, 123, 186), // purple
51 #endif
52
53 #if 0 // Pico-8
54 /* 00: */ bzGenerateColor(0, 0, 0),
55 /* 01: */ bzGenerateColor(29, 43, 83),
56 /* 02: */ bzGenerateColor(126, 37, 83),
57 /* 03: */ bzGenerateColor(0, 135, 81),
58 /* 04: */ bzGenerateColor(171, 82, 54),
59 /* 05: */ bzGenerateColor(95, 87, 79),
60 /* 06: */ bzGenerateColor(194, 195, 199),
61 /* 07: */ bzGenerateColor(255, 241, 232),
62 /* 08: */ bzGenerateColor(255, 0, 77),
63 /* 09: */ bzGenerateColor(255, 163, 0),
64 /* 10: */ bzGenerateColor(255, 236, 39),
65 /* 11: */ bzGenerateColor(0, 228, 54),
66 /* 12: */ bzGenerateColor(41, 173, 255),
67 /* 13: */ bzGenerateColor(131, 118, 156),
68 /* 14: */ bzGenerateColor(255, 119, 168),
69 /* 15: */ bzGenerateColor(255, 204, 170),
70
71 /* 16: */ bzGenerateColor(41,24,20),
72 /* 17: */ bzGenerateColor(17,29,53),
73 /* 18: */ bzGenerateColor(66,33,54),
74 /* 19: */ bzGenerateColor(18,83,89),
75 /* 20: */ bzGenerateColor(116,47,41),
76 /* 21: */ bzGenerateColor(73,51,59),
77 /* 22: */ bzGenerateColor(162,136,121),
78 /* 23: */ bzGenerateColor(243,239,125),
79 /* 24: */ bzGenerateColor(190,18,80),
80 /* 25: */ bzGenerateColor(255,108,36),
81 /* 26: */ bzGenerateColor(168,231,46),
82 /* 27: */ bzGenerateColor(0,181,67),
83 /* 28: */ bzGenerateColor(6,90,181),
84 /* 29: */ bzGenerateColor(117,70,101),
85 /* 30: */ bzGenerateColor(255,110,89),
86 /* 31: */ bzGenerateColor(255,157,129)
87 #endif
88 };
89
90 static void gfxRender(BZRendererPaletteID palette, uint32_t *output, size_t width, size_t height, size_t pixelWidth, size_t pixelHeight) {
91 bzGfxComposite();
92
93 bzPerfTimerStart("game.blit.transfer");
94
95 uint32_t *pixels = output;
96
97 for (size_t y = 0; y < height; ++y) {
98 uint8_t *bufferLine = &bzGfxCompositedBuffer[y << bufferStrideShift]; // FIXME, bitshift
99 for (size_t x = 0; x < width; ++x) {
100 uint8_t c = bufferLine[x];
101 uint32_t out = palette->colors[c % palette->numColors];
102 uint32_t *pixelsOut = pixels;
103 for (size_t py = 0; py < pixelHeight; ++py) {
104 for (size_t px = 0; px < pixelWidth; ++px) {
105 *pixelsOut = out;
106 pixelsOut++;
107 }
108 pixelsOut+=width * pixelWidth - pixelWidth;
109 }
110
111 pixels += pixelWidth;
112 }
113 pixels += (pixelHeight - 1) * width * pixelWidth;
114 }
115
116 bzPerfTimerStop("game.blit.transfer");
117 }
118
119
120
121
122
123
124
125
126 #if 0
127
128 void bzGfxComposite(uint8_t *outputBuffer) {
129 bzPerfTimerStart("game.blit.composite");
130
131 size_t canvasMemorySize = bufferStride * height * sizeof(uint8_t);
132
133 uint8_t *drawBufferReadHead = drawBuffer;
134 uint8_t *paletteBufferReadHead = paletteBuffer;
135 uint8_t *maskBufferReadHead = maskBuffer;
136 uint8_t *overlayBufferReadHead = overlayBuffer;
137 uint8_t *outputBufferWriteHead = outputBuffer;
138 for (size_t i = 0; i < bufferStride * height; ++i) {
139 *outputBufferWriteHead = palettes[*paletteBufferReadHead + 1][*drawBufferReadHead];
140
141 ++drawBufferReadHead;
142 ++paletteBufferReadHead;
143 ++maskBufferReadHead;
144 ++overlayBufferReadHead;
145 ++outputBufferWriteHead;
146 }
147
148 bzPerfTimerStop("game.blit.composite");
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178 // The real memory seems stupid slow??
179
180 //#define kScreenMem 3120
181 //static uint32_t *fakeScreen = NULL;//[3120];
182
183 static void gfxRender(uint32_t *output, size_t pixelWidth, size_t pixelHeight) {
184 // if (fakeScreen == NULL) {
185 // fakeScreen = malloc(kScreenMem * sizeof(uint32_t));
186 // }
187
188 // FIXME, this one is very very slow.
189
190 bzPerfTimerStart("game.blit.composite");
191
192 uint8_t *p = &buffer[0][0][0];
193
194 for (size_t y = 0; y < canvasHeight; ++y) {
195 for (size_t x = 0; x < canvasWidth; ++x) {
196 // bzAssertMessage(buffer[1][y][x] == 1, "Got: %d", buffer[1][y][x]);
197
198 p[7] = palettes[p[1] + 1][p[0]];
199 p+=8*sizeof(uint8_t);
200
201 // uint8_t cIdx = palettes[buffer[y][x][1] + 1][buffer[y][x][0]]; ////////// (palettes[buffer[y][x][1] + 1][buffer[y][x][0]] & buffer[y][x][2]); // PALETTE, return this (buffer[1][y][x]) + 1
202 // if (buffer[y][x][2] == 0) cIdx = 0;
203 // if (buffer[y][x][3] != 0) cIdx = buffer[y][x][3];
204 // bzBufferSet(7, x, y, cIdx);
205
206 // if (buffer[2][y][x] == 0) {
207 // cIdx = 0;
208 // }
209 // if (buffer[3][y][x] > 0) {
210 // cIdx = buffer[3][y][x];
211 // }
212 // intermediateBuffer[y][x] = cIdx;
213 //intermediateBuffer[y][x] = paletteColors[cIdx];
214 }
215 }
216
217 bzPerfTimerStop("game.blit.composite");
218
219 bzPerfTimerStart("game.blit.transfer");
220
221 // uint32_t *pixels = output;
222 uint32_t *pixels = (uint32_t *)output;//(uint32_t *)output;
223 //int idx = 0;
224 uint32_t value = 0;
225 for (size_t y = 0; y < canvasHeight * pixelHeight; ++y) {
226 //idx = y * 13;
227 int patY = y % 4;
228 //int patX = 0;
229 uint8_t ly = y >> 1;
230 uint8_t lx = 0;
231 for (size_t x = 0; x < canvasWidth * pixelWidth; ) {
232 //value = 0;
233 int target = bzMin(canvasWidth * pixelWidth - x, 32);
234 for (int i = 0; i < target; ++i, ++x) {
235 uint8_t c = buffer[ly /*/ pixelHeight*/][lx /*/ pixelWidth*/][7];
236 uint8_t patternIdx = patternLookup[c];
237 //bzAssertMessage(patternIdx <= 7, "Pattern index %d at %d,%d %d,%d", patternIdx, x, y, x / pixelWidth, y / pixelHeight);
238 uint8_t bit = patterns[patternIdx][patY][x & 0b11 /*% 4*/];
239 value = (value << 1) | bit ;// | patterns[patternIdx][patY][x % 4]; //(patterns[patternIdx][patY][x % 4] * 0b10000000000000000000000000000000);//x % 4 -> patX FIXME
240 lx += x&1;
241 }
242 // *pixels = swap(value);
243 __asm volatile ("rev %0, %1" : "=l" (*pixels) : "l" (value));
244 pixels++;// += 4;//sizeof(uint32_t);
245 }
246 //pixels += 2; // stride...
247 }
248
249 bzPerfTimerStop("game.blit.transfer");
250
251 // memcpy(output, fakeScreen, kScreenMem * sizeof(uint32_t));
252 }
253
254
255
256
257
258
259 #include <bz/gfx/gfx_internal.h>
260
261 #include <bz/gfx/font_internal.h>
262 #include <bz/math/math.h>
263 #include <bz/renderer/render_pass_internal.h>
264
265 #include <stdlib.h>
266
267 // http://members.chello.at/~easyfilter/Bresenham.pdf
268
269 static void gfxRender(uint32_t *output, size_t pixelWidth, size_t pixelHeight);
270
271 static BZRenderPass renderPass = {
272 .softwareHook = gfxRender,
273 };
274 BZRenderPassID bzGFXRenderPass = &renderPass;
275
276 #define GFX_WIDTH 200 //256 // 128 //320
277 #define GFX_HEIGHT 120 //128 // 128 //180
278
279 static int currentBuffer = 0;
280 static uint8_t buffer[GFX_HEIGHT][GFX_WIDTH][8];
281 static int cameraX = 0;
282 static int cameraY = 0;
283 static bool fillPattern[4][4];
284
285 #define _bzBufferSet(idx, x, y, value) buffer[(y)][(x)][(idx)] = (value)
286 #define _bzBufferSetSafe(idx, x, y, value) { bzAssert(idx>= 0 && idx<8);bzAssertMessage((x)>= 0 && (x)<GFX_WIDTH, "invalid x: %d %s, %d", x, __FILE__, __LINE__);bzAssertMessage((y)>= 0 && (y)<GFX_HEIGHT, "invalid y: %d %s, %d", y, __FILE__, __LINE__);_bzBufferSet(idx, x, y, value); }
287
288 #define bzBufferSet _bzBufferSet
289
290 //uint32_t intermediateBuffer[GFX_HEIGHT][GFX_WIDTH];
291
292 #define SS_WIDTH 128
293 #define SS_HEIGHT 128
294
295 static uint8_t spritesheet[SS_HEIGHT][SS_WIDTH];
296
297 static BZFont *currentFont;
298
299 #define bzGenerateColor(r, g, b) (r&0xFF) << 0 | (g&0xFF) << 8 | (b&0xFF) << 16 | (0xFF) << 24
300 uint32_t paletteColors[] = {
301 bzGenerateColor(0, 0, 0),
302 bzGenerateColor(29, 43, 83),
303 bzGenerateColor(126, 37, 83),
304 bzGenerateColor(0, 135, 81),
305 bzGenerateColor(171, 82, 54),
306 bzGenerateColor(95, 87, 79),
307 bzGenerateColor(194, 195, 199),
308 bzGenerateColor(255, 241, 232),
309 bzGenerateColor(255, 0, 77),
310 bzGenerateColor(255, 163, 0),
311 bzGenerateColor(255, 236, 39),
312 bzGenerateColor(0, 228, 54),
313 bzGenerateColor(41, 173, 255),
314 bzGenerateColor(131, 118, 156),
315 bzGenerateColor(255, 119, 168),
316 bzGenerateColor(255, 204, 170),
317
318 bzGenerateColor(41,24,20),
319 bzGenerateColor(17,29,53),
320 bzGenerateColor(66,33,54),
321 bzGenerateColor(18,83,89),
322 bzGenerateColor(116,47,41),
323 bzGenerateColor(73,51,59),
324 bzGenerateColor(162,136,121),
325 bzGenerateColor(243,239,125),
326 bzGenerateColor(190,18,80),
327 bzGenerateColor(255,108,36),
328 bzGenerateColor(168,231,46),
329 bzGenerateColor(0,181,67),
330 bzGenerateColor(6,90,181),
331 bzGenerateColor(117,70,101),
332 bzGenerateColor(255,110,89),
333 bzGenerateColor(255,157,129)
334 };
335
336 uint8_t palettes[16][16] = {
337 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
338 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
339 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
340 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
341 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
342 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
343 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
344 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
345 };
346
347 //BZRect bzCalculateCullRect() {
348 // return bzRectMake(cameraX, cameraY, GFX_WIDTH, SS_HEIGHT);
349 //}
350
351 void bzGfxPrepareSpritesheet(size_t width, size_t height, void *data) {
352 uint8_t *imageData = (uint8_t *)data;
353 bzLog("Preparing spritesheet %dx%d", width, height);
354 //assert(width == 128 && height == 128);
355 for (size_t y = 0, i = 0; y < SS_HEIGHT; ++y) {
356 for (size_t x = 0; x < SS_WIDTH; ++x, ++i) {
357 spritesheet[y][x] = imageData[i];
358 }
359 }
360 }
361
362 void bzGfxPrepareFont(void *font) {
363 currentFont = font;
364 }
365
366 static bool prepareFrame(int *minXOut, int *minYOut, int *maxXOut, int *maxYOut, int x0, int y0, int x1, int y1, int *clippedLeftX, int *clippedTopY, int *clippedRightX, int *clippedBottomY) {
367 int xMin = x0, xMax = x1;
368 int yMin = y0, yMax = y1;
369
370 if (x1 < x0) {
371 xMin = x1;
372 xMax = x0;
373 }
374
375 if (y1 < y0) {
376 yMin = y1;
377 yMax = y0;
378 }
379
380 int xMinOut = xMin - cameraX, xMaxOut = xMax - cameraX;
381 int yMinOut = yMin - cameraY, yMaxOut = yMax - cameraY;
382
383 if (xMaxOut < 0 || yMaxOut < 0 || xMinOut >= GFX_WIDTH || yMinOut >= GFX_HEIGHT) {
384 return false;
385 }
386
387 int safeXMinOut = bzMax(0, xMinOut);
388 int safeXMaxOut = bzMin(GFX_WIDTH - 1, xMaxOut);
389 int safeYMinOut = bzMax(0, yMinOut);
390 int safeYMaxOut = bzMin(GFX_HEIGHT - 1, yMaxOut);
391
392 *minXOut = safeXMinOut;
393 *minYOut = safeYMinOut;
394 *maxXOut = safeXMaxOut;
395 *maxYOut = safeYMaxOut;
396
397 if (clippedLeftX != NULL) {
398 *clippedLeftX = safeXMinOut - xMinOut;
399 *clippedTopY = safeYMinOut - yMinOut;
400
401 *clippedRightX = xMaxOut - safeXMaxOut;
402 *clippedBottomY = yMaxOut - safeYMaxOut;
403 }
404
405 return true;
406 }
407
408 static bool prepareColor(int *colorOut, int color) {
409 int c = (color <= 15) ? palettes[0][color] : color;
410 if (c > 0) {
411 *colorOut = c;
412 return true;
413 } else {
414 return false;
415 }
416 }
417
418 void bzPSet(int x, int y, int c) {
419 if (c == 0) return;
420
421 int ox = x - cameraX;
422 int oy = y - cameraY;
423 if (ox >= 0 && ox < GFX_WIDTH && oy >=0 && oy < GFX_HEIGHT) {
424 if(fillPattern[y%4][x%4] == false) bzBufferSet(currentBuffer, ox, oy, (c <= 15) ? palettes[0][c] : c); // FIXME
425 }
426 }
427
428 int bzSGet(int x, int y) {
429 if (x >= 0 && x < SS_WIDTH && y >=0 && y < SS_HEIGHT) {
430 return spritesheet[y][x];
431 } else {
432 return 0;
433 }
434 }
435
436 //void bzSSet(int x, int y, int c);
437
438 //bool bzFGet(int n, int f);
439 //void bzFSet(int n, int f, bool v);
440
441 void bzCls(uint8_t c) {
442
443 //memset(&buffer[currentBuffer], c, BUFFER_WIDTH * GFX_HEIGHT);
444
445 // for (size_t i = 0; i < )
446
447 for (size_t y = 0; y < GFX_HEIGHT; ++y) {
448 for (size_t x = 0; x < GFX_WIDTH; ++x) {
449 bzBufferSet(currentBuffer, x, y, c);
450 }
451 }
452
453 //bzCamera(0, 0);
454 bzFillP(0x0000);
455 }
456
457 void bzGetCamera(int *x, int *y) {
458 if (x != NULL) *x = cameraX;
459 if (y != NULL) *y = cameraY;
460 }
461
462 void bzCamera(int x, int y) {
463 cameraX = x;
464 cameraY = y;
465 }
466
467 void bzCirc(int xm, int ym, int r, int c) {
468 int xMinOut, yMinOut, xMaxOut, yMaxOut, cOut;
469 if (prepareColor(&cOut, c) && prepareFrame(&xMinOut, &yMinOut, &xMaxOut, &yMaxOut, xm - r, ym - r, xm + r, ym + r, NULL, NULL, NULL, NULL)) {
470 xm -= cameraX;
471 ym -= cameraY;
472
473 int x = -r;
474 int y = 0;
475 int err = 2 - 2 * r;
476
477 do {
478 bzPSet(xm-x, ym+y, cOut);
479 bzPSet(xm-y, ym-x, cOut);
480 bzPSet(xm+x, ym-y, cOut);
481 bzPSet(xm+y, ym+x, cOut);
482
483 r = err;
484
485 if (r <= y) err += (++y << 1) + 1;
486 if (r > x || err > y) err += (++x << 1) + 1;
487 } while (x < 0);
488 }
489 }
490
491 void bzCircFill(int xm, int ym, int r, int c) {
492 int xMinOut, yMinOut, xMaxOut, yMaxOut, cOut;
493 if (prepareColor(&cOut, c) && prepareFrame(&xMinOut, &yMinOut, &xMaxOut, &yMaxOut, xm - r, ym - r, xm + r, ym + r, NULL, NULL, NULL, NULL)) {
494 xm -= cameraX;
495 ym -= cameraY;
496
497 int x = -r;
498 int y = 0;
499 int err = 2 - 2 * r;
500
501 do {
502 int fy1 = ym - bzAbs(y);
503 int fy2 = ym + bzAbs(y);
504 int fx = bzMax(xm - bzAbs(x), 0);
505 int tx = bzMin(xm + bzAbs(x), GFX_WIDTH - 1); // FIXME, not as many abs
506
507 bool validFy1 = fy1 >= 0 && fy1 < GFX_HEIGHT;
508 bool validFy2 = fy2 >= 0 && fy2 < GFX_HEIGHT;
509
510 if (validFy1 && validFy2) {
511 for (int ox = fx; ox <= tx; ++ox) {
512 bzBufferSet(currentBuffer, ox, fy1, cOut);
513 bzBufferSet(currentBuffer, ox, fy2, cOut);
514 }
515 } else if (validFy1) {
516 for (int ox = fx; ox <= tx; ++ox) {
517 bzBufferSet(currentBuffer, ox, fy1, cOut);
518 }
519 } else if (validFy2) {
520 for (int ox = fx; ox <= tx; ++ox) {
521 bzBufferSet(currentBuffer, ox, fy2, cOut);
522 }
523 }
524
525 r = err;
526
527 if (r <= y) err += (++y << 1) + 1;
528 if (r > x || err > y) err += (++x << 1) + 1;
529 } while (x < 0);
530 }
531 }
532
533 //void bzOval(int x0, int y0, int x1, int y1, int c);
534 //void bzOvalFill(int x0, int y0, int x1, int y1, int c);
535
536 void bzLine(int x0, int y0, int x1, int y1, int c) {
537 int xMinOut, yMinOut, xMaxOut, yMaxOut, cOut, clipLeft, clipTop, clipRight, clipBottom;
538 if (prepareColor(&cOut, c) && prepareFrame(&xMinOut, &yMinOut, &xMaxOut, &yMaxOut, x0, y0, x1, y1, &clipLeft, &clipTop, &clipRight, &clipBottom)) {
539 x0 = x0 - cameraX;
540 y0 = y0 - cameraY;
541 x1 = x1 - cameraX;
542 y1 = y1 - cameraY;
543
544 int deltaX = bzAbs(x1 - x0);
545 int deltaY = -bzAbs(y1 - y0);
546 int signX = bzSgn(x1 - x0);
547 int signY = bzSgn(y1 - y0);
548 int err = deltaX + deltaY;
549 int e2;
550
551 int x = x0, y = y0;
552
553 for (;;) {
554 if (x >= 0 && x < GFX_WIDTH && y >=0 && y < GFX_HEIGHT) { // FIXME, easier way to offset this...
555 bzBufferSet(currentBuffer, x, y, cOut);
556 }
557
558 e2 = err << 1;
559
560 if (e2 >= deltaY) {
561 if (x == x1) break;
562 err += deltaY;
563 x += signX;
564 }
565
566 if (e2 <= deltaX) {
567 if (y == y1) break;
568 err += deltaX;
569 y += signY;
570 }
571 }
572 }
573 }
574
575 void bzRect(int x0, int y0, int x1, int y1, int c) {
576 int xMinOut, yMinOut, xMaxOut, yMaxOut, cOut, clipLeft, clipTop, clipRight, clipBottom;
577 if (prepareColor(&cOut, c) && prepareFrame(&xMinOut, &yMinOut, &xMaxOut, &yMaxOut, x0, y0, x1, y1, &clipLeft, &clipTop, &clipRight, &clipBottom)) {
578 if (clipLeft == 0 && clipRight == 0) {
579 for (int oy = yMinOut; oy <= yMaxOut; ++oy) {
580 bzBufferSet(currentBuffer, xMinOut, oy, cOut);
581 bzBufferSet(currentBuffer, xMaxOut, oy, cOut);
582 }
583 } else if (clipLeft == 0) {
584 for (int oy = yMinOut; oy <= yMaxOut; ++oy) {
585 bzBufferSet(currentBuffer, xMinOut, oy, cOut);
586 }
587 } else if (clipRight == 0) {
588 for (int oy = yMinOut; oy <= yMaxOut; ++oy) {
589 bzBufferSet(currentBuffer, xMaxOut, oy, cOut);
590 }
591 }
592
593 if (clipTop == 0 && clipBottom == 0) {
594 for (int ox = xMinOut; ox <= xMaxOut; ++ox) {
595 bzBufferSet(currentBuffer, ox, yMinOut, cOut);
596 bzBufferSet(currentBuffer, ox, yMaxOut, cOut);
597 }
598 } else if (clipTop == 0) {
599 for (int ox = xMinOut; ox <= xMaxOut; ++ox) {
600 bzBufferSet(currentBuffer, ox, yMinOut, cOut);
601 }
602 } else if (clipBottom == 0) {
603 for (int ox = xMinOut; ox <= xMaxOut; ++ox) {
604 bzBufferSet(currentBuffer, ox, yMaxOut, cOut);
605 }
606 }
607 }
608 }
609
610 void bzRectFill(int x0, int y0, int x1, int y1, int c) {
611 int xMinOut, yMinOut, xMaxOut, yMaxOut, cOut;
612 if (prepareColor(&cOut, c) && prepareFrame(&xMinOut, &yMinOut, &xMaxOut, &yMaxOut, x0, y0, x1, y1, NULL, NULL, NULL, NULL)) {
613 for (int oy = yMinOut; oy <= yMaxOut; ++oy) {
614 for (int ox = xMinOut; ox <= xMaxOut; ++ox) {
615 bzBufferSet(currentBuffer, ox, oy, cOut);
616 }
617 }
618 }
619 }
620
621 void bzSpr(int n, int x, int y) {
622 bzSprExt(n, x, y, 1, 1, false, false);
623 }
624
625 void bzSprExt(int n, int x, int y, int w, int h, bool flipX, bool flipY) {
626 int px = (n % 16) * 8;
627 int py = (n / 16) * 8;
628 int pw = w * 8;
629 int ph = h * 8;
630 bzSSprExt(px, py, pw, ph, x, y, pw, ph, flipX, flipY);
631 }
632
633 void bzSSpr(int sx, int sy, int sw, int sh, int dx, int dy) {
634 bzSSprExt(sx, sy, sw, sh, dx, dy, sw, sh, false, false);
635 }
636
637 void bzSSprExt(int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, bool flipX, bool flipY) {
638 int xMinOut, yMinOut, xMaxOut, yMaxOut, clipLeft, clipTop, clipRight, clipBottom;
639 if (prepareFrame(&xMinOut, &yMinOut, &xMaxOut, &yMaxOut, dx, dy, dx+dw, dy+dh, &clipLeft, &clipTop, &clipRight, &clipBottom)) {
640
641 for (size_t y = 0; y < sh - (clipTop + clipBottom); ++y) {
642 for (size_t x = 0; x < sw - (clipLeft + clipRight); ++x) {
643 int color = spritesheet[clipTop+sy+y][clipLeft+sx+x];
644 if (color > 0) bzBufferSet(currentBuffer, xMinOut+x, yMinOut+y, color); // FIXME, scaled up and 0 check removal??
645 }
646 }
647 }
648
649 /*int fromX = 0;
650 int toX = sw;
651 int dX = 1;
652
653 if (flipX) {
654 fromX = toX - 1;
655 toX = -1;
656 dX = -1;
657 }
658
659 int fromY = 0;
660 int toY = sh;
661 int dY = 1;
662
663 if (flipY) {
664 fromY = toY - 1;
665 toY = -1;
666 dY = -1;
667 }
668
669 for (int rY = fromY, wY = dy; rY != toY; rY += dY, ++wY) {
670 for (int rX = fromX, wX = dx; rX != toX; rX += dX, ++wX) {
671 bzPSet(wX, wY, bzSGet(sx + rX, sy + rY));
672 }
673 }*/
674 }
675
676 void bzFillP(int p) {
677 int f = 1;
678 for (int y = 3; y >= 0; --y) {
679 for (int x = 3; x >= 0; --x, f<<=1) {
680 fillPattern[y][x] = (p & f) > 0;
681 }
682 }
683 }
684
685
686
687 void bzPrint(int x, int y, int color, const char *text) {
688 int currentX = x, currentY = y;
689 bzGfxRenderFont(bzPSet, &currentX, &currentY, currentFont, color, text);
690 }
691
692 void bzSetPaletteColor(int palette, int colorIdx, int color) {
693 palettes[palette][colorIdx] = color;
694 }
695
696 #define bzGeneratePattern(p11, p12, p13, p14, p21, p22, p23, p24, p31, p32, p33, p34, p41, p42, p43, p44) { {p11, p12, p13, p14}, {p21, p22, p23, p24}, {p31, p32, p33, p34}, {p41, p42, p43, p44} }
697
698 //(r&0xFF) << 0 | (g&0xFF) << 8 | (b&0xFF) << 16 | (0xFF) << 24
699
700 int patterns[8][4][4] = {
701 bzGeneratePattern(0, 0, 0, 0,
702 0, 0, 0, 0,
703 0, 0, 0, 0,
704 0, 0, 0, 0),
705 bzGeneratePattern(1, 0, 0, 0,
706 0, 0, 0, 1,
707 0, 1, 0, 0,
708 0, 0, 1, 0),
709 bzGeneratePattern(0, 0, 0, 0,
710 0, 0, 0, 0,
711 0, 0, 0, 0,
712 0, 0, 0, 0),
713 bzGeneratePattern(0, 1, 0, 1,
714 1, 1, 1, 1,
715 0, 1, 0, 1,
716 1, 1, 1, 1),
717 bzGeneratePattern(0, 0, 0, 0,
718 1, 1, 0, 0,
719 0, 0, 0, 0,
720 0, 0, 0, 0),
721 bzGeneratePattern(0, 1, 0, 1,
722 1, 0, 1, 0,
723 0, 1, 0, 1,
724 1, 0, 1, 0),
725 bzGeneratePattern(1, 1, 1, 1,
726 1, 1, 1, 1,
727 1, 1, 1, 1,
728 1, 1, 1, 1),
729 };
730
731 uint8_t patternLookup[] = {
732 0,
733 0,
734 3,
735 1,
736 5,
737 5,
738 3,
739 6,
740 2,
741 5,
742 2,
743 2,
744 2,
745 5,
746 2,
747 2,
748 1,
749
750
751 1,
752 1,
753 1,
754 1,
755 1,
756 1,
757 1,
758 1,
759 1,
760 1,
761 1,
762 1,
763 1,
764 1,
765 1,
766 1,
767 1
768 };
769
770
771
772
773 // The real memory seems stupid slow??
774
775 //#define kScreenMem 3120
776 //static uint32_t *fakeScreen = NULL;//[3120];
777
778 static void gfxRender(uint32_t *output, size_t pixelWidth, size_t pixelHeight) {
779 // if (fakeScreen == NULL) {
780 // fakeScreen = malloc(kScreenMem * sizeof(uint32_t));
781 // }
782
783 // FIXME, this one is very very slow.
784
785 bzPerfTimerStart("game.blit.composite");
786
787 uint8_t *p = &buffer[0][0][0];
788
789 for (size_t y = 0; y < GFX_HEIGHT; ++y) {
790 for (size_t x = 0; x < GFX_WIDTH; ++x) {
791 // bzAssertMessage(buffer[1][y][x] == 1, "Got: %d", buffer[1][y][x]);
792
793 p[7] = palettes[p[1] + 1][p[0]];
794 p+=8*sizeof(uint8_t);
795
796 // uint8_t cIdx = palettes[buffer[y][x][1] + 1][buffer[y][x][0]]; ////////// (palettes[buffer[y][x][1] + 1][buffer[y][x][0]] & buffer[y][x][2]); // PALETTE, return this (buffer[1][y][x]) + 1
797 // if (buffer[y][x][2] == 0) cIdx = 0;
798 // if (buffer[y][x][3] != 0) cIdx = buffer[y][x][3];
799 // bzBufferSet(7, x, y, cIdx);
800
801 // if (buffer[2][y][x] == 0) {
802 // cIdx = 0;
803 // }
804 // if (buffer[3][y][x] > 0) {
805 // cIdx = buffer[3][y][x];
806 // }
807 // intermediateBuffer[y][x] = cIdx;
808 //intermediateBuffer[y][x] = paletteColors[cIdx];
809 }
810 }
811
812 bzPerfTimerStop("game.blit.composite");
813
814 bzPerfTimerStart("game.blit.transfer");
815
816 // uint32_t *pixels = output;
817 uint32_t *pixels = (uint32_t *)output;//(uint32_t *)output;
818 //int idx = 0;
819 uint32_t value = 0;
820 for (size_t y = 0; y < GFX_HEIGHT * pixelHeight; ++y) {
821 //idx = y * 13;
822 int patY = y % 4;
823 //int patX = 0;
824 uint8_t ly = y >> 1;
825 uint8_t lx = 0;
826 for (size_t x = 0; x < GFX_WIDTH * pixelWidth; ) {
827 //value = 0;
828 int target = bzMin(GFX_WIDTH * pixelWidth - x, 32);
829 for (int i = 0; i < target; ++i, ++x) {
830 uint8_t c = buffer[ly /*/ pixelHeight*/][lx /*/ pixelWidth*/][7];
831 uint8_t patternIdx = patternLookup[c];
832 //bzAssertMessage(patternIdx <= 7, "Pattern index %d at %d,%d %d,%d", patternIdx, x, y, x / pixelWidth, y / pixelHeight);
833 uint8_t bit = patterns[patternIdx][patY][x & 0b11 /*% 4*/];
834 value = (value << 1) | bit ;// | patterns[patternIdx][patY][x % 4]; //(patterns[patternIdx][patY][x % 4] * 0b10000000000000000000000000000000);//x % 4 -> patX FIXME
835 lx += x&1;
836 }
837 // *pixels = swap(value);
838 __asm volatile ("rev %0, %1" : "=l" (*pixels) : "l" (value));
839 pixels++;// += 4;//sizeof(uint32_t);
840 }
841 //pixels += 2; // stride...
842 }
843
844 bzPerfTimerStop("game.blit.transfer");
845
846 // memcpy(output, fakeScreen, kScreenMem * sizeof(uint32_t));
847 }
848
849 void bzSetOutputBuffer(int idx) {
850 currentBuffer = idx;
851 }
852
853 #endif