mirror of
https://github.com/david-schmidt/gsport.git
synced 2024-11-15 14:11:28 +00:00
3675 lines
90 KiB
C
3675 lines
90 KiB
C
/*
|
|
GSport - an Apple //gs Emulator
|
|
Copyright (C) 2010 - 2012 by GSport contributors
|
|
|
|
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
|
|
|
|
This program 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.
|
|
|
|
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <time.h>
|
|
|
|
#include "defc.h"
|
|
|
|
extern int Verbose;
|
|
|
|
int g_a2_line_stat[200];
|
|
int g_a2_line_left_edge[200];
|
|
int g_a2_line_right_edge[200];
|
|
Kimage *g_a2_line_kimage[200];
|
|
|
|
int g_mode_text[2][200];
|
|
int g_mode_hires[2][200];
|
|
int g_mode_superhires[200];
|
|
int g_mode_border[200];
|
|
|
|
byte g_cur_border_colors[270];
|
|
byte g_new_special_border[64][64];
|
|
byte g_cur_special_border[64][64];
|
|
|
|
word32 g_a2_screen_buffer_changed = (word32)-1;
|
|
word32 g_full_refresh_needed = (word32)-1;
|
|
|
|
word32 g_cycs_in_40col = 0;
|
|
word32 g_cycs_in_xredraw = 0;
|
|
word32 g_refresh_bytes_xfer = 0;
|
|
|
|
extern byte *g_slow_memory_ptr;
|
|
extern int g_screen_depth;
|
|
extern int g_screen_mdepth;
|
|
|
|
extern double g_cur_dcycs;
|
|
|
|
extern int g_line_ref_amt;
|
|
|
|
extern int g_c034_val;
|
|
extern int g_config_control_panel;
|
|
|
|
typedef byte Change;
|
|
|
|
word32 slow_mem_changed[SLOW_MEM_CH_SIZE];
|
|
|
|
word32 g_font40_even_bits[0x100][8][16/4];
|
|
word32 g_font40_odd_bits[0x100][8][16/4];
|
|
word32 g_font80_off0_bits[0x100][8][12/4];
|
|
word32 g_font80_off1_bits[0x100][8][12/4];
|
|
word32 g_font80_off2_bits[0x100][8][12/4];
|
|
word32 g_font80_off3_bits[0x100][8][12/4];
|
|
|
|
word32 g_superhires_scan_save[256];
|
|
|
|
Kimage g_kimage_text[2];
|
|
Kimage g_kimage_hires[2];
|
|
Kimage g_kimage_superhires;
|
|
Kimage g_kimage_border_special;
|
|
Kimage g_kimage_border_sides;
|
|
|
|
Kimage g_mainwin_kimage;
|
|
|
|
extern double g_last_vbl_dcycs;
|
|
|
|
double g_video_dcycs_check_input = 0.0;
|
|
int g_video_extra_check_inputs = 0; // OG Not recommended to use it (or apps might miss mouse changes)
|
|
int g_video_act_margin_left = BASE_MARGIN_LEFT;
|
|
int g_video_act_margin_right = BASE_MARGIN_RIGHT;
|
|
int g_video_act_margin_top = BASE_MARGIN_TOP;
|
|
int g_video_act_margin_bottom = BASE_MARGIN_BOTTOM;
|
|
int g_video_act_width = X_A2_WINDOW_WIDTH;
|
|
int g_video_act_height = X_A2_WINDOW_HEIGHT;
|
|
|
|
int g_need_redraw = 1;
|
|
int g_palette_change_summary = 0;
|
|
word32 g_palette_change_cnt[16];
|
|
int g_border_sides_refresh_needed = 1;
|
|
int g_border_special_refresh_needed = 1;
|
|
int g_border_line24_refresh_needed = 1;
|
|
int g_status_refresh_needed = 1;
|
|
|
|
int g_vbl_border_color = 0;
|
|
int g_border_last_vbl_changes = 0;
|
|
|
|
int g_use_dhr140 = 0;
|
|
int g_use_bw_hires = 0;
|
|
|
|
int g_a2_new_all_stat[200];
|
|
int g_a2_cur_all_stat[200];
|
|
int g_new_a2_stat_cur_line = 0;
|
|
int g_vid_update_last_line = 0;
|
|
|
|
int g_expanded_col_0[16];
|
|
int g_expanded_col_1[16];
|
|
int g_expanded_col_2[16];
|
|
|
|
|
|
int g_cur_a2_stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 |
|
|
(0xf << BIT_ALL_STAT_TEXT_COLOR);
|
|
extern int g_save_cur_a2_stat; /* from config.c */
|
|
|
|
int g_a2vid_palette = 0xe;
|
|
int g_installed_full_superhires_colormap = 0;
|
|
|
|
int Max_color_size = 256;
|
|
|
|
word32 g_palette_8to1624[256];
|
|
word32 g_a2palette_8to1624[256];
|
|
|
|
word32 g_saved_line_palettes[200][8];
|
|
int g_saved_a2vid_palette = -1;
|
|
word32 g_a2vid_palette_remap[16];
|
|
|
|
word32 g_cycs_in_refresh_line = 0;
|
|
word32 g_cycs_in_refresh_ximage = 0;
|
|
|
|
int g_num_lines_superhires = 0;
|
|
int g_num_lines_superhires640 = 0;
|
|
int g_num_lines_prev_superhires = 0;
|
|
int g_num_lines_prev_superhires640 = 0;
|
|
|
|
word32 g_red_mask = 0xff;
|
|
word32 g_green_mask = 0xff;
|
|
word32 g_blue_mask = 0xff;
|
|
int g_red_left_shift = 16;
|
|
int g_green_left_shift = 8;
|
|
int g_blue_left_shift = 0;
|
|
int g_red_right_shift = 0;
|
|
int g_green_right_shift = 0;
|
|
int g_blue_right_shift = 0;
|
|
|
|
char g_status_buf[MAX_STATUS_LINES][STATUS_LINE_LENGTH + 1];
|
|
char *g_status_ptrs[MAX_STATUS_LINES] = { 0 };
|
|
|
|
const int g_dbhires_colors[] = {
|
|
/* rgb */
|
|
0x000, /* 0x0 black */
|
|
0xd03, /* 0x1 deep red */
|
|
0x852, /* 0x2 brown */
|
|
0xf60, /* 0x3 orange */
|
|
0x070, /* 0x4 dark green */
|
|
0x555, /* 0x5 dark gray */
|
|
0x0d0, /* 0x6 green */
|
|
0xff0, /* 0x7 yellow */
|
|
0x009, /* 0x8 dark blue */
|
|
0xd0d, /* 0x9 purple */
|
|
0xaaa, /* 0xa light gray */
|
|
0xf98, /* 0xb pink */
|
|
0x22f, /* 0xc medium blue */
|
|
0x6af, /* 0xd light blue */
|
|
0x0f9, /* 0xe aquamarine */
|
|
0xfff /* 0xf white */
|
|
};
|
|
|
|
word32 g_dhires_convert[4096]; /* look up table of 7 bits (concat): */
|
|
/* { 4 bits, |3 prev bits| } */
|
|
|
|
const byte g_dhires_colors_16[] = {
|
|
0x00, /* 0x0 black */
|
|
0x02, /* 0x1 dark blue */
|
|
0x04, /* 0x2 dark green */
|
|
0x06, /* 0x3 medium blue */
|
|
0x08, /* 0x4 brown */
|
|
0x0a, /* 0x5 light gray */
|
|
0x0c, /* 0x6 green */
|
|
0x0e, /* 0x7 aquamarine */
|
|
0x01, /* 0x8 deep red */
|
|
0x03, /* 0x9 purple */
|
|
0x05, /* 0xa dark gray */
|
|
0x07, /* 0xb light blue */
|
|
0x09, /* 0xc orange */
|
|
0x0b, /* 0xd pink */
|
|
0x0d, /* 0xe yellow */
|
|
0x0f/* 0xf white */
|
|
};
|
|
|
|
int g_lores_colors[] = {
|
|
/* rgb */
|
|
0x000, /* 0x0 black */
|
|
0xd03, /* 0x1 deep red */
|
|
0x009, /* 0x2 dark blue */
|
|
0xd0d, /* 0x3 purple */
|
|
0x070, /* 0x4 dark green */
|
|
0x555, /* 0x5 dark gray */
|
|
0x22f, /* 0x6 medium blue */
|
|
0x6af, /* 0x7 light blue */
|
|
0x852, /* 0x8 brown */
|
|
0xf60, /* 0x9 orange */
|
|
0xaaa, /* 0xa light gray */
|
|
0xf98, /* 0xb pink */
|
|
0x0d0, /* 0xc green */
|
|
0xff0, /* 0xd yellow */
|
|
0x0f9, /* 0xe aquamarine */
|
|
0xfff /* 0xf white */
|
|
};
|
|
|
|
const word32 g_bw_hires_convert[4] = {
|
|
BIGEND(0x00000000),
|
|
BIGEND(0x0f0f0000),
|
|
BIGEND(0x00000f0f),
|
|
BIGEND(0x0f0f0f0f)
|
|
};
|
|
|
|
const word32 g_bw_dhires_convert[16] = {
|
|
BIGEND(0x00000000),
|
|
BIGEND(0x0f000000),
|
|
BIGEND(0x000f0000),
|
|
BIGEND(0x0f0f0000),
|
|
|
|
BIGEND(0x00000f00),
|
|
BIGEND(0x0f000f00),
|
|
BIGEND(0x000f0f00),
|
|
BIGEND(0x0f0f0f00),
|
|
|
|
BIGEND(0x0000000f),
|
|
BIGEND(0x0f00000f),
|
|
BIGEND(0x000f000f),
|
|
BIGEND(0x0f0f000f),
|
|
|
|
BIGEND(0x00000f0f),
|
|
BIGEND(0x0f000f0f),
|
|
BIGEND(0x000f0f0f),
|
|
BIGEND(0x0f0f0f0f),
|
|
};
|
|
|
|
const word32 g_hires_convert[64] = {
|
|
BIGEND(0x00000000), /* 00,0000 = black, black, black, black */
|
|
BIGEND(0x00000000), /* 00,0001 = black, black, black, black */
|
|
BIGEND(0x03030000), /* 00,0010 = purp , purp , black, black */
|
|
BIGEND(0x0f0f0000), /* 00,0011 = white, white, black, black */
|
|
BIGEND(0x00000c0c), /* 00,0100 = black, black, green, green */
|
|
BIGEND(0x0c0c0c0c), /* 00,0101 = green, green, green, green */
|
|
BIGEND(0x0f0f0f0f), /* 00,0110 = white, white, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 00,0111 = white, white, white, white */
|
|
BIGEND(0x00000000), /* 00,1000 = black, black, black, black */
|
|
BIGEND(0x00000000), /* 00,1001 = black, black, black, black */
|
|
BIGEND(0x03030303), /* 00,1010 = purp , purp , purp , purp */
|
|
BIGEND(0x0f0f0303), /* 00,1011 = white ,white, purp , purp */
|
|
BIGEND(0x00000f0f), /* 00,1100 = black ,black, white, white */
|
|
BIGEND(0x0c0c0f0f), /* 00,1101 = green ,green, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 00,1110 = white ,white, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 00,1111 = white ,white, white, white */
|
|
|
|
BIGEND(0x00000000), /* 01,0000 = black, black, black, black */
|
|
BIGEND(0x00000000), /* 01,0001 = black, black, black, black */
|
|
BIGEND(0x06060000), /* 01,0010 = blue , blue , black, black */
|
|
BIGEND(0x0f0f0000), /* 01,0011 = white, white, black, black */
|
|
BIGEND(0x00000c0c), /* 01,0100 = black, black, green, green */
|
|
BIGEND(0x09090c0c), /* 01,0101 = orang, orang, green, green */
|
|
BIGEND(0x0f0f0f0f), /* 01,0110 = white, white, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 01,0111 = white, white, white, white */
|
|
BIGEND(0x00000000), /* 01,1000 = black, black, black, black */
|
|
BIGEND(0x00000000), /* 01,1001 = black, black, black, black */
|
|
BIGEND(0x06060303), /* 01,1010 = blue , blue , purp , purp */
|
|
BIGEND(0x0f0f0303), /* 01,1011 = white ,white, purp , purp */
|
|
BIGEND(0x00000f0f), /* 01,1100 = black ,black, white, white */
|
|
BIGEND(0x09090f0f), /* 01,1101 = orang ,orang, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 01,1110 = white ,white, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 01,1111 = white ,white, white, white */
|
|
|
|
BIGEND(0x00000000), /* 10,0000 = black, black, black, black */
|
|
BIGEND(0x00000000), /* 10,0001 = black, black, black, black */
|
|
BIGEND(0x03030000), /* 10,0010 = purp , purp , black, black */
|
|
BIGEND(0x0f0f0000), /* 10,0011 = white, white, black, black */
|
|
BIGEND(0x00000909), /* 10,0100 = black, black, orang, orang */
|
|
BIGEND(0x0c0c0909), /* 10,0101 = green, green, orang, orang */
|
|
BIGEND(0x0f0f0f0f), /* 10,0110 = white, white, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 10,0111 = white, white, white, white */
|
|
BIGEND(0x00000000), /* 10,1000 = black, black, black, black */
|
|
BIGEND(0x00000000), /* 10,1001 = black, black, black, black */
|
|
BIGEND(0x03030606), /* 10,1010 = purp , purp , blue , blue */
|
|
BIGEND(0x0f0f0606), /* 10,1011 = white ,white, blue , blue */
|
|
BIGEND(0x00000f0f), /* 10,1100 = black ,black, white, white */
|
|
BIGEND(0x0c0c0f0f), /* 10,1101 = green ,green, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 10,1110 = white ,white, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 10,1111 = white ,white, white, white */
|
|
|
|
BIGEND(0x00000000), /* 11,0000 = black, black, black, black */
|
|
BIGEND(0x00000000), /* 11,0001 = black, black, black, black */
|
|
BIGEND(0x06060000), /* 11,0010 = blue , blue , black, black */
|
|
BIGEND(0x0f0f0000), /* 11,0011 = white, white, black, black */
|
|
BIGEND(0x00000909), /* 11,0100 = black, black, orang, orang */
|
|
BIGEND(0x09090909), /* 11,0101 = orang, orang, orang, orang */
|
|
BIGEND(0x0f0f0f0f), /* 11,0110 = white, white, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 11,0111 = white, white, white, white */
|
|
BIGEND(0x00000000), /* 11,1000 = black, black, black, black */
|
|
BIGEND(0x00000000), /* 11,1001 = black, black, black, black */
|
|
BIGEND(0x06060606), /* 11,1010 = blue , blue , blue , blue */
|
|
BIGEND(0x0f0f0606), /* 11,1011 = white ,white, blue , blue */
|
|
BIGEND(0x00000f0f), /* 11,1100 = black ,black, white, white */
|
|
BIGEND(0x09090f0f), /* 11,1101 = orang ,orang, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 11,1110 = white ,white, white, white */
|
|
BIGEND(0x0f0f0f0f), /* 11,1111 = white ,white, white, white */
|
|
};
|
|
|
|
int g_screen_index[] = {
|
|
0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380,
|
|
0x028, 0x0a8, 0x128, 0x1a8, 0x228, 0x2a8, 0x328, 0x3a8,
|
|
0x050, 0x0d0, 0x150, 0x1d0, 0x250, 0x2d0, 0x350, 0x3d0
|
|
};
|
|
|
|
|
|
void
|
|
video_init()
|
|
{
|
|
word32 col[4];
|
|
Kimage *kimage_ptr;
|
|
word32 *ptr;
|
|
word32 val0, val1, val2, val3;
|
|
word32 match_col;
|
|
word32 next_col, next2_col, next3_col;
|
|
word32 val;
|
|
word32 cur_col;
|
|
int width, height;
|
|
int total_bytes;
|
|
int i, j;
|
|
/* Initialize video system */
|
|
|
|
// OG Reinit globals
|
|
g_a2_screen_buffer_changed = (word32)-1;
|
|
g_full_refresh_needed = (word32)-1;
|
|
g_cycs_in_40col = 0;
|
|
g_cycs_in_xredraw = 0;
|
|
g_refresh_bytes_xfer = 0;
|
|
|
|
g_video_dcycs_check_input = 0.0;
|
|
//g_video_extra_check_inputs = 0;
|
|
g_video_act_margin_left = BASE_MARGIN_LEFT;
|
|
g_video_act_margin_right = BASE_MARGIN_RIGHT;
|
|
g_video_act_margin_top = BASE_MARGIN_TOP;
|
|
g_video_act_margin_bottom = BASE_MARGIN_BOTTOM;
|
|
g_video_act_width = X_A2_WINDOW_WIDTH;
|
|
g_video_act_height = X_A2_WINDOW_HEIGHT;
|
|
|
|
g_need_redraw = 1;
|
|
g_palette_change_summary = 0;
|
|
|
|
g_border_sides_refresh_needed = 1;
|
|
g_border_special_refresh_needed = 1;
|
|
g_border_line24_refresh_needed = 1;
|
|
g_status_refresh_needed = 1;
|
|
|
|
g_vbl_border_color = 0;
|
|
g_border_last_vbl_changes = 0;
|
|
|
|
g_use_dhr140 = 0;
|
|
g_use_bw_hires = 0;
|
|
|
|
g_new_a2_stat_cur_line = 0;
|
|
g_vid_update_last_line = 0;
|
|
|
|
g_cur_a2_stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 |(0xf << BIT_ALL_STAT_TEXT_COLOR);
|
|
|
|
|
|
g_a2vid_palette = 0xe;
|
|
g_installed_full_superhires_colormap = 0;
|
|
|
|
Max_color_size = 256;
|
|
|
|
g_saved_a2vid_palette = -1;
|
|
|
|
g_cycs_in_refresh_line = 0;
|
|
g_cycs_in_refresh_ximage = 0;
|
|
|
|
g_num_lines_superhires = 0;
|
|
g_num_lines_superhires640 = 0;
|
|
g_num_lines_prev_superhires = 0;
|
|
g_num_lines_prev_superhires640 = 0;
|
|
|
|
/*
|
|
g_red_mask = 0xff;
|
|
g_green_mask = 0xff;
|
|
g_blue_mask = 0xff;
|
|
g_red_left_shift = 16;
|
|
g_green_left_shift = 8;
|
|
g_blue_left_shift = 0;
|
|
g_red_right_shift = 0;
|
|
g_green_right_shift = 0;
|
|
g_blue_right_shift = 0;
|
|
*/
|
|
|
|
/* Initialize video system */
|
|
|
|
for(i = 0; i < 200; i++) {
|
|
g_a2_line_kimage[i] = (Kimage *)0; // OG Changed from void* to kimage*
|
|
g_a2_line_stat[i] = -1;
|
|
g_a2_line_left_edge[i] = 0;
|
|
g_a2_line_right_edge[i] = 0;
|
|
}
|
|
for(i = 0; i < 200; i++) {
|
|
g_a2_new_all_stat[i] = 0;
|
|
g_a2_cur_all_stat[i] = 1;
|
|
for(j = 0; j < 8; j++) {
|
|
g_saved_line_palettes[i][j] = (word32)-1;
|
|
}
|
|
}
|
|
for(i = 0; i < 262; i++) {
|
|
g_cur_border_colors[i] = -1;
|
|
}
|
|
|
|
g_new_a2_stat_cur_line = 0;
|
|
|
|
dev_video_init();
|
|
|
|
read_a2_font();
|
|
|
|
vid_printf("Zeroing out video memory\n");
|
|
|
|
for(i = 0; i < 7; i++) {
|
|
switch(i) {
|
|
case 0:
|
|
kimage_ptr = &(g_kimage_text[0]);
|
|
break;
|
|
case 1:
|
|
kimage_ptr = &(g_kimage_text[1]);
|
|
break;
|
|
case 2:
|
|
kimage_ptr = &(g_kimage_hires[0]);
|
|
break;
|
|
case 3:
|
|
kimage_ptr = &(g_kimage_hires[1]);
|
|
break;
|
|
case 4:
|
|
kimage_ptr = &g_kimage_superhires;
|
|
break;
|
|
case 5:
|
|
kimage_ptr = &g_kimage_border_sides;
|
|
break;
|
|
case 6:
|
|
kimage_ptr = &g_kimage_border_special;
|
|
break;
|
|
default:
|
|
printf("i: %d, unknown\n", i);
|
|
exit(3);
|
|
}
|
|
|
|
ptr = (word32 *)kimage_ptr->data_ptr;
|
|
width = kimage_ptr->width_act;
|
|
height = kimage_ptr->height;
|
|
total_bytes = (kimage_ptr->mdepth >> 3) * width * height;
|
|
|
|
for(j = 0; j < total_bytes >> 2; j++) {
|
|
*ptr++ = 0;
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < SLOW_MEM_CH_SIZE; i++) {
|
|
slow_mem_changed[i] = (word32)-1;
|
|
}
|
|
|
|
/* create g_expanded_col_* */
|
|
for(i = 0; i < 16; i++) {
|
|
val = (g_lores_colors[i] >> 0) & 0xf;
|
|
g_expanded_col_0[i] = val;
|
|
|
|
val = (g_lores_colors[i] >> 4) & 0xf;
|
|
g_expanded_col_1[i] = val;
|
|
|
|
val = (g_lores_colors[i] >> 8) & 0xf;
|
|
g_expanded_col_2[i] = val;
|
|
}
|
|
|
|
/* create g_dhires_convert[] array */
|
|
for(i = 0; i < 4096; i++) {
|
|
/* Convert index bits 11:0 where 3:0 is the previous color */
|
|
/* and 7:4 is the current color to translate */
|
|
/* Bit 4 will be the first pixel displayed on the screen */
|
|
match_col = i & 0xf;
|
|
for(j = 0; j < 4; j++) {
|
|
cur_col = (i >> (1 + j)) & 0xf;
|
|
next_col = (i >> (2 + j)) & 0xf;
|
|
next2_col = (i >> (3 + j)) & 0xf;
|
|
next3_col = (i >> (4 + j)) & 0xf;
|
|
cur_col = (((cur_col << 4) + cur_col) >> (3 - j)) & 0xf;
|
|
|
|
if((cur_col == 0xf) || (next_col == 0xf) ||
|
|
(next2_col == 0xf) ||
|
|
(next3_col == 0xf)) {
|
|
cur_col = 0xf;
|
|
col[j] = cur_col;
|
|
match_col = cur_col;
|
|
} else if((cur_col == 0) || (next_col == 0) ||
|
|
(next2_col == 0) || (next3_col == 0)) {
|
|
cur_col = 0;
|
|
col[j] = cur_col;
|
|
match_col = cur_col;
|
|
} else {
|
|
col[j] = cur_col;
|
|
match_col = cur_col;
|
|
}
|
|
}
|
|
if(g_use_dhr140) {
|
|
for(j = 0; j < 4; j++) {
|
|
col[j] = (i >> 4) & 0xf;
|
|
}
|
|
}
|
|
val0 = g_dhires_colors_16[col[0] & 0xf];
|
|
val1 = g_dhires_colors_16[col[1] & 0xf];
|
|
val2 = g_dhires_colors_16[col[2] & 0xf];
|
|
val3 = g_dhires_colors_16[col[3] & 0xf];
|
|
#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
|
|
val = (val3 << 24) + (val2 << 16) + (val1 << 8) + val0;
|
|
#else
|
|
val = (val0 << 24) + (val1 << 16) + (val2 << 8) + val3;
|
|
#endif
|
|
g_dhires_convert[i] = val;
|
|
}
|
|
|
|
change_display_mode(g_cur_dcycs);
|
|
video_reset();
|
|
display_screen();
|
|
|
|
fflush(stdout);
|
|
}
|
|
|
|
void
|
|
show_a2_line_stuff()
|
|
{
|
|
int i;
|
|
|
|
for(i = 0; i < 200; i++) {
|
|
printf("line: %d: stat: %04x, ptr: %p, "
|
|
"left_edge:%d, right_edge:%d\n",
|
|
i, g_a2_line_stat[i], g_a2_line_kimage[i],
|
|
g_a2_line_left_edge[i],
|
|
g_a2_line_right_edge[i]);
|
|
}
|
|
|
|
printf("new_a2_stat_cur_line: %d, cur_a2_stat:%04x\n",
|
|
g_new_a2_stat_cur_line, g_cur_a2_stat);
|
|
for(i = 0; i < 200; i++) {
|
|
printf("cur_all[%d]: %03x new_all: %03x\n", i,
|
|
g_a2_cur_all_stat[i], g_a2_new_all_stat[i]);
|
|
}
|
|
|
|
}
|
|
|
|
int g_flash_count = 0;
|
|
|
|
void
|
|
video_reset()
|
|
{
|
|
int stat;
|
|
int i;
|
|
|
|
g_installed_full_superhires_colormap = (g_screen_depth != 8);
|
|
stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 |
|
|
(0xf << BIT_ALL_STAT_TEXT_COLOR);
|
|
if(g_use_bw_hires) {
|
|
stat |= ALL_STAT_COLOR_C021;
|
|
}
|
|
if(g_config_control_panel) {
|
|
/* Don't update cur_a2_stat when in configuration panel */
|
|
g_save_cur_a2_stat = stat;
|
|
} else {
|
|
g_cur_a2_stat = stat;
|
|
}
|
|
|
|
g_palette_change_summary = 0;
|
|
for(i = 0; i < 16; i++) {
|
|
g_palette_change_cnt[i] = 0;
|
|
}
|
|
|
|
/* install_a2vid_colormap(); */
|
|
video_update_colormap();
|
|
}
|
|
|
|
int g_screen_redraw_skip_count = 0;
|
|
int g_screen_redraw_skip_amt = -1;
|
|
|
|
word32 g_cycs_in_check_input = 0;
|
|
|
|
int g_needfullrefreshfornextframe = 1 ;
|
|
|
|
void video_update()
|
|
{
|
|
int did_video;
|
|
|
|
// OG g_needfullrefreshfornextframe
|
|
if (g_needfullrefreshfornextframe)
|
|
{
|
|
g_full_refresh_needed = -1;
|
|
g_a2_screen_buffer_changed = -1;
|
|
g_status_refresh_needed = 1;
|
|
g_border_sides_refresh_needed = 1;
|
|
g_border_special_refresh_needed = 1;
|
|
g_needfullrefreshfornextframe = 0;
|
|
}
|
|
|
|
|
|
update_border_info();
|
|
|
|
video_check_input_events();
|
|
|
|
g_screen_redraw_skip_count--;
|
|
did_video = 0;
|
|
if(g_screen_redraw_skip_count < 0) {
|
|
did_video = 1;
|
|
video_update_event_line(262);
|
|
g_screen_redraw_skip_count = g_screen_redraw_skip_amt;
|
|
}
|
|
|
|
/* update flash */
|
|
g_flash_count++;
|
|
if(g_flash_count >= 30) {
|
|
g_flash_count = 0;
|
|
g_cur_a2_stat ^= ALL_STAT_FLASH_STATE;
|
|
change_display_mode(g_cur_dcycs);
|
|
}
|
|
|
|
|
|
check_a2vid_palette();
|
|
|
|
|
|
if(did_video) {
|
|
g_new_a2_stat_cur_line = 0;
|
|
g_a2_new_all_stat[0] = g_cur_a2_stat;
|
|
g_vid_update_last_line = 0;
|
|
video_update_through_line(0);
|
|
}
|
|
|
|
|
|
// OG Notify host that video has been uodated
|
|
#if defined(ACTIVEGSPLUGIN) && defined(MAC)
|
|
{
|
|
extern void x_need2refresh();
|
|
x_need2refresh();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
int
|
|
video_all_stat_to_line_stat(int line, int new_all_stat)
|
|
{
|
|
int page, color, dbl;
|
|
int st80, hires, annunc3, mix_t_gr;
|
|
int altchar, text_color, bg_color, flash_state;
|
|
int mode;
|
|
|
|
st80 = new_all_stat & ALL_STAT_ST80;
|
|
hires = new_all_stat & ALL_STAT_HIRES;
|
|
annunc3 = new_all_stat & ALL_STAT_ANNUNC3;
|
|
mix_t_gr = new_all_stat & ALL_STAT_MIX_T_GR;
|
|
|
|
page = EXTRU(new_all_stat, 31 - BIT_ALL_STAT_PAGE2, 1) && !st80;
|
|
color = EXTRU(new_all_stat, 31 - BIT_ALL_STAT_COLOR_C021, 1);
|
|
dbl = EXTRU(new_all_stat, 31 - BIT_ALL_STAT_VID80, 1);
|
|
|
|
altchar = 0; text_color = 0; bg_color = 0; flash_state = 0;
|
|
|
|
if(new_all_stat & ALL_STAT_SUPER_HIRES) {
|
|
mode = MODE_SUPER_HIRES;
|
|
page = 0; dbl = 0; color = 0;
|
|
} else {
|
|
if(line >= 192) {
|
|
mode = MODE_BORDER;
|
|
page = 0; dbl = 0; color = 0;
|
|
} else if((new_all_stat & ALL_STAT_TEXT) ||
|
|
(line >= 160 && mix_t_gr)) {
|
|
mode = MODE_TEXT;
|
|
color = 0;
|
|
altchar = EXTRU(new_all_stat,
|
|
31 - BIT_ALL_STAT_ALTCHARSET, 1);
|
|
text_color = EXTRU(new_all_stat,
|
|
31 - BIT_ALL_STAT_TEXT_COLOR, 4);
|
|
bg_color = EXTRU(new_all_stat,
|
|
31 - BIT_ALL_STAT_BG_COLOR, 4);
|
|
flash_state = EXTRU(new_all_stat,
|
|
31 - BIT_ALL_STAT_FLASH_STATE, 1);
|
|
if(altchar) {
|
|
/* don't bother flashing if altchar on */
|
|
flash_state = 0;
|
|
}
|
|
} else {
|
|
/* obey the graphics mode */
|
|
dbl = dbl && !annunc3;
|
|
if(hires) {
|
|
color = color | EXTRU(new_all_stat,
|
|
31 - BIT_ALL_STAT_DIS_COLOR_DHIRES, 1);
|
|
mode = MODE_HGR;
|
|
} else {
|
|
mode = MODE_GR;
|
|
}
|
|
}
|
|
}
|
|
|
|
return((text_color << 12) + (bg_color << 8) + (altchar << 7) +
|
|
(mode << 4) + (flash_state << 3) + (page << 2) +
|
|
(color << 1) + dbl);
|
|
}
|
|
|
|
int *
|
|
video_update_kimage_ptr(int line, int new_stat)
|
|
{
|
|
Kimage *kimage_ptr;
|
|
int *mode_ptr;
|
|
int page;
|
|
int mode;
|
|
|
|
page = (new_stat >> 2) & 1;
|
|
mode = (new_stat >> 4) & 7;
|
|
|
|
switch(mode) {
|
|
case MODE_TEXT:
|
|
case MODE_GR:
|
|
kimage_ptr = &(g_kimage_text[page]);
|
|
mode_ptr = &(g_mode_text[page][0]);
|
|
break;
|
|
case MODE_HGR:
|
|
kimage_ptr = &(g_kimage_hires[page]);
|
|
mode_ptr = &(g_mode_hires[page][0]);
|
|
/* arrange to force superhires reparse since we use the */
|
|
/* same memory */
|
|
g_mode_superhires[line] = -1;
|
|
break;
|
|
case MODE_SUPER_HIRES:
|
|
kimage_ptr = &g_kimage_superhires;
|
|
mode_ptr = &(g_mode_superhires[0]);
|
|
/* arrange to force hires reparse since we use the */
|
|
/* same memory */
|
|
g_mode_hires[0][line] = -1;
|
|
g_mode_hires[1][line] = -1;
|
|
break;
|
|
case MODE_BORDER:
|
|
/* Hack: reuse text page last line as the special border */
|
|
kimage_ptr = &(g_kimage_text[0]);
|
|
mode_ptr = &(g_mode_border[0]);
|
|
break;
|
|
default:
|
|
halt_printf("update_a2_ptrs: mode: %d unknown!\n", mode);
|
|
return &(g_mode_superhires[0]);
|
|
}
|
|
|
|
g_a2_line_kimage[line] = kimage_ptr;
|
|
return mode_ptr;
|
|
}
|
|
|
|
void
|
|
change_a2vid_palette(int new_palette)
|
|
{
|
|
int i;
|
|
|
|
for(i = 0; i < 200; i++) {
|
|
g_mode_text[0][i] = -1;
|
|
g_mode_text[1][i] = -1;
|
|
g_mode_hires[0][i] = -1;
|
|
g_mode_hires[1][i] = -1;
|
|
g_mode_superhires[i] = -1;
|
|
g_mode_border[i] = -1;
|
|
}
|
|
|
|
printf("Changed a2vid_palette to %x\n", new_palette);
|
|
|
|
g_a2vid_palette = new_palette;
|
|
g_cur_a2_stat = (g_cur_a2_stat & (~ALL_STAT_A2VID_PALETTE)) +
|
|
(new_palette << BIT_ALL_STAT_A2VID_PALETTE);
|
|
change_display_mode(g_cur_dcycs);
|
|
|
|
g_border_sides_refresh_needed = 1;
|
|
g_border_special_refresh_needed = 1;
|
|
g_status_refresh_needed = 1;
|
|
g_palette_change_cnt[new_palette]++;
|
|
g_border_last_vbl_changes = 1;
|
|
for(i = 0; i < 262; i++) {
|
|
g_cur_border_colors[i] = -1;
|
|
}
|
|
}
|
|
|
|
int g_num_a2vid_palette_checks = 1;
|
|
int g_shr_palette_used[16];
|
|
|
|
void
|
|
check_a2vid_palette()
|
|
{
|
|
int sum;
|
|
int min;
|
|
int val;
|
|
int min_pos;
|
|
int count_cur;
|
|
int i;
|
|
|
|
/* determine if g_a2vid_palette should change */
|
|
/* This is the palette of least use on superhires so that the */
|
|
/* borders don't change when all 256 superhires colors are used */
|
|
|
|
g_num_a2vid_palette_checks--;
|
|
if(g_num_a2vid_palette_checks || g_installed_full_superhires_colormap){
|
|
return;
|
|
}
|
|
|
|
g_num_a2vid_palette_checks = 60;
|
|
|
|
sum = 0;
|
|
min = 0x100000;
|
|
min_pos = -1;
|
|
count_cur = g_shr_palette_used[g_a2vid_palette];
|
|
|
|
for(i = 0; i < 16; i++) {
|
|
val = g_shr_palette_used[i];
|
|
g_shr_palette_used[i] = 0;
|
|
if(val < min) {
|
|
min = val;
|
|
min_pos = i;
|
|
}
|
|
sum += val;
|
|
}
|
|
|
|
if(g_a2vid_palette != min_pos && (count_cur > min)) {
|
|
change_a2vid_palette(min_pos);
|
|
}
|
|
}
|
|
|
|
void
|
|
change_display_mode(double dcycs)
|
|
{
|
|
int line, tmp_line;
|
|
|
|
line = ((get_lines_since_vbl(dcycs) + 0xff) >> 8);
|
|
if(line < 0) {
|
|
line = 0;
|
|
halt_printf("Line < 0!\n");
|
|
}
|
|
tmp_line = MIN(199, line);
|
|
|
|
video_update_all_stat_through_line(tmp_line);
|
|
|
|
if(line < 200) {
|
|
g_a2_new_all_stat[line] = g_cur_a2_stat;
|
|
}
|
|
/* otherwise, g_cur_a2_stat is covered at the end of vbl */
|
|
}
|
|
|
|
void
|
|
video_update_all_stat_through_line(int line)
|
|
{
|
|
int start_line;
|
|
int prev_stat;
|
|
int max_line;
|
|
int i;
|
|
|
|
start_line = g_new_a2_stat_cur_line;
|
|
prev_stat = g_a2_new_all_stat[start_line];
|
|
|
|
max_line = MIN(199, line);
|
|
|
|
for(i = start_line + 1; i <= max_line; i++) {
|
|
g_a2_new_all_stat[i] = prev_stat;
|
|
}
|
|
g_new_a2_stat_cur_line = max_line;
|
|
}
|
|
|
|
|
|
#define MAX_BORDER_CHANGES 16384
|
|
|
|
STRUCT(Border_changes) {
|
|
float fcycs;
|
|
int val;
|
|
};
|
|
|
|
int g_border_color = 0; // OG Expose border color
|
|
|
|
Border_changes g_border_changes[MAX_BORDER_CHANGES];
|
|
int g_num_border_changes = 0;
|
|
|
|
void
|
|
change_border_color(double dcycs, int val)
|
|
{
|
|
int pos;
|
|
|
|
g_border_color = val; // OG Expose border color
|
|
|
|
pos = g_num_border_changes;
|
|
g_border_changes[pos].fcycs = (float)(dcycs - g_last_vbl_dcycs);
|
|
g_border_changes[pos].val = val;
|
|
|
|
pos++;
|
|
g_num_border_changes = pos;
|
|
|
|
if(pos >= MAX_BORDER_CHANGES) {
|
|
halt_printf("num border changes: %d\n", pos);
|
|
g_num_border_changes = 0;
|
|
}
|
|
}
|
|
|
|
extern int first;
|
|
|
|
void
|
|
update_border_info()
|
|
{
|
|
double dlines_per_dcyc;
|
|
double dcycs, dline, dcyc_line_start;
|
|
int offset;
|
|
int new_line_offset, last_line_offset;
|
|
int new_line;
|
|
int new_val;
|
|
int limit;
|
|
int color_now;
|
|
int i;
|
|
|
|
/* to get this routine to redraw the border, change */
|
|
/* g_vbl_border_color, set g_border_last_vbl_changes = 1 */
|
|
/* and change the cur_border_colors[] array */
|
|
|
|
color_now = g_vbl_border_color;
|
|
|
|
dlines_per_dcyc = (double)(1.0 / 65.0);
|
|
limit = g_num_border_changes;
|
|
if(g_border_last_vbl_changes || limit) {
|
|
/* add a dummy entry */
|
|
g_border_changes[limit].fcycs = DCYCS_IN_16MS + 21.0;
|
|
g_border_changes[limit].val = (g_c034_val & 0xf);
|
|
limit++;
|
|
}
|
|
last_line_offset = (-1 << 8) + 44;
|
|
for(i = 0; i < limit; i++) {
|
|
dcycs = g_border_changes[i].fcycs;
|
|
dline = dcycs * dlines_per_dcyc;
|
|
new_line = (int)dline;
|
|
dcyc_line_start = (double)new_line * 65.0;
|
|
offset = ((int)(dcycs - dcyc_line_start)) & 0xff;
|
|
|
|
/* here comes the tricky part */
|
|
/* offset is from 0 to 65, where 0-3 is the right border of */
|
|
/* the previous line, 4-20 is horiz blanking, 21-24 is the */
|
|
/* left border and 25-64 is the main window */
|
|
/* Convert this to a new notation which is 0-3 is the left */
|
|
/* border, 4-43 is the main window, and 44-47 is the right */
|
|
/* basically, add -21 to offset, and wrap < 0 to previous ln */
|
|
/* note this makes line -1 offset 44-47 the left hand border */
|
|
/* for true line 261 on the screen */
|
|
offset -= 21;
|
|
if(offset < 0) {
|
|
new_line--;
|
|
offset += 64;
|
|
}
|
|
new_val = g_border_changes[i].val;
|
|
new_line_offset = (new_line << 8) + offset;
|
|
|
|
if(new_line_offset < -256 || new_line_offset >(262*256 + 0x80)){
|
|
printf("new_line_offset: %05x\n", new_line_offset);
|
|
new_line_offset = last_line_offset;
|
|
}
|
|
while(last_line_offset < new_line_offset) {
|
|
/* see if this will finish it */
|
|
if((last_line_offset & -256)==(new_line_offset & -256)){
|
|
update_border_line(last_line_offset,
|
|
new_line_offset, color_now);
|
|
last_line_offset = new_line_offset;
|
|
} else {
|
|
update_border_line(last_line_offset,
|
|
(last_line_offset & -256) + 65,
|
|
color_now);
|
|
last_line_offset =(last_line_offset & -256)+256;
|
|
}
|
|
}
|
|
|
|
color_now = new_val;
|
|
}
|
|
|
|
#if 0
|
|
if(g_num_border_changes) {
|
|
printf("Border changes: %d\n", g_num_border_changes);
|
|
}
|
|
#endif
|
|
|
|
if(limit > 1) {
|
|
g_border_last_vbl_changes = 1;
|
|
} else {
|
|
g_border_last_vbl_changes = 0;
|
|
}
|
|
|
|
g_num_border_changes = 0;
|
|
g_vbl_border_color = (g_c034_val & 0xf);
|
|
}
|
|
|
|
void
|
|
update_border_line(int st_line_offset, int end_line_offset, int color)
|
|
{
|
|
word32 val;
|
|
int st_offset, end_offset;
|
|
int left, right;
|
|
int line;
|
|
|
|
line = st_line_offset >> 8;
|
|
if(line != (end_line_offset >> 8)) {
|
|
halt_printf("ubl, %04x %04x %02x!\n", st_line_offset,
|
|
end_line_offset, color);
|
|
}
|
|
if(line < -1 || line >= 262) {
|
|
halt_printf("ubl-b, mod line is %d\n", line);
|
|
line = 0;
|
|
}
|
|
if(line < 0 || line >= 262) {
|
|
line = 0;
|
|
}
|
|
|
|
st_offset = st_line_offset & 0xff;
|
|
end_offset = end_line_offset & 0xff;
|
|
|
|
if((st_offset == 0) && (end_offset >= 0x41)) {
|
|
/* might be the same as last time, save some work */
|
|
if(g_cur_border_colors[line] == color) {
|
|
return;
|
|
}
|
|
g_cur_border_colors[line] = color;
|
|
} else {
|
|
g_cur_border_colors[line] = -1;
|
|
}
|
|
|
|
val = (color + (g_a2vid_palette << 4));
|
|
val = (val << 24) + (val << 16) + (val << 8) + val;
|
|
|
|
/* 0-3: left border, 4-43: main window, 44-47: right border */
|
|
/* 48-65: horiz blanking */
|
|
/* first, do the sides from line 0 to line 199 */
|
|
if((line < 200) || (line >= 262)) {
|
|
if(line >= 262) {
|
|
line = 0;
|
|
}
|
|
if(st_offset < 4) {
|
|
/* left side */
|
|
left = st_offset;
|
|
right = MIN(4, end_offset);
|
|
video_border_pixel_write(&g_kimage_border_sides,
|
|
2*line, 2, val, (left * BORDER_WIDTH)/4,
|
|
(right * BORDER_WIDTH) / 4);
|
|
|
|
g_border_sides_refresh_needed = 1;
|
|
}
|
|
if((st_offset < 48) && (end_offset >= 44)) {
|
|
/* right side */
|
|
left = MAX(0, st_offset - 44);
|
|
right = MIN(4, end_offset - 44);
|
|
video_border_pixel_write(&g_kimage_border_sides,
|
|
2*line, 2, val,
|
|
BORDER_WIDTH + (left * EFF_BORDER_WIDTH/4),
|
|
BORDER_WIDTH + (right * EFF_BORDER_WIDTH/4));
|
|
g_border_sides_refresh_needed = 1;
|
|
}
|
|
}
|
|
|
|
if((line >= 192) && (line < 200)) {
|
|
if(st_offset < 44 && end_offset > 4) {
|
|
left = MAX(0, st_offset - 4);
|
|
right = MIN(40, end_offset - 4);
|
|
video_border_pixel_write(&g_kimage_text[0],
|
|
2*line, 2, val, left * 640 / 40,
|
|
right * 640 / 40);
|
|
g_border_line24_refresh_needed = 1;
|
|
}
|
|
}
|
|
|
|
/* now do the bottom, lines 200 to 215 */
|
|
if((line >= 200) && (line < (200 + BASE_MARGIN_BOTTOM/2)) ) {
|
|
line -= 200;
|
|
left = st_offset;
|
|
right = MIN(48, end_offset);
|
|
video_border_pixel_write(&g_kimage_border_special, 2*line, 2,
|
|
val, (left * X_A2_WINDOW_WIDTH / 48),
|
|
(right * X_A2_WINDOW_WIDTH / 48));
|
|
g_border_special_refresh_needed = 1;
|
|
}
|
|
|
|
/* and top, lines 236 to 262 */
|
|
if((line >= (262 - BASE_MARGIN_TOP/2)) && (line < 262)) {
|
|
line -= (262 - BASE_MARGIN_TOP/2);
|
|
left = st_offset;
|
|
right = MIN(48, end_offset);
|
|
video_border_pixel_write(&g_kimage_border_special,
|
|
BASE_MARGIN_BOTTOM + 2*line, 2, val,
|
|
(left * X_A2_WINDOW_WIDTH / 48),
|
|
(right * X_A2_WINDOW_WIDTH / 48));
|
|
g_border_special_refresh_needed = 1;
|
|
}
|
|
}
|
|
|
|
void
|
|
video_border_pixel_write(Kimage *kimage_ptr, int starty, int num_lines,
|
|
word32 val, int st_off, int end_off)
|
|
{
|
|
word32 *ptr;
|
|
int width;
|
|
int width_act;
|
|
int mdepth;
|
|
int num_words, num_bytes;
|
|
int bytes_per_pix;
|
|
int i, j;
|
|
|
|
if(end_off <= st_off) {
|
|
return;
|
|
}
|
|
|
|
width = end_off - st_off;
|
|
width_act = kimage_ptr->width_act;
|
|
mdepth = kimage_ptr->mdepth;
|
|
bytes_per_pix = mdepth >> 3;
|
|
num_bytes = width * bytes_per_pix;
|
|
num_words = num_bytes >> 2;
|
|
|
|
if(width > width_act) {
|
|
halt_printf("border write but width %d > act %d\n", width,
|
|
width_act);
|
|
}
|
|
|
|
if(mdepth == 16) {
|
|
val = g_a2palette_8to1624[val & 0xff];
|
|
val = (val << 16) + val;
|
|
} else if(mdepth == 32) {
|
|
/* 32-bit pixels */
|
|
val = g_a2palette_8to1624[val & 0xff];
|
|
}
|
|
|
|
for(i = 0; i < num_lines; i++) {
|
|
ptr = (word32 *)&(kimage_ptr->data_ptr[
|
|
(starty + i)*width_act*bytes_per_pix]);
|
|
ptr += ((st_off * bytes_per_pix) / 4);
|
|
/* HACK: the above isn't really right when bytes_per_pix is */
|
|
/* less than four... */
|
|
for(j = 0; j < num_words; j++) {
|
|
*ptr++ = val;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#define CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, do_clear) \
|
|
ch_ptr = &(slow_mem_changed[mem_ptr >> CHANGE_SHIFT]); \
|
|
ch_bitpos = 0; \
|
|
bits_per_line = 40 >> SHIFT_PER_CHANGE; \
|
|
ch_shift_amount = (mem_ptr >> SHIFT_PER_CHANGE) & 0x1f; \
|
|
mask_per_line = (-(1 << (32 - bits_per_line))); \
|
|
mask_per_line = mask_per_line >> ch_shift_amount; \
|
|
ch_mask = *ch_ptr & mask_per_line; \
|
|
if(do_clear) { \
|
|
*ch_ptr = *ch_ptr & (~ch_mask); \
|
|
} \
|
|
ch_mask = ch_mask << ch_shift_amount; \
|
|
\
|
|
if(reparse) { \
|
|
ch_mask = - (1 << (32 - bits_per_line)); \
|
|
}
|
|
|
|
#define CH_LOOP_A2_VID(ch_mask, ch_tmp) \
|
|
ch_tmp = ch_mask & 0x80000000; \
|
|
ch_mask = ch_mask << 1; \
|
|
\
|
|
if(!ch_tmp) { \
|
|
continue; \
|
|
}
|
|
|
|
void
|
|
redraw_changed_text_40(int start_offset, int start_line, int num_lines,
|
|
int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val,
|
|
int pixels_per_line)
|
|
{
|
|
register word32 start_time, end_time;
|
|
word32 *img_ptr, *img_ptr2;
|
|
word32 *save_img_ptr, *save_img_ptr2;
|
|
word32 *ch_ptr;
|
|
const word32 *font_ptr1;
|
|
const word32 *font_ptr2;
|
|
byte *slow_mem_ptr;
|
|
byte *b_ptr;
|
|
word32 ch_mask;
|
|
word32 ch_tmp;
|
|
word32 line_mask;
|
|
word32 mask_per_line;
|
|
word32 mem_ptr;
|
|
word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
|
|
word32 palette_add;
|
|
word32 diff_val;
|
|
word32 and_val;
|
|
word32 add_val;
|
|
word32 ff_val;
|
|
word32 val0, val1;
|
|
int flash_state;
|
|
int y;
|
|
int x1, x2;
|
|
int ch_bitpos;
|
|
int bits_per_line;
|
|
int ch_shift_amount;
|
|
int shift_per;
|
|
int left, right;
|
|
int st_line_mod8, st_line;
|
|
int i;
|
|
|
|
/* always redraws to the next multiple of 8 lines due to redraw */
|
|
/* issues: char changed on one screen redraw at line 0 with */
|
|
/* num_lines=1. We need to have drawn lines 1-7 also since line 1 */
|
|
/* will not see any changed bytes */
|
|
st_line_mod8 = start_line & 7;
|
|
st_line = start_line;
|
|
|
|
start_line = start_line >> 3;
|
|
|
|
y = start_line;
|
|
line_mask = 1 << (y);
|
|
mem_ptr = 0x400 + g_screen_index[y] + start_offset;
|
|
if(mem_ptr < 0x400 || mem_ptr >= 0xc00) {
|
|
halt_printf("redraw_changed_text: mem_ptr: %08x\n", mem_ptr);
|
|
}
|
|
|
|
CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0));
|
|
/* avoid clearing changed bits unless we are line 0 (mod 8) */
|
|
|
|
if(ch_mask == 0) {
|
|
return;
|
|
}
|
|
|
|
GET_ITIMER(start_time);
|
|
|
|
shift_per = (1 << SHIFT_PER_CHANGE);
|
|
|
|
g_a2_screen_buffer_changed |= line_mask;
|
|
|
|
palette_add = (g_a2vid_palette << 4);
|
|
palette_add = palette_add + (palette_add << 8) + (palette_add << 16) +
|
|
(palette_add << 24);
|
|
|
|
left = 40;
|
|
right = 0;
|
|
|
|
diff_val = (fg_val - bg_val) & 0xf;
|
|
and_val = diff_val + (diff_val << 8) + (diff_val << 16) +(diff_val<<24);
|
|
add_val = bg_val + (bg_val << 8) + (bg_val << 16) + (bg_val << 24);
|
|
ff_val = 0x0f0f0f0f;
|
|
|
|
|
|
flash_state = (g_cur_a2_stat & ALL_STAT_FLASH_STATE);
|
|
|
|
for(x1 = 0; x1 < 40; x1 += shift_per) {
|
|
|
|
CH_LOOP_A2_VID(ch_mask, ch_tmp);
|
|
|
|
left = MIN(x1, left);
|
|
right = MAX(x1 + shift_per, right);
|
|
slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]);
|
|
b_ptr = &screen_data[(8*y + st_line_mod8)*2*pixels_per_line +
|
|
x1*14];
|
|
img_ptr = (word32 *)b_ptr;
|
|
img_ptr2 = (word32 *)(b_ptr + pixels_per_line);
|
|
|
|
|
|
for(x2 = 0; x2 < shift_per; x2 += 2) {
|
|
val0 = *slow_mem_ptr++;
|
|
val1 = *slow_mem_ptr++;
|
|
|
|
if(!altcharset) {
|
|
if(val0 >= 0x40 && val0 < 0x80) {
|
|
if(flash_state) {
|
|
val0 += 0x40;
|
|
} else {
|
|
val0 -= 0x40;
|
|
}
|
|
}
|
|
if(val1 >= 0x40 && val1 < 0x80) {
|
|
if(flash_state) {
|
|
val1 += 0x40;
|
|
} else {
|
|
val1 -= 0x40;
|
|
}
|
|
}
|
|
}
|
|
save_img_ptr = img_ptr;
|
|
save_img_ptr2 = img_ptr2;
|
|
|
|
for(i = st_line_mod8; i < 8; i++) {
|
|
font_ptr1 = &(g_font40_even_bits[val0][i][0]);
|
|
tmp0 = (font_ptr1[0] & and_val) + add_val;
|
|
tmp1 = (font_ptr1[1] & and_val) + add_val;
|
|
tmp2 = (font_ptr1[2] & and_val) + add_val;
|
|
|
|
font_ptr2 = &(g_font40_odd_bits[val1][i][0]);
|
|
tmp3 = ((font_ptr1[3]+font_ptr2[0]) & and_val)+
|
|
add_val;
|
|
|
|
tmp4 = (font_ptr2[1] & and_val) + add_val;
|
|
tmp5 = (font_ptr2[2] & and_val) + add_val;
|
|
tmp6 = (font_ptr2[3] & and_val) + add_val;
|
|
|
|
tmp0 = (tmp0 & ff_val) + palette_add;
|
|
tmp1 = (tmp1 & ff_val) + palette_add;
|
|
tmp2 = (tmp2 & ff_val) + palette_add;
|
|
tmp3 = (tmp3 & ff_val) + palette_add;
|
|
tmp4 = (tmp4 & ff_val) + palette_add;
|
|
tmp5 = (tmp5 & ff_val) + palette_add;
|
|
tmp6 = (tmp6 & ff_val) + palette_add;
|
|
|
|
img_ptr[0] = tmp0;
|
|
img_ptr[1] = tmp1;
|
|
img_ptr[2] = tmp2;
|
|
img_ptr[3] = tmp3;
|
|
img_ptr[4] = tmp4;
|
|
img_ptr[5] = tmp5;
|
|
img_ptr[6] = tmp6;
|
|
|
|
img_ptr2[0] = tmp0;
|
|
img_ptr2[1] = tmp1;
|
|
img_ptr2[2] = tmp2;
|
|
img_ptr2[3] = tmp3;
|
|
img_ptr2[4] = tmp4;
|
|
img_ptr2[5] = tmp5;
|
|
img_ptr2[6] = tmp6;
|
|
|
|
img_ptr += (2*pixels_per_line)/4;
|
|
img_ptr2 += (2*pixels_per_line)/4;
|
|
}
|
|
|
|
img_ptr = save_img_ptr + 7;
|
|
img_ptr2 = save_img_ptr2 + 7;
|
|
}
|
|
}
|
|
GET_ITIMER(end_time);
|
|
|
|
for(i = 0; i < (8 - st_line_mod8); i++) {
|
|
g_a2_line_left_edge[st_line + i] = (left*14);
|
|
g_a2_line_right_edge[st_line + i] = (right*14);
|
|
}
|
|
|
|
if(left >= right || left < 0 || right < 0) {
|
|
printf("line %d, 40: left >= right: %d >= %d\n",
|
|
start_line, left, right);
|
|
}
|
|
|
|
g_cycs_in_40col += (end_time - start_time);
|
|
|
|
g_need_redraw = 0;
|
|
}
|
|
|
|
void
|
|
redraw_changed_text_80(int start_offset, int start_line, int num_lines,
|
|
int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val,
|
|
int pixels_per_line)
|
|
{
|
|
const word32 *font_ptr0, *font_ptr1, *font_ptr2, *font_ptr3;
|
|
word32 *ch_ptr;
|
|
word32 *img_ptr, *img_ptr2;
|
|
word32 *save_img_ptr, *save_img_ptr2;
|
|
byte *b_ptr;
|
|
byte *slow_mem_ptr;
|
|
word32 ch_mask;
|
|
word32 ch_tmp;
|
|
word32 mask_per_line;
|
|
word32 mem_ptr;
|
|
word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
|
|
word32 diff_val;
|
|
word32 add_val, and_val, ff_val;
|
|
word32 palette_add;
|
|
word32 line_mask;
|
|
word32 val0, val1, val2, val3;
|
|
int st_line_mod8, st_line;
|
|
int flash_state;
|
|
int y;
|
|
int x1, x2;
|
|
int i;
|
|
int ch_bitpos;
|
|
int bits_per_line;
|
|
int ch_shift_amount;
|
|
int shift_per;
|
|
int left, right;
|
|
|
|
st_line_mod8 = start_line & 7;
|
|
st_line = start_line;
|
|
|
|
start_line = start_line >> 3;
|
|
|
|
y = start_line;
|
|
line_mask = 1 << (y);
|
|
mem_ptr = 0x400 + g_screen_index[y] + start_offset;
|
|
if(mem_ptr < 0x400 || mem_ptr >= 0xc00) {
|
|
halt_printf("redraw_changed_text: mem_ptr: %08x\n", mem_ptr);
|
|
}
|
|
|
|
CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0));
|
|
|
|
if(ch_mask == 0) {
|
|
return;
|
|
}
|
|
|
|
shift_per = (1 << SHIFT_PER_CHANGE);
|
|
|
|
g_a2_screen_buffer_changed |= line_mask;
|
|
|
|
palette_add = (g_a2vid_palette << 4);
|
|
palette_add = palette_add + (palette_add << 8) + (palette_add << 16) +
|
|
(palette_add << 24);
|
|
|
|
left = 40;
|
|
right = 0;
|
|
|
|
diff_val = (fg_val - bg_val) & 0xf;
|
|
add_val = bg_val + (bg_val << 8) + (bg_val << 16) + (bg_val << 24);
|
|
and_val = diff_val + (diff_val << 8) + (diff_val << 16) +(diff_val<<24);
|
|
ff_val = 0x0f0f0f0f;
|
|
|
|
flash_state = (g_cur_a2_stat & ALL_STAT_FLASH_STATE);
|
|
|
|
for(x1 = 0; x1 < 40; x1 += shift_per) {
|
|
CH_LOOP_A2_VID(ch_mask, ch_tmp);
|
|
|
|
left = MIN(x1, left);
|
|
right = MAX(x1 + shift_per, right);
|
|
|
|
slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]);
|
|
b_ptr = &screen_data[(y*8 + st_line_mod8)*2*pixels_per_line +
|
|
x1*14];
|
|
img_ptr = (word32 *)b_ptr;
|
|
img_ptr2 = (word32 *)(b_ptr + pixels_per_line);
|
|
|
|
for(x2 = 0; x2 < shift_per; x2 += 2) {
|
|
/* do 4 chars at once! */
|
|
|
|
val1 = slow_mem_ptr[0];
|
|
val3 = slow_mem_ptr[1];
|
|
val0 = slow_mem_ptr[0x10000];
|
|
val2 = slow_mem_ptr[0x10001];
|
|
slow_mem_ptr += 2;
|
|
|
|
if(!altcharset) {
|
|
if(val0 >= 0x40 && val0 < 0x80) {
|
|
if(flash_state) {
|
|
val0 += 0x40;
|
|
} else {
|
|
val0 -= 0x40;
|
|
}
|
|
}
|
|
if(val1 >= 0x40 && val1 < 0x80) {
|
|
if(flash_state) {
|
|
val1 += 0x40;
|
|
} else {
|
|
val1 -= 0x40;
|
|
}
|
|
}
|
|
if(val2 >= 0x40 && val2 < 0x80) {
|
|
if(flash_state) {
|
|
val2 += 0x40;
|
|
} else {
|
|
val2 -= 0x40;
|
|
}
|
|
}
|
|
if(val3 >= 0x40 && val3 < 0x80) {
|
|
if(flash_state) {
|
|
val3 += 0x40;
|
|
} else {
|
|
val3 -= 0x40;
|
|
}
|
|
}
|
|
}
|
|
save_img_ptr = img_ptr;
|
|
save_img_ptr2 = img_ptr2;
|
|
|
|
for(i = st_line_mod8; i < 8; i++) {
|
|
font_ptr0 = &(g_font80_off0_bits[val0][i][0]);
|
|
tmp0 = (font_ptr0[0] & and_val) + add_val;
|
|
|
|
font_ptr3 = &(g_font80_off3_bits[val1][i][0]);
|
|
tmp1 = ((font_ptr0[1]+font_ptr3[0]) & and_val)+
|
|
add_val;
|
|
/* 3 bytes from ptr0, 1 from ptr3 */
|
|
tmp2 = (font_ptr3[1] & and_val) + add_val;
|
|
|
|
font_ptr2 = &(g_font80_off2_bits[val2][i][0]);
|
|
tmp3 = ((font_ptr3[2]+font_ptr2[0]) & and_val)+
|
|
add_val;
|
|
/* 2 bytes from ptr3, 2 from ptr2*/
|
|
tmp4 = (font_ptr2[1] & and_val) + add_val;
|
|
|
|
font_ptr1 = &(g_font80_off1_bits[val3][i][0]);
|
|
tmp5 = ((font_ptr2[2]+font_ptr1[0]) & and_val)+
|
|
add_val;
|
|
/* 1 byte from ptr2, 3 from ptr1 */
|
|
tmp6 = (font_ptr1[1] & and_val) + add_val;
|
|
|
|
tmp0 = (tmp0 & ff_val) + palette_add;
|
|
tmp1 = (tmp1 & ff_val) + palette_add;
|
|
tmp2 = (tmp2 & ff_val) + palette_add;
|
|
tmp3 = (tmp3 & ff_val) + palette_add;
|
|
tmp4 = (tmp4 & ff_val) + palette_add;
|
|
tmp5 = (tmp5 & ff_val) + palette_add;
|
|
tmp6 = (tmp6 & ff_val) + palette_add;
|
|
|
|
img_ptr[0] = tmp0;
|
|
img_ptr[1] = tmp1;
|
|
img_ptr[2] = tmp2;
|
|
img_ptr[3] = tmp3;
|
|
img_ptr[4] = tmp4;
|
|
img_ptr[5] = tmp5;
|
|
img_ptr[6] = tmp6;
|
|
|
|
img_ptr2[0] = tmp0;
|
|
img_ptr2[1] = tmp1;
|
|
img_ptr2[2] = tmp2;
|
|
img_ptr2[3] = tmp3;
|
|
img_ptr2[4] = tmp4;
|
|
img_ptr2[5] = tmp5;
|
|
img_ptr2[6] = tmp6;
|
|
|
|
img_ptr += (2*pixels_per_line)/4;
|
|
img_ptr2 += (2*pixels_per_line)/4;
|
|
}
|
|
|
|
img_ptr = save_img_ptr + 7;
|
|
img_ptr2 = save_img_ptr2 + 7;
|
|
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < (8 - st_line_mod8); i++) {
|
|
g_a2_line_left_edge[st_line + i] = (left*14);
|
|
g_a2_line_right_edge[st_line + i] = (right*14);
|
|
}
|
|
|
|
if(left >= right || left < 0 || right < 0) {
|
|
printf("line %d, 80: left >= right: %d >= %d\n",
|
|
start_line, left, right);
|
|
}
|
|
|
|
g_need_redraw = 0;
|
|
}
|
|
|
|
void
|
|
redraw_changed_gr(int start_offset, int start_line, int num_lines, int reparse,
|
|
byte *screen_data, int pixels_per_line)
|
|
{
|
|
word32 *img_ptr;
|
|
word32 *save_img_ptr;
|
|
word32 *ch_ptr;
|
|
byte *b_ptr;
|
|
byte *slow_mem_ptr;
|
|
word32 mask_per_line;
|
|
word32 ch_mask;
|
|
word32 ch_tmp;
|
|
word32 mem_ptr;
|
|
word32 line_mask;
|
|
word32 val0, val1;
|
|
word32 val0_wd, val1_wd;
|
|
word32 val01_wd;
|
|
word32 val_even, val_odd;
|
|
word32 palette_add;
|
|
int half;
|
|
int x1, x2;
|
|
int y;
|
|
int y2;
|
|
int ch_bitpos;
|
|
int bits_per_line;
|
|
int ch_shift_amount;
|
|
int shift_per;
|
|
int left, right;
|
|
int st_line_mod8, st_line, eff_line, end_line;
|
|
int i;
|
|
|
|
st_line_mod8 = start_line & 7;
|
|
st_line = start_line;
|
|
end_line = 8; // st_line_mod8 + num_lines;
|
|
|
|
start_line = start_line >> 3;
|
|
|
|
y = start_line;
|
|
line_mask = 1 << y;
|
|
mem_ptr = 0x400 + g_screen_index[y] + start_offset;
|
|
if(mem_ptr < 0x400 || mem_ptr >= 0xc00) {
|
|
printf("redraw_changed_gr: mem_ptr: %08x\n", mem_ptr);
|
|
}
|
|
|
|
CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0));
|
|
|
|
if(ch_mask == 0) {
|
|
return;
|
|
}
|
|
|
|
shift_per = (1 << SHIFT_PER_CHANGE);
|
|
|
|
g_a2_screen_buffer_changed |= line_mask;
|
|
|
|
palette_add = (g_a2vid_palette << 4);
|
|
palette_add = palette_add + (palette_add << 8) + (palette_add << 16) +
|
|
(palette_add << 24);
|
|
|
|
left = 40;
|
|
right = 0;
|
|
|
|
for(x1 = 0; x1 < 40; x1 += shift_per) {
|
|
CH_LOOP_A2_VID(ch_mask, ch_tmp);
|
|
|
|
left = MIN(x1, left);
|
|
right = MAX(x1 + shift_per, right);
|
|
|
|
slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]);
|
|
b_ptr = &screen_data[(y*8 + st_line_mod8)*2*pixels_per_line +
|
|
x1*14];
|
|
img_ptr = (word32 *)b_ptr;
|
|
|
|
for(x2 = 0; x2 < shift_per; x2 += 2) {
|
|
val_even = *slow_mem_ptr++;
|
|
val_odd = *slow_mem_ptr++;
|
|
|
|
save_img_ptr = img_ptr;
|
|
|
|
for(half = 0; half < 2; half++) {
|
|
val0 = val_even & 0xf;
|
|
val1 = val_odd & 0xf;
|
|
val0_wd = (val0 << 24) + (val0 << 16) +
|
|
(val0 << 8) + val0;
|
|
val1_wd = (val1 << 24) + (val1 << 16) +
|
|
(val1 << 8) + val1;
|
|
#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
|
|
val01_wd = (val1_wd << 16) + (val0_wd & 0xffff);
|
|
#else
|
|
val01_wd = (val0_wd << 16) + (val1_wd & 0xffff);
|
|
#endif
|
|
|
|
for(y2 = 0; y2 < 8; y2++) {
|
|
eff_line = half*4 + (y2 >> 1);
|
|
if((eff_line < st_line_mod8) ||
|
|
(eff_line > end_line)) {
|
|
continue;
|
|
}
|
|
|
|
img_ptr[0] = val0_wd + palette_add;
|
|
img_ptr[1] = val0_wd + palette_add;
|
|
img_ptr[2] = val0_wd + palette_add;
|
|
img_ptr[3] = val01_wd + palette_add;
|
|
img_ptr[4] = val1_wd + palette_add;
|
|
img_ptr[5] = val1_wd + palette_add;
|
|
img_ptr[6] = val1_wd + palette_add;
|
|
img_ptr += (pixels_per_line)/4;
|
|
}
|
|
|
|
|
|
val_even = val_even >> 4;
|
|
val_odd = val_odd >> 4;
|
|
}
|
|
|
|
img_ptr = save_img_ptr + 7;
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < (8 - st_line_mod8); i++) {
|
|
g_a2_line_left_edge[st_line + i] = (left*14);
|
|
g_a2_line_right_edge[st_line + i] = (right*14);
|
|
}
|
|
|
|
g_need_redraw = 0;
|
|
}
|
|
|
|
void
|
|
redraw_changed_dbl_gr(int start_offset, int start_line, int num_lines,
|
|
int reparse, byte *screen_data, int pixels_per_line)
|
|
{
|
|
word32 *img_ptr;
|
|
word32 *save_img_ptr;
|
|
word32 *ch_ptr;
|
|
byte *b_ptr;
|
|
byte *slow_mem_ptr;
|
|
word32 mask_per_line;
|
|
word32 ch_mask;
|
|
word32 ch_tmp;
|
|
word32 mem_ptr;
|
|
word32 line_mask;
|
|
word32 val0, val1, val2, val3;
|
|
word32 val0_wd, val1_wd, val2_wd, val3_wd;
|
|
word32 val01_wd, val12_wd, val23_wd;
|
|
word32 val_even_main, val_odd_main;
|
|
word32 val_even_aux, val_odd_aux;
|
|
word32 palette_add;
|
|
int half;
|
|
int x1, x2;
|
|
int y;
|
|
int y2;
|
|
int ch_bitpos;
|
|
int bits_per_line;
|
|
int ch_shift_amount;
|
|
int shift_per;
|
|
int left, right;
|
|
int st_line_mod8, st_line, eff_line, end_line;
|
|
int i;
|
|
|
|
st_line_mod8 = start_line & 7;
|
|
end_line = 8; // st_line_mod8 + num_lines
|
|
st_line = start_line;
|
|
|
|
start_line = start_line >> 3;
|
|
|
|
y = start_line;
|
|
line_mask = 1 << y;
|
|
mem_ptr = 0x400 + g_screen_index[y] + start_offset;
|
|
if(mem_ptr < 0x400 || mem_ptr >= 0xc00) {
|
|
printf("redraw_changed_dbl_gr: mem_ptr: %08x\n", mem_ptr);
|
|
}
|
|
|
|
CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, (st_line_mod8 == 0));
|
|
|
|
if(ch_mask == 0) {
|
|
return;
|
|
}
|
|
|
|
shift_per = (1 << SHIFT_PER_CHANGE);
|
|
|
|
g_a2_screen_buffer_changed |= line_mask;
|
|
|
|
palette_add = (g_a2vid_palette << 4);
|
|
palette_add = palette_add + (palette_add << 8) + (palette_add << 16) +
|
|
(palette_add << 24);
|
|
|
|
left = 40;
|
|
right = 0;
|
|
|
|
for(x1 = 0; x1 < 40; x1 += shift_per) {
|
|
CH_LOOP_A2_VID(ch_mask, ch_tmp);
|
|
|
|
left = MIN(x1, left);
|
|
right = MAX(x1 + shift_per, right);
|
|
|
|
slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]);
|
|
b_ptr = &screen_data[(y*8 + st_line_mod8)*2*pixels_per_line +
|
|
x1*14];
|
|
img_ptr = (word32 *)b_ptr;
|
|
|
|
for(x2 = 0; x2 < shift_per; x2 += 2) {
|
|
val_even_main = slow_mem_ptr[0];
|
|
val_odd_main = slow_mem_ptr[1];
|
|
val_even_aux = slow_mem_ptr[0x10000];
|
|
val_odd_aux = slow_mem_ptr[0x10001];
|
|
slow_mem_ptr += 2;
|
|
|
|
save_img_ptr = img_ptr;
|
|
|
|
for(half = 0; half < 2; half++) {
|
|
val0 = val_even_aux & 0xf;
|
|
val1 = val_even_main & 0xf;
|
|
val2 = val_odd_aux & 0xf;
|
|
val3 = val_odd_main & 0xf;
|
|
|
|
/* Handle funny pattern of dbl gr aux mem */
|
|
val0 = ((val0 << 1) & 0xf) + (val0 >> 3);
|
|
val2 = ((val2 << 1) & 0xf) + (val2 >> 3);
|
|
|
|
val0_wd = (val0 << 24) + (val0 << 16) +
|
|
(val0 << 8) + val0;
|
|
val1_wd = (val1 << 24) + (val1 << 16) +
|
|
(val1 << 8) + val1;
|
|
val2_wd = (val2 << 24) + (val2 << 16) +
|
|
(val2 << 8) + val2;
|
|
val3_wd = (val3 << 24) + (val3 << 16) +
|
|
(val3 << 8) + val3;
|
|
#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
|
|
val01_wd = (val1_wd << 24) + (val0_wd&0xffffff);
|
|
val12_wd = (val2_wd << 16) + (val1_wd & 0xffff);
|
|
val23_wd = (val3_wd << 8) + (val2_wd & 0xff);
|
|
#else
|
|
val01_wd = (val0_wd << 8) + (val1_wd & 0xff);
|
|
val12_wd = (val1_wd << 16) + (val2_wd & 0xffff);
|
|
val23_wd = (val2_wd << 24) + (val3_wd&0xffffff);
|
|
#endif
|
|
|
|
for(y2 = 0; y2 < 8; y2++) {
|
|
eff_line = half*4 + (y2 >> 1);
|
|
if((eff_line < st_line_mod8) ||
|
|
(eff_line > end_line)) {
|
|
continue;
|
|
}
|
|
img_ptr[0] = val0_wd + palette_add;
|
|
img_ptr[1] = val01_wd + palette_add;
|
|
img_ptr[2] = val1_wd + palette_add;
|
|
img_ptr[3] = val12_wd + palette_add;
|
|
img_ptr[4] = val2_wd + palette_add;
|
|
img_ptr[5] = val23_wd + palette_add;
|
|
img_ptr[6] = val3_wd + palette_add;
|
|
img_ptr += (pixels_per_line)/4;
|
|
}
|
|
|
|
val_even_aux = val_even_aux >> 4;
|
|
val_even_main = val_even_main >> 4;
|
|
val_odd_aux = val_odd_aux >> 4;
|
|
val_odd_main = val_odd_main >> 4;
|
|
}
|
|
|
|
img_ptr = save_img_ptr + 7;
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < (8 - st_line_mod8); i++) {
|
|
g_a2_line_left_edge[st_line + i] = (left*14);
|
|
g_a2_line_right_edge[st_line + i] = (right*14);
|
|
}
|
|
|
|
g_need_redraw = 0;
|
|
}
|
|
|
|
void
|
|
redraw_changed_hires(int start_offset, int start_line, int num_lines,
|
|
int color, int reparse, byte *screen_data, int pixels_per_line)
|
|
{
|
|
if(!color) {
|
|
redraw_changed_hires_color(start_offset, start_line, num_lines,
|
|
reparse, screen_data, pixels_per_line);
|
|
} else {
|
|
redraw_changed_hires_bw(start_offset, start_line, num_lines,
|
|
reparse, screen_data, pixels_per_line);
|
|
}
|
|
}
|
|
|
|
void
|
|
redraw_changed_hires_bw(int start_offset, int start_line, int num_lines,
|
|
int reparse, byte *screen_data, int pixels_per_line)
|
|
{
|
|
word32 *img_ptr, *img_ptr2;
|
|
word32 *ch_ptr;
|
|
byte *b_ptr;
|
|
byte *slow_mem_ptr;
|
|
word32 mask_per_line;
|
|
word32 ch_mask;
|
|
word32 ch_tmp;
|
|
word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
|
|
word32 mem_ptr;
|
|
word32 val0, val1;
|
|
word32 val_whole;
|
|
word32 line_mask;
|
|
word32 palette_add;
|
|
int y;
|
|
int x1, x2;
|
|
int ch_bitpos;
|
|
int bits_per_line;
|
|
int ch_shift_amount;
|
|
int shift_per;
|
|
int left, right;
|
|
int st_line;
|
|
int i;
|
|
|
|
st_line = start_line;
|
|
start_line = start_line >> 3;
|
|
|
|
palette_add = (g_a2vid_palette << 4);
|
|
palette_add = palette_add + (palette_add << 8) + (palette_add << 16) +
|
|
(palette_add << 24);
|
|
|
|
left = 40;
|
|
right = 0;
|
|
|
|
for(y = st_line; y < (st_line + num_lines); y++) {
|
|
line_mask = 1 << (y >> 3);
|
|
mem_ptr = 0x2000 + (((y & 7) * 0x400) +
|
|
g_screen_index[y >> 3]) + start_offset;
|
|
|
|
CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1);
|
|
|
|
if(ch_mask == 0) {
|
|
continue;
|
|
}
|
|
|
|
/* Hires depends on adjacent bits, so also reparse adjacent */
|
|
/* regions so that if bits on the edge change, redrawing is */
|
|
/* correct */
|
|
ch_mask = ch_mask | (ch_mask >> 1) | (ch_mask << 1);
|
|
|
|
shift_per = (1 << SHIFT_PER_CHANGE);
|
|
|
|
g_a2_screen_buffer_changed |= line_mask;
|
|
|
|
for(x1 = 0; x1 < 40; x1 += shift_per) {
|
|
CH_LOOP_A2_VID(ch_mask, ch_tmp);
|
|
|
|
left = MIN(x1, left);
|
|
right = MAX(x1 + shift_per, right);
|
|
|
|
slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]);
|
|
b_ptr = &screen_data[(y*2)*pixels_per_line + x1*14];
|
|
img_ptr = (word32 *)b_ptr;
|
|
img_ptr2 = (word32 *)(b_ptr + pixels_per_line);
|
|
|
|
for(x2 = 0; x2 < shift_per; x2 += 2) {
|
|
val0 = *slow_mem_ptr++;
|
|
val1 = *slow_mem_ptr++;
|
|
|
|
val_whole = ((val1 & 0x7f) << 7) +(val0 & 0x7f);
|
|
|
|
tmp0 = g_bw_hires_convert[val_whole & 3];
|
|
val_whole = val_whole >> 2;
|
|
tmp1 = g_bw_hires_convert[val_whole & 3];
|
|
val_whole = val_whole >> 2;
|
|
tmp2 = g_bw_hires_convert[val_whole & 3];
|
|
val_whole = val_whole >> 2;
|
|
tmp3 = g_bw_hires_convert[val_whole & 3];
|
|
val_whole = val_whole >> 2;
|
|
tmp4 = g_bw_hires_convert[val_whole & 3];
|
|
val_whole = val_whole >> 2;
|
|
tmp5 = g_bw_hires_convert[val_whole & 3];
|
|
val_whole = val_whole >> 2;
|
|
tmp6 = g_bw_hires_convert[val_whole & 3];
|
|
|
|
img_ptr[0] = tmp0 + palette_add;
|
|
img_ptr[1] = tmp1 + palette_add;
|
|
img_ptr[2] = tmp2 + palette_add;
|
|
img_ptr[3] = tmp3 + palette_add;
|
|
img_ptr[4] = tmp4 + palette_add;
|
|
img_ptr[5] = tmp5 + palette_add;
|
|
img_ptr[6] = tmp6 + palette_add;
|
|
|
|
img_ptr2[0] = tmp0 + palette_add;
|
|
img_ptr2[1] = tmp1 + palette_add;
|
|
img_ptr2[2] = tmp2 + palette_add;
|
|
img_ptr2[3] = tmp3 + palette_add;
|
|
img_ptr2[4] = tmp4 + palette_add;
|
|
img_ptr2[5] = tmp5 + palette_add;
|
|
img_ptr2[6] = tmp6 + palette_add;
|
|
|
|
img_ptr += 7;
|
|
img_ptr2 += 7;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < num_lines; i++) {
|
|
g_a2_line_left_edge[st_line + i] = (left*14);
|
|
g_a2_line_right_edge[st_line + i] = (right*14);
|
|
}
|
|
|
|
g_need_redraw = 0;
|
|
}
|
|
|
|
void
|
|
redraw_changed_hires_color(int start_offset, int start_line, int num_lines,
|
|
int reparse, byte *screen_data, int pixels_per_line)
|
|
{
|
|
word32 *img_ptr, *img_ptr2;
|
|
word32 *ch_ptr;
|
|
byte *b_ptr;
|
|
byte *slow_mem_ptr;
|
|
word32 mask_per_line;
|
|
word32 ch_mask;
|
|
word32 ch_tmp;
|
|
word32 mem_ptr;
|
|
word32 val0, val1;
|
|
word32 val_whole;
|
|
word32 pix_val;
|
|
word32 line_mask;
|
|
word32 prev_pixel;
|
|
word32 prev_hi;
|
|
word32 loc_hi;
|
|
word32 val_hi;
|
|
word32 tmp_val;
|
|
word32 palette_add;
|
|
int y;
|
|
int x1, x2;
|
|
int ch_bitpos;
|
|
int bits_per_line;
|
|
int ch_shift_amount;
|
|
int shift_per;
|
|
int left, right;
|
|
int st_line;
|
|
int i, j;
|
|
|
|
st_line = start_line;
|
|
|
|
start_line = start_line >> 3;
|
|
|
|
palette_add = (g_a2vid_palette << 4);
|
|
palette_add = palette_add + (palette_add << 8) + (palette_add << 16) +
|
|
(palette_add << 24);
|
|
|
|
left = 40;
|
|
right = 0;
|
|
|
|
for(y = st_line; y < (st_line + num_lines); y++) {
|
|
line_mask = 1 << (y >> 3);
|
|
mem_ptr = 0x2000 + (((y & 7) * 0x400) +
|
|
g_screen_index[y >> 3]) + start_offset;
|
|
|
|
CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1);
|
|
|
|
if(ch_mask == 0) {
|
|
continue;
|
|
}
|
|
|
|
/* Hires depends on adjacent bits, so also reparse adjacent */
|
|
/* regions so that if bits on the edge change, redrawing is */
|
|
/* correct */
|
|
ch_mask = ch_mask | (ch_mask >> 1) | (ch_mask << 1);
|
|
|
|
shift_per = (1 << SHIFT_PER_CHANGE);
|
|
|
|
g_a2_screen_buffer_changed |= line_mask;
|
|
|
|
for(x1 = 0; x1 < 40; x1 += shift_per) {
|
|
|
|
CH_LOOP_A2_VID(ch_mask, ch_tmp);
|
|
|
|
left = MIN(x1, left);
|
|
right = MAX(x1 + shift_per, right);
|
|
|
|
slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]);
|
|
b_ptr = &screen_data[(y*2)*pixels_per_line + x1*14];
|
|
img_ptr = (word32 *)b_ptr;
|
|
img_ptr2 = (word32 *)(b_ptr + pixels_per_line);
|
|
|
|
prev_pixel = 0;
|
|
prev_hi = 0;
|
|
|
|
if(x1 > 0) {
|
|
tmp_val = slow_mem_ptr[-1];
|
|
prev_pixel = (tmp_val >> 6) & 1;
|
|
prev_hi = (tmp_val >> 7) & 0x1;
|
|
}
|
|
|
|
for(x2 = 0; x2 < shift_per; x2 += 2) {
|
|
val0 = *slow_mem_ptr++;
|
|
val1 = *slow_mem_ptr++;
|
|
|
|
val_whole = ((val1 & 0x7f) << 8) +
|
|
((val0 & 0x7f) << 1) +
|
|
prev_pixel;
|
|
|
|
loc_hi = prev_hi;
|
|
if(((val1 >> 7) & 1) != 0) {
|
|
loc_hi += 0x7f00;
|
|
}
|
|
if(((val0 >> 7) & 1) != 0) {
|
|
loc_hi += 0xfe;
|
|
}
|
|
|
|
prev_pixel = (val1 >> 6) & 1;
|
|
prev_hi = (val1 >> 7) & 1;
|
|
if((x1 + x2 + 2) < 40) {
|
|
tmp_val = slow_mem_ptr[0];
|
|
if(tmp_val & 1) {
|
|
val_whole |= 0x8000;
|
|
}
|
|
if(tmp_val & 0x80) {
|
|
loc_hi |= 0x8000;
|
|
}
|
|
}
|
|
|
|
loc_hi = loc_hi >> 1;
|
|
|
|
for(j = 0; j < 7; j++) {
|
|
tmp_val = val_whole & 0xf;
|
|
val_hi = loc_hi & 0x3;
|
|
|
|
pix_val = g_hires_convert[(val_hi<<4) +
|
|
tmp_val];
|
|
*img_ptr++ = pix_val + palette_add;
|
|
*img_ptr2++ = pix_val + palette_add;
|
|
val_whole = val_whole >> 2;
|
|
loc_hi = loc_hi >> 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < num_lines; i++) {
|
|
g_a2_line_left_edge[st_line + i] = (left*14);
|
|
g_a2_line_right_edge[st_line + i] = (right*14);
|
|
}
|
|
|
|
g_need_redraw = 0;
|
|
}
|
|
|
|
|
|
void
|
|
redraw_changed_dbl_hires(int start_offset, int start_line, int num_lines,
|
|
int color, int reparse, byte *screen_data, int pixels_per_line)
|
|
{
|
|
if(!color) {
|
|
redraw_changed_dbl_hires_color(start_offset, start_line,
|
|
num_lines, reparse, screen_data, pixels_per_line);
|
|
} else {
|
|
redraw_changed_dbl_hires_bw(start_offset, start_line,
|
|
num_lines, reparse, screen_data, pixels_per_line);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
redraw_changed_dbl_hires_bw(int start_offset, int start_line, int num_lines,
|
|
int reparse, byte *screen_data, int pixels_per_line)
|
|
{
|
|
word32 *img_ptr, *img_ptr2;
|
|
word32 *ch_ptr;
|
|
byte *b_ptr;
|
|
byte *slow_mem_ptr;
|
|
word32 mask_per_line;
|
|
word32 ch_mask;
|
|
word32 ch_tmp;
|
|
word32 mem_ptr;
|
|
word32 val0, val1, val2, val3;
|
|
word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
|
|
word32 val_whole;
|
|
word32 line_mask;
|
|
word32 palette_add;
|
|
int y;
|
|
int x1, x2;
|
|
int ch_bitpos;
|
|
int bits_per_line;
|
|
int ch_shift_amount;
|
|
int shift_per;
|
|
int left, right;
|
|
int st_line;
|
|
int i;
|
|
|
|
st_line = start_line;
|
|
start_line = start_line >> 3;
|
|
|
|
palette_add = (g_a2vid_palette << 4);
|
|
palette_add = palette_add + (palette_add << 8) + (palette_add << 16) +
|
|
(palette_add << 24);
|
|
|
|
left = 40;
|
|
right = 0;
|
|
|
|
for(y = st_line; y < (st_line + num_lines); y++) {
|
|
line_mask = 1 << (y >> 3);
|
|
mem_ptr = 0x2000 + (((y & 7) * 0x400) + g_screen_index[y >> 3] +
|
|
start_offset);
|
|
|
|
CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1);
|
|
|
|
if(ch_mask == 0) {
|
|
continue;
|
|
}
|
|
|
|
shift_per = (1 << SHIFT_PER_CHANGE);
|
|
|
|
g_a2_screen_buffer_changed |= line_mask;
|
|
|
|
for(x1 = 0; x1 < 40; x1 += shift_per) {
|
|
|
|
CH_LOOP_A2_VID(ch_mask, ch_tmp);
|
|
|
|
left = MIN(x1, left);
|
|
right = MAX(x1 + shift_per, right);
|
|
|
|
slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]);
|
|
b_ptr = &screen_data[(y*2)*pixels_per_line + x1*14];
|
|
img_ptr = (word32 *)b_ptr;
|
|
img_ptr2 = (word32 *)(b_ptr + pixels_per_line);
|
|
|
|
for(x2 = 0; x2 < shift_per; x2 += 2) {
|
|
val0 = slow_mem_ptr[0x10000];
|
|
val1 = slow_mem_ptr[0];
|
|
val2 = slow_mem_ptr[0x10001];
|
|
val3 = slow_mem_ptr[1];
|
|
slow_mem_ptr += 2;
|
|
|
|
val_whole = ((val3 & 0x7f) << 21) +
|
|
((val2 & 0x7f) << 14) +
|
|
((val1 & 0x7f) << 7) +
|
|
(val0 & 0x7f);
|
|
|
|
tmp0 = g_bw_dhires_convert[val_whole & 0xf];
|
|
val_whole = val_whole >> 4;
|
|
tmp1 = g_bw_dhires_convert[val_whole & 0xf];
|
|
val_whole = val_whole >> 4;
|
|
tmp2 = g_bw_dhires_convert[val_whole & 0xf];
|
|
val_whole = val_whole >> 4;
|
|
tmp3 = g_bw_dhires_convert[val_whole & 0xf];
|
|
val_whole = val_whole >> 4;
|
|
tmp4 = g_bw_dhires_convert[val_whole & 0xf];
|
|
val_whole = val_whole >> 4;
|
|
tmp5 = g_bw_dhires_convert[val_whole & 0xf];
|
|
val_whole = val_whole >> 4;
|
|
tmp6 = g_bw_dhires_convert[val_whole & 0xf];
|
|
|
|
img_ptr[0] = tmp0 + palette_add;
|
|
img_ptr[1] = tmp1 + palette_add;
|
|
img_ptr[2] = tmp2 + palette_add;
|
|
img_ptr[3] = tmp3 + palette_add;
|
|
img_ptr[4] = tmp4 + palette_add;
|
|
img_ptr[5] = tmp5 + palette_add;
|
|
img_ptr[6] = tmp6 + palette_add;
|
|
|
|
img_ptr2[0] = tmp0 + palette_add;
|
|
img_ptr2[1] = tmp1 + palette_add;
|
|
img_ptr2[2] = tmp2 + palette_add;
|
|
img_ptr2[3] = tmp3 + palette_add;
|
|
img_ptr2[4] = tmp4 + palette_add;
|
|
img_ptr2[5] = tmp5 + palette_add;
|
|
img_ptr2[6] = tmp6 + palette_add;
|
|
|
|
img_ptr += 7;
|
|
img_ptr2 += 7;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < num_lines; i++) {
|
|
g_a2_line_left_edge[st_line + i] = (left*14);
|
|
g_a2_line_right_edge[st_line + i] = (right*14);
|
|
}
|
|
|
|
g_need_redraw = 0;
|
|
}
|
|
|
|
void
|
|
redraw_changed_dbl_hires_color(int start_offset, int start_line, int num_lines,
|
|
int reparse, byte *screen_data, int pixels_per_line)
|
|
{
|
|
word32 *ch_ptr;
|
|
word32 *img_ptr, *img_ptr2;
|
|
byte *slow_mem_ptr;
|
|
byte *b_ptr;
|
|
word32 mask_per_line;
|
|
word32 ch_mask;
|
|
word32 ch_tmp;
|
|
word32 mem_ptr;
|
|
word32 val0, val1, val2, val3;
|
|
word32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
|
|
word32 val_whole;
|
|
word32 prev_val;
|
|
word32 line_mask;
|
|
word32 palette_add;
|
|
int y;
|
|
int x1, x2;
|
|
int ch_bitpos;
|
|
int bits_per_line;
|
|
int ch_shift_amount;
|
|
int shift_per;
|
|
int left, right;
|
|
int st_line;
|
|
int i;
|
|
|
|
st_line = start_line;
|
|
start_line = start_line >> 3;
|
|
|
|
palette_add = (g_a2vid_palette << 4);
|
|
palette_add = palette_add + (palette_add << 8) + (palette_add << 16) +
|
|
(palette_add << 24);
|
|
|
|
left = 40;
|
|
right = 0;
|
|
|
|
for(y = st_line; y < (st_line + num_lines); y++) {
|
|
line_mask = 1 << (y >> 3);
|
|
mem_ptr = 0x2000 + (((y & 7) * 0x400) + g_screen_index[y >> 3] +
|
|
start_offset);
|
|
|
|
CH_SETUP_A2_VID(mem_ptr, ch_mask, reparse, 1);
|
|
|
|
if(ch_mask == 0) {
|
|
continue;
|
|
}
|
|
|
|
/* dbl-hires also depends on adjacent bits, so reparse */
|
|
/* adjacent regions so that if bits on the edge change, */
|
|
/* redrawing is correct */
|
|
ch_mask = ch_mask | (ch_mask >> 1) | (ch_mask << 1);
|
|
ch_mask = -1;
|
|
|
|
shift_per = (1 << SHIFT_PER_CHANGE);
|
|
|
|
g_a2_screen_buffer_changed |= line_mask;
|
|
|
|
for(x1 = 0; x1 < 40; x1 += shift_per) {
|
|
|
|
CH_LOOP_A2_VID(ch_mask, ch_tmp);
|
|
|
|
left = MIN(x1, left);
|
|
right = MAX(x1 + shift_per, right);
|
|
|
|
slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]);
|
|
b_ptr = &screen_data[(y*2)*pixels_per_line + x1*14];
|
|
img_ptr = (word32 *)b_ptr;
|
|
img_ptr2 = (word32 *)(b_ptr + pixels_per_line);
|
|
|
|
for(x2 = 0; x2 < shift_per; x2 += 2) {
|
|
val0 = slow_mem_ptr[0x10000];
|
|
val1 = slow_mem_ptr[0];
|
|
val2 = slow_mem_ptr[0x10001];
|
|
val3 = slow_mem_ptr[1];
|
|
|
|
prev_val = 0;
|
|
if((x1 + x2) > 0) {
|
|
prev_val = (slow_mem_ptr[-1] >> 3) &0xf;
|
|
}
|
|
val_whole = ((val3 & 0x7f) << 25) +
|
|
((val2 & 0x7f) << 18) +
|
|
((val1 & 0x7f) << 11) +
|
|
((val0 & 0x7f) << 4) + prev_val;
|
|
|
|
tmp0 = g_dhires_convert[val_whole & 0xfff];
|
|
val_whole = val_whole >> 4;
|
|
tmp1 = g_dhires_convert[val_whole & 0xfff];
|
|
val_whole = val_whole >> 4;
|
|
tmp2 = g_dhires_convert[val_whole & 0xfff];
|
|
val_whole = val_whole >> 4;
|
|
tmp3 = g_dhires_convert[val_whole & 0xfff];
|
|
val_whole = val_whole >> 4;
|
|
tmp4 = g_dhires_convert[val_whole & 0xfff];
|
|
val_whole = val_whole >> 4;
|
|
tmp5 = g_dhires_convert[val_whole & 0xfff];
|
|
val_whole = val_whole >> 4;
|
|
if((x1 + x2 + 2) < 40) {
|
|
val_whole += (slow_mem_ptr[0x10002]<<8);
|
|
}
|
|
tmp6 = g_dhires_convert[val_whole & 0xfff];
|
|
|
|
img_ptr[0] = tmp0 + palette_add;
|
|
img_ptr[1] = tmp1 + palette_add;
|
|
img_ptr[2] = tmp2 + palette_add;
|
|
img_ptr[3] = tmp3 + palette_add;
|
|
img_ptr[4] = tmp4 + palette_add;
|
|
img_ptr[5] = tmp5 + palette_add;
|
|
img_ptr[6] = tmp6 + palette_add;
|
|
|
|
img_ptr2[0] = tmp0 + palette_add;
|
|
img_ptr2[1] = tmp1 + palette_add;
|
|
img_ptr2[2] = tmp2 + palette_add;
|
|
img_ptr2[3] = tmp3 + palette_add;
|
|
img_ptr2[4] = tmp4 + palette_add;
|
|
img_ptr2[5] = tmp5 + palette_add;
|
|
img_ptr2[6] = tmp6 + palette_add;
|
|
|
|
slow_mem_ptr += 2;
|
|
img_ptr += 7;
|
|
img_ptr2 += 7;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < num_lines; i++) {
|
|
g_a2_line_left_edge[st_line + i] = (left*14);
|
|
g_a2_line_right_edge[st_line + i] = (right*14);
|
|
}
|
|
|
|
g_need_redraw = 0;
|
|
}
|
|
|
|
int
|
|
video_rebuild_super_hires_palette(word32 scan_info, int line, int reparse)
|
|
{
|
|
word32 *word_ptr;
|
|
word32 *ch_ptr;
|
|
byte *byte_ptr;
|
|
word32 ch_mask, mask_per_line;
|
|
word32 tmp;
|
|
word32 scan, old_scan;
|
|
int palette_changed;
|
|
int diff0, diff1, diff2;
|
|
int val0, val1, val2;
|
|
int diffs;
|
|
int low_delta, low_color;
|
|
int delta;
|
|
int full;
|
|
int ch_bit_offset, ch_word_offset;
|
|
int bits_per_line;
|
|
int palette;
|
|
int j, k;
|
|
|
|
palette_changed = 0;
|
|
palette = scan_info & 0xf;
|
|
|
|
ch_ptr = &(slow_mem_changed[0x9e00 >> CHANGE_SHIFT]);
|
|
ch_bit_offset = (palette << 5) >> SHIFT_PER_CHANGE;
|
|
ch_word_offset = ch_bit_offset >> 5;
|
|
ch_bit_offset = ch_bit_offset & 0x1f;
|
|
bits_per_line = (0x20 >> SHIFT_PER_CHANGE);
|
|
mask_per_line = -(1 << (32 - bits_per_line));
|
|
mask_per_line = mask_per_line >> ch_bit_offset;
|
|
|
|
ch_mask = ch_ptr[ch_word_offset] & mask_per_line;
|
|
ch_ptr[ch_word_offset] &= ~mask_per_line; /* clear the bits */
|
|
|
|
old_scan = g_superhires_scan_save[line];
|
|
scan = (scan_info & 0xfaf) + (g_palette_change_cnt[palette] << 12);
|
|
g_superhires_scan_save[line] = scan;
|
|
|
|
#if 0
|
|
if(line == 1) {
|
|
word_ptr = (word32 *)&(g_slow_memory_ptr[0x19e00+palette*0x20]);
|
|
printf("y1vrshp, ch:%08x, s:%08x,os:%08x %d = %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
|
ch_mask, scan, old_scan, reparse,
|
|
word_ptr[0], word_ptr[1], word_ptr[2], word_ptr[3],
|
|
word_ptr[4], word_ptr[5], word_ptr[6], word_ptr[7]);
|
|
}
|
|
#endif
|
|
|
|
diffs = reparse | ((scan ^ old_scan) & 0xf0f);
|
|
/* we must do full reparse if palette changed for this line */
|
|
|
|
if(!diffs && (ch_mask == 0) && (((scan ^ old_scan) & (~0xf0)) == 0)) {
|
|
/* nothing changed, get out fast */
|
|
return 0;
|
|
}
|
|
|
|
if(ch_mask) {
|
|
/* indicates the palette has changed, and other scan lines */
|
|
/* using this palette need to do a full 32-byte compare to */
|
|
/* decide if they need to update or not */
|
|
g_palette_change_cnt[palette]++;
|
|
}
|
|
|
|
word_ptr = (word32 *)&(g_slow_memory_ptr[0x19e00 + palette*0x20]);
|
|
for(j = 0; j < 8; j++) {
|
|
if(word_ptr[j] != g_saved_line_palettes[line][j]) {
|
|
diffs = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(diffs == 0) {
|
|
return 0;
|
|
}
|
|
|
|
/* first, save this word_ptr into saved_line_palettes */
|
|
byte_ptr = (byte *)word_ptr;
|
|
for(j = 0; j < 8; j++) {
|
|
g_saved_line_palettes[line][j] = word_ptr[j];
|
|
}
|
|
|
|
full = g_installed_full_superhires_colormap;
|
|
|
|
if(!full && palette == g_a2vid_palette) {
|
|
/* construct new color approximations from lores */
|
|
for(j = 0; j < 16; j++) {
|
|
tmp = *byte_ptr++;
|
|
val2 = (*byte_ptr++) & 0xf;
|
|
val0 = tmp & 0xf;
|
|
val1 = (tmp >> 4) & 0xf;
|
|
low_delta = 0x1000;
|
|
low_color = 0x0;
|
|
for(k = 0; k < 16; k++) {
|
|
diff0 = g_expanded_col_0[k] - val0;
|
|
diff1 = g_expanded_col_1[k] - val1;
|
|
diff2 = g_expanded_col_2[k] - val2;
|
|
if(diff0 < 0) {
|
|
diff0 = -diff0;
|
|
}
|
|
if(diff1 < 0) {
|
|
diff1 = -diff1;
|
|
}
|
|
if(diff2 < 0) {
|
|
diff2 = -diff2;
|
|
}
|
|
delta = diff0 + diff1 + diff2;
|
|
if(delta < low_delta) {
|
|
low_delta = delta;
|
|
low_color = k;
|
|
}
|
|
}
|
|
|
|
g_a2vid_palette_remap[j] = low_color;
|
|
}
|
|
}
|
|
|
|
byte_ptr = (byte *)word_ptr;
|
|
/* this palette has changed */
|
|
for(j = 0; j < 16; j++) {
|
|
val0 = *byte_ptr++;
|
|
val1 = *byte_ptr++;
|
|
video_update_color_array(palette*16 + j, (val1<<8) + val0);
|
|
}
|
|
|
|
g_palette_change_summary = 1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
#define SUPER_TYPE redraw_changed_super_hires_oneline_nofill_8
|
|
#define SUPER_FILL 0
|
|
#define SUPER_PIXEL_SIZE 8
|
|
#include "superhires.h"
|
|
#undef SUPER_TYPE
|
|
#undef SUPER_FILL
|
|
#undef SUPER_PIXEL_SIZE
|
|
|
|
#define SUPER_TYPE redraw_changed_super_hires_oneline_nofill_16
|
|
#define SUPER_FILL 0
|
|
#define SUPER_PIXEL_SIZE 16
|
|
#include "superhires.h"
|
|
#undef SUPER_TYPE
|
|
#undef SUPER_FILL
|
|
#undef SUPER_PIXEL_SIZE
|
|
|
|
#define SUPER_TYPE redraw_changed_super_hires_oneline_nofill_32
|
|
#define SUPER_FILL 0
|
|
#define SUPER_PIXEL_SIZE 32
|
|
#include "superhires.h"
|
|
#undef SUPER_TYPE
|
|
#undef SUPER_FILL
|
|
#undef SUPER_PIXEL_SIZE
|
|
|
|
#define SUPER_TYPE redraw_changed_super_hires_oneline_fill_8
|
|
#define SUPER_FILL 1
|
|
#define SUPER_PIXEL_SIZE 8
|
|
#include "superhires.h"
|
|
#undef SUPER_TYPE
|
|
#undef SUPER_FILL
|
|
#undef SUPER_PIXEL_SIZE
|
|
|
|
#define SUPER_TYPE redraw_changed_super_hires_oneline_fill_16
|
|
#define SUPER_FILL 1
|
|
#define SUPER_PIXEL_SIZE 16
|
|
#include "superhires.h"
|
|
#undef SUPER_TYPE
|
|
#undef SUPER_FILL
|
|
#undef SUPER_PIXEL_SIZE
|
|
|
|
#define SUPER_TYPE redraw_changed_super_hires_oneline_fill_32
|
|
#define SUPER_FILL 1
|
|
#define SUPER_PIXEL_SIZE 32
|
|
#include "superhires.h"
|
|
#undef SUPER_TYPE
|
|
#undef SUPER_FILL
|
|
#undef SUPER_PIXEL_SIZE
|
|
|
|
|
|
|
|
void
|
|
redraw_changed_super_hires(int start_offset, int start_line, int num_lines,
|
|
int in_reparse, byte *screen_data)
|
|
{
|
|
word32 *ch_ptr;
|
|
word32 mask_per_line;
|
|
word32 all_checks;
|
|
word32 check0, check1, mask0, mask1;
|
|
word32 this_check;
|
|
word32 tmp;
|
|
word32 line_mask;
|
|
word32 pal;
|
|
word32 scan, old_scan;
|
|
word32 kd_tmp_debug;
|
|
int y;
|
|
int bits_per_line;
|
|
int a2vid_palette;
|
|
int type;
|
|
int left, right;
|
|
int st_line;
|
|
int check_bit_pos, check_word_off;
|
|
int pixel_size, pixel_size_type;
|
|
int use_a2vid_palette, mode_640;
|
|
int pixels_per_line;
|
|
int ret;
|
|
int i;
|
|
|
|
st_line = start_line;
|
|
start_line = start_line >> 3;
|
|
|
|
pixel_size = g_kimage_superhires.mdepth;
|
|
pixels_per_line = g_kimage_superhires.width_act;
|
|
|
|
pixel_size_type = (pixel_size >> 3) - 1;
|
|
/* pixel_size_type is now: 0=8bit, 1=16bit, 3=32bit */
|
|
if(pixel_size_type >= 3) {
|
|
pixel_size_type = 2;
|
|
}
|
|
|
|
kd_tmp_debug = g_a2_screen_buffer_changed;
|
|
|
|
line_mask = 1 << (start_line);
|
|
|
|
ch_ptr = &(slow_mem_changed[(0x2000) >> CHANGE_SHIFT]);
|
|
bits_per_line = 160 >> SHIFT_PER_CHANGE;
|
|
mask_per_line = -(1 << (32 - bits_per_line));
|
|
|
|
if(SHIFT_PER_CHANGE != 3) {
|
|
halt_printf("SHIFT_PER_CHANGE must be 3!\n");
|
|
return;
|
|
}
|
|
|
|
a2vid_palette = g_a2vid_palette;
|
|
if(g_installed_full_superhires_colormap) {
|
|
a2vid_palette = -1;
|
|
} else {
|
|
/* handle palette counting for finding least-used palette */
|
|
if(pixel_size == 8) {
|
|
for(y = 8*start_line; y < 8*(start_line + 1); y++) {
|
|
scan = g_slow_memory_ptr[0x19d00 + y];
|
|
pal = scan & 0xf;
|
|
g_shr_palette_used[pal]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
all_checks = 0;
|
|
check0 = 0;
|
|
check1 = 0;
|
|
for(y = st_line; y < (st_line + num_lines); y++) {
|
|
scan = g_slow_memory_ptr[0x19d00 + y];
|
|
check_bit_pos = bits_per_line * y;
|
|
check_word_off = check_bit_pos >> 5; /* 32 bits per word */
|
|
check_bit_pos = check_bit_pos & 0x1f; /* 5-bit bit_pos */
|
|
check0 = ch_ptr[check_word_off];
|
|
check1 = ch_ptr[check_word_off+1];
|
|
mask0 = mask_per_line >> check_bit_pos;
|
|
mask1 = 0;
|
|
this_check = check0 << check_bit_pos;
|
|
/* move indicated bit to MSbit position */
|
|
if((check_bit_pos + bits_per_line) > 32) {
|
|
this_check |= (check1 >> (32 - check_bit_pos));
|
|
mask1 = mask_per_line << (32 - check_bit_pos);
|
|
}
|
|
|
|
ch_ptr[check_word_off] = check0 & ~mask0;
|
|
ch_ptr[check_word_off+1] = check1 & ~mask1;
|
|
|
|
this_check = this_check & mask_per_line;
|
|
old_scan = g_superhires_scan_save[y];
|
|
use_a2vid_palette = ((scan & 0xf) == (word32)a2vid_palette);
|
|
scan = (scan + (a2vid_palette << 8)) & 0xfff;
|
|
|
|
ret = video_rebuild_super_hires_palette(scan, y, in_reparse);
|
|
#if 0
|
|
if(y == 1) {
|
|
printf("y1, ch:%08x, ret:%d, scan:%03x, os:%03x\n",
|
|
this_check, ret, scan, old_scan);
|
|
}
|
|
#endif
|
|
if(ret || in_reparse || ((scan ^ old_scan) & 0xa0)) {
|
|
/* 0x80 == mode640, 0x20 = fill */
|
|
this_check = -1;
|
|
}
|
|
|
|
if(this_check == 0) {
|
|
continue;
|
|
}
|
|
|
|
mode_640 = (scan & 0x80);
|
|
if(mode_640) {
|
|
g_num_lines_superhires640++;
|
|
}
|
|
|
|
type = ((scan >> 5) & 1) + (pixel_size_type << 1);
|
|
if(type & 1) {
|
|
/* fill mode--redraw whole line */
|
|
this_check = -1;
|
|
}
|
|
|
|
all_checks |= this_check;
|
|
|
|
g_a2_screen_buffer_changed |= line_mask;
|
|
|
|
|
|
switch(type) {
|
|
case 0: /* nofill, 8 bit pixels */
|
|
redraw_changed_super_hires_oneline_nofill_8(
|
|
screen_data, pixels_per_line, y, scan,
|
|
this_check, use_a2vid_palette, mode_640);
|
|
break;
|
|
case 1: /* fill, 8 bit pixels */
|
|
redraw_changed_super_hires_oneline_fill_8(
|
|
screen_data, pixels_per_line, y, scan,
|
|
this_check, use_a2vid_palette, mode_640);
|
|
break;
|
|
case 2: /* nofill, 16 bit pixels */
|
|
redraw_changed_super_hires_oneline_nofill_16(
|
|
screen_data, pixels_per_line, y, scan,
|
|
this_check, use_a2vid_palette, mode_640);
|
|
break;
|
|
case 3: /* fill, 16 bit pixels */
|
|
redraw_changed_super_hires_oneline_fill_16(
|
|
screen_data, pixels_per_line, y, scan,
|
|
this_check, use_a2vid_palette, mode_640);
|
|
break;
|
|
case 4: /* nofill, 32 bit pixels */
|
|
redraw_changed_super_hires_oneline_nofill_32(
|
|
screen_data, pixels_per_line, y, scan,
|
|
this_check, use_a2vid_palette, mode_640);
|
|
break;
|
|
case 5: /* fill, 32 byte pixels */
|
|
redraw_changed_super_hires_oneline_fill_32(
|
|
screen_data, pixels_per_line, y, scan,
|
|
this_check, use_a2vid_palette, mode_640);
|
|
break;
|
|
default:
|
|
halt_printf("type: %d bad!\n", type);
|
|
}
|
|
}
|
|
|
|
left = 4*40;
|
|
right = 0;
|
|
|
|
tmp = all_checks;
|
|
if(all_checks) {
|
|
for(i = 0; i < 160; i += 8) {
|
|
if(tmp & 0x80000000) {
|
|
left = MIN(i, left);
|
|
right = MAX(i + 8, right);
|
|
}
|
|
tmp = tmp << 1;
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < num_lines; i++) {
|
|
g_a2_line_left_edge[st_line + i] = 4*left;
|
|
g_a2_line_right_edge[st_line + i] = 4*right;
|
|
}
|
|
|
|
#if 0
|
|
if((g_a2_screen_buffer_changed & (1 << start_line)) != 0) {
|
|
if(((g_full_refresh_needed & (1 << start_line)) == 0) &&
|
|
left >= right) {
|
|
halt_printf("shr: line: %d, left: %d, right:%d\n",
|
|
start_line, left, right);
|
|
printf("mask_per_line: %08x, all_checks: %08x\n",
|
|
mask_per_line, all_checks);
|
|
printf("check0,1 = %08x,%08x\n", check0, check1);
|
|
printf("a2_screen_chang: %08x\n", kd_tmp_debug);
|
|
#ifdef HPUX
|
|
U_STACK_TRACE();
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
|
|
g_need_redraw = 0;
|
|
}
|
|
|
|
void
|
|
display_screen()
|
|
{
|
|
video_update_through_line(262);
|
|
}
|
|
|
|
void
|
|
video_update_event_line(int line)
|
|
{
|
|
int new_line;
|
|
|
|
video_update_through_line(line);
|
|
|
|
new_line = line + g_line_ref_amt;
|
|
if(new_line < 200) {
|
|
if(!g_config_control_panel) {
|
|
add_event_vid_upd(new_line);
|
|
}
|
|
} else if(line >= 262) {
|
|
video_update_through_line(0);
|
|
if(!g_config_control_panel) {
|
|
add_event_vid_upd(1); /* add event for new screen */
|
|
}
|
|
}
|
|
|
|
if(g_video_extra_check_inputs) {
|
|
if(g_video_dcycs_check_input < g_cur_dcycs) {
|
|
video_check_input_events();
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
video_check_input_events()
|
|
{
|
|
word32 start_time, end_time;
|
|
|
|
g_video_dcycs_check_input = g_cur_dcycs + 4000.0;
|
|
|
|
GET_ITIMER(start_time);
|
|
check_input_events();
|
|
GET_ITIMER(end_time);
|
|
|
|
g_cycs_in_check_input += (end_time - start_time);
|
|
}
|
|
|
|
void
|
|
video_update_through_line(int line)
|
|
{
|
|
register word32 start_time;
|
|
register word32 end_time;
|
|
int *mode_ptr;
|
|
word32 mask;
|
|
int last_line, num_lines;
|
|
int must_reparse;
|
|
int new_all_stat, prev_all_stat;
|
|
int new_stat, prev_stat;
|
|
int i;
|
|
|
|
#if 0
|
|
vid_printf("\nvideo_upd for line %d, lines: %06x\n", line,
|
|
get_lines_since_vbl(g_cur_dcycs));
|
|
#endif
|
|
|
|
GET_ITIMER(start_time);
|
|
|
|
video_update_all_stat_through_line(line);
|
|
|
|
i = g_vid_update_last_line;
|
|
|
|
last_line = MIN(200, line+1); /* go through line, but not past 200 */
|
|
|
|
prev_stat = -2;
|
|
prev_all_stat = -2;
|
|
num_lines = 0;
|
|
must_reparse = 0;
|
|
for(i = g_vid_update_last_line; i < last_line; i++) {
|
|
new_all_stat = g_a2_new_all_stat[i];
|
|
if(new_all_stat != g_a2_cur_all_stat[i]) {
|
|
/* regen line_stat for this line */
|
|
g_a2_cur_all_stat[i] = new_all_stat;
|
|
if(new_all_stat == prev_all_stat) {
|
|
/* save a lookup */
|
|
new_stat = prev_stat;
|
|
} else {
|
|
new_stat = video_all_stat_to_line_stat(i,
|
|
new_all_stat);
|
|
}
|
|
if(new_stat != g_a2_line_stat[i]) {
|
|
/* status changed */
|
|
g_a2_line_stat[i] = new_stat;
|
|
mode_ptr = video_update_kimage_ptr(i, new_stat);
|
|
if(mode_ptr[i] != new_stat) {
|
|
must_reparse = 1;
|
|
mode_ptr[i] = new_stat;
|
|
}
|
|
mask = 1 << (line >> 3);
|
|
g_full_refresh_needed |= mask;
|
|
g_a2_screen_buffer_changed |= mask;
|
|
}
|
|
}
|
|
|
|
new_stat = g_a2_line_stat[i];
|
|
|
|
if( ((new_stat == prev_stat) && ((i & 7) != 0)) ||
|
|
(num_lines == 0) ) {
|
|
/* merge prev and this together */
|
|
prev_stat = new_stat;
|
|
num_lines++;
|
|
continue;
|
|
}
|
|
|
|
/* else, we must call refresh */
|
|
video_refresh_lines(i - num_lines, num_lines, must_reparse);
|
|
num_lines = 1;
|
|
prev_all_stat = -1;
|
|
prev_stat = new_stat;
|
|
must_reparse = 0;
|
|
}
|
|
if(num_lines > 0) {
|
|
video_refresh_lines(i - num_lines, num_lines, must_reparse);
|
|
}
|
|
|
|
g_vid_update_last_line = last_line;
|
|
|
|
/* deal with border */
|
|
if(line >= 262) {
|
|
if(g_num_lines_prev_superhires != g_num_lines_superhires) {
|
|
/* switched in/out from superhires--refresh borders */
|
|
g_border_sides_refresh_needed = 1;
|
|
}
|
|
refresh_border();
|
|
|
|
if(g_status_refresh_needed) {
|
|
g_status_refresh_needed = 0;
|
|
x_redraw_status_lines();
|
|
}
|
|
}
|
|
GET_ITIMER(end_time);
|
|
|
|
g_cycs_in_refresh_line += (end_time - start_time);
|
|
|
|
if(line >= 262) {
|
|
GET_ITIMER(start_time);
|
|
if(g_palette_change_summary) {
|
|
g_palette_change_summary = 0;
|
|
video_update_colormap();
|
|
}
|
|
|
|
video_push_kimages();
|
|
GET_ITIMER(end_time);
|
|
g_cycs_in_refresh_ximage += (end_time - start_time);
|
|
|
|
g_num_lines_prev_superhires = g_num_lines_superhires;
|
|
g_num_lines_prev_superhires640 = g_num_lines_superhires640;
|
|
g_num_lines_superhires = 0;
|
|
g_num_lines_superhires640 = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
video_refresh_lines(int st_line, int num_lines, int must_reparse)
|
|
{
|
|
byte *ptr;
|
|
int line;
|
|
int stat;
|
|
int mode;
|
|
int dbl, page, color;
|
|
int altchar, bg_color, text_color;
|
|
int pixels_per_line;
|
|
int i;
|
|
|
|
line = st_line;
|
|
|
|
/* do some basic checking, num_lines should be 1-8, and */
|
|
/* st_line+num_lines-1 cannot roll over 8 */
|
|
if((num_lines < 1) || (num_lines > 8) ||
|
|
(((st_line & 7) + num_lines) > 8) ) {
|
|
halt_printf("video_refresh_lines called with %d, %d\n",
|
|
st_line, num_lines);
|
|
return;
|
|
}
|
|
|
|
stat = g_a2_line_stat[line];
|
|
ptr = g_a2_line_kimage[line]->data_ptr;
|
|
pixels_per_line = g_a2_line_kimage[line]->width_act;
|
|
|
|
/* do not zero g_a2_line_left/right_edge here since text/gr routs */
|
|
/* need to leave stale values around for drawing to work correctly */
|
|
/* all routs force in new left/right when there are screen changes */
|
|
|
|
dbl = stat & 1;
|
|
color = (stat >> 1) & 1;
|
|
page = (stat >> 2) & 1;
|
|
mode = (stat >> 4) & 7;
|
|
|
|
#if 0
|
|
printf("refresh line: %d, stat: %04x\n", line, stat);
|
|
#endif
|
|
|
|
switch(mode) {
|
|
case MODE_TEXT:
|
|
altchar = (stat >> 7) & 1;
|
|
bg_color = (stat >> 8) & 0xf;
|
|
text_color = (stat >> 12) & 0xf;
|
|
if(dbl) {
|
|
redraw_changed_text_80(0x000 + page*0x400, st_line,
|
|
num_lines, must_reparse, ptr, altchar, bg_color,
|
|
text_color, pixels_per_line);
|
|
} else {
|
|
redraw_changed_text_40(0x000 + page*0x400, st_line,
|
|
num_lines, must_reparse, ptr, altchar, bg_color,
|
|
text_color, pixels_per_line);
|
|
}
|
|
break;
|
|
case MODE_GR:
|
|
if(dbl) {
|
|
redraw_changed_dbl_gr(0x000 + page*0x400, st_line,
|
|
num_lines, must_reparse, ptr, pixels_per_line);
|
|
} else {
|
|
redraw_changed_gr(0x000 + page*0x400, st_line,
|
|
num_lines, must_reparse, ptr, pixels_per_line);
|
|
}
|
|
break;
|
|
case MODE_HGR:
|
|
if(dbl) {
|
|
redraw_changed_dbl_hires(0x000 + page*0x2000, st_line,
|
|
num_lines, color, must_reparse, ptr,
|
|
pixels_per_line);
|
|
} else {
|
|
redraw_changed_hires(0x000 + page*0x2000, st_line,
|
|
num_lines, color, must_reparse, ptr,
|
|
pixels_per_line);
|
|
}
|
|
break;
|
|
case MODE_SUPER_HIRES:
|
|
g_num_lines_superhires++;
|
|
redraw_changed_super_hires(0, st_line, num_lines,
|
|
must_reparse, ptr);
|
|
break;
|
|
case MODE_BORDER:
|
|
if(line < 192) {
|
|
halt_printf("Border line not 192: %d\n", line);
|
|
}
|
|
for(i = 0; i < num_lines; i++) {
|
|
g_a2_line_left_edge[line + i] = 0;
|
|
g_a2_line_right_edge[line + i] = 560;
|
|
}
|
|
if(g_border_line24_refresh_needed) {
|
|
g_border_line24_refresh_needed = 0;
|
|
g_a2_screen_buffer_changed |= (1 << 24);
|
|
}
|
|
break;
|
|
default:
|
|
halt_printf("refresh screen: mode: 0x%02x unknown!\n", mode);
|
|
exit(7);
|
|
}
|
|
}
|
|
|
|
void
|
|
refresh_border()
|
|
{
|
|
/**ZZZZ***/
|
|
}
|
|
|
|
// OG Added video_release_kimages proto
|
|
void video_release_kimages();
|
|
|
|
void
|
|
end_screen()
|
|
{
|
|
printf("In end_screen\n");
|
|
|
|
// OG Free up allocated images
|
|
video_release_kimages();
|
|
xdriver_end();
|
|
}
|
|
|
|
byte g_font_array[256][8] = {
|
|
#include "gsportfont.h"
|
|
};
|
|
|
|
void
|
|
read_a2_font()
|
|
{
|
|
byte *f40_e_ptr;
|
|
byte *f40_o_ptr;
|
|
byte *f80_0_ptr, *f80_1_ptr, *f80_2_ptr, *f80_3_ptr;
|
|
int char_num;
|
|
int j, k;
|
|
int val0;
|
|
int mask;
|
|
int pix;
|
|
|
|
for(char_num = 0; char_num < 0x100; char_num++) {
|
|
for(j = 0; j < 8; j++) {
|
|
val0 = g_font_array[char_num][j];
|
|
|
|
mask = 0x80;
|
|
|
|
for(k = 0; k < 3; k++) {
|
|
g_font80_off0_bits[char_num][j][k] = 0;
|
|
g_font80_off1_bits[char_num][j][k] = 0;
|
|
g_font80_off2_bits[char_num][j][k] = 0;
|
|
g_font80_off3_bits[char_num][j][k] = 0;
|
|
g_font40_even_bits[char_num][j][k] = 0;
|
|
g_font40_odd_bits[char_num][j][k] = 0;
|
|
}
|
|
g_font40_even_bits[char_num][j][3] = 0;
|
|
g_font40_odd_bits[char_num][j][3] = 0;
|
|
|
|
f40_e_ptr = (byte *)&g_font40_even_bits[char_num][j][0];
|
|
f40_o_ptr = (byte *)&g_font40_odd_bits[char_num][j][0];
|
|
|
|
f80_0_ptr = (byte *)&g_font80_off0_bits[char_num][j][0];
|
|
f80_1_ptr = (byte *)&g_font80_off1_bits[char_num][j][0];
|
|
f80_2_ptr = (byte *)&g_font80_off2_bits[char_num][j][0];
|
|
f80_3_ptr = (byte *)&g_font80_off3_bits[char_num][j][0];
|
|
|
|
for(k = 0; k < 7; k++) {
|
|
pix = 0;
|
|
if(val0 & mask) {
|
|
pix = 0xf;
|
|
}
|
|
|
|
f40_e_ptr[2*k] = pix;
|
|
f40_e_ptr[2*k+1] = pix;
|
|
|
|
f40_o_ptr[2*k+2] = pix;
|
|
f40_o_ptr[2*k+3] = pix;
|
|
|
|
f80_0_ptr[k] = pix;
|
|
f80_1_ptr[k+1] = pix;
|
|
f80_2_ptr[k+2] = pix;
|
|
f80_3_ptr[k+3] = pix;
|
|
|
|
mask = mask >> 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Helper routine for the *driver.c files */
|
|
|
|
void
|
|
video_get_kimage(Kimage *kimage_ptr, int extend_info, int depth, int mdepth)
|
|
{
|
|
int width;
|
|
int height;
|
|
|
|
width = A2_WINDOW_WIDTH;
|
|
height = A2_WINDOW_HEIGHT;
|
|
if(extend_info & 1) {
|
|
/* Border at top and bottom of screen */
|
|
width = X_A2_WINDOW_WIDTH;
|
|
height = X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT + 2*8;
|
|
}
|
|
if(extend_info & 2) {
|
|
/* Border at sides of screen */
|
|
width = BORDER_WIDTH + EFF_BORDER_WIDTH;
|
|
height = A2_WINDOW_HEIGHT;
|
|
}
|
|
|
|
kimage_ptr->dev_handle = 0;
|
|
kimage_ptr->dev_handle2 = 0;
|
|
kimage_ptr->data_ptr = 0;
|
|
kimage_ptr->width_req = width;
|
|
kimage_ptr->width_act = width;
|
|
kimage_ptr->height = height;
|
|
kimage_ptr->depth = depth;
|
|
kimage_ptr->mdepth = mdepth;
|
|
kimage_ptr->aux_info = 0;
|
|
|
|
x_get_kimage(kimage_ptr);
|
|
}
|
|
|
|
void
|
|
video_get_kimages()
|
|
{
|
|
video_get_kimage(&g_kimage_text[0], 0, 8, 8);
|
|
video_get_kimage(&g_kimage_text[1], 0, 8, 8);
|
|
video_get_kimage(&g_kimage_hires[0], 0, 8, 8);
|
|
video_get_kimage(&g_kimage_hires[1], 0, 8, 8);
|
|
video_get_kimage(&g_kimage_superhires, 0, g_screen_depth,
|
|
g_screen_mdepth);
|
|
video_get_kimage(&g_kimage_border_special, 1, g_screen_depth,
|
|
g_screen_mdepth);
|
|
video_get_kimage(&g_kimage_border_sides, 2, g_screen_depth,
|
|
g_screen_mdepth);
|
|
}
|
|
|
|
// OG Added video_release_kimages (to match video_get_kimages)
|
|
void video_release_kimages()
|
|
{
|
|
extern void x_release_kimage(Kimage *kimage_ptr);
|
|
|
|
x_release_kimage(&g_kimage_text[0]);
|
|
x_release_kimage(&g_kimage_text[1]);
|
|
x_release_kimage(&g_kimage_hires[0]);
|
|
x_release_kimage(&g_kimage_hires[1]);
|
|
x_release_kimage(&g_kimage_superhires);
|
|
x_release_kimage(&g_kimage_border_special);
|
|
x_release_kimage(&g_kimage_border_sides);
|
|
}
|
|
|
|
|
|
void
|
|
video_convert_kimage_depth(Kimage *kim_in, Kimage *kim_out, int startx,
|
|
int starty, int width, int height)
|
|
{
|
|
byte *indata, *inptr;
|
|
word32 *outdata32, *outptr32;
|
|
word16 *outdata16, *outptr16;
|
|
word32 *palptr;
|
|
int out_width, in_width;
|
|
int x, y;
|
|
|
|
indata = (byte *)kim_in->data_ptr;
|
|
outdata32 = (word32 *)kim_out->data_ptr;
|
|
outdata16 = (word16 *)kim_out->data_ptr;
|
|
|
|
if(kim_in == &g_kimage_superhires) {
|
|
palptr = &(g_palette_8to1624[0]);
|
|
} else {
|
|
palptr = &(g_a2palette_8to1624[0]);
|
|
}
|
|
if(kim_in->depth != 8) {
|
|
printf("x_convert_kimage_depth from non-8 bit depth: %p\n",
|
|
kim_in);
|
|
exit(1);
|
|
}
|
|
|
|
out_width = kim_out->width_act;
|
|
in_width = kim_in->width_act;
|
|
indata += (starty * in_width + startx);
|
|
outdata32 += (starty * out_width + startx);
|
|
outdata16 += (starty * out_width + startx);
|
|
if(kim_out->mdepth == 16) {
|
|
for(y = 0; y < height; y++) {
|
|
outptr16 = outdata16;
|
|
inptr = indata;
|
|
for(x = 0; x < width; x++) {
|
|
*outptr16++ = palptr[*inptr++];
|
|
}
|
|
outdata16 += out_width;
|
|
indata += in_width;
|
|
}
|
|
} else {
|
|
/* 32-bit depth */
|
|
for(y = 0; y < height; y++) {
|
|
outptr32 = outdata32;
|
|
inptr = indata;
|
|
for(x = 0; x < width; x++) {
|
|
*outptr32++ = palptr[*inptr++];
|
|
}
|
|
outdata32 += out_width;
|
|
indata += in_width;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
video_push_lines(Kimage *kimage_ptr, int start_line, int end_line, int left_pix,
|
|
int right_pix)
|
|
{
|
|
int mdepth_mismatch;
|
|
int srcy;
|
|
int center = 0; // OG added variable to center screen
|
|
|
|
//OG add null pointer check when emulator is restarted
|
|
if (!kimage_ptr)
|
|
{
|
|
printf("warning : video_push_lines(kimage_ptr=null)\n");
|
|
return ;
|
|
}
|
|
|
|
if(left_pix >= right_pix || left_pix < 0 || right_pix <= 0) {
|
|
halt_printf("video_push_lines: lines %d to %d, pix %d to %d\n",
|
|
start_line, end_line, left_pix, right_pix);
|
|
printf("a2_screen_buf_ch:%08x, g_full_refr:%08x\n",
|
|
g_a2_screen_buffer_changed, g_full_refresh_needed);
|
|
}
|
|
|
|
srcy = 2*start_line;
|
|
|
|
mdepth_mismatch = (kimage_ptr->mdepth != g_screen_mdepth);
|
|
if(mdepth_mismatch) {
|
|
/* translate from 8-bit pseudo to correct visual */
|
|
video_convert_kimage_depth(kimage_ptr, &g_mainwin_kimage,
|
|
left_pix, srcy, (right_pix - left_pix),
|
|
2*(end_line - start_line));
|
|
kimage_ptr = &g_mainwin_kimage;
|
|
}
|
|
g_refresh_bytes_xfer += 2*(end_line - start_line) *
|
|
(right_pix - left_pix);
|
|
|
|
// OG Calculating new center
|
|
if (g_cur_a2_stat & ALL_STAT_SUPER_HIRES)
|
|
center=0;
|
|
else
|
|
center=EFF_BORDER_WIDTH - BORDER_WIDTH;
|
|
|
|
// OG shifting image to the center
|
|
x_push_kimage(kimage_ptr, g_video_act_margin_left + left_pix + center,
|
|
g_video_act_margin_top + srcy, left_pix, srcy,
|
|
(right_pix - left_pix), 2*(end_line - start_line));
|
|
}
|
|
|
|
void
|
|
video_push_border_sides_lines(int src_x, int dest_x, int width, int start_line,
|
|
int end_line)
|
|
{
|
|
Kimage *kimage_ptr;
|
|
int srcy;
|
|
|
|
if(start_line < 0 || width < 0) {
|
|
return;
|
|
}
|
|
|
|
#if 0
|
|
printf("push_border_sides lines:%d-%d from %d to %d\n",
|
|
start_line, end_line, end_x - width, end_x);
|
|
#endif
|
|
kimage_ptr = &g_kimage_border_sides;
|
|
g_refresh_bytes_xfer += 2 * (end_line - start_line) * width;
|
|
|
|
srcy = 2 * start_line;
|
|
|
|
// Adjust dext_x to accound for changed margins
|
|
dest_x = dest_x + g_video_act_margin_left - BASE_MARGIN_LEFT;
|
|
if(dest_x < BASE_MARGIN_LEFT) {
|
|
src_x = src_x + g_video_act_margin_left - BASE_MARGIN_LEFT;
|
|
// Don't adjust src_x if doing right border
|
|
}
|
|
if(dest_x < 0) {
|
|
width = width + dest_x;
|
|
src_x = src_x - dest_x;
|
|
dest_x = 0;
|
|
}
|
|
if(src_x < 0) {
|
|
width = width + src_x;
|
|
dest_x = dest_x - src_x;
|
|
src_x = 0;
|
|
}
|
|
if(dest_x + width > g_video_act_width) {
|
|
width = g_video_act_width - dest_x;
|
|
}
|
|
if(width > 0) {
|
|
x_push_kimage(kimage_ptr, dest_x, g_video_act_margin_top + srcy,
|
|
src_x, srcy, width, 2*(end_line - start_line));
|
|
}
|
|
}
|
|
|
|
void
|
|
video_push_border_sides()
|
|
{
|
|
int old_width;
|
|
int prev_line;
|
|
int width;
|
|
int mode;
|
|
int i;
|
|
|
|
#if 0
|
|
printf("refresh border sides!\n");
|
|
#endif
|
|
|
|
/* redraw left sides */
|
|
// OG Left side can alos be "jagged" as a2 screen is now being centered
|
|
|
|
//video_push_border_sides_lines(0, 0, BORDER_WIDTH, 0, 200);
|
|
|
|
prev_line = -1;
|
|
old_width = -1;
|
|
for(i = 0; i < 200; i++) {
|
|
mode = (g_a2_line_stat[i] >> 4) & 7;
|
|
width = EFF_BORDER_WIDTH;
|
|
if(mode == MODE_SUPER_HIRES) {
|
|
width = BORDER_WIDTH;
|
|
}
|
|
if(width != old_width) {
|
|
video_push_border_sides_lines(BORDER_WIDTH,
|
|
0, old_width,
|
|
prev_line, i);
|
|
prev_line = i;
|
|
old_width = width;
|
|
}
|
|
}
|
|
video_push_border_sides_lines(0/*BORDER_WIDTH*/,
|
|
0, old_width, prev_line, 200);
|
|
|
|
/* right side--can be "jagged" */
|
|
prev_line = -1;
|
|
old_width = -1;
|
|
for(i = 0; i < 200; i++) {
|
|
mode = (g_a2_line_stat[i] >> 4) & 7;
|
|
width = EFF_BORDER_WIDTH;
|
|
if(mode == MODE_SUPER_HIRES) {
|
|
width = BORDER_WIDTH;
|
|
}
|
|
if(width != old_width) {
|
|
video_push_border_sides_lines(BORDER_WIDTH,
|
|
X_A2_WINDOW_WIDTH - old_width, old_width,
|
|
prev_line, i);
|
|
prev_line = i;
|
|
old_width = width;
|
|
}
|
|
}
|
|
|
|
video_push_border_sides_lines(0/*BORDER_WIDTH*/,
|
|
X_A2_WINDOW_WIDTH - old_width, old_width, prev_line, 200);
|
|
}
|
|
|
|
void
|
|
video_push_border_special()
|
|
{
|
|
Kimage *kimage_ptr;
|
|
int width, height;
|
|
int src_x, src_y;
|
|
int dest_x, dest_y;
|
|
|
|
kimage_ptr = &g_kimage_border_special;
|
|
width = g_video_act_width;
|
|
g_refresh_bytes_xfer += width * (BASE_MARGIN_TOP + BASE_MARGIN_BOTTOM);
|
|
|
|
// First do bottom border: dest_x from 0 to 640+MARGIN_LEFT+MARGIN_RIGHT
|
|
// and dest_y of BASE_MARGIN_BOTTOM starting at TOP+A2_HEIGHT
|
|
// src_x is dest_x, and src_y is 0.
|
|
dest_y = g_video_act_margin_top + A2_WINDOW_HEIGHT;
|
|
height = g_video_act_margin_bottom;
|
|
src_y = BASE_MARGIN_BOTTOM - height;
|
|
|
|
dest_x = 0;
|
|
src_x = BASE_MARGIN_LEFT - g_video_act_margin_left;
|
|
|
|
if(width > 0 && height > 0) {
|
|
x_push_kimage(kimage_ptr, dest_x, dest_y, src_x, src_y,
|
|
width, height);
|
|
}
|
|
|
|
// Then fix top border: dest_x from 0 to 640+LEFT+RIGHT and
|
|
// dest_y from 0 to TOP. src_x is dest_x, but src_y is
|
|
// BOTTOM to BOTTOM+TOP
|
|
// Just use src_x and dest_x from earlier.
|
|
height = g_video_act_margin_top;
|
|
dest_y = 0;
|
|
src_y = BASE_MARGIN_BOTTOM;
|
|
if(width > 0 && height > 0) {
|
|
x_push_kimage(kimage_ptr, dest_x, dest_y, src_x, src_y,
|
|
width, height);
|
|
}
|
|
}
|
|
|
|
// OG Added window ratio support
|
|
extern int x_calc_ratio(float ratiox,float ratioy);
|
|
|
|
void
|
|
video_push_kimages()
|
|
{
|
|
register word32 start_time;
|
|
register word32 end_time;
|
|
Kimage *last_kim, *cur_kim;
|
|
word32 mask;
|
|
int start;
|
|
int line;
|
|
int left_pix, right_pix;
|
|
int left, right;
|
|
int line_div8;
|
|
float ratiox = 0,ratioy = 0;
|
|
|
|
if(g_border_sides_refresh_needed) {
|
|
g_border_sides_refresh_needed = 0;
|
|
video_push_border_sides();
|
|
}
|
|
if(g_border_special_refresh_needed) {
|
|
g_border_special_refresh_needed = 0;
|
|
video_push_border_special();
|
|
}
|
|
|
|
if(g_a2_screen_buffer_changed == 0) {
|
|
return;
|
|
}
|
|
|
|
GET_ITIMER(start_time);
|
|
|
|
if (x_calc_ratio(ratiox,ratioy))
|
|
{
|
|
line = 0;
|
|
while (1)
|
|
{
|
|
start = line;
|
|
cur_kim = g_a2_line_kimage[line];
|
|
while(line < 200 && g_a2_line_kimage[line] == cur_kim) line++;
|
|
if (cur_kim == &g_kimage_superhires)
|
|
right = 640;
|
|
else
|
|
right = 560;
|
|
|
|
video_push_lines(cur_kim, start, line,0,right);
|
|
if (line==200) break;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
start = -1;
|
|
last_kim = (Kimage *)-1;
|
|
cur_kim = (Kimage *)0;
|
|
|
|
left_pix = 640;
|
|
right_pix = 0;
|
|
|
|
for(line = 0; line < 200; line++) {
|
|
line_div8 = line >> 3;
|
|
mask = 1 << (line_div8);
|
|
cur_kim = g_a2_line_kimage[line];
|
|
if((g_full_refresh_needed & mask) != 0) {
|
|
left = 0;
|
|
right = 560;
|
|
if(cur_kim == &g_kimage_superhires) {
|
|
right = 640;
|
|
}
|
|
} else {
|
|
left = g_a2_line_left_edge[line];
|
|
right = g_a2_line_right_edge[line];
|
|
}
|
|
|
|
if(!(g_a2_screen_buffer_changed & mask) || (left > right)) {
|
|
/* No need to update this line */
|
|
/* Refresh previous chunks of lines, if any */
|
|
if(start >= 0) {
|
|
video_push_lines(last_kim, start, line,
|
|
left_pix, right_pix);
|
|
start = -1;
|
|
left_pix = 640;
|
|
right_pix = 0;
|
|
}
|
|
} else {
|
|
/* Need to update this line */
|
|
if(start < 0) {
|
|
start = line;
|
|
last_kim = cur_kim;
|
|
}
|
|
if(cur_kim != last_kim) {
|
|
/* do the refresh */
|
|
video_push_lines(last_kim, start, line,
|
|
left_pix, right_pix);
|
|
last_kim = cur_kim;
|
|
start = line;
|
|
left_pix = left;
|
|
right_pix = right;
|
|
}
|
|
left_pix = MIN(left, left_pix);
|
|
right_pix = MAX(right, right_pix);
|
|
}
|
|
}
|
|
|
|
if(start >= 0) {
|
|
video_push_lines(last_kim, start, 200, left_pix, right_pix);
|
|
}
|
|
}
|
|
|
|
g_a2_screen_buffer_changed = 0;
|
|
g_full_refresh_needed = 0;
|
|
|
|
x_push_done();
|
|
|
|
GET_ITIMER(end_time);
|
|
|
|
g_cycs_in_xredraw += (end_time - start_time);
|
|
}
|
|
|
|
|
|
void
|
|
video_update_color_raw(int col_num, int a2_color)
|
|
{
|
|
word32 tmp;
|
|
int red, green, blue;
|
|
int newred, newgreen, newblue;
|
|
|
|
red = (a2_color >> 8) & 0xf;
|
|
green = (a2_color >> 4) & 0xf;
|
|
blue = (a2_color) & 0xf;
|
|
red = ((red << 4) + red);
|
|
green = ((green << 4) + green);
|
|
blue = ((blue << 4) + blue);
|
|
|
|
newred = red >> g_red_right_shift;
|
|
newgreen = green >> g_green_right_shift;
|
|
newblue = blue >> g_blue_right_shift;
|
|
|
|
tmp = ((newred & g_red_mask) << g_red_left_shift) +
|
|
((newgreen & g_green_mask) << g_green_left_shift) +
|
|
((newblue & g_blue_mask) << g_blue_left_shift);
|
|
g_palette_8to1624[col_num] = tmp;
|
|
|
|
x_update_color(col_num, red, green, blue, tmp);
|
|
}
|
|
|
|
void
|
|
video_update_color_array(int col_num, int a2_color)
|
|
{
|
|
int palette;
|
|
int full;
|
|
|
|
if(col_num >= 256 || col_num < 0) {
|
|
halt_printf("video_update_color_array: col: %03x\n", col_num);
|
|
return;
|
|
}
|
|
|
|
full = g_installed_full_superhires_colormap;
|
|
|
|
palette = col_num >> 4;
|
|
if(!full && palette == g_a2vid_palette) {
|
|
return;
|
|
}
|
|
|
|
#if 0
|
|
if(g_screen_depth != 8) {
|
|
/* redraw whole superhires for now */
|
|
g_full_refresh_needed = -1;
|
|
}
|
|
#endif
|
|
|
|
video_update_color_raw(col_num, a2_color);
|
|
}
|
|
|
|
void
|
|
video_update_colormap()
|
|
{
|
|
int palette;
|
|
int full;
|
|
int i;
|
|
|
|
full = g_installed_full_superhires_colormap;
|
|
|
|
if(!full) {
|
|
palette = g_a2vid_palette << 4;
|
|
for(i = 0; i < 16; i++) {
|
|
video_update_color_raw(palette + i, g_lores_colors[i]);
|
|
}
|
|
x_update_physical_colormap();
|
|
}
|
|
}
|
|
|
|
void
|
|
video_update_status_line(int line, const char *string)
|
|
{
|
|
char *buf;
|
|
const char *ptr;
|
|
int i;
|
|
|
|
if(line >= MAX_STATUS_LINES || line < 0) {
|
|
printf("update_status_line: line: %d!\n", line);
|
|
exit(1);
|
|
}
|
|
|
|
ptr = string;
|
|
buf = &(g_status_buf[line][0]);
|
|
g_status_ptrs[line] = buf;
|
|
for(i = 0; i < STATUS_LINE_LENGTH; i++) {
|
|
if(*ptr) {
|
|
buf[i] = *ptr++;
|
|
} else {
|
|
buf[i] = ' ';
|
|
}
|
|
}
|
|
|
|
buf[STATUS_LINE_LENGTH] = 0;
|
|
}
|
|
|
|
void
|
|
video_show_debug_info()
|
|
{
|
|
word32 tmp1;
|
|
|
|
printf("g_cur_dcycs: %f, last_vbl: %f\n", g_cur_dcycs,
|
|
g_last_vbl_dcycs);
|
|
tmp1 = get_lines_since_vbl(g_cur_dcycs);
|
|
printf("lines since vbl: %06x\n", tmp1);
|
|
printf("Last line updated: %d\n", g_vid_update_last_line);
|
|
}
|
|
|
|
word32
|
|
float_bus(double dcycs)
|
|
{
|
|
word32 val;
|
|
int lines_since_vbl;
|
|
int line, eff_line, line24;
|
|
int all_stat;
|
|
int byte_offset;
|
|
int hires, page2;
|
|
int addr;
|
|
|
|
lines_since_vbl = get_lines_since_vbl(dcycs);
|
|
|
|
/* For floating bus, model hires style: Visible lines 0-191 are simply the */
|
|
/* data being displayed at that time. Lines 192-255 are lines 0 - 63 again */
|
|
/* and lines 256-261 are lines 58-63 again */
|
|
/* For each line, figure out starting byte at -25 mod 128 bytes from this */
|
|
/* line's start */
|
|
/* This emulates an Apple II style floating bus. A reall IIgs does not */
|
|
/* drive anything meaningful during the 25 horizontal blanking lines, */
|
|
/* nor during veritical blanking. The data seems to be 0 or related to */
|
|
/* the instruction fetches on a real IIgs during blankings */
|
|
|
|
line = lines_since_vbl >> 8;
|
|
byte_offset = lines_since_vbl & 0xff;
|
|
/* byte offset is from 0 to 65, where the visible screen is drawn */
|
|
/* from 25 to 65 */
|
|
|
|
eff_line = line;
|
|
if(line >= 192) {
|
|
eff_line = line - 192;
|
|
if(line >= 256) {
|
|
eff_line = line - 262 + 64;
|
|
}
|
|
}
|
|
all_stat = g_cur_a2_stat;
|
|
hires = all_stat & ALL_STAT_HIRES;
|
|
if((all_stat & ALL_STAT_MIX_T_GR) && (line >= 160)) {
|
|
hires = 0;
|
|
}
|
|
page2 = EXTRU(all_stat, 31 - BIT_ALL_STAT_PAGE2, 1);
|
|
if(all_stat & ALL_STAT_ST80) {
|
|
page2 = 0;
|
|
}
|
|
|
|
line24 = (eff_line >> 3) & 0x1f;
|
|
addr = g_screen_index[line24] & 0x3ff;
|
|
addr = (addr & 0x380) + (((addr & 0x7f) - 25 + byte_offset) & 0x7f);
|
|
if(hires) {
|
|
addr = 0x2000 + addr + ((eff_line & 7) << 10) + (page2 << 13);
|
|
} else {
|
|
addr = 0x400 + addr + (page2 << 10);
|
|
}
|
|
|
|
val = g_slow_memory_ptr[addr];
|
|
if(byte_offset < 10) {
|
|
/* Bob Bishop's sample program seems to get confused by */
|
|
/* these bytes--so mask some off to prevent seeing some */
|
|
val = 0;
|
|
}
|
|
#if 0
|
|
printf("For %04x (%d) addr=%04x, val=%02x, dcycs:%9.2f\n",
|
|
lines_since_vbl, eff_line, addr, val, dcycs - g_last_vbl_dcycs);
|
|
#endif
|
|
return val;
|
|
}
|