2010-04-11 22:07:58 +00:00
/*
GSport - an Apple //gs Emulator
2012-02-29 17:37:44 +00:00
Copyright ( C ) 2010 - 2012 by GSport contributors
2010-04-11 22:07:58 +00:00
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 ;
2010-05-08 04:41:06 +00:00
int g_video_extra_check_inputs = 0 ; // OG Not recommended to use it (or apps might miss mouse changes)
2010-04-11 22:07:58 +00:00
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 } ;
2015-10-01 10:04:36 +00:00
// These LORES/DHIRES RGB values were extracted from ROM 3 IIgs video signals by Koichi Nishida
# define BLACK_RGB 0x000
# define DEEP_RED_RGB 0xd03
# define BROWN_RGB 0x850
# define ORANGE_RGB 0xf60
# define DARK_GREEN_RGB 0x072
# define DARK_GRAY_RGB 0x555
# define GREEN_RGB 0x1d0
# define YELLOW_RGB 0xff0
# define DARK_BLUE_RGB 0x009
# define PURPLE_RGB 0xd2d
# define LIGHT_GRAY_RGB 0xaaa
# define PINK_RGB 0xf98
# define MEDIUM_BLUE_RGB 0x22f
# define LIGHT_BLUE_RGB 0x6af
# define AQUAMARINE_RGB 0x4f9
# define WHITE_RGB 0xfff
2010-04-11 22:07:58 +00:00
const int g_dbhires_colors [ ] = {
2015-10-01 10:04:36 +00:00
BLACK_RGB , // 0x0 black
DEEP_RED_RGB , // 0x1 deep red
BROWN_RGB , // 0x2 brown
ORANGE_RGB , // 0x3 orange
DARK_GREEN_RGB , // 0x4 dark green
DARK_GRAY_RGB , // 0x5 dark gray
GREEN_RGB , // 0x6 green
YELLOW_RGB , // 0x7 yellow
DARK_BLUE_RGB , // 0x8 dark blue
PURPLE_RGB , // 0x9 purple
LIGHT_GRAY_RGB , // 0xa light gray
PINK_RGB , // 0xb pink
MEDIUM_BLUE_RGB , // 0xc medium blue
LIGHT_BLUE_RGB , // 0xd light blue
AQUAMARINE_RGB , // 0xe aquamarine
WHITE_RGB // 0xf white
2010-04-11 22:07:58 +00:00
} ;
word32 g_dhires_convert [ 4096 ] ; /* look up table of 7 bits (concat): */
/* { 4 bits, |3 prev bits| } */
const byte g_dhires_colors_16 [ ] = {
2015-10-01 10:04:36 +00:00
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
2010-04-11 22:07:58 +00:00
} ;
2015-10-01 10:04:36 +00:00
int g_lores_colors [ ] = {
BLACK_RGB , // 0x0 black
DEEP_RED_RGB , // 0x1 deep red
DARK_BLUE_RGB , // 0x2 dark blue
PURPLE_RGB , // 0x3 purple
DARK_GREEN_RGB , // 0x4 dark green
DARK_GRAY_RGB , // 0x5 dark gray
MEDIUM_BLUE_RGB , // 0x6 medium blue
LIGHT_BLUE_RGB , // 0x7 light blue
BROWN_RGB , // 0x8 brown
ORANGE_RGB , // 0x9 orange
LIGHT_GRAY_RGB , // 0xa light gray
PINK_RGB , // 0xb pink
GREEN_RGB , // 0xc green
YELLOW_RGB , // 0xd yellow
AQUAMARINE_RGB , // 0xe aquamarine
WHITE_RGB // 0xf white
2010-04-11 22:07:58 +00:00
} ;
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 */
} ;
2010-05-08 04:41:06 +00:00
int g_screen_index [ ] = {
2010-04-11 22:07:58 +00:00
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 */
2010-05-08 04:41:06 +00:00
// 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 ;
2010-04-11 22:07:58 +00:00
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 ] ;
2012-02-29 17:37:44 +00:00
# if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
2010-04-11 22:07:58 +00:00
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 ;
2010-05-08 04:41:06 +00:00
int g_needfullrefreshfornextframe = 1 ;
void video_update ( )
2010-04-11 22:07:58 +00:00
{
int did_video ;
2010-05-08 04:41:06 +00:00
// 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 ;
}
2010-04-11 22:07:58 +00:00
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 ;
2010-05-08 04:41:06 +00:00
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
2010-04-11 22:07:58 +00:00
}
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 ;
} ;
2010-05-08 04:41:06 +00:00
int g_border_color = 0 ; // OG Expose border color
2010-04-11 22:07:58 +00:00
Border_changes g_border_changes [ MAX_BORDER_CHANGES ] ;
int g_num_border_changes = 0 ;
void
change_border_color ( double dcycs , int val )
{
int pos ;
2010-05-08 04:41:06 +00:00
g_border_color = val ; // OG Expose border color
2010-04-11 22:07:58 +00:00
pos = g_num_border_changes ;
2010-05-08 04:41:06 +00:00
g_border_changes [ pos ] . fcycs = ( float ) ( dcycs - g_last_vbl_dcycs ) ;
2010-04-11 22:07:58 +00:00
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 ;
}
}
2010-05-08 04:41:06 +00:00
extern int first ;
2010-04-11 22:07:58 +00:00
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 ;
2012-02-29 17:37:44 +00:00
# if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
2010-04-11 22:07:58 +00:00
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 ;
2012-02-29 17:37:44 +00:00
# if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
2010-04-11 22:07:58 +00:00
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 ( " \n video_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***/
}
2010-05-08 04:41:06 +00:00
// OG Added video_release_kimages proto
void video_release_kimages ( ) ;
2010-04-11 22:07:58 +00:00
void
end_screen ( )
{
printf ( " In end_screen \n " ) ;
2010-05-08 04:41:06 +00:00
// OG Free up allocated images
video_release_kimages ( ) ;
2010-04-11 22:07:58 +00:00
xdriver_end ( ) ;
}
byte g_font_array [ 256 ] [ 8 ] = {
2010-04-21 21:59:03 +00:00
# include "gsportfont.h"
2010-04-11 22:07:58 +00:00
} ;
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 ) ;
}
2010-05-08 04:41:06 +00:00
// 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 ) ;
}
2010-04-11 22:07:58 +00:00
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 ;
2010-05-08 04:41:06 +00:00
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 ;
}
2010-04-11 22:07:58 +00:00
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 ) ;
2010-05-08 04:41:06 +00:00
// 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 ,
2010-04-11 22:07:58 +00:00
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 */
2010-05-08 04:41:06 +00:00
// 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 ) ;
2010-04-11 22:07:58 +00:00
/* 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 ;
}
}
2010-05-08 04:41:06 +00:00
video_push_border_sides_lines ( 0 /*BORDER_WIDTH*/ ,
2010-04-11 22:07:58 +00:00
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 ) ;
}
}
2010-05-08 04:41:06 +00:00
// OG Added window ratio support
extern int x_calc_ratio ( float ratiox , float ratioy ) ;
2010-04-11 22:07:58 +00:00
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 ;
2010-05-29 00:33:51 +00:00
float ratiox = 0 , ratioy = 0 ;
2010-04-11 22:07:58 +00:00
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 ) ;
2010-05-08 04:41:06 +00:00
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
{
2010-04-11 22:07:58 +00:00
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 ) ;
}
2010-05-08 04:41:06 +00:00
}
2010-04-11 22:07:58 +00:00
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 ;
}