/* =============== VIDEO_SVGALIB.C =============== Video functions for SVGALIB */ #include #include "v9t9_common.h" #include "emulate.h" #include "error.h" #include "video.h" #include "vdp.h" #include "timer.h" #define _L LOG_VIDEO|LOG_INFO int vga_gfx_mode; static int tixsize, tiysize; static int xsize, ysize; static int xmult, ymult; static void video_setpaletteentry(int index, int c) { vga_setpalette(index, RGB_8_TO_6(vdp_palette[c][0]), RGB_8_TO_6(vdp_palette[c][1]), RGB_8_TO_6(vdp_palette[c][2])); } static void video_updatepalette(void) { int x; for (x = 1; x < 16; x++) video_setpaletteentry(x, x); video_setpaletteentry(0, vdpbg ? vdpbg : 1); video_setpaletteentry(16, vdpfg ? vdpfg : 15); } static int can_use_mode(int num) { vga_modeinfo *vi = vga_getmodeinfo(num); return (vi != NULL && vi->width >= 256 && vi->height >= 192 && vi->colors >= 16 && (vi->width * vi->height * vi->bytesperpixel < 65536 || (vi->flags & (CAPABLE_LINEAR | IS_LINEAR)))); } static int video_setmode(void) { int i; logger(_L|0, "Setting graphics mode\n"); if (vga_setmode(vga_gfx_mode)) return 0; vga_setlinearaddressing(); xsize = vga_getxdim(); ysize = vga_getydim(); xmult = xsize / 256; ymult = ysize / 192; for (i = 0; i < 16; i++) video_setpaletteentry(i, i); return 1; } static void video_settext(void) { logger(_L|0, "Setting text mode\n"); vga_setmode(TEXT); } //static int video_event_tag; extern int console_fd; extern int __svgalib_runinbackground; static vmResult svgavideo_detect(void) { // __svgalib_runinbackground = 1; return console_fd > 0 ? vmOk : vmNotAvailable; } static vmResult svgavideo_init(void) { static int goodmodes[] = { G320x200x256, G320x240x256, 0 }; int x; features |= FE_SHOWVIDEO; vga_init(); for (x = 0; goodmodes[x]; x++) { logger(_L|LOG_USER, "SVGALIB detecting mode %d... ", goodmodes[x]); if (can_use_mode(goodmodes[x])) break; logger(_L|LOG_USER, "\n"); } vga_setmode(TEXT); if (!goodmodes[x]) { logger(_L|LOG_USER, "no suitable VGA modes found.\n"); return vmConfigError; } else { logger(_L|LOG_USER, "succeeded.\n"); vga_gfx_mode = goodmodes[x]; return vmOk; } } static vmResult svgavideo_enable(void) { logger(_L|LOG_USER, "SVGALIB testing mode %d... ", vga_gfx_mode); if (can_use_mode(vga_gfx_mode)) { logger(_L|LOG_USER, "success.\n"); return vmOk; } logger(_L|LOG_USER, "cannot use this mode.\n"); return vmConfigError; } static vmResult svgavideo_disable(void) { return vmOk; } static vmResult svgavideo_restart(void) { //#warning FE_VIDEO if (features & FE_SHOWVIDEO) { if (!video_setmode()) { logger(_L|LOG_USER|LOG_ERROR, "Could not restore permissions for SVGAlib\n"); return vmNotAvailable; } video_updatepalette(); // TM_SetEvent(video_event_tag, TM_HZ*100/30, 0, // TM_REPEAT|TM_FUNC, video_update); } return vmOk; } static vmResult svgavideo_restop(void) { //#warning FE_VIDEO if (features & FE_SHOWVIDEO) { // TM_ResetEvent(video_event_tag); video_settext(); } return vmOk; } static vmResult svgavideo_term(void) { logger(_L|LOG_USER, "Shutting down video... "); if (vga_getcurrentmode() != TEXT) { vga_setdisplaystart(0); // seems to work vga_setmode(TEXT); } logger(_L|LOG_USER, "done.\n"); return vmOk; } static vmResult svgavideo_resize(u32 newxsize, u32 newysize) { u8 *a; int y, b; int yoffs; u8 *n; b = xsize - (newxsize * xmult / 2); yoffs = ysize / 2 - (newysize * ymult / 2); if (b > 0) { n = (u8 *)alloca(b); memset(n, 0, b); a = vga_getgraphmem() + yoffs * UPDATEBLOCK_ROW_STRIDE; for (y = 0; y < newysize * ymult; y++) { if (vga_gfx_mode != G320x200x256) { vga_drawscansegment(n, 0, y + yoffs, b); vga_drawscansegment(n, xsize - b, y + yoffs, b); } else { memset(a, 0, b); memset(a + xsize - b, 0, b); a += UPDATEBLOCK_ROW_STRIDE; } } } tixsize = newxsize; tiysize = newysize; return vmOk; } static vmResult svgavideo_setfgbg(u8 fg, u8 bg) { video_setpaletteentry(0, bg ? bg : 1); video_setpaletteentry(16, fg ? fg : 15); // video_updatepalette(); return vmOk; } static vmResult svgavideo_setblank(u8 bg) { int x; for (x = 1; x <= 15; x++) video_setpaletteentry(x, bg ? bg : 1); return vmOk; } static vmResult svgavideo_resetfromblank(void) { video_updatepalette(); return vmOk; } /***********************************************************/ static void update_list(struct updateblock *ptr, int num) { int i; int width=8; int xoffs, yoffs; u8 *scrn, *video; video = vga_getgraphmem(); if (!video) return; xoffs = (xsize / 2) - (width == 6 ? 120 : 128); yoffs = (ysize / 2) - 96; while (num--) { if (vga_gfx_mode != G320x200x256) { for (i = 0; i < 8; i++) { vga_drawscansegment(ptr->data, ptr->c + xoffs, yoffs + ptr->r++, width); ptr->data += UPDATEBLOCK_ROW_STRIDE; } } else { scrn = video + ((yoffs + ptr->r) * xsize) + ptr->c + xoffs; for (i = 0; i < 8; i++) { memcpy(scrn, ptr->data, width); ptr->data += UPDATEBLOCK_ROW_STRIDE; scrn += xsize; } } ptr++; } } static vmResult svgavideo_updatelist(struct updateblock *ptr, int num) { update_list(ptr, num); return vmOk; } static vmVideoModule svgavideo_videoModule = { 3, svgavideo_updatelist, svgavideo_resize, svgavideo_setfgbg, svgavideo_setblank, svgavideo_resetfromblank }; vmModule svgaVideo = { 3, "SVGALIB video", "vidSVGA", vmTypeVideo, vmFlagsExclusive, svgavideo_detect, svgavideo_init, svgavideo_term, svgavideo_enable, svgavideo_disable, svgavideo_restart, svgavideo_restop, {(vmGenericModule *) & svgavideo_videoModule} };