ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/VIC_SC.cpp
Revision: 1.6
Committed: 2010-04-21T19:53:28Z (12 years, 9 months ago) by cebix
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +6 -4 lines
Log Message:
added missing initializations

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * VIC_SC.cpp - 6569R5 emulation (cycle based)
3     *
4 cebix 1.6 * Frodo Copyright (C) Christian Bauer
5 cebix 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     /*
22     * Incompatibilities:
23     * ------------------
24     *
25     * - Color of $ff bytes read when BA is low and AEC is high
26     * is not correct
27     * - Changes to border/background color are visible 7 pixels
28     * too late
29     * - Sprite data access doesn't respect BA
30     * - Sprite collisions are only detected within the visible
31     * screen area (excluding borders)
32     * - Sprites are only drawn if they completely fit within the
33     * left/right limits of the chunky bitmap
34     */
35    
36     #include "sysdeps.h"
37    
38     #include "VIC.h"
39     #include "C64.h"
40     #include "CPUC64.h"
41     #include "Display.h"
42     #include "Prefs.h"
43    
44    
45     // First and last displayed line
46     const int FIRST_DISP_LINE = 0x10;
47     const int LAST_DISP_LINE = 0x11f;
48    
49     // First and last possible line for Bad Lines
50     const int FIRST_DMA_LINE = 0x30;
51     const int LAST_DMA_LINE = 0xf7;
52    
53     // Display window coordinates
54     const int ROW25_YSTART = 0x33;
55     const int ROW25_YSTOP = 0xfb;
56     const int ROW24_YSTART = 0x37;
57     const int ROW24_YSTOP = 0xf7;
58    
59     #if defined(SMALL_DISPLAY)
60     /* This does not work yet, the sprite code doesn't know about it. */
61     const int COL40_XSTART = 0x14;
62     const int COL40_XSTOP = 0x154;
63     const int COL38_XSTART = 0x1B;
64     const int COL38_XSTOP = 0x14B;
65     #else
66     const int COL40_XSTART = 0x20;
67     const int COL40_XSTOP = 0x160;
68     const int COL38_XSTART = 0x27;
69     const int COL38_XSTOP = 0x157;
70     #endif
71    
72    
73     // Tables for sprite X expansion
74     uint16 ExpTable[256] = {
75     0x0000, 0x0003, 0x000C, 0x000F, 0x0030, 0x0033, 0x003C, 0x003F,
76     0x00C0, 0x00C3, 0x00CC, 0x00CF, 0x00F0, 0x00F3, 0x00FC, 0x00FF,
77     0x0300, 0x0303, 0x030C, 0x030F, 0x0330, 0x0333, 0x033C, 0x033F,
78     0x03C0, 0x03C3, 0x03CC, 0x03CF, 0x03F0, 0x03F3, 0x03FC, 0x03FF,
79     0x0C00, 0x0C03, 0x0C0C, 0x0C0F, 0x0C30, 0x0C33, 0x0C3C, 0x0C3F,
80     0x0CC0, 0x0CC3, 0x0CCC, 0x0CCF, 0x0CF0, 0x0CF3, 0x0CFC, 0x0CFF,
81     0x0F00, 0x0F03, 0x0F0C, 0x0F0F, 0x0F30, 0x0F33, 0x0F3C, 0x0F3F,
82     0x0FC0, 0x0FC3, 0x0FCC, 0x0FCF, 0x0FF0, 0x0FF3, 0x0FFC, 0x0FFF,
83     0x3000, 0x3003, 0x300C, 0x300F, 0x3030, 0x3033, 0x303C, 0x303F,
84     0x30C0, 0x30C3, 0x30CC, 0x30CF, 0x30F0, 0x30F3, 0x30FC, 0x30FF,
85     0x3300, 0x3303, 0x330C, 0x330F, 0x3330, 0x3333, 0x333C, 0x333F,
86     0x33C0, 0x33C3, 0x33CC, 0x33CF, 0x33F0, 0x33F3, 0x33FC, 0x33FF,
87     0x3C00, 0x3C03, 0x3C0C, 0x3C0F, 0x3C30, 0x3C33, 0x3C3C, 0x3C3F,
88     0x3CC0, 0x3CC3, 0x3CCC, 0x3CCF, 0x3CF0, 0x3CF3, 0x3CFC, 0x3CFF,
89     0x3F00, 0x3F03, 0x3F0C, 0x3F0F, 0x3F30, 0x3F33, 0x3F3C, 0x3F3F,
90     0x3FC0, 0x3FC3, 0x3FCC, 0x3FCF, 0x3FF0, 0x3FF3, 0x3FFC, 0x3FFF,
91     0xC000, 0xC003, 0xC00C, 0xC00F, 0xC030, 0xC033, 0xC03C, 0xC03F,
92     0xC0C0, 0xC0C3, 0xC0CC, 0xC0CF, 0xC0F0, 0xC0F3, 0xC0FC, 0xC0FF,
93     0xC300, 0xC303, 0xC30C, 0xC30F, 0xC330, 0xC333, 0xC33C, 0xC33F,
94     0xC3C0, 0xC3C3, 0xC3CC, 0xC3CF, 0xC3F0, 0xC3F3, 0xC3FC, 0xC3FF,
95     0xCC00, 0xCC03, 0xCC0C, 0xCC0F, 0xCC30, 0xCC33, 0xCC3C, 0xCC3F,
96     0xCCC0, 0xCCC3, 0xCCCC, 0xCCCF, 0xCCF0, 0xCCF3, 0xCCFC, 0xCCFF,
97     0xCF00, 0xCF03, 0xCF0C, 0xCF0F, 0xCF30, 0xCF33, 0xCF3C, 0xCF3F,
98     0xCFC0, 0xCFC3, 0xCFCC, 0xCFCF, 0xCFF0, 0xCFF3, 0xCFFC, 0xCFFF,
99     0xF000, 0xF003, 0xF00C, 0xF00F, 0xF030, 0xF033, 0xF03C, 0xF03F,
100     0xF0C0, 0xF0C3, 0xF0CC, 0xF0CF, 0xF0F0, 0xF0F3, 0xF0FC, 0xF0FF,
101     0xF300, 0xF303, 0xF30C, 0xF30F, 0xF330, 0xF333, 0xF33C, 0xF33F,
102     0xF3C0, 0xF3C3, 0xF3CC, 0xF3CF, 0xF3F0, 0xF3F3, 0xF3FC, 0xF3FF,
103     0xFC00, 0xFC03, 0xFC0C, 0xFC0F, 0xFC30, 0xFC33, 0xFC3C, 0xFC3F,
104     0xFCC0, 0xFCC3, 0xFCCC, 0xFCCF, 0xFCF0, 0xFCF3, 0xFCFC, 0xFCFF,
105     0xFF00, 0xFF03, 0xFF0C, 0xFF0F, 0xFF30, 0xFF33, 0xFF3C, 0xFF3F,
106     0xFFC0, 0xFFC3, 0xFFCC, 0xFFCF, 0xFFF0, 0xFFF3, 0xFFFC, 0xFFFF
107     };
108    
109     uint16 MultiExpTable[256] = {
110     0x0000, 0x0005, 0x000A, 0x000F, 0x0050, 0x0055, 0x005A, 0x005F,
111     0x00A0, 0x00A5, 0x00AA, 0x00AF, 0x00F0, 0x00F5, 0x00FA, 0x00FF,
112     0x0500, 0x0505, 0x050A, 0x050F, 0x0550, 0x0555, 0x055A, 0x055F,
113     0x05A0, 0x05A5, 0x05AA, 0x05AF, 0x05F0, 0x05F5, 0x05FA, 0x05FF,
114     0x0A00, 0x0A05, 0x0A0A, 0x0A0F, 0x0A50, 0x0A55, 0x0A5A, 0x0A5F,
115     0x0AA0, 0x0AA5, 0x0AAA, 0x0AAF, 0x0AF0, 0x0AF5, 0x0AFA, 0x0AFF,
116     0x0F00, 0x0F05, 0x0F0A, 0x0F0F, 0x0F50, 0x0F55, 0x0F5A, 0x0F5F,
117     0x0FA0, 0x0FA5, 0x0FAA, 0x0FAF, 0x0FF0, 0x0FF5, 0x0FFA, 0x0FFF,
118     0x5000, 0x5005, 0x500A, 0x500F, 0x5050, 0x5055, 0x505A, 0x505F,
119     0x50A0, 0x50A5, 0x50AA, 0x50AF, 0x50F0, 0x50F5, 0x50FA, 0x50FF,
120     0x5500, 0x5505, 0x550A, 0x550F, 0x5550, 0x5555, 0x555A, 0x555F,
121     0x55A0, 0x55A5, 0x55AA, 0x55AF, 0x55F0, 0x55F5, 0x55FA, 0x55FF,
122     0x5A00, 0x5A05, 0x5A0A, 0x5A0F, 0x5A50, 0x5A55, 0x5A5A, 0x5A5F,
123     0x5AA0, 0x5AA5, 0x5AAA, 0x5AAF, 0x5AF0, 0x5AF5, 0x5AFA, 0x5AFF,
124     0x5F00, 0x5F05, 0x5F0A, 0x5F0F, 0x5F50, 0x5F55, 0x5F5A, 0x5F5F,
125     0x5FA0, 0x5FA5, 0x5FAA, 0x5FAF, 0x5FF0, 0x5FF5, 0x5FFA, 0x5FFF,
126     0xA000, 0xA005, 0xA00A, 0xA00F, 0xA050, 0xA055, 0xA05A, 0xA05F,
127     0xA0A0, 0xA0A5, 0xA0AA, 0xA0AF, 0xA0F0, 0xA0F5, 0xA0FA, 0xA0FF,
128     0xA500, 0xA505, 0xA50A, 0xA50F, 0xA550, 0xA555, 0xA55A, 0xA55F,
129     0xA5A0, 0xA5A5, 0xA5AA, 0xA5AF, 0xA5F0, 0xA5F5, 0xA5FA, 0xA5FF,
130     0xAA00, 0xAA05, 0xAA0A, 0xAA0F, 0xAA50, 0xAA55, 0xAA5A, 0xAA5F,
131     0xAAA0, 0xAAA5, 0xAAAA, 0xAAAF, 0xAAF0, 0xAAF5, 0xAAFA, 0xAAFF,
132     0xAF00, 0xAF05, 0xAF0A, 0xAF0F, 0xAF50, 0xAF55, 0xAF5A, 0xAF5F,
133     0xAFA0, 0xAFA5, 0xAFAA, 0xAFAF, 0xAFF0, 0xAFF5, 0xAFFA, 0xAFFF,
134     0xF000, 0xF005, 0xF00A, 0xF00F, 0xF050, 0xF055, 0xF05A, 0xF05F,
135     0xF0A0, 0xF0A5, 0xF0AA, 0xF0AF, 0xF0F0, 0xF0F5, 0xF0FA, 0xF0FF,
136     0xF500, 0xF505, 0xF50A, 0xF50F, 0xF550, 0xF555, 0xF55A, 0xF55F,
137     0xF5A0, 0xF5A5, 0xF5AA, 0xF5AF, 0xF5F0, 0xF5F5, 0xF5FA, 0xF5FF,
138     0xFA00, 0xFA05, 0xFA0A, 0xFA0F, 0xFA50, 0xFA55, 0xFA5A, 0xFA5F,
139     0xFAA0, 0xFAA5, 0xFAAA, 0xFAAF, 0xFAF0, 0xFAF5, 0xFAFA, 0xFAFF,
140     0xFF00, 0xFF05, 0xFF0A, 0xFF0F, 0xFF50, 0xFF55, 0xFF5A, 0xFF5F,
141     0xFFA0, 0xFFA5, 0xFFAA, 0xFFAF, 0xFFF0, 0xFFF5, 0xFFFA, 0xFFFF
142     };
143    
144     #ifdef GLOBAL_VARS
145     static uint16 mx[8]; // VIC registers
146     static uint8 my[8];
147     static uint8 mx8;
148     static uint8 ctrl1, ctrl2;
149     static uint8 lpx, lpy;
150     static uint8 me, mxe, mye, mdp, mmc;
151     static uint8 vbase;
152     static uint8 irq_flag, irq_mask;
153     static uint8 clx_spr, clx_bgr;
154     static uint8 ec, b0c, b1c, b2c, b3c, mm0, mm1;
155     static uint8 sc[8];
156    
157     static uint8 *ram, *char_rom, *color_ram; // Pointers to RAM and ROM
158     static C64 *the_c64; // Pointer to C64
159     static C64Display *the_display; // Pointer to C64Display
160     static MOS6510 *the_cpu; // Pointer to 6510
161     static MOS6569 *the_vic; // Pointer to self
162    
163     static uint8 colors[256]; // Indices of the 16 C64 colors (16 times mirrored to avoid "& 0x0f")
164    
165     static uint8 ec_color, b0c_color, b1c_color, b2c_color, b3c_color; // Indices for exterior/background colors
166     static uint8 mm0_color, mm1_color; // Indices for MOB multicolors
167     static uint8 spr_color[8]; // Indices for MOB colors
168    
169     static uint8 matrix_line[40]; // Buffer for video line, read in Bad Lines
170     static uint8 color_line[40]; // Buffer for color line, read in Bad Lines
171    
172     #ifdef __POWERPC__
173     static double chunky_tmp[DISPLAY_X/8]; // Temporary line buffer for GameKit speedup
174     #endif
175     static uint8 *chunky_ptr; // Pointer in chunky bitmap buffer
176     static uint8 *chunky_line_start; // Pointer to start of current line in bitmap buffer
177     static uint8 *fore_mask_ptr; // Pointer in fore_mask_buf
178     static int xmod; // Number of bytes per row
179    
180     static uint16 raster_x; // Current raster x position
181     static uint16 raster_y; // Current raster line
182     static uint16 irq_raster; // Interrupt raster line
183     static uint16 dy_start; // Comparison values for border logic
184     static uint16 dy_stop;
185     static uint16 rc; // Row counter
186     static uint16 vc; // Video counter
187     static uint16 vc_base; // Video counter base
188     static uint16 x_scroll; // X scroll value
189     static uint16 y_scroll; // Y scroll value
190     static uint16 cia_vabase; // CIA VA14/15 video base
191    
192     static int cycle; // Current cycle in line (1..63)
193    
194     static int display_idx; // Index of current display mode
195     static int ml_index; // Index in matrix/color_line[]
196     static int skip_counter; // Counter for frame-skipping
197    
198     static uint16 mc[8]; // Sprite data counters
199     static uint16 mc_base[8]; // Sprite data counter bases
200    
201     static uint8 spr_coll_buf[0x180]; // Buffer for sprite-sprite collisions and priorities
202     static uint8 fore_mask_buf[0x180/8]; // Foreground mask for sprite-graphics collisions and priorities
203    
204     static bool display_state; // true: Display state, false: Idle state
205     static bool border_on; // Flag: Upper/lower border on
206     static bool frame_skipped; // Flag: Frame is being skipped
207     static bool bad_lines_enabled; // Flag: Bad Lines enabled for this frame
208     static bool lp_triggered; // Flag: Lightpen was triggered in this frame
209     static bool is_bad_line; // Flag: Current line is Bad Line
210     static bool draw_this_line; // Flag: This line is drawn on the screen
211     static bool ud_border_on; // Flag: Upper/lower border on
212     static bool vblanking; // Flag: VBlank in next cycle
213    
214     static bool border_on_sample[5]; // Samples of border state at different cycles (1, 17, 18, 56, 57)
215     static uint8 border_color_sample[DISPLAY_X/8]; // Samples of border color at each "displayed" cycle
216    
217     static uint16 matrix_base; // Video matrix base
218     static uint16 char_base; // Character generator base
219     static uint16 bitmap_base; // Bitmap base
220    
221     static uint8 ref_cnt; // Refresh counter
222     static uint8 spr_exp_y; // 8 sprite y expansion flipflops
223     static uint8 spr_dma_on; // 8 flags: Sprite DMA active
224     static uint8 spr_disp_on; // 8 flags: Sprite display active
225     static uint8 spr_draw; // 8 flags: Draw sprite in this line
226     static uint16 spr_ptr[8]; // Sprite data pointers
227    
228     static uint8 gfx_data, char_data, color_data, last_char_data;
229     static uint8 spr_data[8][4]; // Sprite data read
230     static uint8 spr_draw_data[8][4]; // Sprite data for drawing
231    
232     static uint32 first_ba_cycle; // Cycle when BA first went low
233     #endif
234    
235    
236     /*
237     * Constructor: Initialize variables
238     */
239    
240     MOS6569::MOS6569(C64 *c64, C64Display *disp, MOS6510 *CPU, uint8 *RAM, uint8 *Char, uint8 *Color)
241     #ifndef GLOBAL_VARS
242     : ram(RAM), char_rom(Char), color_ram(Color), the_c64(c64), the_display(disp), the_cpu(CPU)
243     #endif
244     {
245     int i;
246    
247     // Set pointers
248     #ifdef GLOBAL_VARS
249     the_vic = this;
250     the_c64 = c64;
251     the_display = disp;
252     the_cpu = CPU;
253     ram = RAM;
254     char_rom = Char;
255     color_ram = Color;
256     #endif
257     matrix_base = 0;
258     char_base = 0;
259     bitmap_base = 0;
260    
261     // Get bitmap info
262     chunky_ptr = chunky_line_start = disp->BitmapBase();
263     xmod = disp->BitmapXMod();
264    
265     // Initialize VIC registers
266     mx8 = 0;
267     ctrl1 = ctrl2 = 0;
268     lpx = lpy = 0;
269     me = mxe = mye = mdp = mmc = 0;
270     vbase = irq_flag = irq_mask = 0;
271     clx_spr = clx_bgr = 0;
272     cia_vabase = 0;
273     ec = b0c = b1c = b2c = b3c = mm0 = mm1 = 0;
274     for (i=0; i<8; i++) mx[i] = my[i] = sc[i] = 0;
275    
276     // Initialize other variables
277     raster_y = TOTAL_RASTERS - 1;
278     rc = 7;
279     irq_raster = vc = vc_base = x_scroll = y_scroll = 0;
280     dy_start = ROW24_YSTART;
281     dy_stop = ROW24_YSTOP;
282     ml_index = 0;
283    
284     cycle = 1;
285     display_idx = 0;
286     display_state = false;
287     border_on = ud_border_on = vblanking = false;
288     lp_triggered = draw_this_line = false;
289 cebix 1.6 is_bad_line = false;
290 cebix 1.1
291 cebix 1.6 spr_exp_y = spr_dma_on = spr_disp_on = 0;
292 cebix 1.1 for (i=0; i<8; i++) {
293     mc[i] = 63;
294 cebix 1.6 mc_base[i] = 0;
295 cebix 1.1 spr_ptr[i] = 0;
296     }
297    
298     frame_skipped = false;
299     skip_counter = 1;
300    
301     memset(spr_coll_buf, 0, 0x180);
302     memset(fore_mask_buf, 0, 0x180/8);
303    
304     // Preset colors to black
305     disp->InitColors(colors);
306     ec_color = b0c_color = b1c_color = b2c_color = b3c_color = mm0_color = mm1_color = colors[0];
307     for (i=0; i<8; i++) spr_color[i] = colors[0];
308     }
309    
310    
311     /*
312     * Reinitialize the colors table for when the palette has changed
313     */
314    
315     void MOS6569::ReInitColors(void)
316     {
317     int i;
318    
319     // Build inverse color table.
320     uint8 xlate_colors[256];
321     memset(xlate_colors, 0, sizeof(xlate_colors));
322 cebix 1.3 for (i=0; i<16; i++)
323 cebix 1.1 xlate_colors[colors[i]] = i;
324    
325     // Get the new colors.
326     the_display->InitColors(colors);
327    
328     // Build color translation table.
329 cebix 1.3 for (i=0; i<256; i++)
330 cebix 1.1 xlate_colors[i] = colors[xlate_colors[i]];
331    
332     // Translate all the old colors variables.
333     ec_color = colors[ec];
334     b0c_color = colors[b0c];
335     b1c_color = colors[b1c];
336     b2c_color = colors[b2c];
337     b3c_color = colors[b3c];
338     mm0_color = colors[mm0];
339     mm1_color = colors[mm1];
340 cebix 1.3 for (i=0; i<8; i++)
341 cebix 1.1 spr_color[i] = colors[sc[i]];
342    
343     // Translate the border color sample buffer.
344     for (unsigned x = 0; x < sizeof(border_color_sample); x++)
345     border_color_sample[x] = xlate_colors[border_color_sample[x]];
346    
347     // Translate the chunky buffer.
348     uint8 *scanline = the_display->BitmapBase();
349 cebix 1.3 for (int y=0; y<DISPLAY_Y; y++) {
350     for (int x=0; x<DISPLAY_X; x++)
351 cebix 1.1 scanline[x] = xlate_colors[scanline[x]];
352     scanline += xmod;
353     }
354     }
355    
356    
357     /*
358     * Get VIC state
359     */
360    
361     void MOS6569::GetState(MOS6569State *vd)
362     {
363     int i;
364    
365     vd->m0x = mx[0] & 0xff; vd->m0y = my[0];
366     vd->m1x = mx[1] & 0xff; vd->m1y = my[1];
367     vd->m2x = mx[2] & 0xff; vd->m2y = my[2];
368     vd->m3x = mx[3] & 0xff; vd->m3y = my[3];
369     vd->m4x = mx[4] & 0xff; vd->m4y = my[4];
370     vd->m5x = mx[5] & 0xff; vd->m5y = my[5];
371     vd->m6x = mx[6] & 0xff; vd->m6y = my[6];
372     vd->m7x = mx[7] & 0xff; vd->m7y = my[7];
373     vd->mx8 = mx8;
374    
375     vd->ctrl1 = (ctrl1 & 0x7f) | ((raster_y & 0x100) >> 1);
376     vd->raster = raster_y & 0xff;
377     vd->lpx = lpx; vd->lpy = lpy;
378     vd->ctrl2 = ctrl2;
379     vd->vbase = vbase;
380     vd->irq_flag = irq_flag;
381     vd->irq_mask = irq_mask;
382    
383     vd->me = me; vd->mxe = mxe; vd->mye = mye; vd->mdp = mdp; vd->mmc = mmc;
384     vd->mm = clx_spr; vd->md = clx_bgr;
385    
386     vd->ec = ec;
387     vd->b0c = b0c; vd->b1c = b1c; vd->b2c = b2c; vd->b3c = b3c;
388     vd->mm0 = mm0; vd->mm1 = mm1;
389     vd->m0c = sc[0];
390     vd->m1c = sc[1];
391     vd->m2c = sc[2];
392     vd->m3c = sc[3];
393     vd->m4c = sc[4];
394     vd->m5c = sc[5];
395     vd->m6c = sc[6];
396     vd->m7c = sc[7];
397    
398     vd->pad0 = 0;
399     vd->irq_raster = irq_raster;
400     vd->vc = vc;
401     vd->vc_base = vc_base;
402     vd->rc = rc;
403     vd->spr_dma = spr_dma_on;
404     vd->spr_disp = spr_disp_on;
405     for (i=0; i<8; i++) {
406     vd->mc[i] = mc[i];
407     vd->mc_base[i] = mc_base[i];
408     }
409     vd->display_state = display_state;
410     vd->bad_line = raster_y >= FIRST_DMA_LINE && raster_y <= LAST_DMA_LINE && ((raster_y & 7) == y_scroll) && bad_lines_enabled;
411     vd->bad_line_enable = bad_lines_enabled;
412     vd->lp_triggered = lp_triggered;
413     vd->border_on = border_on;
414    
415     vd->bank_base = cia_vabase;
416     vd->matrix_base = ((vbase & 0xf0) << 6) | cia_vabase;
417     vd->char_base = ((vbase & 0x0e) << 10) | cia_vabase;
418     vd->bitmap_base = ((vbase & 0x08) << 10) | cia_vabase;
419     for (i=0; i<8; i++)
420     vd->sprite_base[i] = spr_ptr[i] | cia_vabase;
421    
422     vd->cycle = cycle;
423     vd->raster_x = raster_x;
424     vd->ml_index = ml_index;
425     vd->ref_cnt = ref_cnt;
426     vd->last_vic_byte = LastVICByte;
427     vd->ud_border_on = ud_border_on;
428     }
429    
430    
431     /*
432     * Set VIC state (only works if in VBlank)
433     */
434    
435     void MOS6569::SetState(MOS6569State *vd)
436     {
437     int i, j;
438    
439     mx[0] = vd->m0x; my[0] = vd->m0y;
440     mx[1] = vd->m1x; my[1] = vd->m1y;
441     mx[2] = vd->m2x; my[2] = vd->m2y;
442     mx[3] = vd->m3x; my[3] = vd->m3y;
443     mx[4] = vd->m4x; my[4] = vd->m4y;
444     mx[5] = vd->m5x; my[5] = vd->m5y;
445     mx[6] = vd->m6x; my[6] = vd->m6y;
446     mx[7] = vd->m7x; my[7] = vd->m7y;
447     mx8 = vd->mx8;
448     for (i=0, j=1; i<8; i++, j<<=1) {
449     if (mx8 & j)
450     mx[i] |= 0x100;
451     else
452     mx[i] &= 0xff;
453     }
454    
455     ctrl1 = vd->ctrl1;
456     ctrl2 = vd->ctrl2;
457     x_scroll = ctrl2 & 7;
458     y_scroll = ctrl1 & 7;
459     if (ctrl1 & 8) {
460     dy_start = ROW25_YSTART;
461     dy_stop = ROW25_YSTOP;
462     } else {
463     dy_start = ROW24_YSTART;
464     dy_stop = ROW24_YSTOP;
465     }
466     display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4;
467    
468     raster_y = 0;
469     lpx = vd->lpx; lpy = vd->lpy;
470    
471     vbase = vd->vbase;
472     cia_vabase = vd->bank_base;
473     matrix_base = (vbase & 0xf0) << 6;
474     char_base = (vbase & 0x0e) << 10;
475     bitmap_base = (vbase & 0x08) << 10;
476    
477     irq_flag = vd->irq_flag;
478     irq_mask = vd->irq_mask;
479    
480     me = vd->me; mxe = vd->mxe; mye = vd->mye; mdp = vd->mdp; mmc = vd->mmc;
481     clx_spr = vd->mm; clx_bgr = vd->md;
482    
483     ec = vd->ec;
484     ec_color = colors[ec];
485    
486     b0c = vd->b0c; b1c = vd->b1c; b2c = vd->b2c; b3c = vd->b3c;
487     b0c_color = colors[b0c];
488     b1c_color = colors[b1c];
489     b2c_color = colors[b2c];
490     b3c_color = colors[b3c];
491    
492     mm0 = vd->mm0; mm1 = vd->mm1;
493     mm0_color = colors[mm0];
494     mm1_color = colors[mm1];
495    
496     sc[0] = vd->m0c; sc[1] = vd->m1c;
497     sc[2] = vd->m2c; sc[3] = vd->m3c;
498     sc[4] = vd->m4c; sc[5] = vd->m5c;
499     sc[6] = vd->m6c; sc[7] = vd->m7c;
500     for (i=0; i<8; i++)
501     spr_color[i] = colors[sc[i]];
502    
503     irq_raster = vd->irq_raster;
504     vc = vd->vc;
505     vc_base = vd->vc_base;
506     rc = vd->rc;
507     spr_dma_on = vd->spr_dma;
508     spr_disp_on = vd->spr_disp;
509     for (i=0; i<8; i++) {
510     mc[i] = vd->mc[i];
511     mc_base[i] = vd->mc_base[i];
512     spr_ptr[i] = vd->sprite_base[i] & 0x3fff;
513     }
514     display_state = vd->display_state;
515     bad_lines_enabled = vd->bad_line_enable;
516     lp_triggered = vd->lp_triggered;
517     border_on = vd->border_on;
518    
519     cycle = vd->cycle;
520     raster_x = vd->raster_x;
521     ml_index = vd->ml_index;
522     ref_cnt = vd->ref_cnt;
523     LastVICByte = vd->last_vic_byte;
524     ud_border_on = vd->ud_border_on;
525     }
526    
527    
528     /*
529     * Trigger raster IRQ
530     */
531    
532     #ifdef GLOBAL_VARS
533     static inline void raster_irq(void)
534     #else
535     inline void MOS6569::raster_irq(void)
536     #endif
537     {
538     irq_flag |= 0x01;
539     if (irq_mask & 0x01) {
540     irq_flag |= 0x80;
541     the_cpu->TriggerVICIRQ();
542     }
543     }
544    
545    
546     /*
547     * Read from VIC register
548     */
549    
550     uint8 MOS6569::ReadRegister(uint16 adr)
551     {
552     switch (adr) {
553     case 0x00: case 0x02: case 0x04: case 0x06:
554     case 0x08: case 0x0a: case 0x0c: case 0x0e:
555     return mx[adr >> 1];
556    
557     case 0x01: case 0x03: case 0x05: case 0x07:
558     case 0x09: case 0x0b: case 0x0d: case 0x0f:
559     return my[adr >> 1];
560    
561     case 0x10: // Sprite X position MSB
562     return mx8;
563    
564     case 0x11: // Control register 1
565     return (ctrl1 & 0x7f) | ((raster_y & 0x100) >> 1);
566    
567     case 0x12: // Raster counter
568     return raster_y;
569    
570     case 0x13: // Light pen X
571     return lpx;
572    
573     case 0x14: // Light pen Y
574     return lpy;
575    
576     case 0x15: // Sprite enable
577     return me;
578    
579     case 0x16: // Control register 2
580     return ctrl2 | 0xc0;
581    
582     case 0x17: // Sprite Y expansion
583     return mye;
584    
585     case 0x18: // Memory pointers
586     return vbase | 0x01;
587    
588     case 0x19: // IRQ flags
589     return irq_flag | 0x70;
590    
591     case 0x1a: // IRQ mask
592     return irq_mask | 0xf0;
593    
594     case 0x1b: // Sprite data priority
595     return mdp;
596    
597     case 0x1c: // Sprite multicolor
598     return mmc;
599    
600     case 0x1d: // Sprite X expansion
601     return mxe;
602    
603     case 0x1e:{ // Sprite-sprite collision
604     uint8 ret = clx_spr;
605     clx_spr = 0; // Read and clear
606     return ret;
607     }
608    
609     case 0x1f:{ // Sprite-background collision
610     uint8 ret = clx_bgr;
611     clx_bgr = 0; // Read and clear
612     return ret;
613     }
614    
615     case 0x20: return ec | 0xf0;
616     case 0x21: return b0c | 0xf0;
617     case 0x22: return b1c | 0xf0;
618     case 0x23: return b2c | 0xf0;
619     case 0x24: return b3c | 0xf0;
620     case 0x25: return mm0 | 0xf0;
621     case 0x26: return mm1 | 0xf0;
622    
623     case 0x27: case 0x28: case 0x29: case 0x2a:
624     case 0x2b: case 0x2c: case 0x2d: case 0x2e:
625     return sc[adr - 0x27] | 0xf0;
626    
627     default:
628     return 0xff;
629     }
630     }
631    
632    
633     /*
634     * Write to VIC register
635     */
636    
637     void MOS6569::WriteRegister(uint16 adr, uint8 byte)
638     {
639     switch (adr) {
640     case 0x00: case 0x02: case 0x04: case 0x06:
641     case 0x08: case 0x0a: case 0x0c: case 0x0e:
642     mx[adr >> 1] = (mx[adr >> 1] & 0xff00) | byte;
643     break;
644    
645     case 0x10:{
646     int i, j;
647     mx8 = byte;
648     for (i=0, j=1; i<8; i++, j<<=1) {
649     if (mx8 & j)
650     mx[i] |= 0x100;
651     else
652     mx[i] &= 0xff;
653     }
654     break;
655     }
656    
657     case 0x01: case 0x03: case 0x05: case 0x07:
658     case 0x09: case 0x0b: case 0x0d: case 0x0f:
659     my[adr >> 1] = byte;
660     break;
661    
662     case 0x11:{ // Control register 1
663     ctrl1 = byte;
664     y_scroll = byte & 7;
665    
666     uint16 new_irq_raster = (irq_raster & 0xff) | ((byte & 0x80) << 1);
667     if (irq_raster != new_irq_raster && raster_y == new_irq_raster)
668     raster_irq();
669     irq_raster = new_irq_raster;
670    
671     if (byte & 8) {
672     dy_start = ROW25_YSTART;
673     dy_stop = ROW25_YSTOP;
674     } else {
675     dy_start = ROW24_YSTART;
676     dy_stop = ROW24_YSTOP;
677     }
678    
679     // In line $30, the DEN bit controls if Bad Lines can occur
680     if (raster_y == 0x30 && byte & 0x10)
681     bad_lines_enabled = true;
682    
683     // Bad Line condition?
684     is_bad_line = (raster_y >= FIRST_DMA_LINE && raster_y <= LAST_DMA_LINE && ((raster_y & 7) == y_scroll) && bad_lines_enabled);
685    
686     display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4;
687     break;
688     }
689    
690     case 0x12:{ // Raster counter
691     uint16 new_irq_raster = (irq_raster & 0xff00) | byte;
692     if (irq_raster != new_irq_raster && raster_y == new_irq_raster)
693     raster_irq();
694     irq_raster = new_irq_raster;
695     break;
696     }
697    
698     case 0x15: // Sprite enable
699     me = byte;
700     break;
701    
702     case 0x16: // Control register 2
703     ctrl2 = byte;
704     x_scroll = byte & 7;
705     display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4;
706     break;
707    
708     case 0x17: // Sprite Y expansion
709     mye = byte;
710     spr_exp_y |= ~byte;
711     break;
712    
713     case 0x18: // Memory pointers
714     vbase = byte;
715     matrix_base = (byte & 0xf0) << 6;
716     char_base = (byte & 0x0e) << 10;
717     bitmap_base = (byte & 0x08) << 10;
718     break;
719    
720     case 0x19: // IRQ flags
721     irq_flag = irq_flag & (~byte & 0x0f);
722     if (irq_flag & irq_mask) // Set master bit if allowed interrupt still pending
723     irq_flag |= 0x80;
724     else
725     the_cpu->ClearVICIRQ(); // Else clear interrupt
726     break;
727    
728     case 0x1a: // IRQ mask
729     irq_mask = byte & 0x0f;
730     if (irq_flag & irq_mask) { // Trigger interrupt if pending and now allowed
731     irq_flag |= 0x80;
732     the_cpu->TriggerVICIRQ();
733     } else {
734     irq_flag &= 0x7f;
735     the_cpu->ClearVICIRQ();
736     }
737     break;
738    
739     case 0x1b: // Sprite data priority
740     mdp = byte;
741     break;
742    
743     case 0x1c: // Sprite multicolor
744     mmc = byte;
745     break;
746    
747     case 0x1d: // Sprite X expansion
748     mxe = byte;
749     break;
750    
751     case 0x20: ec_color = colors[ec = byte]; break;
752     case 0x21: b0c_color = colors[b0c = byte]; break;
753     case 0x22: b1c_color = colors[b1c = byte]; break;
754     case 0x23: b2c_color = colors[b2c = byte]; break;
755     case 0x24: b3c_color = colors[b3c = byte]; break;
756     case 0x25: mm0_color = colors[mm0 = byte]; break;
757     case 0x26: mm1_color = colors[mm1 = byte]; break;
758    
759     case 0x27: case 0x28: case 0x29: case 0x2a:
760     case 0x2b: case 0x2c: case 0x2d: case 0x2e:
761     spr_color[adr - 0x27] = colors[sc[adr - 0x27] = byte];
762     break;
763     }
764     }
765    
766    
767     /*
768     * CIA VA14/15 has changed
769     */
770    
771     void MOS6569::ChangedVA(uint16 new_va)
772     {
773     cia_vabase = new_va << 14;
774     WriteRegister(0x18, vbase); // Force update of memory pointers
775     }
776    
777    
778     /*
779     * Trigger lightpen interrupt, latch lightpen coordinates
780     */
781    
782     void MOS6569::TriggerLightpen(void)
783     {
784     if (!lp_triggered) { // Lightpen triggers only once per frame
785     lp_triggered = true;
786    
787     lpx = raster_x >> 1; // Latch current coordinates
788     lpy = raster_y;
789    
790     irq_flag |= 0x08; // Trigger IRQ
791     if (irq_mask & 0x08) {
792     irq_flag |= 0x80;
793     the_cpu->TriggerVICIRQ();
794     }
795     }
796     }
797    
798    
799     /*
800     * Read a byte from the VIC's address space
801     */
802    
803     #ifdef GLOBAL_VARS
804     static inline uint8 read_byte(uint16 adr)
805     #else
806     inline uint8 MOS6569::read_byte(uint16 adr)
807     #endif
808     {
809     uint16 va = adr | cia_vabase;
810     if ((va & 0x7000) == 0x1000)
811     #ifdef GLOBAL_VARS
812     return the_vic->LastVICByte = char_rom[va & 0x0fff];
813     #else
814     return LastVICByte = char_rom[va & 0x0fff];
815     #endif
816     else
817     #ifdef GLOBAL_VARS
818     return the_vic->LastVICByte = ram[va];
819     #else
820     return LastVICByte = ram[va];
821     #endif
822     }
823    
824    
825     /*
826     * Quick memset of 8 bytes
827     */
828    
829     inline void memset8(uint8 *p, uint8 c)
830     {
831     p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = c;
832     }
833    
834    
835     /*
836     * Video matrix access
837     */
838    
839     #ifdef __i386
840     inline
841     #endif
842     #ifdef GLOBAL_VARS
843     static void matrix_access(void)
844     #else
845     void MOS6569::matrix_access(void)
846     #endif
847     {
848     if (the_cpu->BALow) {
849     if (the_c64->CycleCounter-first_ba_cycle < 3)
850     matrix_line[ml_index] = color_line[ml_index] = 0xff;
851     else {
852     uint16 adr = (vc & 0x03ff) | matrix_base;
853     matrix_line[ml_index] = read_byte(adr);
854     color_line[ml_index] = color_ram[adr & 0x03ff];
855     }
856     }
857     }
858    
859    
860     /*
861     * Graphics data access
862     */
863    
864     #ifdef __i386
865     inline
866     #endif
867     #ifdef GLOBAL_VARS
868     static void graphics_access(void)
869     #else
870     void MOS6569::graphics_access(void)
871     #endif
872     {
873     if (display_state) {
874    
875     uint16 adr;
876     if (ctrl1 & 0x20) // Bitmap
877     adr = ((vc & 0x03ff) << 3) | bitmap_base | rc;
878     else // Text
879     adr = (matrix_line[ml_index] << 3) | char_base | rc;
880     if (ctrl1 & 0x40) // ECM
881     adr &= 0xf9ff;
882     gfx_data = read_byte(adr);
883     char_data = matrix_line[ml_index];
884     color_data = color_line[ml_index];
885     ml_index++;
886     vc++;
887    
888     } else {
889    
890     // Display is off
891     gfx_data = read_byte(ctrl1 & 0x40 ? 0x39ff : 0x3fff);
892     char_data = color_data = 0;
893     }
894     }
895    
896    
897     /*
898     * Background display (8 pixels)
899     */
900    
901     #ifdef GLOBAL_VARS
902     static void draw_background(void)
903     #else
904     void MOS6569::draw_background(void)
905     #endif
906     {
907     uint8 *p = chunky_ptr;
908     uint8 c;
909    
910     if (!draw_this_line)
911     return;
912    
913     switch (display_idx) {
914     case 0: // Standard text
915     case 1: // Multicolor text
916     case 3: // Multicolor bitmap
917     c = b0c_color;
918     break;
919     case 2: // Standard bitmap
920     c = colors[last_char_data];
921     break;
922     case 4: // ECM text
923     if (last_char_data & 0x80)
924     if (last_char_data & 0x40)
925     c = b3c_color;
926     else
927     c = b2c_color;
928     else
929     if (last_char_data & 0x40)
930     c = b1c_color;
931     else
932     c = b0c_color;
933     break;
934     default:
935     c = colors[0];
936     break;
937     }
938     memset8(p, c);
939     }
940    
941    
942     /*
943     * Graphics display (8 pixels)
944     */
945    
946     #ifdef __i386
947     inline
948     #endif
949     #ifdef GLOBAL_VARS
950     static void draw_graphics(void)
951     #else
952     void MOS6569::draw_graphics(void)
953     #endif
954     {
955     uint8 *p = chunky_ptr + x_scroll;
956     uint8 c[4], data;
957    
958     if (!draw_this_line)
959     return;
960     if (ud_border_on) {
961     draw_background();
962     return;
963     }
964    
965     switch (display_idx) {
966    
967     case 0: // Standard text
968     c[0] = b0c_color;
969     c[1] = colors[color_data];
970     goto draw_std;
971    
972     case 1: // Multicolor text
973     if (color_data & 8) {
974     c[0] = b0c_color;
975     c[1] = b1c_color;
976     c[2] = b2c_color;
977     c[3] = colors[color_data & 7];
978     goto draw_multi;
979     } else {
980     c[0] = b0c_color;
981     c[1] = colors[color_data];
982     goto draw_std;
983     }
984    
985     case 2: // Standard bitmap
986     c[0] = colors[char_data];
987     c[1] = colors[char_data >> 4];
988     goto draw_std;
989    
990     case 3: // Multicolor bitmap
991     c[0]= b0c_color;
992     c[1] = colors[char_data >> 4];
993     c[2] = colors[char_data];
994     c[3] = colors[color_data];
995     goto draw_multi;
996    
997     case 4: // ECM text
998     if (char_data & 0x80)
999     if (char_data & 0x40)
1000     c[0] = b3c_color;
1001     else
1002     c[0] = b2c_color;
1003     else
1004     if (char_data & 0x40)
1005     c[0] = b1c_color;
1006     else
1007     c[0] = b0c_color;
1008     c[1] = colors[color_data];
1009     goto draw_std;
1010    
1011     case 5: // Invalid multicolor text
1012     memset8(p, colors[0]);
1013     if (color_data & 8) {
1014     fore_mask_ptr[0] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) >> x_scroll;
1015     fore_mask_ptr[1] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) << (8-x_scroll);
1016     } else {
1017     fore_mask_ptr[0] |= gfx_data >> x_scroll;
1018     fore_mask_ptr[1] |= gfx_data << (7-x_scroll);
1019     }
1020     return;
1021    
1022     case 6: // Invalid standard bitmap
1023     memset8(p, colors[0]);
1024     fore_mask_ptr[0] |= gfx_data >> x_scroll;
1025     fore_mask_ptr[1] |= gfx_data << (7-x_scroll);
1026     return;
1027    
1028     case 7: // Invalid multicolor bitmap
1029     memset8(p, colors[0]);
1030     fore_mask_ptr[0] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) >> x_scroll;
1031     fore_mask_ptr[1] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) << (8-x_scroll);
1032     return;
1033    
1034     default: // Can't happen
1035     return;
1036     }
1037    
1038     draw_std:
1039    
1040     fore_mask_ptr[0] |= gfx_data >> x_scroll;
1041     fore_mask_ptr[1] |= gfx_data << (7-x_scroll);
1042    
1043     data = gfx_data;
1044     p[7] = c[data & 1]; data >>= 1;
1045     p[6] = c[data & 1]; data >>= 1;
1046     p[5] = c[data & 1]; data >>= 1;
1047     p[4] = c[data & 1]; data >>= 1;
1048     p[3] = c[data & 1]; data >>= 1;
1049     p[2] = c[data & 1]; data >>= 1;
1050     p[1] = c[data & 1]; data >>= 1;
1051     p[0] = c[data];
1052     return;
1053    
1054     draw_multi:
1055    
1056     fore_mask_ptr[0] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) >> x_scroll;
1057     fore_mask_ptr[1] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) << (8-x_scroll);
1058    
1059     data = gfx_data;
1060     p[7] = p[6] = c[data & 3]; data >>= 2;
1061     p[5] = p[4] = c[data & 3]; data >>= 2;
1062     p[3] = p[2] = c[data & 3]; data >>= 2;
1063     p[1] = p[0] = c[data];
1064     return;
1065     }
1066    
1067    
1068     /*
1069     * Sprite display
1070     */
1071    
1072     #ifdef GLOBAL_VARS
1073     inline static void draw_sprites(void)
1074     #else
1075     inline void MOS6569::draw_sprites(void)
1076     #endif
1077     {
1078     int i;
1079     int snum, sbit; // Sprite number/bit mask
1080     int spr_coll=0, gfx_coll=0;
1081    
1082     // Clear sprite collision buffer
1083     {
1084     uint32 *lp = (uint32 *)spr_coll_buf - 1;
1085     for (i=0; i<DISPLAY_X/4; i++)
1086     *++lp = 0;
1087     }
1088    
1089     // Loop for all sprites
1090     for (snum=0, sbit=1; snum<8; snum++, sbit<<=1) {
1091    
1092     // Is sprite visible?
1093     if ((spr_draw & sbit) && mx[snum] <= DISPLAY_X-32) {
1094     #ifdef __POWERPC__
1095     uint8 *p = (uint8 *)chunky_tmp + mx[snum] + 8;
1096     #else
1097     uint8 *p = chunky_line_start + mx[snum] + 8;
1098     #endif
1099     uint8 *q = spr_coll_buf + mx[snum] + 8;
1100     uint8 color = spr_color[snum];
1101    
1102     // Fetch sprite data and mask
1103     uint32 sdata = (spr_draw_data[snum][0] << 24) | (spr_draw_data[snum][1] << 16) | (spr_draw_data[snum][2] << 8);
1104    
1105     int spr_mask_pos = mx[snum] + 8; // Sprite bit position in fore_mask_buf
1106    
1107     uint8 *fmbp = fore_mask_buf + (spr_mask_pos / 8);
1108     int sshift = spr_mask_pos & 7;
1109     uint32 fore_mask = (((*(fmbp+0) << 24) | (*(fmbp+1) << 16) | (*(fmbp+2) << 8)
1110     | (*(fmbp+3))) << sshift) | (*(fmbp+4) >> (8-sshift));
1111    
1112     if (mxe & sbit) { // X-expanded
1113     if (mx[snum] > DISPLAY_X-56)
1114     continue;
1115    
1116     uint32 sdata_l = 0, sdata_r = 0, fore_mask_r;
1117     fore_mask_r = (((*(fmbp+4) << 24) | (*(fmbp+5) << 16) | (*(fmbp+6) << 8)
1118     | (*(fmbp+7))) << sshift) | (*(fmbp+8) >> (8-sshift));
1119    
1120     if (mmc & sbit) { // Multicolor mode
1121     uint32 plane0_l, plane0_r, plane1_l, plane1_r;
1122    
1123     // Expand sprite data
1124     sdata_l = MultiExpTable[sdata >> 24 & 0xff] << 16 | MultiExpTable[sdata >> 16 & 0xff];
1125     sdata_r = MultiExpTable[sdata >> 8 & 0xff] << 16;
1126    
1127     // Convert sprite chunky pixels to bitplanes
1128     plane0_l = (sdata_l & 0x55555555) | (sdata_l & 0x55555555) << 1;
1129     plane1_l = (sdata_l & 0xaaaaaaaa) | (sdata_l & 0xaaaaaaaa) >> 1;
1130     plane0_r = (sdata_r & 0x55555555) | (sdata_r & 0x55555555) << 1;
1131     plane1_r = (sdata_r & 0xaaaaaaaa) | (sdata_r & 0xaaaaaaaa) >> 1;
1132    
1133     // Collision with graphics?
1134     if ((fore_mask & (plane0_l | plane1_l)) || (fore_mask_r & (plane0_r | plane1_r))) {
1135     gfx_coll |= sbit;
1136     if (mdp & sbit) {
1137     plane0_l &= ~fore_mask; // Mask sprite if in background
1138     plane1_l &= ~fore_mask;
1139     plane0_r &= ~fore_mask_r;
1140     plane1_r &= ~fore_mask_r;
1141     }
1142     }
1143    
1144     // Paint sprite
1145     for (i=0; i<32; i++, plane0_l<<=1, plane1_l<<=1) {
1146     uint8 col;
1147     if (plane1_l & 0x80000000) {
1148     if (plane0_l & 0x80000000)
1149     col = mm1_color;
1150     else
1151     col = color;
1152     } else {
1153     if (plane0_l & 0x80000000)
1154     col = mm0_color;
1155     else
1156     continue;
1157     }
1158     if (q[i])
1159     spr_coll |= q[i] | sbit;
1160     else {
1161     p[i] = col;
1162     q[i] = sbit;
1163     }
1164     }
1165     for (; i<48; i++, plane0_r<<=1, plane1_r<<=1) {
1166     uint8 col;
1167     if (plane1_r & 0x80000000) {
1168     if (plane0_r & 0x80000000)
1169     col = mm1_color;
1170     else
1171     col = color;
1172     } else {
1173     if (plane0_r & 0x80000000)
1174     col = mm0_color;
1175     else
1176     continue;
1177     }
1178     if (q[i])
1179     spr_coll |= q[i] | sbit;
1180     else {
1181     p[i] = col;
1182     q[i] = sbit;
1183     }
1184     }
1185    
1186     } else { // Standard mode
1187    
1188     // Expand sprite data
1189     sdata_l = ExpTable[sdata >> 24 & 0xff] << 16 | ExpTable[sdata >> 16 & 0xff];
1190     sdata_r = ExpTable[sdata >> 8 & 0xff] << 16;
1191    
1192     // Collision with graphics?
1193     if ((fore_mask & sdata_l) || (fore_mask_r & sdata_r)) {
1194     gfx_coll |= sbit;
1195     if (mdp & sbit) {
1196     sdata_l &= ~fore_mask; // Mask sprite if in background
1197     sdata_r &= ~fore_mask_r;
1198     }
1199     }
1200    
1201     // Paint sprite
1202     for (i=0; i<32; i++, sdata_l<<=1)
1203     if (sdata_l & 0x80000000) {
1204     if (q[i]) // Collision with sprite?
1205     spr_coll |= q[i] | sbit;
1206     else { // Draw pixel if no collision
1207     p[i] = color;
1208     q[i] = sbit;
1209     }
1210     }
1211     for (; i<48; i++, sdata_r<<=1)
1212     if (sdata_r & 0x80000000) {
1213     if (q[i]) // Collision with sprite?
1214     spr_coll |= q[i] | sbit;
1215     else { // Draw pixel if no collision
1216     p[i] = color;
1217     q[i] = sbit;
1218     }
1219     }
1220     }
1221    
1222     } else { // Unexpanded
1223    
1224     if (mmc & sbit) { // Multicolor mode
1225     uint32 plane0, plane1;
1226    
1227     // Convert sprite chunky pixels to bitplanes
1228     plane0 = (sdata & 0x55555555) | (sdata & 0x55555555) << 1;
1229     plane1 = (sdata & 0xaaaaaaaa) | (sdata & 0xaaaaaaaa) >> 1;
1230    
1231     // Collision with graphics?
1232     if (fore_mask & (plane0 | plane1)) {
1233     gfx_coll |= sbit;
1234     if (mdp & sbit) {
1235     plane0 &= ~fore_mask; // Mask sprite if in background
1236     plane1 &= ~fore_mask;
1237     }
1238     }
1239    
1240     // Paint sprite
1241     for (i=0; i<24; i++, plane0<<=1, plane1<<=1) {
1242     uint8 col;
1243     if (plane1 & 0x80000000) {
1244     if (plane0 & 0x80000000)
1245     col = mm1_color;
1246     else
1247     col = color;
1248     } else {
1249     if (plane0 & 0x80000000)
1250     col = mm0_color;
1251     else
1252     continue;
1253     }
1254     if (q[i])
1255     spr_coll |= q[i] | sbit;
1256     else {
1257     p[i] = col;
1258     q[i] = sbit;
1259     }
1260     }
1261    
1262     } else { // Standard mode
1263    
1264     // Collision with graphics?
1265     if (fore_mask & sdata) {
1266     gfx_coll |= sbit;
1267     if (mdp & sbit)
1268     sdata &= ~fore_mask; // Mask sprite if in background
1269     }
1270    
1271     // Paint sprite
1272     for (i=0; i<24; i++, sdata<<=1)
1273     if (sdata & 0x80000000) {
1274     if (q[i]) { // Collision with sprite?
1275     spr_coll |= q[i] | sbit;
1276     } else { // Draw pixel if no collision
1277     p[i] = color;
1278     q[i] = sbit;
1279     }
1280     }
1281     }
1282     }
1283     }
1284     }
1285    
1286     if (ThePrefs.SpriteCollisions) {
1287    
1288     // Check sprite-sprite collisions
1289     if (clx_spr)
1290     clx_spr |= spr_coll;
1291     else {
1292     clx_spr |= spr_coll;
1293     irq_flag |= 0x04;
1294     if (irq_mask & 0x04) {
1295     irq_flag |= 0x80;
1296     the_cpu->TriggerVICIRQ();
1297     }
1298     }
1299    
1300     // Check sprite-background collisions
1301     if (clx_bgr)
1302     clx_bgr |= gfx_coll;
1303     else {
1304     clx_bgr |= gfx_coll;
1305     irq_flag |= 0x02;
1306     if (irq_mask & 0x02) {
1307     irq_flag |= 0x80;
1308     the_cpu->TriggerVICIRQ();
1309     }
1310     }
1311     }
1312     }
1313    
1314    
1315     #ifdef __POWERPC__
1316     static asm void fastcopy(register uchar *dst, register uchar *src);
1317     static asm void fastcopy(register uchar *dst, register uchar *src)
1318     {
1319     lfd fp0,0(src)
1320     lfd fp1,8(src)
1321     lfd fp2,16(src)
1322     lfd fp3,24(src)
1323     lfd fp4,32(src)
1324     lfd fp5,40(src)
1325     lfd fp6,48(src)
1326     lfd fp7,56(src)
1327     addi src,src,64
1328     stfd fp0,0(dst)
1329     stfd fp1,8(dst)
1330     stfd fp2,16(dst)
1331     stfd fp3,24(dst)
1332     stfd fp4,32(dst)
1333     stfd fp5,40(dst)
1334     stfd fp6,48(dst)
1335     stfd fp7,56(dst)
1336     addi dst,dst,64
1337    
1338     lfd fp0,0(src)
1339     lfd fp1,8(src)
1340     lfd fp2,16(src)
1341     lfd fp3,24(src)
1342     lfd fp4,32(src)
1343     lfd fp5,40(src)
1344     lfd fp6,48(src)
1345     lfd fp7,56(src)
1346     addi src,src,64
1347     stfd fp0,0(dst)
1348     stfd fp1,8(dst)
1349     stfd fp2,16(dst)
1350     stfd fp3,24(dst)
1351     stfd fp4,32(dst)
1352     stfd fp5,40(dst)
1353     stfd fp6,48(dst)
1354     stfd fp7,56(dst)
1355     addi dst,dst,64
1356    
1357     lfd fp0,0(src)
1358     lfd fp1,8(src)
1359     lfd fp2,16(src)
1360     lfd fp3,24(src)
1361     lfd fp4,32(src)
1362     lfd fp5,40(src)
1363     lfd fp6,48(src)
1364     lfd fp7,56(src)
1365     addi src,src,64
1366     stfd fp0,0(dst)
1367     stfd fp1,8(dst)
1368     stfd fp2,16(dst)
1369     stfd fp3,24(dst)
1370     stfd fp4,32(dst)
1371     stfd fp5,40(dst)
1372     stfd fp6,48(dst)
1373     stfd fp7,56(dst)
1374     addi dst,dst,64
1375    
1376     lfd fp0,0(src)
1377     lfd fp1,8(src)
1378     lfd fp2,16(src)
1379     lfd fp3,24(src)
1380     lfd fp4,32(src)
1381     lfd fp5,40(src)
1382     lfd fp6,48(src)
1383     lfd fp7,56(src)
1384     addi src,src,64
1385     stfd fp0,0(dst)
1386     stfd fp1,8(dst)
1387     stfd fp2,16(dst)
1388     stfd fp3,24(dst)
1389     stfd fp4,32(dst)
1390     stfd fp5,40(dst)
1391     stfd fp6,48(dst)
1392     stfd fp7,56(dst)
1393     addi dst,dst,64
1394    
1395     lfd fp0,0(src)
1396     lfd fp1,8(src)
1397     lfd fp2,16(src)
1398     lfd fp3,24(src)
1399     lfd fp4,32(src)
1400     lfd fp5,40(src)
1401     lfd fp6,48(src)
1402     lfd fp7,56(src)
1403     addi src,src,64
1404     stfd fp0,0(dst)
1405     stfd fp1,8(dst)
1406     stfd fp2,16(dst)
1407     stfd fp3,24(dst)
1408     stfd fp4,32(dst)
1409     stfd fp5,40(dst)
1410     stfd fp6,48(dst)
1411     stfd fp7,56(dst)
1412     addi dst,dst,64
1413    
1414     lfd fp0,0(src)
1415     lfd fp1,8(src)
1416     lfd fp2,16(src)
1417     lfd fp3,24(src)
1418     lfd fp4,32(src)
1419     lfd fp5,40(src)
1420     lfd fp6,48(src)
1421     lfd fp7,56(src)
1422     addi src,src,64
1423     stfd fp0,0(dst)
1424     stfd fp1,8(dst)
1425     stfd fp2,16(dst)
1426     stfd fp3,24(dst)
1427     stfd fp4,32(dst)
1428     stfd fp5,40(dst)
1429     stfd fp6,48(dst)
1430     stfd fp7,56(dst)
1431     addi dst,dst,64
1432     blr
1433     }
1434     #endif
1435    
1436    
1437     /*
1438     * Emulate one clock cycle, returns true if new raster line has started
1439     */
1440    
1441     // Set BA low
1442     #define SetBALow \
1443     if (!the_cpu->BALow) { \
1444     first_ba_cycle = the_c64->CycleCounter; \
1445     the_cpu->BALow = true; \
1446     }
1447    
1448     // Turn on display if Bad Line
1449     #define DisplayIfBadLine \
1450     if (is_bad_line) \
1451     display_state = true;
1452    
1453     // Turn on display and matrix access if Bad Line
1454     #define FetchIfBadLine \
1455     if (is_bad_line) { \
1456     display_state = true; \
1457     SetBALow; \
1458     }
1459    
1460     // Turn on display and matrix access and reset RC if Bad Line
1461     #define RCIfBadLine \
1462     if (is_bad_line) { \
1463     display_state = true; \
1464     rc = 0; \
1465     SetBALow; \
1466     }
1467    
1468     // Idle access
1469     #define IdleAccess \
1470     read_byte(0x3fff)
1471    
1472     // Refresh access
1473     #define RefreshAccess \
1474     read_byte(0x3f00 | ref_cnt--)
1475    
1476     // Turn on sprite DMA if necessary
1477     #define CheckSpriteDMA \
1478     mask = 1; \
1479     for (i=0; i<8; i++, mask<<=1) \
1480     if ((me & mask) && (raster_y & 0xff) == my[i]) { \
1481     spr_dma_on |= mask; \
1482     mc_base[i] = 0; \
1483     if (mye & mask) \
1484     spr_exp_y &= ~mask; \
1485     }
1486    
1487     // Fetch sprite data pointer
1488     #define SprPtrAccess(num) \
1489     spr_ptr[num] = read_byte(matrix_base | 0x03f8 | num) << 6;
1490    
1491     // Fetch sprite data, increment data counter
1492     #define SprDataAccess(num, bytenum) \
1493     if (spr_dma_on & (1 << num)) { \
1494     spr_data[num][bytenum] = read_byte(mc[num] & 0x3f | spr_ptr[num]); \
1495     mc[num]++; \
1496     } else if (bytenum == 1) \
1497     IdleAccess;
1498    
1499     // Sample border color and increment chunky_ptr and fore_mask_ptr
1500     #define SampleBorder \
1501     if (draw_this_line) { \
1502     if (border_on) \
1503     border_color_sample[cycle-13] = ec_color; \
1504     chunky_ptr += 8; \
1505     fore_mask_ptr++; \
1506     }
1507    
1508    
1509     bool MOS6569::EmulateCycle(void)
1510     {
1511     uint8 mask;
1512     int i;
1513    
1514     switch (cycle) {
1515    
1516     // Fetch sprite pointer 3, increment raster counter, trigger raster IRQ,
1517     // test for Bad Line, reset BA if sprites 3 and 4 off, read data of sprite 3
1518     case 1:
1519 cebix 1.6 if (raster_y == TOTAL_RASTERS-1) {
1520 cebix 1.1
1521     // Trigger VBlank in cycle 2
1522     vblanking = true;
1523    
1524 cebix 1.6 } else {
1525 cebix 1.1
1526     // Increment raster counter
1527     raster_y++;
1528    
1529     // Trigger raster IRQ if IRQ line reached
1530     if (raster_y == irq_raster)
1531     raster_irq();
1532    
1533     // In line $30, the DEN bit controls if Bad Lines can occur
1534     if (raster_y == 0x30)
1535     bad_lines_enabled = ctrl1 & 0x10;
1536    
1537     // Bad Line condition?
1538     is_bad_line = (raster_y >= FIRST_DMA_LINE && raster_y <= LAST_DMA_LINE && ((raster_y & 7) == y_scroll) && bad_lines_enabled);
1539    
1540     // Don't draw all lines, hide some at the top and bottom
1541     draw_this_line = (raster_y >= FIRST_DISP_LINE && raster_y <= LAST_DISP_LINE && !frame_skipped);
1542     }
1543    
1544     // First sample of border state
1545     border_on_sample[0] = border_on;
1546    
1547     SprPtrAccess(3);
1548     SprDataAccess(3, 0);
1549     DisplayIfBadLine;
1550     if (!(spr_dma_on & 0x18))
1551     the_cpu->BALow = false;
1552     break;
1553    
1554     // Set BA for sprite 5, read data of sprite 3
1555     case 2:
1556     if (vblanking) {
1557    
1558     // Vertical blank, reset counters
1559     raster_y = vc_base = 0;
1560     ref_cnt = 0xff;
1561     lp_triggered = vblanking = false;
1562    
1563     if (!(frame_skipped = --skip_counter))
1564     skip_counter = ThePrefs.SkipFrames;
1565    
1566     the_c64->VBlank(!frame_skipped);
1567    
1568     // Get bitmap pointer for next frame. This must be done
1569     // after calling the_c64->VBlank() because the preferences
1570     // and screen configuration may have been changed there
1571     chunky_line_start = the_display->BitmapBase();
1572     xmod = the_display->BitmapXMod();
1573    
1574     // Trigger raster IRQ if IRQ in line 0
1575     if (irq_raster == 0)
1576     raster_irq();
1577    
1578     }
1579    
1580     // Our output goes here
1581     #ifdef __POWERPC__
1582     chunky_ptr = (uint8 *)chunky_tmp;
1583     #else
1584     chunky_ptr = chunky_line_start;
1585     #endif
1586    
1587     // Clear foreground mask
1588     memset(fore_mask_buf, 0, DISPLAY_X/8);
1589     fore_mask_ptr = fore_mask_buf;
1590    
1591     SprDataAccess(3,1);
1592     SprDataAccess(3,2);
1593     DisplayIfBadLine;
1594     if (spr_dma_on & 0x20)
1595     SetBALow;
1596     break;
1597    
1598     // Fetch sprite pointer 4, reset BA is sprite 4 and 5 off
1599     case 3:
1600     SprPtrAccess(4);
1601     SprDataAccess(4, 0);
1602     DisplayIfBadLine;
1603     if (!(spr_dma_on & 0x30))
1604     the_cpu->BALow = false;
1605     break;
1606    
1607     // Set BA for sprite 6, read data of sprite 4
1608     case 4:
1609     SprDataAccess(4, 1);
1610     SprDataAccess(4, 2);
1611     DisplayIfBadLine;
1612     if (spr_dma_on & 0x40)
1613     SetBALow;
1614     break;
1615    
1616     // Fetch sprite pointer 5, reset BA if sprite 5 and 6 off
1617     case 5:
1618     SprPtrAccess(5);
1619     SprDataAccess(5, 0);
1620     DisplayIfBadLine;
1621     if (!(spr_dma_on & 0x60))
1622     the_cpu->BALow = false;
1623     break;
1624    
1625     // Set BA for sprite 7, read data of sprite 5
1626     case 6:
1627     SprDataAccess(5, 1);
1628     SprDataAccess(5, 2);
1629     DisplayIfBadLine;
1630     if (spr_dma_on & 0x80)
1631     SetBALow;
1632     break;
1633    
1634     // Fetch sprite pointer 6, reset BA if sprite 6 and 7 off
1635     case 7:
1636     SprPtrAccess(6);
1637     SprDataAccess(6, 0);
1638     DisplayIfBadLine;
1639     if (!(spr_dma_on & 0xc0))
1640     the_cpu->BALow = false;
1641     break;
1642    
1643     // Read data of sprite 6
1644     case 8:
1645     SprDataAccess(6, 1);
1646     SprDataAccess(6, 2);
1647     DisplayIfBadLine;
1648     break;
1649    
1650     // Fetch sprite pointer 7, reset BA if sprite 7 off
1651     case 9:
1652     SprPtrAccess(7);
1653     SprDataAccess(7, 0);
1654     DisplayIfBadLine;
1655     if (!(spr_dma_on & 0x80))
1656     the_cpu->BALow = false;
1657     break;
1658    
1659     // Read data of sprite 7
1660     case 10:
1661     SprDataAccess(7, 1);
1662     SprDataAccess(7, 2);
1663     DisplayIfBadLine;
1664     break;
1665    
1666     // Refresh, reset BA
1667     case 11:
1668     RefreshAccess;
1669     DisplayIfBadLine;
1670     the_cpu->BALow = false;
1671     break;
1672    
1673     // Refresh, turn on matrix access if Bad Line
1674     case 12:
1675     RefreshAccess;
1676     FetchIfBadLine;
1677     break;
1678    
1679     // Refresh, turn on matrix access if Bad Line, reset raster_x, graphics display starts here
1680     case 13:
1681     draw_background();
1682     SampleBorder;
1683     RefreshAccess;
1684     FetchIfBadLine;
1685     raster_x = 0xfffc;
1686     break;
1687    
1688     // Refresh, VCBASE->VCCOUNT, turn on matrix access and reset RC if Bad Line
1689     case 14:
1690     draw_background();
1691     SampleBorder;
1692     RefreshAccess;
1693     RCIfBadLine;
1694     vc = vc_base;
1695     break;
1696    
1697     // Refresh and matrix access, increment mc_base by 2 if y expansion flipflop is set
1698     case 15:
1699     draw_background();
1700     SampleBorder;
1701     RefreshAccess;
1702     FetchIfBadLine;
1703    
1704     for (i=0; i<8; i++)
1705     if (spr_exp_y & (1 << i))
1706     mc_base[i] += 2;
1707    
1708     ml_index = 0;
1709     matrix_access();
1710     break;
1711    
1712     // Graphics and matrix access, increment mc_base by 1 if y expansion flipflop is set
1713     // and check if sprite DMA can be turned off
1714     case 16:
1715     draw_background();
1716     SampleBorder;
1717     graphics_access();
1718     FetchIfBadLine;
1719    
1720     mask = 1;
1721     for (i=0; i<8; i++, mask<<=1) {
1722     if (spr_exp_y & mask)
1723     mc_base[i]++;
1724     if ((mc_base[i] & 0x3f) == 0x3f)
1725     spr_dma_on &= ~mask;
1726     }
1727    
1728     matrix_access();
1729     break;
1730    
1731     // Graphics and matrix access, turn off border in 40 column mode, display window starts here
1732     case 17:
1733     if (ctrl2 & 8) {
1734     if (raster_y == dy_stop)
1735     ud_border_on = true;
1736     else {
1737     if (ctrl1 & 0x10) {
1738     if (raster_y == dy_start)
1739     border_on = ud_border_on = false;
1740     else
1741     if (!ud_border_on)
1742     border_on = false;
1743     } else
1744     if (!ud_border_on)
1745     border_on = false;
1746     }
1747     }
1748    
1749     // Second sample of border state
1750     border_on_sample[1] = border_on;
1751    
1752     draw_background();
1753     draw_graphics();
1754     SampleBorder;
1755     graphics_access();
1756     FetchIfBadLine;
1757     matrix_access();
1758     break;
1759    
1760     // Turn off border in 38 column mode
1761     case 18:
1762     if (!(ctrl2 & 8)) {
1763     if (raster_y == dy_stop)
1764     ud_border_on = true;
1765     else {
1766     if (ctrl1 & 0x10) {
1767     if (raster_y == dy_start)
1768     border_on = ud_border_on = false;
1769     else
1770     if (!ud_border_on)
1771     border_on = false;
1772     } else
1773     if (!ud_border_on)
1774     border_on = false;
1775     }
1776     }
1777    
1778     // Third sample of border state
1779     border_on_sample[2] = border_on;
1780    
1781     // Falls through
1782    
1783     // Graphics and matrix access
1784     case 19: case 20: case 21: case 22: case 23: case 24:
1785     case 25: case 26: case 27: case 28: case 29: case 30:
1786     case 31: case 32: case 33: case 34: case 35: case 36:
1787     case 37: case 38: case 39: case 40: case 41: case 42:
1788     case 43: case 44: case 45: case 46: case 47: case 48:
1789     case 49: case 50: case 51: case 52: case 53: case 54: // Gnagna...
1790     draw_graphics();
1791     SampleBorder;
1792     graphics_access();
1793     FetchIfBadLine;
1794     matrix_access();
1795     last_char_data = char_data;
1796     break;
1797    
1798     // Last graphics access, turn off matrix access, turn on sprite DMA if Y coordinate is
1799     // right and sprite is enabled, handle sprite y expansion, set BA for sprite 0
1800     case 55:
1801     draw_graphics();
1802     SampleBorder;
1803     graphics_access();
1804     DisplayIfBadLine;
1805    
1806     // Invert y expansion flipflop if bit in MYE is set
1807     mask = 1;
1808     for (i=0; i<8; i++, mask<<=1)
1809     if (mye & mask)
1810     spr_exp_y ^= mask;
1811     CheckSpriteDMA;
1812    
1813     if (spr_dma_on & 0x01) { // Don't remove these braces!
1814     SetBALow;
1815     } else
1816     the_cpu->BALow = false;
1817     break;
1818    
1819     // Turn on border in 38 column mode, turn on sprite DMA if Y coordinate is right and
1820     // sprite is enabled, set BA for sprite 0, display window ends here
1821     case 56:
1822     if (!(ctrl2 & 8))
1823     border_on = true;
1824    
1825     // Fourth sample of border state
1826     border_on_sample[3] = border_on;
1827    
1828     draw_graphics();
1829     SampleBorder;
1830     IdleAccess;
1831     DisplayIfBadLine;
1832     CheckSpriteDMA;
1833    
1834     if (spr_dma_on & 0x01)
1835     SetBALow;
1836     break;
1837    
1838     // Turn on border in 40 column mode, set BA for sprite 1, paint sprites
1839     case 57:
1840     if (ctrl2 & 8)
1841     border_on = true;
1842    
1843     // Fifth sample of border state
1844     border_on_sample[4] = border_on;
1845    
1846     // Sample spr_disp_on and spr_data for sprite drawing
1847 cebix 1.3 if ((spr_draw = spr_disp_on) != 0)
1848 cebix 1.1 memcpy(spr_draw_data, spr_data, 8*4);
1849    
1850     // Turn off sprite display if DMA is off
1851     mask = 1;
1852     for (i=0; i<8; i++, mask<<=1)
1853     if ((spr_disp_on & mask) && !(spr_dma_on & mask))
1854     spr_disp_on &= ~mask;
1855    
1856     draw_background();
1857     SampleBorder;
1858     IdleAccess;
1859     DisplayIfBadLine;
1860     if (spr_dma_on & 0x02)
1861     SetBALow;
1862     break;
1863    
1864     // Fetch sprite pointer 0, mc_base->mc, turn on sprite display if necessary,
1865     // turn off display if RC=7, read data of sprite 0
1866     case 58:
1867     draw_background();
1868     SampleBorder;
1869    
1870     mask = 1;
1871     for (i=0; i<8; i++, mask<<=1) {
1872     mc[i] = mc_base[i];
1873     if ((spr_dma_on & mask) && (raster_y & 0xff) == my[i])
1874     spr_disp_on |= mask;
1875     }
1876     SprPtrAccess(0);
1877     SprDataAccess(0, 0);
1878    
1879     if (rc == 7) {
1880     vc_base = vc;
1881     display_state = false;
1882     }
1883     if (is_bad_line || display_state) {
1884     display_state = true;
1885     rc = (rc + 1) & 7;
1886     }
1887     break;
1888    
1889     // Set BA for sprite 2, read data of sprite 0
1890     case 59:
1891     draw_background();
1892     SampleBorder;
1893     SprDataAccess(0, 1);
1894     SprDataAccess(0, 2);
1895     DisplayIfBadLine;
1896     if (spr_dma_on & 0x04)
1897     SetBALow;
1898     break;
1899    
1900     // Fetch sprite pointer 1, reset BA if sprite 1 and 2 off, graphics display ends here
1901     case 60:
1902     draw_background();
1903     SampleBorder;
1904    
1905     if (draw_this_line) {
1906    
1907     // Draw sprites
1908     if (spr_draw && ThePrefs.SpritesOn)
1909     draw_sprites();
1910    
1911     // Draw border
1912     #ifdef __POWERPC__
1913     if (border_on_sample[0])
1914     for (i=0; i<4; i++)
1915     memset8((uint8 *)chunky_tmp+i*8, border_color_sample[i]);
1916     if (border_on_sample[1])
1917     memset8((uint8 *)chunky_tmp+4*8, border_color_sample[4]);
1918     if (border_on_sample[2])
1919     for (i=5; i<43; i++)
1920     memset8((uint8 *)chunky_tmp+i*8, border_color_sample[i]);
1921     if (border_on_sample[3])
1922     memset8((uint8 *)chunky_tmp+43*8, border_color_sample[43]);
1923     if (border_on_sample[4])
1924     for (i=44; i<DISPLAY_X/8; i++)
1925     memset8((uint8 *)chunky_tmp+i*8, border_color_sample[i]);
1926     #else
1927     if (border_on_sample[0])
1928     for (i=0; i<4; i++)
1929     memset8(chunky_line_start+i*8, border_color_sample[i]);
1930     if (border_on_sample[1])
1931     memset8(chunky_line_start+4*8, border_color_sample[4]);
1932     if (border_on_sample[2])
1933     for (i=5; i<43; i++)
1934     memset8(chunky_line_start+i*8, border_color_sample[i]);
1935     if (border_on_sample[3])
1936     memset8(chunky_line_start+43*8, border_color_sample[43]);
1937     if (border_on_sample[4])
1938     for (i=44; i<DISPLAY_X/8; i++)
1939     memset8(chunky_line_start+i*8, border_color_sample[i]);
1940     #endif
1941    
1942     #ifdef __POWERPC__
1943     // Copy temporary buffer to bitmap
1944     fastcopy(chunky_line_start, (uint8 *)chunky_tmp);
1945     #endif
1946    
1947     // Increment pointer in chunky buffer
1948     chunky_line_start += xmod;
1949     }
1950    
1951     SprPtrAccess(1);
1952     SprDataAccess(1, 0);
1953     DisplayIfBadLine;
1954     if (!(spr_dma_on & 0x06))
1955     the_cpu->BALow = false;
1956     break;
1957    
1958     // Set BA for sprite 3, read data of sprite 1
1959     case 61:
1960     SprDataAccess(1, 1);
1961     SprDataAccess(1, 2);
1962     DisplayIfBadLine;
1963     if (spr_dma_on & 0x08)
1964     SetBALow;
1965     break;
1966    
1967     // Read sprite pointer 2, reset BA if sprite 2 and 3 off, read data of sprite 2
1968     case 62:
1969     SprPtrAccess(2);
1970     SprDataAccess(2, 0);
1971     DisplayIfBadLine;
1972     if (!(spr_dma_on & 0x0c))
1973     the_cpu->BALow = false;
1974     break;
1975    
1976     // Set BA for sprite 4, read data of sprite 2
1977     case 63:
1978     SprDataAccess(2, 1);
1979     SprDataAccess(2, 2);
1980     DisplayIfBadLine;
1981    
1982     if (raster_y == dy_stop)
1983     ud_border_on = true;
1984     else
1985     if (ctrl1 & 0x10 && raster_y == dy_start)
1986     ud_border_on = false;
1987    
1988     if (spr_dma_on & 0x10)
1989     SetBALow;
1990    
1991     // Last cycle
1992     raster_x += 8;
1993     cycle = 1;
1994     return true;
1995     }
1996    
1997     // Next cycle
1998     raster_x += 8;
1999     cycle++;
2000     return false;
2001     }