lsnes rr2-β24
[lsnes.git] / src / emulation / sky / framebuffer.cpp
blob8554e5f8e0e6800c8ed782bcc334296b12c7fa46
1 #include "framebuffer.hpp"
2 #include "instance.hpp"
3 #include <cstring>
4 #include <iostream>
6 namespace sky
8 void render_backbuffer(struct instance& inst)
11 for(unsigned i = 0; i < 200; i++) {
12 for(unsigned j = 0; j < 320; j++) {
13 for(unsigned k = 0; k < FB_SCALE; k++)
14 inst.framebuffer[FB_MAJSTRIDE * i + FB_SCALE * j + k] = inst.origbuffer[
15 320 * i + j];
17 for(unsigned k = 1; k < FB_SCALE; k++)
18 memcpy(inst.framebuffer + (FB_MAJSTRIDE * i + k * FB_WIDTH),
19 inst.framebuffer + FB_MAJSTRIDE * i, FB_WIDTH * sizeof(uint32_t));
21 //Calculate overlap region.
22 for(unsigned i = 0; i < 200; i++) {
23 uint32_t high = 0x00000000U;
24 for(unsigned j = 0; j < 320; j++)
25 high |= inst.origbuffer[320 * i + j];
26 if(high & 0xFF000000U) {
27 inst.overlap_start = FB_SCALE * i;
28 break;
31 for(unsigned i = inst.overlap_start / FB_SCALE; i < 200; i++) {
32 uint32_t low = 0xFFFFFFFFU;
33 for(unsigned j = 0; j < 320; j++)
34 low &= inst.origbuffer[320 * i + j];
35 if((low & 0xFF000000U) == 0xFF000000U) {
36 inst.overlap_end = FB_SCALE * i;
37 break;
42 void render_framebuffer_update(struct instance& inst, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
44 if(x >= 320)
45 return;
46 for(unsigned i = y; i < y + h && i < 200; i++) {
47 for(unsigned j = x; j < x + w && j < 320; j++) {
48 for(unsigned k = 0; k < FB_SCALE; k++)
49 inst.framebuffer[FB_MAJSTRIDE * i + FB_SCALE * j + k] = inst.origbuffer[
50 320 * i + j];
52 for(unsigned k = 1; k < FB_SCALE; k++)
53 memcpy(inst.framebuffer + (FB_MAJSTRIDE * i + FB_SCALE * x + k * FB_WIDTH),
54 inst.framebuffer + FB_MAJSTRIDE * i + FB_SCALE * x, FB_SCALE * w *
55 sizeof(uint32_t));
59 void render_framebuffer_vline(struct instance& inst, uint16_t x, uint16_t y1, uint16_t y2, uint32_t color)
61 for(unsigned i = y1; i <= y2 && i < 200; i++) {
62 for(unsigned k = 0; k < FB_SCALE; k++)
63 inst.framebuffer[FB_MAJSTRIDE * i + x + k * FB_WIDTH] = 0xFF000000U | color;
67 char decode(const char* ch)
69 char c = *ch;
70 if(c >= '\\')
71 c--;
72 return c - 35;
75 void draw_block2(struct instance& inst, const char* pointer, uint16_t position, uint32_t c1, uint32_t c2,
76 bool zero)
78 static const uint8_t tbl[3][6] = {{27, 9, 3, 1}, {32, 16, 8, 4, 2, 1}, {32, 16, 8, 4, 2, 1}};
79 static const uint8_t tbl2[3][3] = {{4, 6, 6}, {3, 2, 2}, {0, 0, 1}};
80 c1 |= 0xFF000000U;
81 c2 |= 0xFF000000U;
82 uint8_t type = decode(pointer++);
83 uint16_t width = decode(pointer++);
84 if(width > 63) width = (width - 64) * 64 + decode(pointer++);
85 uint16_t height = decode(pointer++);
86 if(height > 63) height = (height - 64) * 64 + decode(pointer++);
87 uint16_t origptr = position;
88 uint8_t mod = 0;
89 uint8_t reg = 0;
90 for(unsigned y = 0; y < height; y++) {
91 for(unsigned x = 0; x < width; x++) {
92 if(!mod)
93 reg = decode(pointer++);
94 uint8_t p = ((reg / tbl[type][mod]) % tbl2[1][type]) << tbl2[2][type];
95 mod = (mod + 1) % tbl2[0][type];
96 if(p)
97 inst.origbuffer[position] = (p > 1) ? c2 : c1;
98 else if(zero)
99 inst.origbuffer[position] = 0;
100 position++;
102 position += (320 - width);
104 render_framebuffer_update(inst, origptr % 320, origptr / 320, width, height);
107 void draw_block(struct instance& inst, const uint8_t* pointer, uint16_t position, uint32_t c1, uint32_t c2,
108 bool zero)
110 c1 |= 0xFF000000U;
111 c2 |= 0xFF000000U;
112 uint16_t width = *(pointer++);
113 uint16_t height = *(pointer++);
114 uint16_t origptr = position;
115 for(unsigned y = 0; y < height; y++) {
116 for(unsigned x = 0; x < width; x++) {
117 uint8_t p = *(pointer++);
118 if(p)
119 inst.origbuffer[position] = (p > 1) ? c2 : c1;
120 else if(zero)
121 inst.origbuffer[position] = 0;
122 position++;
124 position += (320 - width);
126 render_framebuffer_update(inst, origptr % 320, origptr / 320, width, height);
129 void draw_message(struct instance& inst, const char* pointer, uint32_t c1, uint32_t c2)
131 auto op = pointer;
132 pointer++;
133 uint16_t width = decode(pointer++);
134 if(width > 63) width = (width - 64) * 64 + decode(pointer++);
135 uint16_t height = decode(pointer++);
136 if(height > 63) height = (height - 64) * 64 + decode(pointer++);
137 uint16_t x = (320 - width) / 2;
138 uint16_t y = (200 - height) / 2;
139 uint16_t p = 320 * y + x;
140 draw_block2(inst, op, p, c1, c2);
143 void draw_distance_column(struct instance& inst, uint16_t col, uint32_t c)
145 uint16_t minline = 0x8f;
146 uint16_t maxline = 0x8f;
147 uint16_t ptr = 320 * 0x8f + 0x2a + (col / FB_SCALE);
148 uint32_t px = inst.origbuffer[ptr] ;
149 while(inst.origbuffer[ptr] == px)
150 ptr -= 320;
151 ptr += 320;
152 minline = ptr / 320;
153 while(inst.origbuffer[ptr] == px)
154 ptr += 320;
155 maxline = ptr / 320 - 1;
156 render_framebuffer_vline(inst, col + FB_SCALE * 0x2a, minline, maxline, c | 0xFF000000U);
159 void blink_between(struct instance& inst, unsigned x, unsigned y, unsigned w, unsigned h, uint32_t c1,
160 uint32_t c2)
162 c1 &= 0xFFFFFF;
163 c2 &= 0xFFFFFF;
164 uint32_t c1x = c1 | 0xFF000000U;
165 uint32_t c2x = c2 | 0xFF000000U;
166 for(unsigned j = y; j < y + h; j++)
167 for(unsigned i = x; i < x + w; i++) {
168 if((inst.origbuffer[320 * j + i] & 0xFFFFFF) == c1)
169 inst.origbuffer[320 * j + i] = c2x;
170 else if((inst.origbuffer[320 * j + i] & 0xFFFFFF) == c2)
171 inst.origbuffer[320 * j + i] = c1x;
173 render_framebuffer_update(inst, x, y, w, h);
176 void draw_bitmap(struct instance& inst, const uint32_t* bitmap, unsigned x, unsigned y)
178 for(unsigned j = 0; j < bitmap[1]; j++)
179 for(unsigned i = 0; i < bitmap[0]; i++)
180 inst.framebuffer[(y + j) * FB_WIDTH + (x + i)] = bitmap[j * bitmap[0] + i + 2];