xref: /haiku/src/system/kernel/debug/blue_screen.cpp (revision 173d0b2fc795efd1d6de9d74ff25f8ff1d9522c3)
1f33c8020SAxel Dörfler /*
2*173d0b2fSAxel Dörfler  * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3f33c8020SAxel Dörfler  * Distributed under the terms of the MIT License.
4f33c8020SAxel Dörfler  */
5f33c8020SAxel Dörfler 
6f33c8020SAxel Dörfler 
7f33c8020SAxel Dörfler #include "blue_screen.h"
8f33c8020SAxel Dörfler 
967f20716SAxel Dörfler #include <KernelExport.h>
10f33c8020SAxel Dörfler #include <frame_buffer_console.h>
11f33c8020SAxel Dörfler #include <console.h>
12f33c8020SAxel Dörfler #include <arch/debug_console.h>
13f33c8020SAxel Dörfler 
14f33c8020SAxel Dörfler #include <string.h>
15f33c8020SAxel Dörfler #include <stdio.h>
16f33c8020SAxel Dörfler 
17f33c8020SAxel Dörfler 
18f33c8020SAxel Dörfler #define USE_SCROLLING 0
19f33c8020SAxel Dörfler #define NO_CLEAR 1
20f33c8020SAxel Dörfler 
2167f20716SAxel Dörfler #define MAX_ARGS 8
2267f20716SAxel Dörfler 
2367f20716SAxel Dörfler #define FMASK 0x0f
2467f20716SAxel Dörfler #define BMASK 0x70
2567f20716SAxel Dörfler 
2667f20716SAxel Dörfler typedef enum {
2767f20716SAxel Dörfler 	CONSOLE_STATE_NORMAL = 0,
2867f20716SAxel Dörfler 	CONSOLE_STATE_GOT_ESCAPE,
2967f20716SAxel Dörfler 	CONSOLE_STATE_SEEN_BRACKET,
3067f20716SAxel Dörfler 	CONSOLE_STATE_NEW_ARG,
3167f20716SAxel Dörfler 	CONSOLE_STATE_PARSING_ARG,
3267f20716SAxel Dörfler } console_state;
3367f20716SAxel Dörfler 
3470c3e1a4SAxel Dörfler typedef enum {
3570c3e1a4SAxel Dörfler 	LINE_ERASE_WHOLE,
3670c3e1a4SAxel Dörfler 	LINE_ERASE_LEFT,
3770c3e1a4SAxel Dörfler 	LINE_ERASE_RIGHT
3870c3e1a4SAxel Dörfler } erase_line_mode;
3970c3e1a4SAxel Dörfler 
40f33c8020SAxel Dörfler struct screen_info {
41f33c8020SAxel Dörfler 	int32	columns;
42f33c8020SAxel Dörfler 	int32	rows;
43f33c8020SAxel Dörfler 	int32	x, y;
44f33c8020SAxel Dörfler 	uint8	attr;
4567f20716SAxel Dörfler 	bool	bright_attr;
4667f20716SAxel Dörfler 	bool	reverse_attr;
4767f20716SAxel Dörfler 
4867f20716SAxel Dörfler 	// state machine
4967f20716SAxel Dörfler 	console_state state;
5067f20716SAxel Dörfler 	int32	arg_count;
5167f20716SAxel Dörfler 	int32	args[MAX_ARGS];
52f33c8020SAxel Dörfler } sScreen;
53f33c8020SAxel Dörfler 
54f33c8020SAxel Dörfler console_module_info *sModule;
55f33c8020SAxel Dörfler 
56f33c8020SAxel Dörfler 
57f33c8020SAxel Dörfler static inline void
58f33c8020SAxel Dörfler hide_cursor(void)
59f33c8020SAxel Dörfler {
60f33c8020SAxel Dörfler 	sModule->move_cursor(-1, -1);
61f33c8020SAxel Dörfler }
62f33c8020SAxel Dörfler 
63f33c8020SAxel Dörfler 
64f33c8020SAxel Dörfler static inline void
65f33c8020SAxel Dörfler update_cursor(int32 x, int32 y)
66f33c8020SAxel Dörfler {
67f33c8020SAxel Dörfler 	sModule->move_cursor(x, y);
68f33c8020SAxel Dörfler }
69f33c8020SAxel Dörfler 
70f33c8020SAxel Dörfler 
7167f20716SAxel Dörfler static inline void
7267f20716SAxel Dörfler move_cursor(int32 x, int32 y)
7367f20716SAxel Dörfler {
7467f20716SAxel Dörfler 	sScreen.x = x;
7567f20716SAxel Dörfler 	sScreen.y = y;
7667f20716SAxel Dörfler 	update_cursor(x, y);
7767f20716SAxel Dörfler }
7867f20716SAxel Dörfler 
7967f20716SAxel Dörfler 
80f33c8020SAxel Dörfler #if USE_SCROLLING
81f33c8020SAxel Dörfler 
82f33c8020SAxel Dörfler /** scroll from the cursor line up to the top of the scroll region up one line */
83f33c8020SAxel Dörfler 
84f33c8020SAxel Dörfler static void
85f33c8020SAxel Dörfler scroll_up(void)
86f33c8020SAxel Dörfler {
87f33c8020SAxel Dörfler 	// move the screen up one
88f33c8020SAxel Dörfler 	sModule->blit(0, 1, sScreen.columns, sScreen.rows - 1, 0, 0);
89f33c8020SAxel Dörfler 
90f33c8020SAxel Dörfler 	// clear the bottom line
91f33c8020SAxel Dörfler 	sModule->fill_glyph(0, 0, sScreen.columns, 1, ' ', sScreen.attr);
92f33c8020SAxel Dörfler }
93f33c8020SAxel Dörfler #endif
94f33c8020SAxel Dörfler 
95f33c8020SAxel Dörfler 
96f33c8020SAxel Dörfler static void
97f33c8020SAxel Dörfler next_line(void)
98f33c8020SAxel Dörfler {
99f33c8020SAxel Dörfler 	if (sScreen.y == sScreen.rows - 1) {
100f33c8020SAxel Dörfler #if USE_SCROLLING
101f33c8020SAxel Dörfler  		scroll_up();
102f33c8020SAxel Dörfler #else
103f33c8020SAxel Dörfler 		sScreen.y = 0;
104f33c8020SAxel Dörfler #endif
105f33c8020SAxel Dörfler 	} else if (sScreen.y < sScreen.rows - 1) {
106f33c8020SAxel Dörfler 		sScreen.y++;
107f33c8020SAxel Dörfler 	}
108f33c8020SAxel Dörfler 
109f33c8020SAxel Dörfler #if NO_CLEAR
1100160c6fbSAxel Dörfler 	sModule->fill_glyph(0, (sScreen.y + 2) % sScreen.rows, sScreen.columns, 1, ' ', sScreen.attr);
111f33c8020SAxel Dörfler #endif
112f33c8020SAxel Dörfler 	sScreen.x = 0;
113f33c8020SAxel Dörfler }
114f33c8020SAxel Dörfler 
115f33c8020SAxel Dörfler 
116f33c8020SAxel Dörfler static void
11770c3e1a4SAxel Dörfler erase_line(erase_line_mode mode)
11870c3e1a4SAxel Dörfler {
11970c3e1a4SAxel Dörfler 	switch (mode) {
12070c3e1a4SAxel Dörfler 		case LINE_ERASE_WHOLE:
12170c3e1a4SAxel Dörfler 			sModule->fill_glyph(0, sScreen.y, sScreen.columns, 1, ' ', sScreen.attr);
12270c3e1a4SAxel Dörfler 			break;
12370c3e1a4SAxel Dörfler 		case LINE_ERASE_LEFT:
12470c3e1a4SAxel Dörfler 			sModule->fill_glyph(0, sScreen.y, sScreen.x + 1, 1, ' ', sScreen.attr);
12570c3e1a4SAxel Dörfler 			break;
12670c3e1a4SAxel Dörfler 		case LINE_ERASE_RIGHT:
12770c3e1a4SAxel Dörfler 			sModule->fill_glyph(sScreen.x, sScreen.y, sScreen.columns - sScreen.x,
12870c3e1a4SAxel Dörfler 				1, ' ', sScreen.attr);
12970c3e1a4SAxel Dörfler 			break;
13070c3e1a4SAxel Dörfler //		default:
13170c3e1a4SAxel Dörfler 	}
13270c3e1a4SAxel Dörfler }
13370c3e1a4SAxel Dörfler 
13470c3e1a4SAxel Dörfler 
13570c3e1a4SAxel Dörfler static void
136f33c8020SAxel Dörfler back_space(void)
137f33c8020SAxel Dörfler {
138f33c8020SAxel Dörfler 	if (sScreen.x <= 0)
139f33c8020SAxel Dörfler 		return;
140f33c8020SAxel Dörfler 
141f33c8020SAxel Dörfler 	sScreen.x--;
142f33c8020SAxel Dörfler 	sModule->put_glyph(sScreen.x, sScreen.y, ' ', sScreen.attr);
143f33c8020SAxel Dörfler }
144f33c8020SAxel Dörfler 
145f33c8020SAxel Dörfler 
146f33c8020SAxel Dörfler static void
147f33c8020SAxel Dörfler put_character(char c)
148f33c8020SAxel Dörfler {
149f33c8020SAxel Dörfler 	if (++sScreen.x >= sScreen.columns) {
150f33c8020SAxel Dörfler 		next_line();
151f33c8020SAxel Dörfler 		sScreen.x++;
152f33c8020SAxel Dörfler 	}
153f33c8020SAxel Dörfler 
154f33c8020SAxel Dörfler 	sModule->put_glyph(sScreen.x - 1, sScreen.y, c, sScreen.attr);
155f33c8020SAxel Dörfler }
156f33c8020SAxel Dörfler 
157f33c8020SAxel Dörfler 
158f33c8020SAxel Dörfler static void
15967f20716SAxel Dörfler set_vt100_attributes(int32 *args, int32 argCount)
16067f20716SAxel Dörfler {
16167f20716SAxel Dörfler 	if (argCount == 0) {
16267f20716SAxel Dörfler 		// that's the default (attributes off)
16367f20716SAxel Dörfler 		argCount++;
16467f20716SAxel Dörfler 		args[0] = 0;
16567f20716SAxel Dörfler 	}
16667f20716SAxel Dörfler 
16767f20716SAxel Dörfler 	for (int32 i = 0; i < argCount; i++) {
16867f20716SAxel Dörfler 		switch (args[i]) {
16967f20716SAxel Dörfler 			case 0: // reset
17067f20716SAxel Dörfler 				sScreen.attr = 0x0f;
17167f20716SAxel Dörfler 				sScreen.bright_attr = true;
17267f20716SAxel Dörfler 				sScreen.reverse_attr = false;
17367f20716SAxel Dörfler 				break;
17467f20716SAxel Dörfler 			case 1: // bright
17567f20716SAxel Dörfler 				sScreen.bright_attr = true;
17667f20716SAxel Dörfler 				sScreen.attr |= 0x08; // set the bright bit
17767f20716SAxel Dörfler 				break;
17867f20716SAxel Dörfler 			case 2: // dim
17967f20716SAxel Dörfler 				sScreen.bright_attr = false;
18067f20716SAxel Dörfler 				sScreen.attr &= ~0x08; // unset the bright bit
18167f20716SAxel Dörfler 				break;
18267f20716SAxel Dörfler 			case 4: // underscore we can't do
18367f20716SAxel Dörfler 				break;
18467f20716SAxel Dörfler 			case 5: // blink
18567f20716SAxel Dörfler 				sScreen.attr |= 0x80; // set the blink bit
18667f20716SAxel Dörfler 				break;
18767f20716SAxel Dörfler 			case 7: // reverse
18867f20716SAxel Dörfler 				sScreen.reverse_attr = true;
18967f20716SAxel Dörfler 				sScreen.attr = ((sScreen.attr & BMASK) >> 4) | ((sScreen.attr & FMASK) << 4);
19067f20716SAxel Dörfler 				if (sScreen.bright_attr)
19167f20716SAxel Dörfler 					sScreen.attr |= 0x08;
19267f20716SAxel Dörfler 				break;
19367f20716SAxel Dörfler 			case 8: // hidden?
19467f20716SAxel Dörfler 				break;
19567f20716SAxel Dörfler 
19667f20716SAxel Dörfler 			/* foreground colors */
19767f20716SAxel Dörfler 			case 30: sScreen.attr = (sScreen.attr & ~FMASK) | 0 | (sScreen.bright_attr ? 0x08 : 0); break; // black
19867f20716SAxel Dörfler 			case 31: sScreen.attr = (sScreen.attr & ~FMASK) | 4 | (sScreen.bright_attr ? 0x08 : 0); break; // red
19967f20716SAxel Dörfler 			case 32: sScreen.attr = (sScreen.attr & ~FMASK) | 2 | (sScreen.bright_attr ? 0x08 : 0); break; // green
20067f20716SAxel Dörfler 			case 33: sScreen.attr = (sScreen.attr & ~FMASK) | 6 | (sScreen.bright_attr ? 0x08 : 0); break; // yellow
20167f20716SAxel Dörfler 			case 34: sScreen.attr = (sScreen.attr & ~FMASK) | 1 | (sScreen.bright_attr ? 0x08 : 0); break; // blue
20267f20716SAxel Dörfler 			case 35: sScreen.attr = (sScreen.attr & ~FMASK) | 5 | (sScreen.bright_attr ? 0x08 : 0); break; // magenta
20367f20716SAxel Dörfler 			case 36: sScreen.attr = (sScreen.attr & ~FMASK) | 3 | (sScreen.bright_attr ? 0x08 : 0); break; // cyan
20467f20716SAxel Dörfler 			case 37: sScreen.attr = (sScreen.attr & ~FMASK) | 7 | (sScreen.bright_attr ? 0x08 : 0); break; // white
20567f20716SAxel Dörfler 
20667f20716SAxel Dörfler 			/* background colors */
20767f20716SAxel Dörfler 			case 40: sScreen.attr = (sScreen.attr & ~BMASK) | (0 << 4); break; // black
20867f20716SAxel Dörfler 			case 41: sScreen.attr = (sScreen.attr & ~BMASK) | (4 << 4); break; // red
20967f20716SAxel Dörfler 			case 42: sScreen.attr = (sScreen.attr & ~BMASK) | (2 << 4); break; // green
21067f20716SAxel Dörfler 			case 43: sScreen.attr = (sScreen.attr & ~BMASK) | (6 << 4); break; // yellow
21167f20716SAxel Dörfler 			case 44: sScreen.attr = (sScreen.attr & ~BMASK) | (1 << 4); break; // blue
21267f20716SAxel Dörfler 			case 45: sScreen.attr = (sScreen.attr & ~BMASK) | (5 << 4); break; // magenta
21367f20716SAxel Dörfler 			case 46: sScreen.attr = (sScreen.attr & ~BMASK) | (3 << 4); break; // cyan
21467f20716SAxel Dörfler 			case 47: sScreen.attr = (sScreen.attr & ~BMASK) | (7 << 4); break; // white
21567f20716SAxel Dörfler 		}
21667f20716SAxel Dörfler 	}
21767f20716SAxel Dörfler }
21867f20716SAxel Dörfler 
21967f20716SAxel Dörfler 
22067f20716SAxel Dörfler static bool
22167f20716SAxel Dörfler process_vt100_command(const char c, bool seenBracket, int32 *args, int32 argCount)
22267f20716SAxel Dörfler {
22367f20716SAxel Dörfler 	bool ret = true;
22467f20716SAxel Dörfler 
22567f20716SAxel Dörfler //	kprintf("process_vt100_command: c '%c', argCount %ld, arg[0] %ld, arg[1] %ld, seenBracket %d\n",
22667f20716SAxel Dörfler //		c, argCount, args[0], args[1], seenBracket);
22767f20716SAxel Dörfler 
22867f20716SAxel Dörfler 	if (seenBracket) {
22967f20716SAxel Dörfler 		switch (c) {
23067f20716SAxel Dörfler 			case 'H': /* set cursor position */
23167f20716SAxel Dörfler 			case 'f': {
23267f20716SAxel Dörfler 				int32 row = argCount > 0 ? args[0] : 1;
23367f20716SAxel Dörfler 				int32 col = argCount > 1 ? args[1] : 1;
23467f20716SAxel Dörfler 				if (row > 0)
23567f20716SAxel Dörfler 					row--;
23667f20716SAxel Dörfler 				if (col > 0)
23767f20716SAxel Dörfler 					col--;
23867f20716SAxel Dörfler 				move_cursor(col, row);
23967f20716SAxel Dörfler 				break;
24067f20716SAxel Dörfler 			}
24167f20716SAxel Dörfler 			case 'A': { /* move up */
24267f20716SAxel Dörfler 				int32 deltay = argCount > 0 ? -args[0] : -1;
24367f20716SAxel Dörfler 				if (deltay == 0)
24467f20716SAxel Dörfler 					deltay = -1;
24567f20716SAxel Dörfler 				move_cursor(sScreen.x, sScreen.y + deltay);
24667f20716SAxel Dörfler 				break;
24767f20716SAxel Dörfler 			}
24867f20716SAxel Dörfler 			case 'e':
24967f20716SAxel Dörfler 			case 'B': { /* move down */
25067f20716SAxel Dörfler 				int32 deltay = argCount > 0 ? args[0] : 1;
25167f20716SAxel Dörfler 				if (deltay == 0)
25267f20716SAxel Dörfler 					deltay = 1;
25367f20716SAxel Dörfler 				move_cursor(sScreen.x, sScreen.y + deltay);
25467f20716SAxel Dörfler 				break;
25567f20716SAxel Dörfler 			}
25667f20716SAxel Dörfler 			case 'D': { /* move left */
25767f20716SAxel Dörfler 				int32 deltax = argCount > 0 ? -args[0] : -1;
25867f20716SAxel Dörfler 				if (deltax == 0)
25967f20716SAxel Dörfler 					deltax = -1;
26067f20716SAxel Dörfler 				move_cursor(sScreen.x + deltax, sScreen.y);
26167f20716SAxel Dörfler 				break;
26267f20716SAxel Dörfler 			}
26367f20716SAxel Dörfler 			case 'a':
26467f20716SAxel Dörfler 			case 'C': { /* move right */
26567f20716SAxel Dörfler 				int32 deltax = argCount > 0 ? args[0] : 1;
26667f20716SAxel Dörfler 				if (deltax == 0)
26767f20716SAxel Dörfler 					deltax = 1;
26867f20716SAxel Dörfler 				move_cursor(sScreen.x + deltax, sScreen.y);
26967f20716SAxel Dörfler 				break;
27067f20716SAxel Dörfler 			}
27167f20716SAxel Dörfler 			case '`':
27267f20716SAxel Dörfler 			case 'G': { /* set X position */
27367f20716SAxel Dörfler 				int32 newx = argCount > 0 ? args[0] : 1;
27467f20716SAxel Dörfler 				if (newx > 0)
27567f20716SAxel Dörfler 					newx--;
27667f20716SAxel Dörfler 				move_cursor(newx, sScreen.y);
27767f20716SAxel Dörfler 				break;
27867f20716SAxel Dörfler 			}
27967f20716SAxel Dörfler 			case 'd': { /* set y position */
28067f20716SAxel Dörfler 				int32 newy = argCount > 0 ? args[0] : 1;
28167f20716SAxel Dörfler 				if (newy > 0)
28267f20716SAxel Dörfler 					newy--;
28367f20716SAxel Dörfler 				move_cursor(sScreen.x, newy);
28467f20716SAxel Dörfler 				break;
28567f20716SAxel Dörfler 			}
28667f20716SAxel Dörfler #if 0
28767f20716SAxel Dörfler 			case 's': /* save current cursor */
28867f20716SAxel Dörfler 				save_cur(console, false);
28967f20716SAxel Dörfler 				break;
29067f20716SAxel Dörfler 			case 'u': /* restore cursor */
29167f20716SAxel Dörfler 				restore_cur(console, false);
29267f20716SAxel Dörfler 				break;
29367f20716SAxel Dörfler 			case 'r': { /* set scroll region */
29467f20716SAxel Dörfler 				int32 low = argCount > 0 ? args[0] : 1;
29567f20716SAxel Dörfler 				int32 high = argCount > 1 ? args[1] : sScreen.lines;
29667f20716SAxel Dörfler 				if (low <= high)
29767f20716SAxel Dörfler 					set_scroll_region(console, low - 1, high - 1);
29867f20716SAxel Dörfler 				break;
29967f20716SAxel Dörfler 			}
30067f20716SAxel Dörfler 			case 'L': { /* scroll virtual down at cursor */
30167f20716SAxel Dörfler 				int32 lines = argCount > 0 ? args[0] : 1;
30267f20716SAxel Dörfler 				while (lines > 0) {
30367f20716SAxel Dörfler 					scrdown(console);
30467f20716SAxel Dörfler 					lines--;
30567f20716SAxel Dörfler 				}
30667f20716SAxel Dörfler 				break;
30767f20716SAxel Dörfler 			}
30867f20716SAxel Dörfler 			case 'M': { /* scroll virtual up at cursor */
30967f20716SAxel Dörfler 				int32 lines = argCount > 0 ? args[0] : 1;
31067f20716SAxel Dörfler 				while (lines > 0) {
31167f20716SAxel Dörfler 					scrup(console);
31267f20716SAxel Dörfler 					lines--;
31367f20716SAxel Dörfler 				}
31467f20716SAxel Dörfler 				break;
31567f20716SAxel Dörfler 			}
31670c3e1a4SAxel Dörfler #endif
31767f20716SAxel Dörfler 			case 'K':
31867f20716SAxel Dörfler 				if (argCount == 0 || args[0] == 0) {
31967f20716SAxel Dörfler 					// erase to end of line
32070c3e1a4SAxel Dörfler 					erase_line(LINE_ERASE_RIGHT);
32167f20716SAxel Dörfler 				} else if (argCount > 0) {
32267f20716SAxel Dörfler 					if (args[0] == 1)
32370c3e1a4SAxel Dörfler 						erase_line(LINE_ERASE_LEFT);
32467f20716SAxel Dörfler 					else if (args[0] == 2)
32570c3e1a4SAxel Dörfler 						erase_line(LINE_ERASE_WHOLE);
32667f20716SAxel Dörfler 				}
32767f20716SAxel Dörfler 				break;
32870c3e1a4SAxel Dörfler #if 0
32967f20716SAxel Dörfler 			case 'J':
33067f20716SAxel Dörfler 				if (argCount == 0 || args[0] == 0) {
33167f20716SAxel Dörfler 					// erase to end of screen
33267f20716SAxel Dörfler 					erase_screen(console, SCREEN_ERASE_DOWN);
33367f20716SAxel Dörfler 				} else {
33467f20716SAxel Dörfler 					if (args[0] == 1)
33567f20716SAxel Dörfler 						erase_screen(console, SCREEN_ERASE_UP);
33667f20716SAxel Dörfler 					else if (args[0] == 2)
33767f20716SAxel Dörfler 						erase_screen(console, SCREEN_ERASE_WHOLE);
33867f20716SAxel Dörfler 				}
33967f20716SAxel Dörfler 				break;
34067f20716SAxel Dörfler #endif
34167f20716SAxel Dörfler 			case 'm':
34267f20716SAxel Dörfler 				if (argCount >= 0)
34367f20716SAxel Dörfler 					set_vt100_attributes(args, argCount);
34467f20716SAxel Dörfler 				break;
34567f20716SAxel Dörfler 			default:
34667f20716SAxel Dörfler 				ret = false;
34767f20716SAxel Dörfler 		}
34867f20716SAxel Dörfler 	} else {
34967f20716SAxel Dörfler 		switch (c) {
35067f20716SAxel Dörfler #if 0
35167f20716SAxel Dörfler 			case 'c':
35267f20716SAxel Dörfler 				reset_console(console);
35367f20716SAxel Dörfler 				break;
35467f20716SAxel Dörfler 			case 'D':
35567f20716SAxel Dörfler 				rlf(console);
35667f20716SAxel Dörfler 				break;
35767f20716SAxel Dörfler 			case 'M':
35867f20716SAxel Dörfler 				lf(console);
35967f20716SAxel Dörfler 				break;
36067f20716SAxel Dörfler 			case '7':
36167f20716SAxel Dörfler 				save_cur(console, true);
36267f20716SAxel Dörfler 				break;
36367f20716SAxel Dörfler 			case '8':
36467f20716SAxel Dörfler 				restore_cur(console, true);
36567f20716SAxel Dörfler 				break;
36667f20716SAxel Dörfler #endif
36767f20716SAxel Dörfler 			default:
36867f20716SAxel Dörfler 				ret = false;
36967f20716SAxel Dörfler 		}
37067f20716SAxel Dörfler 	}
37167f20716SAxel Dörfler 
37267f20716SAxel Dörfler 	return ret;
37367f20716SAxel Dörfler }
37467f20716SAxel Dörfler 
37567f20716SAxel Dörfler 
37667f20716SAxel Dörfler static void
377f33c8020SAxel Dörfler parse_character(char c)
378f33c8020SAxel Dörfler {
37967f20716SAxel Dörfler 	switch (sScreen.state) {
38067f20716SAxel Dörfler 		case CONSOLE_STATE_NORMAL:
381f33c8020SAxel Dörfler 			// just output the stuff
382f33c8020SAxel Dörfler 			switch (c) {
383f33c8020SAxel Dörfler 				case '\n':
384f33c8020SAxel Dörfler 					next_line();
385f33c8020SAxel Dörfler 					break;
386f33c8020SAxel Dörfler 				case 0x8:
387f33c8020SAxel Dörfler 					back_space();
388f33c8020SAxel Dörfler 					break;
389f33c8020SAxel Dörfler 				case '\t':
39067f20716SAxel Dörfler 					// ToDo: real tab...
391f31dc4ddSAxel Dörfler 					sScreen.x = (sScreen.x + 8) & ~7;
392f31dc4ddSAxel Dörfler 					if (sScreen.x >= sScreen.columns)
393f31dc4ddSAxel Dörfler 						next_line();
394f33c8020SAxel Dörfler 					break;
395f33c8020SAxel Dörfler 
396f33c8020SAxel Dörfler 				case '\r':
397f33c8020SAxel Dörfler 				case '\0':
39867f20716SAxel Dörfler 				case '\a': // beep
399f33c8020SAxel Dörfler 					break;
400f33c8020SAxel Dörfler 
40167f20716SAxel Dörfler 				case 0x1b:
40267f20716SAxel Dörfler 					// escape character
40367f20716SAxel Dörfler 					sScreen.arg_count = -1;
40467f20716SAxel Dörfler 					sScreen.state = CONSOLE_STATE_GOT_ESCAPE;
40567f20716SAxel Dörfler 					break;
406f33c8020SAxel Dörfler 				default:
407f33c8020SAxel Dörfler 					put_character(c);
408f33c8020SAxel Dörfler 			}
40967f20716SAxel Dörfler 			break;
41067f20716SAxel Dörfler 		case CONSOLE_STATE_GOT_ESCAPE:
41167f20716SAxel Dörfler 			// look for either commands with no argument, or the '[' character
41267f20716SAxel Dörfler 			switch (c) {
41367f20716SAxel Dörfler 				case '[':
41467f20716SAxel Dörfler 					sScreen.state = CONSOLE_STATE_SEEN_BRACKET;
41567f20716SAxel Dörfler 					break;
41667f20716SAxel Dörfler 				default:
41767f20716SAxel Dörfler 					sScreen.args[sScreen.arg_count] = 0;
41867f20716SAxel Dörfler 					process_vt100_command(c, false, sScreen.args, sScreen.arg_count + 1);
41967f20716SAxel Dörfler 					sScreen.state = CONSOLE_STATE_NORMAL;
42067f20716SAxel Dörfler 			}
42167f20716SAxel Dörfler 			break;
42267f20716SAxel Dörfler 		case CONSOLE_STATE_SEEN_BRACKET:
42367f20716SAxel Dörfler 			switch (c) {
42467f20716SAxel Dörfler 				case '0'...'9':
42567f20716SAxel Dörfler 					sScreen.arg_count = 0;
42667f20716SAxel Dörfler 					sScreen.args[sScreen.arg_count] = c - '0';
42767f20716SAxel Dörfler 					sScreen.state = CONSOLE_STATE_PARSING_ARG;
42867f20716SAxel Dörfler 					break;
42967f20716SAxel Dörfler 				case '?':
43067f20716SAxel Dörfler 					// private DEC mode parameter follows - we ignore those anyway
43167f20716SAxel Dörfler 					break;
43267f20716SAxel Dörfler 				default:
43367f20716SAxel Dörfler 					process_vt100_command(c, true, sScreen.args, sScreen.arg_count + 1);
43467f20716SAxel Dörfler 					sScreen.state = CONSOLE_STATE_NORMAL;
43567f20716SAxel Dörfler 			}
43667f20716SAxel Dörfler 			break;
43767f20716SAxel Dörfler 		case CONSOLE_STATE_NEW_ARG:
43867f20716SAxel Dörfler 			switch (c) {
43967f20716SAxel Dörfler 				case '0'...'9':
44067f20716SAxel Dörfler 					sScreen.arg_count++;
44167f20716SAxel Dörfler 					if (sScreen.arg_count == MAX_ARGS) {
44267f20716SAxel Dörfler 						sScreen.state = CONSOLE_STATE_NORMAL;
44367f20716SAxel Dörfler 						break;
44467f20716SAxel Dörfler 					}
44567f20716SAxel Dörfler 					sScreen.args[sScreen.arg_count] = c - '0';
44667f20716SAxel Dörfler 					sScreen.state = CONSOLE_STATE_PARSING_ARG;
44767f20716SAxel Dörfler 					break;
44867f20716SAxel Dörfler 				default:
44967f20716SAxel Dörfler 					process_vt100_command(c, true, sScreen.args, sScreen.arg_count + 1);
45067f20716SAxel Dörfler 					sScreen.state = CONSOLE_STATE_NORMAL;
45167f20716SAxel Dörfler 			}
45267f20716SAxel Dörfler 			break;
45367f20716SAxel Dörfler 		case CONSOLE_STATE_PARSING_ARG:
45467f20716SAxel Dörfler 			// parse args
45567f20716SAxel Dörfler 			switch (c) {
45667f20716SAxel Dörfler 				case '0'...'9':
45767f20716SAxel Dörfler 					sScreen.args[sScreen.arg_count] *= 10;
45867f20716SAxel Dörfler 					sScreen.args[sScreen.arg_count] += c - '0';
45967f20716SAxel Dörfler 					break;
46067f20716SAxel Dörfler 				case ';':
46167f20716SAxel Dörfler 					sScreen.state = CONSOLE_STATE_NEW_ARG;
46267f20716SAxel Dörfler 					break;
46367f20716SAxel Dörfler 				default:
46467f20716SAxel Dörfler 					process_vt100_command(c, true, sScreen.args, sScreen.arg_count + 1);
46567f20716SAxel Dörfler 					sScreen.state = CONSOLE_STATE_NORMAL;
46667f20716SAxel Dörfler 			}
46767f20716SAxel Dörfler 	}
468f33c8020SAxel Dörfler }
469f33c8020SAxel Dörfler 
470f33c8020SAxel Dörfler 
471f33c8020SAxel Dörfler //	#pragma mark -
472f33c8020SAxel Dörfler 
473f33c8020SAxel Dörfler 
474f33c8020SAxel Dörfler status_t
475f33c8020SAxel Dörfler blue_screen_init(void)
476f33c8020SAxel Dörfler {
477f33c8020SAxel Dörfler 	extern console_module_info gFrameBufferConsoleModule;
478f33c8020SAxel Dörfler 
479f33c8020SAxel Dörfler 	// we can't use get_module() here, since it's too early in the boot process
480f33c8020SAxel Dörfler 
481f33c8020SAxel Dörfler 	if (!frame_buffer_console_available())
482f33c8020SAxel Dörfler 		return B_ERROR;
483f33c8020SAxel Dörfler 
484f33c8020SAxel Dörfler 	sModule = &gFrameBufferConsoleModule;
485f33c8020SAxel Dörfler 	return B_OK;
486f33c8020SAxel Dörfler }
487f33c8020SAxel Dörfler 
488f33c8020SAxel Dörfler 
489*173d0b2fSAxel Dörfler status_t
49092447917SAxel Dörfler blue_screen_enter(bool debugOutput)
491f33c8020SAxel Dörfler {
49292447917SAxel Dörfler 	sScreen.attr = debugOutput ? 0xf0 : 0x0f;
49392447917SAxel Dörfler 		// black on white for KDL, white on black for debug output
494f33c8020SAxel Dörfler 	sScreen.x = sScreen.y = 0;
49567f20716SAxel Dörfler 	sScreen.state = CONSOLE_STATE_NORMAL;
496f33c8020SAxel Dörfler 
497*173d0b2fSAxel Dörfler 	if (sModule == NULL)
498*173d0b2fSAxel Dörfler 		return B_NO_INIT;
499*173d0b2fSAxel Dörfler 
500f33c8020SAxel Dörfler 	sModule->get_size(&sScreen.columns, &sScreen.rows);
501f33c8020SAxel Dörfler #if !NO_CLEAR
502f33c8020SAxel Dörfler 	sModule->clear(sScreen.attr);
503f33c8020SAxel Dörfler #else
504f33c8020SAxel Dörfler 	sModule->fill_glyph(0, sScreen.y, sScreen.columns, 3, ' ', sScreen.attr);
505f33c8020SAxel Dörfler #endif
506*173d0b2fSAxel Dörfler 	return B_OK;
507f33c8020SAxel Dörfler }
508f33c8020SAxel Dörfler 
509f33c8020SAxel Dörfler 
510f33c8020SAxel Dörfler char
511f33c8020SAxel Dörfler blue_screen_getchar(void)
512f33c8020SAxel Dörfler {
513f33c8020SAxel Dörfler 	return arch_debug_blue_screen_getchar();
514f33c8020SAxel Dörfler }
515f33c8020SAxel Dörfler 
516f33c8020SAxel Dörfler 
517f33c8020SAxel Dörfler void
518f33c8020SAxel Dörfler blue_screen_putchar(char c)
519f33c8020SAxel Dörfler {
520f33c8020SAxel Dörfler 	hide_cursor();
521f33c8020SAxel Dörfler 
522f33c8020SAxel Dörfler 	parse_character(c);
523f33c8020SAxel Dörfler 
524f33c8020SAxel Dörfler 	update_cursor(sScreen.x, sScreen.y);
525f33c8020SAxel Dörfler }
526f33c8020SAxel Dörfler 
527f33c8020SAxel Dörfler 
528f33c8020SAxel Dörfler void
529f33c8020SAxel Dörfler blue_screen_puts(const char *text)
530f33c8020SAxel Dörfler {
531f33c8020SAxel Dörfler 	hide_cursor();
532f33c8020SAxel Dörfler 
533f33c8020SAxel Dörfler 	while (text[0] != '\0') {
534f33c8020SAxel Dörfler 		parse_character(text[0]);
535f33c8020SAxel Dörfler 		text++;
536f33c8020SAxel Dörfler 	}
537f33c8020SAxel Dörfler 
538f33c8020SAxel Dörfler 	update_cursor(sScreen.x, sScreen.y);
539f33c8020SAxel Dörfler }
540