diff options
Diffstat (limited to 'private/mvdm/softpc.new/host/src/nt_cga.c')
-rw-r--r-- | private/mvdm/softpc.new/host/src/nt_cga.c | 1193 |
1 files changed, 1193 insertions, 0 deletions
diff --git a/private/mvdm/softpc.new/host/src/nt_cga.c b/private/mvdm/softpc.new/host/src/nt_cga.c new file mode 100644 index 000000000..512ee3ac8 --- /dev/null +++ b/private/mvdm/softpc.new/host/src/nt_cga.c @@ -0,0 +1,1193 @@ +/* + * SoftPC Revision 3.0 + * + * Title : Win32 CGA Graphics Module + * + * Description : + * + * This modules contain the Win32 specific functions required + * to support CGA emulations. + * + * Author : Jerry Sexton (based on module by John Shanly) + * + * Notes : + * + */ + +#include <windows.h> +#include <string.h> + +#include "insignia.h" +#include "host_def.h" + +#include "xt.h" +#include "gvi.h" +#include "gmi.h" +#include "sas.h" +#include "gfx_upd.h" + +#include "error.h" +#include <stdio.h> +#include "trace.h" +#include "debug.h" +#include "config.h" +#include "host_rrr.h" +#include "conapi.h" + +#include "nt_graph.h" +#include "nt_cga.h" +#include "nt_cgalt.h" +#include "nt_det.h" + +#ifdef MONITOR +#include <ntddvdeo.h> +#include "nt_fulsc.h" +#endif /* MONITOR */ + +/* Externs */ + + +extern char *image_buffer; + +/* Statics */ + +static unsigned int cga_med_graph_hi_nyb[256]; +static unsigned int cga_med_graph_lo_nyb[256]; +#ifdef BIGWIN +static unsigned int cga_med_graph_hi_lut_big[256]; +static unsigned int cga_med_graph_mid_lut_big[256]; +static unsigned int cga_med_graph_lo_lut_big[256]; + +static unsigned int cga_med_graph_lut4_huge[256]; +static unsigned int cga_med_graph_lut3_huge[256]; +static unsigned int cga_med_graph_lut2_huge[256]; +static unsigned int cga_med_graph_lut1_huge[256]; +#endif + +/* + * cga_graph_inc_val depends on whether data is interleaved ( EGA/VGA ) + * or not ( CGA ). Currently always interleaved. + */ +#define CGA_GRAPH_INCVAL 4 + +// likewise for TEXT_INCVAL +// for x86 we have 2 bytes per character (char and attr) +// for risc we have 4 bytes per character because of vga interleaving +// +#ifdef MONITOR +#define TEXT_INCVAL 2 +#else +#define TEXT_INCVAL 4 +#endif + + + + + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::::::: Initialise CGA text output ::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_init_text() +{ + half_word misc; + IMPORT void vga_misc_inb(io_addr, half_word *); + + /*::::::::::::::::::::::::::::::::::::: Tell trace program were we are */ + + sub_note_trace0(HERC_HOST_VERBOSE, "nt_init_text"); + +#ifdef X86GFX +if (sc.ScreenState == WINDOWED) //fullscreen valid - mouse buffer +#endif //X86GFX + closeGraphicsBuffer(); /* Tim Oct 92 */ + +#ifdef MONITOR + vga_misc_inb(0x3cc, &misc); + if (misc & 1) + set_screen_ptr((UTINY *)CGA_REGEN_BUFF); //point screen to regen not planes + else + set_screen_ptr((UTINY *)MDA_REGEN_BUFF); //0xb0000 not 0xb8000 +#endif //MONITOR +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::: Init CGA mono graph ::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_init_cga_mono_graph() +{ + sub_note_trace0(CGA_HOST_VERBOSE,"nt_init_cga_mono_graph - NOT SUPPORTED"); +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::::::: Init CGA colour med graphics:::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + + +void nt_init_cga_colour_med_graph() +{ + static boolean cga_colour_med_deja_vu = FALSE; + unsigned int i, + byte1, + byte2, + byte3, + byte4; + + sub_note_trace0(CGA_HOST_VERBOSE, "nt_init_cga_colour_med_graph"); + + /* Set up bits-per-pixel for current mode. */ + sc.BitsPerPixel = CGA_BITS_PER_PIXEL; + + /* Initialise look-up table for first call. */ + if( !cga_colour_med_deja_vu ) + { + for (i = 0; i < 256; i++) + { + byte1 = i & 0x03; + byte2 = ( i & 0x0C ) >> 2; + byte3 = ( i & 0x30 ) >> 4; + byte4 = ( i & 0xC0 ) >> 6; + +#ifdef BIGEND + cga_med_graph_hi_nyb[i] + = ( byte4 << 24 ) | ( byte4 << 16) + | ( byte3 << 8 ) | byte3; + cga_med_graph_lo_nyb[i] + = ( byte2 << 24 ) | ( byte2 << 16) + | ( byte1 << 8 ) | byte1; + +#ifdef BIGWIN + cga_med_graph_hi_lut_big[i] + = ( byte4 << 24 ) | ( byte4 << 16) + | ( byte4 << 8 ) | byte3; + cga_med_graph_mid_lut_big[i] + = ( byte3 << 24) | ( byte3 << 16 ) + | ( byte2 << 8 ) | byte2; + cga_med_graph_lo_lut_big[i] + = ( byte2 << 24 ) | ( byte1 << 16) + | ( byte1 << 8 ) | byte1; + + cga_med_graph_lut4_huge[i] + = ( byte4 << 24 ) | ( byte4 << 16) + | ( byte4 << 8 ) | byte4; + + cga_med_graph_lut3_huge[i] + = ( byte3 << 24 ) | ( byte3 << 16) + | ( byte3 << 8 ) | byte3; + + cga_med_graph_lut2_huge[i] + = ( byte2 << 24 ) | ( byte2 << 16) + | ( byte2 << 8 ) | byte2; + + cga_med_graph_lut1_huge[i] + = ( byte1 << 24 ) | ( byte1 << 16) + | ( byte1 << 8 ) | byte1; +#endif /* BIGWIN */ +#endif /* BIGEND */ + +#ifdef LITTLEND + cga_med_graph_hi_nyb[i] + = ( byte3 << 24 ) | ( byte3 << 16) + | ( byte4 << 8 ) | byte4; + cga_med_graph_lo_nyb[i] + = ( byte1 << 24 ) | ( byte1 << 16) + | ( byte2 << 8 ) | byte2; + +#ifdef BIGWIN + cga_med_graph_hi_lut_big[i] + = ( byte3 << 24 ) | ( byte4 << 16) + | ( byte4 << 8 ) | byte4; + cga_med_graph_mid_lut_big[i] + = ( byte2 << 24) | ( byte2 << 16 ) + | ( byte3 << 8 ) | byte3; + cga_med_graph_lo_lut_big[i] + = ( byte1 << 24 ) | ( byte1 << 16) + | ( byte1 << 8 ) | byte2; + + cga_med_graph_lut4_huge[i] + = ( byte4 << 24 ) | ( byte4 << 16) + | ( byte4 << 8 ) | byte4; + + cga_med_graph_lut3_huge[i] + = ( byte3 << 24 ) | ( byte3 << 16) + | ( byte3 << 8 ) | byte3; + + cga_med_graph_lut2_huge[i] + = ( byte2 << 24 ) | ( byte2 << 16) + | ( byte2 << 8 ) | byte2; + + cga_med_graph_lut1_huge[i] + = ( byte1 << 24 ) | ( byte1 << 16) + | ( byte1 << 8 ) | byte1; +#endif /* BIGWIN */ +#endif /* LITTLEND */ + + } + + cga_colour_med_deja_vu = TRUE; + } +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::: Init CGA colour hi graphics:::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + + +void nt_init_cga_colour_hi_graph() +{ + sub_note_trace0(CGA_HOST_VERBOSE,"nt_init_cga_colour_hi_graph"); + + /* Set up bits-per-pixel for current mode. */ + sc.BitsPerPixel = MONO_BITS_PER_PIXEL; +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::::::::::::: Output CGA text :::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +IMPORT int now_height, now_width; + +void nt_text(int ScreenOffset, int ScreenX, int ScreenY, + int len, int height) +{ + int org_clen, org_height; + int clen=len/2; + int lines; + SMALL_RECT WriteRegion; + PBYTE to; + PBYTE pScreenText = get_screen_ptr(ScreenOffset); + + /*:::::::::::::::::::::::::::::::::::::::::::: Output trace information */ + + sub_note_trace6( CGA_HOST_VERBOSE, + "nt_cga_text off=%d x=%d y=%d len=%d h=%d o=%#x", + ScreenOffset, ScreenX, ScreenY, len, height, pScreenText ); + + /*:::::::::::::: Adjust re-paint start location from pixels to characters */ + +#ifndef MONITOR + /* Adjust for RISC parameters being in pixels */ + ScreenX = ScreenX / get_pix_char_width(); + ScreenY = ScreenY / get_host_char_height(); +#endif + + /*:: Clip requested re-paint region to currently selected console buffer */ + + //Clip width + if(ScreenX + clen > now_width) + { + /* Is it possible to adjust the repaint regions width */ + if(ScreenX+1 >= now_width) + { + assert4(NO,"VDM: nt_text() repaint region out of ranged x:%d y:%d w:%d h:%d\n", + ScreenX, ScreenY, clen, height); + return; + } + + //Calculate maximum width + org_clen = clen; + clen = now_width - ScreenX; + + assert2(NO,"VDM: nt_text() repaint region width clipped from %d to %d\n", + org_clen,clen); + } + + //Clip height + if(ScreenY + height > now_height) + { + /* Is it possible to adjust the repaint regions height */ + if(ScreenY+1 >= now_height) + { + assert4(NO,"VDM: nt_text() repaint region out of ranged x:%d y:%d w:%d h:%d\n", + ScreenX, ScreenY, clen, height); + return; + } + + //Calculate maximum height + org_height = height; + height = now_height - ScreenY; + + assert2(NO,"VDM: nt_text() repaint region height clipped from %d to %d\n", + org_height,clen); + } + + if (get_chars_per_line() == 80) + { + // + // Slam Dunk Screen text buffer into shared buffer + // by copying full width blocks instead of subrecs. + // + RtlCopyMemory(&textBuffer[(ScreenY*get_offset_per_line()/2 + ScreenX)*TEXT_INCVAL], + pScreenText, + (((height - 1)*get_offset_per_line()/2) + clen)*TEXT_INCVAL + ); + } + else + { + // the sharing buffer width never changes((80 chars, decided at the + // moment we make the RegisterConsoleVDM call to the console). + // We have to do some transformation when our screen width is not + // 80. + + // note that the sharing buffer has different format on x86 and RISC + // platforms. On x86, a cell is defined as: + // typedef _x86cell { + // byte char; + // byte attributes; + // } + // on RISC, a cell is defined as: + // typedef _RISCcell { + // byte char; + // byte attributes; + // byte reserved_1; + // byte reserved_2; + // } + // the size of each cell was defined by TEXT_INCVAL + // + // this is done so we can use memcpy for each line. + // + + + /*::::::::::::::::::::::::::::::::::::::::::::: Construct output buffer */ + //Start location of repaint region + to = &textBuffer[(ScreenY*80 + ScreenX) * TEXT_INCVAL]; + + for(lines = height; lines; lines--) + { + RtlCopyMemory(to, pScreenText, clen * TEXT_INCVAL); // copy this line + pScreenText += get_chars_per_line() * TEXT_INCVAL; // update src ptr + to += 80 * TEXT_INCVAL; // update dst ptr + } + } + + + /*:::::::::::::::::::::::::::::::::::::::::::::: Calculate write region */ + + WriteRegion.Left = ScreenX; + WriteRegion.Top = ScreenY; + + WriteRegion.Bottom = WriteRegion.Top + height - 1; + WriteRegion.Right = WriteRegion.Left + clen - 1; + + /*:::::::::::::::::::::::::::::::::::::::::::::::::: Display characters */ + + sub_note_trace4( CGA_HOST_VERBOSE, "t=%d l=%d b=%d r=%d", + WriteRegion.Top, WriteRegion.Left, + WriteRegion.Bottom, WriteRegion.Right, + ); + + if(!InvalidateConsoleDIBits(sc.OutputHandle, &WriteRegion)){ + /* + ** We get a rare failure here due to the WriteRegion + ** rectangle being bigger than the screen. + ** Dump out some values and see if it tells us anything. + ** Have also attempted to fix it by putting a delay between + ** the start of a register level mode change and window resize. + */ + assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x", + GetLastError() ); + assert4( NO, "VDM: rectangle t:%d l:%d b:%d r:%d", + WriteRegion.Top, WriteRegion.Left, + WriteRegion.Bottom, WriteRegion.Right + ); + assert2( NO, "VDM: bpl=%d sl=%d", + get_bytes_per_line(), get_screen_length() ); + } + +} /* end of nt_text() */ + + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::: Paints CGA graphics for a mono monitor, in a standard window :::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_cga_mono_graph_std(int offset, int screen_x, int screen_y, + int len, int height ) +{ +sub_note_trace5(CGA_HOST_VERBOSE, + "nt_cga_mono_graph_std off=%d x=%d y=%d len=%d height=%d - NOT SUPPORTED\n", + offset, screen_x, screen_y, len, height); +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::: Paints CGA graphics for a mono monitor, in a big window :::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_cga_mono_graph_big(int offset, int screen_x, int screen_y, + int len, int height) +{ +sub_note_trace5(CGA_HOST_VERBOSE, + "nt_cga_mono_graph_big off=%d x=%d y=%d len=%d height=%d - NOT SUPPORTED\n", + offset, screen_x, screen_y, len, height); +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::: Paints CGA graphics for a mono monitor, in a huge window ::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_cga_mono_graph_huge(int offset, int screen_x, int screen_y, + int len, int height) +{ +sub_note_trace5( CGA_HOST_VERBOSE, + "nt_cga_mono_graph_huge off=%d x=%d y=%d len=%d height=%d - NOT SUPPORTED\n", + offset, screen_x, screen_y, len, height ); +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/* Paints CGA medium res graphics for a colour monitor,in a standard window */ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_cga_colour_med_graph_std(int offset, int screen_x, int screen_y, + int len, int height) +{ + UTINY *intelmem_ptr; + ULONG *graph_ptr; + LONG local_len, + bytes_per_scanline, + longs_per_scanline; + ULONG inc; + SMALL_RECT rect; + static int rejections=0; /* Stop floods of rejected messages */ + + sub_note_trace5(CGA_HOST_VERBOSE, + "nt_cga_colour_med_graph_std off=%d x=%d y=%d len=%d height=%d\n", + offset, screen_x, screen_y, len, height ); + + /* + ** Tim Jan 93, rapid mode changes cause mismatch between update and + ** paint rountines. Ignore paint request when invalid parameter + ** causes crash. + */ + if( screen_y > 400 ){ + assert1( NO, "VDM: med gfx std rejected y=%d\n", screen_y ); + return; + } + + /* + ** Tim September 92, bounce call if handle to screen buffer is null. + ** This can happen when VDM session is about to suspend, buffer has + ** been closed, but still get a paint request. + */ + if( sc.ScreenBufHandle == (HANDLE)NULL ){ + if( rejections==0 ){ + assert0( NO, "VDM: rejected paint request due to NULL handle" ); + rejections = 1; + } + return; + }else{ + rejections = 0; + } + + /* Clip image to screen */ + if(height > 1 || len > 80) + height = 1; + if (len>80) + len = 80; + + /* Work out the width of a line (ie 640 pixels) in chars and ints. */ + bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo); + longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo); + + /* Grab the mutex. */ + GrabMutex(sc.ConsoleBufInfo.hMutex); + + + /* Build up DIB. */ + inc = offset & 1 ? 3 : 1; + intelmem_ptr = get_screen_ptr(offset); + graph_ptr = (ULONG *) ((UTINY *) sc.ConsoleBufInfo.lpBitMap + + (screen_y * bytes_per_scanline + screen_x)); + local_len = len; + do + { + *(graph_ptr + longs_per_scanline) = *graph_ptr = + cga_med_graph_hi_nyb[*intelmem_ptr]; + graph_ptr++; + + *(graph_ptr + longs_per_scanline) = *graph_ptr = + cga_med_graph_lo_nyb[*intelmem_ptr]; + graph_ptr++; + + intelmem_ptr += inc; + inc ^= 2; + } + while( --local_len ); + + /* Release the mutex. */ + RelMutex(sc.ConsoleBufInfo.hMutex); + + /* Display the new image. */ + rect.Left = screen_x; + rect.Top = screen_y; + rect.Right = rect.Left + (len << 3) - 1; + rect.Bottom = rect.Top + (height << 1) - 1; + + if( sc.ScreenBufHandle ) + { + if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect)) + assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x", + GetLastError() ); + //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__); + } +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:: Paints CGA medium res graphics for a colour monitor, in a big window ::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_cga_colour_med_graph_big(int offset, int screen_x, int screen_y, + int len, int height) +{ +#ifdef BIGWIN + UTINY *intelmem_ptr; + ULONG *graph_ptr; + LONG local_len, + bytes_per_scanline, + longs_per_scanline; + ULONG inc; + SMALL_RECT rect; + + sub_note_trace5(CGA_HOST_VERBOSE, + "nt_cga_colour_med_graph_big off=%d x=%d y=%d len=%d height=%d\n", + offset, screen_x, screen_y, len, height); + + /* + ** Tim Jan 93, rapid mode changes cause mismatch between update and + ** paint rountines. Ignore paint request when invalid parameter + ** causes crash. + */ + if( screen_y > 400 ){ + assert1( NO, "VDM: med gfx big rejected y=%d\n", screen_y ); + return; + } + + /* + ** Tim September 92, bounce call if handle to screen buffer is null. + ** This can happen when VDM session is about to suspend, buffer has + ** been closed, but still get a paint request. + */ + if( sc.ScreenBufHandle == (HANDLE)NULL ){ + assert0( NO, "VDM: rejected paint request due to NULL handle" ); + return; + } + + /* Clip to window */ + height = 1; + if (len > 80) + len = 80; + + bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo); + longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo); + inc = offset & 1 ? 3 : 1; + intelmem_ptr = get_screen_ptr(offset); + graph_ptr = (ULONG *) ((UTINY *) sc.ConsoleBufInfo.lpBitMap + + SCALE(screen_y * bytes_per_scanline + screen_x)); + local_len = len; + + /* Grab the mutex. */ + GrabMutex(sc.ConsoleBufInfo.hMutex); + + do + { + *(graph_ptr + 2 * longs_per_scanline) = + *(graph_ptr + longs_per_scanline) = + *graph_ptr = + cga_med_graph_hi_lut_big[*intelmem_ptr]; + graph_ptr++; + + *(graph_ptr + 2 * longs_per_scanline) = + *(graph_ptr + longs_per_scanline) = + *graph_ptr = + cga_med_graph_mid_lut_big[*intelmem_ptr]; + graph_ptr++; + + *(graph_ptr + 2 * longs_per_scanline) = + *(graph_ptr + longs_per_scanline) = + *graph_ptr = + cga_med_graph_lo_lut_big[*intelmem_ptr]; + graph_ptr++; + + intelmem_ptr += inc; + inc ^= 2; + } + while( --local_len ); + + /* Release the mutex. */ + RelMutex(sc.ConsoleBufInfo.hMutex); + + /* Display the new image. */ + rect.Left = SCALE(screen_x); + rect.Top = SCALE(screen_y); + rect.Right = rect.Left + SCALE(len << 3) - 1; + rect.Bottom = rect.Top + SCALE(height << 1) - 1; + + if( sc.ScreenBufHandle ) + if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect)) + assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x", + GetLastError() ); + //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__); +#endif /* BIGWIN */ +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*: Paints CGA medium res graphics for a colour monitor, in a huge window. :*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_cga_colour_med_graph_huge(int offset, int screen_x, int screen_y, + int len, int height) +{ +#ifdef BIGWIN + UTINY *intelmem_ptr; + ULONG *graph_ptr; + LONG local_len, + bytes_per_scanline, + longs_per_scanline; + ULONG inc; + SMALL_RECT rect; + + sub_note_trace5(CGA_HOST_VERBOSE, + "nt_cga_colour_med_graph_huge off=%d x=%d y=%d len=%d height=%d\n", + offset, screen_x, screen_y, len, height ); + + /* + ** Tim Jan 93, rapid mode changes cause mismatch between update and + ** paint rountines. Ignore paint request when invalid parameter + ** causes crash. + */ + if( screen_y > 400 ){ + assert1( NO, "VDM: med gfx huge rejected y=%d\n", screen_y ); + return; + } + + /* + ** Tim September 92, bounce call if handle to screen buffer is null. + ** This can happen when VDM session is about to suspend, buffer has + ** been closed, but still get a paint request. + */ + if( sc.ScreenBufHandle == (HANDLE)NULL ){ + assert0( NO, "VDM: rejected paint request due to NULL handle" ); + return; + } + + /* Clip to window */ + height = 1; + if (len > 80) + len = 80; + + bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo); + longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo); + inc = offset & 1 ? 3 : 1; + intelmem_ptr = get_screen_ptr(offset); + graph_ptr = (ULONG *) ((UTINY *) sc.ConsoleBufInfo.lpBitMap + + SCALE(screen_y * bytes_per_scanline + screen_x)); + local_len = len; + + /* Grab the mutex. */ + GrabMutex(sc.ConsoleBufInfo.hMutex); + + do + { + *(graph_ptr + 3 * longs_per_scanline) = + *(graph_ptr + 2 * longs_per_scanline) = + *(graph_ptr + longs_per_scanline) = + *graph_ptr = cga_med_graph_lut4_huge[*intelmem_ptr]; + graph_ptr++; + + *(graph_ptr + 3 * longs_per_scanline) = + *(graph_ptr + 2 * longs_per_scanline) = + *(graph_ptr + longs_per_scanline) = + *graph_ptr = cga_med_graph_lut3_huge[*intelmem_ptr]; + graph_ptr++; + + *(graph_ptr + 3 * longs_per_scanline) = + *(graph_ptr + 2 * longs_per_scanline) = + *(graph_ptr + longs_per_scanline) = + *graph_ptr = cga_med_graph_lut2_huge[*intelmem_ptr]; + graph_ptr++; + + *(graph_ptr + 3 * longs_per_scanline) = + *(graph_ptr + 2 * longs_per_scanline) = + *(graph_ptr + longs_per_scanline) = + *graph_ptr = cga_med_graph_lut1_huge[*intelmem_ptr]; + graph_ptr++; + + intelmem_ptr += inc; + inc ^= 2; + } + while(--local_len); + + /* Release the mutex. */ + RelMutex(sc.ConsoleBufInfo.hMutex); + + /* Display the new image. */ + rect.Left = SCALE(screen_x); + rect.Top = SCALE(screen_y); + rect.Right = rect.Left + SCALE(len << 3) - 1; + rect.Bottom = rect.Top + SCALE(height << 1) - 1; + + if( sc.ScreenBufHandle ) + if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect)) + assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x", + GetLastError() ); + //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__); +#endif /* BIGWIN */ +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*: Paints CGA high res graphics for a colour monitor, in a standard window */ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_cga_colour_hi_graph_std(int offset, int screen_x, int screen_y, + int len, int height) +{ + register char *intelmem, + *bufptr; + register int i; + int bytes_per_scanline; + SMALL_RECT rect; + static int rejections=0; /* Stop floods of rejected messages */ + + sub_note_trace5(CGA_HOST_VERBOSE, + "nt_cga_colour_hi_graph_std off=%d x=%d y=%d len=%d height=%d\n", + offset, screen_x, screen_y, len, height ); + + /* + ** Tim September 92, bounce call if handle to screen buffer is null. + ** This can happen when VDM session is about to suspend, buffer has + ** been closed, but still get a paint request. + */ + if( sc.ScreenBufHandle == (HANDLE)NULL ){ + if( rejections == 0 ){ + assert0( NO, "VDM: rejected paint request due to NULL handle" ); + rejections = 1; + } + return; + }else + rejections=0; + + /* Clip to window */ + height = 1; + if (len > 80) + len = 80; + + /* Work out offset, in bytes, of pixel directly below current pixel. */ + bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo); + + /* Grab the mutex. */ + GrabMutex(sc.ConsoleBufInfo.hMutex); + + /* + * Build up DIB data. In 200-line CGA mode, pixels are double height so + * one line of PC pixels is equivalent to two lines of host pixels. + * Note: `height' parameter is always 1 when this function is called so + * only 1 line at a time is updated. + */ + intelmem = (char *) get_screen_ptr(offset); + + bufptr = (char *) sc.ConsoleBufInfo.lpBitMap + + screen_y * bytes_per_scanline + + (screen_x >> 3); + for( i = len; i > 0; i-- ) + { + *(bufptr + bytes_per_scanline) = *bufptr = *intelmem; + intelmem += CGA_GRAPH_INCVAL; + bufptr++; + } + + /* Release the mutex. */ + RelMutex(sc.ConsoleBufInfo.hMutex); + + /* Display the new image. */ + rect.Left = screen_x; + rect.Top = screen_y; + rect.Right = rect.Left + (len << 3) - 1; + rect.Bottom = rect.Top + (height << 1) - 1; + + if( sc.ScreenBufHandle ) + if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect)) + assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x", + GetLastError() ); + //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__); +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::: Paints CGA high res graphics for a colour monitor, in a big window :::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_cga_colour_hi_graph_big(int offset, int screen_x, int screen_y, + int len, int height) +{ +#ifdef BIGWIN + register char *intelmem, + *bufptr; + register int i; + char *buffer; + int bytes_per_scanline; + SMALL_RECT rect; + + sub_note_trace5(CGA_HOST_VERBOSE, + "nt_cga_colour_hi_graph_big off=%d x=%d y=%d len=%d height=%d\n", + offset, screen_x, screen_y, len, height ); + /* + ** Tim September 92, bounce call if handle to screen buffer is null. + ** This can happen when VDM session is about to suspend, buffer has + ** been closed, but still get a paint request. + */ + if( sc.ScreenBufHandle == (HANDLE)NULL ){ + assert0( NO, "VDM: rejected paint request due to NULL handle" ); + return; + } + + /* Clip to window */ + height = 1; + if (len > 80) + len = 80; + + /* + * In this mode each byte becomes 12 bits (1.5 screen size) so if screen_x + * is on an odd byte boundary the resulting bitmap starts on a half-byte + * boundary. To avoid this set screen_x to the previous even byte. + */ + if (screen_x & 8) + { + screen_x -= 8; + offset -= CGA_GRAPH_INCVAL; + len++; + } + + /* `len' must be even for `high_stretch3' to work. */ + if (len & 1) + len++; + + bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo); + bufptr = buffer = (char *) sc.ConsoleBufInfo.lpBitMap + + SCALE(screen_y * bytes_per_scanline + (screen_x >> 3)); + intelmem = (char *) get_screen_ptr(offset); + + /* Grab the mutex. */ + GrabMutex(sc.ConsoleBufInfo.hMutex); + + for(i = len; i > 0; i--) + { + *bufptr = *intelmem; + intelmem += CGA_GRAPH_INCVAL; + bufptr++; + } + + high_stretch3((unsigned char *) buffer, len); + + memcpy(buffer + bytes_per_scanline, buffer, SCALE(len)); + memcpy(buffer + 2 * bytes_per_scanline, buffer, SCALE(len)); + + /* Release the mutex. */ + RelMutex(sc.ConsoleBufInfo.hMutex); + + /* Display the new image. */ + rect.Left = SCALE(screen_x); + rect.Top = SCALE(screen_y); + rect.Right = rect.Left + SCALE(len << 3) - 1; + rect.Bottom = rect.Top + SCALE(height << 1) - 1; + + if( sc.ScreenBufHandle ) + if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect)) + assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x", + GetLastError() ); + //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__); +#endif /* BIGWIN */ +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::: Paints CGA high res graphics for a colour monitor, in a huge window ::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_cga_colour_hi_graph_huge(int offset, int screen_x, int screen_y, + int len, int height ) +{ +#ifdef BIGWIN + register char *intelmem, + *bufptr; + char *buffer; + register int i; + int bytes_per_scanline; + SMALL_RECT rect; + + sub_note_trace5(CGA_HOST_VERBOSE, + "nt_cga_colour_hi_graph_huge off=%d x=%d y=%d len=%d height=%d\n", + offset, screen_x, screen_y, len, height ); + /* + ** Tim September 92, bounce call if handle to screen buffer is null. + ** This can happen when VDM session is about to suspend, buffer has + ** been closed, but still get a paint request. + */ + if( sc.ScreenBufHandle == (HANDLE)NULL ){ + assert0( NO, "VDM: rejected paint request due to NULL handle" ); + return; + } + + /* Clip to window */ + height = 1; + if (len > 80) + len = 80; + + bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo); + intelmem = (char *) get_screen_ptr(offset); + bufptr = buffer = (char *) sc.ConsoleBufInfo.lpBitMap + + SCALE(screen_y * bytes_per_scanline + (screen_x >> 3)); + + /* Grab the mutex. */ + GrabMutex(sc.ConsoleBufInfo.hMutex); + + for( i = len; i > 0; i-- ) + { + *bufptr = *intelmem; + intelmem += CGA_GRAPH_INCVAL; + bufptr++; + } + + high_stretch4((unsigned char *) buffer, len); + + memcpy(buffer + bytes_per_scanline, buffer, SCALE(len)); + memcpy(buffer + 2 * bytes_per_scanline, buffer, SCALE(len)); + memcpy(buffer + 3 * bytes_per_scanline, buffer, SCALE(len)); + + /* Release the mutex. */ + RelMutex(sc.ConsoleBufInfo.hMutex); + + /* Display the new image. */ + rect.Left = SCALE(screen_x); + rect.Top = SCALE(screen_y); + rect.Right = rect.Left + SCALE(len << 3) - 1; + rect.Bottom = rect.Top + SCALE(height << 1) - 1; + + if( sc.ScreenBufHandle ) + if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect)) + assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x", + GetLastError() ); + //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__); +#endif /* BIGWIN */ +} + +#ifdef MONITOR +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/* Paints CGA medium res graphics frozen window. */ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_cga_med_frozen_std(int offset, int screen_x, int screen_y, int len, + int height) +{ + UTINY *plane1_ptr, + *plane2_ptr, + data; + ULONG *graph_ptr, + longs_per_scanline, + local_len, + mem_x = screen_x >> 3, + mem_y = screen_y >> 1, + max_width = sc.PC_W_Width >> 3, + max_height = sc.PC_W_Height >> 1; + SMALL_RECT rect; + + sub_note_trace5(CGA_HOST_VERBOSE, + "nt_cga_med_frozen_std off=%d x=%d y=%d len=%d height=%d\n", + offset, screen_x, screen_y, len, height ); + + /* + ** Tim September 92, bounce call if handle to screen buffer is null. + ** This can happen when VDM session is about to suspend, buffer has + ** been closed, but still get a paint request. + */ + if( sc.ScreenBufHandle == (HANDLE)NULL ){ + assert0( NO, "VDM: rejected paint request due to NULL handle" ); + return; + } + + /* If the image is completely outside the display area do nothing. */ + if ((mem_x >= max_width) || (mem_y >= max_height)) + { + sub_note_trace2(EGA_HOST_VERBOSE, + "VDM: nt_cga_med_frozen_std() x=%d y=%d", + screen_x, screen_y); + return; + } + + /* + * If image partially overlaps display area clip it so we don't start + * overwriting invalid pieces of memory. + */ + if (mem_x + len > max_width) + len = max_width - mem_x; + if (mem_y + height > max_height) + height = max_height - mem_y; + + /* Work out the width of a line (ie 640 pixels) in ints. */ + longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo); + + /* memory in this routine liable to be removed by fullscreen switch */ + try + { + /* Grab the mutex. */ + GrabMutex(sc.ConsoleBufInfo.hMutex); + + /* Set up data pointers. */ + graph_ptr = (ULONG *) sc.ConsoleBufInfo.lpBitMap + + screen_y * longs_per_scanline + (screen_x >> 2); + plane1_ptr = GET_OFFSET(Plane1Offset); + plane2_ptr = GET_OFFSET(Plane2Offset); + + /* Each iteration of the loop processes 2 host bytes. */ + local_len = len >> 1; + + /* 'offset' is designed for interleaved planes. */ + offset >>= 1; + + /* 'height' is always 1 so copy a line to the bitmap. */ + do + { + data = *(plane1_ptr + offset); + *(graph_ptr + longs_per_scanline) = *graph_ptr = + cga_med_graph_hi_nyb[data]; + graph_ptr++; + *(graph_ptr + longs_per_scanline) = *graph_ptr = + cga_med_graph_lo_nyb[data]; + graph_ptr++; + data = *(plane2_ptr + offset); + *(graph_ptr + longs_per_scanline) = *graph_ptr = + cga_med_graph_hi_nyb[data]; + graph_ptr++; + *(graph_ptr + longs_per_scanline) = *graph_ptr = + cga_med_graph_lo_nyb[data]; + graph_ptr++; + offset += 2; + } + while (--local_len); + + /* Release the mutex. */ + RelMutex(sc.ConsoleBufInfo.hMutex); + + /* Display the new image. */ + rect.Left = screen_x; + rect.Top = screen_y; + rect.Right = rect.Left + (len << 3) - 1; + rect.Bottom = rect.Top + (height << 1) - 1; + + if( sc.ScreenBufHandle ) + { + if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect)) + assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x", + GetLastError() ); + } + } except(EXCEPTION_EXECUTE_HANDLER) + { + assert0(NO, "Handled fault in nt_cga_med_frozen_std. fs switch?"); + return; + } +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/* Paints CGA high res graphics frozen window. */ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_cga_hi_frozen_std(int offset, int screen_x, int screen_y, int len, + int height) +{ + UTINY *plane1_ptr, + *graph_ptr; + ULONG bytes_per_scanline, + local_len, + mem_x = screen_x >> 3, + mem_y = screen_y >> 1, + max_width = sc.PC_W_Width >> 3, + max_height = sc.PC_W_Height >> 1; + SMALL_RECT rect; + + sub_note_trace5(CGA_HOST_VERBOSE, + "nt_cga_hi_frozen_std off=%d x=%d y=%d len=%d height=%d\n", + offset, screen_x, screen_y, len, height ); + + /* + ** Tim September 92, bounce call if handle to screen buffer is null. + ** This can happen when VDM session is about to suspend, buffer has + ** been closed, but still get a paint request. + */ + if( sc.ScreenBufHandle == (HANDLE)NULL ){ + assert0( NO, "VDM: rejected paint request due to NULL handle" ); + return; + } + + /* If the image is completely outside the display area do nothing. */ + if ((mem_x >= max_width) || (mem_y >= max_height)) + { + sub_note_trace2(EGA_HOST_VERBOSE, + "VDM: nt_cga_hi_frozen_std() x=%d y=%d", + screen_x, screen_y); + return; + } + + /* + * If image partially overlaps display area clip it so we don't start + * overwriting invalid pieces of memory. + */ + if (mem_x + len > max_width) + len = max_width - mem_x; + if (mem_y + height > max_height) + height = max_height - mem_y; + + /* memory here liable to be removed by fullscreen switch */ + try + { + /* Work out the width of a line (ie 640 pixels) in ints. */ + bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo); + + /* 'offset' is designed for interleaved planes. */ + offset >>= 2; + + /* Grab the mutex. */ + GrabMutex(sc.ConsoleBufInfo.hMutex); + + /* Set up data pointers. */ + graph_ptr = (UTINY *) sc.ConsoleBufInfo.lpBitMap + + screen_y * bytes_per_scanline + screen_x; + plane1_ptr = GET_OFFSET(Plane1Offset) + offset; + + /* 'height' is always 1 so copy a line to the bitmap. */ + local_len = len; + do + { + *(graph_ptr + bytes_per_scanline) = *graph_ptr = *plane1_ptr++; + graph_ptr++; + } + while (--local_len); + + /* Release the mutex. */ + RelMutex(sc.ConsoleBufInfo.hMutex); + + /* Display the new image. */ + rect.Left = screen_x; + rect.Top = screen_y; + rect.Right = rect.Left + (len << 3) - 1; + rect.Bottom = rect.Top + (height << 1) - 1; + + if( sc.ScreenBufHandle ) + { + if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect)) + assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x", + GetLastError() ); + } + } except(EXCEPTION_EXECUTE_HANDLER) + { + assert0(NO, "Handled fault in nt_ega_hi_frozen_std. fs switch?"); + return; + } +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::: Dummy paint routine for frozen screens. ::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +void nt_dummy_frozen(int offset, int screen_x, int screen_y, int len, + int height) +{ + assert0(NO, "Frozen screen error - dummy paint routine called."); +} +#endif /* MONITOR */ |