xref: /haiku/src/system/boot/platform/atari_m68k/console.cpp (revision a944d6a02d6f0543fd4b6863455463e282c4a75e)
1c2b8af8bSFrançois Revol /*
2*a944d6a0SDavid Karoly  * Copyright 2007-2023, Haiku, Inc. All Rights Reserved.
3c2b8af8bSFrançois Revol  * Distributed under the terms of the MIT license.
4c2b8af8bSFrançois Revol  *
5c2b8af8bSFrançois Revol  * Author:
6c2b8af8bSFrançois Revol  *		François Revol, revol@free.fr.
7c2b8af8bSFrançois Revol  */
8c2b8af8bSFrançois Revol 
9c2b8af8bSFrançois Revol #include <SupportDefs.h>
10c2b8af8bSFrançois Revol #include <string.h>
11c2b8af8bSFrançois Revol #include "toscalls.h"
12c2b8af8bSFrançois Revol #include <util/kernel_cpp.h>
13c2b8af8bSFrançois Revol 
14c2b8af8bSFrançois Revol #include "console.h"
1513b1977cSFrançois Revol #include "keyboard.h"
16c2b8af8bSFrançois Revol 
17c2b8af8bSFrançois Revol 
184b9d7940SFrançois Revol static bool sForceBW = false;	// force black & white for Milan
194b9d7940SFrançois Revol 
204b9d7940SFrançois Revol 
21c2b8af8bSFrançois Revol // TOS emulates a VT52
22c2b8af8bSFrançois Revol 
23*a944d6a0SDavid Karoly class Console : public ConsoleNode {
24c2b8af8bSFrançois Revol 	public:
25*a944d6a0SDavid Karoly 		Console();
26c2b8af8bSFrançois Revol 
27c2b8af8bSFrançois Revol 		virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
28c2b8af8bSFrançois Revol 			size_t bufferSize);
29c2b8af8bSFrançois Revol 		virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
30c2b8af8bSFrançois Revol 			size_t bufferSize);
31c2b8af8bSFrançois Revol 
32*a944d6a0SDavid Karoly 		void ClearScreen();
33*a944d6a0SDavid Karoly 		int32 Width();
34*a944d6a0SDavid Karoly 		int32 Height();
35*a944d6a0SDavid Karoly 		void SetCursor(int32 x, int32 y);
36*a944d6a0SDavid Karoly 		void SetCursorVisible(bool visible);
37*a944d6a0SDavid Karoly 		void SetColors(int32 foreground, int32 background);
38c2b8af8bSFrançois Revol 	private:
39*a944d6a0SDavid Karoly 		int16 fHandle;
40c2b8af8bSFrançois Revol };
41c2b8af8bSFrançois Revol 
42c2b8af8bSFrançois Revol 
43*a944d6a0SDavid Karoly extern ConsoleNode* gConsoleNode;
44*a944d6a0SDavid Karoly static Console sConsole;
45c2b8af8bSFrançois Revol FILE *stdin, *stdout, *stderr;
46c2b8af8bSFrançois Revol 
47c2b8af8bSFrançois Revol 
Console()48*a944d6a0SDavid Karoly Console::Console()
49*a944d6a0SDavid Karoly 	: ConsoleNode(), fHandle(DEV_CONSOLE)
50c2b8af8bSFrançois Revol {
51c2b8af8bSFrançois Revol }
52c2b8af8bSFrançois Revol 
53c2b8af8bSFrançois Revol 
54c2b8af8bSFrançois Revol ssize_t
ReadAt(void *,off_t,void * buffer,size_t bufferSize)55*a944d6a0SDavid Karoly Console::ReadAt(void */*cookie*/, off_t /*pos*/, void *buffer,
56c2b8af8bSFrançois Revol 	size_t bufferSize)
57c2b8af8bSFrançois Revol {
58c2b8af8bSFrançois Revol 	// don't seek in character devices
59c2b8af8bSFrançois Revol 	// not implemented (and not yet? needed)
60c2b8af8bSFrançois Revol 	return B_ERROR;
61c2b8af8bSFrançois Revol }
62c2b8af8bSFrançois Revol 
63c2b8af8bSFrançois Revol 
64c2b8af8bSFrançois Revol ssize_t
WriteAt(void *,off_t,const void * buffer,size_t bufferSize)65*a944d6a0SDavid Karoly Console::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
66c2b8af8bSFrançois Revol 	size_t bufferSize)
67c2b8af8bSFrançois Revol {
68c2b8af8bSFrançois Revol 	const char *string = (const char *)buffer;
694f9d8b0eSFrançois Revol 	size_t i;
70c2b8af8bSFrançois Revol 
71c2b8af8bSFrançois Revol 	// be nice to our audience and replace single "\n" with "\r\n"
72c2b8af8bSFrançois Revol 
73c2b8af8bSFrançois Revol 	for (i = 0; i < bufferSize; i++) {
74b75f915aSFrançois Revol 		if (string[i] == '\0')
75b75f915aSFrançois Revol 			break;
76c2b8af8bSFrançois Revol 		if (string[i] == '\n')
77c2b8af8bSFrançois Revol 			Bconout(fHandle, '\r');
78c2b8af8bSFrançois Revol 		Bconout(fHandle, string[i]);
79c2b8af8bSFrançois Revol 	}
80c2b8af8bSFrançois Revol 
81c2b8af8bSFrançois Revol 	return bufferSize;
82c2b8af8bSFrançois Revol }
83c2b8af8bSFrançois Revol 
84c2b8af8bSFrançois Revol 
85c2b8af8bSFrançois Revol void
ClearScreen()86*a944d6a0SDavid Karoly Console::ClearScreen()
87c2b8af8bSFrançois Revol {
88*a944d6a0SDavid Karoly 	Write("\033E", 2);
89c2b8af8bSFrançois Revol }
90c2b8af8bSFrançois Revol 
91c2b8af8bSFrançois Revol 
92c2b8af8bSFrançois Revol int32
Width()93*a944d6a0SDavid Karoly Console::Width()
94c2b8af8bSFrançois Revol {
95*a944d6a0SDavid Karoly 	return 80;
96c2b8af8bSFrançois Revol }
97c2b8af8bSFrançois Revol 
98c2b8af8bSFrançois Revol 
99c2b8af8bSFrançois Revol int32
Height()100*a944d6a0SDavid Karoly Console::Height()
101c2b8af8bSFrançois Revol {
102*a944d6a0SDavid Karoly 	return 25;
103c2b8af8bSFrançois Revol }
104c2b8af8bSFrançois Revol 
105c2b8af8bSFrançois Revol 
106c2b8af8bSFrançois Revol void
SetCursor(int32 x,int32 y)107*a944d6a0SDavid Karoly Console::SetCursor(int32 x, int32 y)
108c2b8af8bSFrançois Revol {
109c2b8af8bSFrançois Revol 	char buff[] = "\033Y  ";
110b70fb738SFrançois Revol 	x = MIN(79,MAX(0,x));
111b70fb738SFrançois Revol 	y = MIN(24,MAX(0,y));
112c2b8af8bSFrançois Revol 	buff[3] += (char)x;
113c2b8af8bSFrançois Revol 	buff[2] += (char)y;
114*a944d6a0SDavid Karoly 	Write(buff, 4);
115c2b8af8bSFrançois Revol }
116c2b8af8bSFrançois Revol 
117c2b8af8bSFrançois Revol 
118*a944d6a0SDavid Karoly void
SetCursorVisible(bool visible)119*a944d6a0SDavid Karoly Console::SetCursorVisible(bool visible)
120*a944d6a0SDavid Karoly {
121*a944d6a0SDavid Karoly 	// TODO
122*a944d6a0SDavid Karoly }
123*a944d6a0SDavid Karoly 
124c2b8af8bSFrançois Revol static int
translate_color(int32 color)125c2b8af8bSFrançois Revol translate_color(int32 color)
126c2b8af8bSFrançois Revol {
127c2b8af8bSFrançois Revol 	/*
128c2b8af8bSFrançois Revol 			r	g	b
129c2b8af8bSFrançois Revol 		0:	0	0	0		// black
130c2b8af8bSFrançois Revol 		1:	0	0	aa		// dark blue
131c2b8af8bSFrançois Revol 		2:	0	aa	0		// dark green
132c2b8af8bSFrançois Revol 		3:	0	aa	aa		// cyan
133c2b8af8bSFrançois Revol 		4:	aa	0	0		// dark red
134c2b8af8bSFrançois Revol 		5:	aa	0	aa		// purple
135c2b8af8bSFrançois Revol 		6:	aa	55	0		// brown
136c2b8af8bSFrançois Revol 		7:	aa	aa	aa		// light gray
137c2b8af8bSFrançois Revol 		8:	55	55	55		// dark gray
138c2b8af8bSFrançois Revol 		9:	55	55	ff		// light blue
139c2b8af8bSFrançois Revol 		a:	55	ff	55		// light green
140c2b8af8bSFrançois Revol 		b:	55	ff	ff		// light cyan
141c2b8af8bSFrançois Revol 		c:	ff	55	55		// light red
142c2b8af8bSFrançois Revol 		d:	ff	55	ff		// magenta
143c2b8af8bSFrançois Revol 		e:	ff	ff	55		// yellow
144c2b8af8bSFrançois Revol 		f:	ff	ff	ff		// white
145c2b8af8bSFrançois Revol 	*/
14668b5c8deSFrançois Revol 	// cf. http://www.fortunecity.com/skyscraper/apple/308/html/chap4.htm
14768b5c8deSFrançois Revol 	static const char cmap[] = {
14868b5c8deSFrançois Revol 		15, 4, 2, 6, 1, 5, 3, 7,
14968b5c8deSFrançois Revol 		8, 12, 10, 14, 9, 13, 11, 0 };
15068b5c8deSFrançois Revol 
151a4a9dadeSLioncash 	if (color < 0 || color >= 16)
152c2b8af8bSFrançois Revol 		return 0;
15368b5c8deSFrançois Revol 	return cmap[color];
154c2b8af8bSFrançois Revol }
155c2b8af8bSFrançois Revol 
156c2b8af8bSFrançois Revol 
157c2b8af8bSFrançois Revol void
SetColors(int32 foreground,int32 background)158*a944d6a0SDavid Karoly Console::SetColors(int32 foreground, int32 background)
159c2b8af8bSFrançois Revol {
1609bc28239SFrançois Revol 	char buff[] = "\033b \033c ";
1614b9d7940SFrançois Revol 	if (sForceBW) {
1624b9d7940SFrançois Revol 		if (background == 0)
1634b9d7940SFrançois Revol 			foreground = 15;
1644b9d7940SFrançois Revol 		else {
1654b9d7940SFrançois Revol 			background = 15;
1664b9d7940SFrançois Revol 			foreground = 0;
1674b9d7940SFrançois Revol 		}
1684b9d7940SFrançois Revol 
1694b9d7940SFrançois Revol 	}
17068b5c8deSFrançois Revol 	buff[2] += (char)translate_color(foreground);
17168b5c8deSFrançois Revol 	buff[5] += (char)translate_color(background);
172*a944d6a0SDavid Karoly 	Write(buff, 6);
173b4aa5d34SRene Gollent }
174b4aa5d34SRene Gollent 
175b4aa5d34SRene Gollent 
176*a944d6a0SDavid Karoly //	#pragma mark -
177*a944d6a0SDavid Karoly 
178*a944d6a0SDavid Karoly 
179*a944d6a0SDavid Karoly constexpr bool kDumpColors = false;
180*a944d6a0SDavid Karoly constexpr bool kDumpMilanModes = false;
181*a944d6a0SDavid Karoly 
182*a944d6a0SDavid Karoly static void
dump_colors()183*a944d6a0SDavid Karoly dump_colors()
184b4aa5d34SRene Gollent {
185*a944d6a0SDavid Karoly 	int bg, fg;
186*a944d6a0SDavid Karoly 	dprintf("colors:\n");
187*a944d6a0SDavid Karoly 	for (bg = 0; bg < 16; bg++) {
188*a944d6a0SDavid Karoly 		for (fg = 0; fg < 16; fg++) {
189*a944d6a0SDavid Karoly 			console_set_color(fg, bg);
190*a944d6a0SDavid Karoly 			dprintf("#");
191*a944d6a0SDavid Karoly 		}
192*a944d6a0SDavid Karoly 		console_set_color(0, 15);
193*a944d6a0SDavid Karoly 		dprintf("\n");
194*a944d6a0SDavid Karoly 	}
195b4aa5d34SRene Gollent }
196b4aa5d34SRene Gollent 
197b4aa5d34SRene Gollent 
198*a944d6a0SDavid Karoly static int32
dump_milan_modes(SCREENINFO * info,uint32 flags)199*a944d6a0SDavid Karoly dump_milan_modes(SCREENINFO *info, uint32 flags)
200b4aa5d34SRene Gollent {
201*a944d6a0SDavid Karoly 	dprintf("mode: %d '%s':\n flags %08" B_PRIx32 " @%08" B_PRIx32 " %dx%d (%dx%d)\n%d planes %d colors fmt %08" B_PRIx32 "\n",
202*a944d6a0SDavid Karoly 		info->devID, info->name, info->scrFlags, info->frameadr,
203*a944d6a0SDavid Karoly 		info->scrWidth, info->scrHeight,
204*a944d6a0SDavid Karoly 		info->virtWidth, info->virtHeight,
205*a944d6a0SDavid Karoly 		info->scrPlanes, info->scrColors, info->scrFormat);
206*a944d6a0SDavid Karoly 	return ENUMMODE_CONT;
207c2b8af8bSFrançois Revol }
208c2b8af8bSFrançois Revol 
209*a944d6a0SDavid Karoly status_t
console_init(void)210*a944d6a0SDavid Karoly console_init(void)
211*a944d6a0SDavid Karoly {
212*a944d6a0SDavid Karoly 	gConsoleNode = &sConsole;
213*a944d6a0SDavid Karoly 
214*a944d6a0SDavid Karoly 	console_clear_screen();
215*a944d6a0SDavid Karoly 
216*a944d6a0SDavid Karoly 	// enable stdio functionality
217*a944d6a0SDavid Karoly 	stdin = (FILE *)&sConsole;
218*a944d6a0SDavid Karoly 	stdout = stderr = (FILE *)&sConsole;
219*a944d6a0SDavid Karoly 
220*a944d6a0SDavid Karoly 	if (tos_find_cookie('_MIL')) {
221*a944d6a0SDavid Karoly 		dprintf("Milan detected... forcing black & white\n");
222*a944d6a0SDavid Karoly 		if (kDumpMilanModes) {
223*a944d6a0SDavid Karoly 			dprintf("Getrez() = %d\n", Getrez());
224*a944d6a0SDavid Karoly 			Setscreen(-1, &dump_milan_modes, MI_MAGIC, CMD_ENUMMODES);
225*a944d6a0SDavid Karoly 			Setscreen((void*)-1, (void*)-1, 0, 0);
226*a944d6a0SDavid Karoly 		}
227*a944d6a0SDavid Karoly 		sForceBW = true;
228*a944d6a0SDavid Karoly 	}
229*a944d6a0SDavid Karoly 
230*a944d6a0SDavid Karoly 	if (kDumpColors)
231*a944d6a0SDavid Karoly 		dump_colors();
232*a944d6a0SDavid Karoly 
233*a944d6a0SDavid Karoly 	return B_OK;
234*a944d6a0SDavid Karoly }
235*a944d6a0SDavid Karoly 
236*a944d6a0SDavid Karoly 
237*a944d6a0SDavid Karoly // #pragma mark -
238*a944d6a0SDavid Karoly 
239c2b8af8bSFrançois Revol 
240c2b8af8bSFrançois Revol int
console_wait_for_key(void)241c2b8af8bSFrançois Revol console_wait_for_key(void)
242c2b8af8bSFrançois Revol {
2439d2f3035SFrançois Revol #if 0
2449d2f3035SFrançois Revol 	// XXX: do this way and remove keyboard.cpp ?
245c2b8af8bSFrançois Revol 	// wait for a key
246c2b8af8bSFrançois Revol 	char buffer[3];
247c2b8af8bSFrançois Revol 	ssize_t bytesRead;
248c2b8af8bSFrançois Revol 	do {
249c2b8af8bSFrançois Revol 		bytesRead = sInput.ReadAt(NULL, 0, buffer, 3);
250c2b8af8bSFrançois Revol 		if (bytesRead < 0)
251c2b8af8bSFrançois Revol 			return 0;
252c2b8af8bSFrançois Revol 	} while (bytesRead == 0);
2539d2f3035SFrançois Revol #endif
2549d2f3035SFrançois Revol 	union key key = wait_for_key();
255c2b8af8bSFrançois Revol 
2569d2f3035SFrançois Revol 	if (key.code.ascii == 0) {
2579d2f3035SFrançois Revol 		switch (key.code.bios) {
2589d2f3035SFrançois Revol 			case BIOS_KEY_UP:
259c2b8af8bSFrançois Revol 				return TEXT_CONSOLE_KEY_UP;
2609d2f3035SFrançois Revol 			case BIOS_KEY_DOWN:
261c2b8af8bSFrançois Revol 				return TEXT_CONSOLE_KEY_DOWN;
2629d2f3035SFrançois Revol 			case BIOS_KEY_PAGE_UP:
2639d2f3035SFrançois Revol 				return TEXT_CONSOLE_KEY_PAGE_UP;
2649d2f3035SFrançois Revol 			case BIOS_KEY_PAGE_DOWN:
2659d2f3035SFrançois Revol 				return TEXT_CONSOLE_KEY_PAGE_DOWN;
2669d2f3035SFrançois Revol 			case BIOS_KEY_HOME:
2679d2f3035SFrançois Revol 				return TEXT_CONSOLE_KEY_HOME;
2689d2f3035SFrançois Revol 			case BIOS_KEY_END:
2699d2f3035SFrançois Revol 				return TEXT_CONSOLE_KEY_END;
270c2b8af8bSFrançois Revol 			default:
2719d2f3035SFrançois Revol 				return 0;
272c2b8af8bSFrançois Revol 		}
2739d2f3035SFrançois Revol 	} else
2749d2f3035SFrançois Revol 		return key.code.ascii;
275c2b8af8bSFrançois Revol }
276c2b8af8bSFrançois Revol 
277