From 7f28c94eda576e3f972fc05468188986f2e45885 Mon Sep 17 00:00:00 2001 From: Torne Wuff Date: Sun, 17 Jan 2010 22:15:13 +0000 Subject: 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 --- apps/plugins/frotz/dumb_output.c | 256 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 apps/plugins/frotz/dumb_output.c (limited to 'apps/plugins/frotz/dumb_output.c') 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 @@ +/* dumb-output.c + * $Id: dumb-output.c,v 1.2 2002/03/26 22:52:31 feedle Exp $ + * + * Copyright 1997,1998 Alfresco Petrofsky . + * Any use permitted provided this notice stays intact. + * + * Changes for Rockbox copyright 2009 Torne Wuff + * + * Rockbox is not really a dumb terminal (it supports printing text wherever + * you like) but it doesn't implement a terminal type buffer, so this is + * close enough to be a good starting point. Keeping a copy of the graphical + * framebuffer would be too expensive, text+attributes is much smaller. + */ + +#include "dumb_frotz.h" + +/* The in-memory state of the screen. */ +/* Each cell contains a style in the upper byte and a char in the lower. */ +typedef unsigned short cell; +static cell screen_data[(LCD_WIDTH/SYSFONT_WIDTH) * (LCD_HEIGHT/SYSFONT_HEIGHT)]; + +static cell make_cell(int style, char c) {return (style << 8) | (0xff & c);} +static char cell_char(cell c) {return c & 0xff;} +static int cell_style(cell c) {return c >> 8;} + +static int current_style = 0; +static int cursor_row = 0, cursor_col = 0; + +static cell *dumb_row(int r) {return screen_data + r * h_screen_cols;} + +int os_char_width (zchar z) +{ + (void)z; + return 1; +} + +int os_string_width (const zchar *s) +{ + int width = 0; + zchar c; + + while ((c = *s++) != 0) + if (c == ZC_NEW_STYLE || c == ZC_NEW_FONT) + s++; + else + width += os_char_width(c); + + return width; +} + +void os_set_cursor(int row, int col) +{ + cursor_row = row - 1; cursor_col = col - 1; + if (cursor_row >= h_screen_rows) + cursor_row = h_screen_rows - 1; +} + +/* Set a cell */ +static void dumb_set_cell(int row, int col, cell c) +{ + dumb_row(row)[col] = c; +} + +void os_set_text_style(int x) +{ + current_style = x & REVERSE_STYLE; +} + +static void dumb_display_cell(int row, int col) +{ + cell cel = dumb_row(row)[col]; + char c = cell_char(cel); + if (!c) + c = ' '; + char style = cell_style(cel); + char s[5]; + char *end = rb->utf8encode(c, s); + *end = 0; + if (style & REVERSE_STYLE) + rb->lcd_set_drawmode(DRMODE_INVERSEVID); + rb->lcd_putsxy(col * SYSFONT_WIDTH, row * SYSFONT_HEIGHT, s); + rb->lcd_set_drawmode(DRMODE_SOLID); +} + +/* put a character in the cell at the cursor and advance the cursor. */ +static void dumb_display_char(char c) +{ + dumb_set_cell(cursor_row, cursor_col, make_cell(current_style, c)); + if (++cursor_col == h_screen_cols) { + if (cursor_row == h_screen_rows - 1) + cursor_col--; + else { + cursor_row++; + cursor_col = 0; + } + } +} + +void os_display_char (zchar c) +{ + if (c >= ZC_LATIN1_MIN /*&& c <= ZC_LATIN1_MAX*/) { + dumb_display_char(c); + } else if (c >= 32 && c <= 126) { + dumb_display_char(c); + } else if (c == ZC_GAP) { + dumb_display_char(' '); dumb_display_char(' '); + } else if (c == ZC_INDENT) { + dumb_display_char(' '); dumb_display_char(' '); dumb_display_char(' '); + } + return; +} + + +/* Haxor your boxor? */ +void os_display_string (const zchar *s) +{ + zchar c; + + while ((c = *s++) != 0) + if (c == ZC_NEW_FONT) + s++; + else if (c == ZC_NEW_STYLE) + os_set_text_style(*s++); + else { + os_display_char (c); + } +} + +void os_erase_area (int top, int left, int bottom, int right) +{ + int row; + top--; left--; bottom--; right--; + if (left == 0 && right == h_screen_cols - 1) + rb->memset(dumb_row(top), 0, (bottom - top + 1) * h_screen_cols * sizeof(cell)); + else + for (row = top; row <= bottom; row++) + rb->memset(dumb_row(row) + left, 0, (right - left + 1) * sizeof(cell)); +} + +void os_scroll_area (int top, int left, int bottom, int right, int units) +{ + int row; + top--; left--; bottom--; right--; + if (units > 0) { + for (row = top; row <= bottom - units; row++) + rb->memcpy(dumb_row(row) + left, + dumb_row(row + units) + left, + (right - left + 1) * sizeof(cell)); + os_erase_area(bottom - units + 2, left + 1, bottom + 1, right + 1); + } else if (units < 0) { + for (row = bottom; row >= top - units; row--) + rb->memcpy(dumb_row(row) + left, + dumb_row(row + units) + left, + (right - left + 1) * sizeof(cell)); + os_erase_area(top + 1, left + 1, top - units, right + 1); + } +} + +int os_font_data(int font, int *height, int *width) +{ + if (font == TEXT_FONT) { + *height = 1; *width = 1; return 1; + } + return 0; +} + +void os_set_colour (int x, int y) { (void)x; (void)y; } +void os_set_font (int x) { (void)x; } + +/* Unconditionally show whole screen. */ +void dumb_dump_screen(void) +{ + int r, c; + rb->lcd_clear_display(); + for (r = 0; r < h_screen_height; r++) + for (c = 0; c < h_screen_width; c++) + dumb_display_cell(r, c); + rb->lcd_update(); +} + +/* Show the current screen contents. */ +void dumb_show_screen(bool show_cursor) +{ + (void)show_cursor; + dumb_dump_screen(); +} + +void os_more_prompt(void) +{ + int old_row = cursor_row; + int old_col = cursor_col; + int old_style = current_style; + + current_style = REVERSE_STYLE; + os_display_string("[MORE]"); + wait_for_key(); + + cursor_row = old_row; + cursor_col = old_col; + current_style = old_style; + os_erase_area(cursor_row+1, cursor_col+1, cursor_row+1, cursor_col+7); +} + +void os_reset_screen(void) +{ + current_style = REVERSE_STYLE; + os_display_string("[Press key to exit]"); + wait_for_key(); +} + + +/* To make the common code happy */ + +void os_prepare_sample (int a) { (void)a; } +void os_finish_with_sample (int a) { (void)a; } +void os_start_sample (int a, int b, int c, zword d) +{ + (void)a; (void)b; (void)c; (void)d; +} +void os_stop_sample (int a) { (void)a; } + +void dumb_init_output(void) +{ + if (h_version == V3) { + h_config |= CONFIG_SPLITSCREEN; + h_flags &= ~OLD_SOUND_FLAG; + } + + if (h_version >= V5) { + h_flags &= ~SOUND_FLAG; + } + + h_screen_height = h_screen_rows; + h_screen_width = h_screen_cols; + + h_font_width = 1; h_font_height = 1; + + os_erase_area(1, 1, h_screen_rows, h_screen_cols); +} + +bool os_picture_data(int num, int *height, int *width) +{ + (void)num; + *height = 0; + *width = 0; + return FALSE; +} + +void os_draw_picture (int num, int row, int col) +{ + (void)num; + (void)row; + (void)col; +} + +int os_peek_colour (void) {return BLACK_COLOUR; } -- cgit v1.2.3