1 /* 2 * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Copyright 2011, Rene Gollent, rene@gollent.com. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "console.h" 9 #include "video.h" 10 #include "graphics.h" 11 #include <Htif.h> 12 #include "virtio.h" 13 14 #include <SupportDefs.h> 15 #include <util/kernel_cpp.h> 16 #include <boot/stage2.h> 17 18 #include <string.h> 19 20 21 class Console : public ConsoleNode { 22 public: 23 Console(); 24 25 virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, 26 size_t bufferSize); 27 virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, 28 size_t bufferSize); 29 30 virtual void ClearScreen(); 31 virtual int32 Width(); 32 virtual int32 Height(); 33 virtual void SetCursor(int32 x, int32 y); 34 virtual void SetCursorVisible(bool visible); 35 virtual void SetColors(int32 foreground, int32 background); 36 }; 37 38 static uint16* sScreenBase; 39 static uint32 sScreenOfsX = 0; 40 static uint32 sScreenOfsY = 0; 41 static uint32 sScreenWidth = 80; 42 static uint32 sScreenHeight = 25; 43 static uint32 sScreenOffset = 0; 44 static uint16 sColor = 0x0f00; 45 46 extern ConsoleNode* gConsoleNode; 47 static Console sConsole; 48 FILE *stdin, *stdout, *stderr; 49 50 51 static const uint32 kPalette[] = { 52 0x000000, 53 0x0000aa, 54 0x00aa00, 55 0x00aaaa, 56 0xaa0000, 57 0xaa00aa, 58 0xaa5500, 59 0xaaaaaa, 60 0x555555, 61 0x5555ff, 62 0x55ff55, 63 0x55ffff, 64 0xff5555, 65 0xff55ff, 66 0xffff55, 67 0xffffff 68 }; 69 70 71 static void 72 RefreshFramebuf(int32 x0, int32 y0, int32 w, int32 h) 73 { 74 for (int32 y = y0; y < y0 + h; y++) 75 for (int32 x = x0; x < x0 + w; x++) { 76 uint16 cell = sScreenBase[x + y * sScreenWidth]; 77 int32 charX = sScreenOfsX + x*gFixedFont.charWidth; 78 int32 charY = sScreenOfsY + y*gFixedFont.charHeight; 79 uint32 bgColor = kPalette[cell / 0x1000 % 0x10]; 80 uint32 fontColor = kPalette[cell / 0x100 % 0x10]; 81 Clear(gFramebuf.Clip(charX, charY, gFixedFont.charWidth, 82 gFixedFont.charHeight), bgColor); 83 BlitMaskRgb(gFramebuf, gFixedFont.ThisGlyph(cell % 0x100), 84 charX, charY, fontColor); 85 } 86 } 87 88 89 static void 90 scroll_up() 91 { 92 memcpy(sScreenBase, sScreenBase + sScreenWidth, 93 sScreenWidth * sScreenHeight * 2 - sScreenWidth * 2); 94 sScreenOffset = (sScreenHeight - 1) * sScreenWidth; 95 96 for (uint32 i = 0; i < sScreenWidth; i++) 97 sScreenBase[sScreenOffset + i] = sColor | ' '; 98 } 99 100 101 // #pragma mark - 102 103 104 Console::Console() 105 : ConsoleNode() 106 { 107 } 108 109 110 ssize_t 111 Console::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) 112 { 113 // don't seek in character devices 114 // not implemented (and not yet? needed) 115 return B_ERROR; 116 } 117 118 119 ssize_t 120 Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer, 121 size_t bufferSize) 122 { 123 const char *string = (const char *)buffer; 124 125 if (gKernelArgs.frame_buffer.enabled) 126 return bufferSize; 127 128 for (uint32 i = 0; i < bufferSize; i++) { 129 if (string[0] == '\n') { 130 sScreenOffset += sScreenWidth - (sScreenOffset % sScreenWidth); 131 } else { 132 sScreenBase[sScreenOffset++] = sColor | string[0]; 133 RefreshFramebuf((sScreenOffset - 1) % sScreenWidth, 134 (sScreenOffset - 1) / sScreenWidth, 1, 1); 135 } 136 137 if (sScreenOffset >= sScreenWidth * sScreenHeight) { 138 scroll_up(); 139 RefreshFramebuf(0, 0, sScreenWidth, sScreenHeight); 140 } 141 142 string++; 143 } 144 145 return bufferSize; 146 } 147 148 149 void 150 Console::ClearScreen() 151 { 152 if (gKernelArgs.frame_buffer.enabled) 153 return; 154 155 for (uint32 i = 0; i < sScreenWidth * sScreenHeight; i++) 156 sScreenBase[i] = sColor; 157 158 // reset cursor position as well 159 sScreenOffset = 0; 160 161 RefreshFramebuf(0, 0, sScreenWidth, sScreenHeight); 162 } 163 164 165 int32 166 Console::Width() 167 { 168 return sScreenWidth; 169 } 170 171 172 int32 173 Console::Height() 174 { 175 return sScreenHeight; 176 } 177 178 179 void 180 Console::SetCursor(int32 x, int32 y) 181 { 182 if (y >= (int32)sScreenHeight) 183 y = sScreenHeight - 1; 184 else if (y < 0) 185 y = 0; 186 if (x >= (int32)sScreenWidth) 187 x = sScreenWidth - 1; 188 else if (x < 0) 189 x = 0; 190 191 sScreenOffset = x + y * sScreenWidth; 192 } 193 194 195 void 196 Console::SetCursorVisible(bool) 197 { 198 // TODO: implement 199 } 200 201 202 void 203 Console::SetColors(int32 foreground, int32 background) 204 { 205 sColor = (background & 0xf) << 12 | (foreground & 0xf) << 8; 206 } 207 208 209 int 210 console_wait_for_key(void) 211 { 212 int key = virtio_input_wait_for_key(); 213 214 switch (key) { 215 case 71: return TEXT_CONSOLE_KEY_RETURN; 216 case 30: return TEXT_CONSOLE_KEY_BACKSPACE; 217 case 1: return TEXT_CONSOLE_KEY_ESCAPE; 218 case 94: return TEXT_CONSOLE_KEY_SPACE; 219 220 case 87: return TEXT_CONSOLE_KEY_UP; 221 case 98: return TEXT_CONSOLE_KEY_DOWN; 222 case 97: return TEXT_CONSOLE_KEY_LEFT; 223 case 99: return TEXT_CONSOLE_KEY_RIGHT; 224 case 33: return TEXT_CONSOLE_KEY_PAGE_UP; 225 case 54: return TEXT_CONSOLE_KEY_PAGE_DOWN; 226 case 32: return TEXT_CONSOLE_KEY_HOME; 227 case 53: return TEXT_CONSOLE_KEY_END; 228 229 default: 230 return TEXT_CONSOLE_NO_KEY; 231 } 232 } 233 234 235 status_t 236 console_init(void) 237 { 238 sScreenWidth = 80; 239 sScreenHeight = 25; 240 sScreenOfsX = gFramebuf.width/2 - sScreenWidth*gFixedFont.charWidth/2; 241 sScreenOfsY = gFramebuf.height/2 - sScreenHeight*gFixedFont.charHeight/2; 242 243 sScreenBase = new(std::nothrow) uint16[sScreenWidth * sScreenHeight]; 244 245 sConsole.ClearScreen(); 246 247 // enable stdio functionality 248 gConsoleNode = &sConsole; 249 stdin = (FILE *)&sConsole; 250 stdout = stderr = (FILE *)&sConsole; 251 252 return B_OK; 253 } 254