Root/
Source at commit 1158 created 13 years 16 days ago. By azimutz, Match nvidia.c with the one on my branch (Chazi) adding dev id's from issue 99 and Asus G74SX (0DF4, 1251). | |
---|---|
1 | ␊ |
2 | /* Graphic utility functions and data types␊ |
3 | * Prashant Vaibhav (C) 12/12/2008␊ |
4 | * Chameleon␊ |
5 | */␊ |
6 | #include "boot.h"␊ |
7 | #include "graphic_utils.h"␊ |
8 | #include "graphics.h"␊ |
9 | #include "vbe.h"␊ |
10 | #include "gui.h"␊ |
11 | ␊ |
12 | #define VIDEO(x) (bootArgs->Video.v_ ## x)␊ |
13 | ␊ |
14 | #define MIN(x, y) ((x) < (y) ? (x) : (y))␊ |
15 | ␊ |
16 | ␊ |
17 | ␊ |
18 | int␊ |
19 | convertImage( unsigned short width,␊ |
20 | ␉␉␉ unsigned short height,␊ |
21 | ␉␉␉ const unsigned char *imageData,␊ |
22 | ␉␉␉ unsigned char **newImageData )␊ |
23 | {␊ |
24 | int cnt;␊ |
25 | unsigned char *img = 0;␊ |
26 | unsigned short *img16;␊ |
27 | unsigned long *img32;␊ |
28 | ␉␊ |
29 | switch ( VIDEO(depth) ) {␊ |
30 | ␉␉case 16 :␊ |
31 | ␉␉␉img16 = malloc(width * height * 2);␊ |
32 | ␉␉␉if ( !img16 ) break;␊ |
33 | ␉␉␉for (cnt = 0; cnt < (width * height); cnt++)␊ |
34 | ␉␉␉␉img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);␊ |
35 | ␉␉␉img = (unsigned char *)img16;␊ |
36 | ␉␉␉break;␊ |
37 | ␉␉␉␊ |
38 | ␉␉case 32 :␊ |
39 | ␉␉␉img32 = malloc(width * height * 4);␊ |
40 | ␉␉␉if ( !img32 ) break;␊ |
41 | ␉␉␉for (cnt = 0; cnt < (width * height); cnt++)␊ |
42 | ␉␉␉␉img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);␊ |
43 | ␉␉␉img = (unsigned char *)img32;␊ |
44 | ␉␉␉break;␊ |
45 | ␉␉␉␊ |
46 | ␉␉default :␊ |
47 | ␉␉␉img = malloc(width * height);␊ |
48 | ␉␉␉bcopy(imageData, img, width * height);␊ |
49 | ␉␉␉break;␊ |
50 | }␊ |
51 | *newImageData = img;␊ |
52 | return 0;␊ |
53 | }␊ |
54 | ␊ |
55 | ␊ |
56 | //==========================================================================␊ |
57 | //␊ |
58 | void ␊ |
59 | printVBEModeInfo()␊ |
60 | {␊ |
61 | VBEInfoBlock vbeInfo;␊ |
62 | unsigned short * modePtr;␊ |
63 | VBEModeInfoBlock modeInfo;␊ |
64 | int err;␊ |
65 | int line;␊ |
66 | ␉␊ |
67 | ␉bzero( &vbeInfo, sizeof(vbeInfo) );␊ |
68 | strcpy( (char*)&vbeInfo, "VBE2" );␊ |
69 | err = getVBEInfo( &vbeInfo );␊ |
70 | if ( err != errSuccess )␊ |
71 | return;␊ |
72 | ␉␊ |
73 | line = 0;␊ |
74 | ␉␊ |
75 | // Activate and clear page 1␊ |
76 | setActiveDisplayPage(1);␊ |
77 | clearScreenRows(0, 24);␊ |
78 | setCursorPosition( 0, 0, 1 );␊ |
79 | ␉␊ |
80 | ␉printf("Video modes supported:\n", VBEDecodeFP(const char *, vbeInfo.OEMStringPtr));␊ |
81 | ␉␊ |
82 | ␉// Loop through the mode list, and find the matching mode.␊ |
83 | ␉␊ |
84 | for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );␊ |
85 | ␉␉ *modePtr != modeEndOfList; modePtr++ )␊ |
86 | {␊ |
87 | // Get mode information.␊ |
88 | ␉␉␊ |
89 | bzero( &modeInfo, sizeof(modeInfo) );␊ |
90 | err = getVBEModeInfo( *modePtr, &modeInfo );␊ |
91 | if ( err != errSuccess )␊ |
92 | {␊ |
93 | continue;␊ |
94 | }␊ |
95 | ␉␉␊ |
96 | printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",␊ |
97 | *modePtr, modeInfo.XResolution, modeInfo.YResolution,␊ |
98 | modeInfo.BitsPerPixel, modeInfo.MemoryModel,␊ |
99 | modeInfo.ModeAttributes);␊ |
100 | ␉␉␊ |
101 | if (line++ >= 20) {␊ |
102 | pause();␊ |
103 | line = 0;␊ |
104 | clearScreenRows(0, 24);␊ |
105 | setCursorPosition( 0, 0, 1 );␊ |
106 | }␊ |
107 | } ␊ |
108 | if (line != 0) {␊ |
109 | pause();␊ |
110 | }␊ |
111 | setActiveDisplayPage(0);␊ |
112 | }␊ |
113 | ␊ |
114 | ␊ |
115 | ␊ |
116 | char *getVBEModeInfoString()␊ |
117 | {␊ |
118 | ␉VBEInfoBlock vbeInfo;␊ |
119 | unsigned short * modePtr;␊ |
120 | VBEModeInfoBlock modeInfo;␊ |
121 | int err;␊ |
122 | ␉␊ |
123 | ␉bzero( &vbeInfo, sizeof(vbeInfo) );␊ |
124 | strcpy( (char*)&vbeInfo, "VBE2" );␊ |
125 | err = getVBEInfo( &vbeInfo );␊ |
126 | if ( err != errSuccess )␊ |
127 | return 0;␊ |
128 | ␉␊ |
129 | ␉char *buff=malloc(sizeof(char)*3072);␊ |
130 | ␉if(!buff) return 0;␊ |
131 | ␉␊ |
132 | ␉// Loop through the mode list, and find the matching mode.␊ |
133 | for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );␊ |
134 | ␉␉ *modePtr != modeEndOfList; modePtr++ )␊ |
135 | {␊ |
136 | // Get mode information.␊ |
137 | ␉␉␊ |
138 | bzero( &modeInfo, sizeof(modeInfo) );␊ |
139 | err = getVBEModeInfo( *modePtr, &modeInfo );␊ |
140 | if ( err != errSuccess )␊ |
141 | {␊ |
142 | continue;␊ |
143 | }␊ |
144 | ␉␉␊ |
145 | sprintf(buff+strlen(buff), "Mode %x: %dx%dx%d mm:%d attr:%x\n",␊ |
146 | ␉␉␉␉*modePtr, modeInfo.XResolution, modeInfo.YResolution,␊ |
147 | ␉␉␉␉modeInfo.BitsPerPixel, modeInfo.MemoryModel,␊ |
148 | ␉␉␉␉modeInfo.ModeAttributes);␊ |
149 | ␉␉␊ |
150 | } ␊ |
151 | ␉return buff;␊ |
152 | }␊ |
153 | ␊ |
154 | ␊ |
155 | void blendImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height,␊ |
156 | ␉␉␉␉uint8_t *data)␊ |
157 | {␊ |
158 | uint16_t drawWidth;␊ |
159 | uint8_t *vram = (uint8_t *) VIDEO(baseAddr) + VIDEO(rowBytes) * y + 4 * x;␊ |
160 | ␉␊ |
161 | drawWidth = MIN(width, VIDEO(width) - x);␊ |
162 | height = MIN(height, VIDEO(height) - y);␊ |
163 | while (height--) {␊ |
164 | ␉␉switch (VIDEO (depth))␊ |
165 | ␉␉{␊ |
166 | ␉␉␉case 32: /* Optimized version*/␊ |
167 | ␉␉␉{␊ |
168 | ␉␉␉␉uint32_t s; uint32_t* d; // Source (img) and destination (bkgd) pixels␊ |
169 | ␉␉␉␉uint32_t a; // Alpha␊ |
170 | ␉␉␉␉uint32_t dstrb, dstg, srcrb, srcg, drb, dg, rb, g, tempB; // Intermediate variables␊ |
171 | ␉␉␉␉uint16_t pos;␊ |
172 | ␉␉␉␉␊ |
173 | ␉␉␉␉for (pos = 0; pos < drawWidth * 4; pos += 4) {␊ |
174 | ␉␉␉␉␉// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html␊ |
175 | ␉␉␉␉␉s = *((uint32_t*) (data + pos));␊ |
176 | ␉␉␉␉␉d = (uint32_t*) (vram + pos);␊ |
177 | ␉␉␉␉␉␊ |
178 | ␉␉␉␉␉// Flip B and R in source␊ |
179 | ␉␉␉␉␉// TODO: use XCHG and inline assembly to do this in a faster, saner way␊ |
180 | ␉␉␉␉␉tempB = (s & 0xFF0000); // save B␊ |
181 | ␉␉␉␉␉s = (s & 0xFF00FFFF) | ((s & 0xFF) << 16); // put R in B␊ |
182 | ␉␉␉␉␉s = (s & 0xFFFFFF00) | (tempB >> 16); // put B in R␊ |
183 | ␉␉␉␉␉␊ |
184 | ␉␉␉␉␉a = (s >> 24) + 1;␊ |
185 | ␉␉␉␉␉␊ |
186 | ␉␉␉␉␉dstrb = *d & 0xFF00FF; dstg = *d & 0xFF00;␊ |
187 | ␉␉␉␉␉srcrb = s & 0xFF00FF; srcg = s & 0xFF00;␊ |
188 | ␉␉␉␉␉␊ |
189 | ␉␉␉␉␉drb = srcrb - dstrb;␊ |
190 | ␉␉␉␉␉dg = srcg - dstg;␊ |
191 | ␉␉␉␉␉drb *= a; dg *= a;␊ |
192 | ␉␉␉␉␉drb >>= 8; dg >>= 8;␊ |
193 | ␉␉␉␉␉␊ |
194 | ␉␉␉␉␉rb = (drb + dstrb) & 0xFF00FF;␊ |
195 | ␉␉␉␉␉g = (dg + dstg) & 0xFF00;␊ |
196 | ␉␉␉␉␉␊ |
197 | ␉␉␉␉␉*d = rb | g;␊ |
198 | ␉␉␉␉}␊ |
199 | ␉␉␉}␊ |
200 | ␉␉␉␉break;␊ |
201 | ␉␉␉␉␊ |
202 | ␉␉␉default: /*Universal version*/␊ |
203 | ␉␉␉{␊ |
204 | ␉␉␉␉uint32_t s; ␊ |
205 | ␉␉␉␉uint32_t a; // Alpha␊ |
206 | ␉␉␉␉uint32_t dr, dg, db, sr, sg, sb; // Intermediate variables␊ |
207 | ␉␉␉␉uint16_t pos;␊ |
208 | ␉␉␉␉int bpp = (VIDEO (depth) + 7)/8;␊ |
209 | ␉␉␉␉␊ |
210 | ␉␉␉␉for (pos = 0; pos < drawWidth; pos ++) {␊ |
211 | ␉␉␉␉␉// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html␊ |
212 | ␉␉␉␉␉s = *((uint32_t*) (data + 4*pos));␊ |
213 | ␉␉␉␉␉␊ |
214 | ␉␉␉␉␉sb = (s & 0xFF0000) >> 16;␊ |
215 | ␉␉␉␉␉sg = (s & 0xFF00) >> 8;␊ |
216 | ␉␉␉␉␉sr = (s & 0xFF);␊ |
217 | ␉␉␉␉␉␊ |
218 | ␉␉␉␉␉a = (s >> 24) + 1;␊ |
219 | ␉␉␉␉␉␊ |
220 | ␉␉␉␉␉switch (VIDEO (depth))␊ |
221 | ␉␉␉␉␉{␊ |
222 | ␉␉␉␉␉␉case 24:␊ |
223 | ␉␉␉␉␉␉␉db = ((*(uint32_t *)(vram + bpp*pos))&0xff);␊ |
224 | ␉␉␉␉␉␉␉dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8;␊ |
225 | ␉␉␉␉␉␉␉dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16;␊ |
226 | ␉␉␉␉␉␉␉break;␊ |
227 | ␉␉␉␉␉␉case 16://16-bit seems to be 15-bit␊ |
228 | ␉␉␉␉␉␉␉/*␉␉␉␉␉␉␉db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;␊ |
229 | ␉␉␉␉␉␉␉ dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3;␊ |
230 | ␉␉␉␉␉␉␉ dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8;␊ |
231 | ␉␉␉␉␉␉␉ break;␉␉␉␉␉␉␉*/␊ |
232 | ␉␉␉␉␉␉case 15:␊ |
233 | ␉␉␉␉␉␉␉db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;␊ |
234 | ␉␉␉␉␉␉␉dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2;␊ |
235 | ␉␉␉␉␉␉␉dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7;␊ |
236 | ␉␉␉␉␉␉␉break;␉␉␊ |
237 | ␉␉␉␉␉␉default:␊ |
238 | ␉␉␉␉␉␉␉return;␊ |
239 | ␉␉␉␉␉}␊ |
240 | ␉␉␉␉␉␊ |
241 | ␉␉␉␉␉dr = (((sr - dr) * a) >> 8) + dr;␊ |
242 | ␉␉␉␉␉dg = (((sg - dg) * a) >> 8) + dg;␊ |
243 | ␉␉␉␉␉db = (((sb - db) * a) >> 8) + db;␊ |
244 | ␉␉␉␉␉switch (VIDEO (depth))␊ |
245 | ␉␉␉␉␉{␊ |
246 | ␉␉␉␉␉␉case 24:␊ |
247 | ␉␉␉␉␉␉␉*(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000)␊ |
248 | ␉␉␉␉␉␉␉| (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16);␊ |
249 | ␉␉␉␉␉␉␉break;␊ |
250 | ␉␉␉␉␉␉case 16:␊ |
251 | ␉␉␉␉␉␉␉//␉␉␉␉␉␉␉*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8);␊ |
252 | ␉␉␉␉␉␉␉//␉␉␉␉␉␉␉break;␉␉␉␉␉␉␉␊ |
253 | ␉␉␉␉␉␉case 15:␊ |
254 | ␉␉␉␉␉␉␉*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7);␊ |
255 | ␉␉␉␉␉␉␉break;␉␉␉␉␉␉␉␉␉␉␉␉␉␉␊ |
256 | ␉␉␉␉␉}␊ |
257 | ␉␉␉␉␉␊ |
258 | ␉␉␉␉}␉␉␉␉␊ |
259 | ␉␉␉}␊ |
260 | ␉␉␉␉break;␊ |
261 | }␊ |
262 | vram += VIDEO(rowBytes);␊ |
263 | data += width * 4;␊ |
264 | }␊ |
265 | }␊ |
266 | ␊ |
267 | void drawCheckerBoard()␊ |
268 | {␊ |
269 | uint32_t *vram = (uint32_t *) VIDEO(baseAddr);␊ |
270 | uint16_t x, y;␊ |
271 | uint8_t color;␊ |
272 | ␉␊ |
273 | for (y = 0; y < VIDEO(height); y++, vram += VIDEO(width)) {␊ |
274 | for (x = 0; x < VIDEO(width); x++) {␊ |
275 | color = 204 + 51 * (((x / 8) % 2) == ((y / 8) % 2));␊ |
276 | vram[x] = (color << 16) | (color << 8) | color;␊ |
277 | }␊ |
278 | }␊ |
279 | }␊ |
280 | ␊ |
281 | ␊ |
282 | //==========================================================================␊ |
283 | // drawDataRectangle␊ |
284 | ␊ |
285 | void drawDataRectangle( unsigned short x,␊ |
286 | ␉␉␉␉␉ unsigned short y,␊ |
287 | ␉␉␉␉␉ unsigned short width,␊ |
288 | ␉␉␉␉␉ unsigned short height,␊ |
289 | ␉␉␉␉␉ unsigned char * data )␊ |
290 | {␊ |
291 | unsigned short drawWidth;␊ |
292 | long pixelBytes = VIDEO(depth) / 8;␊ |
293 | unsigned char * vram = (unsigned char *) VIDEO(baseAddr) +␊ |
294 | ␉VIDEO(rowBytes) * y + pixelBytes * x;␊ |
295 | ␉␊ |
296 | drawWidth = MIN(width, VIDEO(width) - x);␊ |
297 | height = MIN(height, VIDEO(height) - y);␊ |
298 | while ( height-- ) {␊ |
299 | bcopy( data, vram, drawWidth * pixelBytes );␊ |
300 | vram += VIDEO(rowBytes);␊ |
301 | data += width * pixelBytes;␊ |
302 | }␊ |
303 | }␊ |
304 | ␊ |
305 | ␊ |
306 | ␊ |
307 | void getGraphicModeParams(unsigned long params[]) {␊ |
308 | ␉␊ |
309 | ␉params[3] = 0;␊ |
310 | ␉␊ |
311 | ␉VBEModeInfoBlock minfo;␊ |
312 | ␉␊ |
313 | unsigned short vesaVersion;␊ |
314 | unsigned short mode = modeEndOfList;␊ |
315 | ␊ |
316 | ␉getNumberArrayFromProperty( kGraphicsModeKey, params, 4);␊ |
317 | ␉␊ |
318 | ␉mode = getVESAModeWithProperties( params[0], params[1], params[2],␊ |
319 | ␉␉␉␉␉␉␉␉␉ maColorModeBit |␊ |
320 | ␉␉␉␉␉␉␉␉␉ maModeIsSupportedBit |␊ |
321 | ␉␉␉␉␉␉␉␉␉ maGraphicsModeBit |␊ |
322 | ␉␉␉␉␉␉␉␉␉ maLinearFrameBufferAvailBit,␊ |
323 | ␉␉␉␉␉␉␉␉␉ 0,␊ |
324 | ␉␉␉␉␉␉␉␉␉ &minfo, &vesaVersion );␊ |
325 | ␉␊ |
326 | ␉params[0] = minfo.XResolution;␊ |
327 | ␉params[1] = minfo.YResolution;␊ |
328 | ␉params[2] = 32;␊ |
329 | }␊ |
330 | ␊ |
331 | ␊ |
332 | //==========================================================================␊ |
333 | // getVBEInfoString␊ |
334 | ␊ |
335 | char *getVBEInfoString()␊ |
336 | {␊ |
337 | ␉VBEInfoBlock vbeInfo;␊ |
338 | ␉int err, small;␊ |
339 | ␉char *buff = malloc(sizeof(char)*256);␊ |
340 | ␉if(!buff) return 0;␊ |
341 | ␉␊ |
342 | ␉bzero( &vbeInfo, sizeof(vbeInfo) );␊ |
343 | ␉strcpy( (char*)&vbeInfo, "VBE2" );␊ |
344 | ␉err = getVBEInfo( &vbeInfo );␊ |
345 | ␉if (err != errSuccess)␊ |
346 | ␉␉return 0;␊ |
347 | ␉␊ |
348 | ␉if ( strncmp( (char *)vbeInfo.VESASignature, "VESA", 4 ) )␊ |
349 | ␉␉return 0;␊ |
350 | ␉␊ |
351 | ␉small = (vbeInfo.TotalMemory < 16);␊ |
352 | ␉␊ |
353 | ␉sprintf(buff, "VESA v%d.%d %d%s (%s)\n",␊ |
354 | ␉␉␉vbeInfo.VESAVersion >> 8,␊ |
355 | ␉␉␉vbeInfo.VESAVersion & 0xf,␊ |
356 | ␉␉␉small ? (vbeInfo.TotalMemory * 64) : (vbeInfo.TotalMemory / 16),␊ |
357 | ␉␉␉small ? "KB" : "MB",␊ |
358 | ␉␉␉VBEDecodeFP(const char *, vbeInfo.OEMStringPtr) );␊ |
359 | ␉␊ |
360 | ␉return buff;␊ |
361 | }␊ |
362 | ␊ |
363 | ␊ |
364 | void blend( const pixmap_t *blendThis, // Source image␊ |
365 | ␉␉ pixmap_t *blendInto, // Dest image␊ |
366 | ␉␉ const position_t position) // Where to place the source image␊ |
367 | {␊ |
368 | uint16_t sx, sy, dx, dy;␊ |
369 | uint32_t dstrb, dstag, srcrb, srcag, drb, dag, rb, ag, alpha;␊ |
370 | ␉␊ |
371 | ␉uint16_t width = (blendThis->width + position.x < blendInto->width) ? blendThis->width: blendInto->width-position.x;␊ |
372 | ␉uint16_t height = (blendThis->height + position.y < blendInto->height) ? blendThis->height: blendInto->height-position.y;␊ |
373 | ␉␊ |
374 | for (dy = position.y, sy = 0; sy < height; dy++, sy++) ␊ |
375 | ␉{␊ |
376 | for (dx = position.x, sx = 0; sx < width; dx++, sx++) ␊ |
377 | ␉␉{␊ |
378 | alpha = (pixel(blendThis, sx, sy).ch.a);␊ |
379 | ␉␉␉␊ |
380 | ␉␉␉/* Skip blending for fully transparent pixel */␊ |
381 | ␉␉␉if (alpha == 0) continue;␊ |
382 | ␉␉␉␊ |
383 | ␉␉␉/* For fully opaque pixel, there is no need to interpolate */␊ |
384 | ␉␉␉if (alpha == 255)␊ |
385 | ␉␉␉{␊ |
386 | ␉␉␉␉pixel(blendInto, dx, dy).value = pixel(blendThis, sx, sy).value;␊ |
387 | ␉␉␉␉continue;␊ |
388 | ␉␉␉}␊ |
389 | ␉␉␉␊ |
390 | ␉␉␉/* For semi-transparent pixels, do a full blend */␊ |
391 | ␉␉␉//alpha++␊ |
392 | ␉␉␉/* This is needed to spread the alpha over [0..256] instead of [0..255]␊ |
393 | ␉␉␉ Boundary conditions were handled above */␊ |
394 | dstrb = pixel(blendInto, dx, dy).value & 0xFF00FF;␊ |
395 | dstag = (pixel(blendInto, dx, dy).value >> 8) & 0xFF00FF;␊ |
396 | srcrb = pixel(blendThis, sx, sy).value & 0xFF00FF;␊ |
397 | srcag = (pixel(blendThis, sx, sy).value >> 8) & 0xFF00FF;␊ |
398 | drb = srcrb - dstrb;␊ |
399 | dag = srcag - dstag;␊ |
400 | drb *= alpha; dag *= alpha;␊ |
401 | drb >>= 8; dag >>= 8;␊ |
402 | rb = (drb + dstrb) & 0x00FF00FF;␊ |
403 | ag = ((dag + dstag) << 8) & 0xFF00FF00;␊ |
404 | pixel(blendInto, dx, dy).value = (rb | ag);␊ |
405 | }␊ |
406 | }␊ |
407 | }␊ |
408 | ␊ |
409 | position_t centeredIn( const pixmap_t *background, const pixmap_t *toCenter )␊ |
410 | {␊ |
411 | position_t centered;␊ |
412 | centered.x = ( background->width - toCenter->width ) / 2;␊ |
413 | centered.y = ( background->height - toCenter->height ) / 2;␊ |
414 | return centered;␊ |
415 | }␊ |
416 | ␊ |
417 | position_t centeredAt( const pixmap_t *pixmap, const position_t center )␊ |
418 | {␊ |
419 | position_t topleft;␊ |
420 | topleft.x = center.x - (pixmap->width / 2);␊ |
421 | topleft.y = center.y - (pixmap->height / 2);␊ |
422 | return topleft;␊ |
423 | }␊ |
424 | ␊ |
425 | position_t pos(const uint16_t x, const uint16_t y) { position_t p; p.x = x; p.y = y; return p; }␊ |
426 | ␊ |
427 | void flipRB(pixmap_t *p)␊ |
428 | {␊ |
429 | ␉//if(testForQemu()) return;␊ |
430 | ␉␊ |
431 | ␉uint32_t x;␊ |
432 | register uint8_t tempB;␊ |
433 | ␉for (x = 0; x < (p->height) * (p->width) ; x++) {␊ |
434 | ␉␉tempB = (p->pixels[x]).ch.b;␊ |
435 | (p->pixels[x]).ch.b = (p->pixels[x]).ch.r;␊ |
436 | (p->pixels[x]).ch.r = tempB;␊ |
437 | ␉}␊ |
438 | }␊ |
439 |