]> git.bts.cx Git - benzene.git/blob - src_platform/playdate/bz/gfx/gfx_platform.c
Initial version
[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