1 // EmuScan routines for Pico, also simple text and shape drawing routines.
\r
3 // (c) Copyright 2006, notaz
\r
4 // All Rights Reserved
\r
7 #include "ClientServer.h"
\r
8 #include "SimpleServer.h"
\r
9 #include "pico\picoInt.h"
\r
14 extern TPicoConfig currentConfig;
\r
15 extern TPicoKeyConfigEntry *keyConfig;
\r
16 extern TPicoAreaConfigEntry areaConfig[];
\r
17 extern const char * actionNames[];
\r
20 static void *screenbuff = 0; // pointer to real device video memory
\r
22 unsigned short *framebuff = 0; // temporary buffer in sega native BGR format
\r
23 const int framebuffsize = (8+320)*(8+208+8)*2; // actual framebuffer size (in bytes+to support new rendering mode)
\r
24 static int framebuff_offs = 0; // where to start copying (in pixels)
\r
25 static int framebuff_len = 0; // how much of the framebuffer actually needs to be copied (in pixels)
\r
26 static int fc_lines, fc_inc; // lines, inc for "0 fit2" mode
\r
28 // drawer function pointers
\r
29 void (*drawTextFps)(const char *text) = 0;
\r
30 void (*drawTextNotice)(const char *text) = 0;
\r
33 void (*vidBlit)(int full) = 0;
\r
34 void (*vidBlitKeyCfg)(int full) = 0;
\r
36 // stuff for rendermode2
\r
37 static unsigned short cram_high[0x40];
\r
38 static unsigned short dt_dmask=0x0333;
\r
39 unsigned short color_redM2 = 0x022F;
\r
42 const unsigned short color_red = 0x022F;
\r
43 const unsigned short color_red_dim = 0x0004;
\r
44 const unsigned short color_green = 0x01F1;
\r
45 const unsigned short color_blue = 0x0F11;
\r
46 const unsigned short color_grey = 0x0222;
\r
49 int txtheight_fit = 138;
\r
52 static const unsigned long mask_numbers[] = {
\r
53 0x12244800, // 47 2F /
\r
54 0x69999600, // 48 30 0
\r
55 0x26222200, // 49 31 1
\r
56 0x69168F00, // 50 32 2
\r
57 0x69219600, // 51 33 3
\r
58 0x266AF200, // 52 34 4
\r
59 0xF8E11E00, // 53 35 5
\r
60 0x68E99600, // 54 36 6
\r
61 0x71222200, // 55 37 7
\r
62 0x69699600, // 56 38 8
\r
63 0x69719600, // 57 39 9
\r
64 0x04004000, // 58 3A :
\r
65 0x04004400, // 59 3B ;
\r
66 0x01242100, // 60 3C <
\r
67 0x00707000, // 61 3D =
\r
68 0x04212400, // 62 3E >
\r
69 0x69240400, // 63 3F ?
\r
70 0x00000000, // 64 40 @ [used instead of space for now]
\r
71 0x22579900, // 65 41 A
\r
72 0xE9E99E00, // 66 42 B
\r
73 0x69889600, // 67 43 C
\r
74 0xE9999E00, // 68 44 D
\r
75 0xF8E88F00, // 69 45 E
\r
76 0xF8E88800, // 70 46 F
\r
77 0x698B9700, // 71 47 G
\r
78 0x99F99900, // 72 48 H
\r
79 0x44444400, // 73 49 I
\r
80 0x11119600, // 74 4A J
\r
81 0x9ACCA900, // 75 4B K
\r
82 0x88888F00, // 76 4C L
\r
83 0x9F999900, // 77 4D M
\r
84 0x9DDBB900, // 78 4E N
\r
85 0x69999600, // 79 4F O
\r
86 0xE99E8800, // 80 50 P
\r
87 0x6999A500, // 81 51 Q
\r
88 0xE99E9900, // 82 52 R
\r
89 0x69429600, // 83 53 S
\r
90 0x72222200, // 84 54 T
\r
91 0x99999600, // 85 55 U
\r
92 0x55552200, // 86 56 V
\r
93 0x9999F900, // 87 57 W
\r
94 0x55225500, // 88 58 X
\r
95 0x55222200, // 89 59 Y
\r
96 0xF1248F00, // 90 5A Z
\r
100 ////////////////////////////////
\r
103 inline int EmuCramNull(int cram)
\r
105 User::Panic(_L("Cram called!!"), 0);
\r
110 ////////////////////////////////
\r
111 // PicoScan functions in "center" mode
\r
113 int EmuScanCenter0(unsigned int num, unsigned short *sdata)
\r
115 //unsigned short *vidmem=framebuff;
\r
117 //unsigned short *sp, *sto;
\r
118 //sp=sdata+56; sto=sdata+264; vidmem += num*208;
\r
120 //do { *vidmem++ = *sp++; } while(sp < sto);
\r
121 memcpy(framebuff + num*208, sdata+56, 208*2); // memcpy gives ~1 fps (~2 with optimized memcpy)
\r
127 int EmuScanCenter90(unsigned int num, unsigned short *sdata)
\r
129 // ignore top and bottom lines
\r
130 if(num < 8) return 7-num; // skip first 8 lines
\r
131 if(num > 215) return 223+8-num; // this should not happen, just in case
\r
135 if(Pico.video.reg[12]&1) { // copy less in 32-col mode
\r
137 framebuff_len = 208*320;
\r
139 framebuff_offs= 208*32;
\r
140 framebuff_len = 208*256;
\r
144 unsigned short *vidmem=framebuff;
\r
145 vidmem += 207-num; // adjust x
\r
147 // do less copy in 32-column mode
\r
148 unsigned short *sp, *sto;
\r
150 if(!(Pico.video.reg[12]&1))
\r
151 { sp=sdata+32; sto=sdata+288; pixels = 288; vidmem += 32*208; }
\r
152 else { sp=sdata; sto=sdata+320; pixels = 320; }
\r
154 do { *vidmem = *sp++; vidmem+=208; } while(sp < sto);
\r
156 if(num == 207) return 16; // skip bottom of this frame and top of next
\r
162 int EmuScanCenter180(unsigned int num, unsigned short *sdata)
\r
164 unsigned short *vidmem=framebuff;
\r
166 unsigned short *sp, *sto;
\r
167 sp=sdata+56; sto=sdata+264; vidmem += (224-num)*208;
\r
169 do { *(--vidmem) = *sp++; } while(sp < sto); // reversed
\r
175 int EmuScanCenter270(unsigned int num, unsigned short *sdata)
\r
177 // ignore top and bottom lines
\r
178 if(num < 8) return 7-num; // skip first 8 lines
\r
179 if(num > 215) return 223-num+8;
\r
182 if(num > 207) return 0;
\r
184 if(Pico.video.reg[12]&1) {
\r
186 framebuff_len = 208*320;
\r
188 framebuff_offs= 208*32;
\r
189 framebuff_len = 208*256;
\r
193 unsigned short *vidmem=framebuff+320*208;
\r
194 vidmem -= 208-num; // adjust x
\r
196 // do less copy in 32-column mode
\r
197 unsigned short *sp, *sto;
\r
198 if(!(Pico.video.reg[12]&1))
\r
199 { sp=sdata+32; sto=sdata+288; vidmem -= 32*208; }
\r
200 else { sp=sdata; sto=sdata+320; }
\r
202 do { *vidmem = *sp++; vidmem-=208; } while(sp < sto);
\r
204 if(num == 207) return 16; // skip bottom of this frame and top of next
\r
211 ////////////////////////////////
\r
212 // PicoScan functions in "fit" mode
\r
214 static int EmuScanFit0(unsigned int num, unsigned short *sdata)
\r
216 // 0.65, 145 lines in normal mode; 0.8125, 182 lines in 32-column mode
\r
218 // draw this line? (ARM4s don't support division, so do some tricks here)
\r
219 static int u = 0, num2 = 0;
\r
222 if(currentConfig.iScreenMode == TPicoConfig::PMFit) {
\r
223 if(Pico.video.reg[12]&1) { // 32 col mode? This can change on any frame
\r
225 txtheight_fit = 138;
\r
226 framebuff_len = 208*145;
\r
227 memset(framebuff+208*145, 0, 208*37*2);
\r
230 txtheight_fit = 175;
\r
231 framebuff_len = 208*182;
\r
236 if(u < 10000) return 0;
\r
239 unsigned short *vidmem=framebuff;
\r
242 unsigned short *sp;
\r
243 if(!(Pico.video.reg[12]&1))
\r
244 { sp=sdata+32; slen=256; }
\r
245 else { sp=sdata; slen=320; }
\r
247 vidmem += num2*208;
\r
259 PicuShrink(vidmem, 208, sp, slen);
\r
263 // calculate how many lines pico engine should skip,
\r
264 // making sure this func will be called on scanline 0
\r
266 while(u+fc_inc < 10000 && num+skip != 223) { u+=fc_inc; skip++; }
\r
271 int EmuScanFit90(unsigned int num, unsigned short *sdata)
\r
276 static int u = 0, num2 = 0;
\r
279 if(Pico.video.reg[12]&1) {
\r
281 framebuff_len = 208*320;
\r
283 framebuff_offs= 208*32;
\r
284 framebuff_len = 208*256;
\r
288 if(u < 10000) return 0;
\r
291 unsigned short *vidmem=framebuff;
\r
292 vidmem += 207-num2; // adjust x
\r
294 // do less copy in 32-column mode
\r
295 unsigned short *sp, *sto;
\r
296 if(!(Pico.video.reg[12]&1))
\r
297 { sp=sdata+32; sto=sdata+288; vidmem += 32*208; }
\r
298 else { sp=sdata; sto=sdata+320; }
\r
300 do { *vidmem = *sp++; vidmem+=208; } while(sp < sto);
\r
305 if(u+9285 < 10000 && num != 223) { u+=9285; return 1; }
\r
310 int EmuScanFit180(unsigned int num, unsigned short *sdata)
\r
312 // 0.65, 145 lines in normal mode; 0.8125, 182 lines in 32-column mode
\r
314 // draw this line? (ARM4s don't support division)
\r
315 static int u = 0, num2 = 0;
\r
318 if(currentConfig.iScreenMode == TPicoConfig::PMFit) {
\r
319 if(Pico.video.reg[12]&1) { // 32 col mode? This can change on any frame
\r
322 txtheight_fit = 138;
\r
323 framebuff_len = 208*145;
\r
324 memset(framebuff+208*145, 0, 208*37*2);
\r
328 txtheight_fit = 175;
\r
329 framebuff_len = 208*182;
\r
334 if(u < 10000) return 0;
\r
337 unsigned short *vidmem=framebuff;
\r
340 unsigned short *sp;
\r
341 if(!(Pico.video.reg[12]&1))
\r
342 { sp=sdata+32; slen=256; }
\r
343 else { sp=sdata; slen=320; }
\r
345 vidmem += (fc_lines-num2)*208;
\r
347 PicuShrinkReverse(vidmem, 208, sp, slen);
\r
351 // skip some lines?
\r
353 while(u+fc_inc < 10000 && num+skip != 223) { u+=fc_inc; skip++; }
\r
358 int EmuScanFit270(unsigned int num, unsigned short *sdata)
\r
363 static int u = 0, num2 = 0;
\r
366 if(Pico.video.reg[12]&1) {
\r
368 framebuff_len = 208*320;
\r
370 framebuff_offs= 208*32;
\r
371 framebuff_len = 208*256;
\r
375 if(u < 10000) return 0;
\r
378 unsigned short *vidmem=framebuff+320*208;
\r
379 vidmem -= 208-num2; // adjust x
\r
381 // do less copy in 32-column mode
\r
382 unsigned short *sp, *sto;
\r
383 if(!(Pico.video.reg[12]&1))
\r
384 { sp=sdata+32; sto=sdata+288; vidmem -= 32*208; }
\r
385 else { sp=sdata; sto=sdata+320; }
\r
387 do { *vidmem = *sp++; vidmem-=208; } while(sp < sto);
\r
392 if(u+9285 < 10000 && num != 223) { u+=9285; return 1; }
\r
398 ////////////////////////////////
\r
400 // warning: text must be at least 1px away from screen borders
\r
402 void drawTextM2(int x, int y, const char *text, long color)
\r
404 unsigned short *vidmem=framebuff;
\r
405 int charmask, i, cx = x, cy;
\r
406 unsigned short *l, *le;
\r
408 // darken the background (left border)
\r
409 for(l=vidmem+(cx-1)+(y-1)*328, le=vidmem+(cx-1)+(y+7)*328; l < le; l+=328)
\r
410 *l = (*l >> 2) & dt_dmask;
\r
412 for(const char *p=text; *p; p++) {
\r
414 charmask = *(mask_numbers + (*p - 0x2F));
\r
416 for(l = vidmem+cx+(y-1)*328, le = vidmem+cx+(y+7)*328; l < le; l+=328-4) {
\r
417 *l = (*l >> 2) & dt_dmask; l++; *l = (*l >> 2) & dt_dmask; l++;
\r
418 *l = (*l >> 2) & dt_dmask; l++; *l = (*l >> 2) & dt_dmask; l++;
\r
419 *l = (*l >> 2) & dt_dmask;
\r
422 for(i=0; i < 24; i++) {
\r
423 // draw dot. Is this fast?
\r
424 if(charmask&0x80000000) *( vidmem + (cx+(i&3)) + (cy+(i>>2))*328 ) = color;
\r
431 void drawText0(int x, int y, const char *text, long color)
\r
433 unsigned short *vidmem=framebuff;
\r
434 int charmask, i, cx = x, cy;
\r
435 unsigned short *l, *le, dmask=0x0333;
\r
437 // darken the background (left border)
\r
438 for(l=vidmem+(cx-1)+(y-1)*208, le=vidmem+(cx-1)+(y+7)*208; l < le; l+=208)
\r
439 *l = (*l >> 2) & dmask;
\r
441 for(const char *p=text; *p; p++) {
\r
443 charmask = *(mask_numbers + (*p - 0x2F));
\r
445 for(l = vidmem+cx+(y-1)*208, le = vidmem+cx+(y+7)*208; l < le; l+=208-4) {
\r
446 *l = (*l >> 2) & dmask; l++; *l = (*l >> 2) & dmask; l++;
\r
447 *l = (*l >> 2) & dmask; l++; *l = (*l >> 2) & dmask; l++;
\r
448 *l = (*l >> 2) & dmask;
\r
451 for(i=0; i < 24; i++) {
\r
452 // draw dot. Is this fast?
\r
453 if(charmask&0x80000000) *( vidmem + (cx+(i&3)) + (cy+(i>>2))*208 ) = color;
\r
460 void drawText90(int x, int y, const char *text, long color)
\r
462 unsigned short *vidmem=framebuff;
\r
463 unsigned short *l, *le, dmask=0x0333;
\r
464 int charmask, i, cx, cy = y;
\r
466 for(l=vidmem+(x+1)+(cy-1)*208, le=vidmem+(x-7)+(cy-1)*208; l > le; l--)
\r
467 *l = (*l >> 2) & dmask;
\r
469 for(const char *p=text; *p; p++) {
\r
471 charmask = *(mask_numbers + (*p - 0x2F));
\r
473 for(l = vidmem+(x+1)+(cy)*208, le = vidmem+(x+1)+(cy+5)*208; l < le; l+=208+7) {
\r
474 *l = (*l >> 2) & dmask; l--; *l = (*l >> 2) & dmask; l--;
\r
475 *l = (*l >> 2) & dmask; l--; *l = (*l >> 2) & dmask; l--;
\r
476 *l = (*l >> 2) & dmask; l--; *l = (*l >> 2) & dmask; l--;
\r
477 *l = (*l >> 2) & dmask; l--; *l = (*l >> 2) & dmask;
\r
480 for(i=0; i < 24; i++) {
\r
481 if(charmask&0x80000000) *( vidmem + (cy+(i&3))*208 + (cx-(i>>2)) ) = color;
\r
488 void drawText180(int x, int y, const char *text, long color)
\r
490 unsigned short *vidmem=framebuff;
\r
491 int charmask, i, cx = x, cy;
\r
492 unsigned short *l, *le, dmask=0x0333;
\r
494 for(l=vidmem+(cx+1)+(y+1)*208, le=vidmem+(cx+1)+(y-7)*208; l > le; l-=208)
\r
495 *l = (*l >> 2) & dmask;
\r
497 for(const char *p=text; *p; p++) {
\r
499 charmask = *(mask_numbers + (*p - 0x2F));
\r
501 for(l = vidmem+cx+(y+1)*208, le = vidmem+cx+(y-8)*208; l > le; l-=208-4) {
\r
502 *l = (*l >> 2) & dmask; l--; *l = (*l >> 2) & dmask; l--;
\r
503 *l = (*l >> 2) & dmask; l--; *l = (*l >> 2) & dmask; l--;
\r
504 *l = (*l >> 2) & dmask;
\r
507 for(i=0; i < 24; i++) {
\r
508 if(charmask&0x80000000) *( vidmem + (cx-(i&3)) + (cy-(i>>2))*208 ) = color;
\r
515 void drawText270(int x, int y, const char *text, long color)
\r
517 unsigned short *vidmem=framebuff;
\r
518 int charmask, i, cx, cy = y;
\r
519 unsigned short *l, *le, dmask=0x0333;
\r
521 for(l=vidmem+(x-1)+(cy+1)*208, le=vidmem+(x+7)+(cy+1)*208; l < le; l++)
\r
522 *l = (*l >> 2) & dmask;
\r
524 for(const char *p=text; *p; p++) {
\r
526 charmask = *(mask_numbers + (*p - 0x2F));
\r
528 for(l = vidmem+(x-1)+(cy)*208, le = vidmem+(x-1)+(cy-5)*208; l > le; l-=208+7) {
\r
529 *l = (*l >> 2) & dmask; l++; *l = (*l >> 2) & dmask; l++;
\r
530 *l = (*l >> 2) & dmask; l++; *l = (*l >> 2) & dmask; l++;
\r
531 *l = (*l >> 2) & dmask; l++; *l = (*l >> 2) & dmask; l++;
\r
532 *l = (*l >> 2) & dmask; l++; *l = (*l >> 2) & dmask;
\r
535 for(i=0; i < 24; i++) {
\r
536 if(charmask&0x80000000) *( vidmem + (cy-(i&3))*208 + (cx+(i>>2)) ) = color;
\r
543 void drawTextFpsM2(const char *text)
\r
546 drawTextM2((Pico.video.reg[12]&1) ? 256 : 224, 200, text, color_redM2);
\r
549 void drawTextFps0(const char *text)
\r
552 drawText0(176, 216, text, color_red);
\r
555 void drawTextFpsFit0(const char *text)
\r
558 drawText0(176, txtheight_fit, text, color_red);
\r
561 void drawTextFps90(const char *text)
\r
564 drawText90(10, 256, text, color_red);
\r
567 void drawTextFps180(const char *text)
\r
570 drawText180(32, 8, text, color_red);
\r
573 void drawTextFps270(const char *text)
\r
576 drawText270(200, 64, text, color_red);
\r
579 void drawTextNoticeM2(const char *text)
\r
582 drawTextM2(20, 200, text, color_redM2);
\r
585 void drawTextNotice0(const char *text)
\r
588 drawText0(2, 216, text, color_red);
\r
591 void drawTextNoticeFit0(const char *text)
\r
594 drawText0(2, txtheight_fit, text, color_red);
\r
597 void drawTextNotice90(const char *text)
\r
600 drawText90(10, 34, text, color_red);
\r
603 void drawTextNotice180(const char *text)
\r
606 drawText180(206, 8, text, color_red);
\r
609 void drawTextNotice270(const char *text)
\r
612 drawText270(200, 286, text, color_red);
\r
616 ////////////////////////////////
\r
619 // draws rect with width - 1 and height - 1
\r
620 void drawRect(const TRect &rc, unsigned short color)
\r
622 if(rc.iTl.iX - rc.iBr.iX && rc.iTl.iY - rc.iBr.iY) {
\r
623 int stepX = rc.iTl.iX < rc.iBr.iX ? 1 : -1;
\r
624 int stepY = rc.iTl.iY < rc.iBr.iY ? 1 : -1;
\r
626 for(int x = rc.iTl.iX;; x += stepX) {
\r
627 *(framebuff + rc.iTl.iY*208 + x) = *(framebuff + (rc.iBr.iY - stepY)*208 + x) = color;
\r
628 if(x == rc.iBr.iX - stepX) break;
\r
631 for(int y = rc.iTl.iY;; y += stepY) {
\r
632 *(framebuff + y*208 + rc.iTl.iX) = *(framebuff + y*208 + rc.iBr.iX - stepX) = color;
\r
633 if(y == rc.iBr.iY - stepY) break;
\r
638 // draws fullsize filled rect
\r
639 void drawRectFilled(const TRect rc, unsigned short color)
\r
641 if(rc.iTl.iX - rc.iBr.iX && rc.iTl.iY - rc.iBr.iY) {
\r
642 int stepX = rc.iTl.iX < rc.iBr.iX ? 1 : -1;
\r
643 int stepY = rc.iTl.iY < rc.iBr.iY ? 1 : -1;
\r
645 for(int y = rc.iTl.iY;; y += stepY) {
\r
646 for(int x = rc.iTl.iX;; x += stepX) {
\r
647 *(framebuff + y*208 + x) = *(framebuff + y*208 + x) = color;
\r
648 if(x == rc.iBr.iX) break;
\r
650 if(y == rc.iBr.iY) break;
\r
655 // direction: -1 left, 1 right
\r
656 void drawArrow0(TPoint p, int direction, unsigned short color)
\r
662 for(; width > 0; x+=direction, y++, width -=2)
\r
663 for(int i=0; i < width; i++)
\r
664 *(framebuff + x + y*208 + i*208) = color;
\r
667 void drawArrow90(TPoint p, int direction, unsigned short color)
\r
670 int x = p.iX - width;
\r
673 for(; width > 0; x++, y+=direction, width -=2)
\r
674 for(int i=0; i < width; i++)
\r
675 *(framebuff + x + y*208 + i) = color;
\r
679 // copies temporary framebuff to real device framebuffer
\r
680 void vidBlitRGB444(int full)
\r
682 unsigned short *ps;
\r
683 unsigned short *pd;
\r
687 pd = (unsigned short *) screenbuff;
\r
690 ps = framebuff + framebuff_offs;
\r
691 pd = (unsigned short *) screenbuff + framebuff_offs;
\r
692 pixels = framebuff_len;
\r
695 vidConvCpyRGB444(pd, ps, pixels);
\r
696 //for(unsigned short *ps_end = ps + pixels; ps < ps_end; ps++)
\r
697 // Convert 0000bbb0 ggg0rrr0
\r
698 // to 0000rrr0 ggg0bbb0
\r
699 // *pd++ = ((*ps&0x000F)<<8) | (*ps&0x00F0) | ((*ps&0x0F00)>>8);
\r
702 void vidBlitRGB565(int full)
\r
704 unsigned short *ps;
\r
705 unsigned short *pd;
\r
709 pd = (unsigned short *) screenbuff;
\r
712 ps = framebuff + framebuff_offs;
\r
713 pd = (unsigned short *) screenbuff + framebuff_offs;
\r
714 pixels = framebuff_len;
\r
717 vidConvCpyRGB565(pd, ps, pixels);
\r
718 //for(; ps < ps_end; ps++)
\r
719 // Convert 0000bbb0 ggg0rrr0
\r
720 // to rrr00ggg 000bbb00
\r
721 // *pd++ = ((*ps&0x000F)<<12) | ((*ps&0x00F0)<<3) | ((*ps&0x0F00)>>7);
\r
724 void vidBlitRGB32(int full)
\r
726 unsigned short *ps;
\r
731 pd = (unsigned long *) screenbuff;
\r
734 ps = framebuff + framebuff_offs;
\r
735 pd = (unsigned long *) screenbuff + framebuff_offs;
\r
736 pixels = framebuff_len;
\r
739 vidConvCpyRGB32(pd, ps, pixels);
\r
740 //for(; ps < ps_end; ps++)
\r
741 // Convert 0000bbb0 ggg0rrr0
\r
742 // to ..0 rrr00000 ggg00000 bbb00000
\r
743 // *pd++ = ((*ps&0x000F)<<20) | ((*ps&0x00F0)<<8) | ((*ps&0x0F00)>>4);
\r
746 // -------- rendermode 2 ---------
\r
748 void vidBlit16M2(int full)
\r
750 unsigned short *ps = framebuff+328*8;
\r
751 unsigned short *pd = (unsigned short *) screenbuff;
\r
753 if(currentConfig.iScreenRotation == TPicoConfig::PRot90) {
\r
754 if(Pico.video.reg[12]&1)
\r
755 vidConvCpyM2_16_90(pd, ps, 320/8);
\r
757 if(full) memset(pd, 0, 208*32*2);
\r
759 vidConvCpyM2_16_90(pd, ps, 256/8);
\r
760 if(full) memset(pd + 208*256, 0, 208*32*2);
\r
762 } else if(currentConfig.iScreenRotation == TPicoConfig::PRot270) {
\r
763 if(Pico.video.reg[12]&1)
\r
764 vidConvCpyM2_16_270(pd, ps, 320/8);
\r
766 if(full) memset(pd, 0, 208*32*2);
\r
768 ps -= 64; // the blitter starts copying from the right border, so we need to adjust
\r
769 vidConvCpyM2_16_270(pd, ps, 256/8);
\r
770 if(full) memset(pd + 208*256, 0, 208*32*2);
\r
774 for(int x=0; x < 320; x++)
\r
775 for(int y=207; y>=0; y--) {
\r
776 *pd++ = *(ps+8+x+y*328);
\r
781 void vidBlitRGB32M2(int full)
\r
783 unsigned short *ps = framebuff+328*8;
\r
784 unsigned long *pd = (unsigned long *) screenbuff;
\r
786 if(currentConfig.iScreenRotation == TPicoConfig::PRot90) {
\r
787 if(Pico.video.reg[12]&1)
\r
788 vidConvCpyM2_RGB32_90(pd, ps, 320/8);
\r
790 if(full) memset(pd, 0, 208*32*4);
\r
792 vidConvCpyM2_RGB32_90(pd, ps, 256/8);
\r
793 if(full) memset(pd + 208*256, 0, 208*32*4);
\r
795 } else if(currentConfig.iScreenRotation == TPicoConfig::PRot270) {
\r
796 if(Pico.video.reg[12]&1)
\r
797 vidConvCpyM2_RGB32_270(pd, ps, 320/8);
\r
799 if(full) memset(pd, 0, 208*32*4);
\r
801 ps -= 64; // the blitter starts copying from the right border, so we need to adjust
\r
802 vidConvCpyM2_RGB32_270(pd, ps, 256/8);
\r
803 if(full) memset(pd + 208*256, 0, 208*32*4);
\r
808 void PrepareCramRGB444M2()
\r
810 vidConvCpyRGB444(cram_high, Pico.cram, 0x40);
\r
813 void PrepareCramRGB565M2()
\r
815 vidConvCpyRGB565(cram_high, Pico.cram, 0x40);
\r
819 ////////////////////////////////
\r
822 int vidInit(int displayMode, void *vidmem, int p800, int reinit)
\r
825 // prepare framebuffer
\r
826 screenbuff = (unsigned short *) vidmem;
\r
827 framebuff = (unsigned short *) malloc(framebuffsize);
\r
829 if(!screenbuff) return KErrNotSupported;
\r
830 if(!framebuff) return KErrNoMemory;
\r
832 // Cram function: go and hack Pico so it never gets called
\r
833 PicoCram = EmuCramNull;
\r
836 // select suitable blitter
\r
837 switch(displayMode) {
\r
838 case EColor4K: vidBlit = vidBlitKeyCfg = vidBlitRGB444; break;
\r
839 case EColor64K: vidBlit = vidBlitKeyCfg = vidBlitRGB565; break;
\r
840 case EColor16M: vidBlit = vidBlitKeyCfg = vidBlitRGB32; break;
\r
841 default: return KErrNotSupported;
\r
844 memset(framebuff, 0, framebuffsize);
\r
848 switch(displayMode) {
\r
850 vidBlit = vidBlit16M2;
\r
851 PicoPrepareCram = PrepareCramRGB444M2;
\r
852 PicoCramHigh = cram_high;
\r
853 color_redM2 = 0x0F22;
\r
857 vidBlit = vidBlit16M2;
\r
858 PicoPrepareCram = PrepareCramRGB565M2;
\r
859 PicoCramHigh = cram_high;
\r
860 color_redM2 = 0xF882;
\r
864 vidBlit = vidBlitRGB32M2;
\r
867 drawTextFps = drawTextFpsM2;
\r
868 drawTextNotice = drawTextNoticeM2;
\r
873 framebuff_offs = 0;
\r
874 framebuff_len = 208*320;
\r
877 // setup all orientation related stuff
\r
878 if(currentConfig.iScreenRotation == TPicoConfig::PRot0) {
\r
879 if(currentConfig.iScreenMode == TPicoConfig::PMCenter) {
\r
880 PicoScan = EmuScanCenter0;
\r
881 framebuff_len = 208*224;
\r
882 drawTextFps = drawTextFps0;
\r
883 drawTextNotice = drawTextNotice0;
\r
885 if(currentConfig.iScreenMode == TPicoConfig::PMFit2) {
\r
887 fc_inc = 6518; // 0.651786 (144+2)
\r
888 txtheight_fit = 139;
\r
889 framebuff_len = 208*146;
\r
891 fc_inc = 9286; // 0.92857
\r
892 txtheight_fit = 201;
\r
893 framebuff_len = 208*208;
\r
896 PicoScan = EmuScanFit0;
\r
897 drawTextFps = drawTextFpsFit0;
\r
898 drawTextNotice = drawTextNoticeFit0;
\r
900 } else if(currentConfig.iScreenRotation == TPicoConfig::PRot90) {
\r
901 if(currentConfig.iScreenMode == TPicoConfig::PMFit)
\r
902 PicoScan = EmuScanFit90;
\r
903 else PicoScan = EmuScanCenter90;
\r
904 drawTextFps = drawTextFps90;
\r
905 drawTextNotice = drawTextNotice90;
\r
906 } else if(currentConfig.iScreenRotation == TPicoConfig::PRot180) {
\r
907 if(currentConfig.iScreenMode == TPicoConfig::PMCenter) {
\r
908 PicoScan = EmuScanCenter180;
\r
909 framebuff_len = 208*224;
\r
911 if(currentConfig.iScreenMode == TPicoConfig::PMFit2) {
\r
913 fc_inc = 6518; // 0.651786
\r
915 framebuff_len = 208*146;
\r
917 fc_inc = 9286; // 0.92857
\r
919 framebuff_len = 208*208;
\r
922 PicoScan = EmuScanFit180;
\r
924 drawTextFps = drawTextFps180;
\r
925 drawTextNotice = drawTextNotice180;
\r
926 } else if(currentConfig.iScreenRotation == TPicoConfig::PRot270) {
\r
927 if(currentConfig.iScreenMode == TPicoConfig::PMFit)
\r
928 PicoScan = EmuScanFit270;
\r
929 else PicoScan = EmuScanCenter270;
\r
930 drawTextFps = drawTextFps270;
\r
931 drawTextNotice = drawTextNotice270;
\r
943 void vidDrawFrame(char *noticeStr, char *fpsStr, int num)
\r
946 if(currentConfig.iFlags & 2)
\r
947 drawTextFps(fpsStr);
\r
948 drawTextNotice(noticeStr);
\r
950 vidBlit(!num); // copy full frame once a second
\r
953 void vidKeyConfigFrame(const TUint whichAction, TInt flipClosed)
\r
956 char buttonNames[128];
\r
957 buttonNames[0] = 0;
\r
958 memset(framebuff, 0, framebuffsize);
\r
960 unsigned long currentActCode = 1 << whichAction;
\r
963 drawRectFilled(TRect(56, 2, 152, 16), color_grey); // 96x14
\r
964 drawArrow0(TPoint(64, 3), -1, color_green);
\r
965 drawArrow0(TPoint(144, 3), 1, color_green);
\r
966 drawText0(64, 20, "USE@JOG@TO@SELECT", color_red);
\r
968 drawText0(68, 6, actionNames[whichAction], color_red);
\r
970 // draw all "buttons" in reverse order
\r
971 const TPicoAreaConfigEntry *e = areaConfig + 1; i = 0;
\r
972 while(e->rect != TRect(0,0,0,0)) { e++; i++; }
\r
973 for(e--, i--; e->rect != TRect(0,0,0,0); e--, i--)
\r
974 drawRect(e->rect, (currentConfig.iAreaBinds[i] & currentActCode) ? color_red : color_red_dim);
\r
976 // draw config controls
\r
977 drawRectFilled(TRect(190, 112, 204, 208), color_grey);
\r
978 drawArrow90(TPoint(203, 120), -1, color_green);
\r
979 drawArrow90(TPoint(203, 200), 1, color_green);
\r
981 drawText90(200, 124, actionNames[whichAction], color_red);
\r
984 // draw active button names if there are any
\r
986 for(TPicoKeyConfigEntry *e = keyConfig; e->name; e++, i++)
\r
987 if(currentConfig.iKeyBinds[i] & currentActCode) {
\r
988 if(buttonNames[0]) strcat(buttonNames, ";@");
\r
989 strcat(buttonNames, e->name);
\r
991 if(buttonNames[0]) {
\r
993 buttonNames[41] = 0; // only 61 chars fit
\r
994 drawText0(2, 138, buttonNames, color_blue);
\r
996 buttonNames[61] = 0;
\r
997 drawText90(12, 10, buttonNames, color_blue);
\r
1004 void vidDrawFCconfigDone()
\r
1006 drawText0(64, 20, "USE@JOG@TO@SELECT", 0); // blank prev text
\r
1007 drawText0(54, 30, "OPEN@FLIP@TO@CONTINUE", color_red);
\r
1011 void vidDrawNotice(const char *txt)
\r
1014 drawTextNotice(txt);
\r