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