This is video.c in view mode; [Download] [Up]
/* * video.c - MS-DOS graphics handling, based on the Allegro library by Shawn * Hargreaves (http://www.talula.demon.co.uk/allegro). * * Written by * Ettore Perazzoli (ettore@comm2000.it) * * This file is part of VICE, the Versatile Commodore Emulator. * See README for copyright notice. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. * */ #include "vice.h" #include <stdio.h> #include <string.h> #include "video.h" #include "cmdline.h" #include "kbd.h" #include "resources.h" #include "tui.h" /* #define DEBUG_VIDEO */ vga_mode_t vga_modes[] = { /* VGA_320x200 */ { 320, 200, "320x200" }, /* VGA_360x240 */ { 360, 240, "360x240" }, /* VGA_360x270 */ { 360, 270, "360x270" }, /* VGA_376x282 */ { 376, 282, "376x282" }, /* VGA_400x300 */ { 400, 300, "400x300" }, /* VGA_640x480 */ { 640, 480, "640x480" } }; canvas_t last_canvas; #ifdef DEBUG_VIDEO #define DEBUG(x) \ do { \ printf("%s, %d: ", __FUNCTION__, __LINE__); \ printf x; \ putchar('\n'); \ } while (0) #else #define DEBUG(x) #endif /* Flag: are we in graphics mode? */ static int in_gfx_mode; /* ------------------------------------------------------------------------- */ /* Video-related resources. */ /* VGA Video mode to use. */ static int vga_mode; static int set_vga_mode(resource_value_t v) { /* FIXME: Sanity check! */ vga_mode = (int) v; return 0; } #ifndef USE_MIDAS_SOUND /* Flag: do we try to use triple buffering if possible? */ static int try_triple_buffering; static int set_try_triple_buffering(resource_value_t v) { /* FIXME: this has only effect when we switch to gfx mode. This is OK for now, but is not the correct behavior. */ try_triple_buffering = (int) v; return 0; } #endif static resource_t resources[] = { { "VGAMode", RES_INTEGER, (resource_value_t) VGA_320x200, (resource_value_t *) &vga_mode, set_vga_mode }, #ifndef USE_MIDAS_SOUND { "TripleBuffering", RES_INTEGER, (resource_value_t) 0, (resource_value_t *) &try_triple_buffering, set_try_triple_buffering }, #endif { NULL } }; int video_init_resources(void) { return resources_register(resources); } /* ------------------------------------------------------------------------- */ /* Video-specific command-line options. */ static cmdline_option_t cmdline_options[] = { { "-vgamode", SET_RESOURCE, 1, NULL, NULL, "VGAMode", NULL, "<mode>", "Set VGA mode to <mode>" }, #ifndef USE_MIDAS_SOUND { "-triplebuf", SET_RESOURCE, 0, NULL, NULL, "TripleBuffering", (resource_value_t) 1, NULL, "Try to use triple buffering when possible" }, { "+triplebuf", SET_RESOURCE, 0, NULL, NULL, "TripleBuffering", (resource_value_t) 1, NULL, "Disable usage of triple buffering" }, #endif { NULL } }; int video_init_cmdline_options(void) { return cmdline_register_options(cmdline_options); } /* ------------------------------------------------------------------------- */ int video_init(void) { if (allegro_init()) { fprintf(stderr, "??? Cannot initialize the Allegro library ???\n"); exit(-1); } printf("Allegro initialized.\n"); in_gfx_mode = 0; return 0; } int frame_buffer_alloc(frame_buffer_t *i, unsigned int width, unsigned int height) { DEBUG(("Allocating bitmap width=%d, height=%d", width, height)); *i = create_bitmap(width, height); if (*i == NULL) { DEBUG(("Bitmap allocation failed")); return -1; } else { DEBUG(("Bitmap allocation successful")); return 0; } } void frame_buffer_free(frame_buffer_t *i) { DEBUG(("Freeing frame buffer 0x%x", (unsigned int)i)); destroy_bitmap(*i); } void frame_buffer_clear(frame_buffer_t * f, BYTE value) { int i; DEBUG(("Clearing frame buffer 0x%x with value 0x%x", (unsigned int)f, value)); for (i = 0; i < (*f)->h; i++) memset((*f)->line[i], value, (*f)->w); } static void canvas_set_vga_mode(canvas_t c) { int i; #ifndef USE_MIDAS_SOUND /* If the user wants triple buffering, try Mode X first of all, as that is (currently) the only reliable way to achieve the result. Virtual height is twice visible height to allow smooth page flipping. */ if (try_triple_buffering && (set_gfx_mode(GFX_MODEX, c->width, c->height, 0, c->height * 2) >= 0)) { DEBUG(("GFX_MODEX successful with width=%d height=%d vheight=%d", c->width, c->height, c->height * 2)); c->use_triple_buffering = 1; } else #endif /* If we don't want triple buffering, try to get a VESA linear mode first, which might not be the default. */ if (set_gfx_mode(GFX_VESA2L, c->width, c->height, 0, 0) >= 0) { DEBUG(("GFX_VESA2L successful with width=%d height=%d", c->width, c->height)); c->use_triple_buffering = 0; } else if (set_gfx_mode(GFX_AUTODETECT, c->width, c->height, 0, 0) >= 0) { DEBUG(("GFX_AUTODETECT successful with width=%d height=%d", c->width, c->height)); c->use_triple_buffering = 0; } else { fprintf(stderr, "Cannot enable %dx%dx256 graphics.\n", c->width, c->height); exit(-1); } printf("Using mode %dx%dx256 (%s)%s.\n", c->width, c->height, is_linear_bitmap(screen) ? "linear" : "planar", c->use_triple_buffering ? "; triple buffering possible" : ""); in_gfx_mode = 1; #ifndef USE_MIDAS_SOUND /* If using triple buffering, setup the timer used by Allegro to emulate vertical retrace interrupts. Wish I had $D012/$D011 on VGA. */ timer_simulate_retrace(c->use_triple_buffering); #endif if (c->use_triple_buffering) { c->pages[0] = create_sub_bitmap(screen, 0, 0, c->width, c->height); c->pages[1] = create_sub_bitmap(screen, 0, c->height, c->width, c->height); c->back_page = 1; } for (i = 0; i < NUM_AVAILABLE_COLORS; i++) set_color(i, &c->colors[i]); } /* Note: `mapped' is ignored. */ canvas_t canvas_create(const char *win_name, unsigned int *width, unsigned int *height, int mapped, canvas_redraw_t exposure_handler, const palette_t *palette, PIXEL *pixel_return) { int i; canvas_t new_canvas; DEBUG(("Creating canvas width=%d height=%d", *width, *height)); if (palette->num_entries > NUM_AVAILABLE_COLORS) { fprintf(stderr, "??? Too many colors requested! ???\n"); return (canvas_t) NULL; } new_canvas = (canvas_t) malloc(sizeof(struct _canvas)); if (!new_canvas) return (canvas_t) NULL; canvas_set_palette(new_canvas, palette, pixel_return); /* Set width and height. */ canvas_resize(new_canvas, 0, 0); *width = new_canvas->width; *height = new_canvas->height; DEBUG(("Setting VGA mode")); canvas_set_vga_mode(new_canvas); new_canvas->exposure_handler = exposure_handler; new_canvas->back_page = 1; last_canvas = new_canvas; return new_canvas; } int canvas_set_palette(canvas_t c, const palette_t *palette, PIXEL *pixel_return) { int i; DEBUG(("Allocating colors")); for (i = 0; i < palette->num_entries; i++) { c->colors[i].r = palette->entries[i].red >> 2; c->colors[i].g = palette->entries[i].green >> 2; c->colors[i].b = palette->entries[i].blue >> 2; pixel_return[i] = i; if (in_gfx_mode) set_color(i, &c->colors[i]); } return 0; } void canvas_map(canvas_t c) { /* Not implemented. */ } void canvas_unmap(canvas_t c) { /* Not implemented. */ } /* Warning: this does not do what you would expect from it. It just sets the canvas size according to the `VGAMode' resource. */ void canvas_resize(canvas_t c, unsigned int width, unsigned int height) { DEBUG(("Resizing, vga_mode=%d", vga_mode)); c->width = vga_modes[vga_mode].width; c->height = vga_modes[vga_mode].height; } void video_ack_vga_mode(void) { if (last_canvas != NULL) { canvas_resize(last_canvas, last_canvas->width, last_canvas->height); last_canvas->exposure_handler(last_canvas->width, last_canvas->height); DEBUG(("Acknowledged vgaMode %d", vga_mode)); } } /* ------------------------------------------------------------------------- */ void enable_text(void) { DEBUG(("Enabling text mode")); kbd_uninstall(); set_gfx_mode(GFX_TEXT, 80, 25, 0, 0); _set_screen_lines(25); DEBUG(("Successful")); in_gfx_mode = 0; } void disable_text(void) { DEBUG(("Enabling gfx mode")); kbd_install(); if (last_canvas->width > 0 && last_canvas->height > 0) { int i; video_ack_vga_mode(); canvas_set_vga_mode(last_canvas); for (i = 0; i < NUM_AVAILABLE_COLORS; i++) set_color(i, &last_canvas->colors[i]); last_canvas->exposure_handler(last_canvas->width, last_canvas->height); in_gfx_mode = 1; } DEBUG(("Successful")); } int num_text_lines(void) { return tui_num_lines(); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.