xref: /haiku/src/system/boot/platform/generic/video_text_console.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
1 /*
2  * Copyright 2021, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <boot/stage2.h>
7 #include <boot/platform/generic/text_console.h>
8 #include <boot/platform/generic/video.h>
9 
10 #include <frame_buffer_console.h>
11 
12 
13 extern console_module_info gFrameBufferConsoleModule;
14 
15 
16 class VideoTextConsole : public ConsoleNode {
17 	public:
18 		VideoTextConsole(addr_t framebuffer);
19 
20 		virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
21 			size_t bufferSize);
22 		virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
23 			size_t bufferSize);
24 
25 		virtual void	ClearScreen();
26 		virtual int32	Width();
27 		virtual int32	Height();
28 		virtual void	SetCursor(int32 x, int32 y);
29 		virtual void	SetCursorVisible(bool visible);
30 		virtual void	SetColors(int32 foreground, int32 background);
31 
32 	private:
33 		uint16 fColor = 0x0f00;
34 		bool fShowCursor;
35 		int32 fCursorX, fCursorY;
36 		int32 fScreenWidth, fScreenHeight;
37 };
38 
39 
40 //	#pragma mark -
41 
42 
43 VideoTextConsole::VideoTextConsole(addr_t framebuffer)
44 	: ConsoleNode()
45 {
46 	frame_buffer_update(framebuffer, gKernelArgs.frame_buffer.width,
47 		gKernelArgs.frame_buffer.height, gKernelArgs.frame_buffer.depth,
48 		gKernelArgs.frame_buffer.bytes_per_row);
49 	gFrameBufferConsoleModule.get_size(&fScreenWidth, &fScreenHeight);
50 
51 	SetCursorVisible(false);
52 	ClearScreen();
53 }
54 
55 
56 ssize_t
57 VideoTextConsole::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
58 {
59 	return B_ERROR;
60 }
61 
62 
63 ssize_t
64 VideoTextConsole::WriteAt(void *cookie, off_t /*pos*/, const void *buffer,
65 	size_t bufferSize)
66 {
67 	const char *string = (const char *)buffer;
68 	for (size_t i = 0; i < bufferSize; i++) {
69 		const char c = string[i];
70 		if (c == '\n' || fCursorX >= fScreenWidth) {
71 			fCursorX = 0;
72 			if (fCursorY == (fScreenHeight - 1)) {
73 				// Move the screen up and clear the bottom line.
74 				gFrameBufferConsoleModule.blit(0, 1, fScreenWidth, 0,
75 					0, fScreenHeight - 1);
76 				gFrameBufferConsoleModule.fill_glyph(0, fCursorY, fScreenWidth,
77 					1, ' ', fColor);
78 			} else {
79 				fCursorY++;
80 			}
81 		}
82 
83 		switch (c) {
84 			case '\n':
85 				// already handled above
86 				break;
87 
88 			default:
89 				gFrameBufferConsoleModule.put_glyph(fCursorX, fCursorY, c, fColor);
90 				break;
91 		}
92 		fCursorX++;
93 	}
94 	return bufferSize;
95 }
96 
97 
98 void
99 VideoTextConsole::ClearScreen()
100 {
101 	gFrameBufferConsoleModule.clear(fColor);
102 }
103 
104 
105 int32
106 VideoTextConsole::Width()
107 {
108 	return fScreenWidth;
109 }
110 
111 
112 int32
113 VideoTextConsole::Height()
114 {
115 	return fScreenHeight;
116 }
117 
118 
119 void
120 VideoTextConsole::SetCursor(int32 x, int32 y)
121 {
122 	fCursorX = x;
123 	fCursorY = y;
124 	if (fShowCursor)
125 		SetCursorVisible(true);
126 }
127 
128 
129 void
130 VideoTextConsole::SetCursorVisible(bool visible)
131 {
132 	fShowCursor = visible;
133 	if (fShowCursor)
134 		gFrameBufferConsoleModule.move_cursor(fCursorX, fCursorY);
135 	else
136 		gFrameBufferConsoleModule.move_cursor(-1, -1);
137 }
138 
139 
140 void
141 VideoTextConsole::SetColors(int32 foreground, int32 background)
142 {
143 	fColor = (background & 0xf) << 4 | (foreground & 0xf);
144 }
145 
146 
147 ConsoleNode*
148 video_text_console_init(addr_t frameBuffer)
149 {
150 	return new VideoTextConsole(frameBuffer);
151 }
152