mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4845 lines
116 KiB
4845 lines
116 KiB
/* INSIGNIA (SUB)MODULE SPECIFICATION
|
|
-----------------------------
|
|
|
|
|
|
THIS PROGRAM SOURCE FILE IS SUPPLIED IN CONFIDENCE TO THE
|
|
CUSTOMER, THE CONTENTS OR DETAILS OF ITS OPERATION MUST
|
|
NOT BE DISCLOSED TO ANY OTHER PARTIES WITHOUT THE EXPRESS
|
|
AUTHORISATION FROM THE DIRECTORS OF INSIGNIA SOLUTIONS LTD.
|
|
|
|
DOCUMENT : Display Update Algorithms
|
|
|
|
DESIGNER : William Gulland
|
|
|
|
REVISION HISTORY :
|
|
First version : date, who
|
|
|
|
SccsID[]="@(#)gfx_update.c 1.82 06/30/95 Copyright Insignia Solutions Ltd.";
|
|
|
|
*/
|
|
|
|
/*
|
|
PURPOSE : Keep the host screen up to date.
|
|
[1.INTERMODULE INTERFACE SPECIFICATION]
|
|
|
|
[1.1 INTERMODULE EXPORTS]
|
|
|
|
DATA : give type and name
|
|
struct _UPDATE_ALG update_alg
|
|
|
|
-------------------------------------------------------------------------
|
|
[1.2 DATATYPES FOR [1.1] (if not basic C types)]
|
|
|
|
STRUCTURES/TYPEDEFS/ENUMS:
|
|
|
|
-------------------------------------------------------------------------
|
|
[1.3 INTERMODULE IMPORTS]
|
|
None
|
|
-------------------------------------------------------------------------
|
|
|
|
[1.4 DESCRIPTION OF INTERMODULE INTERFACE]
|
|
|
|
[1.4.1 IMPORTED OBJECTS]
|
|
None.
|
|
[1.4.2 EXPORTED OBJECTS]
|
|
=========================================================================
|
|
GLOBALS : describe what exported data objects are
|
|
accessed and how. Likewise for imported
|
|
data objects.
|
|
update_alg - pointers to update functions contained
|
|
here or elsewhere - eg. host specific update stuff.
|
|
|
|
text_update() - routine to do a text update, by comparing
|
|
the adaptor regen area with video_copy.
|
|
|
|
cga_graph_update() - routine to do a graphics update, by comparing
|
|
the adaptor regen area with video_copy.
|
|
|
|
text_scroll_up/down() - scroll portion of the screen in text mode.
|
|
cga_graph_scroll_up/down() - scroll portion of the screen in cga graphics mode.
|
|
=========================================================================
|
|
[3.INTERMODULE INTERFACE DECLARATIONS]
|
|
=========================================================================
|
|
|
|
[3.1 INTERMODULE IMPORTS] */
|
|
|
|
#include "insignia.h"
|
|
#include "host_def.h"
|
|
|
|
#include <stdio.h>
|
|
#include StringH
|
|
#include "xt.h"
|
|
#include "sas.h"
|
|
#include "ios.h"
|
|
#include CpuH
|
|
#include "gmi.h"
|
|
#include "gvi.h"
|
|
#include "cga.h"
|
|
#include "error.h"
|
|
#include "config.h" /* to get defn of MDA! */
|
|
#include "trace.h"
|
|
#include "debug.h"
|
|
#include "gfx_upd.h"
|
|
#include "host_gfx.h"
|
|
#include "video.h"
|
|
|
|
#ifdef EGG
|
|
#include "egacpu.h"
|
|
#include "egagraph.h"
|
|
#include "vgaports.h"
|
|
#include "egaports.h"
|
|
#endif /* EGG */
|
|
|
|
#ifdef GORE
|
|
#include "gore.h"
|
|
#endif /* GORE */
|
|
|
|
#include "ga_mark.h"
|
|
#include "ga_defs.h"
|
|
|
|
/*[3.2 INTERMODULE EXPORTS] */
|
|
|
|
/*
|
|
* Terminal type. This is initialised to a set default which is determined
|
|
* in host_graph.h.
|
|
*/
|
|
|
|
int terminal_type = TERMINAL_TYPE_DEFAULT;
|
|
|
|
/*
|
|
5.MODULE INTERNALS : (not visible externally, global internally)]
|
|
|
|
[5.1 LOCAL DECLARATIONS] */
|
|
|
|
/* [5.1.1 #DEFINES] */
|
|
#ifdef SEGMENTATION
|
|
/*
|
|
* The following #include specifies the code segment into which this
|
|
* module will by placed by the MPW C compiler on the Mac II running
|
|
* MultiFinder.
|
|
*/
|
|
#include "SOFTPC_GRAPHICS.seg"
|
|
#endif
|
|
|
|
#if defined(PROD) || (!defined(EGG))
|
|
#define init_dirty_recs() dirty_next = 0
|
|
#else
|
|
#define init_dirty_recs() { dirty_next = 0 ; if (io_verbose & EGA_DISPLAY_VERBOSE) \
|
|
trace("--- start collecting update records ---\n",0); }
|
|
#endif
|
|
|
|
#define get_dirty_rec_total() (dirty_next)
|
|
#ifdef VGG
|
|
#if defined(PROD) || (!defined(EGG))
|
|
#define add_dirty_rec(line,st,len,off,fr) { dirty[dirty_next].line_no = (line); \
|
|
dirty[dirty_next].start = (st); \
|
|
dirty[dirty_next].end = (st) + (len); \
|
|
dirty[dirty_next].video_copy_offset = (off); \
|
|
dirty[dirty_next].v7frig = (fr); \
|
|
dirty_next++; \
|
|
}
|
|
#else
|
|
#define add_dirty_rec(line,st,len,off,fr) { if (io_verbose & EGA_DISPLAY_VERBOSE) {\
|
|
char trace_string[80]; \
|
|
sprintf(trace_string,"dirty[%d]line_no %d, start %d end %d", \
|
|
dirty_next,(line),(st),(st)+(len));\
|
|
trace(trace_string,0); \
|
|
} \
|
|
dirty[dirty_next].line_no = (line); \
|
|
dirty[dirty_next].start = (st); \
|
|
dirty[dirty_next].end = (st) + (len); \
|
|
dirty[dirty_next].video_copy_offset = (off); \
|
|
dirty[dirty_next].v7frig = (fr); \
|
|
dirty_next++; \
|
|
}
|
|
#endif
|
|
#else /* VGG */
|
|
#if defined(PROD) || (!defined(EGG))
|
|
#define add_dirty_rec(line,st,len,off) { dirty[dirty_next].line_no = (line); \
|
|
dirty[dirty_next].start = (st); \
|
|
dirty[dirty_next].end = (st) + (len); \
|
|
dirty[dirty_next].video_copy_offset = (off); \
|
|
dirty_next++; \
|
|
}
|
|
#else
|
|
#define add_dirty_rec(line,st,len,off) { if (io_verbose & EGA_DISPLAY_VERBOSE) {\
|
|
char trace_string[80]; \
|
|
sprintf(trace_string,"dirty[%d]line_no %d, start %d end %d", \
|
|
dirty_next,(line),(st),(st)+(len));\
|
|
trace(trace_string,0); \
|
|
} \
|
|
dirty[dirty_next].line_no = (line); \
|
|
dirty[dirty_next].start = (st); \
|
|
dirty[dirty_next].end = (st) + (len); \
|
|
dirty[dirty_next].video_copy_offset = (off); \
|
|
dirty_next++; \
|
|
}
|
|
#endif
|
|
#endif /* VGG */
|
|
|
|
#define get_dirty_line(ind) (dirty[(ind)].line_no)
|
|
#define get_dirty_start(ind) (dirty[(ind)].start)
|
|
#define get_dirty_end(ind) (dirty[(ind)].end)
|
|
#define get_dirty_offset(ind) (dirty[(ind)].video_copy_offset)
|
|
#define clear_dirty() {setVideodirty_total(0);setVideodirty_low(0x80001);setVideodirty_high(-1);}
|
|
|
|
#ifdef NO_STRING_OPERATIONS
|
|
#define SET_VGLOBS_MARK_STRING(func) /*nothing*/
|
|
#else
|
|
#define SET_VGLOBS_MARK_STRING(func) setVideomark_string(func);
|
|
#endif /* NO_STRING_OPERATIONS */
|
|
|
|
|
|
/* Parts of update and paint routines assume start of screen memory is on
|
|
a 4-byte boundary. This macro makes this true and reports if it wasn't. */
|
|
#ifdef PROD
|
|
#define ALIGN_SCREEN_START(start) (start &= ~3L)
|
|
#else
|
|
#define ALIGN_SCREEN_START(start) if (start & 3L) \
|
|
{ file_id; printf("Start of screen not 4-byte aligned"); newline; \
|
|
start &= ~3L; }
|
|
#endif /* PROD */
|
|
|
|
GLOBAL LONG dirty_curs_offs = -1; /* GLOBAL for JOKER */
|
|
GLOBAL LONG dirty_curs_x;
|
|
GLOBAL LONG dirty_curs_y;
|
|
|
|
#ifndef REAL_VGA
|
|
|
|
/* [5.1.2 TYPEDEF, STRUCTURE, ENUM DECLARATIONS] */
|
|
|
|
/* [5.1.3 PROCEDURE() DECLARATIONS] */
|
|
|
|
LOCAL boolean simple_update IPT0();
|
|
boolean dummy_scroll IPT6(int,dummy1,int,dummy2,int,dummy3,
|
|
int,dummy4,int,dummy5,int,dummy6);
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
boolean mon_text_scroll_up IPT6(sys_addr, start, int, width, int, height, int, attr, int, lines, int, colour);
|
|
boolean mon_text_scroll_down IPT6(sys_addr, start, int, width, int, height, int, attr, int, lines, int, colour);
|
|
#endif /* NTVDM & MONITOR */
|
|
|
|
LOCAL VOID save_gfx_update_routines IPT0();
|
|
LOCAL VOID inhibit_gfx_update_routines IPT0();
|
|
|
|
/* Imports from v7_ports.c */
|
|
|
|
#ifdef V7VGA
|
|
IMPORT VOID draw_v7ptr IPT0();
|
|
IMPORT VOID remove_v7ptr IPT0();
|
|
IMPORT BOOL v7ptr_between_lines IPT2(int,start_line,int,end_line);
|
|
#endif /* V7VGA */
|
|
|
|
|
|
#ifdef HOST_SCREEN_UPDATES
|
|
|
|
IMPORT BOOL HostUpdatedVGA IPT0(); /* Called from vga_graph_update() */
|
|
IMPORT BOOL HostUpdatedEGA IPT0(); /* ega_graph_update() */
|
|
|
|
#else /* HOST_SCREEN_UPDATES */
|
|
|
|
#define HostUpdatedVGA() FALSE
|
|
#define HostUpdatedEGA() FALSE
|
|
|
|
#endif /* HOST_SCREEN_UPDATES */
|
|
|
|
|
|
/* -----------------------------------------------------------------------
|
|
[5.2 LOCAL DEFINITIONS]
|
|
|
|
[5.2.1 INTERNAL DATA DEFINITIONS */
|
|
|
|
byte *video_copy; /* video_copy is now allocated in host_init_screen()'s */
|
|
|
|
#ifndef macintosh
|
|
#ifdef VGG
|
|
#ifdef V7VGA
|
|
static DIRTY_PARTS dirty[768];
|
|
#else
|
|
static DIRTY_PARTS dirty[480];
|
|
#endif /* V7VGA */
|
|
#else
|
|
static DIRTY_PARTS dirty[350];
|
|
#endif
|
|
#else
|
|
DIRTY_PARTS *dirty; /* NB. Allocated as 350*4*sizeof(int) in applInit(). */
|
|
#endif
|
|
|
|
IMPORT half_word bg_col_mask;
|
|
static int dirty_next=0;
|
|
|
|
/* [5.2.2 INTERNAL PROCEDURE DEFINITIONS] */
|
|
|
|
static int search_video_copy IFN3(int, start_line,
|
|
int, end_line, int, start_offset)
|
|
{
|
|
register byte *ptr,*k;
|
|
register int j;
|
|
register int quarter_opl = get_offset_per_line()>>2;
|
|
byte *vcopy = &video_copy[start_offset];
|
|
byte save,*end_ptr;
|
|
|
|
ptr = vcopy;
|
|
end_ptr = ptr + quarter_opl*(end_line-start_line);
|
|
save = *end_ptr;
|
|
*end_ptr = 1; /* End marker */
|
|
while(ptr < end_ptr)
|
|
{
|
|
if(!*ptr)
|
|
do {; } while (!(*++ptr));
|
|
if(ptr >= end_ptr)break;
|
|
/* Work out where in line we've reached */
|
|
j = (int)((ptr - vcopy)%quarter_opl);
|
|
/*
|
|
* Have found a dirty line. Find width
|
|
*/
|
|
for ( k= ptr+quarter_opl-j-1; *k == 0 ; k-- ) ; /* We know *ptr != 0, so k will stop at ptr */
|
|
#ifdef VGG
|
|
add_dirty_rec((int)((ptr-vcopy)/quarter_opl)+start_line,
|
|
j<<2, (int)(k-ptr+1)<<2, ptr-video_copy-j,0);
|
|
#else
|
|
add_dirty_rec((int)((ptr-vcopy)/quarter_opl)+start_line,
|
|
j<<2, (int)(k-ptr+1)<<2, ptr-video_copy-j);
|
|
#endif /* VGG */
|
|
|
|
ptr += quarter_opl - j;
|
|
/*
|
|
* Don't clear out the marked area in case the plane wraps
|
|
*/
|
|
}
|
|
*end_ptr = save;
|
|
return( get_dirty_rec_total() );
|
|
}
|
|
|
|
#ifdef VGG
|
|
|
|
/*
|
|
* Special version of search_video_copy() for the Video 7 Extended Modes 60h & 61h
|
|
* and 'undocumented' VGA mode which have chars_per_line of 90 & 94 which don't seem
|
|
* to be multiples of 4. Interestingly, Zany Golf ( EGA, Mode 14 ) also ends up
|
|
* calling this code.
|
|
*/
|
|
|
|
static int v7_search_video_copy IFN3(int, start_line,
|
|
int, end_line, int, start_offset)
|
|
{
|
|
register byte *ptr,*k;
|
|
register int j;
|
|
register int half_opl = get_offset_per_line()>>1;
|
|
register int quarter_opl = get_offset_per_line()>>2;
|
|
byte *vcopy = &video_copy[start_offset];
|
|
byte save,*end_ptr;
|
|
long length;
|
|
int bodge = 0;
|
|
|
|
if (start_line & 1)
|
|
bodge = 2;
|
|
ptr = vcopy;
|
|
|
|
/*
|
|
* This calculation sets end_ptr slightly too high to
|
|
* ensure that all the dirty areas get found.
|
|
*/
|
|
|
|
end_ptr = ptr + (half_opl*(end_line-start_line+1))/2;
|
|
|
|
save = *end_ptr;
|
|
*end_ptr = 1; /* End marker */
|
|
while(ptr < end_ptr)
|
|
{
|
|
if(!*ptr)
|
|
{
|
|
while (!(*++ptr));
|
|
}
|
|
if(ptr >= end_ptr)break;
|
|
/* Work out where in line we've reached */
|
|
j = (int)((ptr - vcopy)%half_opl);
|
|
/*
|
|
* Have found a dirty line. Find width
|
|
*/
|
|
for ( k= ptr+half_opl-j-1; *k == 0 ; k-- ) ; /* We know *ptr != 0, so k will stop at ptr */
|
|
|
|
length = k-ptr+1;
|
|
if (j <= quarter_opl)
|
|
{
|
|
if (length > quarter_opl-j)
|
|
{
|
|
add_dirty_rec((int)(2*(ptr-vcopy)/half_opl)+start_line,
|
|
j<<2, (int)(half_opl-2*j)<<1, ptr-video_copy-j,bodge);
|
|
add_dirty_rec((int)(2*(ptr-vcopy)/half_opl)+start_line+1,
|
|
0, ((int)(j+length-quarter_opl)<<2)-2, ptr-video_copy-j+quarter_opl,2+bodge);
|
|
}
|
|
else
|
|
{
|
|
add_dirty_rec((int)(2*(ptr-vcopy)/half_opl)+start_line,
|
|
j<<2, (int)(length)<<2, ptr-video_copy-j,bodge);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
add_dirty_rec((int)(2*(ptr-vcopy)/half_opl)+start_line,
|
|
(j-quarter_opl-1)<<2, (int)((length)<<2), ptr-video_copy-j+quarter_opl,2+bodge);
|
|
}
|
|
|
|
ptr += half_opl - j;
|
|
/*
|
|
* Don't clear out the marked area in case the plane wraps
|
|
*/
|
|
}
|
|
*end_ptr = save;
|
|
return( get_dirty_rec_total() );
|
|
}
|
|
#endif /* VGG */
|
|
|
|
static int search_video_copy_aligned IFN3(int, start_line,
|
|
int, end_line, int, start_offset)
|
|
{
|
|
register unsigned int *ptr4;
|
|
register byte *ptr,*k;
|
|
register int j;
|
|
register int quarter_opl = get_offset_per_line()>>2;
|
|
byte *vcopy = &video_copy[start_offset];
|
|
byte save,*end_ptr;
|
|
|
|
ptr = vcopy;
|
|
end_ptr = ptr + quarter_opl*(end_line-start_line);
|
|
save = *end_ptr;
|
|
*end_ptr = 1; /* End marker */
|
|
while(ptr < end_ptr)
|
|
{
|
|
ptr4 = (unsigned int *)(ptr-4);
|
|
do {; } while (!(*++ptr4));
|
|
ptr = (byte *)ptr4;
|
|
if(!*ptr)
|
|
do {; } while (!(*++ptr));
|
|
if(ptr >= end_ptr)break;
|
|
/* Work out where in line we've reached */
|
|
j = (int)((ptr - vcopy)%quarter_opl);
|
|
/*
|
|
* Have found a dirty line. Find width
|
|
*/
|
|
for ( k= ptr+quarter_opl-j-1; *k == 0 ; k-- ) ; /* We know *ptr != 0, so k will stop at ptr */
|
|
#ifdef VGG
|
|
add_dirty_rec((int)((ptr-vcopy)/quarter_opl)+start_line,
|
|
j<<2, (int)(k-ptr+1)<<2, ptr-video_copy-j,0);
|
|
#else
|
|
add_dirty_rec((int)((ptr-vcopy)/quarter_opl)+start_line,
|
|
j<<2, (int)(k-ptr+1)<<2, ptr-video_copy-j);
|
|
#endif /* VGG */
|
|
ptr += quarter_opl - j;
|
|
/*
|
|
* Don't clear out the marked area in case the plane wraps
|
|
*/
|
|
}
|
|
*end_ptr = save;
|
|
return( get_dirty_rec_total() );
|
|
}
|
|
|
|
static void paint_records IFN2(int, start_rec, int, end_rec)
|
|
{
|
|
register DIRTY_PARTS *i,*end_ptr;
|
|
#ifdef VGG
|
|
int dirty_frig;
|
|
#endif /* VGG */
|
|
|
|
i= &dirty[start_rec];
|
|
end_ptr = &dirty[end_rec];
|
|
while (i<end_ptr) {
|
|
register int last_line, cur_start, cur_end,max_width;
|
|
int first_line;
|
|
long dirty_vc_offset;
|
|
|
|
first_line = i->line_no;
|
|
last_line = first_line;
|
|
cur_start = i->start;
|
|
cur_end = i->end;
|
|
max_width = (cur_end-cur_start) << 1; /* To split up diagonal lines */
|
|
|
|
/*
|
|
* offset in bytes into video_copy, which is quarter offset into plane at start of this rectangle
|
|
*/
|
|
|
|
dirty_vc_offset = i->video_copy_offset;
|
|
#ifdef VGG
|
|
dirty_frig = i->v7frig; /* for the V7 modes with chars_per_line not a multiple of 4 */
|
|
#endif /* VGG */
|
|
i++;
|
|
while (i < end_ptr) {
|
|
if ( i->line_no - last_line < 3 ) {
|
|
/*
|
|
* This entry can be included into the same paint
|
|
* as long as it doesn't make the rectangle too wide
|
|
*/
|
|
|
|
if ( i->end > cur_end ){
|
|
if(i->end - cur_start > max_width)break;
|
|
cur_end = i->end;
|
|
}
|
|
if ( i->start < cur_start ){
|
|
if(cur_end - i->start > max_width)break;
|
|
cur_start = i->start;
|
|
}
|
|
last_line = i->line_no;
|
|
i++;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
/*
|
|
* paint the rectangle found
|
|
*/
|
|
|
|
/* do not paint beyond the right hand side of the screen;
|
|
these checks were put in to cope with the special
|
|
case of the brain-scan display in 'EGAWOW' */
|
|
if (cur_end > get_bytes_per_line())
|
|
cur_end = get_bytes_per_line();
|
|
#ifdef VGG
|
|
if (cur_end > cur_start)
|
|
(*paint_screen)((dirty_vc_offset<<2) + dirty_frig + cur_start,
|
|
cur_start<<3, first_line, cur_end-cur_start,
|
|
last_line-first_line+1);
|
|
#else
|
|
if (cur_end > cur_start)
|
|
(*paint_screen)((dirty_vc_offset<<2) + cur_start,
|
|
cur_start<<3, first_line, cur_end-cur_start,
|
|
last_line-first_line+1);
|
|
#endif /* VGG */
|
|
}
|
|
/* Clear out video copy */
|
|
for(i = &dirty[start_rec];i<end_ptr;i++)
|
|
{
|
|
register byte *j,*end;
|
|
end = &video_copy[ i->video_copy_offset+(i->end>>2)];
|
|
#ifdef VGG
|
|
j = &video_copy[ i->video_copy_offset+(i->start>>2)+i->v7frig];
|
|
#else
|
|
j = &video_copy[ i->video_copy_offset+(i->start>>2)];
|
|
#endif /* VGG */
|
|
do *j++ = 0; while(j<end);
|
|
}
|
|
}
|
|
|
|
#ifdef BIGEND
|
|
#define get_char_attr(unsigned_long_ptr) ((*(unsigned_long_ptr)) >> 16)
|
|
#else
|
|
#define get_char_attr(unsigned_long_ptr) (((*(unsigned_long_ptr)) & 0xffff))
|
|
#endif
|
|
|
|
#ifdef EGG
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_EGA.seg"
|
|
#endif
|
|
|
|
static int ega_text_find_dirty_lines IFN5(byte *, vcopy, byte *, planes,
|
|
int, start_line, int, end_line, int, screen_start)
|
|
{
|
|
register int i,j,k;
|
|
register unsigned short shorts_per_line=get_chars_per_line();
|
|
register int offset,cur_y;
|
|
register int char_height=get_host_char_height();
|
|
register int opl=get_offset_per_line();
|
|
register IU32 *from;
|
|
register USHORT *to;
|
|
|
|
for(i=start_line,offset=0,cur_y=start_line*char_height; i<end_line;
|
|
i++,offset += opl, cur_y += char_height )
|
|
{
|
|
to = (USHORT *) &vcopy[offset];
|
|
from = (IU32 *) &planes[(offset<<1)];
|
|
for(j=0;j<shorts_per_line;j++)
|
|
{
|
|
if(*to++ != get_char_attr(from++))
|
|
{
|
|
to--;from--;
|
|
for(k=shorts_per_line-1-j;*(to+k) == get_char_attr(from+k);k--)
|
|
;
|
|
|
|
/*
|
|
* Note: For text mode there is one char for every word.
|
|
* no of bytes into screen=line*bytes_per_line + ints_into_line*4
|
|
* x_coord=width_of_one_char*(no_of_ints_into_line*2)
|
|
* y_coord=height_of_one_char*2*line
|
|
* The host y co-ords are doubled
|
|
*/
|
|
|
|
#ifdef VGG
|
|
add_dirty_rec(cur_y,j<<2,(k<<1)+2,screen_start+(offset<<1),0);
|
|
#else
|
|
add_dirty_rec(cur_y,j<<2,(k<<1)+2,screen_start+(offset<<1));
|
|
#endif /* VGG */
|
|
break; /* onto next line */
|
|
}
|
|
}
|
|
}
|
|
return( get_dirty_rec_total() );
|
|
}
|
|
|
|
static void ega_text_paint_dirty_recs IFN2(int, start_rec, int, end_rec)
|
|
{
|
|
register int char_wid = get_pix_char_width()>>1;
|
|
register int i;
|
|
register int length;
|
|
register USHORT *to,*from;
|
|
|
|
for (i=start_rec;i<end_rec;i++)
|
|
{
|
|
length = get_dirty_end(i)-get_dirty_start(i);
|
|
|
|
(*paint_screen)(get_dirty_offset(i)+get_dirty_start(i),
|
|
(get_dirty_start(i)>>1)*char_wid,get_dirty_line(i), length, 1);
|
|
|
|
length >>= 1;
|
|
to = (USHORT *) &video_copy[(get_dirty_offset(i)+
|
|
get_dirty_start (i))>>1];
|
|
|
|
from = (USHORT *)get_screen_ptr(get_dirty_offset(i)+get_dirty_start(i));
|
|
|
|
while ( length-- > 0 )
|
|
{
|
|
*to++ = *from; /* char and attribute bytes */
|
|
from += 2; /* skip over the planes 2,3 */
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* EGG */
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_GRAPHICS.seg"
|
|
#endif
|
|
|
|
#endif /* REAL_VGA */
|
|
|
|
VOID remove_old_cursor IFN0()
|
|
{
|
|
if( dirty_curs_offs >= 0 )
|
|
{
|
|
sub_note_trace2( ALL_ADAPT_VERBOSE,
|
|
"remove_old_cursor x=%d, y=%d", dirty_curs_x, dirty_curs_y );
|
|
|
|
(*paint_screen)( dirty_curs_offs, dirty_curs_x * get_pix_char_width(),
|
|
dirty_curs_y * get_host_char_height(), 2 );
|
|
|
|
dirty_curs_offs = -1;
|
|
}
|
|
}
|
|
|
|
|
|
GLOBAL VOID
|
|
simple_handler IFN0()
|
|
{
|
|
setVideodirty_total(getVideodirty_total() + 1);
|
|
}
|
|
|
|
LOCAL boolean simple_update IFN0()
|
|
{
|
|
setVideodirty_total(getVideodirty_total() + 1);
|
|
return( FALSE );
|
|
}
|
|
|
|
LOCAL VOID simple_update_b_move IFN4(UTINY *, laddr, UTINY *, haddr,
|
|
UTINY *, src, UTINY, src_type)
|
|
{
|
|
UNUSED(laddr);
|
|
UNUSED(haddr);
|
|
UNUSED(src);
|
|
UNUSED(src_type);
|
|
|
|
setVideodirty_total(getVideodirty_total() + 1);
|
|
}
|
|
|
|
MEM_HANDLERS vid_handlers =
|
|
{
|
|
simple_handler,
|
|
simple_handler,
|
|
simple_handler,
|
|
simple_handler,
|
|
simple_update_b_move,
|
|
simple_handler
|
|
};
|
|
|
|
GLOBAL void dummy_calc IFN0()
|
|
{
|
|
}
|
|
|
|
/*
|
|
[7.1 INTERMODULE DATA DEFINITIONS] */
|
|
|
|
UPDATE_ALG update_alg =
|
|
{
|
|
(T_mark_byte)simple_update,
|
|
(T_mark_word)simple_update,
|
|
(T_mark_fill)simple_update,
|
|
(T_mark_wfill)simple_update,
|
|
(T_mark_string)simple_update,
|
|
dummy_calc,
|
|
dummy_scroll,
|
|
dummy_scroll,
|
|
};
|
|
|
|
#ifndef REAL_VGA
|
|
|
|
/*
|
|
[7.2 INTERMODULE PROCEDURE DEFINITIONS] */
|
|
|
|
|
|
/*
|
|
==========================================================================
|
|
FUNCTION : flag_mode_change_required()
|
|
PURPOSE : Flag that a mode change is imminent and set the
|
|
scrolling routines to dummies to avoid scrolling
|
|
using routines for the wrong mode.
|
|
EXTERNAL OBJECTS:
|
|
RETURN VALUE : None
|
|
INPUT PARAMS : None
|
|
RETURN PARAMS : None
|
|
==========================================================================
|
|
*/
|
|
|
|
void flag_mode_change_required IFN0()
|
|
{
|
|
set_mode_change_required(YES);
|
|
|
|
update_alg.mark_byte = (T_mark_byte)simple_update;
|
|
update_alg.mark_word = (T_mark_word)simple_update;
|
|
update_alg.mark_fill = (T_mark_fill)simple_update;
|
|
update_alg.mark_wfill = (T_mark_wfill)simple_update;
|
|
update_alg.mark_string = (T_mark_string)simple_update;
|
|
|
|
update_alg.scroll_up = dummy_scroll;
|
|
update_alg.scroll_down = dummy_scroll;
|
|
}
|
|
|
|
|
|
/*
|
|
==========================================================================
|
|
FUNCTION : reset_paint_routines()
|
|
PURPOSE : Reset paint routines to dummies to ensure
|
|
there are no problems painting the screen
|
|
using incorrect routines during reboot.
|
|
EXTERNAL OBJECTS:
|
|
RETURN VALUE : None
|
|
INPUT PARAMS : None
|
|
RETURN PARAMS : None
|
|
==========================================================================
|
|
*/
|
|
|
|
void reset_paint_routines IFN0()
|
|
{
|
|
set_mode_change_required(YES);
|
|
|
|
update_alg.calc_update = dummy_calc;
|
|
update_alg.scroll_up = dummy_scroll;
|
|
update_alg.scroll_down = dummy_scroll;
|
|
}
|
|
|
|
/*
|
|
* Update the window to look like the regen buffer says it should
|
|
*/
|
|
#ifdef EGG
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_EGA.seg"
|
|
#endif
|
|
|
|
void ega_wrap_split_text_update IFN0()
|
|
{
|
|
register int i; /* Loop counter */
|
|
register USHORT *from,*to;
|
|
register int cur_ypos;
|
|
int lines_per_screen;
|
|
int offset;
|
|
int screen_start;
|
|
int split_line;
|
|
|
|
if (getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
host_start_update();
|
|
|
|
screen_start=get_screen_start() << 2;
|
|
|
|
ALIGN_SCREEN_START(screen_start);
|
|
|
|
lines_per_screen = get_screen_length()/get_offset_per_line();
|
|
split_line = (get_screen_split()+(get_char_height()>>1))/get_char_height();
|
|
|
|
if (split_line>lines_per_screen)
|
|
split_line=lines_per_screen;
|
|
|
|
to = (USHORT *) &video_copy[screen_start >> 1];
|
|
from = (USHORT *) get_screen_ptr(screen_start);
|
|
|
|
if( getVideodirty_total() > 1500 ) /* paint the whole lot */
|
|
{
|
|
int no_of_split_lines = lines_per_screen - split_line;
|
|
int limit;
|
|
|
|
cur_ypos = 0;
|
|
|
|
if( screen_start + (get_screen_length() << 1) > 4 * EGA_PLANE_DISP_SIZE )
|
|
{
|
|
note_display_state0("Split screen and wrapping !!");
|
|
|
|
limit = (4 * EGA_PLANE_DISP_SIZE - screen_start) >> 2;
|
|
|
|
for( i = 0; i < limit; i++ )
|
|
{
|
|
*to++ = *from;
|
|
from += 2;
|
|
}
|
|
|
|
to = (USHORT *) &video_copy[0];
|
|
from = (USHORT * ) get_screen_ptr(0);
|
|
limit = (screen_start + ((get_screen_length() - 2 * EGA_PLANE_DISP_SIZE) << 1)) >> 2;
|
|
|
|
for( i = 0; i < limit; i++ )
|
|
{
|
|
*to++ = *from;
|
|
from += 2;
|
|
}
|
|
limit = 4 * EGA_PLANE_DISP_SIZE;
|
|
for( i = 0, offset = screen_start; offset < limit;
|
|
i++, offset += (get_offset_per_line() << 1 ))
|
|
{
|
|
(*paint_screen)(offset,0,cur_ypos,get_bytes_per_line(), 1);
|
|
cur_ypos += get_host_char_height();
|
|
}
|
|
|
|
for( i = 0, offset = 0; i < split_line;
|
|
i++, offset += (get_offset_per_line() << 1 ))
|
|
{
|
|
(*paint_screen)(offset,0,cur_ypos,get_bytes_per_line(), 1);
|
|
cur_ypos += get_host_char_height();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
to = (USHORT *) &video_copy[screen_start >> 1];
|
|
from = (USHORT * ) get_screen_ptr(screen_start);
|
|
limit = (split_line * get_offset_per_line()) >> 1;
|
|
|
|
for( i = 0; i < limit; i++ )
|
|
{
|
|
*to++ = *from;
|
|
from += 2;
|
|
}
|
|
|
|
for( i = 0, offset = screen_start; i < split_line;
|
|
i++, offset += (get_offset_per_line() << 1 ))
|
|
{
|
|
(*paint_screen)(offset,0,cur_ypos,get_bytes_per_line(), 1);
|
|
cur_ypos += get_host_char_height();
|
|
}
|
|
}
|
|
|
|
if( no_of_split_lines > 0 )
|
|
{
|
|
to = (USHORT *) &video_copy[0];
|
|
from = (USHORT * ) get_screen_ptr(0);
|
|
limit = (no_of_split_lines * get_offset_per_line()) >> 1;
|
|
|
|
for( i = 0; i < limit; i++ )
|
|
{
|
|
*to++ = *from;
|
|
from += 2;
|
|
}
|
|
|
|
for( i = split_line, offset = 0; i < lines_per_screen;
|
|
i++, offset += (get_offset_per_line() << 1 ))
|
|
{
|
|
(*paint_screen)(offset,0,cur_ypos,get_bytes_per_line(), 1);
|
|
cur_ypos += get_host_char_height();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( screen_start + (get_screen_length() << 1) > 4 * EGA_PLANE_DISP_SIZE )
|
|
{
|
|
register int wrap_line =
|
|
(4 * EGA_PLANE_DISP_SIZE - screen_start) / (get_offset_per_line() << 1);
|
|
int next,next1,next2;
|
|
|
|
note_display_state0("Its a text wrap!");
|
|
|
|
init_dirty_recs();
|
|
|
|
next = ega_text_find_dirty_lines(&video_copy[screen_start >> 1],
|
|
get_screen_ptr(screen_start), 0,
|
|
wrap_line, screen_start );
|
|
|
|
next1 = ega_text_find_dirty_lines(&video_copy[0],
|
|
get_screen_ptr(0), wrap_line, split_line, 0 );
|
|
|
|
next2 = ega_text_find_dirty_lines(&video_copy[0],
|
|
get_screen_ptr(0), split_line, lines_per_screen, 0 );
|
|
|
|
ega_text_paint_dirty_recs(0,next);
|
|
ega_text_paint_dirty_recs(next,next1);
|
|
ega_text_paint_dirty_recs(next1,next2);
|
|
}
|
|
else
|
|
{
|
|
int next,next1;
|
|
|
|
init_dirty_recs();
|
|
next = ega_text_find_dirty_lines( &video_copy[screen_start >> 1],
|
|
get_screen_ptr(screen_start), 0, split_line, screen_start );
|
|
|
|
next1 = ega_text_find_dirty_lines( &video_copy[0], get_screen_ptr(0),
|
|
split_line, lines_per_screen, 0 );
|
|
|
|
ega_text_paint_dirty_recs(0,next);
|
|
ega_text_paint_dirty_recs(next,next1);
|
|
}
|
|
}
|
|
|
|
host_end_update();
|
|
|
|
setVideodirty_total(0);
|
|
}
|
|
|
|
void ega_split_text_update IFN0()
|
|
{
|
|
register int i; /* Loop counter */
|
|
register USHORT *from,*to;
|
|
register int cur_ypos;
|
|
int lines_per_screen;
|
|
int offset;
|
|
int screen_start;
|
|
int split_line;
|
|
|
|
if (getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
host_start_update();
|
|
|
|
screen_start = get_screen_start() << 2;
|
|
|
|
ALIGN_SCREEN_START(screen_start);
|
|
|
|
lines_per_screen = get_screen_length()/get_offset_per_line();
|
|
|
|
split_line = (get_screen_split()+(get_char_height()>>1))/get_char_height();
|
|
|
|
if( split_line > lines_per_screen )
|
|
split_line = lines_per_screen;
|
|
|
|
to = (USHORT *) &video_copy[screen_start >> 1];
|
|
from = (USHORT *) get_screen_ptr(screen_start);
|
|
|
|
if( getVideodirty_total() > 1500 ) /* paint the whole lot */
|
|
{
|
|
int no_of_split_lines = lines_per_screen - split_line;
|
|
|
|
sub_note_trace2( EGA_DISPLAY_VERBOSE,
|
|
"split line %d (lines_per_screen %d)", split_line, lines_per_screen);
|
|
sub_note_trace1( EGA_DISPLAY_VERBOSE, "screen split %d", get_screen_split() );
|
|
|
|
cur_ypos = 0;
|
|
|
|
for( i = 0; i < (split_line * get_offset_per_line()) >> 1; i++ )
|
|
{
|
|
*to++ = *from;
|
|
from += 2;
|
|
}
|
|
|
|
for( i = 0, offset = screen_start; i < split_line;
|
|
i++, offset += ( get_offset_per_line() << 1 ))
|
|
{
|
|
(*paint_screen)( offset, 0, cur_ypos, get_bytes_per_line(), 1 );
|
|
cur_ypos += get_host_char_height();
|
|
}
|
|
|
|
if( no_of_split_lines > 0 )
|
|
{
|
|
to = (USHORT *) &video_copy[0];
|
|
from = (USHORT *) get_screen_ptr(0);
|
|
|
|
for( i = 0; i < (no_of_split_lines * get_offset_per_line()) >> 1; i++ )
|
|
{
|
|
*to++ = *from;
|
|
from += 2;
|
|
}
|
|
|
|
for( i = split_line, offset = 0; i < lines_per_screen;
|
|
i++, offset += ( get_offset_per_line() << 1 ))
|
|
{
|
|
(*paint_screen)( offset, 0, cur_ypos, get_bytes_per_line(), 1);
|
|
cur_ypos += get_host_char_height();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int next,next1;
|
|
|
|
assert0( FALSE, "ega_split_text - partial update" );
|
|
|
|
init_dirty_recs();
|
|
|
|
next = ega_text_find_dirty_lines( &video_copy[screen_start >> 1],
|
|
get_screen_ptr(screen_start) , 0, split_line, screen_start );
|
|
|
|
next1 = ega_text_find_dirty_lines( &video_copy[0], get_screen_ptr(0),
|
|
split_line, lines_per_screen, 0 );
|
|
|
|
ega_text_paint_dirty_recs(0,next);
|
|
ega_text_paint_dirty_recs(next,next1);
|
|
}
|
|
|
|
host_end_update();
|
|
|
|
setVideodirty_total(0);
|
|
}
|
|
|
|
void ega_wrap_text_update IFN0()
|
|
{
|
|
register int i; /* Loop counter */
|
|
register USHORT *from,*to;
|
|
register int cur_ypos;
|
|
int lines_per_screen;
|
|
int offset;
|
|
int screen_start;
|
|
|
|
if (getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
host_start_update();
|
|
|
|
screen_start=get_screen_start() << 2;
|
|
|
|
ALIGN_SCREEN_START(screen_start);
|
|
|
|
lines_per_screen = get_screen_length()/get_offset_per_line();
|
|
|
|
if( getVideodirty_total() > 1500 ) /* paint the whole lot */
|
|
{
|
|
to = (USHORT *) &video_copy[screen_start >> 1];
|
|
from = (USHORT *) get_screen_ptr(screen_start);
|
|
|
|
for( i = get_screen_length() >> 1; i > 0; i-- )
|
|
{
|
|
*to++ = *from;
|
|
from += 2;
|
|
}
|
|
|
|
cur_ypos = 0;
|
|
|
|
if( screen_start + (get_screen_length() << 1) > 4 * EGA_PLANE_DISP_SIZE )
|
|
{
|
|
register int leftover;
|
|
int limit;
|
|
|
|
note_display_state0("Wrapping text");
|
|
|
|
limit = 4 * EGA_PLANE_DISP_SIZE;
|
|
for( offset = screen_start; offset < limit;
|
|
offset+=(get_offset_per_line() << 1) )
|
|
{
|
|
(*paint_screen)(offset,0,cur_ypos,get_bytes_per_line(), 1);
|
|
cur_ypos += get_host_char_height();
|
|
}
|
|
|
|
leftover = screen_start
|
|
+ ((get_screen_length() - 2 * EGA_PLANE_DISP_SIZE) << 1);
|
|
|
|
for( offset = 0; offset < leftover;
|
|
offset += ( get_offset_per_line() << 1 ))
|
|
{
|
|
(*paint_screen)(offset,0,cur_ypos,get_bytes_per_line(), 1);
|
|
cur_ypos += get_host_char_height();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( offset = screen_start;
|
|
offset < screen_start + (get_screen_length() << 1);
|
|
offset += ( get_offset_per_line() << 1 ))
|
|
{
|
|
(*paint_screen)( offset, 0, cur_ypos, get_bytes_per_line(), 1 );
|
|
cur_ypos += get_host_char_height();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( screen_start + (get_screen_length() << 1) > 4 * EGA_PLANE_DISP_SIZE )
|
|
{
|
|
int next,next1;
|
|
int lines_left = (screen_start +
|
|
((get_screen_length() - 2 * EGA_PLANE_DISP_SIZE) << 1)) /
|
|
(get_offset_per_line() << 1);
|
|
|
|
note_display_state0("Wrapping text");
|
|
|
|
init_dirty_recs();
|
|
next = ega_text_find_dirty_lines( &video_copy[screen_start >> 1],
|
|
get_screen_ptr(screen_start), 0,
|
|
lines_per_screen - lines_left, screen_start);
|
|
|
|
next1 = ega_text_find_dirty_lines( video_copy, get_screen_ptr(0),
|
|
lines_per_screen - lines_left, lines_per_screen, 0 );
|
|
|
|
ega_text_paint_dirty_recs(0,next);
|
|
ega_text_paint_dirty_recs(next,next1);
|
|
}
|
|
else
|
|
{
|
|
register int next;
|
|
|
|
init_dirty_recs();
|
|
next = ega_text_find_dirty_lines( &video_copy[screen_start >> 1],
|
|
get_screen_ptr(screen_start), 0,
|
|
lines_per_screen, screen_start);
|
|
|
|
ega_text_paint_dirty_recs(0,next);
|
|
}
|
|
}
|
|
|
|
host_end_update();
|
|
|
|
setVideodirty_total(0);
|
|
}
|
|
|
|
void ega_text_update IFN0()
|
|
{
|
|
register int i; /* Loop counter */
|
|
register USHORT *from,*to;
|
|
register int cur_ypos;
|
|
int lines_per_screen;
|
|
int offset;
|
|
int screen_start;
|
|
|
|
if (getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
host_start_update();
|
|
|
|
screen_start=get_screen_start()<<2;
|
|
|
|
ALIGN_SCREEN_START(screen_start);
|
|
|
|
lines_per_screen = get_screen_length()/get_offset_per_line();
|
|
|
|
if(getVideodirty_total()>1500) /* paint the whole lot */
|
|
{
|
|
to = (USHORT *)&video_copy[screen_start>>1];
|
|
from = (USHORT *) get_screen_ptr(screen_start);
|
|
|
|
for(i=get_screen_length()>>1;i>0;i--)
|
|
{
|
|
*to++ = *from; /* char and attribute bytes */
|
|
from += 2; /* planes 2,3 interleaved */
|
|
}
|
|
|
|
cur_ypos = 0;
|
|
for(offset=screen_start;offset<screen_start+(get_screen_length()<<1);
|
|
offset+=(get_offset_per_line()<<1) )
|
|
{
|
|
(*paint_screen)(offset,0,cur_ypos,get_bytes_per_line(), 1);
|
|
cur_ypos += get_host_char_height();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
register int next;
|
|
|
|
init_dirty_recs();
|
|
next = ega_text_find_dirty_lines( &video_copy[screen_start>>1],
|
|
get_screen_ptr(screen_start), 0, lines_per_screen, screen_start);
|
|
|
|
ega_text_paint_dirty_recs(0,next);
|
|
|
|
remove_old_cursor();
|
|
}
|
|
|
|
setVideodirty_total(0);
|
|
|
|
if (is_cursor_visible())
|
|
{
|
|
half_word attr;
|
|
|
|
dirty_curs_x = get_cur_x();
|
|
dirty_curs_y = get_cur_y();
|
|
|
|
dirty_curs_offs = screen_start+dirty_curs_y * (get_offset_per_line()<<1) + (dirty_curs_x<<2);
|
|
attr = *(get_screen_ptr(dirty_curs_offs + 1));
|
|
|
|
host_paint_cursor( dirty_curs_x, dirty_curs_y, attr );
|
|
}
|
|
|
|
host_end_update();
|
|
}
|
|
#endif /* EGG */
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_GRAPHICS.seg"
|
|
#endif
|
|
|
|
/*
|
|
* Update the window to look like the regen buffer says it should
|
|
*/
|
|
|
|
void text_update IFN0()
|
|
{
|
|
|
|
register int i; /* Loop counters */
|
|
register int j,k;
|
|
register IU32 *from,*to;
|
|
register int ints_per_line = get_bytes_per_line()>>2;
|
|
register int cur_ypos;
|
|
int lines_per_screen;
|
|
int offset,len,x,screen_start;
|
|
USHORT *wfrom;
|
|
USHORT *wto;
|
|
|
|
if (getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
lines_per_screen = get_screen_length()/get_bytes_per_line();
|
|
|
|
host_start_update();
|
|
screen_start=get_screen_start()<<1;
|
|
ALIGN_SCREEN_START(screen_start);
|
|
to = (IU32 *)&video_copy[screen_start];
|
|
from = (IU32 *) get_screen_ptr(screen_start);
|
|
|
|
if(getVideodirty_total()>1500) /* paint the whole lot */
|
|
{
|
|
for(i=get_screen_length()>>2;i>0;i--)*to++ = *from++;
|
|
cur_ypos = 0;
|
|
for(offset=0;offset<get_screen_length();offset+=get_bytes_per_line() )
|
|
{
|
|
(*paint_screen)(screen_start+offset,0,cur_ypos,get_bytes_per_line(), 1);
|
|
cur_ypos += get_host_char_height();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i=0;i<lines_per_screen;i++)
|
|
{
|
|
for(j=0;j<ints_per_line;j++)
|
|
{
|
|
if(*to++ != *from++)
|
|
{
|
|
to--;from--;
|
|
for(k=ints_per_line-1-j;*(to+k)== *(from+k);k--){};
|
|
/*
|
|
* Note: For text mode there is one char for every word.
|
|
* no of bytes into screen=line*bytes_per_line + ints_into_line*4
|
|
* x_coord=width_of_one_char*(no_of_ints_into_line*2)
|
|
* y_coord=height_of_one_char*2*line
|
|
* length=no_of_ints*4+4 the plus 4 is to counteract the k--
|
|
* The host y co-ords are doubled
|
|
*/
|
|
|
|
/* one or more ints of data are now selected
|
|
but refine difference to words (i.e. characters),
|
|
to avoid a glitch on the screen when typing in to
|
|
a dumb terminal */
|
|
|
|
offset = i * get_bytes_per_line() + (j<<2);
|
|
len = (k<<2) + 4;
|
|
x = (j<<1) * get_pix_char_width();
|
|
wfrom = (USHORT *)from;
|
|
wto = (USHORT *)to;
|
|
if (*wfrom == *wto)
|
|
{
|
|
offset += 2;
|
|
x += get_pix_char_width();
|
|
len -= 2;
|
|
}
|
|
wfrom += (k<<1) + 1;
|
|
wto += (k<<1) + 1;
|
|
if (*wfrom == *wto)
|
|
{
|
|
len -= 2;
|
|
}
|
|
|
|
(*paint_screen)(offset+screen_start,x,i*get_host_char_height(),len, 1);
|
|
|
|
for(k=j;k<ints_per_line;k++)
|
|
*to++ = *from++;
|
|
break; /* onto next line */
|
|
}
|
|
}
|
|
}
|
|
|
|
remove_old_cursor();
|
|
} /* end if(getVideodirty_total()>1500) */
|
|
|
|
setVideodirty_total(0);
|
|
|
|
if (is_cursor_visible())
|
|
{
|
|
half_word attr;
|
|
|
|
dirty_curs_x = get_cur_x();
|
|
dirty_curs_y = get_cur_y();
|
|
|
|
dirty_curs_offs = screen_start+dirty_curs_y * get_offset_per_line() + (dirty_curs_x<<1);
|
|
attr = *(get_screen_ptr(dirty_curs_offs + 1));
|
|
|
|
host_paint_cursor( dirty_curs_x, dirty_curs_y, attr );
|
|
}
|
|
|
|
host_end_update();
|
|
}
|
|
|
|
/*
|
|
* Update the physical screen to reflect the CGA regen buffer
|
|
*/
|
|
|
|
LOCAL VOID
|
|
cga_graph_update_unchained IFN0()
|
|
{
|
|
LONG i, j, k, l; /* Loop counters */
|
|
IU32 *from,*to;
|
|
LONG cur_ypos;
|
|
LONG offs;
|
|
|
|
if (getVideodirty_total() == 0 || get_display_disabled() ) return;
|
|
|
|
host_start_update();
|
|
|
|
/*
|
|
* Graphics mode
|
|
*/
|
|
|
|
to = (IU32 *)&video_copy[0];
|
|
from = (IU32 *) get_screen_ptr(0);
|
|
|
|
if (getVideodirty_total() > 5000)
|
|
{
|
|
/*
|
|
* Refresh the whole screen from the regen buffer
|
|
*/
|
|
|
|
for(i=4096;i>0;i--)
|
|
{
|
|
*to++ = *from++;
|
|
}
|
|
|
|
for (cur_ypos = 0,offs=0; cur_ypos < 400; offs += SCAN_LINE_LENGTH, cur_ypos += 4)
|
|
{
|
|
(*paint_screen)(offs,0,cur_ypos,SCAN_LINE_LENGTH,1);
|
|
(*paint_screen)((offs+ODD_OFFSET),0,cur_ypos+2,SCAN_LINE_LENGTH,1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Draw the dirtied blocks
|
|
*/
|
|
|
|
/* do even lines */
|
|
|
|
for (i = 0; i < 100; i++ )
|
|
{
|
|
for(j=20;j>0;j--)
|
|
{
|
|
if(*to != *from)
|
|
{
|
|
for(k=j-1;*(to+k)== *(from+k);k--)
|
|
;
|
|
|
|
/*
|
|
* i is pc scanline no/2,
|
|
* so offset=(i*SCAN_LINE_LENGTH + bytes_into_line)*inc_count
|
|
* host_x = bytes_into_line*8 -- 8 pixels per byte
|
|
* host_y = i*2*2 -- to convert pc scanlines to host ones
|
|
* length = k -- plus one to counteract k-- in loop
|
|
*/
|
|
|
|
(*paint_screen)
|
|
(((i*SCAN_LINE_LENGTH+((20-j)<<2))),
|
|
(20-j)<<5,i<<2,(k<<2)+4,1);
|
|
|
|
for(l=k+1;l>0;l--)
|
|
{
|
|
*to++ = *from++;
|
|
}
|
|
|
|
l = j - k - 1;
|
|
to += l;
|
|
from += l;
|
|
|
|
break; /* onto next line */
|
|
}
|
|
|
|
to++;
|
|
from++;
|
|
}
|
|
}
|
|
|
|
/* do odd lines */
|
|
|
|
from = (IU32 *) get_screen_ptr(ODD_OFFSET);
|
|
to = (IU32 *)&video_copy[ODD_OFFSET];
|
|
|
|
for (i = 0; i < 100; i++ )
|
|
{
|
|
for(j=20;j>0;j--)
|
|
{
|
|
if(*to != *from)
|
|
{
|
|
for(k=j-1;*(to+k)== *(from+k);k--)
|
|
;
|
|
/*
|
|
* i=line_no/2
|
|
* j=bytes_from_end => (80-j)=bytes from start of line
|
|
* k=no of bytes less 1 different => length in bytes=k+1
|
|
* offset=(i*SCAN_LINE_LENGTH+OFFSET_TO_ODD_BANK+
|
|
* (80-j))*inc_count
|
|
*/
|
|
|
|
(*paint_screen)(
|
|
((i*SCAN_LINE_LENGTH+ODD_OFFSET+((20-j)<<2))),
|
|
(20-j)<<5,(i<<2)+2,(k<<2)+4,1);
|
|
|
|
for(l=k+1;l>0;l--)
|
|
{
|
|
*to++ = *from++;
|
|
}
|
|
|
|
l = j - k - 1;
|
|
to += l;
|
|
from += l;
|
|
|
|
break; /* onto next line */
|
|
}
|
|
|
|
to++;
|
|
from++;
|
|
}
|
|
}
|
|
}
|
|
|
|
host_end_update();
|
|
|
|
setVideodirty_total(0);
|
|
}
|
|
|
|
#ifdef EGG
|
|
LOCAL VOID
|
|
cga_graph_update_chain2 IFN0()
|
|
{
|
|
LONG i, j, k, l; /* Loop counters */
|
|
USHORT *from,*to;
|
|
LONG cur_ypos;
|
|
LONG offs;
|
|
SHORT start_line, end_line;
|
|
|
|
if (getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
host_start_update();
|
|
|
|
/*
|
|
* Graphics mode
|
|
*/
|
|
|
|
to = (USHORT *)&video_copy[0];
|
|
from = (USHORT *) get_screen_ptr(0);
|
|
|
|
if (getVideodirty_total() > 5000)
|
|
{
|
|
/*
|
|
* Refresh the whole screen from the regen buffer
|
|
*/
|
|
|
|
for(i=4096*2;i>0;i--)
|
|
{
|
|
*to++ = *from;
|
|
from += 2;
|
|
}
|
|
|
|
for (cur_ypos = 0,offs=0; cur_ypos < 400;
|
|
offs += SCAN_LINE_LENGTH, cur_ypos += 4)
|
|
{
|
|
(*paint_screen)(offs<<1,0,cur_ypos,SCAN_LINE_LENGTH,1);
|
|
(*paint_screen)((offs+ODD_OFFSET)<<1,0,cur_ypos+2,
|
|
SCAN_LINE_LENGTH,1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Draw the dirtied blocks
|
|
*/
|
|
|
|
/*
|
|
* Start and end line represent the lines within the 8 K video
|
|
* memory blocks, NOT the lines as they appear on screen.
|
|
*/
|
|
start_line = (getVideodirty_low() / SCAN_LINE_LENGTH);
|
|
end_line = (getVideodirty_high() / SCAN_LINE_LENGTH) + 1;
|
|
|
|
/* AJO 6/1/92
|
|
* Can get start/end lines past end of screen since video bank
|
|
* is larger than actally required for these modes; just ignore
|
|
* lines after end of screen. Not doing this check can cause
|
|
* incorrect screen update for programs that deliberately write
|
|
* into the memory between the end of that used for the screen
|
|
* display and the end of the bank (e.g. PCLABS).
|
|
*/
|
|
if (start_line <= 100)
|
|
{
|
|
if (end_line > 100)
|
|
end_line = 100;
|
|
|
|
to = (USHORT *)&video_copy[start_line * SCAN_LINE_LENGTH];
|
|
from = (USHORT *)get_screen_ptr((start_line *
|
|
SCAN_LINE_LENGTH) << 1);
|
|
|
|
/* do even lines */
|
|
|
|
for (i = start_line; i < end_line; i++ )
|
|
{
|
|
for(j=40;j>0;j--)
|
|
{
|
|
if(*to != *from)
|
|
{
|
|
for(k=j-1;*(to+k)== *(from+(k<<1));k--)
|
|
;
|
|
|
|
|
|
/*
|
|
* i is pc scanline no/2,
|
|
* so offset=(i*SCAN_LINE_LENGTH + bytes_into_line)*inc_count
|
|
* host_x = bytes_into_line*8 -- 8 pixels per byte
|
|
* host_y = i*2*2 -- to convert pc scanlines to host ones
|
|
* length = k -- plus one to counteract k-- in loop
|
|
*/
|
|
|
|
(*paint_screen)(
|
|
((i*SCAN_LINE_LENGTH+((40-j)<<1))<<1),
|
|
(40-j)<<4,i<<2,(k<<1)+2,1);
|
|
|
|
for(l=k+1;l>0;l--)
|
|
{
|
|
*to++ = *from;
|
|
from += 2;
|
|
}
|
|
|
|
l = j - k - 1;
|
|
to += l;
|
|
from += l << 1;
|
|
|
|
break; /* onto next line */
|
|
}
|
|
|
|
to++;
|
|
from += 2;
|
|
}
|
|
}
|
|
|
|
/* do odd lines */
|
|
|
|
from = (USHORT *) get_screen_ptr((start_line * SCAN_LINE_LENGTH + ODD_OFFSET) << 1);
|
|
to = (USHORT *)&video_copy[start_line * SCAN_LINE_LENGTH + ODD_OFFSET];
|
|
|
|
for (i = start_line; i < end_line; i++ )
|
|
{
|
|
for(j=40;j>0;j--)
|
|
{
|
|
if(*to != *from)
|
|
{
|
|
for(k=j-1;*(to+k)== *(from+(k<<1));k--)
|
|
;
|
|
|
|
/*
|
|
* i=line_no/2
|
|
* j=bytes_from_end => (80-j)=bytes from start of line
|
|
* k=no of bytes less 1 different => length in bytes=k+1
|
|
* offset=(i*SCAN_LINE_LENGTH+OFFSET_TO_ODD_BANK+(80-j))*inc_count
|
|
*/
|
|
|
|
(*paint_screen)(
|
|
((i*SCAN_LINE_LENGTH+ODD_OFFSET+((40-j)<<1))<<1),
|
|
(40-j)<<4,(i<<2)+2,(k<<1)+2,1);
|
|
|
|
for(l=k+1;l>0;l--)
|
|
{
|
|
*to++ = *from;
|
|
from += 2;
|
|
}
|
|
|
|
l = j - k - 1;
|
|
to += l;
|
|
from += l << 1;
|
|
|
|
break; /* onto next line */
|
|
}
|
|
|
|
to++;
|
|
from += 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
clear_dirty();
|
|
|
|
host_end_update();
|
|
}
|
|
|
|
LOCAL VOID
|
|
cga_graph_update_chain4 IFN0()
|
|
{
|
|
LONG i, j, k, l; /* Loop counters */
|
|
UTINY *from,*to;
|
|
LONG cur_ypos;
|
|
LONG offs;
|
|
SHORT start_line, end_line;
|
|
|
|
if (getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
host_start_update();
|
|
|
|
/*
|
|
* Graphics mode
|
|
*/
|
|
|
|
to = (UTINY *)&video_copy[0];
|
|
from = (UTINY *) get_screen_ptr(0);
|
|
|
|
if (getVideodirty_total() > 5000)
|
|
{
|
|
/*
|
|
* Refresh the whole screen from the regen buffer
|
|
*/
|
|
|
|
for(i=4096*4;i>0;i--)
|
|
{
|
|
*to++ = *from;
|
|
from += 4;
|
|
}
|
|
|
|
for (cur_ypos = 0,offs=0; cur_ypos < 400;
|
|
offs += SCAN_LINE_LENGTH, cur_ypos += 4)
|
|
{
|
|
(*paint_screen)(offs<<2,0,cur_ypos,SCAN_LINE_LENGTH,1);
|
|
(*paint_screen)((offs+ODD_OFFSET)<<2,0,cur_ypos+2,
|
|
SCAN_LINE_LENGTH,1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Draw the dirtied blocks
|
|
*/
|
|
|
|
/*
|
|
* start and end line represent the lines within the 8 K video
|
|
* memory blocks, NOT the lines as they appear on screen.
|
|
*/
|
|
start_line = (getVideodirty_low() / SCAN_LINE_LENGTH);
|
|
end_line = (getVideodirty_high() / SCAN_LINE_LENGTH) + 1;
|
|
|
|
/* AJO 6/1/92
|
|
* Can get start/end lines past end of screen since video bank
|
|
* is larger than actally required for these modes; just ignore
|
|
* lines after end of screen. Not doing this check can cause
|
|
* incorrect screen update for programs that deliberately write
|
|
* into the memory between the end of that used for the screen
|
|
* display and the end of the bank (e.g. PCLABS).
|
|
*/
|
|
if (start_line <= 100)
|
|
{
|
|
if (end_line > 100)
|
|
end_line = 100;
|
|
|
|
to = (UTINY *)&video_copy[start_line * SCAN_LINE_LENGTH];
|
|
from = (UTINY *) get_screen_ptr((start_line *
|
|
SCAN_LINE_LENGTH) << 2);
|
|
|
|
/* do even lines */
|
|
|
|
for (i = start_line; i < end_line; i++ )
|
|
{
|
|
for(j=80;j>0;j--)
|
|
{
|
|
if(*to != *from)
|
|
{
|
|
for(k=j-1;*(to+k)== *(from+(k<<2));k--)
|
|
;
|
|
|
|
/*
|
|
* i is pc scanline no/2, so offset=(i*SCAN_LINE_LENGTH +
|
|
* bytes_into_line)*inc_count
|
|
* host_x = bytes_into_line*8 -- 8 pixels per byte
|
|
* host_y = i*2*2 -- to convert pc scanlines to host ones
|
|
* length = k -- plus one to counteract k-- in loop
|
|
*/
|
|
|
|
(*paint_screen)(
|
|
(i*SCAN_LINE_LENGTH+(80-j))<<2,
|
|
(80-j)<<3,i<<2,k+1,1);
|
|
|
|
for(l=k+1;l>0;l--)
|
|
{
|
|
*to++ = *from;
|
|
from += 4;
|
|
}
|
|
|
|
l = j - k - 1;
|
|
to += l;
|
|
from += l << 2;
|
|
|
|
break; /* onto next line */
|
|
}
|
|
|
|
to++;
|
|
from += 4;
|
|
}
|
|
}
|
|
/* do odd lines */
|
|
|
|
from = (UTINY *) get_screen_ptr(((start_line * SCAN_LINE_LENGTH) + ODD_OFFSET)<<2);
|
|
to = (UTINY *)&video_copy[(start_line * SCAN_LINE_LENGTH) + ODD_OFFSET];
|
|
|
|
for (i = start_line; i < end_line; i++ )
|
|
{
|
|
for(j=80;j>0;j--)
|
|
{
|
|
if(*to != *from)
|
|
{
|
|
for(k=j-1;*(to+k)== *(from+(k<<2));k--)
|
|
;
|
|
/*
|
|
* i=line_no/2
|
|
* j=bytes_from_end => (80-j)=bytes from start of line
|
|
* k=no of bytes less 1 different => length in bytes=k+1
|
|
* offset=(i*SCAN_LINE_LENGTH+OFFSET_TO_ODD_BANK+(80-j))*inc_count
|
|
*/
|
|
|
|
(*paint_screen)(
|
|
(i*SCAN_LINE_LENGTH+(80-j)+ODD_OFFSET)<<2,
|
|
(80-j)<<3,(i<<2)+2,k+1,1);
|
|
|
|
for(l=k+1;l>0;l--)
|
|
{
|
|
*to++ = *from;
|
|
from += 4;
|
|
}
|
|
|
|
l = j - k - 1;
|
|
to += l;
|
|
from += l << 2;
|
|
|
|
break; /* onto next line */
|
|
}
|
|
|
|
to++;
|
|
from += 4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
clear_dirty();
|
|
|
|
host_end_update();
|
|
}
|
|
#endif /* EGG */
|
|
|
|
GLOBAL VOID
|
|
cga_med_graph_update IFN0()
|
|
|
|
{
|
|
|
|
/*
|
|
* The med res CGA graphics mode ( mode 4 ) is an EGA CHAIN2 mode !!
|
|
* It uses the simple ega copy routines that use an interleaved format
|
|
* for the data.
|
|
*/
|
|
|
|
#ifdef EGG
|
|
if( video_adapter != CGA )
|
|
cga_graph_update_chain2( );
|
|
else
|
|
#endif
|
|
cga_graph_update_unchained( );
|
|
}
|
|
|
|
GLOBAL VOID
|
|
cga_hi_graph_update IFN0()
|
|
|
|
{
|
|
|
|
/*
|
|
* The hi res CGA graphics mode ( mode 6 ) is an EGA CHAIN4 mode !!
|
|
* It uses the simple ega copy routines that use an interleaved format
|
|
* for the data.
|
|
*/
|
|
|
|
#ifdef EGG
|
|
if( video_adapter != CGA )
|
|
cga_graph_update_chain4( );
|
|
else
|
|
#endif
|
|
cga_graph_update_unchained( );
|
|
}
|
|
|
|
#ifdef EGG
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_EGA.seg"
|
|
#endif
|
|
|
|
void ega_wrap_split_graph_update IFN0()
|
|
{
|
|
register int bpl;
|
|
register int quarter_opl;
|
|
register int screen_split;
|
|
|
|
if ( getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
screen_split=get_screen_split();
|
|
|
|
/*
|
|
* make sure don't fall off end of screen
|
|
*/
|
|
|
|
if (screen_split>get_screen_height())
|
|
screen_split = get_screen_height();
|
|
|
|
bpl = get_bytes_per_line();
|
|
quarter_opl = get_offset_per_line()>>2;
|
|
|
|
host_start_update();
|
|
|
|
if (getVideodirty_total() > 20000 ) {
|
|
int split_scanlines = get_screen_height() - screen_split;
|
|
|
|
if ( get_screen_start() + screen_split*get_offset_per_line() > EGA_PLANE_DISP_SIZE ) {
|
|
assert0(NO,"Panic he wants to do split screens and wrappig!!");
|
|
|
|
/*
|
|
* Ignore wrapping for now
|
|
*/
|
|
|
|
memset(&video_copy[get_screen_start()>>2],0,screen_split*quarter_opl);
|
|
(*paint_screen)( get_screen_start(), 0, 0, bpl, screen_split );
|
|
}
|
|
else {
|
|
memset(&video_copy[get_screen_start()>>2],0,screen_split*quarter_opl);
|
|
(*paint_screen)( get_screen_start(), 0, 0, bpl, screen_split );
|
|
}
|
|
if (split_scanlines>0) {
|
|
memset(&video_copy[0],0,split_scanlines*quarter_opl);
|
|
(*paint_screen)( 0, 0, screen_split, bpl, split_scanlines);
|
|
}
|
|
}
|
|
else {
|
|
int next,next1;
|
|
|
|
init_dirty_recs();
|
|
|
|
if ( get_screen_start() + screen_split*get_offset_per_line() > EGA_PLANE_DISP_SIZE ) {
|
|
assert0(NO, "Wrapping and spliting, its too much for my head");
|
|
next = search_video_copy(0,screen_split,get_screen_start()>>2);
|
|
}
|
|
else {
|
|
next = search_video_copy(0,screen_split,get_screen_start()>>2);
|
|
}
|
|
next1 = search_video_copy(screen_split,get_screen_height(),0);
|
|
|
|
paint_records(0,next);
|
|
paint_records(next,next1);
|
|
}
|
|
|
|
clear_dirty();
|
|
|
|
host_end_update();
|
|
}
|
|
|
|
void ega_split_graph_update IFN0()
|
|
{
|
|
register int bpl;
|
|
register int quarter_opl;
|
|
register int screen_split;
|
|
register int screen_height;
|
|
|
|
if ( getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
screen_split = get_screen_split()/get_pc_pix_height();
|
|
screen_height = get_screen_height()/get_pc_pix_height();
|
|
|
|
/*
|
|
* make sure don't fall off end of screen
|
|
*/
|
|
|
|
if (screen_split > screen_height)
|
|
screen_split = screen_height;
|
|
|
|
bpl = get_bytes_per_line();
|
|
quarter_opl = get_offset_per_line()>>2;
|
|
|
|
host_start_update();
|
|
|
|
if (getVideodirty_total() > 20000 ) {
|
|
int split_scanlines = screen_height - screen_split;
|
|
|
|
memset(&video_copy[get_screen_start()>>2],0,screen_split*quarter_opl);
|
|
(*paint_screen)( get_screen_start(), 0, 0, bpl, screen_split );
|
|
if (split_scanlines>0) {
|
|
memset(&video_copy[0],0,split_scanlines*quarter_opl);
|
|
(*paint_screen)( 0, 0, screen_split, bpl, split_scanlines);
|
|
}
|
|
}
|
|
else {
|
|
int next,next1;
|
|
|
|
init_dirty_recs();
|
|
|
|
next = search_video_copy(0,screen_split,get_screen_start()>>2);
|
|
next1 = search_video_copy(screen_split,screen_height,0);
|
|
|
|
paint_records(0,next);
|
|
paint_records(next,next1);
|
|
}
|
|
|
|
clear_dirty();
|
|
|
|
host_end_update();
|
|
}
|
|
|
|
#ifdef VGG
|
|
/* again v similar to ega version but works on 1 large plane instead of 4 */
|
|
static void vga_paint_records IFN2(int, start_rec, int, end_rec)
|
|
{
|
|
register DIRTY_PARTS *i,*end_ptr;
|
|
int dirty_frig;
|
|
|
|
i= &dirty[start_rec];
|
|
end_ptr = &dirty[end_rec];
|
|
while (i<end_ptr) {
|
|
register int last_line, cur_start, cur_end,max_width;
|
|
int first_line;
|
|
int dirty_vc_offset;
|
|
|
|
first_line = i->line_no;
|
|
last_line = first_line;
|
|
cur_start = i->start;
|
|
cur_end = i->end;
|
|
max_width = (cur_end-cur_start) << 1; /* To split up diagonal lines */
|
|
|
|
/*
|
|
* offset in bytes into video_copy, which is equivalent to off
|
|
* into 'large' vga plane
|
|
*/
|
|
|
|
dirty_vc_offset = i->video_copy_offset;
|
|
dirty_frig = i->v7frig;
|
|
i++;
|
|
while (i < end_ptr) {
|
|
if ( i->line_no - last_line < 3 ) {
|
|
/*
|
|
* This entry can be included into the same paint
|
|
* as long as it doesn't make the rectangle too wide
|
|
*/
|
|
if ( i->end > cur_end ){
|
|
if(i->end - cur_start > max_width)break;
|
|
cur_end = i->end;
|
|
}
|
|
if ( i->start < cur_start ){
|
|
if(cur_end - i->start > max_width)break;
|
|
cur_start = i->start;
|
|
}
|
|
last_line = i->line_no;
|
|
i++;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
/*
|
|
* paint the rectangle found
|
|
*/
|
|
|
|
/* do not paint beyond the right hand side of the screen;
|
|
these checks were put in to cope with the special
|
|
case of the brain-scan display in 'EGAWOW' */
|
|
if (cur_end > get_bytes_per_line())
|
|
cur_end = get_bytes_per_line();
|
|
if (cur_end > cur_start)
|
|
(*paint_screen)((dirty_vc_offset<<2) + dirty_frig + cur_start,
|
|
cur_start, first_line, cur_end-cur_start,
|
|
last_line-first_line+1);
|
|
}
|
|
/* Clear out video copy */
|
|
for(i = &dirty[start_rec];i<end_ptr;i++)
|
|
{
|
|
register byte *j,*end;
|
|
end = &video_copy[ i->video_copy_offset+(i->end>>2)];
|
|
j = &video_copy[ i->video_copy_offset+(i->start>>2) + i->v7frig];
|
|
do *j++ = 0; while(j<end);
|
|
}
|
|
}
|
|
|
|
|
|
/* dramatically similar to ega graph update but calls vga-ish paint interface */
|
|
void vga_graph_update IFN0()
|
|
{
|
|
register int opl = get_offset_per_line();
|
|
register int bpl = get_bytes_per_line();
|
|
int screen_height = get_screen_height()/
|
|
(get_char_height()*get_pc_pix_height());
|
|
|
|
if ( getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
host_start_update();
|
|
|
|
if (!HostUpdatedVGA()) {
|
|
if (getVideodirty_total() > 20000 )
|
|
{
|
|
register byte *vcopy = &video_copy[get_screen_start()>>2];
|
|
|
|
memset(vcopy,0,get_screen_length()>>2);
|
|
(*paint_screen)( get_screen_start(), 0, 0, bpl, screen_height );
|
|
|
|
#ifdef V7VGA
|
|
draw_v7ptr();
|
|
#endif /* V7VGA */
|
|
}
|
|
else
|
|
{
|
|
register int next;
|
|
register int start_line,end_line;
|
|
|
|
start_line = ((getVideodirty_low()<<2) - get_screen_start())/opl;
|
|
end_line = ((getVideodirty_high()<<2) - get_screen_start())/opl + 1; /* changed from +2, but I'm not happy. WJG 24/5/89 */
|
|
|
|
if(start_line<0)start_line = 0;
|
|
if (end_line > screen_height)
|
|
end_line = screen_height;
|
|
if(start_line < end_line) /* Sanity check - could be drawing to another page */
|
|
{
|
|
/*
|
|
6.4.92 MG
|
|
We remove the pointer before the update. Hits performance, but
|
|
makes the display work correctly.
|
|
*/
|
|
|
|
#ifdef V7VGA
|
|
if (v7ptr_between_lines(start_line,end_line))
|
|
remove_v7ptr();
|
|
#endif /* V7VGA */
|
|
|
|
init_dirty_recs();
|
|
/* see if we can search the video copy by ints instead of bytes - need opl divisible by 16 */
|
|
if(opl & 15)
|
|
#ifdef VGG
|
|
if (opl & 3)
|
|
next = v7_search_video_copy(start_line,end_line,(get_screen_start()+start_line*opl)>>2);
|
|
else
|
|
#endif /* VGG */
|
|
next = search_video_copy(start_line,end_line,(get_screen_start()+start_line*opl)>>2);
|
|
else
|
|
next = search_video_copy_aligned(start_line,end_line,(get_screen_start()+start_line*opl)>>2);
|
|
vga_paint_records(0,next);
|
|
|
|
#ifdef V7VGA
|
|
/*
|
|
* We might have just blatted over the V7 h/w graphics pointer.
|
|
* Hence redraw it. A more intelligent solution would be preferable.
|
|
*
|
|
* 6/4/92 MG We now have a somewhat more intelligent solution,
|
|
* checking if the pointer is in the update region before we
|
|
* draw it.
|
|
*/
|
|
|
|
if (v7ptr_between_lines(start_line,end_line))
|
|
draw_v7ptr();
|
|
#endif /* V7VGA */
|
|
|
|
}
|
|
}
|
|
} /* Host didn't update screen itself */
|
|
|
|
clear_dirty();
|
|
|
|
host_end_update();
|
|
}
|
|
|
|
void vga_split_graph_update IFN0()
|
|
{
|
|
register int bpl;
|
|
register int quarter_opl;
|
|
register int screen_split;
|
|
register int screen_height;
|
|
|
|
if ( getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
screen_split = get_screen_split() /
|
|
(get_char_height() * get_pc_pix_height());
|
|
screen_height = get_screen_height() /
|
|
(get_char_height() * get_pc_pix_height());
|
|
|
|
/*
|
|
* make sure don't fall off end of screen
|
|
*/
|
|
|
|
if (screen_split>screen_height)
|
|
screen_split = screen_height;
|
|
|
|
bpl = get_bytes_per_line();
|
|
quarter_opl = get_offset_per_line()>>2;
|
|
|
|
host_start_update();
|
|
|
|
if (getVideodirty_total() > 20000 ) {
|
|
int split_scanlines = screen_height - screen_split;
|
|
|
|
memset(&video_copy[get_screen_start()>>2],0,screen_split*quarter_opl);
|
|
(*paint_screen)( get_screen_start(), 0, 0, bpl, screen_split );
|
|
if (split_scanlines>0) {
|
|
memset(&video_copy[0],0,split_scanlines*quarter_opl);
|
|
(*paint_screen)( 0, 0, screen_split, bpl, split_scanlines);
|
|
}
|
|
}
|
|
else {
|
|
int next,next1;
|
|
|
|
init_dirty_recs();
|
|
|
|
next = search_video_copy(0,screen_split,get_screen_start()>>2);
|
|
next1 = search_video_copy(screen_split,screen_height,0);
|
|
|
|
vga_paint_records(0,next);
|
|
vga_paint_records(next,next1);
|
|
}
|
|
|
|
clear_dirty();
|
|
|
|
host_end_update();
|
|
}
|
|
|
|
#endif /* VGG */
|
|
|
|
void ega_graph_update IFN0()
|
|
{
|
|
register int opl = get_offset_per_line();
|
|
register int bpl = get_bytes_per_line();
|
|
|
|
if ( getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
host_start_update();
|
|
|
|
if (!HostUpdatedEGA()) {
|
|
if (getVideodirty_total() > 20000)
|
|
{
|
|
register byte *vcopy = &video_copy[get_screen_start()>>2];
|
|
|
|
memset(vcopy,0,get_screen_length()>>2);
|
|
(*paint_screen)( get_screen_start(), 0, 0, bpl, get_screen_height()/get_pc_pix_height());
|
|
}
|
|
else
|
|
{
|
|
register int next;
|
|
register int start_line,end_line;
|
|
|
|
start_line = ((getVideodirty_low()<<2) - get_screen_start())/opl;
|
|
end_line = ((getVideodirty_high()<<2) - get_screen_start())/opl + 1; /* changed from +2, but I'm not happy. WJG 24/5/89 */
|
|
if(start_line<0)start_line = 0;
|
|
if(end_line>(get_screen_height()/get_pc_pix_height()))end_line = get_screen_height()/get_pc_pix_height();
|
|
if(start_line < end_line) /* Sanity check - could be drawing to another page */
|
|
{
|
|
init_dirty_recs();
|
|
|
|
/*
|
|
* See if we can search the video copy by ints instead of bytes
|
|
* - we need opl and the screen_start divisible by 16
|
|
*/
|
|
|
|
if(( opl & 15 ) || ( get_screen_start() & 15 ))
|
|
#ifdef VGG
|
|
if (opl & 3)
|
|
next = v7_search_video_copy( start_line,
|
|
end_line, (get_screen_start()+start_line*opl) >> 2 );
|
|
else
|
|
#endif /* VGG */
|
|
next = search_video_copy( start_line,
|
|
end_line, (get_screen_start()+start_line*opl) >> 2 );
|
|
else
|
|
next = search_video_copy_aligned( start_line,
|
|
end_line, (get_screen_start()+start_line*opl) >> 2 );
|
|
|
|
paint_records(0,next);
|
|
}
|
|
}
|
|
} /* Host updated EGA screen */
|
|
|
|
clear_dirty();
|
|
|
|
#ifdef V7VGA
|
|
/*
|
|
* We might have just blatted over the V7 h/w graphics pointer.
|
|
* Hence redraw it. A more intelligent solution would be preferable.
|
|
*/
|
|
|
|
draw_v7ptr();
|
|
#endif /* V7VGA */
|
|
|
|
host_end_update();
|
|
}
|
|
|
|
|
|
void ega_wrap_graph_update IFN0()
|
|
{
|
|
register int opl = get_offset_per_line();
|
|
register int bpl = get_bytes_per_line();
|
|
|
|
if ( getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
host_start_update();
|
|
|
|
if (getVideodirty_total() > 20000 ) {
|
|
register byte *vcopy = &video_copy[get_screen_start()>>2];
|
|
|
|
if (get_screen_start()+get_screen_length()>EGA_PLANE_DISP_SIZE) {
|
|
register int offset = (EGA_PLANE_DISP_SIZE - get_screen_start());
|
|
register int left_over = offset % opl;
|
|
register int ht1 = offset / opl;
|
|
register int ht2 = get_screen_height() - ht1 - 1;
|
|
register int quarter_opl = opl>>2;
|
|
|
|
memset(vcopy,0,offset>>2);
|
|
memset(&video_copy[0],0,(get_screen_length()-offset)>>2);
|
|
(*paint_screen)( get_screen_start(), 0, 0, bpl, ht1 );
|
|
|
|
/*
|
|
* Deal with line that is split by wrapping
|
|
*/
|
|
|
|
if ( left_over > bpl ) {
|
|
(*paint_screen)( ht1*opl, 0, ht1, bpl, 1);
|
|
}
|
|
else {
|
|
(*paint_screen)( get_screen_start()+ht1*opl, 0, ht1, left_over, 1);
|
|
(*paint_screen)( 0, left_over<<3, ht1, bpl-left_over, 1);
|
|
}
|
|
|
|
(*paint_screen)( opl-left_over, 0, ht1+1, bpl, ht2 );
|
|
}
|
|
else {
|
|
memset(vcopy,0,get_screen_length()>>2);
|
|
(*paint_screen)( get_screen_start(), 0, 0, bpl, get_screen_height() );
|
|
}
|
|
}
|
|
else {
|
|
register int next;
|
|
|
|
init_dirty_recs();
|
|
if (get_screen_start()+get_screen_length()>EGA_PLANE_DISP_SIZE) {
|
|
|
|
register int offset = (EGA_PLANE_DISP_SIZE - get_screen_start());
|
|
register int left_over = offset % opl;
|
|
register int ht1 = offset / opl;
|
|
register int next1;
|
|
register int wrapped_bytes = opl-left_over;
|
|
|
|
|
|
/*
|
|
* Search video copy
|
|
*/
|
|
|
|
next = search_video_copy(0,ht1,get_screen_start()>>2);
|
|
next1 = search_video_copy(ht1,get_screen_height(),wrapped_bytes>>2);
|
|
|
|
paint_records(0,next);
|
|
|
|
/*
|
|
* paint middle line anyway 'cos its too hard to work out whats happened
|
|
*/
|
|
|
|
if (left_over<bpl) {
|
|
(*paint_screen)(EGA_PLANE_DISP_SIZE-left_over,0,ht1,left_over,1);
|
|
(*paint_screen)(0,left_over<<3,ht1,bpl-left_over,1);
|
|
}
|
|
else {
|
|
(*paint_screen)(EGA_PLANE_DISP_SIZE-left_over,0,ht1,bpl,1);
|
|
}
|
|
|
|
/*
|
|
* now do wrapped area
|
|
*/
|
|
|
|
paint_records(next,next1);
|
|
}
|
|
else {
|
|
next = search_video_copy(0,get_screen_height(),get_screen_start()>>2);
|
|
paint_records(0,next);
|
|
}
|
|
}
|
|
|
|
clear_dirty();
|
|
|
|
host_end_update();
|
|
}
|
|
|
|
#endif /* EGG */
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_GRAPHICS.seg"
|
|
#endif
|
|
|
|
/*--------------------- Scrolling routines --------------------------*/
|
|
|
|
#define UP 0
|
|
#define DOWN 1
|
|
|
|
LOCAL VOID
|
|
adjust_cursor IFN7(ULONG, dirn, ULONG, tlx, ULONG, tly, ULONG, width,
|
|
ULONG, height, ULONG, lines, ULONG, bpl )
|
|
{
|
|
|
|
/*
|
|
* We must not adjust dirty_curs_offset here if it is -1, as this tells
|
|
* us that the cursor is not displayed. If dirty_curs_offs becomes
|
|
* positive, we fool remove_old_cursor into trying to replace the cursor
|
|
* with spurious data. JJS - 29/6/95.
|
|
*/
|
|
if (dirty_curs_offs != -1)
|
|
if(( dirty_curs_x >= tlx ) && ( dirty_curs_x < ( tlx + width )))
|
|
if(( dirty_curs_y >= tly ) && ( dirty_curs_y < ( tly + height )))
|
|
{
|
|
switch( dirn )
|
|
{
|
|
case UP:
|
|
dirty_curs_y -= lines;
|
|
dirty_curs_offs -= lines * bpl * 2;
|
|
break;
|
|
|
|
case DOWN:
|
|
dirty_curs_y += lines;
|
|
dirty_curs_offs += lines * bpl * 2;
|
|
break;
|
|
}
|
|
setVideodirty_total(getVideodirty_total() + 1);
|
|
}
|
|
}
|
|
|
|
/*ARGSUSED5*/
|
|
boolean text_scroll_up IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines, int, dummy_arg)
|
|
{
|
|
short blank_word, *ptr, *top_left_ptr,*top_right_ptr, *bottom_right_ptr;
|
|
unsigned short dummy;
|
|
unsigned char *p;
|
|
int words_per_line;
|
|
int i,tlx,tly,htlx,htly,colour;
|
|
int bpl = 2*get_chars_per_line();
|
|
long start_offset;
|
|
register half_word *src,*dest;
|
|
register word *s_ptr,*d_ptr;
|
|
register word data;
|
|
register int j;
|
|
boolean result;
|
|
|
|
UNUSED(dummy_arg);
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
if (video_adapter == MDA)
|
|
{
|
|
/*
|
|
* The colour we fill with for MDA is either black or low intensity white,
|
|
* depending on whether the attribute byte specifies reverse video.
|
|
*/
|
|
colour = ((attr & 0x77) == 0x70)? 1 : 0;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The colour we fill with for colour text displays is controlled by
|
|
* bits 4-6 of attr, with bit 7 turning on blinking (which we don't support)
|
|
*/
|
|
colour = (attr & bg_col_mask) >> 4;
|
|
}
|
|
/*
|
|
* Reduce the width of the rectangle if any right hand area is completely
|
|
* blank.
|
|
*
|
|
* Don't reduce the size of the scrolling region for a dumb terminal.
|
|
* Dumb terminal uses line feeds to scroll up, but only if the whole
|
|
* screen is to be scrolled. Reducing the scroll region causes
|
|
* the whole region to be redrawn.
|
|
*/
|
|
|
|
#ifdef DUMB_TERMINAL
|
|
if (terminal_type != TERMINAL_TYPE_DUMB)
|
|
{
|
|
#endif /* DUMB_TERMINAL */
|
|
|
|
/* originally dummy was char [2] */
|
|
/* unfortunately doing (short) *dummy */
|
|
/* causes a bus error on M88K */
|
|
p = (unsigned char *) &dummy;
|
|
p [0] = ' ';
|
|
p [1] = attr;
|
|
blank_word = dummy;
|
|
|
|
words_per_line = get_chars_per_line();
|
|
top_left_ptr = (short *) get_screen_ptr((start - gvi_pc_low_regen)<<1);
|
|
top_right_ptr = top_left_ptr + width - 2;
|
|
bottom_right_ptr = top_right_ptr + bpl * (height - 1);
|
|
ptr = bottom_right_ptr;
|
|
if (width > 2) /* dont want to get a zero rectangle for safetys sake */
|
|
{
|
|
while (*ptr == blank_word)
|
|
{
|
|
if (ptr == top_right_ptr) /* reached top of column? */
|
|
{
|
|
top_right_ptr -= 2; /* yes go to bottom of next */
|
|
bottom_right_ptr -= 2;
|
|
if (top_right_ptr == top_left_ptr)
|
|
break;
|
|
ptr = bottom_right_ptr;
|
|
}
|
|
else
|
|
ptr -= bpl; /* skipping interleaved planes */
|
|
}
|
|
}
|
|
width = (int)(top_right_ptr - top_left_ptr + 2) << 1;
|
|
#ifdef DUMB_TERMINAL
|
|
}
|
|
#endif /* DUMB_TERMINAL */
|
|
|
|
/* Do the host stuff */
|
|
|
|
start_offset = start - sas_w_at_no_check(VID_ADDR) - gvi_pc_low_regen;
|
|
|
|
tlx = (int)(start_offset%get_bytes_per_line());
|
|
|
|
htlx = tlx * get_pix_char_width()/2;
|
|
|
|
tly = (int)(start_offset/get_bytes_per_line());
|
|
htly = tly * get_host_char_height();
|
|
|
|
result = host_scroll_up(htlx,htly,htlx+width/4*get_pix_char_width()-1,
|
|
htly+height*get_host_char_height()-1, lines*get_host_char_height(),colour);
|
|
|
|
if(!result)
|
|
return FALSE;
|
|
|
|
adjust_cursor( UP, tlx >> 1, tly, width >> 2, height, lines, bpl );
|
|
|
|
/* Scroll up the video_copy */
|
|
|
|
dest = video_copy + start - gvi_pc_low_regen;
|
|
src = dest + lines * bpl;
|
|
|
|
if( width == (2 * bpl))
|
|
{
|
|
/* Can do the whole thing in one go */
|
|
|
|
memcpy(dest,src,(width>>1)*(height-lines));
|
|
fwd_word_fill( (' '<<8) | attr, dest+(width>>1)*(height-lines),(width>>1)*lines/2);
|
|
}
|
|
else
|
|
{
|
|
/* Not scrolling whole width of screen, so do each line seperately */
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width>>1);
|
|
dest += bpl;
|
|
src += bpl;
|
|
}
|
|
|
|
/* Fill exposed area of video copy */
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
fwd_word_fill( (' '<<8) | attr, dest,width>>2);
|
|
dest += bpl;
|
|
}
|
|
}
|
|
|
|
/* Update video buffer */
|
|
|
|
dest = get_screen_ptr((start - gvi_pc_low_regen)<<1);
|
|
src = dest + lines * bpl * 2;
|
|
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
j = width >> 2;
|
|
d_ptr = (word *)dest;
|
|
s_ptr = (word *)src;
|
|
|
|
while( j-- > 0 )
|
|
{
|
|
*d_ptr = *s_ptr; /* CHAR and ATTRIB */
|
|
d_ptr += 2; /* skip FONT and plane 3 */
|
|
s_ptr += 2;
|
|
}
|
|
|
|
dest += bpl * 2;
|
|
src += bpl * 2;
|
|
}
|
|
|
|
/* Fill exposed area of buffer */
|
|
|
|
#ifdef BIGEND
|
|
data = (' ' << 8) | attr;
|
|
#else
|
|
data = (attr << 8) | ' ';
|
|
#endif
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
j = width >> 2;
|
|
d_ptr = (word *) dest;
|
|
|
|
while( j-- > 0 )
|
|
{
|
|
*d_ptr = data;
|
|
d_ptr += 2;
|
|
}
|
|
|
|
dest += bpl * 2;
|
|
}
|
|
|
|
host_scroll_complete();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*ARGSUSED5*/
|
|
boolean text_scroll_down IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines,int,dummy_arg)
|
|
{
|
|
int i,tlx,tly,htlx,htly,colour;
|
|
int bpl = 2*get_chars_per_line();
|
|
long start_offset;
|
|
register half_word *src,*dest;
|
|
register word *d_ptr,*s_ptr;
|
|
register word data;
|
|
register int j;
|
|
boolean result;
|
|
|
|
UNUSED(dummy_arg);
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
if(video_adapter == MDA)
|
|
{
|
|
/*
|
|
* The colour we fill with for MDA is either black or low intensity white,
|
|
* depending on whether the attribute byte specifies reverse video.
|
|
*/
|
|
colour = ((attr & 0x77) == 0x70)? 1 : 0;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The colour we fill with for colour text displays is controlled by
|
|
* bits 4-6 of attr, with bit 7 turning on blinking (which we don't support)
|
|
*/
|
|
colour = (attr & bg_col_mask) >>4;
|
|
}
|
|
|
|
width <<= 1;
|
|
|
|
/* Do the host stuff */
|
|
|
|
start_offset = start - get_screen_start() * 2 - gvi_pc_low_regen;
|
|
|
|
tlx = (int)(start_offset%get_bytes_per_line());
|
|
htlx = tlx * get_pix_char_width()/2;
|
|
|
|
tly = (int)(start_offset/get_bytes_per_line());
|
|
htly = tly * get_host_char_height();
|
|
|
|
result = host_scroll_down(htlx,htly,htlx+width/4*get_pix_char_width()-1,
|
|
htly+height*get_host_char_height()-1, lines*get_host_char_height(),colour);
|
|
|
|
if(!result)
|
|
return FALSE;
|
|
|
|
adjust_cursor( DOWN, tlx >> 1, tly, width >> 2, height, lines, bpl );
|
|
|
|
/* Scroll down the video_copy */
|
|
|
|
if( width == (2 * bpl))
|
|
{
|
|
/* Can do the whole thing in one go */
|
|
src = video_copy + start - gvi_pc_low_regen;
|
|
dest = src + lines * bpl;
|
|
memcpy(dest,src,(width>>1)*(height-lines));
|
|
fwd_word_fill( (' '<<8) | attr, src,(width>>1)*lines/2);
|
|
}
|
|
else
|
|
{
|
|
/* Not scrolling whole width of screen, so do each line seperatly */
|
|
dest = video_copy + start-gvi_pc_low_regen + (height-1) * bpl;
|
|
src = dest - lines * bpl;
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width>>1);
|
|
dest -= bpl;
|
|
src -= bpl;
|
|
}
|
|
|
|
/* Fill exposed area of video copy */
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
fwd_word_fill( (' '<<8) | attr, dest,width>>2);
|
|
dest -= bpl;
|
|
}
|
|
}
|
|
|
|
/* Update video buffer */
|
|
|
|
dest = get_screen_ptr((start - gvi_pc_low_regen)<<1) + (height-1) * bpl * 2;
|
|
src = dest - lines * bpl * 2;
|
|
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
j = width >> 2;
|
|
d_ptr = (word *) dest;
|
|
s_ptr = (word *) src;
|
|
|
|
while( j-- > 0 )
|
|
{
|
|
*d_ptr = *s_ptr;
|
|
d_ptr += 2;
|
|
s_ptr += 2;
|
|
}
|
|
|
|
dest -= bpl * 2;
|
|
src -= bpl * 2;
|
|
}
|
|
|
|
/* Fill exposed area of buffer */
|
|
|
|
#ifdef BIGEND
|
|
data = (' ' << 8) | attr;
|
|
#else
|
|
data = (attr << 8) | ' ';
|
|
#endif
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
j = width >> 2;
|
|
d_ptr = (word *) dest;
|
|
|
|
while( j-- > 0 )
|
|
{
|
|
*d_ptr = data;
|
|
d_ptr += 2;
|
|
}
|
|
|
|
dest -= bpl * 2;
|
|
}
|
|
|
|
host_scroll_complete();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*--------------------- CGA Scrolling routines --------------------------*/
|
|
|
|
/*ARGSUSED5*/
|
|
boolean cga_text_scroll_up IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines,int,dummy_arg)
|
|
{
|
|
short blank_word, *ptr, *top_left_ptr,*top_right_ptr, *bottom_right_ptr;
|
|
unsigned short dummy;
|
|
unsigned char *p;
|
|
int words_per_line;
|
|
int i,tlx,tly,colour;
|
|
int bpl = 2*get_chars_per_line();
|
|
long start_offset;
|
|
register half_word *src,*dest;
|
|
boolean result;
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
UNUSED(dummy_arg);
|
|
|
|
if (video_adapter == MDA)
|
|
{
|
|
/*
|
|
* The colour we fill with for MDA is either black or low intensity white,
|
|
* depending on whether the attribute byte specifies reverse video.
|
|
*/
|
|
colour = ((attr & 0x77) == 0x70)? 1 : 0;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The colour we fill with for colour text displays is controlled by
|
|
* bits 4-6 of attr, with bit 7 turning on blinking (which we don't support)
|
|
*/
|
|
colour = (attr & bg_col_mask) >>4;
|
|
}
|
|
/*
|
|
* Reduce the width of the rectangle if any right hand area is completely
|
|
* blank.
|
|
*
|
|
* Don't reduce the size of the scrolling region for a dumb terminal.
|
|
* Dumb terminal uses line feeds to scroll up, but only if the whole
|
|
* screen is to be scrolled. Reducing the scroll region causes
|
|
* the whole region to be redrawn.
|
|
*/
|
|
|
|
#ifdef DUMB_TERMINAL
|
|
if (terminal_type != TERMINAL_TYPE_DUMB)
|
|
{
|
|
#endif /* DUMB_TERMINAL */
|
|
|
|
/* originally dummy was char [2] */
|
|
/* unfortunately doing (short) *dummy */
|
|
/* causes a bus error on M88K */
|
|
p = (unsigned char *) &dummy;
|
|
p [0] = ' ';
|
|
p [1] = attr;
|
|
blank_word = dummy;
|
|
|
|
words_per_line = get_chars_per_line();
|
|
top_left_ptr = (short *) get_screen_ptr(start - gvi_pc_low_regen);
|
|
top_right_ptr = top_left_ptr + (width >> 1) - 1;
|
|
bottom_right_ptr = top_right_ptr + words_per_line * (height - 1);
|
|
ptr = bottom_right_ptr;
|
|
if (width > 2) /* dont want to get a zero rectangle for safetys sake */
|
|
{
|
|
while (*ptr == blank_word)
|
|
{
|
|
if (ptr == top_right_ptr) /* reached top of column? */
|
|
{
|
|
top_right_ptr--; /* yes go to bottom of next */
|
|
bottom_right_ptr--;
|
|
if (top_right_ptr == top_left_ptr)
|
|
break;
|
|
ptr = bottom_right_ptr;
|
|
}
|
|
else
|
|
ptr -= words_per_line;
|
|
}
|
|
}
|
|
width = (int)(top_right_ptr - top_left_ptr + 1) << 1;
|
|
#ifdef DUMB_TERMINAL
|
|
}
|
|
#endif /* DUMB_TERMINAL */
|
|
|
|
/* do the host stuff */
|
|
start_offset = start - get_screen_start()*2 - gvi_pc_low_regen;
|
|
tlx = (int)(start_offset%get_bytes_per_line())*get_pix_char_width()/2;
|
|
tly = (int)(start_offset/get_bytes_per_line())*get_host_char_height();
|
|
result = host_scroll_up(tlx,tly,tlx+width/2*get_pix_char_width()-1,
|
|
tly+height*get_host_char_height()-1, lines*get_host_char_height(),colour);
|
|
|
|
if(!result)
|
|
return FALSE;
|
|
|
|
/* Adjust cursor */
|
|
|
|
if(( dirty_curs_offs != -1 ) && ( dirty_curs_x < ( width >> 1 )))
|
|
{
|
|
dirty_curs_y -= lines;
|
|
dirty_curs_offs -= lines * bpl;
|
|
setVideodirty_total(getVideodirty_total() + 1);
|
|
}
|
|
|
|
/* Scroll up the video_copy */
|
|
dest = video_copy + start-gvi_pc_low_regen;
|
|
src = dest + lines * bpl;
|
|
|
|
if(width == bpl)
|
|
{
|
|
/* Can do the whole thing in one go */
|
|
memcpy(dest,src,width*(height-lines));
|
|
fwd_word_fill( (' '<<8) | attr, dest+width*(height-lines),width*lines/2);
|
|
}
|
|
else
|
|
{
|
|
/* Not scrolling whole width of screen, so do each line seperatly */
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
dest += bpl;
|
|
src += bpl;
|
|
}
|
|
|
|
/* Fill exposed area of video copy */
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
fwd_word_fill( (' '<<8) | attr, dest,width/2);
|
|
dest += bpl;
|
|
}
|
|
}
|
|
|
|
/* Update video buffer */
|
|
|
|
dest = get_screen_ptr(start - gvi_pc_low_regen);
|
|
src = dest + lines * bpl;
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
dest += bpl;
|
|
src += bpl;
|
|
}
|
|
|
|
/* Fill exposed area of buffer */
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
fwd_word_fill( (' '<<8) | attr, dest,width/2);
|
|
dest += bpl;
|
|
}
|
|
|
|
host_scroll_complete();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*ARGSUSED5*/
|
|
boolean cga_text_scroll_down IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines,int,dummy_arg)
|
|
{
|
|
int i,tlx,tly,colour;
|
|
int bpl = 2*get_chars_per_line();
|
|
long start_offset;
|
|
register half_word *src,*dest;
|
|
boolean result;
|
|
|
|
UNUSED(dummy_arg);
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
if(video_adapter == MDA)
|
|
{
|
|
/*
|
|
* The colour we fill with for MDA is either black or low intensity white,
|
|
* depending on whether the attribute byte specifies reverse video.
|
|
*/
|
|
colour = ((attr & 0x77) == 0x70)? 1 : 0;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The colour we fill with for colour text displays is controlled by
|
|
* bits 4-6 of attr, with bit 7 turning on blinking (which we don't support)
|
|
*/
|
|
colour = (attr & bg_col_mask) >>4;
|
|
}
|
|
|
|
/* do the host stuff */
|
|
start_offset = start - get_screen_start() * 2 - gvi_pc_low_regen;
|
|
tlx = (int)(start_offset%get_bytes_per_line())*get_pix_char_width()/2;
|
|
tly = (int)(start_offset/get_bytes_per_line())*get_host_char_height();
|
|
result = host_scroll_down(tlx,tly,tlx+width/2*get_pix_char_width()-1,
|
|
tly+height*get_host_char_height()-1, lines*get_host_char_height(),colour);
|
|
|
|
if(!result)
|
|
return FALSE;
|
|
|
|
/* Adjust cursor */
|
|
|
|
if(( dirty_curs_offs != -1 ) && ( dirty_curs_x < ( width >> 1 )))
|
|
{
|
|
dirty_curs_y += lines;
|
|
dirty_curs_offs += lines * bpl;
|
|
setVideodirty_total(getVideodirty_total() + 1);
|
|
}
|
|
|
|
/* Scroll down the video_copy */
|
|
|
|
if(width == bpl)
|
|
{
|
|
/* Can do the whole thing in one go */
|
|
src = video_copy + start - gvi_pc_low_regen;
|
|
dest = src + lines * bpl;
|
|
memcpy(dest,src,width*(height-lines));
|
|
fwd_word_fill( (' '<<8) | attr, src,width*lines/2);
|
|
}
|
|
else
|
|
{
|
|
/* Not scrolling whole width of screen, so do each line seperatly */
|
|
dest = video_copy + start-gvi_pc_low_regen + (height-1) * bpl;
|
|
src = dest - lines * bpl;
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
dest -= bpl;
|
|
src -= bpl;
|
|
}
|
|
|
|
/* Fill exposed area of video copy */
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
fwd_word_fill( (' '<<8) | attr, dest,width/2);
|
|
dest -= bpl;
|
|
}
|
|
}
|
|
|
|
/* Update video buffer */
|
|
|
|
dest = get_screen_ptr(start - gvi_pc_low_regen) + (height-1) * bpl;
|
|
src = dest - lines * bpl;
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
dest -= bpl;
|
|
src -= bpl;
|
|
}
|
|
|
|
/* Fill exposed area of buffer */
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
fwd_word_fill( (' '<<8) | attr, dest,width/2);
|
|
dest -= bpl;
|
|
}
|
|
|
|
host_scroll_complete();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
boolean cga_graph_scroll_up IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines, int, colour)
|
|
{
|
|
int i,tlx,tly;
|
|
long start_offset;
|
|
half_word *src,*dest;
|
|
boolean result;
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
/* Do the host stuff */
|
|
|
|
start_offset = start - gvi_pc_low_regen;
|
|
tlx = (int)(start_offset%SCAN_LINE_LENGTH)*8;
|
|
tly = (int)(start_offset/SCAN_LINE_LENGTH)*4;
|
|
|
|
result = host_scroll_up(tlx,tly,tlx+width*8-1,tly+height*4-1,lines*4,colour);
|
|
|
|
if(!result)return FALSE;
|
|
|
|
/* scroll up the video_copy */
|
|
dest = video_copy + start_offset;
|
|
src = dest + lines*SCAN_LINE_LENGTH;
|
|
|
|
if(width == SCAN_LINE_LENGTH)
|
|
{
|
|
/* Can do the whole thing in one go */
|
|
memcpy(dest,src,width*(height-lines));
|
|
memset( dest+width*(height-lines),attr,width*lines);
|
|
memcpy(dest+(ODD_OFFSET),src+(ODD_OFFSET),width*(height-lines));
|
|
memset( dest+width*(height-lines)+(ODD_OFFSET),attr,width*lines);
|
|
}
|
|
else
|
|
{
|
|
/* Not scrolling whole width of screen, so do each line seperatly */
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
memcpy(dest+(ODD_OFFSET),src+(ODD_OFFSET),width);
|
|
dest += SCAN_LINE_LENGTH;
|
|
src += SCAN_LINE_LENGTH;
|
|
}
|
|
|
|
/* clear the video_copy */
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
memset( dest,attr,width);
|
|
memset( dest+(ODD_OFFSET),attr,width);
|
|
dest += SCAN_LINE_LENGTH;
|
|
}
|
|
}
|
|
#ifdef EGG
|
|
if(video_adapter == EGA || video_adapter == VGA)
|
|
{
|
|
int bpl = SCAN_LINE_LENGTH;
|
|
int oof = ODD_OFFSET;
|
|
|
|
if( sas_hw_at_no_check(vd_video_mode) == 6 )
|
|
{
|
|
/* Hi-res mode stored in interleaved format in 3.0 */
|
|
|
|
start_offset <<= 2;
|
|
bpl <<= 2;
|
|
width <<= 2;
|
|
oof <<= 2;
|
|
}
|
|
else
|
|
{
|
|
start_offset <<= 1;
|
|
bpl <<= 1;
|
|
width <<= 1;
|
|
oof <<= 1;
|
|
}
|
|
|
|
dest = EGA_plane01 + start_offset;
|
|
src = dest + lines*bpl;
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
memcpy(dest+oof,src+oof,width);
|
|
dest += bpl;
|
|
src += bpl;
|
|
}
|
|
|
|
/* clear the EGA plane */
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
memset( dest,attr,width);
|
|
memset( dest+oof,attr,width);
|
|
dest += bpl;
|
|
}
|
|
}
|
|
#endif /* EGG */
|
|
|
|
host_scroll_complete();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
boolean cga_graph_scroll_down IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines, int, colour)
|
|
{
|
|
int i,tlx,tly;
|
|
long start_offset;
|
|
register half_word *src,*dest;
|
|
boolean result;
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
/* Do the host stuff */
|
|
|
|
start_offset = start - gvi_pc_low_regen;
|
|
tlx = (int)(start_offset%SCAN_LINE_LENGTH)*8;
|
|
tly = (int)(start_offset/SCAN_LINE_LENGTH)*4;
|
|
|
|
result = host_scroll_down(tlx,tly,tlx+width*8-1,tly+height*4-1, lines*4,colour);
|
|
|
|
if(!result)return FALSE;
|
|
|
|
/* Scroll down the video_copy */
|
|
|
|
if(width == SCAN_LINE_LENGTH)
|
|
{
|
|
/* Can do the whole thing in one go */
|
|
src = video_copy + start - gvi_pc_low_regen;
|
|
dest = src + lines*SCAN_LINE_LENGTH;
|
|
memcpy(dest,src,width*(height-lines));
|
|
memset(src,attr,width*lines);
|
|
memcpy(dest+ODD_OFFSET,src+ODD_OFFSET,width*(height-lines));
|
|
memset(src+ODD_OFFSET,attr,width*lines);
|
|
}
|
|
else
|
|
{
|
|
/* Not scrolling whole width of screen, so do each line seperatly */
|
|
dest = video_copy + start - gvi_pc_low_regen + (height-1)*SCAN_LINE_LENGTH;
|
|
src = dest - lines*SCAN_LINE_LENGTH;
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
memcpy(dest+ODD_OFFSET,src+ODD_OFFSET,width);
|
|
dest -= SCAN_LINE_LENGTH;
|
|
src -= SCAN_LINE_LENGTH;
|
|
}
|
|
|
|
/* clear the video_copy */
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
memset(dest,attr,width);
|
|
memset(dest+ODD_OFFSET,attr,width);
|
|
dest -= SCAN_LINE_LENGTH;
|
|
}
|
|
}
|
|
#ifdef EGG
|
|
if(video_adapter == EGA || video_adapter == VGA)
|
|
{
|
|
register int bpl = SCAN_LINE_LENGTH;
|
|
register int oof = ODD_OFFSET;
|
|
|
|
if( sas_hw_at_no_check(vd_video_mode) == 6 )
|
|
{
|
|
/* Hi-res mode stored in interleaved format in 3.0 */
|
|
|
|
start_offset <<= 2;
|
|
bpl <<= 2;
|
|
width <<= 2;
|
|
oof <<= 2;
|
|
}
|
|
else
|
|
{
|
|
start_offset <<= 1;
|
|
bpl <<= 1;
|
|
width <<= 1;
|
|
oof <<= 1;
|
|
}
|
|
|
|
dest = EGA_plane01 + start - gvi_pc_low_regen + (height-1)*bpl;
|
|
src = dest - lines*bpl;
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
memcpy(dest+oof,src+oof,width);
|
|
dest -= bpl;
|
|
src -= bpl;
|
|
}
|
|
|
|
/* clear the EGA plane */
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
memset(dest,attr,width);
|
|
memset(dest+oof,attr,width);
|
|
dest -= bpl;
|
|
}
|
|
}
|
|
#endif /* EGG */
|
|
|
|
host_scroll_complete();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef VGG
|
|
/*ARGSUSED5*/
|
|
boolean vga_graph_scroll_up IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines,int,dummy)
|
|
{
|
|
int start_offset,tlx,tly;
|
|
boolean status;
|
|
|
|
UNUSED(dummy);
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
(*update_alg.calc_update)();
|
|
/* do the host stuff */
|
|
start_offset = start - get_screen_start();
|
|
tlx = (start_offset%get_offset_per_line())*2;
|
|
tly = (start_offset/get_offset_per_line())*2;
|
|
status = host_scroll_up(tlx,tly,tlx+width*2-1,tly+height*2-1,lines*2,attr);
|
|
|
|
host_scroll_complete();
|
|
|
|
return(status);
|
|
|
|
}
|
|
|
|
/*ARGSUSED5*/
|
|
boolean vga_graph_scroll_down IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines,int,dummy_arg)
|
|
{
|
|
int start_offset,tlx,tly;
|
|
boolean status;
|
|
|
|
UNUSED(dummy_arg);
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
(*update_alg.calc_update)();
|
|
/* do the host stuff */
|
|
start_offset = start - get_screen_start();
|
|
tlx = (start_offset%get_offset_per_line())*2;
|
|
tly = (start_offset/get_offset_per_line())*2;
|
|
status = host_scroll_down(tlx,tly,tlx+width*2-1,tly+height*2-1,lines*2,attr);
|
|
|
|
host_scroll_complete();
|
|
|
|
return(status);
|
|
|
|
}
|
|
|
|
#ifdef V7VGA
|
|
/*ARGSUSED5*/
|
|
boolean v7vga_graph_scroll_up IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines,int,dummy)
|
|
{
|
|
int start_offset,tlx,tly;
|
|
boolean status;
|
|
|
|
UNUSED(dummy);
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
(*update_alg.calc_update)();
|
|
/* do the host stuff */
|
|
start_offset = start - get_screen_start();
|
|
tlx = (start_offset%get_offset_per_line());
|
|
tly = (start_offset/get_offset_per_line());
|
|
status = host_scroll_up(tlx,tly,tlx+width-1,tly+height-1,lines,attr);
|
|
|
|
host_scroll_complete();
|
|
|
|
return(status);
|
|
}
|
|
|
|
/*ARGSUSED5*/
|
|
boolean v7vga_graph_scroll_down IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines,int, dummy_arg)
|
|
{
|
|
int start_offset,tlx,tly;
|
|
boolean status;
|
|
|
|
UNUSED(dummy_arg);
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
(*update_alg.calc_update)();
|
|
/* do the host stuff */
|
|
start_offset = start - get_screen_start();
|
|
tlx = (start_offset%get_offset_per_line());
|
|
tly = (start_offset/get_offset_per_line());
|
|
status = host_scroll_down(tlx,tly,tlx+width-1,tly+height-1,lines,attr);
|
|
|
|
host_scroll_complete();
|
|
|
|
return(status);
|
|
}
|
|
#endif /* V7VGA */
|
|
#endif /* VGG */
|
|
|
|
#ifdef EGG
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#if defined(JOKER) && !defined(PROD)
|
|
#include "SOFTPC_GRAPHICS.seg"
|
|
#undef SEGMENTATION /* HeeHee! */
|
|
#else
|
|
#include "SOFTPC_EGA.seg"
|
|
#endif /* DEV JOKER variants */
|
|
#endif
|
|
|
|
/*ARGSUSED5*/
|
|
boolean ega_graph_scroll_up IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines,int,dummy)
|
|
{
|
|
int start_offset,tlx,tly;
|
|
boolean status;
|
|
|
|
UNUSED(dummy);
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
(*update_alg.calc_update)();
|
|
/* do the host stuff */
|
|
attr &= 0xf;
|
|
start_offset = start - get_screen_start();
|
|
tlx = (start_offset%get_offset_per_line())*8*get_pix_width();
|
|
tly = (start_offset/get_offset_per_line())*get_pc_pix_height();
|
|
status = (host_scroll_up(tlx,tly,tlx+width*8*get_pix_width()-1,tly+height*get_pc_pix_height()-1,lines*get_pc_pix_height(),attr));
|
|
|
|
host_scroll_complete();
|
|
|
|
return(status);
|
|
|
|
}
|
|
|
|
/*ARGSUSED5*/
|
|
boolean ega_graph_scroll_down IFN6(int, start, int, width, int, height,
|
|
int, attr, int, lines,int,dummy_arg)
|
|
{
|
|
int start_offset,tlx,tly;
|
|
boolean status;
|
|
|
|
UNUSED(dummy_arg);
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
(*update_alg.calc_update)();
|
|
|
|
/* do the host stuff */
|
|
attr &= 0xf;
|
|
start_offset = start - get_screen_start();
|
|
tlx = (start_offset%get_offset_per_line())*8*get_pix_width();
|
|
tly = (start_offset/get_offset_per_line())*get_pc_pix_height();
|
|
status = (host_scroll_down(tlx,tly,tlx+width*8*get_pix_width()-1,tly+height*get_pc_pix_height()-1,lines*get_pc_pix_height(),attr));
|
|
|
|
host_scroll_complete();
|
|
|
|
return(status);
|
|
|
|
}
|
|
#endif /* EGG */
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_GRAPHICS.seg"
|
|
#endif
|
|
|
|
#endif /* REAL_VGA */
|
|
|
|
/*ARGSUSED0*/
|
|
boolean dummy_scroll IFN6(int,dummy1,int,dummy2,int,dummy3,int,
|
|
dummy4,int,dummy5,int,dummy6)
|
|
{
|
|
UNUSED(dummy1);
|
|
UNUSED(dummy2);
|
|
UNUSED(dummy3);
|
|
UNUSED(dummy4);
|
|
UNUSED(dummy5);
|
|
UNUSED(dummy6);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#ifndef REAL_VGA
|
|
|
|
/*--------------------- End of scrolling routines --------------------------*/
|
|
|
|
#ifdef GORE
|
|
|
|
#ifdef GORE_PIG
|
|
GLOBAL UTINY gore_copy[0x80000]; /* Big enough for enormous Super7 VGA modes */
|
|
#endif /* GORE_PIG */
|
|
|
|
LOCAL VOID
|
|
gore_mark_byte_nch IFN0()
|
|
{
|
|
#ifdef GORE_PIG
|
|
gore_copy[(Ead >> 2) + (v7_write_bank << 16)] = gd.gd_b_wrt.mark_type;
|
|
#endif /* GORE_PIG */
|
|
|
|
(*gu_handler.b_wrt)(( Ead >> 2 ) + ( v7_write_bank << 16 ));
|
|
}
|
|
|
|
LOCAL VOID
|
|
gore_mark_word_nch IFN0()
|
|
{
|
|
#ifdef GORE_PIG
|
|
gore_copy[(Ead >> 2 ) + 1 + (v7_write_bank << 16)] =
|
|
gore_copy[(Ead >> 2) + (v7_write_bank << 16)] = gd.gd_w_wrt.mark_type;
|
|
#endif /* GORE_PIG */
|
|
|
|
(*gu_handler.w_wrt)(( Ead >> 2 ) + ( v7_write_bank << 16 ));
|
|
}
|
|
|
|
LOCAL VOID
|
|
gore_mark_string_nch IFN0()
|
|
{
|
|
ULONG temp = ( Ead >> 2 ) + ( v7_write_bank << 16 );
|
|
|
|
#ifdef GORE_PIG
|
|
memfill( gd.gd_b_str.mark_type, &gore_copy[temp], &gore_copy[temp+V3-1] );
|
|
#endif /* GORE_PIG */
|
|
|
|
(*gu_handler.b_str)( temp, temp + V3 - 1, V3 );
|
|
}
|
|
|
|
LOCAL VOID
|
|
gore_mark_byte_ch4 IFN0()
|
|
{
|
|
ULONG temp = Ead + ( v7_write_bank << 16 );
|
|
|
|
#ifdef GORE_PIG
|
|
if( temp < gd.dirty_low )
|
|
gd.dirty_low = temp;
|
|
|
|
if( temp > gd.dirty_high )
|
|
gd.dirty_high = temp;
|
|
|
|
gore_copy[temp] = gd.gd_b_wrt.mark_type;
|
|
#endif /* GORE_PIG */
|
|
|
|
(*gu_handler.b_wrt)( temp );
|
|
}
|
|
|
|
LOCAL VOID
|
|
gore_mark_word_ch4 IFN0()
|
|
{
|
|
ULONG temp = Ead + ( v7_write_bank << 16 );
|
|
|
|
#ifdef GORE_PIG
|
|
if( temp < gd.dirty_low )
|
|
gd.dirty_low = temp;
|
|
|
|
if(( temp + 1 ) > gd.dirty_high )
|
|
gd.dirty_high = temp + 1;
|
|
|
|
gore_copy[temp + 1] = gore_copy[temp] = gd.gd_w_wrt.mark_type;
|
|
#endif /* GORE_PIG */
|
|
|
|
(*gu_handler.w_wrt)( Ead + ( v7_write_bank << 16 ));
|
|
}
|
|
|
|
LOCAL VOID
|
|
gore_mark_string_ch4 IFN0()
|
|
{
|
|
ULONG temp = Ead + ( v7_write_bank << 16 );
|
|
ULONG temp2 = temp + V3 - 1;
|
|
|
|
#ifdef GORE_PIG
|
|
if( temp < gd.dirty_low )
|
|
gd.dirty_low = temp;
|
|
|
|
if( temp2 > gd.dirty_high )
|
|
gd.dirty_high = temp2;
|
|
|
|
memfill( gd.gd_b_str.mark_type, &gore_copy[temp], &gore_copy[temp2] );
|
|
#endif /* GORE_PIG */
|
|
|
|
(*gu_handler.b_str)( temp, temp2, V3 );
|
|
}
|
|
#endif /* GORE */
|
|
|
|
#ifdef EGG
|
|
/*
|
|
* Given an offset into CGA memory return the offset
|
|
* within an 8K bank of video memory.
|
|
*/
|
|
#define BANK_OFFSET(off) (off & 0xDFFF)
|
|
|
|
GLOBAL VOID cga_mark_byte IFN1(int, addr)
|
|
{
|
|
register int offset = BANK_OFFSET(addr);
|
|
|
|
if(offset < getVideodirty_low())
|
|
setVideodirty_low(offset);
|
|
|
|
if(offset > getVideodirty_high())
|
|
setVideodirty_high(offset);
|
|
|
|
setVideodirty_total(getVideodirty_total() + 1);
|
|
}
|
|
|
|
GLOBAL VOID cga_mark_word IFN1(int, addr)
|
|
{
|
|
register int offset1 = BANK_OFFSET(addr);
|
|
register int offset2 = offset1 + 1;
|
|
|
|
if(offset1 < getVideodirty_low())
|
|
setVideodirty_low(offset1);
|
|
|
|
if(offset2 > getVideodirty_high())
|
|
setVideodirty_high(offset2);
|
|
|
|
setVideodirty_total(getVideodirty_total() + 2);
|
|
}
|
|
|
|
GLOBAL VOID cga_mark_string IFN2(int, laddr, int, haddr)
|
|
{
|
|
register int offset1 = BANK_OFFSET(laddr);
|
|
register int offset2 = BANK_OFFSET(haddr);
|
|
|
|
if(offset1 < getVideodirty_low())
|
|
setVideodirty_low(offset1);
|
|
|
|
if(offset2 > getVideodirty_high())
|
|
setVideodirty_high(offset2);
|
|
|
|
setVideodirty_total(getVideodirty_total() + offset2-offset1+1);
|
|
}
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_EGA.seg"
|
|
#endif
|
|
|
|
GLOBAL VOID ega_mark_byte IFN1(int, off_in)
|
|
{
|
|
#ifdef GORE
|
|
(*gu_handler.b_wrt)( off_in );
|
|
#else
|
|
register int offset = off_in>>2;
|
|
|
|
video_copy[offset] = 1;
|
|
|
|
if(offset < getVideodirty_low())
|
|
setVideodirty_low(offset);
|
|
|
|
if(offset > getVideodirty_high())
|
|
setVideodirty_high(offset);
|
|
|
|
setVideodirty_total(getVideodirty_total() + 1);
|
|
#endif /* GORE */
|
|
}
|
|
|
|
GLOBAL VOID ega_mark_word IFN1(int, addr)
|
|
{
|
|
#ifdef GORE
|
|
(*gu_handler.w_wrt)( addr );
|
|
#else
|
|
|
|
register int offset1 = addr >> 2;
|
|
register int offset2 = (addr+1) >> 2;
|
|
|
|
video_copy[offset1] = 1;
|
|
video_copy[offset2] = 1;
|
|
|
|
if(offset1 < getVideodirty_low())
|
|
setVideodirty_low(offset1);
|
|
|
|
if(offset2 > getVideodirty_high())
|
|
setVideodirty_high(offset2);
|
|
|
|
setVideodirty_total(getVideodirty_total() + 2);
|
|
#endif /* GORE */
|
|
}
|
|
|
|
GLOBAL VOID ega_mark_wfill IFN3(int, laddr, int, haddr, int, col)
|
|
{
|
|
#ifdef GORE
|
|
(*gu_handler.w_fill)( laddr, haddr, haddr - laddr + 1, col );
|
|
#else
|
|
|
|
register int offset1 = laddr >> 2;
|
|
register int offset2 = haddr >> 2;
|
|
|
|
UNUSED(col);
|
|
|
|
memfill(1,&video_copy[offset1],&video_copy[offset2]);
|
|
|
|
if(offset1 < getVideodirty_low())
|
|
setVideodirty_low(offset1);
|
|
|
|
if(offset2 > getVideodirty_high())
|
|
setVideodirty_high(offset2);
|
|
|
|
setVideodirty_total(getVideodirty_total() + offset2-offset1+1);
|
|
#endif /* GORE */
|
|
}
|
|
|
|
GLOBAL VOID ega_mark_string IFN2(int, laddr, int, haddr)
|
|
{
|
|
#ifdef GORE
|
|
(*gu_handler.b_str)( laddr, haddr, haddr - laddr + 1 );
|
|
#else
|
|
register int offset1 = laddr >> 2;
|
|
register int offset2 = haddr >> 2;
|
|
|
|
memfill(1,&video_copy[offset1],&video_copy[offset2]);
|
|
|
|
if(offset1 < getVideodirty_low())
|
|
setVideodirty_low(offset1);
|
|
|
|
if(offset2 > getVideodirty_high())
|
|
setVideodirty_high(offset2);
|
|
|
|
setVideodirty_total(getVideodirty_total() + offset2-offset1+1);
|
|
#endif /* GORE */
|
|
}
|
|
|
|
#endif /* EGG */
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_GRAPHICS.seg"
|
|
#endif
|
|
|
|
GLOBAL VOID screen_refresh_required IFN0()
|
|
{
|
|
|
|
#ifdef GORE
|
|
(*gu_handler.b_str)( 0, get_screen_length(), get_screen_length() );
|
|
#endif /* GORE */
|
|
|
|
#ifndef CPU_40_STYLE
|
|
/*
|
|
* This is to stop the VGA globals pointer being
|
|
* dereferenced before it is set up in main.c.
|
|
*/
|
|
|
|
if (VGLOBS)
|
|
VGLOBS->dirty_flag = 1000000L;
|
|
#else
|
|
setVideodirty_total(1000000L);
|
|
#endif /* CPU_40_STYLE */
|
|
}
|
|
|
|
#ifdef EGG
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_EGA.seg"
|
|
#endif
|
|
|
|
LOCAL MARKING_TYPE curr_mark_type;
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(X86GFX) ) /* remove uneeded code */
|
|
|
|
GLOBAL VOID
|
|
set_mark_funcs IFN0()
|
|
{
|
|
switch (curr_mark_type)
|
|
{
|
|
case SIMPLE_MARKING:
|
|
update_alg.mark_byte = (T_mark_byte)simple_update;
|
|
update_alg.mark_word = (T_mark_word)simple_update;
|
|
update_alg.mark_fill = (T_mark_fill)simple_update;
|
|
update_alg.mark_wfill = (T_mark_wfill)simple_update;
|
|
update_alg.mark_string = (T_mark_string)simple_update;
|
|
|
|
#ifndef CPU_40_STYLE /* EVID */
|
|
setVideomark_byte(FAST_FUNC_ADDR(_simple_mark_sml));
|
|
setVideomark_word(FAST_FUNC_ADDR(_simple_mark_sml));
|
|
|
|
SET_VGLOBS_MARK_STRING(_simple_mark_lge);
|
|
#else /* CPU_40_STYLE - EVID */
|
|
SetMarkPointers(0);
|
|
#endif /* CPU_40_STYLE - EVID */
|
|
break;
|
|
|
|
case CGA_GRAPHICS_MARKING:
|
|
update_alg.mark_byte = (boolean(*)())cga_mark_byte;
|
|
update_alg.mark_word = (boolean(*)())cga_mark_word;
|
|
update_alg.mark_fill = (boolean(*)())cga_mark_string;
|
|
update_alg.mark_wfill = (boolean(*)())cga_mark_string;
|
|
update_alg.mark_string = (boolean(*)())cga_mark_string;
|
|
|
|
#ifndef CPU_40_STYLE /* EVID */
|
|
setVideomark_byte(FAST_FUNC_ADDR(_cga_mark_byte));
|
|
setVideomark_word(FAST_FUNC_ADDR(_cga_mark_word));
|
|
|
|
SET_VGLOBS_MARK_STRING(_cga_mark_string);
|
|
#else /* CPU_40_STYLE - EVID */
|
|
SetMarkPointers(1);
|
|
#endif /* CPU_40_STYLE - EVID */
|
|
|
|
break;
|
|
|
|
case EGA_GRAPHICS_MARKING:
|
|
#ifdef GORE
|
|
reset_gore_ptrs();
|
|
gd.curr_line_diff = get_bytes_per_line();
|
|
gd.max_vis_addr = get_screen_length() - 1 + ( v7_write_bank << 16 );
|
|
#ifdef VGG
|
|
gd.shift_count = get_256_colour_mode() ? 0 : 3;
|
|
#else
|
|
gd.shift_count = 3;
|
|
#endif /* VGG */
|
|
#endif /* GORE */
|
|
|
|
update_alg.mark_byte = (boolean(*)())ega_mark_byte;
|
|
update_alg.mark_word = (boolean(*)())ega_mark_word;
|
|
update_alg.mark_fill = (boolean(*)())ega_mark_string;
|
|
update_alg.mark_wfill = (boolean(*)())ega_mark_wfill;
|
|
update_alg.mark_string = (boolean(*)())ega_mark_string;
|
|
|
|
switch( EGA_CPU.chain )
|
|
{
|
|
case UNCHAINED:
|
|
#ifdef GORE
|
|
setVideomark_byte(gore_mark_byte_nch);
|
|
setVideomark_word(gore_mark_word_nch);
|
|
|
|
SET_VGLOBS_MARK_STRING(gore_mark_string_nch);
|
|
#else
|
|
#ifndef CPU_40_STYLE /* EVID */
|
|
setVideomark_byte(FAST_FUNC_ADDR(_mark_byte_nch));
|
|
setVideomark_word(FAST_FUNC_ADDR(_mark_word_nch));
|
|
|
|
SET_VGLOBS_MARK_STRING(_mark_string_nch);
|
|
#else /* CPU_40_STYLE - EVID */
|
|
SetMarkPointers(2);
|
|
#endif /* CPU_40_STYLE - EVID */
|
|
#endif /* GORE */
|
|
break;
|
|
|
|
case CHAIN2:
|
|
assert0( NO, "CHAIN2 in graphics mode !!" );
|
|
|
|
break;
|
|
|
|
#ifdef VGG
|
|
case CHAIN4:
|
|
#ifdef GORE
|
|
setVideomark_byte(gore_mark_byte_ch4);
|
|
setVideomark_word(gore_mark_word_ch4);
|
|
|
|
SET_VGLOBS_MARK_STRING(gore_mark_string_ch4);
|
|
#else
|
|
#ifndef CPU_40_STYLE /* EVID */
|
|
setVideomark_byte(FAST_FUNC_ADDR(_mark_byte_ch4));
|
|
setVideomark_word(FAST_FUNC_ADDR(_mark_word_ch4));
|
|
|
|
SET_VGLOBS_MARK_STRING(_mark_string_ch4);
|
|
#else /* CPU_40_STYLE - EVID */
|
|
SetMarkPointers(3);
|
|
#endif /* CPU_40_STYLE - EVID */
|
|
#endif /* GORE */
|
|
break;
|
|
#endif /* VGG */
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
assert1(NO,"Unknown marking type %d", (int) curr_mark_type);
|
|
break;
|
|
}
|
|
}
|
|
#endif /* !NTVDM | (NTVDM & !X86GFX) */
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_GRAPHICS.seg"
|
|
#endif
|
|
|
|
GLOBAL void set_gfx_update_routines IFN3(T_calc_update, update_routine,
|
|
MARKING_TYPE, marking_type, SCROLL_TYPE, scroll_type)
|
|
{
|
|
enable_gfx_update_routines();
|
|
update_alg.calc_update = update_routine;
|
|
switch (scroll_type) {
|
|
case NO_SCROLL:
|
|
update_alg.scroll_up = dummy_scroll;
|
|
update_alg.scroll_down = dummy_scroll;
|
|
break;
|
|
case TEXT_SCROLL:
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
update_alg.scroll_up = mon_text_scroll_up;
|
|
update_alg.scroll_down = mon_text_scroll_down;
|
|
#else
|
|
update_alg.scroll_up = text_scroll_up;
|
|
update_alg.scroll_down = text_scroll_down;
|
|
#endif /* NTVDM & MONITOR */
|
|
break;
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(X86GFX) ) /* remove unneeded code */
|
|
case CGA_GRAPH_SCROLL:
|
|
update_alg.scroll_up = cga_graph_scroll_up;
|
|
update_alg.scroll_down = cga_graph_scroll_down;
|
|
break;
|
|
case EGA_GRAPH_SCROLL:
|
|
update_alg.scroll_up = ega_graph_scroll_up;
|
|
update_alg.scroll_down = ega_graph_scroll_down;
|
|
break;
|
|
#ifdef VGG
|
|
case VGA_GRAPH_SCROLL:
|
|
update_alg.scroll_up = vga_graph_scroll_up;
|
|
update_alg.scroll_down = vga_graph_scroll_down;
|
|
break;
|
|
#ifdef V7VGA
|
|
case V7VGA_GRAPH_SCROLL:
|
|
update_alg.scroll_up = v7vga_graph_scroll_up;
|
|
update_alg.scroll_down = v7vga_graph_scroll_down;
|
|
break;
|
|
#endif /* V7VGA */
|
|
#endif /* VGG */
|
|
#endif /* !NTVDM | (NTVDM & !X86GFX) */
|
|
}
|
|
|
|
curr_mark_type = marking_type;
|
|
|
|
set_mark_funcs();
|
|
|
|
/*
|
|
* The newly setup update routines will not be needed yet if the
|
|
* display is disabled, but must be saved in any case so that
|
|
* redundant enables (as in dosshell) restore the correct ones.
|
|
* If the display is disabled we must also then install the dummy
|
|
* update routines as the current ones.
|
|
*
|
|
* AJO 23/4/93
|
|
* DON'T use disable_gfx_update_routines() here cos' it's a NOP
|
|
* if the display is already disabled which causes bizarre problems
|
|
* if a mode change is performed while disabled.
|
|
*/
|
|
save_gfx_update_routines();
|
|
if (get_display_disabled())
|
|
inhibit_gfx_update_routines();
|
|
}
|
|
#endif /* EGG */
|
|
|
|
#endif /* REAL_VGA */
|
|
|
|
#ifndef cursor_changed
|
|
void cursor_changed IFN2(int, x, int, y)
|
|
{
|
|
#ifndef REAL_VGA
|
|
UNUSED(x);
|
|
UNUSED(y);
|
|
|
|
setVideodirty_total(getVideodirty_total() + 1);
|
|
#else
|
|
IU32 offset;
|
|
|
|
offset = (y * 2 * get_chars_per_line()) + (x << 1);
|
|
offset += get_screen_start()<<1; /* Because screen start is in WORDS */
|
|
vga_card_place_cursor((word)offset);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
void host_cga_cursor_has_moved IFN2(int, x, int, y)
|
|
{
|
|
cursor_changed(x,y);
|
|
}
|
|
|
|
/* Called when the start & end of the cursor are changed. */
|
|
|
|
void base_cursor_shape_changed IFN0()
|
|
{
|
|
cursor_changed(get_cur_x(),get_cur_y());
|
|
}
|
|
|
|
#ifndef REAL_VGA
|
|
#ifdef HERC
|
|
|
|
#define DIRTY ((unsigned char)-1)
|
|
|
|
void herc_update_screen IFN0()
|
|
{
|
|
register int i, j, k, offs, y;
|
|
register USHORT *from, *to;
|
|
int lines_per_screen = get_screen_length() / get_bytes_per_line();
|
|
/* lines of text on screen */
|
|
half_word begin[349], end[348];
|
|
|
|
if(( getVideodirty_total() == 0 ) || get_display_disabled())
|
|
return;
|
|
|
|
host_start_update();
|
|
|
|
if (get_cga_mode() == TEXT)
|
|
{
|
|
/*
|
|
* arbitrary limit over which we just repaint the whole screen in one operation, assuming
|
|
* this is more efficient than working out large minimum rectangles. This value should be
|
|
* tuned at some future point.
|
|
*/
|
|
to = (USHORT *) &video_copy[get_screen_start()];
|
|
from = (USHORT *) get_screen_ptr((get_screen_start() << 1));
|
|
|
|
if (getVideodirty_total() > 1500)
|
|
{
|
|
for (i = get_screen_length() >> 1; i > 0; i--)
|
|
*to++ = *from++;
|
|
|
|
offs = 0;
|
|
y = 0;
|
|
|
|
for( i = 0; i < lines_per_screen; i++ )
|
|
{
|
|
(*paint_screen) (offs, 0, y, get_bytes_per_line() );
|
|
offs += get_bytes_per_line();
|
|
y += get_host_char_height();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* step through row/cols looking for a dirty bit then look for the last clear dirty bit,
|
|
* and draw the line of text
|
|
*/
|
|
register int ints_per_line = get_bytes_per_line() >> 1;
|
|
|
|
for (i = 0, offs = 0; i < lines_per_screen; i++, offs += get_bytes_per_line())
|
|
{
|
|
for (j = 0; j < ints_per_line; j++)
|
|
{
|
|
if (*to++ != *from++)
|
|
{
|
|
to--;
|
|
from--;
|
|
for (k = ints_per_line - 1 - j; *(to + k) == *(from + k); k--)
|
|
;
|
|
|
|
(*paint_screen) (offs + (j << 1), j * get_pix_char_width(),
|
|
i * get_host_char_height() , (k << 1) + 2 );
|
|
|
|
for (k = j; k < ints_per_line; k++)
|
|
*to++ = *from++;
|
|
break; /* onto next line */
|
|
}
|
|
}
|
|
}
|
|
} /* end else getVideodirty_total() > 1500 */
|
|
|
|
remove_old_cursor();
|
|
|
|
if (is_cursor_visible())
|
|
{
|
|
half_word attr;
|
|
|
|
dirty_curs_x = get_cur_x();
|
|
dirty_curs_y = get_cur_y();
|
|
|
|
dirty_curs_offs = dirty_curs_y * get_bytes_per_line() + (dirty_curs_x << 1);
|
|
attr = *(get_screen_ptr(dirty_curs_offs + 1));
|
|
|
|
host_paint_cursor( dirty_curs_x, dirty_curs_y, attr );
|
|
}
|
|
}
|
|
else /* GRAPHICS MODE */
|
|
{
|
|
|
|
to = (USHORT *) &video_copy[0];
|
|
from = (USHORT *) get_screen_ptr(get_screen_start());
|
|
|
|
/*
|
|
* arbitrary limit over which we just repaint the whole screen in one operation, assuming
|
|
* this is more efficient than working out large minimum rectangles. This value should be
|
|
* tuned at some future point.
|
|
*/
|
|
|
|
if (getVideodirty_total() > 8000)
|
|
{
|
|
for (i = 16384; i > 0; i--)
|
|
*to++ = *from++;
|
|
(*paint_screen) (0, 0, 90, 348);
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < 348; i += 4) /* bank 0 */
|
|
{
|
|
begin[i] = DIRTY;
|
|
for (j = 0; j < 45; j++)
|
|
{
|
|
if (*to++ != *from++)
|
|
{
|
|
to--;
|
|
from--;
|
|
for (k = 44 - j; *(to + k) == *(from + k); k--)
|
|
;
|
|
begin[i] = j;
|
|
end[i] = j + k;
|
|
for (k = j; k < 45; k++)
|
|
*to++ = *from++;
|
|
break; /* onto next scan line */
|
|
}
|
|
}
|
|
}
|
|
|
|
to += 181;
|
|
from += 181; /* skip over the gap */
|
|
|
|
for (i = 1; i < 349; i += 4) /* bank 1 */
|
|
{
|
|
begin[i] = DIRTY;
|
|
for (j = 0; j < 45; j++)
|
|
{
|
|
if (*to++ != *from++)
|
|
{
|
|
to--;
|
|
from--;
|
|
for (k = 44 - j; *(to + k) == *(from + k); k--)
|
|
;
|
|
begin[i] = j;
|
|
end[i] = j + k;
|
|
for (k = j; k < 45; k++)
|
|
*to++ = *from++;
|
|
break; /* onto next scan line */
|
|
}
|
|
}
|
|
}
|
|
|
|
to += 181;
|
|
from += 181; /* skip over the gap */
|
|
|
|
for (i = 2; i < 348; i += 4) /* bank 2 */
|
|
{
|
|
begin[i] = DIRTY;
|
|
for (j = 0; j < 45; j++)
|
|
{
|
|
if (*to++ != *from++)
|
|
{
|
|
to--;
|
|
from--;
|
|
for (k = 44 - j; *(to + k) == *(from + k); k--)
|
|
;
|
|
begin[i] = j;
|
|
end[i] = j + k;
|
|
for (k = j; k < 45; k++)
|
|
*to++ = *from++;
|
|
break; /* onto next scan line */
|
|
}
|
|
}
|
|
}
|
|
|
|
to += 181;
|
|
from += 181; /* skip over the gap */
|
|
|
|
for (i = 3; i < 349; i += 4) /* bank 3 */
|
|
{
|
|
begin[i] = DIRTY;
|
|
for (j = 0; j < 45; j++)
|
|
{
|
|
if (*to++ != *from++)
|
|
{
|
|
to--;
|
|
from--;
|
|
for (k = 44 - j; *(to + k) == *(from + k); k--)
|
|
;
|
|
begin[i] = j;
|
|
end[i] = j + k;
|
|
for (k = j; k < 45; k++)
|
|
*to++ = *from++;
|
|
break; /* onto next scan line */
|
|
}
|
|
}
|
|
}
|
|
|
|
begin[348] = DIRTY; /* end marker */
|
|
for (i = 0; i < 348; i++)
|
|
{
|
|
register int beginx, endx, beginy;
|
|
if (begin[i] != DIRTY) /* a dirty scan line */
|
|
{
|
|
beginy = i;
|
|
beginx = begin[i];
|
|
endx = end[i];
|
|
while (begin[++i] != DIRTY)
|
|
{
|
|
if (begin[i] < beginx)
|
|
beginx = begin[i];
|
|
if (end[i] > endx)
|
|
endx = end[i];
|
|
}
|
|
(*paint_screen) (beginy, 2 * beginx, 2 * (endx - beginx + 1), i - beginy);
|
|
}
|
|
}
|
|
} /* end else (getVideodirty_total() > 8000) */
|
|
}
|
|
|
|
setVideodirty_total(0);
|
|
|
|
host_end_update();
|
|
}
|
|
#endif
|
|
|
|
#if defined(VGG) || defined(EGG)
|
|
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_EGA.seg"
|
|
#endif
|
|
|
|
/* ============================================================================
|
|
* The following routines enable and disable the GFX update routines
|
|
* by saving/restoring the current routines and replacing them with
|
|
* dummy routines that do nothing while update is disabled.
|
|
*
|
|
* AJO 23/4/93
|
|
* Any sequence of enable/disable/mode change should now work as expected.
|
|
* ============================================================================
|
|
*/
|
|
|
|
LOCAL UPDATE_ALG save_update_alg;
|
|
LOCAL IBOOL gfx_update_routines_inhibited = FALSE;
|
|
|
|
LOCAL VOID save_gfx_update_routines IFN0()
|
|
{
|
|
/*
|
|
* Save all current update functions so we can restore them later
|
|
*/
|
|
save_update_alg.mark_byte = update_alg.mark_byte;
|
|
save_update_alg.mark_word = update_alg.mark_word;
|
|
save_update_alg.mark_fill = update_alg.mark_fill;
|
|
save_update_alg.mark_wfill = update_alg.mark_wfill;
|
|
save_update_alg.mark_string = update_alg.mark_string;
|
|
save_update_alg.calc_update = update_alg.calc_update;
|
|
save_update_alg.scroll_up = update_alg.scroll_up;
|
|
save_update_alg.scroll_down = update_alg.scroll_down;
|
|
}
|
|
|
|
LOCAL VOID inhibit_gfx_update_routines IFN0()
|
|
{
|
|
/*
|
|
* Set all current update routines to dummy ones that do nothing.
|
|
*/
|
|
gfx_update_routines_inhibited = TRUE;
|
|
|
|
update_alg.mark_byte = (T_mark_byte)simple_update;
|
|
update_alg.mark_word = (T_mark_word)simple_update;
|
|
update_alg.mark_fill = (T_mark_fill)simple_update;
|
|
update_alg.mark_wfill = (T_mark_wfill)simple_update;
|
|
update_alg.mark_string = (T_mark_string)simple_update;
|
|
update_alg.calc_update = dummy_calc;
|
|
update_alg.scroll_up = dummy_scroll;
|
|
update_alg.scroll_down = dummy_scroll;
|
|
}
|
|
|
|
GLOBAL void disable_gfx_update_routines IFN0()
|
|
{
|
|
/*
|
|
* Disable GFX update routines; do nothing if update already disabled,
|
|
* otherwise save the current routines and install dummy ones in their
|
|
* place.
|
|
*/
|
|
note_entrance0("disable gfx update routines");
|
|
|
|
if (gfx_update_routines_inhibited)
|
|
return;
|
|
|
|
save_gfx_update_routines();
|
|
inhibit_gfx_update_routines();
|
|
}
|
|
|
|
GLOBAL void enable_gfx_update_routines IFN0()
|
|
{
|
|
/*
|
|
* Reenable GFX update routines; copy the saved routines back to be
|
|
* the current ones.
|
|
*/
|
|
note_entrance0("enable gfx update routines");
|
|
|
|
gfx_update_routines_inhibited = FALSE;
|
|
|
|
update_alg.mark_byte = save_update_alg.mark_byte;
|
|
update_alg.mark_word = save_update_alg.mark_word;
|
|
update_alg.mark_fill = save_update_alg.mark_fill;
|
|
update_alg.mark_wfill = save_update_alg.mark_wfill;
|
|
update_alg.mark_string = save_update_alg.mark_string;
|
|
update_alg.calc_update = save_update_alg.calc_update;
|
|
update_alg.scroll_up = save_update_alg.scroll_up;
|
|
update_alg.scroll_down = save_update_alg.scroll_down;
|
|
}
|
|
|
|
#endif /* VGG */
|
|
#ifdef SEGMENTATION /* See note with first use of this flag */
|
|
#include "SOFTPC_GRAPHICS.seg"
|
|
#endif
|
|
|
|
#ifdef NTVDM
|
|
|
|
void init_text_rect();
|
|
void add_to_rect(int screen_start,register int x, register int y, int len);
|
|
void paint_text_rect(int screen_start);
|
|
|
|
int RectDefined;
|
|
int RectTop, RectBottom, RectLeft, RectRight;
|
|
|
|
#ifdef MONITOR
|
|
/*
|
|
* Update the window to look like the regen buffer says it should
|
|
* and with no help from dirty_total.
|
|
*/
|
|
|
|
static int now_cur_x = -1, now_cur_y = -1;
|
|
/*
|
|
* Reset the static cursor variables:
|
|
*/
|
|
GLOBAL void resetNowCur()
|
|
{
|
|
now_cur_x = -1;
|
|
now_cur_y = -1;
|
|
}
|
|
|
|
void mon_text_update()
|
|
{
|
|
|
|
register int i; /* Loop counters */
|
|
register int j,k;
|
|
register unsigned long *from,*to;
|
|
register int ints_per_line = get_offset_per_line()>>2;
|
|
int lines_per_screen;
|
|
int len,x,screen_start;
|
|
unsigned short *wfrom;
|
|
unsigned short *wto;
|
|
int dwords_to_compare;
|
|
|
|
/*::::::::::::::::::::::::::::::::::::::::::::::: Is the display disable */
|
|
|
|
if(get_display_disabled()) return;
|
|
|
|
/*::::::::::::::::::::::::::::::::: get screen size and location details */
|
|
|
|
screen_start=get_screen_start()<<1;
|
|
ALIGN_SCREEN_START(screen_start);
|
|
|
|
to = (unsigned long *)&video_copy[screen_start];
|
|
from = (unsigned long *) get_screen_ptr(screen_start);
|
|
|
|
/*::::::::::::::::::::::::::::::::::::::::::: Check for buffer overflows */
|
|
|
|
#ifndef PROD
|
|
if(((int)to) & 3) printf("Video copy not aligned on DWORD\n");
|
|
if(get_screen_length() & 3) printf("Screen size incorrect\n");
|
|
#endif
|
|
|
|
/*::::::::::::::::::::::::::::::::::::::::::::::: Has the screen changed */
|
|
|
|
#ifndef CPU_40_STYLE
|
|
#if defined(NTVDM)
|
|
if( VGLOBS && VGLOBS->dirty_flag >= 1000000L ){
|
|
#else
|
|
if( VGLOBS && VGLOBS->dirtyTotal >= 1000000L ){
|
|
#endif
|
|
|
|
#else
|
|
if(getVideodirty_total() >= 1000000L ){
|
|
#endif
|
|
|
|
/*
|
|
** screen_refresh_required() has requested a complete screen
|
|
** repaint by setting the dirtyTotal.
|
|
**
|
|
** When switching between display pages video copy and display
|
|
** memory could be the same so our normal partial update algorithm
|
|
** gets confused.
|
|
** This scheme updates video copy and then forces a complete
|
|
** repaint.
|
|
** Another option would have been to splat video copy and then go
|
|
** through the partial update code below, but this is quicker.
|
|
**
|
|
** Tim Jan 93.
|
|
*/
|
|
setVideodirty_total(0);
|
|
|
|
/*
|
|
** Copy the screen data to our video copy.
|
|
*/
|
|
dwords_to_compare = get_screen_length() / 4;
|
|
_asm
|
|
{
|
|
push esi //Save orginal values of registers used by the
|
|
push edi //complier
|
|
push ecx
|
|
|
|
mov edi,to //Ptr to video copy
|
|
mov esi,from //Ptr to intel video memory
|
|
|
|
mov ecx,dwords_to_compare
|
|
rep movsd //Move screen data to video copy.
|
|
|
|
pop ecx
|
|
pop edi
|
|
pop esi
|
|
}
|
|
|
|
/*
|
|
** Re-paint the whole screen.
|
|
** Set up rectangle dimension globals here for paint_text_rect(),
|
|
** instead of calling add_to_rect().
|
|
*/
|
|
if (get_offset_per_line() == 0) /* showing up in stress */
|
|
lines_per_screen = 25;
|
|
else
|
|
lines_per_screen = get_screen_length()/get_offset_per_line();
|
|
RectTop = 0;
|
|
RectLeft = 0;
|
|
RectBottom = lines_per_screen - 1;
|
|
RectRight = (ints_per_line<<1) - 1;
|
|
RectDefined = TRUE;
|
|
host_start_update();
|
|
paint_text_rect(screen_start);
|
|
host_end_update();
|
|
|
|
}else{
|
|
|
|
/*
|
|
** Normal partial screen update.
|
|
*/
|
|
|
|
dwords_to_compare = get_screen_length() / 4;
|
|
|
|
_asm
|
|
{
|
|
push esi //Save orginal values of registers used by the
|
|
push edi //complier
|
|
push ecx
|
|
|
|
mov esi,to //Ptr to screen copy
|
|
mov edi,from //Ptr to intel video memory
|
|
|
|
mov ecx,dwords_to_compare
|
|
repe cmpsd //Compare screen buffers
|
|
|
|
mov dwords_to_compare,ecx
|
|
// mov to,esi
|
|
// mov from,edi
|
|
|
|
pop ecx
|
|
pop edi
|
|
pop esi
|
|
}
|
|
|
|
/*::::::::::::::::::::::: Repaint parts of the screen that have changed */
|
|
|
|
|
|
if (get_offset_per_line() == 0) /* showing up in stress */
|
|
lines_per_screen = 25;
|
|
else
|
|
lines_per_screen = get_screen_length()/get_offset_per_line();
|
|
|
|
if(dwords_to_compare)
|
|
{
|
|
host_start_update();
|
|
/* Screen changed, calculate position of first variation */
|
|
|
|
init_text_rect();
|
|
|
|
for(i=0;i<lines_per_screen;i++)
|
|
{
|
|
for(j=0;j<ints_per_line;j++)
|
|
{
|
|
if(*to++ != *from++)
|
|
{
|
|
to--;from--;
|
|
for(k=ints_per_line-1-j;*(to+k)== *(from+k);k--){};
|
|
/*
|
|
* Note: For text mode there is one char for every word.
|
|
* no of bytes into screen=line*bytes_per_line + ints_into_line*4
|
|
* x_coord=width_of_one_char*(no_of_ints_into_line*2)
|
|
* y_coord=height_of_one_char*2*line
|
|
* length=no_of_ints*4+4 the plus 4 is to counteract the k--
|
|
* The host y co-ords are doubled
|
|
*/
|
|
|
|
/* one or more ints of data are now selected
|
|
but refine difference to words (i.e. characters),
|
|
to avoid a glitch on the screen when typing in to
|
|
a dumb terminal */
|
|
|
|
len = (k<<2) + 4;
|
|
x = (j<<1);
|
|
|
|
wfrom = (unsigned short *)from;
|
|
wto = (unsigned short *)to;
|
|
if (*wfrom == *wto)
|
|
{
|
|
x++;
|
|
len -= 2;
|
|
}
|
|
wfrom += (k<<1) + 1;
|
|
wto += (k<<1) + 1;
|
|
if (*wfrom == *wto)
|
|
{
|
|
len -= 2;
|
|
}
|
|
|
|
add_to_rect(screen_start, x, i, len/2);
|
|
|
|
/*.............................. transfer data painted to video copy */
|
|
|
|
for(k=j;k<ints_per_line;k++)
|
|
*to++ = *from++;
|
|
|
|
break; /* onto next line */
|
|
}
|
|
}
|
|
}
|
|
|
|
/* End of screen, flush any outstanding text update rectangles */
|
|
paint_text_rect(screen_start);
|
|
|
|
host_end_update();
|
|
|
|
} /* End of partial screen update */
|
|
|
|
} /* End of if dirtyTotal stuff, which selects full or partial repaint */
|
|
|
|
|
|
/*:::::::::::::::::::::::::::::::::::::: Does the cursor need repainting */
|
|
|
|
if(is_cursor_visible())
|
|
{
|
|
half_word attr;
|
|
|
|
dirty_curs_x = get_cur_x();
|
|
dirty_curs_y = get_cur_y();
|
|
|
|
if(dirty_curs_x == now_cur_x && dirty_curs_y == now_cur_y)
|
|
{
|
|
host_end_update();
|
|
return;
|
|
}
|
|
|
|
now_cur_x = dirty_curs_x;
|
|
now_cur_y = dirty_curs_y;
|
|
dirty_curs_offs = screen_start+dirty_curs_y * get_offset_per_line() + (dirty_curs_x<<1);
|
|
|
|
if(dirty_curs_offs < 0x8001) /* no lookup in possible gap */
|
|
attr = *(get_screen_ptr(dirty_curs_offs + 1));
|
|
else
|
|
attr = 0; /* will be off screen anyway */
|
|
|
|
host_paint_cursor(dirty_curs_x, dirty_curs_y, attr);
|
|
}
|
|
|
|
}
|
|
|
|
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
|
|
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
|
|
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
|
|
|
|
boolean mon_text_scroll_up IFN6(sys_addr, start, int, width, int, height, int, attr, int, lines, int, colour)
|
|
{
|
|
short blank_word, *ptr, *top_left_ptr,*top_right_ptr, *bottom_right_ptr;
|
|
unsigned short dummy;
|
|
unsigned char *p;
|
|
int words_per_line;
|
|
int i,tlx,tly;
|
|
int bpl = 2*get_chars_per_line();
|
|
long start_offset;
|
|
register half_word *src,*dest;
|
|
boolean result;
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
/*
|
|
* The colour we fill with for colour text displays is controlled by
|
|
* bits 4-6 of attr, with bit 7 turning on blinking (which we don't support)
|
|
*/
|
|
colour = ((half_word)attr>>4) & 7;
|
|
|
|
/*
|
|
* Reduce the width of the rectangle if any right hand area is completely
|
|
* blank.
|
|
*
|
|
* Don't reduce the size of the scrolling region for a dumb terminal.
|
|
* Dumb terminal uses line feeds to scroll up, but only if the whole
|
|
* screen is to be scrolled. Reducing the scroll region causes
|
|
* the whole region to be redrawn.
|
|
*/
|
|
|
|
/* originally dummy was char [2] */
|
|
/* unfortunately doing (short) *dummy */
|
|
/* causes a bus error on M88K */
|
|
p = (unsigned char *) &dummy;
|
|
p [0] = ' ';
|
|
p [1] = attr;
|
|
blank_word = dummy;
|
|
|
|
words_per_line = get_chars_per_line();
|
|
top_left_ptr = (short *) get_screen_ptr(start - gvi_pc_low_regen);
|
|
top_right_ptr = top_left_ptr + (width >> 1) - 1;
|
|
bottom_right_ptr = top_right_ptr + words_per_line * (height - 1);
|
|
ptr = bottom_right_ptr;
|
|
if (width > 2) /* dont want to get a zero rectangle for safetys sake */
|
|
{
|
|
while (*ptr == blank_word)
|
|
{
|
|
if (ptr == top_right_ptr) /* reached top of column? */
|
|
{
|
|
top_right_ptr--; /* yes go to bottom of next */
|
|
bottom_right_ptr--;
|
|
if (top_right_ptr == top_left_ptr)
|
|
break;
|
|
ptr = bottom_right_ptr;
|
|
}
|
|
else
|
|
ptr -= words_per_line;
|
|
}
|
|
}
|
|
width = (int)(top_right_ptr - top_left_ptr + 1) << 1;
|
|
|
|
/* do the host stuff */
|
|
start_offset = start - get_screen_start()*2 - gvi_pc_low_regen;
|
|
tlx = (int)(start_offset%get_bytes_per_line())*get_pix_char_width()/2;
|
|
tly = (int)(start_offset/get_bytes_per_line())*get_host_char_height();
|
|
result = host_scroll_up(tlx,tly,tlx+width/2*get_pix_char_width()-1,
|
|
tly+height*get_host_char_height()-1, lines*get_host_char_height(),colour);
|
|
|
|
if(!result)
|
|
return FALSE;
|
|
|
|
|
|
adjust_cursor( UP, tlx, tly, width >> 1, height, lines, bpl );
|
|
|
|
/* Scroll up the video_copy */
|
|
dest = video_copy + start-gvi_pc_low_regen;
|
|
src = dest + lines * bpl;
|
|
|
|
if(width == bpl)
|
|
{
|
|
/* Can do the whole thing in one go */
|
|
memcpy(dest,src,width*(height-lines));
|
|
fwd_word_fill( (' '<<8) | (half_word)attr, dest+width*(height-lines),width*lines/2);
|
|
}
|
|
else
|
|
{
|
|
/* Not scrolling whole width of screen, so do each line seperatly */
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
dest += bpl;
|
|
src += bpl;
|
|
}
|
|
|
|
/* Fill exposed area of video copy */
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
fwd_word_fill( (' '<<8) | (half_word)attr, dest,width/2);
|
|
dest += bpl;
|
|
}
|
|
}
|
|
|
|
/* Update video buffer */
|
|
|
|
dest = get_screen_ptr(start - gvi_pc_low_regen);
|
|
src = dest + lines * bpl;
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
dest += bpl;
|
|
src += bpl;
|
|
}
|
|
|
|
/* Fill exposed area of buffer */
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
fwd_word_fill( (' '<<8) | (half_word)attr, dest,width/2);
|
|
dest += bpl;
|
|
}
|
|
|
|
host_scroll_complete();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
boolean mon_text_scroll_down IFN6(sys_addr, start, int, width, int, height, int, attr, int, lines, int, colour)
|
|
{
|
|
int i,tlx,tly;
|
|
int bpl = 2*get_chars_per_line();
|
|
long start_offset;
|
|
register half_word *src,*dest;
|
|
boolean result;
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(MONITOR))
|
|
if ( getVM() )
|
|
return FALSE; /* Don't optimise in V86 Mode */
|
|
#endif
|
|
|
|
/*
|
|
* The colour we fill with for colour text displays is controlled by
|
|
* bits 4-6 of attr, with bit 7 turning on blinking (which we don't support)
|
|
*/
|
|
colour = ((half_word)attr>>4) & 7;
|
|
|
|
|
|
/* do the host stuff */
|
|
start_offset = start - get_screen_start() * 2 - gvi_pc_low_regen;
|
|
tlx = (int)(start_offset%get_bytes_per_line())*get_pix_char_width()/2;
|
|
tly = (int)(start_offset/get_bytes_per_line())*get_host_char_height();
|
|
result = host_scroll_down(tlx,tly,tlx+width/2*get_pix_char_width()-1,
|
|
tly+height*get_host_char_height()-1, lines*get_host_char_height(),colour);
|
|
|
|
if(!result)
|
|
return FALSE;
|
|
|
|
adjust_cursor( DOWN, tlx, tly, width >> 1, height, lines, bpl );
|
|
|
|
/* Scroll down the video_copy */
|
|
|
|
if(width == bpl)
|
|
{
|
|
/* Can do the whole thing in one go */
|
|
src = video_copy + start - gvi_pc_low_regen;
|
|
dest = src + lines * bpl;
|
|
memcpy(dest,src,width*(height-lines));
|
|
fwd_word_fill( (' '<<8) | (half_word)attr, src,width*lines/2);
|
|
}
|
|
else
|
|
{
|
|
/* Not scrolling whole width of screen, so do each line seperatly */
|
|
dest = video_copy + start-gvi_pc_low_regen + (height-1) * bpl;
|
|
src = dest - lines * bpl;
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
dest -= bpl;
|
|
src -= bpl;
|
|
}
|
|
|
|
/* Fill exposed area of video copy */
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
fwd_word_fill( (' '<<8) | (half_word)attr, dest,width/2);
|
|
dest -= bpl;
|
|
}
|
|
}
|
|
|
|
/* Update video buffer */
|
|
|
|
dest = get_screen_ptr(start - gvi_pc_low_regen) + (height-1) * bpl;
|
|
src = dest - lines * bpl;
|
|
for(i=0;i<height-lines;i++)
|
|
{
|
|
memcpy(dest,src,width);
|
|
dest -= bpl;
|
|
src -= bpl;
|
|
}
|
|
|
|
/* Fill exposed area of buffer */
|
|
|
|
for(i=0;i<lines;i++)
|
|
{
|
|
fwd_word_fill( (' '<<8) | (half_word)attr, dest,width/2);
|
|
dest -= bpl;
|
|
}
|
|
|
|
host_scroll_complete();
|
|
|
|
return TRUE;
|
|
}
|
|
#endif /* MONITOR */
|
|
|
|
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
|
|
/*::::::::::::::::::::::::: Text handling routines :::::::::::::::::::::::::::*/
|
|
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
|
|
|
|
#define MAX_LEFT_VARIATION (2)
|
|
#define MAX_RIGHT_VARIATION (5)
|
|
|
|
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
|
|
|
int ExpandCount;
|
|
int BaseL, BaseR;
|
|
|
|
/* Init text rect variables */
|
|
|
|
void init_text_rect()
|
|
{
|
|
RectDefined = FALSE; /* No rectangle defined yet */
|
|
ExpandCount = 0;
|
|
}
|
|
|
|
/* Add coordinates to rectangle */
|
|
|
|
void add_to_rect(int screen_start, register int x, register int y, int len)
|
|
{
|
|
int endx = x + len - 1;
|
|
|
|
/* printf("add rect - (%d,%d) len %d\n", x, y, len); */
|
|
|
|
|
|
/* Is there an existing rectangle */
|
|
if(RectDefined)
|
|
{
|
|
/* Validate X variation and Y coord */
|
|
|
|
if(abs(BaseL - x) <= MAX_LEFT_VARIATION &&
|
|
abs(BaseR - endx) <= MAX_RIGHT_VARIATION &&
|
|
RectBottom+1 >= y)
|
|
{
|
|
/* Expand rectangle */
|
|
ExpandCount++;
|
|
/* printf("Expanding rect\n"); */
|
|
|
|
RectLeft = MIN(RectLeft,x);
|
|
RectRight = MAX(RectRight,endx);
|
|
RectBottom = y;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
paint_text_rect(screen_start);
|
|
}
|
|
}
|
|
|
|
/* New rectangle */
|
|
|
|
/* printf("Defining new rect\n"); */
|
|
|
|
RectDefined = TRUE; /* Rectangle defined */
|
|
|
|
BaseL = x; /* Base Left/Right */
|
|
BaseR = endx;
|
|
|
|
RectTop = y; /* Define rectangle */
|
|
RectLeft = x;
|
|
|
|
RectBottom = y;
|
|
RectRight = endx;
|
|
}
|
|
|
|
|
|
/* Paint rectangle */
|
|
|
|
void paint_text_rect(int screen_start)
|
|
{
|
|
#ifdef MONITOR
|
|
int offset = RectTop * get_offset_per_line() + (RectLeft<<1);
|
|
#else
|
|
int offset = (RectTop * (get_offset_per_line()<<1)) + (RectLeft<<2);
|
|
#endif
|
|
|
|
/* Is there a rectangled defined */
|
|
if(!RectDefined) return;
|
|
|
|
/* Paint rectangle */
|
|
|
|
/* printf("Paint rect (%d,%d) (%d,%d) \t[%d]\n",RectLeft,RectTop,RectRight,RectBottom,ExpandCount); */
|
|
|
|
(*paint_screen)(offset + screen_start, /* Start Offset */
|
|
#ifdef MONITOR
|
|
RectLeft, RectTop, /* Screen X,Y */
|
|
#else
|
|
RectLeft*get_pix_char_width(),RectTop*get_host_char_height(),
|
|
#endif
|
|
(RectRight - RectLeft +1)*2, /* Len */
|
|
RectBottom - RectTop +1); /* Height */
|
|
|
|
RectDefined = FALSE; /* Rectangle painted */
|
|
ExpandCount = 0;
|
|
}
|
|
|
|
#ifndef MONITOR
|
|
void jazz_text_update()
|
|
{
|
|
|
|
register int i; /* Loop counters */
|
|
register int j,k;
|
|
register unsigned short *from,*to;
|
|
register int chars_per_line = get_offset_per_line()>>1;
|
|
int lines_per_screen;
|
|
int offset,len,x,screen_start;
|
|
unsigned short *wfrom;
|
|
unsigned short *wto;
|
|
|
|
if (getVideodirty_total() == 0 || get_display_disabled() )
|
|
return;
|
|
|
|
lines_per_screen = get_screen_length()/get_offset_per_line();
|
|
|
|
host_start_update();
|
|
|
|
screen_start=get_screen_start()<<2;
|
|
ALIGN_SCREEN_START(screen_start);
|
|
|
|
to = (unsigned short *)&video_copy[get_screen_start()<<1];
|
|
from = (unsigned short *) get_screen_ptr(screen_start);
|
|
|
|
if(getVideodirty_total() >1500) /* paint the whole lot */
|
|
{
|
|
for(i=get_screen_length()>>1;i>0;i--)
|
|
{
|
|
*to++ = *from; /* char and attribute bytes */
|
|
from += 2; /* planes 2,3 interleaved */
|
|
}
|
|
|
|
(*paint_screen)(screen_start, 0, 0, get_bytes_per_line(),
|
|
lines_per_screen);
|
|
}
|
|
else
|
|
{
|
|
init_text_rect();
|
|
|
|
for(i=0;i<lines_per_screen;i++)
|
|
{
|
|
for(j=0;j<chars_per_line;j++)
|
|
{
|
|
if(*to != *from)
|
|
{
|
|
k=chars_per_line-1-j;
|
|
wfrom = from + k*2;
|
|
wto = to + k;
|
|
|
|
for(;*wto== *wfrom;k--,wto--,wfrom-=2){};
|
|
/*
|
|
* Note: For text mode there is one char for every word.
|
|
* no of bytes into screen=line*bytes_per_line + ints_into_line*4
|
|
* x_coord=width_of_one_char*(no_of_ints_into_line*2)
|
|
* y_coord=height_of_one_char*2*line
|
|
* length=no_of_ints*4+4 the plus 4 is to counteract the k--
|
|
* The host y co-ords are doubled
|
|
*/
|
|
|
|
/* one or more ints of data are now selected
|
|
but refine difference to words (i.e. characters),
|
|
to avoid a glitch on the screen when typing in to
|
|
a dumb terminal */
|
|
|
|
offset = (i * (get_offset_per_line()<<1)) + (j<<2);
|
|
len = (k<<2) + 4;
|
|
add_to_rect(screen_start, j, i, len/4);
|
|
|
|
for(k=j;k<chars_per_line;k++)
|
|
{
|
|
*to++ = *from;
|
|
from+=2;
|
|
}
|
|
break; /* onto next line */
|
|
}
|
|
else
|
|
{
|
|
to++; from +=2;
|
|
}
|
|
}
|
|
}
|
|
/* End of screen, flush any outstanding text update rectangles */
|
|
paint_text_rect(screen_start);
|
|
}
|
|
|
|
setVideodirty_total(0);
|
|
|
|
/*:::::::::::::::::::::::::::::::::::::::::::::::::: Repaint cursor */
|
|
|
|
if (is_cursor_visible())
|
|
{
|
|
half_word attr;
|
|
|
|
dirty_curs_x = get_cur_x();
|
|
dirty_curs_y = get_cur_y();
|
|
|
|
dirty_curs_offs = screen_start+dirty_curs_y * (get_offset_per_line()<<1) + (dirty_curs_x<<2);
|
|
attr = *(get_screen_ptr(dirty_curs_offs + 1));
|
|
|
|
host_paint_cursor( dirty_curs_x, dirty_curs_y, attr );
|
|
}
|
|
|
|
host_end_update();
|
|
}
|
|
#endif /* MONITOR */
|
|
#endif /* NTVDM */
|
|
#endif /* REAL_VGA */
|
|
|
|
#ifdef NTVDM
|
|
void stream_io_update(void)
|
|
{
|
|
|
|
#ifdef MONITOR
|
|
if (sas_w_at_no_check(stream_io_bios_busy_sysaddr)) {
|
|
return;
|
|
|
|
}
|
|
#endif
|
|
|
|
if (*stream_io_dirty_count_ptr) {
|
|
host_start_update();
|
|
host_stream_io_update(stream_io_buffer, *stream_io_dirty_count_ptr);
|
|
host_end_update();
|
|
*stream_io_dirty_count_ptr = 0;
|
|
|
|
}
|
|
|
|
}
|
|
#endif
|