33 #define SPRITE_SPRITE_COLLISION
34 #define SPRITE_FG_COLLISION
40 static Uint32 *current_pixel;
41 static Uint32 *pixel_start;
42 static Uint32 *pixel_raster_start;
45 static int compare_raster;
46 static int logical_raster = 0;
47 static int interrupt_status;
48 static int blink_phase = 0;
50 static Uint8 reg_d018_screen_addr = 0;
51 static int vic_hotreg_touched = 0;
52 static int vic4_sideborder_touched = 0;
53 static int border_x_left= 0;
54 static int border_x_right= 0;
55 static int xcounter = 0, ycounter = 0;
56 static int char_row = 0, display_row = 0;
59 static Uint8 is_fg[2048];
60 #ifdef SPRITE_SPRITE_COLLISION
61 static Uint8 is_sprite[1024];
63 static float char_x_step = 0.0;
64 static int enable_bg_paint = 1;
66 #define display_row_count vic_registers[0x7B]
69 static int vicii_first_raster = 7;
71 static Uint8 *bitplane_p[8];
72 static Uint32 red_colour, black_colour;
73 static Uint8 vic_pixel_readback_result[4];
74 static Uint8 vic_color_register_mask = 0xFF;
75 static Uint32 *used_palette;
76 static int EFFECTIVE_V400;
79 static int etherbuffer_is_io_mapped = 0;
87 static const char NTSC_STD_NAME[] =
"NTSC";
88 static const char PAL_STD_NAME[] =
"PAL";
94 #define DISPLAY_HEIGHT ((max_rasters-1)-20)
95 #define TEXT_HEIGHT_200 400
96 #define TEXT_HEIGHT_400 400
97 #define CHARGEN_Y_SCALE_200 2
98 #define CHARGEN_Y_SCALE_400 1
99 #define chargen_y_pixels 0
100 #define TOP_BORDERS_HEIGHT_200 (DISPLAY_HEIGHT - TEXT_HEIGHT_200)
101 #define TOP_BORDERS_HEIGHT_400 (DISPLAY_HEIGHT - TEXT_HEIGHT_400)
102 #define SINGLE_TOP_BORDER_200 (TOP_BORDERS_HEIGHT_200 >> 1)
103 #define SINGLE_TOP_BORDER_400 (TOP_BORDERS_HEIGHT_400 >> 1)
107 static const Uint8 reverse_byte_table[] = {
108 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
109 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
110 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
111 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
112 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
113 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
114 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
115 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
116 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
117 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
118 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
119 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
120 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
121 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
122 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
123 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
124 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
125 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
126 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
127 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
128 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
129 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
130 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
131 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
132 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
133 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
134 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
135 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
136 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
137 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
138 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
139 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
146 interrupt_status = 0;
150 for (
int i = 0; i < 0x140; i++) {
164 static inline void vic4_reset_display_counters (
void )
175 vic_pixel_readback_result[0] = 0xFF;
177 red_colour = SDL_MapRGBA(
sdl_pix_fmt, 0xFF, 0x00, 0x00, 0xFF);
178 black_colour = SDL_MapRGBA(
sdl_pix_fmt, 0x00, 0x00, 0x00, 0xFF);
184 vic4_reset_display_counters();
185 DEBUG(
"VIC4: has been initialized." NL);
195 if (
XEMU_UNLIKELY(pix_readback_y >= 0 && pix_readback_x >= 0 && pix_readback_y < max_rasters && pix_readback_x <
TEXTURE_WIDTH)) {
199 vic_pixel_readback_result[1] = (texpixcol >>
sdl_pix_fmt->Rshift) & 0xFF;
200 vic_pixel_readback_result[2] = (texpixcol >>
sdl_pix_fmt->Gshift) & 0xFF;
201 vic_pixel_readback_result[3] = (texpixcol >>
sdl_pix_fmt->Bshift) & 0xFF;
207 for (
int a = 0; a < max_rasters; a++) {
222 #ifdef XEMU_FILES_SCREENSHOT_SUPPORT
225 unsigned int x1, y1, x2, y2;
228 if (!xemu_screenshot_png(
236 const char *p = strrchr(xemu_screenshot_full_path,
DIRSEP_CHR);
238 OSD(-1, -1,
"%s", p + 1);
244 unsigned int x_origin, y_origin;
246 for (
unsigned int y = 0;
y < 8;
y++)
247 for (
unsigned int x = 0;
x < 8;
x++)
248 *(pixel_start + x_origin - 10 +
x + (
y + 2 + y_origin) * (
TEXTURE_WIDTH)) = (
x > 1 && x < 7 && y > 1 &&
y < 7) ? red_colour : black_colour;
262 static inline unsigned int vic4_single_side_border_clamped(
void )
268 static void vic4_update_sideborder_dimensions (
void )
271 border_x_left =
FRAME_H_FRONT + vic4_single_side_border_clamped();
279 border_x_left =
FRAME_H_FRONT + vic4_single_side_border_clamped() + 14;
281 border_x_left =
FRAME_H_FRONT + vic4_single_side_border_clamped() + 15;
288 static void vic4_update_vertical_borders(
void )
306 if (!EFFECTIVE_V400) {
336 static void vic4_interpret_legacy_mode_registers (
void )
339 vic4_update_sideborder_dimensions();
340 vic4_update_vertical_borders();
363 DEBUGPRINT(
"VIC4: 16bit=%d, chrcount=%d, linestep=%d bytes, charxscale=%d, ras_src=%d "
364 "screen_ram=$%06x, charset/bitmap=$%06x, sprite=$%06x" NL,
378 FATAL(
"tail_sdl is not zero!");
393 const char *new_name;
396 new_name = NTSC_STD_NAME;
401 vicii_first_raster = 7;
405 new_name = PAL_STD_NAME;
410 vicii_first_raster = 0;
420 vic4_update_sideborder_dimensions();
421 vic4_update_vertical_borders();
436 static void interrupt_checker (
void )
438 int vic_irq_old = cpu65.irqLevel & 2;
441 interrupt_status |= 128;
444 interrupt_status &= 127;
447 if (vic_irq_old != vic_irq_new) {
448 DEBUG(
"VIC4: interrupt change %s -> %s" NL, vic_irq_old ?
"active" :
"inactive", vic_irq_new ?
"active" :
"inactive");
452 cpu65.irqLevel &= ~2;
457 static inline void check_raster_interrupt (
int nraster )
459 if (nraster == compare_raster)
460 interrupt_status |= 1;
462 interrupt_status &= 0xFE;
467 static inline void calculate_char_x_step (
void )
482 unsigned int and_mask, bit_shifter;
486 if (EFFECTIVE_V400) {
488 and_mask = h640 ? 12 << 4 : 14 << 4;
489 bit_shifter = 12 - 4;
491 and_mask = h640 ? 12 : 14 ;
496 and_mask = h640 ? 12 : 14;
502 ((bpn & 1) ? 0x10000 : 0) +
503 (((
y >> 3) * (h640 ? 640 : 320)) + (
x << 3) + (
y & 7))
522 static const char vic_registers_internal_mode_names[] = {
'4',
'3',
'2'};
524 #define CASE_VIC_2(n) case n+0x100
525 #define CASE_VIC_3(n) case n+0x080
526 #define CASE_VIC_4(n) case n
527 #define CASE_VIC_ALL(n) CASE_VIC_2(n): CASE_VIC_3(n): CASE_VIC_4(n)
528 #define CASE_VIC_3_4(n) CASE_VIC_3(n): CASE_VIC_4(n)
551 vic_hotreg_touched = 1;
552 compare_raster = (compare_raster & 0xFF) | ((
data & 0x80) << 1);
553 DEBUG(
"VIC: compare raster is now %d" NL, compare_raster);
556 compare_raster = (compare_raster & 0xFF00) |
data;
557 DEBUG(
"VIC: compare raster is now %d" NL, compare_raster);
565 vic_hotreg_touched = 1;
579 reg_d018_screen_addr = (
data & 0xF0) >> 4;
580 vic_hotreg_touched = 1;
585 interrupt_status = interrupt_status & (~
data) & 0xF;
616 etherbuffer_is_io_mapped = 0;
619 vic_color_register_mask = 0xFF;
622 vic_color_register_mask = 0xFF;
625 DEBUGPRINT(
"VIC: warning, unimplemented ethernet I/O mode is set!" NL);
627 vic_color_register_mask = 0xFF;
628 etherbuffer_is_io_mapped = 1;
631 vic_color_register_mask = 0x0F;
654 vic_hotreg_touched = 1;
657 calculate_char_x_step();
692 calculate_char_x_step();
697 vic4_sideborder_touched = 1;
704 vic4_sideborder_touched = 1;
742 if ((
data & 7) <= 2) {
745 DEBUG(
"VIC4: bitmap bank offset is $%X" NL, (
unsigned int)(bitplane_bank_p -
main_ram));
747 DEBUGPRINT(
"VIC4: bitplane selection 128K-bank tried to set over 2. Refused to do so." NL);
752 DEBUG(
"VIC2: this register does not exist for this mode, ignoring write." NL);
761 DEBUG(
"VIC3: this register does not exist for this mode, ignoring write." NL);
765 FATAL(
"Xemu: invalid VIC internal register numbering on write: $%X",
addr);
769 if (vic_hotreg_touched) {
771 vic4_interpret_legacy_mode_registers();
772 vic_hotreg_touched = 0;
773 vic4_sideborder_touched = 0;
776 if (vic4_sideborder_touched) {
778 vic4_update_sideborder_dimensions();
779 vic4_sideborder_touched = 0;
793 result = (result & 0x7F) | ((logical_raster & 0x100) >> 1);
796 result = logical_raster & 0xFF;
814 result = interrupt_status | (64 + 32 + 16);
854 result = *get_dat_addr(
addr & 7);
865 result = (result & 0xC0) | ((result + 1) & 0x3F);
883 result = vic_pixel_readback_result[
vic_registers[0x7C] >> 6];
890 DEBUG(
"VIC2: this register does not exist for this mode, $FF for read answer." NL);
900 DEBUG(
"VIC3: this register does not exist for this mode, $FF for read answer." NL);
905 FATAL(
"Xemu: invalid VIC internal register numbering on read: $%X",
addr);
907 DEBUG(
"VIC%c: read reg $%02X (internally $%03X) with result $%02X" NL,
XEMU_LIKELY(
addr < 0x180) ? vic_registers_internal_mode_names[
addr >> 7] :
'?',
addr & 0x7F,
addr, result);
919 #ifdef SPRITE_SPRITE_COLLISION
920 # warning "Sprite-sprite collision is an experimental feature (SPRITE_SPRITE_COLLISION is defined)!"
921 # define DO_SPRITE_SPRITE_COLLISION(pos,cond) do { \
923 const Uint8 sp = is_sprite[pos]; \
924 is_sprite[pos] = sp | sprbmask; \
926 vic_registers[0x1E] |= sp | sprbmask; \
929 #ifndef SPRITE_ANY_COLLISION
930 #define SPRITE_ANY_COLLISION
934 # define DO_SPRITE_SPRITE_COLLISION(pos,cond)
938 #ifdef SPRITE_FG_COLLISION
939 # warning "Sprite-foreground collision is an experimental feature (SPRITE_FG_COLLISION is defined)!"
940 # define DO_SPRITE_FG_COLLISION(pos,cond) do { \
941 if (is_fg[pos] && (cond)) \
942 vic_registers[0x1F] |= sprbmask; \
944 #ifndef SPRITE_ANY_COLLISION
945 #define SPRITE_ANY_COLLISION
949 # define DO_SPRITE_FG_COLLISION(pos,cond)
953 static XEMU_INLINE void vic4_draw_sprite_row_16color (
const int sprnum,
int x_display_pos,
const Uint8* row_data_ptr,
const int xscale,
const int do_tiling )
962 # ifdef SPRITE_ANY_COLLISION
963 const Uint8 sprbmask = 1 << sprnum;
966 for (
int byte = 0;
byte < totalBytes;
byte++) {
967 const Uint8 c0 = (*(row_data_ptr + byte)) >> 4;
968 const Uint8 c1 = (*(row_data_ptr + byte)) & 0xF;
969 for (
int p = 0; p < xscale && x_display_pos < border_x_right; p++, x_display_pos++) {
970 if (c0 != transparency_palette_index && x_display_pos >= border_x_left && (
973 *(pixel_raster_start + x_display_pos) = pal16[c0];
978 for (
int p = 0; p < xscale && x_display_pos < border_x_right; p++, x_display_pos++) {
979 if (c1 != transparency_palette_index && x_display_pos >= border_x_left && (
982 *(pixel_raster_start + x_display_pos) = pal16[c1];
988 }
while (
XEMU_UNLIKELY(do_tiling && x_display_pos < border_x_right));
992 static XEMU_INLINE void vic4_draw_sprite_row_multicolor (
const int sprnum,
int x_display_pos,
const Uint8* row_data_ptr,
const int xscale,
const int do_tiling )
996 # ifdef SPRITE_ANY_COLLISION
997 const Uint8 sprbmask = 1 << sprnum;
1000 for (
int byte = 0;
byte < totalBytes;
byte++) {
1001 const Uint8 row_data = *row_data_ptr++;
1002 for (
int shift = 6; shift >= 0; shift -= 2) {
1003 const int mcm_pixel_value = (row_data >> shift) & 3;
1005 for (
int p = 0; p < xscale && x_display_pos < border_x_right; p++, x_display_pos += 2) {
1006 if (mcm_pixel_value) {
1007 if (x_display_pos >= border_x_left && (
1010 *(pixel_raster_start + x_display_pos) = sdl_pixel;
1014 if (x_display_pos + 1 >= border_x_left && (
1017 *(pixel_raster_start + x_display_pos + 1) = sdl_pixel;
1025 }
while (
XEMU_UNLIKELY(do_tiling && x_display_pos < border_x_right));
1029 static XEMU_INLINE void vic4_draw_sprite_row_mono (
const int sprnum,
int x_display_pos,
const Uint8 *row_data_ptr,
const int xscale,
const int do_tiling )
1033 # ifdef SPRITE_ANY_COLLISION
1034 const Uint8 sprbmask = 1 << sprnum;
1037 for (
int byte = 0;
byte < totalBytes;
byte++) {
1038 for (
int xbit = 0; xbit < 8; xbit++) {
1039 const Uint8 sprite_bit = *row_data_ptr & (0x80 >> xbit);
1040 for (
int p = 0; p < xscale && x_display_pos < border_x_right; p++, x_display_pos++) {
1041 if (x_display_pos >= border_x_left && sprite_bit && (
1045 *(pixel_raster_start + x_display_pos) = sdl_pixel;
1053 }
while (
XEMU_UNLIKELY(do_tiling && x_display_pos < border_x_right));
1066 for (
int sprnum = 7; sprnum >= 0; sprnum--) {
1073 int sprite_row_in_raster = ycounter - y_display_pos;
1076 sprite_row_in_raster = sprite_row_in_raster >> 1;
1079 sprite_row_in_raster = sprite_row_in_raster >> 1;
1081 if (sprite_row_in_raster >= 0 && sprite_row_in_raster < spriteHeight) {
1087 64 * ((*(sprite_data_pointer + 1) << 8) | (*sprite_data_pointer))
1088 : ((64 * (*sprite_data_pointer)) | ( ((~
last_dd00_bits) & 0x3)) << 14);
1092 const Uint8 *row_data = sprite_data + widthBytes * sprite_row_in_raster;
1094 const int do_tiling = reg_tiling & (1 << sprnum);
1096 vic4_draw_sprite_row_multicolor(sprnum, x_display_pos, row_data, xscale, do_tiling);
1098 vic4_draw_sprite_row_16color(sprnum, x_display_pos, row_data, xscale, do_tiling);
1100 vic4_draw_sprite_row_mono(sprnum, x_display_pos, row_data, xscale, do_tiling);
1111 Uint32* active_palette = used_palette;
1117 char_byte = ~char_byte;
1126 const Uint32 sdl_fg_color = used_palette[fg_color];
1128 const Uint32 sdl_bg_color = used_palette[bg_color];
1129 for (
float cx = 0; cx < glyph_width && xcounter < border_x_right; cx += char_x_step) {
1130 const Uint8 char_pixel = (char_byte & (0x80 >> (int)cx));
1131 *(current_pixel++) = char_pixel ? sdl_fg_color : sdl_bg_color;
1132 is_fg[xcounter++] = char_pixel;
1135 for (
float cx = 0; cx < glyph_width && xcounter < border_x_right; cx += char_x_step) {
1136 const Uint8 char_pixel = (char_byte & (0x80 >> (int)cx));
1138 *current_pixel = sdl_fg_color;
1140 is_fg[xcounter++] = char_pixel;
1143 used_palette = active_palette;
1147 static XEMU_INLINE void vic4_render_multicolor_char_row (
const Uint8 char_byte,
const int glyph_width,
const Uint8 color_source[4] )
1149 for (
float cx = 0; cx < glyph_width && xcounter < border_x_right; cx += char_x_step) {
1150 const Uint8 bitsel = 2 * (int)(cx / 2);
1151 const Uint8 bit_pair = (char_byte & (0x80 >> bitsel)) >> (6-bitsel) | (char_byte & (0x40 >> bitsel)) >> (6-bitsel);
1153 *current_pixel = used_palette[color_source[bit_pair]];
1155 is_fg[xcounter++] = (bit_pair & 2);
1161 static XEMU_INLINE void vic4_render_fullcolor_char_row (
const Uint8* char_row,
const int glyph_width,
const Uint32 bg_sdl_color,
const Uint32 fg_sdl_color,
const int hflip )
1163 for (
float cx = 0; cx < glyph_width && xcounter < border_x_right; cx += char_x_step) {
1164 const Uint8 char_data = char_row[
XEMU_LIKELY(!hflip) ? (int)cx : glyph_width - 1 - (
int)cx];
1165 if (char_data == 0xFF)
1166 *current_pixel = fg_sdl_color;
1168 *current_pixel = used_palette[char_data];
1170 *current_pixel = bg_sdl_color;
1172 is_fg[xcounter++] = char_data;
1178 static XEMU_INLINE void vic4_render_16color_char_row (
const Uint8* char_row,
const int glyph_width,
const Uint32 bg_sdl_color,
const Uint32 *palette16,
const int hflip )
1180 for (
float cx = 0; cx < glyph_width && xcounter < border_x_right; cx += char_x_step) {
1183 char_data = char_row[((int)cx) / 2];
1189 char_data = char_row[glyph_width / 2 - 1 - (((int)cx) / 2)];
1195 is_fg[xcounter++] = char_data;
1197 *current_pixel = palette16[char_data];
1198 else if (enable_bg_paint)
1199 *current_pixel = bg_sdl_color;
1205 static XEMU_INLINE void set_bitplane_pointers (
void )
1209 int and_mask, bit_shifter;
1210 if (EFFECTIVE_V400) {
1211 if (!(ycounter & 1)) {
1215 and_mask = (
REG_H640 ? 12 << 4 : 14 << 4);
1216 bit_shifter = 12 - 4;
1222 bitplane_p[0] = bitplane_bank_p + ((
vic_registers[0x33] & and_mask) << bit_shifter);
1223 bitplane_p[1] = bitplane_bank_p + ((
vic_registers[0x34] & and_mask) << bit_shifter) + 0x10000;
1224 bitplane_p[2] = bitplane_bank_p + ((
vic_registers[0x35] & and_mask) << bit_shifter);
1225 bitplane_p[3] = bitplane_bank_p + ((
vic_registers[0x36] & and_mask) << bit_shifter) + 0x10000;
1226 bitplane_p[4] = bitplane_bank_p + ((
vic_registers[0x37] & and_mask) << bit_shifter);
1227 bitplane_p[5] = bitplane_bank_p + ((
vic_registers[0x38] & and_mask) << bit_shifter) + 0x10000;
1228 bitplane_p[6] = bitplane_bank_p + ((
vic_registers[0x39] & and_mask) << bit_shifter);
1229 bitplane_p[7] = bitplane_bank_p + ((
vic_registers[0x3A] & and_mask) << bit_shifter) + 0x10000;
1234 static XEMU_INLINE void vic4_render_bitplane_char_row (
const Uint32 offset,
const int glyph_width )
1237 for (
float cx = 0; cx < glyph_width && xcounter < border_x_right; cx += char_x_step) {
1238 const Uint8 bitsel = 0x80 >> ((int)cx);
1239 *(current_pixel++) = palette[((
1240 ((*(bitplane_p[0] + offset) & bitsel) ? 1 : 0) |
1241 ((*(bitplane_p[1] + offset) & bitsel) ? 2 : 0) |
1242 ((*(bitplane_p[2] + offset) & bitsel) ? 4 : 0) |
1243 ((*(bitplane_p[3] + offset) & bitsel) ? 8 : 0) |
1244 ((*(bitplane_p[4] + offset) & bitsel) ? 16 : 0) |
1245 ((*(bitplane_p[5] + offset) & bitsel) ? 32 : 0) |
1246 ((*(bitplane_p[6] + offset) & bitsel) ? 64 : 0) |
1247 ((*(bitplane_p[7] + offset) & bitsel) ? 128 : 0)
1250 is_fg[xcounter++] = (*(bitplane_p[2] + offset) & bitsel);
1255 static XEMU_INLINE void vic4_render_bitplane_raster (
void )
1259 set_bitplane_pointers();
1261 int line_char_index = 0;
1263 vic4_render_bitplane_char_row(offset, 8);
1267 if (!EFFECTIVE_V400 || (ycounter & 1)) {
1268 if (++char_row > 7) {
1273 while (xcounter++ < border_x_right)
1311 static XEMU_INLINE void vic4_render_char_raster (
void )
1313 int line_char_index = 0;
1314 enable_bg_paint = 1;
1315 const Uint8 *row_data_base_addr = get_charset_effective_addr();
1324 const int xcounter_start = xcounter;
1325 Uint8 char_fetch_offset = 0;
1328 Uint16 color_data = *(colour_ram_current_ptr++);
1329 Uint16 char_value = *(screen_ram_current_ptr++);
1331 color_data = (color_data << 8) | (*(colour_ram_current_ptr++));
1332 char_value = char_value | (*(screen_ram_current_ptr++) << 8);
1335 xcounter = (char_value & 0x3FF);
1340 if (0x400 - xcounter <= xcounter_start)
1341 xcounter = xcounter_start - (0x400 - xcounter);
1343 xcounter += xcounter_start;
1346 if (0x800 - xcounter <= xcounter_start)
1347 xcounter = xcounter_start - (0x800 - xcounter);
1349 xcounter += xcounter_start;
1358 current_pixel = pixel_raster_start + xcounter;
1361 char_fetch_offset = char_value >> 13;
1363 enable_bg_paint = 0;
1372 const Uint8 char_fgcolor = color_data & 0xF;
1373 const Uint16 char_id =
REG_EBM ? (char_value & 0x3f) : char_value & 0x1fff;
1380 vic4_render_16color_char_row(
1381 main_ram + (((char_id * 64) + ((sel_char_row + char_fetch_offset) * 8)) & 0x7FFFF),
1383 used_palette[char_bgcolor],
1384 used_palette + (color_data & 0xF0),
1390 vic4_render_fullcolor_char_row(
1391 main_ram + (((char_id * 64) + ((sel_char_row + char_fetch_offset) * 8)) & 0x7FFFF),
1393 used_palette[char_bgcolor],
1394 used_palette[char_fgcolor],
1401 static Uint8 color_source_mcm[4];
1406 color_source_mcm[1] = char_value >> 4;
1407 color_source_mcm[2] = char_value & 0xF;
1408 color_source_mcm[3] = color_data & 0xF;
1409 char_byte = *(row_data_base_addr + display_row * (
LINESTEP_BYTES * 8) + 8 * line_char_index + sel_char_row);
1414 color_source_mcm[3] = char_fgcolor & 7;
1415 char_byte = *(row_data_base_addr + (char_id * 8) + sel_char_row);
1420 char_byte = reverse_byte_table[char_byte];
1421 vic4_render_multicolor_char_row(
1427 Uint8 char_byte, char_bgcolor_now, char_fgcolor_now;
1429 char_bgcolor_now = char_bgcolor;
1430 char_fgcolor_now = char_fgcolor;
1431 char_byte = *(row_data_base_addr + (char_id * 8) + sel_char_row);
1433 char_bgcolor_now = char_value & 0xF;
1434 char_fgcolor_now = char_value >> 4;
1435 char_byte = *(row_data_base_addr + display_row * (
LINESTEP_BYTES * 8) + 8 * line_char_index + sel_char_row);
1439 char_byte = reverse_byte_table[char_byte];
1441 vic4_render_mono_char_row(
1452 if (++char_row > 7) {
1457 while (xcounter++ < border_x_right)
1469 pixel_raster_start = current_pixel;
1472 logical_raster = ycounter >> (EFFECTIVE_V400 ? 0 : 1);
1475 if (!(ycounter & 1) || EFFECTIVE_V400)
1476 check_raster_interrupt(logical_raster);
1480 if (!EFFECTIVE_V400 && (ycounter & 1)) {
1495 xcounter += border_x_left;
1496 current_pixel += border_x_left;
1498 vic4_render_char_raster();
1500 vic4_render_bitplane_raster();
1501 # ifdef SPRITE_SPRITE_COLLISION
1502 memset(is_sprite, 0,
sizeof is_sprite);
1509 while (xcounter++ < border_x_right)
1512 for (
Uint32 *p = pixel_raster_start; p < pixel_raster_start + border_x_left; p++)
1514 for (
Uint32 *p = current_pixel; p < current_pixel + border_x_right; p++)
1526 if (ycounter == max_rasters) {
1527 vic4_reset_display_counters();
1528 static int blink_frame_counter = 0;
1529 blink_frame_counter++;
1531 blink_frame_counter = 0;
1532 blink_phase = !blink_phase;
1543 #ifdef XEMU_SNAPSHOT_SUPPORT
1547 #define SNAPSHOT_VIC4_BLOCK_VERSION 2
1548 #define SNAPSHOT_VIC4_BLOCK_SIZE (0x100 + ((NO_OF_PALETTE_REGS) * 3))
1550 int vic4_snapshot_load_state (
const struct xemu_snapshot_definition_st *def,
struct xemu_snapshot_block_st *
block )
1552 Uint8 buffer[SNAPSHOT_VIC4_BLOCK_SIZE];
1554 if (
block->block_version != SNAPSHOT_VIC4_BLOCK_VERSION ||
block->sub_counter ||
block->sub_size !=
sizeof buffer)
1555 RETURN_XSNAPERR_USER(
"Bad VIC-4 block syntax");
1556 a = xemusnap_read_file(buffer,
sizeof buffer);
1559 for (a = 0; a < 0x80; a++)
1568 interrupt_status = (int)P_AS_BE32(buffer + 1);
1573 int vic4_snapshot_save_state (
const struct xemu_snapshot_definition_st *def )
1575 Uint8 buffer[SNAPSHOT_VIC4_BLOCK_SIZE];
1576 int a = xemusnap_write_block_header(def->idstr, SNAPSHOT_VIC4_BLOCK_VERSION);
1578 memset(buffer, 0xFF,
sizeof buffer);
1586 U32_AS_BE(buffer + 1, interrupt_status);
1587 return xemusnap_write_sub_block(buffer,
sizeof buffer);