You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
698 lines
21 KiB
C
698 lines
21 KiB
C
/* PDCurses */
|
|
|
|
#include "pdcdos.h"
|
|
|
|
#ifdef PDC_WIDE
|
|
#define USE_UNICODE_ACS_CHARS 1
|
|
#else
|
|
#define USE_UNICODE_ACS_CHARS 0
|
|
#endif
|
|
|
|
#include "../common/acs_defs.h"
|
|
|
|
#ifdef __DJGPP__
|
|
#include <go32.h>
|
|
#include <sys/farptr.h>
|
|
#endif
|
|
|
|
#ifdef __WATCOMC__
|
|
/* For Watcom, we need conio.h, but the Curses macro for getch fouls it up */
|
|
#undef getch
|
|
#include <conio.h>
|
|
#define outportb(a, b) outp((a), (b))
|
|
#endif
|
|
|
|
#ifdef __DMC__
|
|
#define outportb(a, b) outp((a), (b))
|
|
#endif
|
|
|
|
/* Maximum run of characters per call to _transform_line_[48] */
|
|
#ifdef PDC_FLAT
|
|
# define MAX_PACKET 512 /* optimize for speed */
|
|
#else
|
|
# define MAX_PACKET 32 /* keep stack usage reasonable */
|
|
#endif
|
|
|
|
static unsigned long _get_colors(chtype glyph);
|
|
static unsigned long _address_4(int row, int col);
|
|
static unsigned long _address_8(int row, int col);
|
|
static void _video_read(void *data, unsigned long addr, size_t size);
|
|
static void _video_write(unsigned long addr, const void *data, size_t size);
|
|
static unsigned _set_window(unsigned window, unsigned long addr);
|
|
|
|
/* position hardware cursor at (y, x) */
|
|
|
|
void PDC_gotoyx(int row, int col)
|
|
{
|
|
if (PDC_state.cursor_visible)
|
|
PDC_private_cursor_off();
|
|
PDC_private_cursor_on(row, col);
|
|
}
|
|
|
|
/* Draw a run of characters with the same colors */
|
|
/* Used with 4 bit pixels only */
|
|
|
|
static void _new_packet(unsigned long colors, int lineno, int x, int len, const chtype *srcp)
|
|
{
|
|
struct
|
|
{
|
|
const unsigned char *font_addr;
|
|
} glyphs[MAX_PACKET];
|
|
int i;
|
|
|
|
/* Colors */
|
|
unsigned fore = colors & 0xF;
|
|
unsigned back = (colors >> 16) & 0xF;
|
|
|
|
/* Width of a character in bytes */
|
|
unsigned ch_width = (PDC_state.font_width + 7) / 8;
|
|
|
|
/* Bit to set for A_RIGHT */
|
|
unsigned char r_mask = 0x80 >> ((PDC_state.font_width - 1) % 8);
|
|
|
|
/* Bytes to write in a single pass */
|
|
unsigned char bytes[1024];
|
|
|
|
/* Which plane we're writing */
|
|
unsigned plane;
|
|
|
|
/* Compute these just once */
|
|
for (i = 0; i < len; ++i)
|
|
{
|
|
const chtype glyph = srcp[i];
|
|
unsigned ch = glyph & A_CHARTEXT;
|
|
|
|
if( _is_altcharset( glyph))
|
|
ch = acs_map[ch];
|
|
glyphs[i].font_addr = PDC_state.font_glyph_data(FALSE, ch);
|
|
}
|
|
|
|
if (PDC_state.font_width % 8 == 0)
|
|
{
|
|
/* Faster algorithm for use when we're always writing whole bytes */
|
|
|
|
/* Write data twice: once direct, once inverted */
|
|
for (plane = 0; plane < 2; ++plane)
|
|
{
|
|
unsigned xpix = x * PDC_state.font_width;
|
|
unsigned long addr = _address_4(lineno, xpix / 8);
|
|
unsigned plane_bit;
|
|
unsigned char invert;
|
|
unsigned line;
|
|
|
|
if (plane == 0)
|
|
{
|
|
plane_bit = fore & ~back & 0xF;
|
|
invert = 0x00;
|
|
}
|
|
else
|
|
{
|
|
plane_bit = ~fore & back & 0xF;
|
|
invert = 0xFF;
|
|
}
|
|
if (plane_bit == 0)
|
|
continue;
|
|
|
|
/* Select the planes */
|
|
outportb(0x3c4, 2);
|
|
outportb(0x3c5, plane_bit);
|
|
|
|
/* Loop once per raster line */
|
|
for (line = 0; line < PDC_state.font_height; ++line)
|
|
{
|
|
unsigned long cp;
|
|
unsigned num_bytes = 0;
|
|
int col;
|
|
|
|
/* Loop once per column */
|
|
cp = addr;
|
|
for (col = 0; col < len; ++col)
|
|
{
|
|
chtype glyph = srcp[col];
|
|
const unsigned char *font_data;
|
|
unsigned ch_byte;
|
|
|
|
font_data = glyphs[col].font_addr;
|
|
|
|
/* Loop once per byte within the font */
|
|
for (ch_byte = 0; ch_byte < ch_width; ++ch_byte)
|
|
{
|
|
unsigned index = line * ch_width + ch_byte;
|
|
unsigned char byte = font_data[index];
|
|
if ((glyph & A_UNDERLINE) && line == PDC_state.underline)
|
|
byte |= 0xFF;
|
|
if ((glyph & A_LEFT) != 0 && ch_byte == 0)
|
|
byte |= 0x80;
|
|
if ((glyph & A_RIGHT) != 0 && ch_byte + 1 == ch_width)
|
|
byte |= r_mask;
|
|
bytes[num_bytes++] = byte ^ invert;
|
|
if (num_bytes >= sizeof(bytes))
|
|
{
|
|
/* Flush the bytes array to the frame buffer */
|
|
_video_write(cp, bytes, num_bytes);
|
|
cp += num_bytes;
|
|
num_bytes = 0;
|
|
}
|
|
}
|
|
}
|
|
/* Write any remaining bytes */
|
|
_video_write(cp, bytes, num_bytes);
|
|
|
|
addr += PDC_state.bytes_per_line;
|
|
}
|
|
}
|
|
|
|
/* Write fill bytes: once all zeros, once all ones */
|
|
for (plane = 0; plane < 2; ++plane)
|
|
{
|
|
unsigned xpix = x * PDC_state.font_width;
|
|
unsigned long addr = _address_4(lineno, xpix / 8);
|
|
unsigned plane_bit;
|
|
unsigned char fill;
|
|
unsigned width;
|
|
unsigned line;
|
|
|
|
if (plane == 0)
|
|
{
|
|
plane_bit = ~fore & ~back & 0xF;
|
|
fill = 0x00;
|
|
}
|
|
else
|
|
{
|
|
plane_bit = fore & back & 0xF;
|
|
fill = 0xFF;
|
|
}
|
|
if (plane_bit == 0)
|
|
continue;
|
|
|
|
/* Select the planes */
|
|
outportb(0x3c4, 2);
|
|
outportb(0x3c5, plane_bit);
|
|
|
|
/* Fill with bytes to be written */
|
|
width = ch_width * len;
|
|
memset(bytes, fill, (width < sizeof(bytes)) ? width : sizeof(bytes));
|
|
|
|
/* Loop once per raster line */
|
|
for (line = 0; line < PDC_state.font_height; ++line)
|
|
{
|
|
unsigned count = width;
|
|
unsigned long cp = addr;
|
|
/* Fill */
|
|
while (count > sizeof(bytes))
|
|
{
|
|
_video_write(cp, bytes, sizeof(bytes));
|
|
cp += sizeof(bytes);
|
|
count -= sizeof(bytes);
|
|
}
|
|
_video_write(cp, bytes, count);
|
|
addr += PDC_state.bytes_per_line;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Loop once per plane */
|
|
for (plane = 0; plane < 4; ++plane)
|
|
{
|
|
unsigned xpix = x * PDC_state.font_width;
|
|
unsigned long addr = _address_4(lineno, xpix / 8);
|
|
unsigned plane_bit = 1 << plane;
|
|
unsigned cbits;
|
|
unsigned line;
|
|
|
|
/* Select the plane */
|
|
outportb(0x3c4, 2);
|
|
outportb(0x3c5, plane_bit);
|
|
outportb(0x3ce, 4);
|
|
outportb(0x3cf, plane);
|
|
|
|
/* Select the mask for the current plane */
|
|
cbits = ((fore & plane_bit) ? 1 : 0)
|
|
| ((back & plane_bit) ? 2 : 0);
|
|
|
|
/* Loop once per raster line */
|
|
for (line = 0; line < PDC_state.font_height; ++line)
|
|
{
|
|
unsigned shift = xpix % 8;
|
|
unsigned long cp;
|
|
unsigned num_bytes = 0;
|
|
int col;
|
|
unsigned ch_byte;
|
|
|
|
if (shift != 0)
|
|
{
|
|
/* We need the existing data from the frame buffer */
|
|
_video_read(bytes, addr, 1);
|
|
bytes[0] &= 0xFF00 >> shift;
|
|
}
|
|
else
|
|
{
|
|
bytes[0] = 0;
|
|
}
|
|
|
|
col = 0;
|
|
ch_byte = 0;
|
|
cp = addr;
|
|
while (col < len)
|
|
{
|
|
/* Render one byte from the current character */
|
|
chtype glyph = srcp[col];
|
|
const unsigned char *font_data = glyphs[col].font_addr;
|
|
unsigned char byte;
|
|
unsigned num_bits;
|
|
|
|
/* Get one byte of pixel data for the current plane */
|
|
if (cbits == 1 || cbits == 2)
|
|
{
|
|
unsigned index = line * ch_width + ch_byte;
|
|
byte = font_data[index];
|
|
if ((glyph & A_UNDERLINE) && line == PDC_state.underline)
|
|
byte |= 0xFF;
|
|
if ((glyph & A_LEFT) != 0 && ch_byte == 0)
|
|
byte |= 0x80;
|
|
if ((glyph & A_RIGHT) != 0 && ch_byte + 1 == ch_width)
|
|
byte |= r_mask;
|
|
}
|
|
else
|
|
{
|
|
byte = 0x00;
|
|
}
|
|
if (cbits & 2)
|
|
byte ^= 0xFF;
|
|
|
|
/* Get the number of bits to render in this pass */
|
|
if (ch_byte + 1 < ch_width)
|
|
num_bits = 8;
|
|
else
|
|
{
|
|
num_bits = PDC_state.font_width - ch_byte * 8;
|
|
byte &= 0xFF00 >> num_bits;
|
|
}
|
|
|
|
/* Add the bits to the bytes array */
|
|
bytes[num_bytes] |= byte >> shift;
|
|
byte <<= 8 - shift;
|
|
shift += num_bits;
|
|
if (shift >= 8)
|
|
{
|
|
++num_bytes;
|
|
shift -= 8;
|
|
if (num_bytes >= sizeof(bytes))
|
|
{
|
|
/* Flush the bytes array to the frame buffer */
|
|
_video_write(cp, bytes, num_bytes);
|
|
cp += num_bytes;
|
|
num_bytes = 0;
|
|
}
|
|
bytes[num_bytes] = byte;
|
|
}
|
|
|
|
/* Advance to the next byte of the character */
|
|
++ch_byte;
|
|
if (ch_byte >= ch_width)
|
|
{
|
|
ch_byte = 0;
|
|
++col;
|
|
}
|
|
}
|
|
if (num_bytes != 0)
|
|
{
|
|
/* There are bytes remaining in the bytes array */
|
|
_video_write(cp, bytes, num_bytes);
|
|
cp += num_bytes;
|
|
bytes[0] = bytes[num_bytes];
|
|
}
|
|
if (shift != 0)
|
|
{
|
|
/* There are bits remaining in the bytes array */
|
|
unsigned char b;
|
|
_video_read(&b, cp, 1);
|
|
bytes[0] |= b & (0xFF >> shift);
|
|
_video_write(cp, bytes, 1);
|
|
}
|
|
|
|
addr += PDC_state.bytes_per_line;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* PDC_transform_line for 4 bit pixels */
|
|
|
|
static void _transform_line_4(int lineno, int x, int len, const chtype *srcp)
|
|
{
|
|
unsigned long old_colors, colors;
|
|
int i, j;
|
|
|
|
/* Draw runs of characters that have the same colors */
|
|
old_colors = _get_colors(srcp[0]);
|
|
|
|
for (i = 1, j = 1; j < len; i++, j++)
|
|
{
|
|
colors = _get_colors(srcp[i]);
|
|
|
|
if (colors != old_colors || i >= MAX_PACKET)
|
|
{
|
|
_new_packet(old_colors, lineno, x, i, srcp);
|
|
old_colors = colors;
|
|
srcp += i;
|
|
x += i;
|
|
i = 0;
|
|
}
|
|
}
|
|
|
|
_new_packet(old_colors, lineno, x, i, srcp);
|
|
|
|
/* Reset the VGA plane register to its normal state */
|
|
outportb(0x3c4, 2);
|
|
outportb(0x3c5, 0xF);
|
|
}
|
|
|
|
/* PDC_transform_line for 8, 15, 16, 24 and 32 bit pixels */
|
|
|
|
static void _transform_line_8(int lineno, int x, int len, const chtype *srcp)
|
|
{
|
|
unsigned char bytes[1024];
|
|
unsigned long addr = _address_8(lineno, x);
|
|
unsigned bytes_per_pixel = (PDC_state.bits_per_pixel + 7) / 8;
|
|
|
|
struct
|
|
{
|
|
const unsigned char *font_addr;
|
|
unsigned char ul_mask;
|
|
unsigned long fore;
|
|
unsigned long back;
|
|
} glyphs[MAX_PACKET];
|
|
|
|
/* Width of a character in bytes */
|
|
unsigned ch_width = (PDC_state.font_width + 7) / 8;
|
|
|
|
/* Bit to set for A_RIGHT */
|
|
unsigned char r_mask = 0x80 >> ((PDC_state.font_width - 1) % 8);
|
|
|
|
int col;
|
|
unsigned line;
|
|
|
|
/* Compute basic glyph data only once per character */
|
|
for (col = 0; col < len; col++)
|
|
{
|
|
chtype glyph = srcp[col];
|
|
unsigned ch;
|
|
unsigned long colors, fore, back;
|
|
|
|
/* Get the index into the font */
|
|
ch = glyph & A_CHARTEXT;
|
|
if( _is_altcharset( glyph))
|
|
ch = acs_map[ch & 0x7f];
|
|
|
|
/* Get the address of the font data */
|
|
glyphs[col].font_addr = PDC_state.font_glyph_data(FALSE, ch);
|
|
|
|
/* Bit mask for underline */
|
|
glyphs[col].ul_mask = (glyph & A_UNDERLINE) ? 0xFF : 0x00;
|
|
|
|
/* Get the colors */
|
|
colors = _get_colors(glyph);
|
|
fore = colors & 0xFFFF;
|
|
back = (colors >> 16) & 0xFFFF;
|
|
if (PDC_state.bits_per_pixel > 8)
|
|
{
|
|
fore = PDC_state.colors[fore].mapped;
|
|
back = PDC_state.colors[back].mapped;
|
|
}
|
|
/*
|
|
* If this is ever run on big endian hardware, we'll need to shift
|
|
* fore and back left as follows:
|
|
* fore <<= 32 - (bytes_per_pixel * 8);
|
|
* back <<= 32 - (bytes_per_pixel * 8);
|
|
*/
|
|
glyphs[col].fore = fore;
|
|
glyphs[col].back = back;
|
|
}
|
|
|
|
/* Loop by raster line */
|
|
for (line = 0; line < PDC_state.font_height; line++)
|
|
{
|
|
unsigned long cp = addr;
|
|
unsigned bindex;
|
|
|
|
/* Loop by column */
|
|
bindex = 0;
|
|
for (col = 0; col < len; col++)
|
|
{
|
|
/* Get glyph data */
|
|
chtype glyph = srcp[col];
|
|
const unsigned char *font_addr = glyphs[col].font_addr;
|
|
unsigned index = line * ch_width;
|
|
unsigned long fore = glyphs[col].fore;
|
|
unsigned long back = glyphs[col].back;
|
|
unsigned ch_byte;
|
|
unsigned byte;
|
|
|
|
/* Loop by byte within the font */
|
|
for (ch_byte = 0; ch_byte < ch_width; ++ch_byte)
|
|
{
|
|
unsigned bit, num_bits;
|
|
|
|
/* Get one byte of the font data */
|
|
byte = font_addr[index + ch_byte];
|
|
if ((glyph & A_LEFT) != 0 && ch_byte == 0)
|
|
byte |= 0x80;
|
|
if ((glyph & A_RIGHT) != 0 && ch_byte + 1 == ch_width)
|
|
byte |= r_mask;
|
|
if (line == PDC_state.underline)
|
|
byte |= glyphs[col].ul_mask;
|
|
if (PDC_state.cursor_visible
|
|
&& lineno == PDC_state.cursor_row
|
|
&& col + x == PDC_state.cursor_col
|
|
&& PDC_state.cursor_start <= line && line <= PDC_state.cursor_end)
|
|
byte ^= 0xFF;
|
|
|
|
/* Number of pixels to render on this pass */
|
|
if (ch_byte + 1 == ch_width)
|
|
num_bits = PDC_state.font_width - ch_byte * 8;
|
|
else
|
|
num_bits = 8;
|
|
|
|
/* Render one byte's worth of pixels of the glyph */
|
|
for (bit = 0; bit < num_bits; ++bit)
|
|
{
|
|
unsigned long color = (byte & (0x80 >> bit)) ? fore : back;
|
|
*(unsigned long *)(bytes + bindex) = color;
|
|
bindex += bytes_per_pixel;
|
|
if (bindex + sizeof(unsigned long) > sizeof(bytes))
|
|
{
|
|
/* Flush bytes to the frame buffer */
|
|
_video_write(cp, bytes, bindex);
|
|
cp += bindex;
|
|
bindex = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_video_write(cp, bytes, bindex);
|
|
addr += PDC_state.bytes_per_line;
|
|
}
|
|
}
|
|
|
|
/* update the given physical line to look like the corresponding line in
|
|
curscr */
|
|
|
|
void PDC_transform_line(int lineno, int x, int len, const chtype *srcp)
|
|
{
|
|
PDC_LOG(("PDC_transform_line() - called: lineno=%d\n", lineno));
|
|
|
|
if (PDC_state.bits_per_pixel == 4)
|
|
{
|
|
_transform_line_4(lineno, x, len, srcp);
|
|
}
|
|
else
|
|
{
|
|
while (len > MAX_PACKET)
|
|
{
|
|
_transform_line_8(lineno, x, MAX_PACKET, srcp);
|
|
x += MAX_PACKET;
|
|
len -= MAX_PACKET;
|
|
srcp += MAX_PACKET;
|
|
}
|
|
_transform_line_8(lineno, x, len, srcp);
|
|
}
|
|
}
|
|
|
|
void PDC_doupdate(void)
|
|
{
|
|
}
|
|
|
|
static unsigned long _get_colors(chtype glyph)
|
|
{
|
|
attr_t attr;
|
|
short fore, back;
|
|
|
|
/* Get the foreground and background colors */
|
|
attr = glyph & (A_ATTRIBUTES ^ A_ALTCHARSET);
|
|
pair_content(PAIR_NUMBER(attr), &fore, &back);
|
|
|
|
if ((attr & A_BOLD) != 0 && fore < 16)
|
|
fore |= 8;
|
|
if ((attr & A_BLINK) != 0 && back < 16)
|
|
back |= 8;
|
|
|
|
if (attr & A_REVERSE)
|
|
{
|
|
short swap = fore;
|
|
fore = back;
|
|
back = swap;
|
|
}
|
|
|
|
/* Return them as a pair */
|
|
return ((unsigned long)back << 16) | fore;
|
|
}
|
|
|
|
void PDC_private_cursor_off(void)
|
|
{
|
|
/* This gets called before atrtab is set up; avoid a null dereference */
|
|
if (!SP || !SP->pairs)
|
|
return;
|
|
|
|
PDC_state.cursor_visible = FALSE;
|
|
if (PDC_state.cursor_row < (unsigned)LINES
|
|
&& PDC_state.cursor_col < (unsigned)COLS)
|
|
{
|
|
static const chtype space = ' ';
|
|
|
|
PDC_transform_line(PDC_state.cursor_row, PDC_state.cursor_col, 1,
|
|
(curscr && curscr->_y)
|
|
? &curscr->_y[PDC_state.cursor_row][PDC_state.cursor_col]
|
|
: &space);
|
|
}
|
|
}
|
|
|
|
void PDC_private_cursor_on(int row, int col)
|
|
{
|
|
PDC_state.cursor_visible = TRUE;
|
|
PDC_state.cursor_row = row;
|
|
PDC_state.cursor_col = col;
|
|
if (row < (unsigned)LINES && col < (unsigned)COLS)
|
|
{
|
|
static const chtype space = ' ';
|
|
|
|
PDC_transform_line(PDC_state.cursor_row, PDC_state.cursor_col, 1,
|
|
(curscr && curscr->_y)
|
|
? &curscr->_y[PDC_state.cursor_row][PDC_state.cursor_col]
|
|
: &space);
|
|
}
|
|
}
|
|
|
|
static unsigned long _address_4(int row, int col)
|
|
{
|
|
return (unsigned long)row * PDC_state.bytes_per_line * PDC_state.font_height + col;
|
|
}
|
|
|
|
static unsigned long _address_8(int row, int col)
|
|
{
|
|
return (unsigned long)row * PDC_state.bytes_per_line * PDC_state.font_height
|
|
+ col * PDC_state.font_width * ((PDC_state.bits_per_pixel + 7)/8);
|
|
}
|
|
|
|
static void _video_read(void *data, unsigned long addr, size_t size)
|
|
{
|
|
#ifdef PDC_FLAT
|
|
if (PDC_state.linear_sel)
|
|
{
|
|
#ifdef __DJGPP__
|
|
movedata(PDC_state.linear_sel, addr,
|
|
_go32_my_ds(), (unsigned)data, size);
|
|
#else /* Watcom */
|
|
_fmemcpy(data, MK_FP(PDC_state.linear_sel, addr), size);
|
|
#endif
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
unsigned window = PDC_state.window[PDC_state.read_win];
|
|
|
|
while (size != 0)
|
|
{
|
|
unsigned offset = _set_window(PDC_state.read_win, addr);
|
|
unsigned long size2 = PDC_state.window_size - offset;
|
|
if (size2 > size)
|
|
size2 = size;
|
|
#ifdef __DJGPP__
|
|
dosmemget(window * 16L + offset, size2, data);
|
|
#elif defined(__WATCOMC__) && defined(__386__)
|
|
_fmemcpy(data, (void PDC_FAR *)(window * 16L + offset), size2);
|
|
#else
|
|
if (size2 >= 65532)
|
|
size2 = 65532;
|
|
|
|
_fmemcpy(data, MK_FP(window, offset), size2);
|
|
#endif
|
|
addr += size2;
|
|
data = (char *)data + size2;
|
|
size -= size2;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void _video_write(unsigned long addr, const void *data, size_t size)
|
|
{
|
|
#ifdef PDC_FLAT
|
|
if (PDC_state.linear_sel)
|
|
{
|
|
#ifdef __DJGPP__
|
|
movedata(_go32_my_ds(), (unsigned)data,
|
|
PDC_state.linear_sel, addr, size);
|
|
#else /* Watcom */
|
|
_fmemcpy(MK_FP(PDC_state.linear_sel, addr), data, size);
|
|
#endif
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
unsigned window = PDC_state.window[PDC_state.write_win];
|
|
|
|
while (size != 0)
|
|
{
|
|
unsigned offset = _set_window(PDC_state.write_win, addr);
|
|
unsigned long size2 = PDC_state.window_size - offset;
|
|
if (size2 > size)
|
|
size2 = size;
|
|
#ifdef __DJGPP__
|
|
dosmemput(data, size2, window * 16L + offset);
|
|
#elif defined(__WATCOMC__) && defined(__386__)
|
|
_fmemcpy((void PDC_FAR *)(window * 16L + offset), data, size2);
|
|
#else
|
|
if (size2 >= 65532)
|
|
size2 = 65532;
|
|
|
|
_fmemcpy(MK_FP(window, offset), data, size2);
|
|
#endif
|
|
addr += size2;
|
|
data = (const char *)data + size2;
|
|
size -= size2;
|
|
}
|
|
}
|
|
}
|
|
|
|
static unsigned _set_window(unsigned window, unsigned long addr)
|
|
{
|
|
unsigned long offset = PDC_state.offset[window];
|
|
if (addr < offset || offset + PDC_state.window_size <= addr)
|
|
{
|
|
/* Need to move the window */
|
|
PDCREGS regs;
|
|
unsigned long gran = PDC_state.window_gran * 1024L;
|
|
|
|
memset(®s, 0, sizeof(regs));
|
|
regs.W.ax = 0x4F05;
|
|
regs.W.bx = window;
|
|
regs.W.dx = addr / gran;
|
|
offset = regs.W.dx * gran;
|
|
PDCINT(0x10, regs);
|
|
PDC_state.offset[window] = offset;
|
|
}
|
|
|
|
return addr - offset;
|
|
}
|