2059 lines
50 KiB
C
Executable File
2059 lines
50 KiB
C
Executable File
/*
|
|
* xep80.c - XEP80 emulation
|
|
*
|
|
* Copyright (C) 2007 Mark Grebe
|
|
*
|
|
* This file is part of the Atari800 emulator project which emulates
|
|
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
|
|
*
|
|
* Atari800 is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Atari800 is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Atari800; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "config.h"
|
|
#ifdef XEP80_EMULATION
|
|
#include "xep80.h"
|
|
#include "xep80_fonts.h"
|
|
#include "statesav.h"
|
|
#include "atari.h"
|
|
#include "antic.h"
|
|
#include <string.h>
|
|
#include "platform.h"
|
|
#include "util.h"
|
|
#include "log.h"
|
|
|
|
#define IN_QUEUE_SIZE 10
|
|
|
|
/* Definitions for command protocol between the XEP and the Atari */
|
|
#define CMD_XX_MASK 0xC0
|
|
#define CMD_00 0x00
|
|
#define CMD_X_CUR_LOW 0x00
|
|
#define CMD_01 0x40
|
|
#define CMD_01_MASK 0x70
|
|
#define CMD_X_CUR_UPPER 0x40
|
|
#define CMD_X_CUR_HIGH 0x50
|
|
#define CMD_LEFT_MAR_L 0x60
|
|
#define CMD_LEFT_MAR_H 0x70
|
|
#define CMD_10 0x80
|
|
#define CMD_10_MASK 0xF0
|
|
#define CMD_Y_CUR_LOW 0x80
|
|
#define CMD_1001 0x90
|
|
#define CMD_1001_MASK 0xF8
|
|
#define CMD_Y_CUR_HIGH 0x90
|
|
#define CMD_Y_CUR_STATUS 0x98
|
|
#define CMD_GRAPH_50HZ 0x99
|
|
#define CMD_GRAPH_60HZ 0x9A
|
|
#define CMD_RIGHT_MAR_L 0xA0
|
|
#define CMD_RIGHT_MAR_H 0xB0
|
|
#define CMD_11 0xC0
|
|
#define CMD_GET_CHAR 0xC0
|
|
#define CMD_REQ_X_CUR 0xC1
|
|
#define CMD_MRST 0xC2
|
|
#define CMD_PRT_STAT 0xC3
|
|
#define CMD_FILL_PREV 0xC4
|
|
#define CMD_FILL_SPACE 0xC5
|
|
#define CMD_FILL_EOL 0xC6
|
|
#define CMD_CLR_LIST 0xD0
|
|
#define CMD_SET_LIST 0xD1
|
|
#define CMD_SCR_NORMAL 0xD2
|
|
#define CMD_SCR_BURST 0xD3
|
|
#define CMD_CHAR_SET_A 0xD4
|
|
#define CMD_CHAR_SET_B 0xD5
|
|
#define CMD_CHAR_SET_INT 0xD6
|
|
#define CMD_TEXT_50HZ 0xD7
|
|
#define CMD_CUR_OFF 0xD8
|
|
#define CMD_CUR_ON 0xD9
|
|
#define CMD_CUR_BLINK 0xDA
|
|
#define CMD_CUR_ST_LINE 0xDB
|
|
#define CMD_SET_SCRL_WIN 0xDC
|
|
#define CMD_SET_PRINT 0xDD
|
|
#define CMD_WHT_ON_BLK 0xDE
|
|
#define CMD_BLK_ON_WHT 0xDF
|
|
#define CMD_VIDEO_CTRL 0xED
|
|
#define CMD_ATTRIB_A 0xF4
|
|
#define CMD_ATTRIB_B 0xF5
|
|
|
|
#define CHAR_SET_A 0
|
|
#define CHAR_SET_B 1
|
|
#define CHAR_SET_INTERNAL 2
|
|
|
|
/* These center the graphics screen inside of the XEP80 screen */
|
|
#define XEP80_GRAPH_X_OFFSET ((XEP80_SCRN_WIDTH - XEP80_GRAPH_WIDTH) / 2)
|
|
#define XEP80_GRAPH_Y_OFFSET ((XEP80_SCRN_HEIGHT - XEP80_GRAPH_HEIGHT) / 2)
|
|
|
|
/* Used to determine if a charcter is double width */
|
|
#define IS_DOUBLE(x,y) (((xep80_data[y][x] & 0x80) && font_b_double) || \
|
|
(((xep80_data[y][x] & 0x80) == 0) && font_a_double))
|
|
|
|
/* Global variables */
|
|
int XEP80_enabled = FALSE;
|
|
int XEP80_port = 0;
|
|
int XEP80_first_row = XEP80_SCRN_HEIGHT - 1;
|
|
int XEP80_last_row = 0;
|
|
|
|
/* Local procedures */
|
|
static void XEP80_InputWord(int word);
|
|
static void XEP80_OutputWord(int word);
|
|
static void XEP80_ReceiveChar(UBYTE byte);
|
|
static void XEP80_SendCursorStatus(void);
|
|
static void XEP80_SetXCur(UBYTE cursor);
|
|
static void XEP80_SetXCurHigh(UBYTE cursor);
|
|
static void XEP80_SetLeftMarginLow(UBYTE margin);
|
|
static void XEP80_SetLeftMarginHigh(UBYTE margin);
|
|
static void XEP80_SetYCur(UBYTE cursor);
|
|
static void XEP80_SetScreenMode(int graphics, int pal);
|
|
static void XEP80_SetRightMarginLow(UBYTE margin);
|
|
static void XEP80_SetRightMarginHigh(UBYTE margin);
|
|
static void XEP80_GetChar(void);
|
|
static void XEP80_GetXCur(void);
|
|
static void XEP80_MasterReset(void);
|
|
static void XEP80_GetPrinterStatus(void);
|
|
static void XEP80_FillMem(UBYTE c, int output);
|
|
static void XEP80_SetList(int list);
|
|
static void XEP80_SetOutputDevice(int screen, int burst);
|
|
static void XEP80_SetCharSet(int set);
|
|
static void XEP80_SetCursor(int on, int blink);
|
|
static void XEP80_SetXCurStart(void);
|
|
static void XEP80_SetScrollWindow(void);
|
|
static void XEP80_SetInverse(int inverse);
|
|
static void XEP80_SetVideoCtrl(UBYTE video_ctrl);
|
|
static void XEP80_SetAttributeA(UBYTE attrib);
|
|
static void XEP80_SetAttributeB(UBYTE attrib);
|
|
static void XEP80_UpdateCursor(void);
|
|
static void XEP80_AddCharAtCursor(UBYTE byte);
|
|
static void XEP80_AddGraphCharAtCursor(UBYTE byte);
|
|
static void XEP80_CursorUp(void);
|
|
static void XEP80_CursorDown(void);
|
|
static void XEP80_CursorLeft(void);
|
|
static void XEP80_CursorRight(void);
|
|
static void XEP80_ClearScreen(void);
|
|
static void XEP80_Backspace(void);
|
|
static void XEP80_AddEOL(void);
|
|
static void XEP80_DeleteChar(void);
|
|
static void XEP80_InsertChar(void);
|
|
static void XEP80_DeleteLogicalLine(void);
|
|
static void XEP80_InsertLine(void);
|
|
static void XEP80_GoToNextTab(void);
|
|
static void XEP80_ScrollUpLast(void);
|
|
static void XEP80_ScrollDown(int y);
|
|
static void XEP80_ScrollUp(int y_start, int y_end);
|
|
static void XEP80_FindEndLogicalLine(int *x, int *y);
|
|
static void XEP80_FindStartLogicalLine(int *x, int *y);
|
|
static void XEP80_BlitChar(int x, int y, int cur);
|
|
static void XEP80_BlitScreen(void);
|
|
static void XEP80_BlitRows(int y_start, int y_end);
|
|
static void XEP80_BlitGraphChar(int x, int y);
|
|
|
|
/* Local state variables */
|
|
static int output_state = -1;
|
|
static int output_word = 0;
|
|
|
|
static UWORD input_queue[IN_QUEUE_SIZE];
|
|
static int input_count = 0;
|
|
static int input_bit = 0;
|
|
static int input_first = TRUE;
|
|
|
|
static int xcur = 0;
|
|
static int xscroll = 0;
|
|
static int ycur = 0;
|
|
static int new_xcur = 0;
|
|
static int new_ycur = 0;
|
|
static int old_xcur = 0;
|
|
static int old_ycur = 0;
|
|
static int lmargin = 0;
|
|
static int rmargin = 0x4f;
|
|
static UBYTE attrib_a = 0;
|
|
static UBYTE attrib_b = 0;
|
|
static int list_mode = FALSE;
|
|
static int char_set = CHAR_SET_A;
|
|
static int cursor_on = TRUE;
|
|
static int cursor_blink = FALSE;
|
|
static int cursor_overwrite = FALSE;
|
|
static int blink_reverse = FALSE;
|
|
static int inverse_mode = FALSE;
|
|
static int screen_output = TRUE;
|
|
static int burst_mode = FALSE;
|
|
static int graphics_mode = FALSE;
|
|
static int pal_mode = FALSE;
|
|
static int escape_mode = FALSE;
|
|
static int font_a_index = 0;
|
|
static int font_a_double = FALSE;
|
|
static int font_a_blank = FALSE;
|
|
static int font_a_blink = FALSE;
|
|
static int font_b_index = 0;
|
|
static int font_b_double = FALSE;
|
|
static int font_b_blank = FALSE;
|
|
static int font_b_blink = FALSE;
|
|
static UBYTE input_mask[2] = {0x02,0x20};
|
|
static UBYTE output_mask[2] = {0x01,0x10};
|
|
|
|
static UBYTE xep80_data[XEP80_HEIGHT][XEP80_WIDTH];
|
|
static UBYTE xep80_graph_data[XEP80_GRAPH_HEIGHT][XEP80_GRAPH_WIDTH/8];
|
|
UBYTE XEP80_screen_1[XEP80_SCRN_WIDTH*XEP80_SCRN_HEIGHT];
|
|
UBYTE XEP80_screen_2[XEP80_SCRN_WIDTH*XEP80_SCRN_HEIGHT];
|
|
|
|
UBYTE (*font)[XEP80_FONTS_CHAR_COUNT][XEP80_CHAR_HEIGHT][XEP80_CHAR_WIDTH];
|
|
|
|
static int tab_stops[256] =
|
|
{0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
|
|
0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
|
|
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
|
|
0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
|
|
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
|
|
0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
|
|
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
|
|
0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
|
|
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
|
|
0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
|
|
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
|
|
0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
|
|
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1};
|
|
|
|
static int eol_at_margin[XEP80_HEIGHT] =
|
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
|
|
|
int XEP80_Initialise(int *argc, char *argv[])
|
|
{
|
|
int i, j;
|
|
for (i = j = 1; i < *argc; i++) {
|
|
int i_a = (i + 1 < *argc); /* is argument available? */
|
|
int a_m = FALSE; /* error, argument missing! */
|
|
|
|
if (strcmp(argv[i], "-xep80") == 0) {
|
|
XEP80_enabled = TRUE;
|
|
}
|
|
else if (strcmp(argv[i], "-xep80port") == 0) {
|
|
if (i_a) {
|
|
XEP80_port = Util_sscandec(argv[++i]);
|
|
if (XEP80_port != 0 && XEP80_port != 1) {
|
|
Log_print("Invalid XEP80 port - should be 0 or 1");
|
|
return FALSE;
|
|
}
|
|
}
|
|
else a_m = TRUE;
|
|
}
|
|
else {
|
|
if (strcmp(argv[i], "-help") == 0) {
|
|
Log_print("\t-xep80 Emulate the XEP80");
|
|
Log_print("\t-xep80port <n> Use XEP80 on joystick port <n>");
|
|
}
|
|
argv[j++] = argv[i];
|
|
}
|
|
|
|
if (a_m) {
|
|
Log_print("Missing argument for '%s'", argv[i]);
|
|
return FALSE;
|
|
}
|
|
}
|
|
*argc = j;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void XEP80_InputWord(int word)
|
|
{
|
|
input_queue[input_count] = word;
|
|
input_count++;
|
|
input_bit = 0;
|
|
input_first = TRUE;
|
|
}
|
|
|
|
static float XEP80_DeltaXYPos(float a, float b)
|
|
{
|
|
if (b > a)
|
|
return (b-a);
|
|
else
|
|
return(((float) Atari800_tv_mode) - a + b);
|
|
}
|
|
|
|
UBYTE XEP80_GetBit(void)
|
|
{
|
|
UBYTE ret = 0xFF;
|
|
int word_bit_num;
|
|
int input_word;
|
|
int input_word_num;
|
|
static float last_xypos;
|
|
/* This calculates the number of scan lines between bit
|
|
* reads. A scan line is the same time duration as a
|
|
* XEP80 Bit period */
|
|
float xypos = ANTIC_ypos +
|
|
((float) ANTIC_xpos)/
|
|
((float) ANTIC_xpos_limit);
|
|
|
|
/* If there is not input to be sent, just return */
|
|
if (input_count == 0)
|
|
return(ret);
|
|
|
|
/* If this is the first time, do nothing, start with bit 0 */
|
|
if (input_first)
|
|
{
|
|
input_first = FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* If we are more than half a bit period since the last
|
|
* read, assume it should be the next bit. If it's less
|
|
* do nothing, as SpartaDos driver does multiple reads at
|
|
* times */
|
|
if (XEP80_DeltaXYPos(last_xypos, xypos) > 0.5)
|
|
input_bit++;
|
|
/* If it is the stop bit on the first or second character
|
|
* to be sent, and we have taken more than a scan line to
|
|
* read it, then skip it and go to the next start bit.
|
|
* This is required to not confuse the stock AtariDOS
|
|
* driver. */
|
|
if ((XEP80_DeltaXYPos(last_xypos, xypos) > 1.1) &&
|
|
(input_bit == 10 || input_bit == 20))
|
|
input_bit++;
|
|
}
|
|
|
|
/* Figure out which word of the queue it is in based on bit */
|
|
input_word_num = (input_bit / 11) + 1;
|
|
|
|
/* If it is greater than we have, then clear queue and return */
|
|
if (input_word_num > (input_count))
|
|
{
|
|
input_count = 0;
|
|
return(ret);
|
|
}
|
|
|
|
/* Get the word from the queue, and calculate which bit of the
|
|
* word we are sending */
|
|
input_word = input_queue[input_word_num - 1];
|
|
word_bit_num = input_bit % 11;
|
|
|
|
/* Send the return value based on the bit */
|
|
switch(word_bit_num) {
|
|
case 0: /* Start Bit - 0 */
|
|
ret = 0xFF & ~input_mask[XEP80_port];
|
|
break;
|
|
case 1: /* 9 Data Bits */
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
if (input_word & (1 << (word_bit_num-1))) {
|
|
ret = 0xFF;
|
|
}
|
|
else {
|
|
ret = 0xFF & ~input_mask[XEP80_port];
|
|
}
|
|
break;
|
|
case 10: /* Stop Bit - 1 */
|
|
ret = 0xFF;
|
|
break;
|
|
}
|
|
|
|
last_xypos = xypos;
|
|
/* If we are done with all bits, clear the queue */
|
|
if (input_bit >= ((input_count * 11) - 2))
|
|
input_count = 0;
|
|
return(ret);
|
|
}
|
|
|
|
void XEP80_PutBit(UBYTE byte)
|
|
{
|
|
byte &= output_mask[XEP80_port];
|
|
|
|
/* Shift output words from the Atari for each write */
|
|
switch(output_state) {
|
|
case -1:
|
|
if (!byte) {
|
|
output_state = 0;
|
|
output_word = 0;
|
|
}
|
|
break;
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
if (byte) {
|
|
output_word |= 1 << (output_state);
|
|
}
|
|
output_state ++;
|
|
break;
|
|
case 9:
|
|
output_state = -1;
|
|
/* Clear any unread input from last command */
|
|
input_count = 0;
|
|
if (byte) {
|
|
/* Handle the new word */
|
|
XEP80_OutputWord(output_word);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void XEP80_OutputWord(int word)
|
|
{
|
|
UBYTE byte = word & 0xFF;
|
|
int cmd_flag = word & 0x100;
|
|
static UBYTE lastChar = 0;
|
|
|
|
/* Is it a command or data word? */
|
|
if (cmd_flag) {
|
|
switch(byte & CMD_XX_MASK) {
|
|
case CMD_00:
|
|
XEP80_SetXCur(byte & 0x3F);
|
|
break;
|
|
case CMD_01:
|
|
switch(byte & CMD_01_MASK) {
|
|
case CMD_X_CUR_UPPER:
|
|
XEP80_SetXCur(0x40 + (byte & 0x0F));
|
|
break;
|
|
case CMD_X_CUR_HIGH:
|
|
XEP80_SetXCurHigh(byte & 0x0F);
|
|
break;
|
|
case CMD_LEFT_MAR_L:
|
|
XEP80_SetLeftMarginLow(byte & 0x0f);
|
|
break;
|
|
case CMD_LEFT_MAR_H:
|
|
XEP80_SetLeftMarginHigh(byte & 0x0f);
|
|
break;
|
|
}
|
|
break;
|
|
case CMD_10:
|
|
switch(byte & CMD_10_MASK) {
|
|
case CMD_Y_CUR_LOW:
|
|
XEP80_SetYCur(byte & 0x0F);
|
|
break;
|
|
case CMD_1001:
|
|
if ((byte & CMD_1001_MASK) == CMD_Y_CUR_HIGH) {
|
|
XEP80_SetYCur(0x10 + (byte & 0x07));
|
|
}
|
|
else {
|
|
switch(byte) {
|
|
case CMD_Y_CUR_STATUS:
|
|
XEP80_SetYCur(24);
|
|
break;
|
|
case CMD_GRAPH_50HZ:
|
|
XEP80_SetScreenMode(TRUE, TRUE);
|
|
break;
|
|
case CMD_GRAPH_60HZ:
|
|
XEP80_SetScreenMode(TRUE, FALSE);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case CMD_RIGHT_MAR_L:
|
|
XEP80_SetRightMarginLow(byte & 0x0f);
|
|
break;
|
|
case CMD_RIGHT_MAR_H:
|
|
XEP80_SetRightMarginHigh(byte & 0x0f);
|
|
break;
|
|
}
|
|
break;
|
|
case CMD_11:
|
|
switch (byte) {
|
|
case CMD_GET_CHAR:
|
|
XEP80_GetChar();
|
|
break;
|
|
case CMD_REQ_X_CUR:
|
|
XEP80_GetXCur();
|
|
break;
|
|
case CMD_MRST:
|
|
XEP80_MasterReset();
|
|
break;
|
|
case CMD_PRT_STAT:
|
|
XEP80_GetPrinterStatus();
|
|
break;
|
|
case CMD_FILL_PREV:
|
|
XEP80_FillMem(lastChar, TRUE);
|
|
break;
|
|
case CMD_FILL_SPACE:
|
|
XEP80_FillMem(0x20, TRUE);
|
|
break;
|
|
case CMD_FILL_EOL:
|
|
XEP80_FillMem(0x9B, TRUE);
|
|
break;
|
|
case CMD_CLR_LIST:
|
|
XEP80_SetList(FALSE);
|
|
break;
|
|
case CMD_SET_LIST:
|
|
XEP80_SetList(TRUE);
|
|
break;
|
|
case CMD_SCR_NORMAL:
|
|
XEP80_SetOutputDevice(TRUE, FALSE);
|
|
break;
|
|
case CMD_SCR_BURST:
|
|
XEP80_SetOutputDevice(TRUE, TRUE);
|
|
break;
|
|
case CMD_SET_PRINT:
|
|
XEP80_SetOutputDevice(FALSE, TRUE);
|
|
break;
|
|
case CMD_CHAR_SET_A:
|
|
XEP80_SetCharSet(CHAR_SET_A);
|
|
XEP80_BlitScreen();
|
|
break;
|
|
case CMD_CHAR_SET_B:
|
|
XEP80_SetCharSet(CHAR_SET_B);
|
|
XEP80_BlitScreen();
|
|
break;
|
|
case CMD_CHAR_SET_INT:
|
|
XEP80_SetCharSet(CHAR_SET_INTERNAL);
|
|
XEP80_BlitScreen();
|
|
break;
|
|
case CMD_TEXT_50HZ:
|
|
XEP80_SetScreenMode(FALSE, TRUE);
|
|
break;
|
|
case CMD_CUR_OFF:
|
|
XEP80_SetCursor(FALSE, FALSE);
|
|
break;
|
|
case CMD_CUR_ON:
|
|
XEP80_SetCursor(TRUE, FALSE);
|
|
break;
|
|
case CMD_CUR_BLINK:
|
|
XEP80_SetCursor(TRUE, TRUE);
|
|
break;
|
|
case CMD_CUR_ST_LINE:
|
|
XEP80_SetXCurStart();
|
|
break;
|
|
case CMD_SET_SCRL_WIN:
|
|
XEP80_SetScrollWindow();
|
|
break;
|
|
case CMD_WHT_ON_BLK:
|
|
XEP80_SetInverse(FALSE);
|
|
break;
|
|
case CMD_BLK_ON_WHT:
|
|
XEP80_SetInverse(TRUE);
|
|
break;
|
|
case CMD_VIDEO_CTRL:
|
|
XEP80_Backspace();
|
|
XEP80_SetVideoCtrl(lastChar);
|
|
break;
|
|
case CMD_ATTRIB_A:
|
|
XEP80_Backspace();
|
|
XEP80_SetAttributeA(lastChar);
|
|
break;
|
|
case CMD_ATTRIB_B:
|
|
XEP80_Backspace();
|
|
XEP80_SetAttributeB(lastChar);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
/* If it's data, then handle it as a character */
|
|
else {
|
|
old_xcur = xcur;
|
|
old_ycur = ycur;
|
|
XEP80_ReceiveChar(byte);
|
|
lastChar = byte;
|
|
if (!burst_mode)
|
|
XEP80_SendCursorStatus();
|
|
}
|
|
}
|
|
|
|
static void XEP80_ReceiveChar(UBYTE byte)
|
|
{
|
|
if (graphics_mode) {
|
|
XEP80_AddGraphCharAtCursor(byte);
|
|
}
|
|
else if (escape_mode) {
|
|
XEP80_AddCharAtCursor(byte);
|
|
escape_mode = FALSE;
|
|
}
|
|
/* List mode prints control chars like escape mode, except for EOL */
|
|
else if (list_mode) {
|
|
if (byte == XEP80_ATARI_EOL) {
|
|
XEP80_AddEOL();
|
|
}
|
|
else {
|
|
XEP80_AddCharAtCursor(byte);
|
|
}
|
|
}
|
|
else if (!screen_output) {
|
|
/* Printer characters are thrown away, handled elsewhere. The
|
|
* XEP80 driver needs to be set up to send printer characters
|
|
* to the existing P: driver. */
|
|
}
|
|
else {
|
|
/* If we are on the status line, only allow Delete Line and char adds */
|
|
if (ycur == 24) {
|
|
if (byte == 0x9c) { /* Delete Line */
|
|
memset(xep80_data[ycur],XEP80_ATARI_EOL,XEP80_WIDTH);
|
|
}
|
|
else {
|
|
XEP80_AddCharAtCursor(byte);
|
|
}
|
|
}
|
|
else {
|
|
switch(byte) {
|
|
case 0x1b: /* Escape - Print next char even if a control char */
|
|
escape_mode = TRUE;
|
|
break;
|
|
case 0x1c: /* Cursor Up */
|
|
XEP80_CursorUp();
|
|
break;
|
|
case 0x1d: /* Cursor Down */
|
|
XEP80_CursorDown();
|
|
break;
|
|
case 0x1e: /* Cursor Left */
|
|
XEP80_CursorLeft();
|
|
break;
|
|
case 0x1f: /* Cursor Right */
|
|
XEP80_CursorRight();
|
|
break;
|
|
case 0x7d: /* Clear Screen */
|
|
XEP80_ClearScreen();
|
|
break;
|
|
case 0x7e: /* Backspace */
|
|
XEP80_Backspace();
|
|
break;
|
|
case 0x7f: /* Tab */
|
|
XEP80_GoToNextTab();
|
|
break;
|
|
case XEP80_ATARI_EOL: /* Atari EOL */
|
|
XEP80_AddEOL();
|
|
break;
|
|
case 0x9c: /* Delete Line */
|
|
XEP80_DeleteLogicalLine();
|
|
break;
|
|
case 0x9d: /* Insert Line */
|
|
XEP80_InsertLine();
|
|
break;
|
|
case 0x9e: /* Clear tab */
|
|
tab_stops[xcur] = FALSE;
|
|
break;
|
|
case 0x9f: /* Set Tab */
|
|
tab_stops[xcur] = TRUE;
|
|
break;
|
|
case 0xfd: /* Sound Bell */
|
|
/* Do nothing here */
|
|
break;
|
|
case 0xfe: /* Delete Char */
|
|
XEP80_DeleteChar();
|
|
break;
|
|
case 0xff: /* Insert Char */
|
|
XEP80_InsertChar();
|
|
break;
|
|
default:
|
|
XEP80_AddCharAtCursor(byte);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static void XEP80_SendCursorStatus()
|
|
{
|
|
/* Send X cursor only */
|
|
if ((old_xcur == xcur && old_ycur == ycur) ||
|
|
(old_ycur == ycur)) {
|
|
if (xcur > 0x4f) {
|
|
XEP80_InputWord(0x150);
|
|
}
|
|
else {
|
|
XEP80_InputWord(0x100 | (xcur & 0x7F));
|
|
}
|
|
}
|
|
/* Send Y cursor only */
|
|
else if (old_xcur == xcur) {
|
|
XEP80_InputWord(0x1E0 | (ycur & 0x1F));
|
|
}
|
|
/* Send X followed by Y cursor */
|
|
else {
|
|
if (xcur > 0x4f) {
|
|
XEP80_InputWord(0x1D0);
|
|
}
|
|
else {
|
|
XEP80_InputWord(0x180 | (xcur & 0x7F));
|
|
}
|
|
XEP80_InputWord(0x1E0 | (ycur & 0x1F));
|
|
}
|
|
}
|
|
|
|
static void XEP80_SetXCur(UBYTE cursor)
|
|
{
|
|
new_xcur = cursor;
|
|
new_ycur = ycur;
|
|
XEP80_UpdateCursor();
|
|
XEP80_SendCursorStatus();
|
|
}
|
|
|
|
static void XEP80_SetXCurHigh(UBYTE cursor)
|
|
{
|
|
new_xcur = ((UBYTE)xcur & 0x3f) | (cursor << 4);
|
|
new_ycur = ycur;
|
|
XEP80_UpdateCursor();
|
|
XEP80_SendCursorStatus();
|
|
}
|
|
|
|
static void XEP80_SetLeftMarginLow(UBYTE margin)
|
|
{
|
|
lmargin = margin;
|
|
}
|
|
|
|
static void XEP80_SetLeftMarginHigh(UBYTE margin)
|
|
{
|
|
lmargin = ((UBYTE)lmargin & 0x3f) | (margin << 4);
|
|
}
|
|
|
|
static void XEP80_SetYCur(UBYTE cursor)
|
|
{
|
|
new_xcur = xcur;
|
|
new_ycur = cursor;
|
|
XEP80_UpdateCursor();
|
|
XEP80_SendCursorStatus();
|
|
}
|
|
|
|
static void XEP80_SetScreenMode(int graphics, int pal)
|
|
{
|
|
graphics_mode = graphics;
|
|
pal_mode = pal;
|
|
if (graphics_mode) {
|
|
xcur = 0;
|
|
ycur = 0;
|
|
burst_mode = TRUE;
|
|
/* Clear the old text screen */
|
|
XEP80_FillMem(0x20, FALSE);
|
|
XEP80_BlitScreen();
|
|
/* Clear the graphics memory */
|
|
memset(xep80_graph_data,0,
|
|
(XEP80_GRAPH_WIDTH/8)*XEP80_GRAPH_HEIGHT);
|
|
}
|
|
else {
|
|
xcur = 0;
|
|
ycur = 0;
|
|
burst_mode = FALSE;
|
|
XEP80_FillMem(0x9b, FALSE);
|
|
XEP80_BlitScreen();
|
|
new_xcur = xcur;
|
|
new_ycur = ycur;
|
|
XEP80_UpdateCursor();
|
|
}
|
|
}
|
|
|
|
static void XEP80_SetRightMarginLow(UBYTE margin)
|
|
{
|
|
rmargin = margin;
|
|
}
|
|
|
|
static void XEP80_SetRightMarginHigh(UBYTE margin)
|
|
{
|
|
rmargin = ((UBYTE)rmargin & 0x3f) | (margin << 4);
|
|
}
|
|
|
|
static void XEP80_GetChar(void)
|
|
{
|
|
static int at_eol_at_margin = FALSE;
|
|
|
|
if (xcur == rmargin && at_eol_at_margin) {
|
|
XEP80_InputWord(XEP80_ATARI_EOL);
|
|
at_eol_at_margin = FALSE;
|
|
} else {
|
|
XEP80_InputWord(xep80_data[ycur][xcur]);
|
|
}
|
|
|
|
old_xcur = xcur;
|
|
old_ycur = ycur;
|
|
new_xcur = xcur + 1;
|
|
new_ycur = ycur;
|
|
|
|
if (new_xcur > rmargin)
|
|
{
|
|
if (eol_at_margin[new_ycur]) {
|
|
new_ycur = ycur;
|
|
new_xcur -= 1;
|
|
at_eol_at_margin = TRUE;
|
|
}
|
|
else {
|
|
new_xcur = lmargin;
|
|
if (new_ycur < XEP80_HEIGHT-2)
|
|
new_ycur++;
|
|
}
|
|
}
|
|
XEP80_UpdateCursor();
|
|
XEP80_SendCursorStatus();
|
|
}
|
|
|
|
static void XEP80_GetXCur(void)
|
|
{
|
|
XEP80_InputWord(xcur);
|
|
}
|
|
|
|
static void XEP80_MasterReset(void)
|
|
{
|
|
int i;
|
|
|
|
input_count = 0;
|
|
|
|
xcur = 0;
|
|
xscroll = 0;
|
|
ycur = 0;
|
|
new_xcur = 0;
|
|
new_ycur = 0;
|
|
old_xcur = 0;
|
|
old_ycur = 0;
|
|
lmargin = 0;
|
|
rmargin = 0x4f;
|
|
attrib_a = 0;
|
|
attrib_b = 0;
|
|
list_mode = FALSE;
|
|
char_set = CHAR_SET_A;
|
|
cursor_on = TRUE;
|
|
cursor_blink = FALSE;
|
|
cursor_overwrite = FALSE;
|
|
blink_reverse = FALSE;
|
|
inverse_mode = FALSE;
|
|
screen_output = TRUE;
|
|
burst_mode = FALSE;
|
|
graphics_mode = FALSE;
|
|
pal_mode = FALSE;
|
|
escape_mode = FALSE;
|
|
|
|
font_a_index = 0;
|
|
font_a_double = FALSE;
|
|
font_a_blank = FALSE;
|
|
font_a_blink = FALSE;
|
|
font_b_index = 0;
|
|
font_b_double = FALSE;
|
|
font_b_blank = FALSE;
|
|
font_b_blink = FALSE;
|
|
memset(xep80_data,XEP80_ATARI_EOL,XEP80_WIDTH*XEP80_HEIGHT);
|
|
if (!XEP80_FONTS_inited)
|
|
XEP80_FONTS_InitFonts();
|
|
for (i=0;i<XEP80_HEIGHT;i++)
|
|
eol_at_margin[i] = FALSE;
|
|
XEP80_BlitScreen();
|
|
XEP80_UpdateCursor();
|
|
XEP80_InputWord(0x01);
|
|
}
|
|
|
|
static void XEP80_GetPrinterStatus(void)
|
|
{
|
|
XEP80_InputWord(0x01);
|
|
}
|
|
|
|
static void XEP80_FillMem(UBYTE c, int output)
|
|
{
|
|
int i;
|
|
|
|
for (i=0;i<XEP80_HEIGHT;i++)
|
|
eol_at_margin[i] = FALSE;
|
|
|
|
memset(xep80_data,c,XEP80_WIDTH*XEP80_HEIGHT);
|
|
if (output)
|
|
XEP80_InputWord(0x01);
|
|
}
|
|
|
|
static void XEP80_SetList(int list)
|
|
{
|
|
list_mode = list;
|
|
}
|
|
|
|
static void XEP80_SetOutputDevice(int screen, int burst)
|
|
{
|
|
screen_output = screen;
|
|
burst_mode = burst;
|
|
}
|
|
|
|
static void XEP80_SetCharSet(int set)
|
|
{
|
|
char_set = set;
|
|
}
|
|
|
|
static void XEP80_SetCursor(int on, int blink)
|
|
{
|
|
cursor_on = on;
|
|
cursor_blink = blink;
|
|
if (!cursor_on) {
|
|
XEP80_BlitChar(xcur, ycur, FALSE);
|
|
}
|
|
else {
|
|
new_xcur = xcur;
|
|
new_ycur = ycur;
|
|
XEP80_UpdateCursor();
|
|
}
|
|
}
|
|
|
|
static void XEP80_SetXCurStart(void)
|
|
{
|
|
int x_start = xcur;
|
|
int y_start = ycur;
|
|
|
|
XEP80_FindStartLogicalLine(&x_start, &y_start);
|
|
new_xcur = x_start;
|
|
new_ycur = y_start;
|
|
XEP80_UpdateCursor();
|
|
XEP80_SendCursorStatus();
|
|
}
|
|
|
|
static void XEP80_SetScrollWindow(void)
|
|
{
|
|
xscroll = xcur;
|
|
XEP80_BlitScreen();
|
|
}
|
|
|
|
static void XEP80_SetInverse(int inverse)
|
|
{
|
|
inverse_mode = inverse;
|
|
XEP80_BlitScreen();
|
|
}
|
|
|
|
static void XEP80_SetVideoCtrl(UBYTE video_ctrl)
|
|
{
|
|
if (video_ctrl & 0x08) {
|
|
inverse_mode = TRUE;
|
|
}
|
|
else {
|
|
inverse_mode = FALSE;
|
|
}
|
|
if (video_ctrl & 0x02) {
|
|
cursor_blink = FALSE;
|
|
}
|
|
else {
|
|
cursor_blink = TRUE;
|
|
}
|
|
if (video_ctrl & 0x04) {
|
|
cursor_overwrite = FALSE;
|
|
}
|
|
else {
|
|
cursor_overwrite = TRUE;
|
|
}
|
|
if (video_ctrl & 0x01) {
|
|
blink_reverse = TRUE;
|
|
}
|
|
else {
|
|
blink_reverse = FALSE;
|
|
}
|
|
XEP80_BlitScreen();
|
|
new_xcur = xcur;
|
|
new_ycur = ycur;
|
|
XEP80_UpdateCursor();
|
|
}
|
|
|
|
static void XEP80_SetAttributeA(UBYTE attrib)
|
|
{
|
|
attrib_a = ~attrib;
|
|
|
|
font_a_index = 0;
|
|
if (attrib_a & 0x01) {
|
|
font_a_index |= XEP80_FONTS_REV_FONT_BIT;
|
|
}
|
|
if (attrib_a & 0x20) {
|
|
font_a_index |= XEP80_FONTS_UNDER_FONT_BIT;
|
|
}
|
|
if (attrib_a & 0x80) {
|
|
font_a_index |= XEP80_FONTS_BLK_FONT_BIT;
|
|
}
|
|
if (attrib_a & 0x10) {
|
|
font_a_double = TRUE;
|
|
}
|
|
else {
|
|
font_a_double = FALSE;
|
|
}
|
|
if (attrib_a & 0x40) {
|
|
font_a_blank = TRUE;
|
|
}
|
|
else {
|
|
font_a_blank = FALSE;
|
|
}
|
|
if (attrib_a & 0x04) {
|
|
font_a_blink = TRUE;
|
|
}
|
|
else {
|
|
font_a_blink = FALSE;
|
|
}
|
|
XEP80_BlitScreen();
|
|
}
|
|
|
|
static void XEP80_SetAttributeB(UBYTE attrib)
|
|
{
|
|
attrib_b = ~attrib;
|
|
|
|
font_b_index = 0;
|
|
if (attrib_b & 0x01) {
|
|
font_b_index |= XEP80_FONTS_REV_FONT_BIT;
|
|
}
|
|
if (attrib_b & 0x20) {
|
|
font_b_index |= XEP80_FONTS_UNDER_FONT_BIT;
|
|
}
|
|
if (attrib_b & 0x80) {
|
|
font_b_index |= XEP80_FONTS_BLK_FONT_BIT;
|
|
}
|
|
if (attrib_b & 0x10) {
|
|
font_b_double = TRUE;
|
|
}
|
|
else {
|
|
font_b_double = FALSE;
|
|
}
|
|
if (attrib_b & 0x40) {
|
|
font_b_blank = TRUE;
|
|
}
|
|
else {
|
|
font_b_blank = FALSE;
|
|
}
|
|
if (attrib_b & 0x04) {
|
|
font_b_blink = TRUE;
|
|
}
|
|
else {
|
|
font_b_blink = FALSE;
|
|
}
|
|
XEP80_BlitScreen();
|
|
}
|
|
|
|
static void XEP80_UpdateCursor(void)
|
|
{
|
|
if (cursor_on) {
|
|
/* Redraw character cursor was at */
|
|
XEP80_BlitChar(xcur, ycur, FALSE);
|
|
/* Handle reblitting double wide's which cursor may have overwritten */
|
|
if (xcur != 0) {
|
|
XEP80_BlitChar(xcur-1, ycur, FALSE);
|
|
}
|
|
/* Redraw cursor at new location */
|
|
XEP80_BlitChar(new_xcur, new_ycur, TRUE);
|
|
}
|
|
xcur = new_xcur;
|
|
ycur = new_ycur;
|
|
}
|
|
|
|
static void XEP80_AddCharAtCursor(UBYTE byte)
|
|
{
|
|
xep80_data[ycur][xcur] = byte;
|
|
XEP80_BlitChar(xcur, ycur, FALSE);
|
|
|
|
new_xcur = xcur + 1;
|
|
new_ycur = ycur;
|
|
if (new_xcur > rmargin)
|
|
{
|
|
new_xcur = lmargin;
|
|
if (new_ycur == XEP80_HEIGHT-2) {
|
|
XEP80_ScrollUpLast();
|
|
}
|
|
else if (new_ycur != XEP80_HEIGHT-1) {
|
|
new_ycur++;
|
|
XEP80_ScrollDown(new_ycur);
|
|
}
|
|
}
|
|
else {
|
|
XEP80_UpdateCursor();
|
|
}
|
|
}
|
|
|
|
static void XEP80_AddGraphCharAtCursor(UBYTE byte)
|
|
{
|
|
xep80_graph_data[ycur][xcur] = byte;
|
|
XEP80_BlitGraphChar(xcur, ycur);
|
|
xcur++;
|
|
if (xcur >= 40) {
|
|
xcur = 0;
|
|
ycur++;
|
|
if (ycur >= 240) {
|
|
ycur = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void XEP80_CursorUp(void)
|
|
{
|
|
new_ycur = ycur - 1;
|
|
new_xcur = xcur;
|
|
if (new_ycur < 0)
|
|
{
|
|
new_ycur = XEP80_HEIGHT-2;
|
|
}
|
|
XEP80_UpdateCursor();
|
|
}
|
|
|
|
static void XEP80_CursorDown(void)
|
|
{
|
|
new_ycur = ycur + 1;
|
|
new_xcur = xcur;
|
|
if (new_ycur > XEP80_HEIGHT-2)
|
|
{
|
|
new_ycur = 0;
|
|
}
|
|
XEP80_UpdateCursor();
|
|
}
|
|
|
|
static void XEP80_CursorLeft(void)
|
|
{
|
|
new_xcur = xcur - 1;
|
|
new_ycur = ycur;
|
|
if (new_xcur < lmargin)
|
|
{
|
|
new_xcur = rmargin;
|
|
}
|
|
XEP80_UpdateCursor();
|
|
}
|
|
|
|
static void XEP80_CursorRight(void)
|
|
{
|
|
if (xep80_data[ycur][xcur] == XEP80_ATARI_EOL) {
|
|
xep80_data[ycur][xcur] = 0x20;
|
|
}
|
|
new_xcur = xcur + 1;
|
|
new_ycur = ycur;
|
|
if (new_xcur > rmargin)
|
|
{
|
|
new_xcur = lmargin;
|
|
}
|
|
XEP80_UpdateCursor();
|
|
}
|
|
|
|
static void XEP80_ClearScreen(void)
|
|
{
|
|
int y;
|
|
|
|
for (y=0;y<XEP80_HEIGHT-1;y++) {
|
|
memset(&xep80_data[y][xscroll],XEP80_ATARI_EOL,XEP80_LINE_LEN);
|
|
eol_at_margin[y] = FALSE;
|
|
}
|
|
XEP80_BlitScreen();
|
|
new_xcur = 0;
|
|
new_ycur = 0;
|
|
XEP80_UpdateCursor();
|
|
}
|
|
|
|
|
|
static void XEP80_Backspace(void)
|
|
{
|
|
int x_start = xcur;
|
|
int y_start = ycur;
|
|
|
|
XEP80_FindStartLogicalLine(&x_start, &y_start);
|
|
|
|
if (xcur == lmargin && x_start == xcur && y_start == ycur) {
|
|
return;
|
|
}
|
|
|
|
if (xcur == lmargin) {
|
|
new_ycur = ycur-1;
|
|
new_xcur = rmargin;
|
|
}
|
|
else {
|
|
new_xcur = xcur-1;
|
|
new_ycur = ycur;
|
|
}
|
|
xep80_data[new_ycur][new_xcur] = 0x20;
|
|
XEP80_UpdateCursor();
|
|
}
|
|
|
|
static void XEP80_DeleteChar(void)
|
|
{
|
|
int x_end = xcur;
|
|
int y_end = ycur;
|
|
int x_del, y_del;
|
|
|
|
XEP80_FindEndLogicalLine(&x_end, &y_end);
|
|
|
|
x_del = xcur;
|
|
y_del = ycur;
|
|
|
|
while(x_del != x_end || y_del != y_end) {
|
|
if (x_del == rmargin) {
|
|
if (y_del == XEP80_HEIGHT-2) {
|
|
xep80_data[y_del][x_del] = XEP80_ATARI_EOL;
|
|
break;
|
|
}
|
|
xep80_data[y_del][x_del] = xep80_data[y_del+1][lmargin];
|
|
if (xep80_data[y_del+1][lmargin+1] == XEP80_ATARI_EOL) {
|
|
XEP80_ScrollUp(y_del+1, y_del+1);
|
|
eol_at_margin[y_del] = TRUE;
|
|
break;
|
|
}
|
|
y_del++;
|
|
x_del=lmargin;
|
|
}
|
|
else {
|
|
xep80_data[y_del][x_del] = xep80_data[y_del][x_del+1];
|
|
if (x_del == rmargin-1 && eol_at_margin[y_del]) {
|
|
xep80_data[y_del][x_del+1] = XEP80_ATARI_EOL;
|
|
eol_at_margin[y_del] = FALSE;
|
|
}
|
|
x_del++;
|
|
}
|
|
}
|
|
XEP80_BlitRows(ycur,y_end);
|
|
if (cursor_on)
|
|
XEP80_BlitChar(xcur, ycur, TRUE);
|
|
}
|
|
|
|
|
|
static void XEP80_InsertChar(void)
|
|
{
|
|
int x_end = xcur;
|
|
int y_end = ycur;
|
|
int x_ins, y_ins;
|
|
|
|
XEP80_FindEndLogicalLine(&x_end, &y_end);
|
|
|
|
x_ins = x_end;
|
|
y_ins = y_end;
|
|
|
|
if (x_ins == rmargin) {
|
|
if (eol_at_margin[y_end]) {
|
|
if (y_end == XEP80_HEIGHT-2) {
|
|
new_ycur = ycur-1;
|
|
new_xcur = xcur;
|
|
XEP80_ScrollUpLast();
|
|
y_ins--;
|
|
eol_at_margin[y_end-1] = FALSE;
|
|
xep80_data[y_end][lmargin] = XEP80_ATARI_EOL;
|
|
} else {
|
|
XEP80_ScrollDown(y_ins+1);
|
|
eol_at_margin[y_end] = FALSE;
|
|
y_end++;
|
|
xep80_data[y_end][lmargin] = XEP80_ATARI_EOL;
|
|
}
|
|
}
|
|
else if (xep80_data[y_end][x_end] == XEP80_ATARI_EOL) {
|
|
x_ins--;
|
|
eol_at_margin[y_end] = TRUE;
|
|
}
|
|
}
|
|
|
|
while(x_ins != xcur || y_ins != ycur) {
|
|
if (y_ins == ycur && x_ins < xcur)
|
|
break;
|
|
if (x_ins == rmargin) {
|
|
if (y_ins != XEP80_HEIGHT-2) {
|
|
xep80_data[y_ins+1][lmargin] = xep80_data[y_ins][x_ins];
|
|
}
|
|
}
|
|
else {
|
|
xep80_data[y_ins][x_ins+1] = xep80_data[y_ins][x_ins];
|
|
}
|
|
if (x_ins == lmargin) {
|
|
x_ins = rmargin;
|
|
y_ins--;
|
|
}
|
|
else {
|
|
x_ins--;
|
|
}
|
|
}
|
|
|
|
if (x_ins == rmargin) {
|
|
xep80_data[y_ins+1][lmargin] = xep80_data[y_ins][x_ins];
|
|
}
|
|
else {
|
|
xep80_data[y_ins][x_ins+1] = xep80_data[y_ins][x_ins];
|
|
}
|
|
xep80_data[y_ins][x_ins] = 0x20;
|
|
XEP80_BlitRows(ycur,y_end);
|
|
if (cursor_on)
|
|
XEP80_BlitChar(xcur, ycur, TRUE);
|
|
}
|
|
|
|
static void XEP80_GoToNextTab(void)
|
|
{
|
|
int x_search = xcur+1;
|
|
int y_search = ycur;
|
|
|
|
while(1) {
|
|
while(x_search<=rmargin) {
|
|
if (tab_stops[x_search]) {
|
|
new_xcur = x_search;
|
|
new_ycur = y_search;
|
|
XEP80_UpdateCursor();
|
|
return;
|
|
}
|
|
x_search++;
|
|
}
|
|
y_search++;
|
|
x_search = lmargin;
|
|
if (y_search >= XEP80_HEIGHT-1) {
|
|
new_ycur = XEP80_HEIGHT-2;
|
|
new_xcur = lmargin;
|
|
XEP80_ScrollUpLast();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void XEP80_AddEOL(void)
|
|
{
|
|
int x_end = xcur;
|
|
int y_end = ycur;
|
|
|
|
XEP80_FindEndLogicalLine(&x_end,&y_end);
|
|
xep80_data[y_end][x_end] = XEP80_ATARI_EOL;
|
|
new_xcur = lmargin;
|
|
if (y_end == XEP80_HEIGHT-2) {
|
|
new_ycur = y_end;
|
|
XEP80_ScrollUpLast();
|
|
}
|
|
else {
|
|
new_ycur = y_end+1;
|
|
XEP80_UpdateCursor();
|
|
}
|
|
}
|
|
|
|
static void XEP80_DeleteLogicalLine(void)
|
|
{
|
|
int x_start = xcur;
|
|
int y_start = ycur;
|
|
int x_end = xcur;
|
|
int y_end = ycur;
|
|
|
|
XEP80_FindStartLogicalLine(&x_start, &y_start);
|
|
XEP80_FindEndLogicalLine(&x_end, &y_end);
|
|
new_ycur = y_start;
|
|
new_xcur = lmargin;
|
|
XEP80_ScrollUp(y_start, y_end);
|
|
}
|
|
|
|
static void XEP80_InsertLine(void)
|
|
{
|
|
new_xcur = lmargin;
|
|
new_ycur = ycur;
|
|
|
|
XEP80_ScrollDown(ycur);;
|
|
}
|
|
|
|
static void XEP80_ScrollUpLast(void)
|
|
{
|
|
int row;
|
|
|
|
if (cursor_on) {
|
|
XEP80_BlitChar(xcur, ycur, FALSE);
|
|
if (xcur != 0) {
|
|
XEP80_BlitChar(xcur-1, ycur, FALSE);
|
|
}
|
|
}
|
|
|
|
for (row=1;row<=XEP80_HEIGHT-2;row++) {
|
|
memcpy(xep80_data[row-1],
|
|
xep80_data[row],
|
|
XEP80_WIDTH);
|
|
eol_at_margin[row-1] = eol_at_margin[row] ;
|
|
}
|
|
|
|
memset(xep80_data[23],XEP80_ATARI_EOL,XEP80_WIDTH);
|
|
eol_at_margin[23] = FALSE ;
|
|
|
|
XEP80_BlitScreen();
|
|
|
|
if (cursor_on) {
|
|
XEP80_BlitChar(new_xcur, new_ycur, TRUE);
|
|
}
|
|
xcur = new_xcur;
|
|
ycur = new_ycur;
|
|
}
|
|
|
|
static void XEP80_ScrollDown(int y)
|
|
{
|
|
int row;
|
|
|
|
if (cursor_on) {
|
|
XEP80_BlitChar(xcur, ycur, FALSE);
|
|
if (xcur != 0) {
|
|
XEP80_BlitChar(xcur-1, ycur, FALSE);
|
|
}
|
|
}
|
|
|
|
for (row=XEP80_HEIGHT-3;row>=y;row--) {
|
|
memcpy(xep80_data[row+1],
|
|
xep80_data[row],
|
|
XEP80_WIDTH);
|
|
eol_at_margin[row+1] = eol_at_margin[row] ;
|
|
}
|
|
|
|
memset(xep80_data[y],XEP80_ATARI_EOL,XEP80_WIDTH);
|
|
eol_at_margin[y] = FALSE ;
|
|
|
|
XEP80_BlitRows(y,23);
|
|
|
|
if (cursor_on) {
|
|
XEP80_BlitChar(new_xcur, new_ycur, TRUE);
|
|
}
|
|
xcur = new_xcur;
|
|
ycur = new_ycur;
|
|
}
|
|
|
|
static void XEP80_ScrollUp(int y_start, int y_end)
|
|
{
|
|
int row;
|
|
int num_rows = y_end - y_start + 1;
|
|
|
|
if (cursor_on) {
|
|
XEP80_BlitChar(xcur, ycur, FALSE);
|
|
if (xcur != 0) {
|
|
XEP80_BlitChar(xcur-1, ycur, FALSE);
|
|
}
|
|
}
|
|
|
|
for (row=y_start;row<XEP80_HEIGHT-2;row++) {
|
|
memcpy(xep80_data[row],
|
|
xep80_data[row+num_rows],
|
|
XEP80_WIDTH);
|
|
eol_at_margin[row] = eol_at_margin[row+num_rows] ;
|
|
}
|
|
|
|
for (row=24-num_rows; row < 24; row++) {
|
|
memset(xep80_data[row],XEP80_ATARI_EOL,XEP80_WIDTH);
|
|
eol_at_margin[row] = FALSE;
|
|
}
|
|
|
|
XEP80_BlitRows(y_start,23);
|
|
|
|
if (cursor_on) {
|
|
XEP80_BlitChar(new_xcur, new_ycur, TRUE);
|
|
}
|
|
xcur = new_xcur;
|
|
ycur = new_ycur;
|
|
}
|
|
|
|
static void XEP80_FindEndLogicalLine(int *x, int *y)
|
|
{
|
|
int x_search = *x;
|
|
int y_search = *y;
|
|
int found = FALSE;
|
|
|
|
while(1) {
|
|
while(x_search<=rmargin) {
|
|
if (xep80_data[y_search][x_search] == XEP80_ATARI_EOL) {
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
x_search++;
|
|
}
|
|
if (found)
|
|
break;
|
|
if (eol_at_margin[y_search]) {
|
|
x_search = rmargin;
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
y_search++;
|
|
if (y_search >= XEP80_HEIGHT-1)
|
|
break;
|
|
x_search = lmargin;
|
|
}
|
|
|
|
if (!found) {
|
|
*x = rmargin;
|
|
*y = XEP80_HEIGHT-2;
|
|
}
|
|
else {
|
|
if (x_search == 0 && y_search != ycur) {
|
|
*x = rmargin;
|
|
*y = y_search-1;
|
|
}
|
|
else {
|
|
*x = x_search;
|
|
*y = y_search;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void XEP80_FindStartLogicalLine(int *x, int *y)
|
|
{
|
|
int y_search = *y;
|
|
int x_search = rmargin;
|
|
int found = FALSE;
|
|
|
|
if (y_search==0) {
|
|
*x = lmargin;
|
|
return;
|
|
}
|
|
|
|
y_search--;
|
|
while(1) {
|
|
while(x_search>=lmargin) {
|
|
if (xep80_data[y_search][x_search] == XEP80_ATARI_EOL) {
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
x_search--;
|
|
}
|
|
if (found)
|
|
break;
|
|
y_search--;
|
|
if (y_search < 0)
|
|
break;
|
|
x_search = rmargin;
|
|
}
|
|
|
|
*x = lmargin;
|
|
|
|
if (!found) {
|
|
*y = 0;
|
|
}
|
|
else {
|
|
*y = y_search + 1;
|
|
}
|
|
}
|
|
|
|
static void XEP80_BlitChar(int x, int y, int cur)
|
|
{
|
|
int screen_col;
|
|
int font_row, font_col;
|
|
UBYTE *from, *to;
|
|
UBYTE ch;
|
|
UBYTE on, off, blink;
|
|
int font_index, font_double, font_blank, font_blink;
|
|
int blink_rev;
|
|
int last_double_cur = FALSE;
|
|
|
|
/* Don't Blit characters that aren't on the screen at the moment. */
|
|
if (x < xscroll || x >= xscroll + XEP80_LINE_LEN)
|
|
return;
|
|
|
|
screen_col = x-xscroll;
|
|
ch = xep80_data[y][x];
|
|
|
|
/* Dispaly Atari EOL's as spaces */
|
|
if (ch == XEP80_ATARI_EOL && ((font_a_index & XEP80_FONTS_BLK_FONT_BIT) == 0)
|
|
&& char_set != CHAR_SET_INTERNAL)
|
|
ch = 0x20;
|
|
|
|
if (ch & 0x80) {
|
|
font_index = font_b_index;
|
|
font_double = font_b_double;
|
|
font_blank = font_b_blank;
|
|
font_blink = font_b_blink;
|
|
}
|
|
else {
|
|
font_index = font_a_index;
|
|
font_double = font_a_double;
|
|
font_blank = font_a_blank;
|
|
font_blink = font_a_blink;
|
|
}
|
|
|
|
if (font_blink && blink_reverse && (font_index & XEP80_FONTS_REV_FONT_BIT)) {
|
|
blink_rev = TRUE;
|
|
}
|
|
else {
|
|
blink_rev = FALSE;
|
|
}
|
|
|
|
if (inverse_mode) {
|
|
font_index ^= XEP80_FONTS_REV_FONT_BIT;
|
|
}
|
|
|
|
if (ch==XEP80_ATARI_EOL) {
|
|
if (inverse_mode) {
|
|
font_index |= XEP80_FONTS_REV_FONT_BIT;
|
|
}
|
|
else {
|
|
font_index &= ~XEP80_FONTS_REV_FONT_BIT;
|
|
}
|
|
}
|
|
|
|
/* Skip the charcter if the last one was a displayed double */
|
|
if (screen_col != 0 && !cur) {
|
|
if (IS_DOUBLE(x-1,y)) {
|
|
int firstd;
|
|
|
|
firstd = x-1;
|
|
while (firstd > xscroll) {
|
|
if (!IS_DOUBLE(firstd,y)) {
|
|
firstd++;
|
|
break;
|
|
}
|
|
firstd--;
|
|
}
|
|
if ((x-firstd) % 2)
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Check if we are doing a cursor, and the charcter before is double */
|
|
if (cur) {
|
|
if (screen_col != 0) {
|
|
if (IS_DOUBLE(x-1,y))
|
|
last_double_cur = TRUE;
|
|
}
|
|
}
|
|
|
|
if (y*XEP80_CHAR_HEIGHT < XEP80_first_row)
|
|
XEP80_first_row = y*XEP80_CHAR_HEIGHT;
|
|
if (y*XEP80_CHAR_HEIGHT + XEP80_CHAR_HEIGHT - 1 > XEP80_last_row)
|
|
XEP80_last_row = y*XEP80_CHAR_HEIGHT + XEP80_CHAR_HEIGHT - 1;
|
|
|
|
if (inverse_mode) {
|
|
on = XEP80_FONTS_offcolor;
|
|
off = XEP80_FONTS_oncolor;
|
|
}
|
|
else {
|
|
on = XEP80_FONTS_oncolor;
|
|
off = XEP80_FONTS_offcolor;
|
|
}
|
|
|
|
if (font_index & XEP80_FONTS_REV_FONT_BIT) {
|
|
blink = on;
|
|
}
|
|
else {
|
|
blink = off;
|
|
}
|
|
|
|
if (font_blank) {
|
|
UBYTE color;
|
|
|
|
to = &XEP80_screen_1[XEP80_SCRN_WIDTH * XEP80_CHAR_HEIGHT * y +
|
|
screen_col * XEP80_CHAR_WIDTH];
|
|
for (font_row=0;font_row < XEP80_CHAR_HEIGHT; font_row++) {
|
|
if (cur || (font_index & XEP80_FONTS_REV_FONT_BIT)) {
|
|
color = on;
|
|
}
|
|
else {
|
|
color = off;
|
|
}
|
|
|
|
for (font_col=0; font_col < XEP80_CHAR_WIDTH; font_col++) {
|
|
if (font_double)
|
|
*to++ = color;
|
|
*to++ = color;
|
|
}
|
|
if (font_double)
|
|
to += XEP80_SCRN_WIDTH - 2*XEP80_CHAR_WIDTH;
|
|
else
|
|
to += XEP80_SCRN_WIDTH - 1*XEP80_CHAR_WIDTH;
|
|
}
|
|
|
|
to = &XEP80_screen_2[XEP80_SCRN_WIDTH * XEP80_CHAR_HEIGHT * y +
|
|
screen_col * XEP80_CHAR_WIDTH];
|
|
for (font_row=0;font_row < XEP80_CHAR_HEIGHT; font_row++) {
|
|
if ((cur && !cursor_blink) || (font_index & XEP80_FONTS_REV_FONT_BIT)) {
|
|
color = on;
|
|
}
|
|
else {
|
|
color = off;
|
|
}
|
|
|
|
for (font_col=0; font_col < XEP80_CHAR_WIDTH; font_col++) {
|
|
if (font_double)
|
|
*to++ = color;
|
|
*to++ = color;
|
|
}
|
|
if (font_double)
|
|
to += XEP80_SCRN_WIDTH - 2*XEP80_CHAR_WIDTH;
|
|
else
|
|
to += XEP80_SCRN_WIDTH - 1*XEP80_CHAR_WIDTH;
|
|
}
|
|
}
|
|
else if (font_double && !cur) {
|
|
int width;
|
|
|
|
if (screen_col == 79)
|
|
width = XEP80_CHAR_WIDTH/2;
|
|
else
|
|
width = XEP80_CHAR_WIDTH;
|
|
|
|
to = &XEP80_screen_1[XEP80_SCRN_WIDTH * XEP80_CHAR_HEIGHT * y +
|
|
screen_col * XEP80_CHAR_WIDTH];
|
|
for (font_row=0;font_row < XEP80_CHAR_HEIGHT; font_row++) {
|
|
from = XEP80_FONTS_atari_fonts[char_set][font_index][ch][font_row];
|
|
|
|
for (font_col=0; font_col < width; font_col++) {
|
|
*to++ = *from;
|
|
*to++ = *from++;
|
|
}
|
|
to += XEP80_SCRN_WIDTH - 2*XEP80_CHAR_WIDTH;
|
|
}
|
|
|
|
to = &XEP80_screen_2[XEP80_SCRN_WIDTH * XEP80_CHAR_HEIGHT * y +
|
|
screen_col * XEP80_CHAR_WIDTH];
|
|
for (font_row=0;font_row < XEP80_CHAR_HEIGHT; font_row++) {
|
|
if (blink_rev)
|
|
from = XEP80_FONTS_atari_fonts[char_set][font_index ^ XEP80_FONTS_REV_FONT_BIT][ch][font_row];
|
|
else
|
|
from = XEP80_FONTS_atari_fonts[char_set][font_index][ch][font_row];
|
|
|
|
for (font_col=0; font_col < width; font_col++) {
|
|
if (font_blink && !cur && !blink_rev) {
|
|
if ((font_index & XEP80_FONTS_UNDER_FONT_BIT) && font_row == XEP80_FONTS_UNDER_ROW) {
|
|
*to++ = *from;
|
|
*to++ = *from++;
|
|
}
|
|
else {
|
|
*to++ = blink;
|
|
*to++ = blink;
|
|
from++;
|
|
}
|
|
}
|
|
else {
|
|
*to++ = *from;
|
|
*to++ = *from++;
|
|
}
|
|
}
|
|
to += XEP80_SCRN_WIDTH - 2*XEP80_CHAR_WIDTH;
|
|
}
|
|
}
|
|
else if ((font_double || last_double_cur) && cur && !cursor_overwrite) {
|
|
int first_half, start_col, end_col;
|
|
|
|
/* Determine if this is a double first or second half */
|
|
if (screen_col == 0) {
|
|
first_half = TRUE;
|
|
} else {
|
|
if (IS_DOUBLE(x-1,y)) {
|
|
int firstd;
|
|
|
|
firstd = x-1;
|
|
while (firstd > xscroll) {
|
|
if (!IS_DOUBLE(firstd,y)) {
|
|
firstd++;
|
|
break;
|
|
}
|
|
firstd--;
|
|
}
|
|
first_half = (((x-firstd) % 2) == 0);
|
|
}
|
|
else {
|
|
first_half = TRUE;
|
|
}
|
|
}
|
|
|
|
if (first_half) {
|
|
start_col = 0;
|
|
end_col = 3;
|
|
}
|
|
else {
|
|
start_col = 3;
|
|
end_col = 6;
|
|
ch = xep80_data[y][x-1];
|
|
}
|
|
|
|
to = &XEP80_screen_1[XEP80_SCRN_WIDTH * XEP80_CHAR_HEIGHT * y +
|
|
screen_col * XEP80_CHAR_WIDTH];
|
|
for (font_row=0;font_row < XEP80_CHAR_HEIGHT; font_row++) {
|
|
from = XEP80_FONTS_atari_fonts[char_set][font_index ^ XEP80_FONTS_REV_FONT_BIT][ch][font_row] + start_col;
|
|
if (first_half)
|
|
*to++ = *from++;
|
|
for (font_col=start_col; font_col < end_col; font_col++) {
|
|
*to++ = *from;
|
|
*to++ = *from++;
|
|
}
|
|
if (!first_half)
|
|
*to++ = *from;
|
|
to += XEP80_SCRN_WIDTH - XEP80_CHAR_WIDTH;
|
|
}
|
|
to = &XEP80_screen_2[XEP80_SCRN_WIDTH * XEP80_CHAR_HEIGHT * y +
|
|
screen_col * XEP80_CHAR_WIDTH];
|
|
for (font_row=0;font_row < XEP80_CHAR_HEIGHT; font_row++) {
|
|
if (!cursor_blink) {
|
|
from = XEP80_FONTS_atari_fonts[char_set][font_index ^ XEP80_FONTS_REV_FONT_BIT][ch][font_row] + start_col;
|
|
}
|
|
else {
|
|
from = XEP80_FONTS_atari_fonts[char_set][font_index][ch][font_row] + start_col;
|
|
}
|
|
if (first_half)
|
|
*to++ = *from++;
|
|
for (font_col=start_col; font_col < end_col; font_col++) {
|
|
*to++ = *from;
|
|
*to++ = *from++;
|
|
}
|
|
if (!first_half)
|
|
*to++ = *from;
|
|
to += XEP80_SCRN_WIDTH - XEP80_CHAR_WIDTH;
|
|
}
|
|
}
|
|
else {
|
|
to = &XEP80_screen_1[XEP80_SCRN_WIDTH * XEP80_CHAR_HEIGHT * y +
|
|
screen_col * XEP80_CHAR_WIDTH];
|
|
if (cur & cursor_overwrite) {
|
|
for (font_row=0;font_row < XEP80_CHAR_HEIGHT; font_row++) {
|
|
for (font_col=0; font_col < XEP80_CHAR_WIDTH; font_col++) {
|
|
*to++ = on;
|
|
}
|
|
to += XEP80_SCRN_WIDTH - XEP80_CHAR_WIDTH;
|
|
}
|
|
}
|
|
else {
|
|
for (font_row=0;font_row < XEP80_CHAR_HEIGHT; font_row++) {
|
|
if (cur) {
|
|
from = XEP80_FONTS_atari_fonts[char_set][font_index ^ XEP80_FONTS_REV_FONT_BIT][ch][font_row];
|
|
}
|
|
else {
|
|
from = XEP80_FONTS_atari_fonts[char_set][font_index][ch][font_row];
|
|
}
|
|
|
|
for (font_col=0; font_col < XEP80_CHAR_WIDTH; font_col++) {
|
|
*to++ = *from++;
|
|
}
|
|
to += XEP80_SCRN_WIDTH - XEP80_CHAR_WIDTH;
|
|
}
|
|
}
|
|
|
|
to = &XEP80_screen_2[XEP80_SCRN_WIDTH * XEP80_CHAR_HEIGHT * y +
|
|
screen_col * XEP80_CHAR_WIDTH];
|
|
if (cur & cursor_overwrite) {
|
|
if (cursor_blink) {
|
|
for (font_row=0;font_row < XEP80_CHAR_HEIGHT; font_row++) {
|
|
for (font_col=0; font_col < XEP80_CHAR_WIDTH; font_col++) {
|
|
*to++ = off;
|
|
}
|
|
to += XEP80_SCRN_WIDTH - XEP80_CHAR_WIDTH;
|
|
}
|
|
}
|
|
else {
|
|
for (font_row=0;font_row < XEP80_CHAR_HEIGHT; font_row++) {
|
|
for (font_col=0; font_col < XEP80_CHAR_WIDTH; font_col++) {
|
|
*to++ = on;
|
|
}
|
|
to += XEP80_SCRN_WIDTH - XEP80_CHAR_WIDTH;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (font_row=0;font_row < XEP80_CHAR_HEIGHT; font_row++) {
|
|
if (cur && !cursor_blink) {
|
|
from = XEP80_FONTS_atari_fonts[char_set][font_index ^ XEP80_FONTS_REV_FONT_BIT][ch][font_row];
|
|
}
|
|
else {
|
|
if (blink_rev)
|
|
from = XEP80_FONTS_atari_fonts[char_set][font_index ^ XEP80_FONTS_REV_FONT_BIT][ch][font_row];
|
|
else
|
|
from = XEP80_FONTS_atari_fonts[char_set][font_index][ch][font_row];
|
|
}
|
|
for (font_col=0; font_col < XEP80_CHAR_WIDTH; font_col++) {
|
|
if (font_blink && !cur) {
|
|
if ((font_index & XEP80_FONTS_UNDER_FONT_BIT) && font_row == XEP80_FONTS_UNDER_ROW) {
|
|
*to++ = *from++;
|
|
}
|
|
else {
|
|
*to++ = blink;
|
|
from++;
|
|
}
|
|
}
|
|
else {
|
|
*to++ = *from++;
|
|
}
|
|
}
|
|
to += XEP80_SCRN_WIDTH - XEP80_CHAR_WIDTH;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void XEP80_BlitScreen(void)
|
|
{
|
|
int screen_row, screen_col;
|
|
|
|
for (screen_row = 0; screen_row < XEP80_HEIGHT; screen_row++) {
|
|
for (screen_col = xscroll; screen_col < xscroll + XEP80_LINE_LEN;
|
|
screen_col++) {
|
|
XEP80_BlitChar(screen_col, screen_row, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void XEP80_BlitRows(int y_start, int y_end)
|
|
{
|
|
int screen_row, screen_col;
|
|
|
|
for (screen_row = y_start; screen_row <= y_end; screen_row++) {
|
|
for (screen_col = xscroll; screen_col < xscroll + XEP80_LINE_LEN;
|
|
screen_col++) {
|
|
XEP80_BlitChar(screen_col, screen_row, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void XEP80_BlitGraphChar(int x, int y)
|
|
{
|
|
int graph_col;
|
|
UBYTE *to1,*to2;
|
|
UBYTE ch;
|
|
UBYTE on, off;
|
|
|
|
if (inverse_mode) {
|
|
on = XEP80_FONTS_offcolor;
|
|
off = XEP80_FONTS_oncolor;
|
|
}
|
|
else {
|
|
on = XEP80_FONTS_oncolor;
|
|
off = XEP80_FONTS_offcolor;
|
|
}
|
|
|
|
if (y + XEP80_GRAPH_Y_OFFSET < XEP80_first_row)
|
|
XEP80_first_row = y + XEP80_GRAPH_Y_OFFSET;
|
|
if (y + XEP80_GRAPH_Y_OFFSET > XEP80_last_row)
|
|
XEP80_last_row = y + XEP80_GRAPH_Y_OFFSET;
|
|
|
|
ch = xep80_graph_data[y][x];
|
|
|
|
to1 = &XEP80_screen_1[XEP80_SCRN_WIDTH * (y + XEP80_GRAPH_Y_OFFSET)
|
|
+ x * 8 + XEP80_GRAPH_X_OFFSET];
|
|
to2 = &XEP80_screen_2[XEP80_SCRN_WIDTH * (y + XEP80_GRAPH_Y_OFFSET)
|
|
+ x * 8 + XEP80_GRAPH_X_OFFSET];
|
|
|
|
for (graph_col=7; graph_col >= 0; graph_col--) {
|
|
if (ch & (1<<graph_col)) {
|
|
*to1++ = on;
|
|
*to2++ = on;
|
|
}
|
|
else {
|
|
*to1++ = off;
|
|
*to2++ = off;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void XEP80_BlitGraphScreen(void)
|
|
{
|
|
int x, y;
|
|
|
|
for (x=0; x<XEP80_GRAPH_WIDTH/8; x++)
|
|
for (y=0; y<XEP80_GRAPH_HEIGHT; y++)
|
|
XEP80_BlitGraphChar(x,y);
|
|
}
|
|
|
|
void XEP80_ChangeColors(void)
|
|
{
|
|
XEP80_FONTS_InitFonts();
|
|
if (graphics_mode)
|
|
XEP80_BlitGraphScreen();
|
|
else {
|
|
XEP80_BlitScreen();
|
|
XEP80_BlitChar(xcur, ycur, TRUE);
|
|
}
|
|
}
|
|
|
|
void XEP80_StateSave(void)
|
|
{
|
|
StateSav_SaveINT(&XEP80_enabled, 1);
|
|
if (XEP80_enabled) {
|
|
StateSav_SaveINT(&XEP80_port, 1);
|
|
StateSav_SaveINT(&PLATFORM_xep80, 1);
|
|
StateSav_SaveINT(&output_state, 1);
|
|
StateSav_SaveINT(&output_word, 1);
|
|
StateSav_SaveINT(&input_count, 1);
|
|
StateSav_SaveINT(&input_bit, 1);
|
|
StateSav_SaveUWORD(input_queue, IN_QUEUE_SIZE);
|
|
StateSav_SaveINT(&input_first, 1);
|
|
StateSav_SaveINT(&input_first, 1);
|
|
|
|
StateSav_SaveINT(&xcur, 1);
|
|
StateSav_SaveINT(&xscroll, 1);
|
|
StateSav_SaveINT(&ycur, 1);
|
|
StateSav_SaveINT(&new_xcur, 1);
|
|
StateSav_SaveINT(&new_ycur, 1);
|
|
StateSav_SaveINT(&old_xcur, 1);
|
|
StateSav_SaveINT(&old_ycur, 1);
|
|
StateSav_SaveINT(&lmargin, 1);
|
|
StateSav_SaveINT(&rmargin, 1);
|
|
StateSav_SaveUBYTE(&attrib_a, 1);
|
|
StateSav_SaveUBYTE(&attrib_b, 1);
|
|
StateSav_SaveINT(&list_mode, 1);
|
|
StateSav_SaveINT(&char_set, 1);
|
|
StateSav_SaveINT(&cursor_on, 1);
|
|
StateSav_SaveINT(&cursor_blink, 1);
|
|
StateSav_SaveINT(&cursor_overwrite, 1);
|
|
StateSav_SaveINT(&blink_reverse, 1);
|
|
StateSav_SaveINT(&inverse_mode, 1);
|
|
StateSav_SaveINT(&screen_output, 1);
|
|
StateSav_SaveINT(&burst_mode, 1);
|
|
StateSav_SaveINT(&graphics_mode, 1);
|
|
StateSav_SaveINT(&pal_mode, 1);
|
|
StateSav_SaveINT(&font_a_index, 1);
|
|
StateSav_SaveINT(&font_a_double, 1);
|
|
StateSav_SaveINT(&font_a_blank, 1);
|
|
StateSav_SaveINT(&font_a_blink, 1);
|
|
StateSav_SaveINT(&font_b_index, 1);
|
|
StateSav_SaveINT(&font_b_double, 1);
|
|
StateSav_SaveINT(&font_b_blank, 1);
|
|
StateSav_SaveINT(&font_b_blink, 1);
|
|
StateSav_SaveUBYTE(&xep80_data[0][0], XEP80_HEIGHT * XEP80_WIDTH);
|
|
StateSav_SaveUBYTE(&xep80_graph_data[0][0], XEP80_GRAPH_HEIGHT*XEP80_GRAPH_WIDTH/8);
|
|
}
|
|
}
|
|
|
|
void XEP80_StateRead(void)
|
|
{
|
|
int local_xep80_enabled = 0;
|
|
int local_xep80 = 0;
|
|
|
|
/* test for end of file */
|
|
StateSav_ReadINT(&local_xep80_enabled, 1);
|
|
if (local_xep80_enabled) {
|
|
StateSav_ReadINT(&XEP80_port, 1);
|
|
StateSav_ReadINT(&local_xep80, 1);
|
|
StateSav_ReadINT(&output_state, 1);
|
|
StateSav_ReadINT(&output_word, 1);
|
|
StateSav_ReadINT(&input_count, 1);
|
|
StateSav_ReadINT(&input_bit, 1);
|
|
StateSav_ReadUWORD(input_queue, IN_QUEUE_SIZE);
|
|
StateSav_ReadINT(&input_first, 1);
|
|
StateSav_ReadINT(&input_first, 1);
|
|
|
|
StateSav_ReadINT(&xcur, 1);
|
|
StateSav_ReadINT(&xscroll, 1);
|
|
StateSav_ReadINT(&ycur, 1);
|
|
StateSav_ReadINT(&new_xcur, 1);
|
|
StateSav_ReadINT(&new_ycur, 1);
|
|
StateSav_ReadINT(&old_xcur, 1);
|
|
StateSav_ReadINT(&old_ycur, 1);
|
|
StateSav_ReadINT(&lmargin, 1);
|
|
StateSav_ReadINT(&rmargin, 1);
|
|
StateSav_ReadUBYTE(&attrib_a, 1);
|
|
StateSav_ReadUBYTE(&attrib_b, 1);
|
|
StateSav_ReadINT(&list_mode, 1);
|
|
StateSav_ReadINT(&char_set, 1);
|
|
StateSav_ReadINT(&cursor_on, 1);
|
|
StateSav_ReadINT(&cursor_blink, 1);
|
|
StateSav_ReadINT(&cursor_overwrite, 1);
|
|
StateSav_ReadINT(&blink_reverse, 1);
|
|
StateSav_ReadINT(&inverse_mode, 1);
|
|
StateSav_ReadINT(&screen_output, 1);
|
|
StateSav_ReadINT(&burst_mode, 1);
|
|
StateSav_ReadINT(&graphics_mode, 1);
|
|
StateSav_ReadINT(&pal_mode, 1);
|
|
StateSav_ReadINT(&font_a_index, 1);
|
|
StateSav_ReadINT(&font_a_double, 1);
|
|
StateSav_ReadINT(&font_a_blank, 1);
|
|
StateSav_ReadINT(&font_a_blink, 1);
|
|
StateSav_ReadINT(&font_b_index, 1);
|
|
StateSav_ReadINT(&font_b_double, 1);
|
|
StateSav_ReadINT(&font_b_blank, 1);
|
|
StateSav_ReadINT(&font_b_blink, 1);
|
|
StateSav_ReadUBYTE(&xep80_data[0][0], XEP80_HEIGHT * XEP80_WIDTH);
|
|
StateSav_ReadUBYTE(&xep80_graph_data[0][0], XEP80_GRAPH_HEIGHT*XEP80_GRAPH_WIDTH/8);
|
|
if (!XEP80_FONTS_inited)
|
|
XEP80_FONTS_InitFonts();
|
|
if (graphics_mode)
|
|
XEP80_BlitGraphScreen();
|
|
else {
|
|
XEP80_BlitScreen();
|
|
XEP80_BlitChar(xcur, ycur, TRUE);
|
|
}
|
|
XEP80_enabled = TRUE;
|
|
/* not correct for SDL version */
|
|
#if 0
|
|
if (PLATFORM_xep80 != local_xep80)
|
|
PLATFORM_SwitchXep80();
|
|
#endif
|
|
PLATFORM_xep80 = local_xep80;
|
|
}
|
|
else {
|
|
XEP80_enabled = FALSE;
|
|
/* not correct for SDL version */
|
|
#if 0
|
|
if (PLATFORM_xep80)
|
|
PLATFORM_SwitchXep80();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#endif /* XEP80 */
|
|
|
|
/*
|
|
vim:ts=4:sw=4:
|
|
*/
|
|
|