Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

VIC_SC.cpp

Go to the documentation of this file.
00001 /*
00002  *  VIC_SC.cpp - 6569R5 emulation (cycle based)
00003  *
00004  *  Frodo (C) 1994-1997 Christian Bauer
00005  *
00006 
00007  *
00008  * Incompatibilities:
00009  * ------------------
00010  *
00011  *  - Color of $ff bytes read when BA is low and AEC is high
00012  *    is not correct
00013  *  - Changes to border/background color are visible 7 pixels
00014  *    too late
00015  *  - Sprite data access doesn't respect BA
00016  *  - Sprite collisions are only detected within the visible
00017  *    screen area (excluding borders)
00018  *  - Sprites are only drawn if they completely fit within the
00019  *    left/right limits of the chunky bitmap
00020  */
00021 
00022 #include "sysdeps.h"
00023 
00024 #include "VIC.h"
00025 #include "C64.h"
00026 #include "CPUC64.h"
00027 #include "Display.h"
00028 #include "Prefs.h"
00029 
00030 
00031 // First and last displayed line
00032 const int FIRST_DISP_LINE = 0x10;
00033 const int LAST_DISP_LINE = 0x11f;
00034 
00035 // First and last possible line for Bad Lines
00036 const int FIRST_DMA_LINE = 0x30;
00037 const int LAST_DMA_LINE = 0xf7;
00038 
00039 // Display window coordinates
00040 const int ROW25_YSTART = 0x33;
00041 const int ROW25_YSTOP = 0xfb;
00042 const int ROW24_YSTART = 0x37;
00043 const int ROW24_YSTOP = 0xf7;
00044 
00045 #if defined(SMALL_DISPLAY)
00046 /* This does not work yet, the sprite code doesn't know about it. */
00047 const int COL40_XSTART = 0x14;
00048 const int COL40_XSTOP = 0x154;
00049 const int COL38_XSTART = 0x1B;
00050 const int COL38_XSTOP = 0x14B;
00051 #else
00052 const int COL40_XSTART = 0x20;
00053 const int COL40_XSTOP = 0x160;
00054 const int COL38_XSTART = 0x27;
00055 const int COL38_XSTOP = 0x157;
00056 #endif
00057 
00058 
00059 // Tables for sprite X expansion
00060 uint16 ExpTable[256] = {
00061         0x0000, 0x0003, 0x000C, 0x000F, 0x0030, 0x0033, 0x003C, 0x003F,
00062         0x00C0, 0x00C3, 0x00CC, 0x00CF, 0x00F0, 0x00F3, 0x00FC, 0x00FF,
00063         0x0300, 0x0303, 0x030C, 0x030F, 0x0330, 0x0333, 0x033C, 0x033F,
00064         0x03C0, 0x03C3, 0x03CC, 0x03CF, 0x03F0, 0x03F3, 0x03FC, 0x03FF,
00065         0x0C00, 0x0C03, 0x0C0C, 0x0C0F, 0x0C30, 0x0C33, 0x0C3C, 0x0C3F,
00066         0x0CC0, 0x0CC3, 0x0CCC, 0x0CCF, 0x0CF0, 0x0CF3, 0x0CFC, 0x0CFF,
00067         0x0F00, 0x0F03, 0x0F0C, 0x0F0F, 0x0F30, 0x0F33, 0x0F3C, 0x0F3F,
00068         0x0FC0, 0x0FC3, 0x0FCC, 0x0FCF, 0x0FF0, 0x0FF3, 0x0FFC, 0x0FFF,
00069         0x3000, 0x3003, 0x300C, 0x300F, 0x3030, 0x3033, 0x303C, 0x303F,
00070         0x30C0, 0x30C3, 0x30CC, 0x30CF, 0x30F0, 0x30F3, 0x30FC, 0x30FF,
00071         0x3300, 0x3303, 0x330C, 0x330F, 0x3330, 0x3333, 0x333C, 0x333F,
00072         0x33C0, 0x33C3, 0x33CC, 0x33CF, 0x33F0, 0x33F3, 0x33FC, 0x33FF,
00073         0x3C00, 0x3C03, 0x3C0C, 0x3C0F, 0x3C30, 0x3C33, 0x3C3C, 0x3C3F,
00074         0x3CC0, 0x3CC3, 0x3CCC, 0x3CCF, 0x3CF0, 0x3CF3, 0x3CFC, 0x3CFF,
00075         0x3F00, 0x3F03, 0x3F0C, 0x3F0F, 0x3F30, 0x3F33, 0x3F3C, 0x3F3F,
00076         0x3FC0, 0x3FC3, 0x3FCC, 0x3FCF, 0x3FF0, 0x3FF3, 0x3FFC, 0x3FFF,
00077         0xC000, 0xC003, 0xC00C, 0xC00F, 0xC030, 0xC033, 0xC03C, 0xC03F,
00078         0xC0C0, 0xC0C3, 0xC0CC, 0xC0CF, 0xC0F0, 0xC0F3, 0xC0FC, 0xC0FF,
00079         0xC300, 0xC303, 0xC30C, 0xC30F, 0xC330, 0xC333, 0xC33C, 0xC33F,
00080         0xC3C0, 0xC3C3, 0xC3CC, 0xC3CF, 0xC3F0, 0xC3F3, 0xC3FC, 0xC3FF,
00081         0xCC00, 0xCC03, 0xCC0C, 0xCC0F, 0xCC30, 0xCC33, 0xCC3C, 0xCC3F,
00082         0xCCC0, 0xCCC3, 0xCCCC, 0xCCCF, 0xCCF0, 0xCCF3, 0xCCFC, 0xCCFF,
00083         0xCF00, 0xCF03, 0xCF0C, 0xCF0F, 0xCF30, 0xCF33, 0xCF3C, 0xCF3F,
00084         0xCFC0, 0xCFC3, 0xCFCC, 0xCFCF, 0xCFF0, 0xCFF3, 0xCFFC, 0xCFFF,
00085         0xF000, 0xF003, 0xF00C, 0xF00F, 0xF030, 0xF033, 0xF03C, 0xF03F,
00086         0xF0C0, 0xF0C3, 0xF0CC, 0xF0CF, 0xF0F0, 0xF0F3, 0xF0FC, 0xF0FF,
00087         0xF300, 0xF303, 0xF30C, 0xF30F, 0xF330, 0xF333, 0xF33C, 0xF33F,
00088         0xF3C0, 0xF3C3, 0xF3CC, 0xF3CF, 0xF3F0, 0xF3F3, 0xF3FC, 0xF3FF,
00089         0xFC00, 0xFC03, 0xFC0C, 0xFC0F, 0xFC30, 0xFC33, 0xFC3C, 0xFC3F,
00090         0xFCC0, 0xFCC3, 0xFCCC, 0xFCCF, 0xFCF0, 0xFCF3, 0xFCFC, 0xFCFF,
00091         0xFF00, 0xFF03, 0xFF0C, 0xFF0F, 0xFF30, 0xFF33, 0xFF3C, 0xFF3F,
00092         0xFFC0, 0xFFC3, 0xFFCC, 0xFFCF, 0xFFF0, 0xFFF3, 0xFFFC, 0xFFFF
00093 };
00094 
00095 uint16 MultiExpTable[256] = {
00096         0x0000, 0x0005, 0x000A, 0x000F, 0x0050, 0x0055, 0x005A, 0x005F,
00097         0x00A0, 0x00A5, 0x00AA, 0x00AF, 0x00F0, 0x00F5, 0x00FA, 0x00FF,
00098         0x0500, 0x0505, 0x050A, 0x050F, 0x0550, 0x0555, 0x055A, 0x055F,
00099         0x05A0, 0x05A5, 0x05AA, 0x05AF, 0x05F0, 0x05F5, 0x05FA, 0x05FF,
00100         0x0A00, 0x0A05, 0x0A0A, 0x0A0F, 0x0A50, 0x0A55, 0x0A5A, 0x0A5F,
00101         0x0AA0, 0x0AA5, 0x0AAA, 0x0AAF, 0x0AF0, 0x0AF5, 0x0AFA, 0x0AFF,
00102         0x0F00, 0x0F05, 0x0F0A, 0x0F0F, 0x0F50, 0x0F55, 0x0F5A, 0x0F5F,
00103         0x0FA0, 0x0FA5, 0x0FAA, 0x0FAF, 0x0FF0, 0x0FF5, 0x0FFA, 0x0FFF,
00104         0x5000, 0x5005, 0x500A, 0x500F, 0x5050, 0x5055, 0x505A, 0x505F,
00105         0x50A0, 0x50A5, 0x50AA, 0x50AF, 0x50F0, 0x50F5, 0x50FA, 0x50FF,
00106         0x5500, 0x5505, 0x550A, 0x550F, 0x5550, 0x5555, 0x555A, 0x555F,
00107         0x55A0, 0x55A5, 0x55AA, 0x55AF, 0x55F0, 0x55F5, 0x55FA, 0x55FF,
00108         0x5A00, 0x5A05, 0x5A0A, 0x5A0F, 0x5A50, 0x5A55, 0x5A5A, 0x5A5F,
00109         0x5AA0, 0x5AA5, 0x5AAA, 0x5AAF, 0x5AF0, 0x5AF5, 0x5AFA, 0x5AFF,
00110         0x5F00, 0x5F05, 0x5F0A, 0x5F0F, 0x5F50, 0x5F55, 0x5F5A, 0x5F5F,
00111         0x5FA0, 0x5FA5, 0x5FAA, 0x5FAF, 0x5FF0, 0x5FF5, 0x5FFA, 0x5FFF,
00112         0xA000, 0xA005, 0xA00A, 0xA00F, 0xA050, 0xA055, 0xA05A, 0xA05F,
00113         0xA0A0, 0xA0A5, 0xA0AA, 0xA0AF, 0xA0F0, 0xA0F5, 0xA0FA, 0xA0FF,
00114         0xA500, 0xA505, 0xA50A, 0xA50F, 0xA550, 0xA555, 0xA55A, 0xA55F,
00115         0xA5A0, 0xA5A5, 0xA5AA, 0xA5AF, 0xA5F0, 0xA5F5, 0xA5FA, 0xA5FF,
00116         0xAA00, 0xAA05, 0xAA0A, 0xAA0F, 0xAA50, 0xAA55, 0xAA5A, 0xAA5F,
00117         0xAAA0, 0xAAA5, 0xAAAA, 0xAAAF, 0xAAF0, 0xAAF5, 0xAAFA, 0xAAFF,
00118         0xAF00, 0xAF05, 0xAF0A, 0xAF0F, 0xAF50, 0xAF55, 0xAF5A, 0xAF5F,
00119         0xAFA0, 0xAFA5, 0xAFAA, 0xAFAF, 0xAFF0, 0xAFF5, 0xAFFA, 0xAFFF,
00120         0xF000, 0xF005, 0xF00A, 0xF00F, 0xF050, 0xF055, 0xF05A, 0xF05F,
00121         0xF0A0, 0xF0A5, 0xF0AA, 0xF0AF, 0xF0F0, 0xF0F5, 0xF0FA, 0xF0FF,
00122         0xF500, 0xF505, 0xF50A, 0xF50F, 0xF550, 0xF555, 0xF55A, 0xF55F,
00123         0xF5A0, 0xF5A5, 0xF5AA, 0xF5AF, 0xF5F0, 0xF5F5, 0xF5FA, 0xF5FF,
00124         0xFA00, 0xFA05, 0xFA0A, 0xFA0F, 0xFA50, 0xFA55, 0xFA5A, 0xFA5F,
00125         0xFAA0, 0xFAA5, 0xFAAA, 0xFAAF, 0xFAF0, 0xFAF5, 0xFAFA, 0xFAFF,
00126         0xFF00, 0xFF05, 0xFF0A, 0xFF0F, 0xFF50, 0xFF55, 0xFF5A, 0xFF5F,
00127         0xFFA0, 0xFFA5, 0xFFAA, 0xFFAF, 0xFFF0, 0xFFF5, 0xFFFA, 0xFFFF
00128 };
00129 
00130 #ifdef GLOBAL_VARS
00131 static uint16 mx[8];                                            // VIC registers
00132 static uint8 my[8];
00133 static uint8 mx8;
00134 static uint8 ctrl1, ctrl2;
00135 static uint8 lpx, lpy;
00136 static uint8 me, mxe, mye, mdp, mmc;
00137 static uint8 vbase;
00138 static uint8 irq_flag, irq_mask;
00139 static uint8 clx_spr, clx_bgr;
00140 static uint8 ec, b0c, b1c, b2c, b3c, mm0, mm1;
00141 static uint8 sc[8];
00142 
00143 static uint8 *ram, *char_rom, *color_ram; // Pointers to RAM and ROM
00144 static C64 *the_c64;                                    // Pointer to C64
00145 static C64Display *the_display;                 // Pointer to C64Display
00146 static MOS6510 *the_cpu;                                // Pointer to 6510
00147 static MOS6569 *the_vic;                                // Pointer to self
00148 
00149 static uint8 colors[256];                               // Indices of the 16 C64 colors (16 times mirrored to avoid "& 0x0f")
00150 
00151 static uint8 ec_color, b0c_color, b1c_color, b2c_color, b3c_color; // Indices for exterior/background colors
00152 static uint8 mm0_color, mm1_color;              // Indices for MOB multicolors
00153 static uint8 spr_color[8];                              // Indices for MOB colors
00154 
00155 static uint8 matrix_line[40];                   // Buffer for video line, read in Bad Lines
00156 static uint8 color_line[40];                    // Buffer for color line, read in Bad Lines
00157 
00158 #ifdef __POWERPC__
00159 static double chunky_tmp[DISPLAY_X/8];  // Temporary line buffer for GameKit speedup
00160 #endif
00161 static uint8 *chunky_ptr;                               // Pointer in chunky bitmap buffer
00162 static uint8 *chunky_line_start;                // Pointer to start of current line in bitmap buffer
00163 static uint8 *fore_mask_ptr;                    // Pointer in fore_mask_buf
00164 static int xmod;                                                // Number of bytes per row
00165 
00166 static uint16 raster_x;                                 // Current raster x position
00167 static uint16 raster_y;                                 // Current raster line
00168 static uint16 irq_raster;                               // Interrupt raster line
00169 static uint16 dy_start;                                 // Comparison values for border logic
00170 static uint16 dy_stop;
00171 static uint16 rc;                                               // Row counter
00172 static uint16 vc;                                               // Video counter
00173 static uint16 vc_base;                                  // Video counter base
00174 static uint16 x_scroll;                                 // X scroll value
00175 static uint16 y_scroll;                                 // Y scroll value
00176 static uint16 cia_vabase;                               // CIA VA14/15 video base
00177 
00178 static int cycle;                                               // Current cycle in line (1..63)
00179 
00180 static int display_idx;                                 // Index of current display mode
00181 static int ml_index;                                    // Index in matrix/color_line[]
00182 static int skip_counter;                                // Counter for frame-skipping
00183 
00184 static uint16 mc[8];                                    // Sprite data counters
00185 static uint16 mc_base[8];                               // Sprite data counter bases
00186 
00187 static uint8 spr_coll_buf[0x180];               // Buffer for sprite-sprite collisions and priorities
00188 static uint8 fore_mask_buf[0x180/8];    // Foreground mask for sprite-graphics collisions and priorities
00189 
00190 static bool display_state;                              // true: Display state, false: Idle state
00191 static bool border_on;                                  // Flag: Upper/lower border on
00192 static bool frame_skipped;                              // Flag: Frame is being skipped
00193 static bool bad_lines_enabled;                  // Flag: Bad Lines enabled for this frame
00194 static bool lp_triggered;                               // Flag: Lightpen was triggered in this frame
00195 static bool is_bad_line;                                // Flag: Current line is Bad Line
00196 static bool draw_this_line;                             // Flag: This line is drawn on the screen
00197 static bool ud_border_on;                               // Flag: Upper/lower border on
00198 static bool vblanking;                                  // Flag: VBlank in next cycle
00199 
00200 static bool border_on_sample[5];                // Samples of border state at different cycles (1, 17, 18, 56, 57)
00201 static uint8 border_color_sample[DISPLAY_X/8];  // Samples of border color at each "displayed" cycle
00202 
00203 static uint16 matrix_base;                              // Video matrix base
00204 static uint16 char_base;                                        // Character generator base
00205 static uint16 bitmap_base;                              // Bitmap base
00206 
00207 static uint8 ref_cnt;                                   // Refresh counter
00208 static uint8 spr_exp_y;                                 // 8 sprite y expansion flipflops
00209 static uint8 spr_dma_on;                                // 8 flags: Sprite DMA active
00210 static uint8 spr_disp_on;                               // 8 flags: Sprite display active
00211 static uint8 spr_draw;                                  // 8 flags: Draw sprite in this line
00212 static uint16 spr_ptr[8];                               // Sprite data pointers
00213 
00214 static uint8 gfx_data, char_data, color_data, last_char_data;
00215 static uint8 spr_data[8][4];                    // Sprite data read
00216 static uint8 spr_draw_data[8][4];               // Sprite data for drawing
00217 
00218 static uint32 first_ba_cycle;                   // Cycle when BA first went low
00219 #endif
00220 
00221 
00222 /*
00223  *  Constructor: Initialize variables
00224  */
00225 
00226 MOS6569::MOS6569(C64 *c64, C64Display *disp, MOS6510 *CPU, uint8 *RAM, uint8 *Char, uint8 *Color)
00227 #ifndef GLOBAL_VARS
00228         : ram(RAM), char_rom(Char), color_ram(Color), the_c64(c64), the_display(disp), the_cpu(CPU)
00229 #endif
00230 {
00231         int i;
00232 
00233         // Set pointers
00234 #ifdef GLOBAL_VARS
00235         the_vic = this;
00236         the_c64 = c64;
00237         the_display = disp;
00238         the_cpu = CPU;
00239         ram = RAM;
00240         char_rom = Char;
00241         color_ram = Color;
00242 #endif
00243         matrix_base = 0;
00244         char_base = 0;
00245         bitmap_base = 0;
00246 
00247         // Get bitmap info
00248         chunky_ptr = chunky_line_start = disp->BitmapBase();
00249         xmod = disp->BitmapXMod();
00250 
00251         // Initialize VIC registers
00252         mx8 = 0;
00253         ctrl1 = ctrl2 = 0;
00254         lpx = lpy = 0;
00255         me = mxe = mye = mdp = mmc = 0;
00256         vbase = irq_flag = irq_mask = 0;
00257         clx_spr = clx_bgr = 0;
00258         cia_vabase = 0;
00259         ec = b0c = b1c = b2c = b3c = mm0 = mm1 = 0;
00260         for (i=0; i<8; i++) mx[i] = my[i] = sc[i] = 0;
00261 
00262         // Initialize other variables
00263         raster_y = TOTAL_RASTERS - 1;
00264         rc = 7;
00265         irq_raster = vc = vc_base = x_scroll = y_scroll = 0;
00266         dy_start = ROW24_YSTART;
00267         dy_stop = ROW24_YSTOP;
00268         ml_index = 0;
00269 
00270         cycle = 1;
00271         display_idx = 0;
00272         display_state = false;
00273         border_on = ud_border_on = vblanking = false;
00274         lp_triggered = draw_this_line = false;
00275 
00276         spr_dma_on = spr_disp_on = 0;
00277         for (i=0; i<8; i++) {
00278                 mc[i] = 63;
00279                 spr_ptr[i] = 0;
00280         }
00281 
00282         frame_skipped = false;
00283         skip_counter = 1;
00284 
00285         memset(spr_coll_buf, 0, 0x180);
00286         memset(fore_mask_buf, 0, 0x180/8);
00287 
00288         // Preset colors to black
00289         disp->InitColors(colors);
00290         ec_color = b0c_color = b1c_color = b2c_color = b3c_color = mm0_color = mm1_color = colors[0];
00291         for (i=0; i<8; i++) spr_color[i] = colors[0];
00292 }
00293 
00294 
00295 /*
00296  *  Reinitialize the colors table for when the palette has changed
00297  */
00298 
00299 void MOS6569::ReInitColors(void)
00300 {
00301         int i;
00302 
00303         // Build inverse color table.
00304         uint8 xlate_colors[256];
00305         memset(xlate_colors, 0, sizeof(xlate_colors));
00306         for (i = 0; i < 16; i++)
00307                 xlate_colors[colors[i]] = i;
00308 
00309         // Get the new colors.
00310         the_display->InitColors(colors);
00311 
00312         // Build color translation table.
00313         for (i = 0; i < 256; i++)
00314                 xlate_colors[i] = colors[xlate_colors[i]];
00315 
00316         // Translate all the old colors variables.
00317         ec_color = colors[ec];
00318         b0c_color = colors[b0c];
00319         b1c_color = colors[b1c];
00320         b2c_color = colors[b2c];
00321         b3c_color = colors[b3c];
00322         mm0_color = colors[mm0];
00323         mm1_color = colors[mm1];
00324         for (i = 0; i < 8; i++)
00325                 spr_color[i] = colors[sc[i]];
00326 
00327         // Translate the border color sample buffer.
00328         for (int x = 0; x < sizeof(border_color_sample); x++)
00329                 border_color_sample[x] = xlate_colors[border_color_sample[x]];
00330 
00331         // Translate the chunky buffer.
00332         uint8 *scanline = the_display->BitmapBase();
00333         for (int y = 0; y < DISPLAY_Y; y++) {
00334                 for (int x = 0; x < DISPLAY_X; x++)
00335                         scanline[x] = xlate_colors[scanline[x]];
00336                 scanline += xmod;
00337         }
00338 }
00339 
00340 
00341 /*
00342  *  Get VIC state
00343  */
00344 
00345 void MOS6569::GetState(MOS6569State *vd)
00346 {
00347         int i;
00348 
00349         vd->m0x = mx[0] & 0xff; vd->m0y = my[0];
00350         vd->m1x = mx[1] & 0xff; vd->m1y = my[1];
00351         vd->m2x = mx[2] & 0xff; vd->m2y = my[2];
00352         vd->m3x = mx[3] & 0xff; vd->m3y = my[3];
00353         vd->m4x = mx[4] & 0xff; vd->m4y = my[4];
00354         vd->m5x = mx[5] & 0xff; vd->m5y = my[5];
00355         vd->m6x = mx[6] & 0xff; vd->m6y = my[6];
00356         vd->m7x = mx[7] & 0xff; vd->m7y = my[7];
00357         vd->mx8 = mx8;
00358 
00359         vd->ctrl1 = (ctrl1 & 0x7f) | ((raster_y & 0x100) >> 1);
00360         vd->raster = raster_y & 0xff;
00361         vd->lpx = lpx; vd->lpy = lpy;
00362         vd->ctrl2 = ctrl2;
00363         vd->vbase = vbase;
00364         vd->irq_flag = irq_flag;
00365         vd->irq_mask = irq_mask;
00366 
00367         vd->me = me; vd->mxe = mxe; vd->mye = mye; vd->mdp = mdp; vd->mmc = mmc;
00368         vd->mm = clx_spr; vd->md = clx_bgr;
00369 
00370         vd->ec = ec;
00371         vd->b0c = b0c; vd->b1c = b1c; vd->b2c = b2c; vd->b3c = b3c;
00372         vd->mm0 = mm0; vd->mm1 = mm1;
00373         vd->m0c = sc[0];
00374         vd->m1c = sc[1];
00375         vd->m2c = sc[2];
00376         vd->m3c = sc[3];
00377         vd->m4c = sc[4];
00378         vd->m5c = sc[5];
00379         vd->m6c = sc[6];
00380         vd->m7c = sc[7];
00381 
00382         vd->pad0 = 0;
00383         vd->irq_raster = irq_raster;
00384         vd->vc = vc;
00385         vd->vc_base = vc_base;
00386         vd->rc = rc;
00387         vd->spr_dma = spr_dma_on;
00388         vd->spr_disp = spr_disp_on;
00389         for (i=0; i<8; i++) {
00390                 vd->mc[i] = mc[i];
00391                 vd->mc_base[i] = mc_base[i];
00392         }
00393         vd->display_state = display_state;
00394         vd->bad_line = raster_y >= FIRST_DMA_LINE && raster_y <= LAST_DMA_LINE && ((raster_y & 7) == y_scroll) && bad_lines_enabled;
00395         vd->bad_line_enable = bad_lines_enabled;
00396         vd->lp_triggered = lp_triggered;
00397         vd->border_on = border_on;
00398 
00399         vd->bank_base = cia_vabase;
00400         vd->matrix_base = ((vbase & 0xf0) << 6) | cia_vabase;
00401         vd->char_base = ((vbase & 0x0e) << 10) | cia_vabase;
00402         vd->bitmap_base = ((vbase & 0x08) << 10) | cia_vabase;
00403         for (i=0; i<8; i++)
00404                 vd->sprite_base[i] = spr_ptr[i] | cia_vabase;
00405 
00406         vd->cycle = cycle;
00407         vd->raster_x = raster_x;
00408         vd->ml_index = ml_index;
00409         vd->ref_cnt = ref_cnt;
00410         vd->last_vic_byte = LastVICByte;
00411         vd->ud_border_on = ud_border_on;
00412 }
00413 
00414 
00415 /*
00416  *  Set VIC state (only works if in VBlank)
00417  */
00418 
00419 void MOS6569::SetState(MOS6569State *vd)
00420 {
00421         int i, j;
00422 
00423         mx[0] = vd->m0x; my[0] = vd->m0y;
00424         mx[1] = vd->m1x; my[1] = vd->m1y;
00425         mx[2] = vd->m2x; my[2] = vd->m2y;
00426         mx[3] = vd->m3x; my[3] = vd->m3y;
00427         mx[4] = vd->m4x; my[4] = vd->m4y;
00428         mx[5] = vd->m5x; my[5] = vd->m5y;
00429         mx[6] = vd->m6x; my[6] = vd->m6y;
00430         mx[7] = vd->m7x; my[7] = vd->m7y;
00431         mx8 = vd->mx8;
00432         for (i=0, j=1; i<8; i++, j<<=1) {
00433                 if (mx8 & j)
00434                         mx[i] |= 0x100;
00435                 else
00436                         mx[i] &= 0xff;
00437         }
00438 
00439         ctrl1 = vd->ctrl1;
00440         ctrl2 = vd->ctrl2;
00441         x_scroll = ctrl2 & 7;
00442         y_scroll = ctrl1 & 7;
00443         if (ctrl1 & 8) {
00444                 dy_start = ROW25_YSTART;
00445                 dy_stop = ROW25_YSTOP;
00446         } else {
00447                 dy_start = ROW24_YSTART;
00448                 dy_stop = ROW24_YSTOP;
00449         }
00450         display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4;
00451 
00452         raster_y = 0;
00453         lpx = vd->lpx; lpy = vd->lpy;
00454 
00455         vbase = vd->vbase;
00456         cia_vabase = vd->bank_base;
00457         matrix_base = (vbase & 0xf0) << 6;
00458         char_base = (vbase & 0x0e) << 10;
00459         bitmap_base = (vbase & 0x08) << 10;
00460 
00461         irq_flag = vd->irq_flag;
00462         irq_mask = vd->irq_mask;
00463 
00464         me = vd->me; mxe = vd->mxe; mye = vd->mye; mdp = vd->mdp; mmc = vd->mmc;
00465         clx_spr = vd->mm; clx_bgr = vd->md;
00466 
00467         ec = vd->ec;
00468         ec_color = colors[ec];
00469 
00470         b0c = vd->b0c; b1c = vd->b1c; b2c = vd->b2c; b3c = vd->b3c;
00471         b0c_color = colors[b0c];
00472         b1c_color = colors[b1c];
00473         b2c_color = colors[b2c];
00474         b3c_color = colors[b3c];
00475 
00476         mm0 = vd->mm0; mm1 = vd->mm1;
00477         mm0_color = colors[mm0];
00478         mm1_color = colors[mm1];
00479 
00480         sc[0] = vd->m0c; sc[1] = vd->m1c;
00481         sc[2] = vd->m2c; sc[3] = vd->m3c;
00482         sc[4] = vd->m4c; sc[5] = vd->m5c;
00483         sc[6] = vd->m6c; sc[7] = vd->m7c;
00484         for (i=0; i<8; i++)
00485                 spr_color[i] = colors[sc[i]];
00486 
00487         irq_raster = vd->irq_raster;
00488         vc = vd->vc;
00489         vc_base = vd->vc_base;
00490         rc = vd->rc;
00491         spr_dma_on = vd->spr_dma;
00492         spr_disp_on = vd->spr_disp;
00493         for (i=0; i<8; i++) {
00494                 mc[i] = vd->mc[i];
00495                 mc_base[i] = vd->mc_base[i];
00496                 spr_ptr[i] = vd->sprite_base[i] & 0x3fff;
00497         }
00498         display_state = vd->display_state;
00499         bad_lines_enabled = vd->bad_line_enable;
00500         lp_triggered = vd->lp_triggered;
00501         border_on = vd->border_on;
00502 
00503         cycle = vd->cycle;
00504         raster_x = vd->raster_x;
00505         ml_index = vd->ml_index;
00506         ref_cnt = vd->ref_cnt;
00507         LastVICByte = vd->last_vic_byte;
00508         ud_border_on = vd->ud_border_on;
00509 }
00510 
00511 
00512 /*
00513  *  Trigger raster IRQ
00514  */
00515 
00516 #ifdef GLOBAL_VARS
00517 static inline void raster_irq(void)
00518 #else
00519 inline void MOS6569::raster_irq(void)
00520 #endif
00521 {
00522         irq_flag |= 0x01;
00523         if (irq_mask & 0x01) {
00524                 irq_flag |= 0x80;
00525                 the_cpu->TriggerVICIRQ();
00526         }
00527 }
00528 
00529 
00530 /*
00531  *  Read from VIC register
00532  */
00533 
00534 uint8 MOS6569::ReadRegister(uint16 adr)
00535 {
00536         switch (adr) {
00537                 case 0x00: case 0x02: case 0x04: case 0x06:
00538                 case 0x08: case 0x0a: case 0x0c: case 0x0e:
00539                         return mx[adr >> 1];
00540 
00541                 case 0x01: case 0x03: case 0x05: case 0x07:
00542                 case 0x09: case 0x0b: case 0x0d: case 0x0f:
00543                         return my[adr >> 1];
00544 
00545                 case 0x10:      // Sprite X position MSB
00546                         return mx8;
00547 
00548                 case 0x11:      // Control register 1
00549                         return (ctrl1 & 0x7f) | ((raster_y & 0x100) >> 1);
00550 
00551                 case 0x12:      // Raster counter
00552                         return raster_y;
00553 
00554                 case 0x13:      // Light pen X
00555                         return lpx;
00556 
00557                 case 0x14:      // Light pen Y
00558                         return lpy;
00559 
00560                 case 0x15:      // Sprite enable
00561                         return me;
00562 
00563                 case 0x16:      // Control register 2
00564                         return ctrl2 | 0xc0;
00565 
00566                 case 0x17:      // Sprite Y expansion
00567                         return mye;
00568 
00569                 case 0x18:      // Memory pointers
00570                         return vbase | 0x01;
00571 
00572                 case 0x19:      // IRQ flags
00573                         return irq_flag | 0x70;
00574 
00575                 case 0x1a:      // IRQ mask
00576                         return irq_mask | 0xf0;
00577 
00578                 case 0x1b:      // Sprite data priority
00579                         return mdp;
00580 
00581                 case 0x1c:      // Sprite multicolor
00582                         return mmc;
00583 
00584                 case 0x1d:      // Sprite X expansion
00585                         return mxe;
00586 
00587                 case 0x1e:{     // Sprite-sprite collision
00588                         uint8 ret = clx_spr;
00589                         clx_spr = 0;    // Read and clear
00590                         return ret;
00591                 }
00592 
00593                 case 0x1f:{     // Sprite-background collision
00594                         uint8 ret = clx_bgr;
00595                         clx_bgr = 0;    // Read and clear
00596                         return ret;
00597                 }
00598 
00599                 case 0x20: return ec | 0xf0;
00600                 case 0x21: return b0c | 0xf0;
00601                 case 0x22: return b1c | 0xf0;
00602                 case 0x23: return b2c | 0xf0;
00603                 case 0x24: return b3c | 0xf0;
00604                 case 0x25: return mm0 | 0xf0;
00605                 case 0x26: return mm1 | 0xf0;
00606 
00607                 case 0x27: case 0x28: case 0x29: case 0x2a:
00608                 case 0x2b: case 0x2c: case 0x2d: case 0x2e:
00609                         return sc[adr - 0x27] | 0xf0;
00610 
00611                 default:
00612                         return 0xff;
00613         }
00614 }
00615 
00616 
00617 /*
00618  *  Write to VIC register
00619  */
00620 
00621 void MOS6569::WriteRegister(uint16 adr, uint8 byte)
00622 {
00623         switch (adr) {
00624                 case 0x00: case 0x02: case 0x04: case 0x06:
00625                 case 0x08: case 0x0a: case 0x0c: case 0x0e:
00626                         mx[adr >> 1] = (mx[adr >> 1] & 0xff00) | byte;
00627                         break;
00628 
00629                 case 0x10:{
00630                         int i, j;
00631                         mx8 = byte;
00632                         for (i=0, j=1; i<8; i++, j<<=1) {
00633                                 if (mx8 & j)
00634                                         mx[i] |= 0x100;
00635                                 else
00636                                         mx[i] &= 0xff;
00637                         }
00638                         break;
00639                 }
00640 
00641                 case 0x01: case 0x03: case 0x05: case 0x07:
00642                 case 0x09: case 0x0b: case 0x0d: case 0x0f:
00643                         my[adr >> 1] = byte;
00644                         break;
00645 
00646                 case 0x11:{     // Control register 1
00647                         ctrl1 = byte;
00648                         y_scroll = byte & 7;
00649 
00650                         uint16 new_irq_raster = (irq_raster & 0xff) | ((byte & 0x80) << 1);
00651                         if (irq_raster != new_irq_raster && raster_y == new_irq_raster)
00652                                 raster_irq();
00653                         irq_raster = new_irq_raster;
00654 
00655                         if (byte & 8) {
00656                                 dy_start = ROW25_YSTART;
00657                                 dy_stop = ROW25_YSTOP;
00658                         } else {
00659                                 dy_start = ROW24_YSTART;
00660                                 dy_stop = ROW24_YSTOP;
00661                         }
00662 
00663                         // In line $30, the DEN bit controls if Bad Lines can occur
00664                         if (raster_y == 0x30 && byte & 0x10)
00665                                 bad_lines_enabled = true;
00666 
00667                         // Bad Line condition?
00668                         is_bad_line = (raster_y >= FIRST_DMA_LINE && raster_y <= LAST_DMA_LINE && ((raster_y & 7) == y_scroll) && bad_lines_enabled);
00669 
00670                         display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4;
00671                         break;
00672                 }
00673 
00674                 case 0x12:{     // Raster counter
00675                         uint16 new_irq_raster = (irq_raster & 0xff00) | byte;
00676                         if (irq_raster != new_irq_raster && raster_y == new_irq_raster)
00677                                 raster_irq();
00678                         irq_raster = new_irq_raster;
00679                         break;
00680                 }
00681 
00682                 case 0x15:      // Sprite enable
00683                         me = byte;
00684                         break;
00685 
00686                 case 0x16:      // Control register 2
00687                         ctrl2 = byte;
00688                         x_scroll = byte & 7;
00689                         display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4;
00690                         break;
00691 
00692                 case 0x17:      // Sprite Y expansion
00693                         mye = byte;
00694                         spr_exp_y |= ~byte;
00695                         break;
00696 
00697                 case 0x18:      // Memory pointers
00698                         vbase = byte;
00699                         matrix_base = (byte & 0xf0) << 6;
00700                         char_base = (byte & 0x0e) << 10;
00701                         bitmap_base = (byte & 0x08) << 10;
00702                         break;
00703 
00704                 case 0x19: // IRQ flags
00705                         irq_flag = irq_flag & (~byte & 0x0f);
00706                         if (irq_flag & irq_mask)        // Set master bit if allowed interrupt still pending
00707                                 irq_flag |= 0x80;
00708                         else
00709                                 the_cpu->ClearVICIRQ(); // Else clear interrupt
00710                         break;
00711                 
00712                 case 0x1a:      // IRQ mask
00713                         irq_mask = byte & 0x0f;
00714                         if (irq_flag & irq_mask) {      // Trigger interrupt if pending and now allowed
00715                                 irq_flag |= 0x80;
00716                                 the_cpu->TriggerVICIRQ();
00717                         } else {
00718                                 irq_flag &= 0x7f;
00719                                 the_cpu->ClearVICIRQ();
00720                         }
00721                         break;
00722 
00723                 case 0x1b:      // Sprite data priority
00724                         mdp = byte;
00725                         break;
00726 
00727                 case 0x1c:      // Sprite multicolor
00728                         mmc = byte;
00729                         break;
00730 
00731                 case 0x1d:      // Sprite X expansion
00732                         mxe = byte;
00733                         break;
00734 
00735                 case 0x20: ec_color = colors[ec = byte]; break;
00736                 case 0x21: b0c_color = colors[b0c = byte]; break;
00737                 case 0x22: b1c_color = colors[b1c = byte]; break;
00738                 case 0x23: b2c_color = colors[b2c = byte]; break;
00739                 case 0x24: b3c_color = colors[b3c = byte]; break;
00740                 case 0x25: mm0_color = colors[mm0 = byte]; break;
00741                 case 0x26: mm1_color = colors[mm1 = byte]; break;
00742 
00743                 case 0x27: case 0x28: case 0x29: case 0x2a:
00744                 case 0x2b: case 0x2c: case 0x2d: case 0x2e:
00745                         spr_color[adr - 0x27] = colors[sc[adr - 0x27] = byte];
00746                         break;
00747         }
00748 }
00749 
00750 
00751 /*
00752  *  CIA VA14/15 has changed
00753  */
00754 
00755 void MOS6569::ChangedVA(uint16 new_va)
00756 {
00757         cia_vabase = new_va << 14;
00758         WriteRegister(0x18, vbase); // Force update of memory pointers
00759 }
00760 
00761 
00762 /*
00763  *  Trigger lightpen interrupt, latch lightpen coordinates
00764  */
00765 
00766 void MOS6569::TriggerLightpen(void)
00767 {
00768         if (!lp_triggered) {            // Lightpen triggers only once per frame
00769                 lp_triggered = true;
00770 
00771                 lpx = raster_x >> 1;    // Latch current coordinates
00772                 lpy = raster_y;
00773 
00774                 irq_flag |= 0x08;               // Trigger IRQ
00775                 if (irq_mask & 0x08) {
00776                         irq_flag |= 0x80;
00777                         the_cpu->TriggerVICIRQ();
00778                 }
00779         }
00780 }
00781 
00782 
00783 /*
00784  *  Read a byte from the VIC's address space
00785  */
00786 
00787 #ifdef GLOBAL_VARS
00788 static inline uint8 read_byte(uint16 adr)
00789 #else
00790 inline uint8 MOS6569::read_byte(uint16 adr)
00791 #endif
00792 {
00793         uint16 va = adr | cia_vabase;
00794         if ((va & 0x7000) == 0x1000)
00795 #ifdef GLOBAL_VARS
00796                 return the_vic->LastVICByte = char_rom[va & 0x0fff];
00797 #else
00798                 return LastVICByte = char_rom[va & 0x0fff];
00799 #endif
00800         else
00801 #ifdef GLOBAL_VARS
00802                 return the_vic->LastVICByte = ram[va];
00803 #else
00804                 return LastVICByte = ram[va];
00805 #endif
00806 }
00807 
00808 
00809 /*
00810  *  Quick memset of 8 bytes
00811  */
00812 
00813 inline void memset8(uint8 *p, uint8 c)
00814 {
00815         p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = c;
00816 }
00817 
00818 
00819 /*
00820  *  Video matrix access
00821  */
00822 
00823 #ifdef __i386
00824 inline
00825 #endif
00826 #ifdef GLOBAL_VARS
00827 static void matrix_access(void)
00828 #else
00829 void MOS6569::matrix_access(void)
00830 #endif
00831 {
00832         if (the_cpu->BALow) {
00833                 if (the_c64->CycleCounter-first_ba_cycle < 3)
00834                         matrix_line[ml_index] = color_line[ml_index] = 0xff;
00835                 else {
00836                         uint16 adr = (vc & 0x03ff) | matrix_base;
00837                         matrix_line[ml_index] = read_byte(adr);
00838                         color_line[ml_index] = color_ram[adr & 0x03ff];
00839                 }
00840         }
00841 }
00842 
00843 
00844 /*
00845  *  Graphics data access
00846  */
00847 
00848 #ifdef __i386
00849 inline
00850 #endif
00851 #ifdef GLOBAL_VARS
00852 static void graphics_access(void)
00853 #else
00854 void MOS6569::graphics_access(void)
00855 #endif
00856 {
00857         if (display_state) {
00858 
00859                 uint16 adr;
00860                 if (ctrl1 & 0x20)       // Bitmap
00861                         adr = ((vc & 0x03ff) << 3) | bitmap_base | rc;
00862                 else                            // Text
00863                         adr = (matrix_line[ml_index] << 3) | char_base | rc;
00864                 if (ctrl1 & 0x40)       // ECM
00865                         adr &= 0xf9ff;
00866                 gfx_data = read_byte(adr);
00867                 char_data = matrix_line[ml_index];
00868                 color_data = color_line[ml_index];
00869                 ml_index++;
00870                 vc++;
00871 
00872         } else {
00873 
00874                 // Display is off
00875                 gfx_data = read_byte(ctrl1 & 0x40 ? 0x39ff : 0x3fff);
00876                 char_data = color_data = 0;
00877         }
00878 }
00879 
00880 
00881 /*
00882  *  Background display (8 pixels)
00883  */
00884 
00885 #ifdef GLOBAL_VARS
00886 static void draw_background(void)
00887 #else
00888 void MOS6569::draw_background(void)
00889 #endif
00890 {
00891         uint8 *p = chunky_ptr;
00892         uint8 c;
00893 
00894         if (!draw_this_line)
00895                 return;
00896 
00897         switch (display_idx) {
00898                 case 0:         // Standard text
00899                 case 1:         // Multicolor text
00900                 case 3:         // Multicolor bitmap
00901                         c = b0c_color;
00902                         break;
00903                 case 2:         // Standard bitmap
00904                         c = colors[last_char_data];
00905                         break;
00906                 case 4:         // ECM text
00907                         if (last_char_data & 0x80)
00908                                 if (last_char_data & 0x40)
00909                                         c = b3c_color;
00910                                 else
00911                                         c = b2c_color;
00912                         else
00913                                 if (last_char_data & 0x40)
00914                                         c = b1c_color;
00915                                 else
00916                                         c = b0c_color;
00917                         break;
00918                 default:
00919                         c = colors[0];
00920                         break;
00921         }
00922         memset8(p, c);
00923 }
00924 
00925 
00926 /*
00927  *  Graphics display (8 pixels)
00928  */
00929 
00930 #ifdef __i386
00931 inline
00932 #endif
00933 #ifdef GLOBAL_VARS
00934 static void draw_graphics(void)
00935 #else
00936 void MOS6569::draw_graphics(void)
00937 #endif
00938 {
00939         uint8 *p = chunky_ptr + x_scroll;
00940         uint8 c[4], data;
00941 
00942         if (!draw_this_line)
00943                 return;
00944         if (ud_border_on) {
00945                 draw_background();
00946                 return;
00947         }
00948 
00949         switch (display_idx) {
00950 
00951                 case 0:         // Standard text
00952                         c[0] = b0c_color;
00953                         c[1] = colors[color_data];
00954                         goto draw_std;
00955 
00956                 case 1:         // Multicolor text
00957                         if (color_data & 8) {
00958                                 c[0] = b0c_color;
00959                                 c[1] = b1c_color;
00960                                 c[2] = b2c_color;
00961                                 c[3] = colors[color_data & 7];
00962                                 goto draw_multi;
00963                         } else {
00964                                 c[0] = b0c_color;
00965                                 c[1] = colors[color_data];
00966                                 goto draw_std;
00967                         }
00968 
00969                 case 2:         // Standard bitmap
00970                         c[0] = colors[char_data];
00971                         c[1] = colors[char_data >> 4];
00972                         goto draw_std;
00973 
00974                 case 3:         // Multicolor bitmap
00975                         c[0]= b0c_color;
00976                         c[1] = colors[char_data >> 4];
00977                         c[2] = colors[char_data];
00978                         c[3] = colors[color_data];
00979                         goto draw_multi;
00980 
00981                 case 4:         // ECM text
00982                         if (char_data & 0x80)
00983                                 if (char_data & 0x40)
00984                                         c[0] = b3c_color;
00985                                 else
00986                                         c[0] = b2c_color;
00987                         else
00988                                 if (char_data & 0x40)
00989                                         c[0] = b1c_color;
00990                                 else
00991                                         c[0] = b0c_color;
00992                         c[1] = colors[color_data];
00993                         goto draw_std;
00994 
00995                 case 5:         // Invalid multicolor text
00996                         memset8(p, colors[0]);
00997                         if (color_data & 8) {
00998                                 fore_mask_ptr[0] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) >> x_scroll;
00999                                 fore_mask_ptr[1] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) << (8-x_scroll);
01000                         } else {
01001                                 fore_mask_ptr[0] |= gfx_data >> x_scroll;
01002                                 fore_mask_ptr[1] |= gfx_data << (7-x_scroll);
01003                         }
01004                         return;
01005 
01006                 case 6:         // Invalid standard bitmap
01007                         memset8(p, colors[0]);
01008                         fore_mask_ptr[0] |= gfx_data >> x_scroll;
01009                         fore_mask_ptr[1] |= gfx_data << (7-x_scroll);
01010                         return;
01011 
01012                 case 7:         // Invalid multicolor bitmap
01013                         memset8(p, colors[0]);
01014                         fore_mask_ptr[0] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) >> x_scroll;
01015                         fore_mask_ptr[1] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) << (8-x_scroll);
01016                         return;
01017 
01018                 default:        // Can't happen
01019                         return;
01020         }
01021 
01022 draw_std:
01023 
01024         fore_mask_ptr[0] |= gfx_data >> x_scroll;
01025         fore_mask_ptr[1] |= gfx_data << (7-x_scroll);
01026 
01027         data = gfx_data;
01028         p[7] = c[data & 1]; data >>= 1;
01029         p[6] = c[data & 1]; data >>= 1;
01030         p[5] = c[data & 1]; data >>= 1;
01031         p[4] = c[data & 1]; data >>= 1;
01032         p[3] = c[data & 1]; data >>= 1;
01033         p[2] = c[data & 1]; data >>= 1;
01034         p[1] = c[data & 1]; data >>= 1;
01035         p[0] = c[data];
01036         return;
01037 
01038 draw_multi:
01039 
01040         fore_mask_ptr[0] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) >> x_scroll;
01041         fore_mask_ptr[1] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) << (8-x_scroll);
01042 
01043         data = gfx_data;
01044         p[7] = p[6] = c[data & 3]; data >>= 2;
01045         p[5] = p[4] = c[data & 3]; data >>= 2;
01046         p[3] = p[2] = c[data & 3]; data >>= 2;
01047         p[1] = p[0] = c[data];
01048         return;
01049 }
01050 
01051 
01052 /*
01053  *  Sprite display
01054  */
01055 
01056 #ifdef GLOBAL_VARS
01057 inline static void draw_sprites(void)
01058 #else
01059 inline void MOS6569::draw_sprites(void)
01060 #endif
01061 {
01062         int i;
01063         int snum, sbit;         // Sprite number/bit mask
01064         int spr_coll=0, gfx_coll=0;
01065 
01066         // Clear sprite collision buffer
01067         {
01068                 uint32 *lp = (uint32 *)spr_coll_buf - 1;
01069                 for (i=0; i<DISPLAY_X/4; i++)
01070                         *++lp = 0;
01071         }
01072 
01073         // Loop for all sprites
01074         for (snum=0, sbit=1; snum<8; snum++, sbit<<=1) {
01075 
01076                 // Is sprite visible?
01077                 if ((spr_draw & sbit) && mx[snum] <= DISPLAY_X-32) {
01078 #ifdef __POWERPC__
01079                         uint8 *p = (uint8 *)chunky_tmp + mx[snum] + 8;
01080 #else
01081                         uint8 *p = chunky_line_start + mx[snum] + 8;
01082 #endif
01083                         uint8 *q = spr_coll_buf + mx[snum] + 8;
01084                         uint8 color = spr_color[snum];
01085 
01086                         // Fetch sprite data and mask
01087                         uint32 sdata = (spr_draw_data[snum][0] << 24) | (spr_draw_data[snum][1] << 16) | (spr_draw_data[snum][2] << 8);
01088 
01089                         int spr_mask_pos = mx[snum] + 8;        // Sprite bit position in fore_mask_buf
01090                         
01091                         uint8 *fmbp = fore_mask_buf + (spr_mask_pos / 8);
01092                         int sshift = spr_mask_pos & 7;
01093                         uint32 fore_mask = (((*(fmbp+0) << 24) | (*(fmbp+1) << 16) | (*(fmbp+2) << 8)
01094                                                     | (*(fmbp+3))) << sshift) | (*(fmbp+4) >> (8-sshift));
01095 
01096                         if (mxe & sbit) {               // X-expanded
01097                                 if (mx[snum] > DISPLAY_X-56)
01098                                         continue;
01099 
01100                                 uint32 sdata_l = 0, sdata_r = 0, fore_mask_r;
01101                                 fore_mask_r = (((*(fmbp+4) << 24) | (*(fmbp+5) << 16) | (*(fmbp+6) << 8)
01102                                                 | (*(fmbp+7))) << sshift) | (*(fmbp+8) >> (8-sshift));
01103 
01104                                 if (mmc & sbit) {       // Multicolor mode
01105                                         uint32 plane0_l, plane0_r, plane1_l, plane1_r;
01106 
01107                                         // Expand sprite data
01108                                         sdata_l = MultiExpTable[sdata >> 24 & 0xff] << 16 | MultiExpTable[sdata >> 16 & 0xff];
01109                                         sdata_r = MultiExpTable[sdata >> 8 & 0xff] << 16;
01110 
01111                                         // Convert sprite chunky pixels to bitplanes
01112                                         plane0_l = (sdata_l & 0x55555555) | (sdata_l & 0x55555555) << 1;
01113                                         plane1_l = (sdata_l & 0xaaaaaaaa) | (sdata_l & 0xaaaaaaaa) >> 1;
01114                                         plane0_r = (sdata_r & 0x55555555) | (sdata_r & 0x55555555) << 1;
01115                                         plane1_r = (sdata_r & 0xaaaaaaaa) | (sdata_r & 0xaaaaaaaa) >> 1;
01116 
01117                                         // Collision with graphics?
01118                                         if ((fore_mask & (plane0_l | plane1_l)) || (fore_mask_r & (plane0_r | plane1_r))) {
01119                                                 gfx_coll |= sbit;
01120                                                 if (mdp & sbit) {
01121                                                         plane0_l &= ~fore_mask; // Mask sprite if in background
01122                                                         plane1_l &= ~fore_mask;
01123                                                         plane0_r &= ~fore_mask_r;
01124                                                         plane1_r &= ~fore_mask_r;
01125                                                 }
01126                                         }
01127 
01128                                         // Paint sprite
01129                                         for (i=0; i<32; i++, plane0_l<<=1, plane1_l<<=1) {
01130                                                 uint8 col;
01131                                                 if (plane1_l & 0x80000000) {
01132                                                         if (plane0_l & 0x80000000)
01133                                                                 col = mm1_color;
01134                                                         else
01135                                                                 col = color;
01136                                                 } else {
01137                                                         if (plane0_l & 0x80000000)
01138                                                                 col = mm0_color;
01139                                                         else
01140                                                                 continue;
01141                                                 }
01142                                                 if (q[i])
01143                                                         spr_coll |= q[i] | sbit;
01144                                                 else {
01145                                                         p[i] = col;
01146                                                         q[i] = sbit;
01147                                                 }
01148                                         }
01149                                         for (; i<48; i++, plane0_r<<=1, plane1_r<<=1) {
01150                                                 uint8 col;
01151                                                 if (plane1_r & 0x80000000) {
01152                                                         if (plane0_r & 0x80000000)
01153                                                                 col = mm1_color;
01154                                                         else
01155                                                                 col = color;
01156                                                 } else {
01157                                                         if (plane0_r & 0x80000000)
01158                                                                 col = mm0_color;
01159                                                         else
01160                                                                 continue;
01161                                                 }
01162                                                 if (q[i])
01163                                                         spr_coll |= q[i] | sbit;
01164                                                 else {
01165                                                         p[i] = col;
01166                                                         q[i] = sbit;
01167                                                 }
01168                                         }
01169 
01170                                 } else {                        // Standard mode
01171 
01172                                         // Expand sprite data
01173                                         sdata_l = ExpTable[sdata >> 24 & 0xff] << 16 | ExpTable[sdata >> 16 & 0xff];
01174                                         sdata_r = ExpTable[sdata >> 8 & 0xff] << 16;
01175 
01176                                         // Collision with graphics?
01177                                         if ((fore_mask & sdata_l) || (fore_mask_r & sdata_r)) {
01178                                                 gfx_coll |= sbit;
01179                                                 if (mdp & sbit) {
01180                                                         sdata_l &= ~fore_mask;  // Mask sprite if in background
01181                                                         sdata_r &= ~fore_mask_r;
01182                                                 }
01183                                         }
01184 
01185                                         // Paint sprite
01186                                         for (i=0; i<32; i++, sdata_l<<=1)
01187                                                 if (sdata_l & 0x80000000) {
01188                                                         if (q[i])       // Collision with sprite?
01189                                                                 spr_coll |= q[i] | sbit;
01190                                                         else {          // Draw pixel if no collision
01191                                                                 p[i] = color;
01192                                                                 q[i] = sbit;
01193                                                         }
01194                                                 }
01195                                         for (; i<48; i++, sdata_r<<=1)
01196                                                 if (sdata_r & 0x80000000) {
01197                                                         if (q[i])       // Collision with sprite?
01198                                                                 spr_coll |= q[i] | sbit;
01199                                                         else {          // Draw pixel if no collision
01200                                                                 p[i] = color;
01201                                                                 q[i] = sbit;
01202                                                         }
01203                                                 }
01204                                 }
01205 
01206                         } else {                                // Unexpanded
01207 
01208                                 if (mmc & sbit) {       // Multicolor mode
01209                                         uint32 plane0, plane1;
01210 
01211                                         // Convert sprite chunky pixels to bitplanes
01212                                         plane0 = (sdata & 0x55555555) | (sdata & 0x55555555) << 1;
01213                                         plane1 = (sdata & 0xaaaaaaaa) | (sdata & 0xaaaaaaaa) >> 1;
01214 
01215                                         // Collision with graphics?
01216                                         if (fore_mask & (plane0 | plane1)) {
01217                                                 gfx_coll |= sbit;
01218                                                 if (mdp & sbit) {
01219                                                         plane0 &= ~fore_mask;   // Mask sprite if in background
01220                                                         plane1 &= ~fore_mask;
01221                                                 }
01222                                         }
01223 
01224                                         // Paint sprite
01225                                         for (i=0; i<24; i++, plane0<<=1, plane1<<=1) {
01226                                                 uint8 col;
01227                                                 if (plane1 & 0x80000000) {
01228                                                         if (plane0 & 0x80000000)
01229                                                                 col = mm1_color;
01230                                                         else
01231                                                                 col = color;
01232                                                 } else {
01233                                                         if (plane0 & 0x80000000)
01234                                                                 col = mm0_color;
01235                                                         else
01236                                                                 continue;
01237                                                 }
01238                                                 if (q[i])
01239                                                         spr_coll |= q[i] | sbit;
01240                                                 else {
01241                                                         p[i] = col;
01242                                                         q[i] = sbit;
01243                                                 }
01244                                         }
01245 
01246                                 } else {                        // Standard mode
01247 
01248                                         // Collision with graphics?
01249                                         if (fore_mask & sdata) {
01250                                                 gfx_coll |= sbit;
01251                                                 if (mdp & sbit)
01252                                                         sdata &= ~fore_mask;    // Mask sprite if in background
01253                                         }
01254         
01255                                         // Paint sprite
01256                                         for (i=0; i<24; i++, sdata<<=1)
01257                                                 if (sdata & 0x80000000) {
01258                                                         if (q[i]) {     // Collision with sprite?
01259                                                                 spr_coll |= q[i] | sbit;
01260                                                         } else {                // Draw pixel if no collision
01261                                                                 p[i] = color;
01262                                                                 q[i] = sbit;
01263                                                         }
01264                                                 }
01265                                 }
01266                         }
01267                 }
01268         }
01269 
01270         if (ThePrefs.SpriteCollisions) {
01271 
01272                 // Check sprite-sprite collisions
01273                 if (clx_spr)
01274                         clx_spr |= spr_coll;
01275                 else {
01276                         clx_spr |= spr_coll;
01277                         irq_flag |= 0x04;
01278                         if (irq_mask & 0x04) {
01279                                 irq_flag |= 0x80;
01280                                 the_cpu->TriggerVICIRQ();
01281                         }
01282                 }
01283 
01284                 // Check sprite-background collisions
01285                 if (clx_bgr)
01286                         clx_bgr |= gfx_coll;
01287                 else {
01288                         clx_bgr |= gfx_coll;
01289                         irq_flag |= 0x02;
01290                         if (irq_mask & 0x02) {
01291                                 irq_flag |= 0x80;
01292                                 the_cpu->TriggerVICIRQ();
01293                         }
01294                 }
01295         }
01296 }
01297 
01298 
01299 #ifdef __POWERPC__
01300 static asm void fastcopy(register uchar *dst, register uchar *src);
01301 static asm void fastcopy(register uchar *dst, register uchar *src)
01302 {
01303         lfd             fp0,0(src)
01304         lfd             fp1,8(src)
01305         lfd             fp2,16(src)
01306         lfd             fp3,24(src)
01307         lfd             fp4,32(src)
01308         lfd             fp5,40(src)
01309         lfd             fp6,48(src)
01310         lfd             fp7,56(src)
01311         addi    src,src,64
01312         stfd    fp0,0(dst)
01313         stfd    fp1,8(dst)
01314         stfd    fp2,16(dst)
01315         stfd    fp3,24(dst)
01316         stfd    fp4,32(dst)
01317         stfd    fp5,40(dst)
01318         stfd    fp6,48(dst)
01319         stfd    fp7,56(dst)
01320         addi    dst,dst,64
01321 
01322         lfd             fp0,0(src)
01323         lfd             fp1,8(src)
01324         lfd             fp2,16(src)
01325         lfd             fp3,24(src)
01326         lfd             fp4,32(src)
01327         lfd             fp5,40(src)
01328         lfd             fp6,48(src)
01329         lfd             fp7,56(src)
01330         addi    src,src,64
01331         stfd    fp0,0(dst)
01332         stfd    fp1,8(dst)
01333         stfd    fp2,16(dst)
01334         stfd    fp3,24(dst)
01335         stfd    fp4,32(dst)
01336         stfd    fp5,40(dst)
01337         stfd    fp6,48(dst)
01338         stfd    fp7,56(dst)
01339         addi    dst,dst,64
01340 
01341         lfd             fp0,0(src)
01342         lfd             fp1,8(src)
01343         lfd             fp2,16(src)
01344         lfd             fp3,24(src)
01345         lfd             fp4,32(src)
01346         lfd             fp5,40(src)
01347         lfd             fp6,48(src)
01348         lfd             fp7,56(src)
01349         addi    src,src,64
01350         stfd    fp0,0(dst)
01351         stfd    fp1,8(dst)
01352         stfd    fp2,16(dst)
01353         stfd    fp3,24(dst)
01354         stfd    fp4,32(dst)
01355         stfd    fp5,40(dst)
01356         stfd    fp6,48(dst)
01357         stfd    fp7,56(dst)
01358         addi    dst,dst,64
01359 
01360         lfd             fp0,0(src)
01361         lfd             fp1,8(src)
01362         lfd             fp2,16(src)
01363         lfd             fp3,24(src)
01364         lfd             fp4,32(src)
01365         lfd             fp5,40(src)
01366         lfd             fp6,48(src)
01367         lfd             fp7,56(src)
01368         addi    src,src,64
01369         stfd    fp0,0(dst)
01370         stfd    fp1,8(dst)
01371         stfd    fp2,16(dst)
01372         stfd    fp3,24(dst)
01373         stfd    fp4,32(dst)
01374         stfd    fp5,40(dst)
01375         stfd    fp6,48(dst)
01376         stfd    fp7,56(dst)
01377         addi    dst,dst,64
01378 
01379         lfd             fp0,0(src)
01380         lfd             fp1,8(src)
01381         lfd             fp2,16(src)
01382         lfd             fp3,24(src)
01383         lfd             fp4,32(src)
01384         lfd             fp5,40(src)
01385         lfd             fp6,48(src)
01386         lfd             fp7,56(src)
01387         addi    src,src,64
01388         stfd    fp0,0(dst)
01389         stfd    fp1,8(dst)
01390         stfd    fp2,16(dst)
01391         stfd    fp3,24(dst)
01392         stfd    fp4,32(dst)
01393         stfd    fp5,40(dst)
01394         stfd    fp6,48(dst)
01395         stfd    fp7,56(dst)
01396         addi    dst,dst,64
01397 
01398         lfd             fp0,0(src)
01399         lfd             fp1,8(src)
01400         lfd             fp2,16(src)
01401         lfd             fp3,24(src)
01402         lfd             fp4,32(src)
01403         lfd             fp5,40(src)
01404         lfd             fp6,48(src)
01405         lfd             fp7,56(src)
01406         addi    src,src,64
01407         stfd    fp0,0(dst)
01408         stfd    fp1,8(dst)
01409         stfd    fp2,16(dst)
01410         stfd    fp3,24(dst)
01411         stfd    fp4,32(dst)
01412         stfd    fp5,40(dst)
01413         stfd    fp6,48(dst)
01414         stfd    fp7,56(dst)
01415         addi    dst,dst,64
01416         blr             
01417 }
01418 #endif
01419 
01420 
01421 /*
01422  *  Emulate one clock cycle, returns true if new raster line has started
01423  */
01424 
01425 // Set BA low
01426 #define SetBALow \
01427         if (!the_cpu->BALow) { \
01428                 first_ba_cycle = the_c64->CycleCounter; \
01429                 the_cpu->BALow = true; \
01430         }
01431 
01432 // Turn on display if Bad Line
01433 #define DisplayIfBadLine \
01434         if (is_bad_line) \
01435                 display_state = true;
01436 
01437 // Turn on display and matrix access if Bad Line
01438 #define FetchIfBadLine \
01439         if (is_bad_line) { \
01440                 display_state = true; \
01441                 SetBALow; \
01442         }
01443 
01444 // Turn on display and matrix access and reset RC if Bad Line
01445 #define RCIfBadLine \
01446         if (is_bad_line) { \
01447                 display_state = true; \
01448                 rc = 0; \
01449                 SetBALow; \
01450         }
01451 
01452 // Idle access
01453 #define IdleAccess \
01454         read_byte(0x3fff)
01455 
01456 // Refresh access
01457 #define RefreshAccess \
01458         read_byte(0x3f00 | ref_cnt--)
01459 
01460 // Turn on sprite DMA if necessary
01461 #define CheckSpriteDMA \
01462         mask = 1; \
01463         for (i=0; i<8; i++, mask<<=1) \
01464                 if ((me & mask) && (raster_y & 0xff) == my[i]) { \
01465                         spr_dma_on |= mask; \
01466                         mc_base[i] = 0; \
01467                         if (mye & mask) \
01468                                 spr_exp_y &= ~mask; \
01469                 }
01470 
01471 // Fetch sprite data pointer
01472 #define SprPtrAccess(num) \
01473         spr_ptr[num] = read_byte(matrix_base | 0x03f8 | num) << 6;
01474 
01475 // Fetch sprite data, increment data counter
01476 #define SprDataAccess(num, bytenum) \
01477         if (spr_dma_on & (1 << num)) { \
01478                 spr_data[num][bytenum] = read_byte(mc[num] & 0x3f | spr_ptr[num]); \
01479                 mc[num]++; \
01480         } else if (bytenum == 1) \
01481                 IdleAccess;
01482 
01483 // Sample border color and increment chunky_ptr and fore_mask_ptr
01484 #define SampleBorder \
01485         if (draw_this_line) { \
01486                 if (border_on) \
01487                         border_color_sample[cycle-13] = ec_color; \
01488                 chunky_ptr += 8; \
01489                 fore_mask_ptr++; \
01490         }
01491 
01492 
01493 bool MOS6569::EmulateCycle(void)
01494 {
01495         uint8 mask;
01496         int i;
01497 
01498         switch (cycle) {
01499 
01500                 // Fetch sprite pointer 3, increment raster counter, trigger raster IRQ,
01501                 // test for Bad Line, reset BA if sprites 3 and 4 off, read data of sprite 3
01502                 case 1:
01503                         if (raster_y == TOTAL_RASTERS-1)
01504 
01505                                 // Trigger VBlank in cycle 2
01506                                 vblanking = true;
01507 
01508                         else {
01509 
01510                                 // Increment raster counter
01511                                 raster_y++;
01512 
01513                                 // Trigger raster IRQ if IRQ line reached
01514                                 if (raster_y == irq_raster)
01515                                         raster_irq();
01516 
01517                                 // In line $30, the DEN bit controls if Bad Lines can occur
01518                                 if (raster_y == 0x30)
01519                                         bad_lines_enabled = ctrl1 & 0x10;
01520 
01521                                 // Bad Line condition?
01522                                 is_bad_line = (raster_y >= FIRST_DMA_LINE && raster_y <= LAST_DMA_LINE && ((raster_y & 7) == y_scroll) && bad_lines_enabled);
01523 
01524                                 // Don't draw all lines, hide some at the top and bottom
01525                                 draw_this_line = (raster_y >= FIRST_DISP_LINE && raster_y <= LAST_DISP_LINE && !frame_skipped);
01526                         }
01527 
01528                         // First sample of border state
01529                         border_on_sample[0] = border_on;
01530 
01531                         SprPtrAccess(3);
01532                         SprDataAccess(3, 0);
01533                         DisplayIfBadLine;
01534                         if (!(spr_dma_on & 0x18))
01535                                 the_cpu->BALow = false;
01536                         break;
01537 
01538                 // Set BA for sprite 5, read data of sprite 3
01539                 case 2:
01540                         if (vblanking) {
01541 
01542                                 // Vertical blank, reset counters
01543                                 raster_y = vc_base = 0;
01544                                 ref_cnt = 0xff;
01545                                 lp_triggered = vblanking = false;
01546 
01547                                 if (!(frame_skipped = --skip_counter))
01548                                         skip_counter = ThePrefs.SkipFrames;
01549 
01550                                 the_c64->VBlank(!frame_skipped);
01551 
01552                                 // Get bitmap pointer for next frame. This must be done
01553                                 // after calling the_c64->VBlank() because the preferences
01554                                 // and screen configuration may have been changed there
01555                                 chunky_line_start = the_display->BitmapBase();
01556                                 xmod = the_display->BitmapXMod();
01557 
01558                                 // Trigger raster IRQ if IRQ in line 0
01559                                 if (irq_raster == 0)
01560                                         raster_irq();
01561 
01562                         }
01563 
01564                         // Our output goes here
01565 #ifdef __POWERPC__
01566                         chunky_ptr = (uint8 *)chunky_tmp;
01567 #else
01568                         chunky_ptr = chunky_line_start;
01569 #endif
01570 
01571                         // Clear foreground mask
01572                         memset(fore_mask_buf, 0, DISPLAY_X/8);
01573                         fore_mask_ptr = fore_mask_buf;
01574 
01575                         SprDataAccess(3,1);
01576                         SprDataAccess(3,2);
01577                         DisplayIfBadLine;
01578                         if (spr_dma_on & 0x20)
01579                                 SetBALow;
01580                         break;
01581 
01582                 // Fetch sprite pointer 4, reset BA is sprite 4 and 5 off
01583                 case 3:
01584                         SprPtrAccess(4);
01585                         SprDataAccess(4, 0);
01586                         DisplayIfBadLine;
01587                         if (!(spr_dma_on & 0x30))
01588                                 the_cpu->BALow = false;
01589                         break;
01590 
01591                 // Set BA for sprite 6, read data of sprite 4 
01592                 case 4:
01593                         SprDataAccess(4, 1);
01594                         SprDataAccess(4, 2);
01595                         DisplayIfBadLine;
01596                         if (spr_dma_on & 0x40)
01597                                 SetBALow;
01598                         break;
01599 
01600                 // Fetch sprite pointer 5, reset BA if sprite 5 and 6 off
01601                 case 5:
01602                         SprPtrAccess(5);
01603                         SprDataAccess(5, 0);
01604                         DisplayIfBadLine;
01605                         if (!(spr_dma_on & 0x60))
01606                                 the_cpu->BALow = false;
01607                         break;
01608 
01609                 // Set BA for sprite 7, read data of sprite 5
01610                 case 6:
01611                         SprDataAccess(5, 1);
01612                         SprDataAccess(5, 2);
01613                         DisplayIfBadLine;
01614                         if (spr_dma_on & 0x80)
01615                                 SetBALow;
01616                         break;
01617 
01618                 // Fetch sprite pointer 6, reset BA if sprite 6 and 7 off
01619                 case 7:
01620                         SprPtrAccess(6);
01621                         SprDataAccess(6, 0);
01622                         DisplayIfBadLine;
01623                         if (!(spr_dma_on & 0xc0))
01624                                 the_cpu->BALow = false;
01625                         break;
01626 
01627                 // Read data of sprite 6
01628                 case 8:
01629                         SprDataAccess(6, 1);
01630                         SprDataAccess(6, 2);
01631                         DisplayIfBadLine;
01632                         break;
01633 
01634                 // Fetch sprite pointer 7, reset BA if sprite 7 off
01635                 case 9:
01636                         SprPtrAccess(7);
01637                         SprDataAccess(7, 0);
01638                         DisplayIfBadLine;
01639                         if (!(spr_dma_on & 0x80))
01640                                 the_cpu->BALow = false;
01641                         break;
01642 
01643                 // Read data of sprite 7
01644                 case 10:
01645                         SprDataAccess(7, 1);
01646                         SprDataAccess(7, 2);
01647                         DisplayIfBadLine;
01648                         break;
01649 
01650                 // Refresh, reset BA
01651                 case 11:
01652                         RefreshAccess;
01653                         DisplayIfBadLine;
01654                         the_cpu->BALow = false;
01655                         break;
01656 
01657                 // Refresh, turn on matrix access if Bad Line
01658                 case 12:
01659                         RefreshAccess;
01660                         FetchIfBadLine;
01661                         break;
01662 
01663                 // Refresh, turn on matrix access if Bad Line, reset raster_x, graphics display starts here
01664                 case 13:
01665                         draw_background();
01666                         SampleBorder;
01667                         RefreshAccess;
01668                         FetchIfBadLine;
01669                         raster_x = 0xfffc;
01670                         break;
01671 
01672                 // Refresh, VCBASE->VCCOUNT, turn on matrix access and reset RC if Bad Line
01673                 case 14:
01674                         draw_background();
01675                         SampleBorder;
01676                         RefreshAccess;
01677                         RCIfBadLine;
01678                         vc = vc_base;
01679                         break;
01680 
01681                 // Refresh and matrix access, increment mc_base by 2 if y expansion flipflop is set
01682                 case 15:
01683                         draw_background();
01684                         SampleBorder;
01685                         RefreshAccess;
01686                         FetchIfBadLine;
01687 
01688                         for (i=0; i<8; i++)
01689                                 if (spr_exp_y & (1 << i))
01690                                         mc_base[i] += 2;
01691 
01692                         ml_index = 0;
01693                         matrix_access();
01694                         break;
01695 
01696                 // Graphics and matrix access, increment mc_base by 1 if y expansion flipflop is set
01697                 // and check if sprite DMA can be turned off
01698                 case 16:
01699                         draw_background();
01700                         SampleBorder;
01701                         graphics_access();
01702                         FetchIfBadLine;
01703 
01704                         mask = 1;
01705                         for (i=0; i<8; i++, mask<<=1) {
01706                                 if (spr_exp_y & mask)
01707                                         mc_base[i]++;
01708                                 if ((mc_base[i] & 0x3f) == 0x3f)
01709                                         spr_dma_on &= ~mask;
01710                         }
01711 
01712                         matrix_access();
01713                         break;
01714 
01715                 // Graphics and matrix access, turn off border in 40 column mode, display window starts here
01716                 case 17:
01717                         if (ctrl2 & 8) {
01718                                 if (raster_y == dy_stop)
01719                                         ud_border_on = true;
01720                                 else {
01721                                         if (ctrl1 & 0x10) {
01722                                                 if (raster_y == dy_start)
01723                                                         border_on = ud_border_on = false;
01724                                                 else
01725                                                         if (!ud_border_on)
01726                                                                 border_on = false;
01727                                         } else
01728                                                 if (!ud_border_on)
01729                                                         border_on = false;
01730                                 }
01731                         }
01732 
01733                         // Second sample of border state
01734                         border_on_sample[1] = border_on;
01735 
01736                         draw_background();
01737                         draw_graphics();
01738                         SampleBorder;
01739                         graphics_access();
01740                         FetchIfBadLine;
01741                         matrix_access();
01742                         break;
01743 
01744                 // Turn off border in 38 column mode
01745                 case 18:
01746                         if (!(ctrl2 & 8)) {
01747                                 if (raster_y == dy_stop)
01748                                         ud_border_on = true;
01749                                 else {
01750                                         if (ctrl1 & 0x10) {
01751                                                 if (raster_y == dy_start)
01752                                                         border_on = ud_border_on = false;
01753                                                 else
01754                                                         if (!ud_border_on)
01755                                                                 border_on = false;
01756                                         } else
01757                                                 if (!ud_border_on)
01758                                                         border_on = false;
01759                                 }
01760                         }
01761 
01762                         // Third sample of border state
01763                         border_on_sample[2] = border_on;
01764 
01765                         // Falls through
01766 
01767                 // Graphics and matrix access
01768                 case 19: case 20: case 21: case 22: case 23: case 24:
01769                 case 25: case 26: case 27: case 28: case 29: case 30:
01770                 case 31: case 32: case 33: case 34: case 35: case 36:
01771                 case 37: case 38: case 39: case 40: case 41: case 42:
01772                 case 43: case 44: case 45: case 46: case 47: case 48:
01773                 case 49: case 50: case 51: case 52: case 53: case 54:   // Gnagna...
01774                         draw_graphics();
01775                         SampleBorder;
01776                         graphics_access();
01777                         FetchIfBadLine;
01778                         matrix_access();
01779                         last_char_data = char_data;
01780                         break;
01781 
01782                 // Last graphics access, turn off matrix access, turn on sprite DMA if Y coordinate is
01783                 // right and sprite is enabled, handle sprite y expansion, set BA for sprite 0
01784                 case 55:
01785                         draw_graphics();
01786                         SampleBorder;
01787                         graphics_access();
01788                         DisplayIfBadLine;
01789 
01790                         // Invert y expansion flipflop if bit in MYE is set
01791                         mask = 1;
01792                         for (i=0; i<8; i++, mask<<=1)
01793                                 if (mye & mask)
01794                                         spr_exp_y ^= mask;
01795                         CheckSpriteDMA;
01796 
01797                         if (spr_dma_on & 0x01) {        // Don't remove these braces!
01798                                 SetBALow;
01799                         } else
01800                                 the_cpu->BALow = false;
01801                         break;
01802 
01803                 // Turn on border in 38 column mode, turn on sprite DMA if Y coordinate is right and
01804                 // sprite is enabled, set BA for sprite 0, display window ends here
01805                 case 56:
01806                         if (!(ctrl2 & 8))
01807                                 border_on = true;
01808 
01809                         // Fourth sample of border state
01810                         border_on_sample[3] = border_on;
01811 
01812                         draw_graphics();
01813                         SampleBorder;
01814                         IdleAccess;
01815                         DisplayIfBadLine;
01816                         CheckSpriteDMA;
01817 
01818                         if (spr_dma_on & 0x01)
01819                                 SetBALow;
01820                         break;
01821 
01822                 // Turn on border in 40 column mode, set BA for sprite 1, paint sprites
01823                 case 57:
01824                         if (ctrl2 & 8)
01825                                 border_on = true;
01826 
01827                         // Fifth sample of border state
01828                         border_on_sample[4] = border_on;
01829 
01830                         // Sample spr_disp_on and spr_data for sprite drawing
01831                         if ((spr_draw = spr_disp_on))
01832                                 memcpy(spr_draw_data, spr_data, 8*4);
01833 
01834                         // Turn off sprite display if DMA is off
01835                         mask = 1;
01836                         for (i=0; i<8; i++, mask<<=1)
01837                                 if ((spr_disp_on & mask) && !(spr_dma_on & mask))
01838                                         spr_disp_on &= ~mask;
01839 
01840                         draw_background();
01841                         SampleBorder;
01842                         IdleAccess;
01843                         DisplayIfBadLine;
01844                         if (spr_dma_on & 0x02)
01845                                 SetBALow;
01846                         break;
01847 
01848                 // Fetch sprite pointer 0, mc_base->mc, turn on sprite display if necessary,
01849                 // turn off display if RC=7, read data of sprite 0
01850                 case 58:
01851                         draw_background();
01852                         SampleBorder;
01853 
01854                         mask = 1;
01855                         for (i=0; i<8; i++, mask<<=1) {
01856                                 mc[i] = mc_base[i];
01857                                 if ((spr_dma_on & mask) && (raster_y & 0xff) == my[i])
01858                                         spr_disp_on |= mask;
01859                         }
01860                         SprPtrAccess(0);
01861                         SprDataAccess(0, 0);
01862 
01863                         if (rc == 7) {
01864                                 vc_base = vc;
01865                                 display_state = false;
01866                         }
01867                         if (is_bad_line || display_state) {
01868                                 display_state = true;
01869                                 rc = (rc + 1) & 7;
01870                         }
01871                         break;
01872 
01873                 // Set BA for sprite 2, read data of sprite 0
01874                 case 59:
01875                         draw_background();
01876                         SampleBorder;
01877                         SprDataAccess(0, 1);
01878                         SprDataAccess(0, 2);
01879                         DisplayIfBadLine;
01880                         if (spr_dma_on & 0x04)
01881                                 SetBALow;
01882                         break;
01883 
01884                 // Fetch sprite pointer 1, reset BA if sprite 1 and 2 off, graphics display ends here
01885                 case 60:
01886                         draw_background();
01887                         SampleBorder;
01888 
01889                         if (draw_this_line) {
01890 
01891                                 // Draw sprites
01892                                 if (spr_draw && ThePrefs.SpritesOn)
01893                                         draw_sprites();
01894 
01895                                 // Draw border
01896 #ifdef __POWERPC__
01897                                 if (border_on_sample[0])
01898                                         for (i=0; i<4; i++)
01899                                                 memset8((uint8 *)chunky_tmp+i*8, border_color_sample[i]);
01900                                 if (border_on_sample[1])
01901                                         memset8((uint8 *)chunky_tmp+4*8, border_color_sample[4]);
01902                                 if (border_on_sample[2])
01903                                         for (i=5; i<43; i++)
01904                                                 memset8((uint8 *)chunky_tmp+i*8, border_color_sample[i]);
01905                                 if (border_on_sample[3])
01906                                         memset8((uint8 *)chunky_tmp+43*8, border_color_sample[43]);
01907                                 if (border_on_sample[4])
01908                                         for (i=44; i<DISPLAY_X/8; i++)
01909                                                 memset8((uint8 *)chunky_tmp+i*8, border_color_sample[i]);
01910 #else
01911                                 if (border_on_sample[0])
01912                                         for (i=0; i<4; i++)
01913                                                 memset8(chunky_line_start+i*8, border_color_sample[i]);
01914                                 if (border_on_sample[1])
01915                                         memset8(chunky_line_start+4*8, border_color_sample[4]);
01916                                 if (border_on_sample[2])
01917                                         for (i=5; i<43; i++)
01918                                                 memset8(chunky_line_start+i*8, border_color_sample[i]);
01919                                 if (border_on_sample[3])
01920                                         memset8(chunky_line_start+43*8, border_color_sample[43]);
01921                                 if (border_on_sample[4])
01922                                         for (i=44; i<DISPLAY_X/8; i++)
01923                                                 memset8(chunky_line_start+i*8, border_color_sample[i]);
01924 #endif
01925 
01926 #ifdef __POWERPC__
01927                                 // Copy temporary buffer to bitmap
01928                                 fastcopy(chunky_line_start, (uint8 *)chunky_tmp);
01929 #endif
01930 
01931                                 // Increment pointer in chunky buffer
01932                                 chunky_line_start += xmod;
01933                         }
01934 
01935                         SprPtrAccess(1);
01936                         SprDataAccess(1, 0);
01937                         DisplayIfBadLine;
01938                         if (!(spr_dma_on & 0x06))
01939                                 the_cpu->BALow = false;
01940                         break;
01941 
01942                 // Set BA for sprite 3, read data of sprite 1
01943                 case 61:
01944                         SprDataAccess(1, 1);
01945                         SprDataAccess(1, 2);
01946                         DisplayIfBadLine;
01947                         if (spr_dma_on & 0x08)
01948                                 SetBALow;
01949                         break;
01950 
01951                 // Read sprite pointer 2, reset BA if sprite 2 and 3 off, read data of sprite 2
01952                 case 62:
01953                         SprPtrAccess(2);
01954                         SprDataAccess(2, 0);
01955                         DisplayIfBadLine;
01956                         if (!(spr_dma_on & 0x0c))
01957                                 the_cpu->BALow = false;
01958                         break;
01959 
01960                 // Set BA for sprite 4, read data of sprite 2
01961                 case 63:
01962                         SprDataAccess(2, 1);
01963                         SprDataAccess(2, 2);
01964                         DisplayIfBadLine;
01965 
01966                         if (raster_y == dy_stop)
01967                                 ud_border_on = true;
01968                         else
01969                                 if (ctrl1 & 0x10 && raster_y == dy_start)
01970                                         ud_border_on = false;
01971 
01972                         if (spr_dma_on & 0x10)
01973                                 SetBALow;
01974 
01975                         // Last cycle
01976                         raster_x += 8;
01977                         cycle = 1;
01978                         return true;
01979         }
01980 
01981         // Next cycle
01982         raster_x += 8;
01983         cycle++;
01984         return false;
01985 }

Generated on Tue Feb 8 04:08:16 2005 for E32frodo by doxygen 1.3.3