xref: /haiku/src/system/boot/platform/atari_m68k/console.cpp (revision 002f37b0cca92e4cf72857c72ac95db5a8b09615)
1 /*
2  * Copyright 2007-2010, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT license.
4  *
5  * Author:
6  *		François Revol, revol@free.fr.
7  */
8 
9 #include <SupportDefs.h>
10 #include <string.h>
11 #include "toscalls.h"
12 #include <util/kernel_cpp.h>
13 
14 #include "Handle.h"
15 #include "console.h"
16 #include "keyboard.h"
17 
18 
19 static bool sForceBW = false;	// force black & white for Milan
20 
21 
22 // TOS emulates a VT52
23 
24 class ConsoleHandle : public CharHandle {
25 	public:
26 		ConsoleHandle();
27 
28 		virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
29 			size_t bufferSize);
30 		virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
31 			size_t bufferSize);
32 };
33 
34 class InputConsoleHandle : public ConsoleHandle {
35 	public:
36 		InputConsoleHandle();
37 
38 		virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
39 			size_t bufferSize);
40 
41 		void PutChar(char c);
42 		void PutChars(const char *buffer, int count);
43 		char GetChar();
44 
45 	private:
46 		enum { BUFFER_SIZE = 32 };
47 
48 		char	fBuffer[BUFFER_SIZE];
49 		int		fStart;
50 		int		fCount;
51 };
52 
53 
54 static InputConsoleHandle sInput;
55 static ConsoleHandle sOutput;
56 FILE *stdin, *stdout, *stderr;
57 
58 
59 ConsoleHandle::ConsoleHandle()
60 	: CharHandle()
61 {
62 }
63 
64 
65 ssize_t
66 ConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *buffer,
67 	size_t bufferSize)
68 {
69 	// don't seek in character devices
70 	// not implemented (and not yet? needed)
71 	return B_ERROR;
72 }
73 
74 
75 ssize_t
76 ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
77 	size_t bufferSize)
78 {
79 	const char *string = (const char *)buffer;
80 	size_t i;
81 
82 	// be nice to our audience and replace single "\n" with "\r\n"
83 
84 	for (i = 0; i < bufferSize; i++) {
85 		if (string[i] == '\0')
86 			break;
87 		if (string[i] == '\n')
88 			Bconout(fHandle, '\r');
89 		Bconout(fHandle, string[i]);
90 	}
91 
92 	return bufferSize;
93 }
94 
95 
96 //	#pragma mark -
97 
98 
99 InputConsoleHandle::InputConsoleHandle()
100 	: ConsoleHandle()
101 	, fStart(0)
102 	, fCount(0)
103 {
104 }
105 
106 
107 ssize_t
108 InputConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer,
109 	size_t bufferSize)
110 {
111 	char *buffer = (char*)_buffer;
112 
113 	// copy buffered bytes first
114 	int bytesTotal = 0;
115 	while (bufferSize > 0 && fCount > 0) {
116 		*buffer++ = GetChar();
117 		bytesTotal++;
118 		bufferSize--;
119 	}
120 
121 	// read from console
122 	if (bufferSize > 0) {
123 		ssize_t bytesRead = ConsoleHandle::ReadAt(NULL, 0, buffer, bufferSize);
124 		if (bytesRead < 0)
125 			return bytesRead;
126 		bytesTotal += bytesRead;
127 	}
128 
129 	return bytesTotal;
130 }
131 
132 
133 void
134 InputConsoleHandle::PutChar(char c)
135 {
136 	if (fCount >= BUFFER_SIZE)
137 		return;
138 
139 	int pos = (fStart + fCount) % BUFFER_SIZE;
140 	fBuffer[pos] = c;
141 	fCount++;
142 }
143 
144 
145 void
146 InputConsoleHandle::PutChars(const char *buffer, int count)
147 {
148 	for (int i = 0; i < count; i++)
149 		PutChar(buffer[i]);
150 }
151 
152 
153 char
154 InputConsoleHandle::GetChar()
155 {
156 	if (fCount == 0)
157 		return 0;
158 
159 	fCount--;
160 	char c = fBuffer[fStart];
161 	fStart = (fStart + 1) % BUFFER_SIZE;
162 	return c;
163 }
164 
165 
166 //	#pragma mark -
167 
168 
169 static void
170 dump_colors()
171 {
172 	int bg, fg;
173 	dprintf("colors:\n");
174 	for (bg = 0; bg < 16; bg++) {
175 		for (fg = 0; fg < 16; fg++) {
176 			console_set_color(fg, bg);
177 			dprintf("#");
178 		}
179 		console_set_color(0, 15);
180 		dprintf("\n");
181 	}
182 }
183 
184 
185 static int32
186 dump_milan_modes(SCREENINFO *info, uint32 flags)
187 {
188 	dprintf("mode: %d '%s':\n flags %08lx @%08lx %dx%d (%dx%d)\n%d planes %d colors fmt %08lx\n",
189 		info->devID, info->name, info->scrFlags, info->frameadr,
190 		info->scrWidth, info->scrHeight,
191 		info->virtWidth, info->virtHeight,
192 		info->scrPlanes, info->scrColors, info->scrFormat);
193 	return ENUMMODE_CONT;
194 }
195 
196 status_t
197 console_init(void)
198 {
199 	sInput.SetHandle(DEV_CONSOLE);
200 	sOutput.SetHandle(DEV_CONSOLE);
201 
202 	// now that we're initialized, enable stdio functionality
203 	stdin = (FILE *)&sInput;
204 	stdout = stderr = (FILE *)&sOutput;
205 
206 	if (tos_find_cookie('_MIL')) {
207 		dprintf("Milan detected... forcing black & white\n");
208 		/*
209 		dprintf("Getrez() = %d\n", Getrez());
210 		Setscreen(-1, &dump_milan_modes, MI_MAGIC, CMD_ENUMMODES);
211 		Setscreen((void*)-1, (void*)-1, 0, 0);
212 		*/
213 		sForceBW = true;
214 	}
215 	//dump_colors();
216 
217 	return B_OK;
218 }
219 
220 
221 // #pragma mark -
222 
223 
224 void
225 console_clear_screen(void)
226 {
227 	sInput.WriteAt(NULL, 0LL, "\033E", 2);
228 }
229 
230 
231 int32
232 console_width(void)
233 {
234 	int columnCount = 80; //XXX: check video mode
235 	return columnCount;
236 }
237 
238 
239 int32
240 console_height(void)
241 {
242 	int lineCount = 25; //XXX: check video mode
243 	return lineCount;
244 }
245 
246 
247 void
248 console_set_cursor(int32 x, int32 y)
249 {
250 	char buff[] = "\033Y  ";
251 	x = MIN(79,MAX(0,x));
252 	y = MIN(24,MAX(0,y));
253 	buff[3] += (char)x;
254 	buff[2] += (char)y;
255 	sInput.WriteAt(NULL, 0LL, buff, 4);
256 }
257 
258 
259 static int
260 translate_color(int32 color)
261 {
262 	/*
263 			r	g	b
264 		0:	0	0	0		// black
265 		1:	0	0	aa		// dark blue
266 		2:	0	aa	0		// dark green
267 		3:	0	aa	aa		// cyan
268 		4:	aa	0	0		// dark red
269 		5:	aa	0	aa		// purple
270 		6:	aa	55	0		// brown
271 		7:	aa	aa	aa		// light gray
272 		8:	55	55	55		// dark gray
273 		9:	55	55	ff		// light blue
274 		a:	55	ff	55		// light green
275 		b:	55	ff	ff		// light cyan
276 		c:	ff	55	55		// light red
277 		d:	ff	55	ff		// magenta
278 		e:	ff	ff	55		// yellow
279 		f:	ff	ff	ff		// white
280 	*/
281 	// cf. http://www.fortunecity.com/skyscraper/apple/308/html/chap4.htm
282 	static const char cmap[] = {
283 		15, 4, 2, 6, 1, 5, 3, 7,
284 		8, 12, 10, 14, 9, 13, 11, 0 };
285 
286 	if (color < 0 && color >= 16)
287 		return 0;
288 	return cmap[color];
289 	//return color;
290 }
291 
292 
293 void
294 console_set_color(int32 foreground, int32 background)
295 {
296 	char buff[] = "\033b \033c ";
297 	if (sForceBW) {
298 		if (background == 0)
299 			foreground = 15;
300 		else {
301 			background = 15;
302 			foreground = 0;
303 		}
304 
305 	}
306 	buff[2] += (char)translate_color(foreground);
307 	buff[5] += (char)translate_color(background);
308 	sInput.WriteAt(NULL, 0LL, buff, 6);
309 }
310 
311 
312 void
313 console_show_cursor(void)
314 {
315 }
316 
317 
318 void
319 console_hide_cursor(void)
320 {
321 }
322 
323 
324 int
325 console_wait_for_key(void)
326 {
327 #if 0
328 	// XXX: do this way and remove keyboard.cpp ?
329 	// wait for a key
330 	char buffer[3];
331 	ssize_t bytesRead;
332 	do {
333 		bytesRead = sInput.ReadAt(NULL, 0, buffer, 3);
334 		if (bytesRead < 0)
335 			return 0;
336 	} while (bytesRead == 0);
337 #endif
338 	union key key = wait_for_key();
339 
340 	if (key.code.ascii == 0) {
341 		switch (key.code.bios) {
342 			case BIOS_KEY_UP:
343 				return TEXT_CONSOLE_KEY_UP;
344 			case BIOS_KEY_DOWN:
345 				return TEXT_CONSOLE_KEY_DOWN;
346 			case BIOS_KEY_PAGE_UP:
347 				return TEXT_CONSOLE_KEY_PAGE_UP;
348 			case BIOS_KEY_PAGE_DOWN:
349 				return TEXT_CONSOLE_KEY_PAGE_DOWN;
350 			case BIOS_KEY_HOME:
351 				return TEXT_CONSOLE_KEY_HOME;
352 			case BIOS_KEY_END:
353 				return TEXT_CONSOLE_KEY_END;
354 			default:
355 				return 0;
356 		}
357 	} else
358 		return key.code.ascii;
359 }
360 
361