lfb.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright (C) 2018 bzt (bztsrc@github)
  3. *
  4. * Permission is hereby granted, free of charge, to any person
  5. * obtaining a copy of this software and associated documentation
  6. * files (the "Software"), to deal in the Software without
  7. * restriction, including without limitation the rights to use, copy,
  8. * modify, merge, publish, distribute, sublicense, and/or sell copies
  9. * of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  19. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  20. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22. * DEALINGS IN THE SOFTWARE.
  23. *
  24. */
  25. #include "uart.h"
  26. #include "mbox.h"
  27. #include "delays.h"
  28. /* PC Screen Font as used by Linux Console */
  29. typedef struct {
  30. unsigned int magic;
  31. unsigned int version;
  32. unsigned int headersize;
  33. unsigned int flags;
  34. unsigned int numglyph;
  35. unsigned int bytesperglyph;
  36. unsigned int height;
  37. unsigned int width;
  38. unsigned char glyphs;
  39. } __attribute__((packed)) psf_t;
  40. extern volatile unsigned char _binary_font_psf_start;
  41. /* Scalable Screen Font (https://gitlab.com/bztsrc/scalable-font2) */
  42. typedef struct {
  43. unsigned char magic[4];
  44. unsigned int size;
  45. unsigned char type;
  46. unsigned char features;
  47. unsigned char width;
  48. unsigned char height;
  49. unsigned char baseline;
  50. unsigned char underline;
  51. unsigned short fragments_offs;
  52. unsigned int characters_offs;
  53. unsigned int ligature_offs;
  54. unsigned int kerning_offs;
  55. unsigned int cmap_offs;
  56. } __attribute__((packed)) sfn_t;
  57. extern volatile unsigned char _binary_font_sfn_start;
  58. unsigned int width, height, pitch;
  59. unsigned char *lfb;
  60. /**
  61. * Set screen resolution to 1024x768
  62. */
  63. void lfb_init()
  64. {
  65. /* newer qemu segfaults if we don't wait here a bit */
  66. wait_msec(100000);
  67. mbox[0] = 35*4;
  68. mbox[1] = MBOX_REQUEST;
  69. mbox[2] = 0x48003; //set phy wh
  70. mbox[3] = 8;
  71. mbox[4] = 8;
  72. mbox[5] = 1024; //FrameBufferInfo.width
  73. mbox[6] = 768; //FrameBufferInfo.height
  74. mbox[7] = 0x48004; //set virt wh
  75. mbox[8] = 8;
  76. mbox[9] = 8;
  77. mbox[10] = 1024; //FrameBufferInfo.virtual_width
  78. mbox[11] = 768; //FrameBufferInfo.virtual_height
  79. mbox[12] = 0x48009; //set virt offset
  80. mbox[13] = 8;
  81. mbox[14] = 8;
  82. mbox[15] = 0; //FrameBufferInfo.x_offset
  83. mbox[16] = 0; //FrameBufferInfo.y.offset
  84. mbox[17] = 0x48005; //set depth
  85. mbox[18] = 4;
  86. mbox[19] = 4;
  87. mbox[20] = 32; //FrameBufferInfo.depth
  88. mbox[21] = 0x48006; //set pixel order
  89. mbox[22] = 4;
  90. mbox[23] = 4;
  91. mbox[24] = 1; //RGB, not BGR preferably
  92. mbox[25] = 0x40001; //get framebuffer, gets alignment on request
  93. mbox[26] = 8;
  94. mbox[27] = 8;
  95. mbox[28] = 4096; //FrameBufferInfo.pointer
  96. mbox[29] = 0; //FrameBufferInfo.size
  97. mbox[30] = 0x40008; //get pitch
  98. mbox[31] = 4;
  99. mbox[32] = 4;
  100. mbox[33] = 0; //FrameBufferInfo.pitch
  101. mbox[34] = MBOX_TAG_LAST;
  102. if(mbox_call(MBOX_CH_PROP) && mbox[20]==32 && mbox[28]!=0) {
  103. mbox[28]&=0x3FFFFFFF;
  104. width=mbox[5];
  105. height=mbox[6];
  106. pitch=mbox[33];
  107. lfb=(void*)((unsigned long)mbox[28]);
  108. } else {
  109. uart_puts("Unable to set screen resolution to 1024x768x32\n");
  110. }
  111. }
  112. /**
  113. * Display a string using fixed size PSF
  114. */
  115. void lfb_print(int x, int y, char *s)
  116. {
  117. // get our font
  118. psf_t *font = (psf_t*)&_binary_font_psf_start;
  119. // draw next character if it's not zero
  120. while(*s) {
  121. // get the offset of the glyph. Need to adjust this to support unicode table
  122. unsigned char *glyph = (unsigned char*)&_binary_font_psf_start +
  123. font->headersize + (*((unsigned char*)s)<font->numglyph?*s:0)*font->bytesperglyph;
  124. // calculate the offset on screen
  125. int offs = (y * pitch) + (x * 4);
  126. // variables
  127. int i,j, line,mask, bytesperline=(font->width+7)/8;
  128. // handle carrige return
  129. if(*s == '\r') {
  130. x = 0;
  131. } else
  132. // new line
  133. if(*s == '\n') {
  134. x = 0; y += font->height;
  135. } else {
  136. // display a character
  137. for(j=0;j<font->height;j++){
  138. // display one row
  139. line=offs;
  140. mask=1<<(font->width-1);
  141. for(i=0;i<font->width;i++){
  142. // if bit set, we use white color, otherwise black
  143. *((unsigned int*)(lfb + line))=((int)*glyph) & mask?0xFFFFFF:0;
  144. mask>>=1;
  145. line+=4;
  146. }
  147. // adjust to next line
  148. glyph+=bytesperline;
  149. offs+=pitch;
  150. }
  151. x += (font->width+1);
  152. }
  153. // next character
  154. s++;
  155. }
  156. }
  157. /**
  158. * Display a string using proportional SSFN
  159. */
  160. void lfb_proprint(int x, int y, char *s)
  161. {
  162. // get our font
  163. sfn_t *font = (sfn_t*)&_binary_font_sfn_start;
  164. unsigned char *ptr, *chr, *frg;
  165. unsigned int c;
  166. unsigned long o, p;
  167. int i, j, k, l, m, n;
  168. while(*s) {
  169. // UTF-8 to UNICODE code point
  170. if((*s & 128) != 0) {
  171. if(!(*s & 32)) { c = ((*s & 0x1F)<<6)|(*(s+1) & 0x3F); s += 1; } else
  172. if(!(*s & 16)) { c = ((*s & 0xF)<<12)|((*(s+1) & 0x3F)<<6)|(*(s+2) & 0x3F); s += 2; } else
  173. if(!(*s & 8)) { c = ((*s & 0x7)<<18)|((*(s+1) & 0x3F)<<12)|((*(s+2) & 0x3F)<<6)|(*(s+3) & 0x3F); s += 3; }
  174. else c = 0;
  175. } else c = *s;
  176. s++;
  177. // handle carrige return
  178. if(c == '\r') {
  179. x = 0; continue;
  180. } else
  181. // new line
  182. if(c == '\n') {
  183. x = 0; y += font->height; continue;
  184. }
  185. // find glyph, look up "c" in Character Table
  186. for(ptr = (unsigned char*)font + font->characters_offs, chr = 0, i = 0; i < 0x110000; i++) {
  187. if(ptr[0] == 0xFF) { i += 65535; ptr++; }
  188. else if((ptr[0] & 0xC0) == 0xC0) { j = (((ptr[0] & 0x3F) << 8) | ptr[1]); i += j; ptr += 2; }
  189. else if((ptr[0] & 0xC0) == 0x80) { j = (ptr[0] & 0x3F); i += j; ptr++; }
  190. else { if((unsigned int)i == c) { chr = ptr; break; } ptr += 6 + ptr[1] * (ptr[0] & 0x40 ? 6 : 5); }
  191. }
  192. if(!chr) continue;
  193. // uncompress and display fragments
  194. ptr = chr + 6; o = (unsigned long)lfb + y * pitch + x * 4;
  195. for(i = n = 0; i < chr[1]; i++, ptr += chr[0] & 0x40 ? 6 : 5) {
  196. if(ptr[0] == 255 && ptr[1] == 255) continue;
  197. frg = (unsigned char*)font + (chr[0] & 0x40 ? ((ptr[5] << 24) | (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]) :
  198. ((ptr[4] << 16) | (ptr[3] << 8) | ptr[2]));
  199. if((frg[0] & 0xE0) != 0x80) continue;
  200. o += (int)(ptr[1] - n) * pitch; n = ptr[1];
  201. k = ((frg[0] & 0x1F) + 1) << 3; j = frg[1] + 1; frg += 2;
  202. for(m = 1; j; j--, n++, o += pitch)
  203. for(p = o, l = 0; l < k; l++, p += 4, m <<= 1) {
  204. if(m > 0x80) { frg++; m = 1; }
  205. if(*frg & m) *((unsigned int*)p) = 0xFFFFFF;
  206. }
  207. }
  208. // add advances
  209. x += chr[4]+1; y += chr[5];
  210. }
  211. }