Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1218 lines
27 KiB

#include "insignia.h"
#include "host_def.h"
#if !defined(NTVDM) || (defined(NTVDM) && !defined(X86GFX) )
/* 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 : name and number
RELATED DOCS : include all relevant references
DESIGNER : J Maiden
REVISION HISTORY :
First version : J Maiden, SoftPC 2.0
Second version : J Shanly, SoftPC 3.0
SUBMODULE NAME : write mode 1 and 2
SOURCE FILE NAME : ega_writem1.c
PURPOSE : functions to write to EGA memory in write modes 1 & 2
SccsID = @(#)ega_wrtm12.c 1.20 3/9/94 Copyright Insignia Solutions Ltd.
[1.INTERMODULE INTERFACE SPECIFICATION]
[1.0 INCLUDE FILE NEEDED TO ACCESS THIS INTERFACE FROM OTHER SUBMODULES]
INCLUDE FILE : ega_cpu.pi
[1.1 INTERMODULE EXPORTS]
PROCEDURES() :
ega_mode1_chn_b_write();
ega_mode1_chn_w_write();
ega_mode1_chn_b_fill();
ega_mode1_chn_w_fill();
ega_mode1_chn_b_move();
ega_mode1_chn_w_move();
ega_mode2_chn_b_write();
ega_mode2_chn_w_write();
ega_mode2_chn_b_fill();
ega_mode2_chn_w_fill();
ega_mode2_chn_b_move();
ega_mode2_chn_w_move();
DATA : give type and name
-------------------------------------------------------------------------
[1.2 DATATYPES FOR [1.1] (if not basic C types)]
STRUCTURES/TYPEDEFS/ENUMS:
-------------------------------------------------------------------------
[1.3 INTERMODULE IMPORTS]
(not o/s objects or standard libs)
-------------------------------------------------------------------------
[1.4 DESCRIPTION OF INTERMODULE INTERFACE]
[1.4.1 IMPORTED OBJECTS]
DATA OBJECTS : struct EGA_CPU
FILES ACCESSED : NONE
DEVICES ACCESSED : NONE
SIGNALS CAUGHT : NONE
SIGNALS ISSUED : NONE
[1.4.2 EXPORTED OBJECTS]
/*=======================================================================
[3.INTERMODULE INTERFACE DECLARATIONS]
=========================================================================
[3.1 INTERMODULE IMPORTS] */
/* [3.1.1 #INCLUDES] */
#ifdef EGG
#include "xt.h"
#include "debug.h"
#include "sas.h"
#include TypesH
#include CpuH
#include "gmi.h"
#include "egacpu.h"
#include "egaports.h"
#include "cpu_vid.h"
#include "gfx_upd.h"
/* [3.1.2 DECLARATIONS] */
/* [3.2 INTERMODULE EXPORTS] */
/*
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.
*/
#ifdef PROD
#include "SOFTPC_EGA.seg"
#else
#include "SOFTPC_EGA_WRITE.seg"
#endif
#endif
/* [5.1.2 TYPEDEF, STRUCTURE, ENUM DECLARATIONS] */
/* [5.1.3 PROCEDURE() DECLARATIONS] */
/* -----------------------------------------------------------------------
[5.2 LOCAL DEFINITIONS]
[5.2.1 INTERNAL DATA DEFINITIONS */
/* [5.2.2 INTERNAL PROCEDURE DEFINITIONS] */
/*
7.INTERMODULE INTERFACE IMPLEMENTATION :
/*
[7.1 INTERMODULE DATA DEFINITIONS] */
#ifdef A_VID
IMPORT VOID _ch2_mode1_chn_byte_write_glue();
IMPORT VOID _ch2_mode1_chn_word_write_glue();
IMPORT VOID _ch2_mode1_chn_byte_fill_glue();
IMPORT VOID _ch2_mode1_chn_word_fill_glue();
IMPORT VOID _ch2_mode1_chn_byte_move_glue();
IMPORT VOID _ch2_mode1_chn_word_move_glue();
WRT_POINTERS mode1_handlers =
{
_ch2_mode1_chn_byte_write_glue,
_ch2_mode1_chn_word_write_glue
#ifndef NO_STRING_OPERATIONS
,
_ch2_mode1_chn_byte_fill_glue,
_ch2_mode1_chn_word_fill_glue,
_ch2_mode1_chn_byte_move_glue,
_ch2_mode1_chn_byte_move_glue,
_ch2_mode1_chn_word_move_glue,
_ch2_mode1_chn_word_move_glue
#endif /* NO_STRING_OPERATIONS */
};
IMPORT VOID _ch2_mode2_chn_byte_write_glue();
IMPORT VOID _ch2_mode2_chn_word_write_glue();
IMPORT VOID _ch2_mode2_chn_byte_fill_glue();
IMPORT VOID _ch2_mode2_chn_word_fill_glue();
IMPORT VOID _ch2_mode2_chn_byte_move_glue();
IMPORT VOID _ch2_mode2_chn_word_move_glue();
WRT_POINTERS mode2_handlers =
{
_ch2_mode2_chn_byte_write_glue,
_ch2_mode2_chn_word_write_glue
#ifndef NO_STRING_OPERATIONS
,
_ch2_mode2_chn_byte_fill_glue,
_ch2_mode2_chn_word_fill_glue,
_ch2_mode2_chn_byte_move_glue,
_ch2_mode2_chn_byte_move_glue,
_ch2_mode2_chn_word_move_glue,
_ch2_mode2_chn_word_move_glue
#endif /* NO_STRING_OPERATIONS */
};
#else
VOID ega_mode1_chn_b_write();
VOID ega_mode1_chn_w_write();
VOID ega_mode1_chn_b_fill();
VOID ega_mode1_chn_w_fill();
VOID ega_mode1_chn_b_move();
VOID ega_mode1_chn_w_move();
VOID ega_mode2_chn_b_write();
VOID ega_mode2_chn_w_write();
VOID ega_mode2_chn_b_fill();
VOID ega_mode2_chn_w_fill();
VOID ega_mode2_chn_b_move IPT4(ULONG, ead, ULONG, eas,
ULONG, count, ULONG, src_flag);
VOID ega_mode2_chn_w_move IPT4(ULONG, ead, ULONG, eas,
ULONG, count, ULONG, src_flag);
WRT_POINTERS mode1_handlers =
{
ega_mode1_chn_b_write,
ega_mode1_chn_w_write
#ifndef NO_STRING_OPERATIONS
,
ega_mode1_chn_b_fill,
ega_mode1_chn_w_fill,
ega_mode1_chn_b_move,
ega_mode1_chn_b_move,
ega_mode1_chn_w_move,
ega_mode1_chn_w_move,
#endif /* NO_STRING_OPERATIONS */
};
WRT_POINTERS mode2_handlers =
{
ega_mode2_chn_b_write,
ega_mode2_chn_w_write
#ifndef NO_STRING_OPERATIONS
,
ega_mode2_chn_b_fill,
ega_mode2_chn_w_fill,
ega_mode2_chn_b_move,
ega_mode2_chn_b_move,
ega_mode2_chn_w_move,
ega_mode2_chn_w_move,
#endif /* NO_STRING_OPERATIONS */
};
#endif /* A_VID */
GLOBAL VOID
copy_alternate_bytes IFN3(byte *, start, byte *, end, byte *, source)
{
while (start <= end)
{
*start = *source;
start += 4; /* advance by longs, writing bytes */
source += 4;
}
}
GLOBAL VOID
fill_alternate_bytes IFN3(byte *, start, byte *, end, byte, value )
{
while( start <= end )
{
*start = value;
start += 4; /* advance by longs, writing bytes */
}
}
#ifdef BIGEND
#define first_half(wd) ((wd & 0xff00) >> 8)
#define sec_half(wd) (wd & 0xff)
#else
#define first_half(wd) (wd & 0xff)
#define sec_half(wd) ((wd & 0xff00) >> 8)
#endif
GLOBAL VOID
fill_both_bytes IFN3(USHORT, data, USHORT *, dest, ULONG, len )
{
USHORT swapped;
#ifdef BIGEND
swapped = ((data & 0xff00) >> 8) | ((data & 0xff) << 8);
#endif
if( (ULONG) dest & 1 )
{
*((UTINY *) dest) = first_half(data);
dest = (USHORT *) ((ULONG) dest + 1);
len--;
while( len-- )
{
*dest = data;
dest += 2;
}
*((UTINY *) dest) = sec_half(data);
}
else
{
while( len-- )
{
#ifdef BIGEND
*dest = swapped;
#else
*dest = data;
#endif
dest += 2;
}
}
}
#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_EGA_CHN.seg"
#endif
VOID
ega_mode1_chn_b_write IFN2(ULONG, value, ULONG, offset )
{
ULONG lsb;
UNUSED(value);
note_entrance0("ega_mode1_chn_b_write");
lsb = offset & 1;
offset = (offset >> 1) << 2;
if( lsb ) /* odd address, in plane 1 or 3 */
{
if( getVideoplane_enable() & 2 )
EGA_plane01[offset + 1] = get_latch1;
if( getVideoplane_enable() & 8 )
EGA_plane23[offset + 1] = get_latch3;
}
else /* even address, in plane 0 or 2 */
{
if( getVideoplane_enable() & 1 )
EGA_plane01[offset] = get_latch0;
if( getVideoplane_enable() & 4 )
EGA_plane23[offset] = get_latch2;
}
update_alg.mark_byte( offset );
}
VOID
ega_mode1_chn_w_write IFN2(ULONG, value, ULONG, offset )
{
ULONG lsb;
UNUSED(value);
note_entrance0("ega_mode1_chn_w_write");
lsb = offset & 1;
offset = (offset >> 1) << 2;
if( lsb ) /* odd address, low byte in planes 1 and 3 */
{
if( getVideoplane_enable() & 2 )
EGA_plane01[offset + 1] = get_latch1;
if( getVideoplane_enable() & 1 )
EGA_plane01[offset + 4] = get_latch0;
if( getVideoplane_enable() & 8 )
EGA_plane23[offset + 1] = get_latch3;
if( getVideoplane_enable() & 4 )
EGA_plane23[offset + 4] = get_latch2;
}
else /* even address, low byte in planes 0 and 2 */
{
if( getVideoplane_enable() & 1 )
EGA_plane01[offset] = get_latch0;
if( getVideoplane_enable() & 2 )
EGA_plane01[offset + 1] = get_latch1;
if( getVideoplane_enable() & 4 )
EGA_plane23[offset] = get_latch2;
if( getVideoplane_enable() & 8 )
EGA_plane23[offset + 1] = get_latch3;
}
update_alg.mark_word( offset );
}
/* used by both byte and word mode1 fill */
LOCAL VOID
ega_mode1_chn_fill IFN2(ULONG, offset, ULONG, count )
{
ULONG low_offset; /* distance into regen buffer of start of write */
ULONG high_offset; /* distance into regen buffer of end of write */
ULONG length; /* length of fill in bytes */
ULONG lsb;
note_entrance0("ega_mode1_chn_fill");
/*
* Complicated by possibility that only one of a chained pair of
* planes is write enabled, needing alternate bytes to be written.
*/
high_offset = offset + count - 1;
lsb = high_offset & 1;
high_offset = (high_offset >> 1) << 2;
high_offset |= lsb;
low_offset = offset;
length = count;
switch( getVideoplane_enable() & 3 )
{
case 1: /* just plane 0, ie even addresses to be written */
if( offset & 1 )
low_offset++;
low_offset = (low_offset >> 1) << 2;
fill_alternate_bytes( &EGA_plane01[low_offset],
&EGA_plane01[high_offset], get_latch0 );
break;
case 2: /* just plane 1, ie odd addresses to be written */
if(( offset & 1 ) == 0 )
low_offset++;
low_offset = (low_offset >> 1) << 2;
fill_alternate_bytes( &EGA_plane01[low_offset],
&EGA_plane01[high_offset], get_latch1 );
break;
case 3: /* sensible case is to have both chained planes write enabled */
lsb = low_offset & 1;
low_offset = (low_offset >> 1) << 2;
if( lsb )
{
EGA_plane01[low_offset + 1] = get_latch1;
low_offset += 4;
length--;
}
if( length & 1 )
{
length -= 1;
EGA_plane01[low_offset + (length << 1)] = get_latch0;
}
fill_both_bytes( get_latch1 | get_latch0 << 8,
(USHORT *)&EGA_plane01[low_offset], length >> 1 );
break;
} /* end of switch on plane01 enabled */
low_offset = offset;
length = count;
switch( getVideoplane_enable() & 0xc ) /* isolate 2 bits for planes2 and 3 */
{
case 4: /* just plane 2, ie even addresses to be written */
if( low_offset & 1 )
low_offset++;
low_offset = (low_offset >> 1) << 2;
fill_alternate_bytes( &EGA_plane23[low_offset],
&EGA_plane23[high_offset], get_latch2 );
break;
case 8: /* just plane 3, ie odd addresses to be written */
if(( low_offset & 1 ) == 0 )
low_offset++;
low_offset = (low_offset >> 1) << 2;
fill_alternate_bytes( &EGA_plane23[low_offset],
&EGA_plane23[high_offset], get_latch3 );
break;
case 12: /* sensible case is to have both chained planes write enabled */
lsb = low_offset & 1;
low_offset = (low_offset >> 1) << 2;
if( lsb )
{
EGA_plane23[low_offset + 1] = get_latch1;
low_offset += 4;
length--;
}
if( length & 1 )
{
length -= 1;
EGA_plane23[low_offset + (length << 1)] = get_latch0;
}
fill_both_bytes( get_latch1 | get_latch0 << 8,
(USHORT *)&EGA_plane23[low_offset], length >> 1 );
break;
} /* end of switch on plane23 enabled */
}
VOID
ega_mode1_chn_b_fill IFN3(ULONG, value, ULONG, offset, ULONG, count )
{
UNUSED(value);
note_entrance0("ega_mode1_chn_b_fill");
ega_mode1_chn_fill( offset, count );
update_alg.mark_fill( offset, offset + count - 1 );
}
VOID
ega_mode1_chn_w_fill IFN3(ULONG, value, ULONG, offset, ULONG, count )
{
UNUSED(value);
note_entrance0("ega_mode1_chn_w_fill");
ega_mode1_chn_fill( offset, count );
update_alg.mark_fill( offset, offset + count - 1 );
}
LOCAL VOID
ega_mode1_chn_move_vid_src IFN5(ULONG, ead, ULONG, eas, ULONG, count,
UTINY *, EGA_plane, ULONG, plane )
{
ULONG end, lsbd, lsbs, dst, src;
lsbs = eas & 1;
eas = (eas >> 1) << 2;
eas |= lsbs;
end = ead + count - 1;
lsbd = end & 1;
end = (end >> 1) << 2;
end |= lsbd;
lsbd = ead & 1;
ead = (ead >> 1) << 2;
ead |= lsbd;
if( lsbd != ( plane & 1 ))
{
dst = lsbd ? ead + 3 : ead + 1;
src = lsbs ? eas + 3 : eas + 1;
}
else
{
dst = ead;
src = eas;
}
copy_alternate_bytes( &EGA_plane[dst], &EGA_plane[end], &EGA_plane[src] );
}
GLOBAL VOID
ega_mode1_chn_b_move IFN4(ULONG, ead, ULONG, eas, ULONG, count, ULONG, src_flag )
{
note_entrance0("ega_mode1_chn_b_move");
if( src_flag )
{
if( getDF() )
{
eas -= count - 1;
ead -= count - 1;
}
if( getVideoplane_enable() & 1 )
ega_mode1_chn_move_vid_src( ead, eas, count, EGA_plane01, 0 );
if( getVideoplane_enable() & 2 )
ega_mode1_chn_move_vid_src( ead, eas, count, EGA_plane01, 1 );
if( getVideoplane_enable() & 4 )
ega_mode1_chn_move_vid_src( ead, eas, count, EGA_plane23, 2 );
if( getVideoplane_enable() & 8 )
ega_mode1_chn_move_vid_src( ead, eas, count, EGA_plane23, 3 );
}
else /* source is not in ega memory, it becomes a fill */
{
if( getDF() )
ead -= count - 1;
ega_mode1_chn_fill( ead, count );
}
update_alg.mark_string( ead, ead + count - 1 );
}
VOID
ega_mode1_chn_w_move IFN4(ULONG, ead, ULONG, eas, ULONG, count, ULONG, src_flag)
{
note_entrance0("ega_mode1_chn_w_move");
count <<= 1;
if( src_flag )
{
if( getDF() )
{
eas -= count - 2;
ead -= count - 2;
}
if( getVideoplane_enable() & 1 )
ega_mode1_chn_move_vid_src( ead, eas, count, EGA_plane01, 0 );
if( getVideoplane_enable() & 2 )
ega_mode1_chn_move_vid_src( ead, eas, count, EGA_plane01, 1 );
if( getVideoplane_enable() & 4 )
ega_mode1_chn_move_vid_src( ead, eas, count, EGA_plane23, 2 );
if( getVideoplane_enable() & 8 )
ega_mode1_chn_move_vid_src( ead, eas, count, EGA_plane23, 3 );
}
else /* source is not in ega memory, it becomes a fill */
{
if( getDF() )
ead -= count - 2;
ega_mode1_chn_fill( ead, count );
}
update_alg.mark_string( ead, ead + count - 1 );
}
VOID
ega_mode2_chn_b_write IFN2(ULONG, value, ULONG, offset )
{
ULONG value1;
ULONG lsb;
note_entrance0("ega_mode2_chn_b_write");
lsb = offset & 1;
offset = (offset >> 1) << 2;
if( EGA_CPU.fun_or_protection )
{
if( lsb ) /* odd address, applies to planes 1 and 3 */
{
if( getVideoplane_enable() & 2 )
{
value1 = value & 2 ? 0xff : 0;
EGA_plane01[offset + 1] = do_logicals( value1, get_latch1 );
}
if( getVideoplane_enable() & 8 )
{
value1 = value & 8 ? 0xff : 0;
EGA_plane23[offset + 1] = do_logicals( value1, get_latch3 );
}
}
else /* even address, applies to planes 0 and 2 */
{
if( getVideoplane_enable() & 1 )
{
value1 = value & 1 ? 0xff : 0;
EGA_plane01[offset] = do_logicals( value1, get_latch0 );
}
if( getVideoplane_enable() & 4 )
{
value1 = value & 4 ? 0xff : 0;
EGA_plane23[offset] = do_logicals( value1, get_latch2 );
}
}
}
else /* no difficult function or protection stuff */
{
if( lsb ) /* odd address, applies to planes 1 and 3 */
{
if( getVideoplane_enable() & 2 )
EGA_plane01[offset + 1] = value & 2 ? 0xff : 0;
if( getVideoplane_enable() & 8 )
EGA_plane23[offset + 1] = value & 8 ? 0xff : 0;
}
else /* even address, applies to planes 0 and 2 */
{
if( getVideoplane_enable() & 1 )
EGA_plane01[offset] = value & 1 ? 0xff : 0;
if( getVideoplane_enable() & 8 )
EGA_plane23[offset] = value & 4 ? 0xff : 0;
}
}
update_alg.mark_byte( offset );
}
VOID
ega_mode2_chn_w_write IFN2(ULONG, value, ULONG, offset )
{
ULONG value2;
ULONG lsb;
ULONG low, high;
low = value & 0xff;
high = value >> 8;
note_entrance0("ega_mode2_chn_w_write");
lsb = offset & 1;
offset = (offset >> 1) << 2;
if( EGA_CPU.fun_or_protection )
{
if( lsb ) /* odd address, low byte in planes 1 and 3 */
{
if( getVideoplane_enable() & 2 )
{
value2 = low & 2 ? 0xff : 0;
EGA_plane01[offset + 1] = do_logicals( value2, get_latch1 );
}
if( getVideoplane_enable() & 1 )
{
value2 = high & 1 ? 0xff : 0;
EGA_plane01[offset + 4] = do_logicals( value2, get_latch0 );
}
if( getVideoplane_enable() & 8 )
{
value2 = low & 8 ? 0xff : 0;
EGA_plane23[offset + 1] = do_logicals( value2, get_latch3 );
}
if( getVideoplane_enable() & 4 )
{
value2 = high & 4 ? 0xff : 0;
EGA_plane23[offset + 4] = do_logicals( value2, get_latch2 );
}
}
else /* even address, low byte in planes 0 and 2 */
{
if( getVideoplane_enable() & 1 )
{
value2 = low & 1 ? 0xff : 0;
EGA_plane01[offset] = do_logicals( value2, get_latch0 );
}
if( getVideoplane_enable() & 2 )
{
value2 = high & 2 ? 0xff : 0;
EGA_plane01[offset + 1] = do_logicals( value2, get_latch1 );
}
if( getVideoplane_enable() & 4 )
{
value2 = low & 4 ? 0xff : 0;
EGA_plane23[offset] = do_logicals( value2, get_latch2 );
}
if( getVideoplane_enable() & 8 )
{
value2 = high & 8 ? 0xff : 0;
EGA_plane23[offset + 1] = do_logicals( value2, get_latch3 );
}
}
}
else /* easy no function or bit prot case */
{
if( lsb ) /* odd address, low byte in planes 1 and 3 */
{
if( getVideoplane_enable() & 2 )
EGA_plane01[offset + 1] = low & 2 ? 0xff : 0;
if( getVideoplane_enable() & 1 )
EGA_plane01[offset + 4] = high & 1 ? 0xff : 0;
if( getVideoplane_enable() & 8 )
EGA_plane23[offset + 1] = low & 8 ? 0xff : 0;
if( getVideoplane_enable() & 4 )
EGA_plane23[offset + 4] = high & 4 ? 0xff : 0;
}
else /* even address, low byte in planes 0 and 2 */
{
if( getVideoplane_enable() & 1 )
EGA_plane01[offset] = low & 1 ? 0xff : 0;
if( getVideoplane_enable() & 2 )
EGA_plane01[offset + 1] = high & 2 ? 0xff : 0;
if( getVideoplane_enable() & 4 )
EGA_plane23[offset] = low & 4 ? 0xff : 0;
if( getVideoplane_enable() & 8 )
EGA_plane23[offset + 1] = high & 8 ? 0xff : 0;
}
}
update_alg.mark_word( offset );
}
VOID
ega_mode2_chn_b_fill IFN3(ULONG, value, ULONG, offset, ULONG, count )
{
ULONG low_offset; /* distance into regen buffer of write start and end */
ULONG high_offset; /* distance into regen buffer of write start and end */
ULONG new_value;
note_entrance0("ega_mode2_chn_b_fill");
/*
* Complicated by possibility that only one of a chained pair of
* planes is write enabled, needing alternate bytes to be written.
*/
/* starting on odd address makes it difficult, go to next one */
if(( (ULONG) offset & 1 ) && count )
{
ega_mode2_chn_b_write(value, offset++ );
count--;
}
/* ending on even address makes it difficult, retreat to previous one */
if(( (ULONG)( offset + count - 1 ) & 1 ) == 0 && count )
{
ega_mode2_chn_b_write(value, offset + count - 1 );
count--;
}
low_offset = (offset >> 1) << 2; /* start of write */
high_offset = ((offset + count - 1) >> 1) << 2; /* end of write */
switch( getVideoplane_enable() & 3 )
{
case 1: /* just plane 0, ie even addresses to be written */
value = value & 1 ? 0xff : 0;
if( EGA_CPU.fun_or_protection )
value = do_logicals( value, get_latch0 );
fill_alternate_bytes( &EGA_plane01[low_offset],
&EGA_plane01[high_offset], value );
break;
case 2: /* just plane 1, ie odd addresses to be written */
value = value & 2 ? 0xff : 0;
if( EGA_CPU.fun_or_protection )
value = do_logicals( value, get_latch1 );
fill_alternate_bytes( &EGA_plane01[low_offset + 1],
&EGA_plane01[high_offset], value );
break;
case 3: /* sensible case is to have both chained planes write enabled */
new_value = ( value & 1 ? 0xff : 0) | (value & 2 ? 0xff00: 0);
if( EGA_CPU.fun_or_protection )
new_value = do_logicals( new_value, get_latch01);
fill_both_bytes( new_value, (USHORT *)&EGA_plane01[low_offset], count >> 1 );
break;
} /* end of switch on plane01 enabled */
switch( getVideoplane_enable() & 0xc ) /* isolate 2 bits for planes2 and 3 */
{
case 4: /* just plane 2, ie even addresses to be written */
value = value & 4 ? 0xff : 0;
if( EGA_CPU.fun_or_protection )
value = do_logicals( value, get_latch2 );
fill_alternate_bytes( &EGA_plane23[low_offset],
&EGA_plane23[high_offset], value );
break;
case 8: /* just plane 3, ie odd addresses to be written */
value = value & 8 ? 0xff : 0;
if( EGA_CPU.fun_or_protection )
value = do_logicals( value, get_latch3 );
fill_alternate_bytes( &EGA_plane23[low_offset + 1],
&EGA_plane23[high_offset], value );
break;
case 12: /* sensible case is to have both chained planes write enabled */
new_value = ( value & 4 ? 0xff : 0) | (value & 8 ? 0xff00: 0);
if( EGA_CPU.fun_or_protection )
new_value = do_logicals( new_value, get_latch23);
fill_both_bytes( new_value, (USHORT *)&EGA_plane23[low_offset], count >> 1 );
break;
} /* end of switch on plane23 enabled */
update_alg.mark_fill( offset, offset + count - 1 );
}
VOID
ega_mode2_chn_w_fill IFN3(ULONG, value, ULONG, offset, ULONG, count )
{
ULONG low_offset; /* distance into regen buffer of write start and end */
ULONG high_offset; /* distance into regen buffer of write start and end */
ULONG value1;
note_entrance0("ega_mode2_chn_w_fill");
/*
* Complicated by possibility that only one of a chained pair of
* planes is write enabled, needing alternate bytes to be written.
*/
/* starting on odd address makes it difficult, go to next one */
if(( (ULONG) offset & 1 ) && count )
{
ega_mode2_chn_b_write( value, offset++);
count--;
if( count )
{
ega_mode2_chn_b_write( value >> 8, offset + count - 1 );
count--;
}
value = ( value << 8 ) | ( value >> 8 );
}
low_offset = (offset >> 1) << 2; /* start of write */
high_offset = ((offset + count - 1) >> 1) << 2; /* end of write */
switch( getVideoplane_enable() & 3 )
{
case 1: /* just plane 0, ie even addresses to be written */
value1 = value & 1 ? 0xff : 0;
if( EGA_CPU.fun_or_protection )
value1 = do_logicals( value1, get_latch0 );
fill_alternate_bytes( &EGA_plane01[low_offset],
&EGA_plane01[high_offset], value1 );
break;
case 2: /* just plane 1, ie odd addresses to be written */
value1 = ( value >> 8 ) & 2 ? 0xff : 0;
if( EGA_CPU.fun_or_protection )
value1 = do_logicals( value1, get_latch1 );
fill_alternate_bytes( &EGA_plane01[low_offset + 1],
&EGA_plane01[high_offset], value1 );
break;
case 3: /* sensible case is to have both chained planes write enabled */
/* get a word pattern for filling */
value1 = ( value & 1 ? 0xff : 0 ) | (( value >> 8 ) & 2 ? 0xff00: 0 );
if( EGA_CPU.fun_or_protection )
value1 = do_logicals( value1, get_latch01 );
fill_both_bytes( value1, (USHORT *)&EGA_plane01[low_offset], count >> 1 );
break;
} /* end of switch on plane01 enabled */
switch( getVideoplane_enable() & 0xc ) /* isolate 2 bits for planes 2 and 3 */
{
case 4: /* just plane 2, ie even addresses to be written */
value1 = value & 4 ? 0xff : 0;
if( EGA_CPU.fun_or_protection )
value1 = do_logicals( value1, get_latch2 );
fill_alternate_bytes( &EGA_plane23[low_offset],
&EGA_plane23[high_offset], value1 );
break;
case 8: /* just plane 3, ie odd addresses to be written */
value1 = ( value >> 8 ) & 8 ? 0xff : 0;
if( EGA_CPU.fun_or_protection )
value1 = do_logicals( value1, get_latch3 );
fill_alternate_bytes( &EGA_plane23[low_offset + 1],
&EGA_plane23[high_offset], value1 );
break;
case 12: /* sensible case is to have both chained planes write enabled */
/* get a word pattern for filling */
value1 = ( value & 4 ? 0xff : 0 ) | (( value >> 8 ) & 8 ? 0xff00: 0 );
if( EGA_CPU.fun_or_protection )
value1 = do_logicals( value1, get_latch23);
fill_both_bytes( value1, (USHORT *)&EGA_plane23[low_offset], count >> 1 );
break;
} /* end of switch on plane23 enabled */
/* the 3rd parameter is needed by GORE. */
update_alg.mark_wfill( offset, offset + count - 1, 0 );
}
LOCAL VOID
ega_mode2_chn_move_guts IFN8(UTINY *, eas, UTINY *, ead, LONG, count,
UTINY *, EGA_plane, ULONG, scratch, ULONG, plane, ULONG, w,
ULONG, src_flag )
{
ULONG src, dst;
UTINY *source;
USHORT value;
ULONG lsb;
src = (ULONG) eas;
dst = (ULONG) ead;
/*
* even planes cannot start with odd addresses
* odd planes cannot start with even addresses
*/
if(( dst & 1 ) != ( plane & 1 ))
{
#ifdef BACK_M
src--;
scratch--;
#else
src++;
scratch++;
#endif
dst++;
count--;
}
lsb = dst & 1;
dst = (dst >> 1) << 2;
dst |= lsb;
if( src_flag )
{
lsb = src & 1;
src = (src >> 1) << 2;
src |= lsb;
if( plane & 1 )
{
/*
* This causes latches to be read from 2 bytes above the word
* that was read if it was on an odd address, ie it only applies
* to planes 1 and 3 in chained mode word operations.
*/
source = w ? &EGA_plane[src] + 2 : &EGA_plane[src];
}
else
{
source = &EGA_plane[src];
}
src = scratch;
}
if( EGA_CPU.fun_or_protection )
{
while( count > 0 )
{
count -= 2;
value = *(UTINY *) src & (1 << plane) ? 0xff : 0;
#ifdef BACK_M
src -= 2;
#else
src += 2;
#endif
if( src_flag )
{
put_latch( plane, *source );
source += 4;
}
EGA_plane[dst] = do_logicals( value, get_latch(plane) );
dst += 4;
}
}
else
{
while( count > 0 )
{
count -= 2;
EGA_plane[dst] = *(UTINY *) src & (1 << plane) ? 0xff : 0;
#ifdef BACK_M
src -= 2;
#else
src += 2;
#endif
dst += 4;
}
}
}
/*
* Used by ega_mode2_chn_b_move with w == 0 and by
* ega_mode2_gen_w_move with w == 1
*/
VOID
ega_mode2_chn_move IFN5(UTINY, w, UTINY *, ead, UTINY *, eas, ULONG, count,
ULONG, src_flag )
{
UTINY *scr;
IMPORT VOID (*string_read_ptr)();
count <<= w;
if( src_flag )
{
/*
* Source is in EGA, latches will change with each byte moved. We
* restore CPU's view of source in regen, and use it to update planes
* with the aid of the SAS scratch area.
*/
#ifdef BACK_M
scr = getVideoscratch() + 0x10000 - 1;
#else
scr = getVideoscratch();
#endif
if( getDF() )
{
eas = eas - count + 1 + w;
ead = ead - count + 1 + w;
}
(*string_read_ptr)( scr, eas, count );
}
else
{
if( getDF() )
{
#ifdef BACK_M
eas = eas + count - 1 - w;
#else
eas = eas - count + 1 + w;
#endif
ead = ead - count + 1 + w;
}
}
if( getVideoplane_enable() & 1 ) /* plane 0, even addresses, enabled */
ega_mode2_chn_move_guts( eas, ead, count, EGA_plane01, (ULONG) scr, 0, w, src_flag );
if( getVideoplane_enable() & 2 ) /* plane 1, odd addresses, enabled */
ega_mode2_chn_move_guts( eas, ead, count, EGA_plane01, (ULONG) scr, 1, w, src_flag );
if( getVideoplane_enable() & 4 ) /* plane 2, even addresses, enabled */
ega_mode2_chn_move_guts( eas, ead, count, EGA_plane23, (ULONG) scr, 2, w, src_flag );
if( getVideoplane_enable() & 8 ) /* plane 3, odd addresses, enabled */
ega_mode2_chn_move_guts( eas, ead, count, EGA_plane23, (ULONG) scr, 3, w, src_flag );
update_alg.mark_string( (int) ead, (int) ead + count - 1 );
}
VOID
ega_mode2_chn_b_move IFN4(ULONG, ead, ULONG, eas, ULONG, count,
ULONG, src_flag)
{
note_entrance0("ega_mode2_chn_b_move");
/* general function, 0 means byte write */
ega_mode2_chn_move(0, (UTINY *) ead, (UTINY *) eas, count, src_flag);
}
VOID
ega_mode2_chn_w_move IFN4(ULONG, ead, ULONG, eas, ULONG, count,
ULONG, src_flag)
{
note_entrance0("ega_mode2_chn_w_move");
/* general function, 1 means word write */
ega_mode2_chn_move(1, (UTINY *)ead, (UTINY *)eas, count, src_flag);
}
#endif
#endif /* !NTVDM | (NTVDM & !X86GFX) */