diff options
author | Torne Wuff <torne@wolfpuppy.org.uk> | 2010-01-17 22:15:13 +0000 |
---|---|---|
committer | Torne Wuff <torne@wolfpuppy.org.uk> | 2010-01-17 22:15:13 +0000 |
commit | 7f28c94eda576e3f972fc05468188986f2e45885 (patch) | |
tree | e03b94613028d16855a5d3df0f4853e077931214 /apps/plugins/frotz/dumb_output.c | |
parent | 563f2602f471208cb8544a36539a79dcceaad643 (diff) | |
download | rockbox-7f28c94eda576e3f972fc05468188986f2e45885.tar.gz rockbox-7f28c94eda576e3f972fc05468188986f2e45885.zip |
New plugin: frotz, a Z-machine interpreter, for playing interactive fiction.
The interpreter more or less passes all the tests in the z-machine test suite.
It should build for every target except Archos (for which it is disabled).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24267 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/frotz/dumb_output.c')
-rw-r--r-- | apps/plugins/frotz/dumb_output.c | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/apps/plugins/frotz/dumb_output.c b/apps/plugins/frotz/dumb_output.c new file mode 100644 index 0000000000..eb61419195 --- /dev/null +++ b/apps/plugins/frotz/dumb_output.c | |||
@@ -0,0 +1,256 @@ | |||
1 | /* dumb-output.c | ||
2 | * $Id: dumb-output.c,v 1.2 2002/03/26 22:52:31 feedle Exp $ | ||
3 | * | ||
4 | * Copyright 1997,1998 Alfresco Petrofsky <alfresco@petrofsky.berkeley.edu>. | ||
5 | * Any use permitted provided this notice stays intact. | ||
6 | * | ||
7 | * Changes for Rockbox copyright 2009 Torne Wuff | ||
8 | * | ||
9 | * Rockbox is not really a dumb terminal (it supports printing text wherever | ||
10 | * you like) but it doesn't implement a terminal type buffer, so this is | ||
11 | * close enough to be a good starting point. Keeping a copy of the graphical | ||
12 | * framebuffer would be too expensive, text+attributes is much smaller. | ||
13 | */ | ||
14 | |||
15 | #include "dumb_frotz.h" | ||
16 | |||
17 | /* The in-memory state of the screen. */ | ||
18 | /* Each cell contains a style in the upper byte and a char in the lower. */ | ||
19 | typedef unsigned short cell; | ||
20 | static cell screen_data[(LCD_WIDTH/SYSFONT_WIDTH) * (LCD_HEIGHT/SYSFONT_HEIGHT)]; | ||
21 | |||
22 | static cell make_cell(int style, char c) {return (style << 8) | (0xff & c);} | ||
23 | static char cell_char(cell c) {return c & 0xff;} | ||
24 | static int cell_style(cell c) {return c >> 8;} | ||
25 | |||
26 | static int current_style = 0; | ||
27 | static int cursor_row = 0, cursor_col = 0; | ||
28 | |||
29 | static cell *dumb_row(int r) {return screen_data + r * h_screen_cols;} | ||
30 | |||
31 | int os_char_width (zchar z) | ||
32 | { | ||
33 | (void)z; | ||
34 | return 1; | ||
35 | } | ||
36 | |||
37 | int os_string_width (const zchar *s) | ||
38 | { | ||
39 | int width = 0; | ||
40 | zchar c; | ||
41 | |||
42 | while ((c = *s++) != 0) | ||
43 | if (c == ZC_NEW_STYLE || c == ZC_NEW_FONT) | ||
44 | s++; | ||
45 | else | ||
46 | width += os_char_width(c); | ||
47 | |||
48 | return width; | ||
49 | } | ||
50 | |||
51 | void os_set_cursor(int row, int col) | ||
52 | { | ||
53 | cursor_row = row - 1; cursor_col = col - 1; | ||
54 | if (cursor_row >= h_screen_rows) | ||
55 | cursor_row = h_screen_rows - 1; | ||
56 | } | ||
57 | |||
58 | /* Set a cell */ | ||
59 | static void dumb_set_cell(int row, int col, cell c) | ||
60 | { | ||
61 | dumb_row(row)[col] = c; | ||
62 | } | ||
63 | |||
64 | void os_set_text_style(int x) | ||
65 | { | ||
66 | current_style = x & REVERSE_STYLE; | ||
67 | } | ||
68 | |||
69 | static void dumb_display_cell(int row, int col) | ||
70 | { | ||
71 | cell cel = dumb_row(row)[col]; | ||
72 | char c = cell_char(cel); | ||
73 | if (!c) | ||
74 | c = ' '; | ||
75 | char style = cell_style(cel); | ||
76 | char s[5]; | ||
77 | char *end = rb->utf8encode(c, s); | ||
78 | *end = 0; | ||
79 | if (style & REVERSE_STYLE) | ||
80 | rb->lcd_set_drawmode(DRMODE_INVERSEVID); | ||
81 | rb->lcd_putsxy(col * SYSFONT_WIDTH, row * SYSFONT_HEIGHT, s); | ||
82 | rb->lcd_set_drawmode(DRMODE_SOLID); | ||
83 | } | ||
84 | |||
85 | /* put a character in the cell at the cursor and advance the cursor. */ | ||
86 | static void dumb_display_char(char c) | ||
87 | { | ||
88 | dumb_set_cell(cursor_row, cursor_col, make_cell(current_style, c)); | ||
89 | if (++cursor_col == h_screen_cols) { | ||
90 | if (cursor_row == h_screen_rows - 1) | ||
91 | cursor_col--; | ||
92 | else { | ||
93 | cursor_row++; | ||
94 | cursor_col = 0; | ||
95 | } | ||
96 | } | ||
97 | } | ||
98 | |||
99 | void os_display_char (zchar c) | ||
100 | { | ||
101 | if (c >= ZC_LATIN1_MIN /*&& c <= ZC_LATIN1_MAX*/) { | ||
102 | dumb_display_char(c); | ||
103 | } else if (c >= 32 && c <= 126) { | ||
104 | dumb_display_char(c); | ||
105 | } else if (c == ZC_GAP) { | ||
106 | dumb_display_char(' '); dumb_display_char(' '); | ||
107 | } else if (c == ZC_INDENT) { | ||
108 | dumb_display_char(' '); dumb_display_char(' '); dumb_display_char(' '); | ||
109 | } | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | |||
114 | /* Haxor your boxor? */ | ||
115 | void os_display_string (const zchar *s) | ||
116 | { | ||
117 | zchar c; | ||
118 | |||
119 | while ((c = *s++) != 0) | ||
120 | if (c == ZC_NEW_FONT) | ||
121 | s++; | ||
122 | else if (c == ZC_NEW_STYLE) | ||
123 | os_set_text_style(*s++); | ||
124 | else { | ||
125 | os_display_char (c); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | void os_erase_area (int top, int left, int bottom, int right) | ||
130 | { | ||
131 | int row; | ||
132 | top--; left--; bottom--; right--; | ||
133 | if (left == 0 && right == h_screen_cols - 1) | ||
134 | rb->memset(dumb_row(top), 0, (bottom - top + 1) * h_screen_cols * sizeof(cell)); | ||
135 | else | ||
136 | for (row = top; row <= bottom; row++) | ||
137 | rb->memset(dumb_row(row) + left, 0, (right - left + 1) * sizeof(cell)); | ||
138 | } | ||
139 | |||
140 | void os_scroll_area (int top, int left, int bottom, int right, int units) | ||
141 | { | ||
142 | int row; | ||
143 | top--; left--; bottom--; right--; | ||
144 | if (units > 0) { | ||
145 | for (row = top; row <= bottom - units; row++) | ||
146 | rb->memcpy(dumb_row(row) + left, | ||
147 | dumb_row(row + units) + left, | ||
148 | (right - left + 1) * sizeof(cell)); | ||
149 | os_erase_area(bottom - units + 2, left + 1, bottom + 1, right + 1); | ||
150 | } else if (units < 0) { | ||
151 | for (row = bottom; row >= top - units; row--) | ||
152 | rb->memcpy(dumb_row(row) + left, | ||
153 | dumb_row(row + units) + left, | ||
154 | (right - left + 1) * sizeof(cell)); | ||
155 | os_erase_area(top + 1, left + 1, top - units, right + 1); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | int os_font_data(int font, int *height, int *width) | ||
160 | { | ||
161 | if (font == TEXT_FONT) { | ||
162 | *height = 1; *width = 1; return 1; | ||
163 | } | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | void os_set_colour (int x, int y) { (void)x; (void)y; } | ||
168 | void os_set_font (int x) { (void)x; } | ||
169 | |||
170 | /* Unconditionally show whole screen. */ | ||
171 | void dumb_dump_screen(void) | ||
172 | { | ||
173 | int r, c; | ||
174 | rb->lcd_clear_display(); | ||
175 | for (r = 0; r < h_screen_height; r++) | ||
176 | for (c = 0; c < h_screen_width; c++) | ||
177 | dumb_display_cell(r, c); | ||
178 | rb->lcd_update(); | ||
179 | } | ||
180 | |||
181 | /* Show the current screen contents. */ | ||
182 | void dumb_show_screen(bool show_cursor) | ||
183 | { | ||
184 | (void)show_cursor; | ||
185 | dumb_dump_screen(); | ||
186 | } | ||
187 | |||
188 | void os_more_prompt(void) | ||
189 | { | ||
190 | int old_row = cursor_row; | ||
191 | int old_col = cursor_col; | ||
192 | int old_style = current_style; | ||
193 | |||
194 | current_style = REVERSE_STYLE; | ||
195 | os_display_string("[MORE]"); | ||
196 | wait_for_key(); | ||
197 | |||
198 | cursor_row = old_row; | ||
199 | cursor_col = old_col; | ||
200 | current_style = old_style; | ||
201 | os_erase_area(cursor_row+1, cursor_col+1, cursor_row+1, cursor_col+7); | ||
202 | } | ||
203 | |||
204 | void os_reset_screen(void) | ||
205 | { | ||
206 | current_style = REVERSE_STYLE; | ||
207 | os_display_string("[Press key to exit]"); | ||
208 | wait_for_key(); | ||
209 | } | ||
210 | |||
211 | |||
212 | /* To make the common code happy */ | ||
213 | |||
214 | void os_prepare_sample (int a) { (void)a; } | ||
215 | void os_finish_with_sample (int a) { (void)a; } | ||
216 | void os_start_sample (int a, int b, int c, zword d) | ||
217 | { | ||
218 | (void)a; (void)b; (void)c; (void)d; | ||
219 | } | ||
220 | void os_stop_sample (int a) { (void)a; } | ||
221 | |||
222 | void dumb_init_output(void) | ||
223 | { | ||
224 | if (h_version == V3) { | ||
225 | h_config |= CONFIG_SPLITSCREEN; | ||
226 | h_flags &= ~OLD_SOUND_FLAG; | ||
227 | } | ||
228 | |||
229 | if (h_version >= V5) { | ||
230 | h_flags &= ~SOUND_FLAG; | ||
231 | } | ||
232 | |||
233 | h_screen_height = h_screen_rows; | ||
234 | h_screen_width = h_screen_cols; | ||
235 | |||
236 | h_font_width = 1; h_font_height = 1; | ||
237 | |||
238 | os_erase_area(1, 1, h_screen_rows, h_screen_cols); | ||
239 | } | ||
240 | |||
241 | bool os_picture_data(int num, int *height, int *width) | ||
242 | { | ||
243 | (void)num; | ||
244 | *height = 0; | ||
245 | *width = 0; | ||
246 | return FALSE; | ||
247 | } | ||
248 | |||
249 | void os_draw_picture (int num, int row, int col) | ||
250 | { | ||
251 | (void)num; | ||
252 | (void)row; | ||
253 | (void)col; | ||
254 | } | ||
255 | |||
256 | int os_peek_colour (void) {return BLACK_COLOUR; } | ||