1 |
cebix |
1.1 |
/* |
2 |
|
|
* VIC_SC.cpp - 6569R5 emulation (cycle based) |
3 |
|
|
* |
4 |
cebix |
1.2 |
* Frodo (C) 1994-1997,2002-2003 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 |
|
|
|
290 |
|
|
spr_dma_on = spr_disp_on = 0; |
291 |
|
|
for (i=0; i<8; i++) { |
292 |
|
|
mc[i] = 63; |
293 |
|
|
spr_ptr[i] = 0; |
294 |
|
|
} |
295 |
|
|
|
296 |
|
|
frame_skipped = false; |
297 |
|
|
skip_counter = 1; |
298 |
|
|
|
299 |
|
|
memset(spr_coll_buf, 0, 0x180); |
300 |
|
|
memset(fore_mask_buf, 0, 0x180/8); |
301 |
|
|
|
302 |
|
|
// Preset colors to black |
303 |
|
|
disp->InitColors(colors); |
304 |
|
|
ec_color = b0c_color = b1c_color = b2c_color = b3c_color = mm0_color = mm1_color = colors[0]; |
305 |
|
|
for (i=0; i<8; i++) spr_color[i] = colors[0]; |
306 |
|
|
} |
307 |
|
|
|
308 |
|
|
|
309 |
|
|
/* |
310 |
|
|
* Reinitialize the colors table for when the palette has changed |
311 |
|
|
*/ |
312 |
|
|
|
313 |
|
|
void MOS6569::ReInitColors(void) |
314 |
|
|
{ |
315 |
|
|
int i; |
316 |
|
|
|
317 |
|
|
// Build inverse color table. |
318 |
|
|
uint8 xlate_colors[256]; |
319 |
|
|
memset(xlate_colors, 0, sizeof(xlate_colors)); |
320 |
|
|
for (i = 0; i < 16; i++) |
321 |
|
|
xlate_colors[colors[i]] = i; |
322 |
|
|
|
323 |
|
|
// Get the new colors. |
324 |
|
|
the_display->InitColors(colors); |
325 |
|
|
|
326 |
|
|
// Build color translation table. |
327 |
|
|
for (i = 0; i < 256; i++) |
328 |
|
|
xlate_colors[i] = colors[xlate_colors[i]]; |
329 |
|
|
|
330 |
|
|
// Translate all the old colors variables. |
331 |
|
|
ec_color = colors[ec]; |
332 |
|
|
b0c_color = colors[b0c]; |
333 |
|
|
b1c_color = colors[b1c]; |
334 |
|
|
b2c_color = colors[b2c]; |
335 |
|
|
b3c_color = colors[b3c]; |
336 |
|
|
mm0_color = colors[mm0]; |
337 |
|
|
mm1_color = colors[mm1]; |
338 |
|
|
for (i = 0; i < 8; i++) |
339 |
|
|
spr_color[i] = colors[sc[i]]; |
340 |
|
|
|
341 |
|
|
// Translate the border color sample buffer. |
342 |
|
|
for (unsigned x = 0; x < sizeof(border_color_sample); x++) |
343 |
|
|
border_color_sample[x] = xlate_colors[border_color_sample[x]]; |
344 |
|
|
|
345 |
|
|
// Translate the chunky buffer. |
346 |
|
|
uint8 *scanline = the_display->BitmapBase(); |
347 |
|
|
for (int y = 0; y < DISPLAY_Y; y++) { |
348 |
|
|
for (int x = 0; x < DISPLAY_X; x++) |
349 |
|
|
scanline[x] = xlate_colors[scanline[x]]; |
350 |
|
|
scanline += xmod; |
351 |
|
|
} |
352 |
|
|
} |
353 |
|
|
|
354 |
|
|
|
355 |
|
|
/* |
356 |
|
|
* Get VIC state |
357 |
|
|
*/ |
358 |
|
|
|
359 |
|
|
void MOS6569::GetState(MOS6569State *vd) |
360 |
|
|
{ |
361 |
|
|
int i; |
362 |
|
|
|
363 |
|
|
vd->m0x = mx[0] & 0xff; vd->m0y = my[0]; |
364 |
|
|
vd->m1x = mx[1] & 0xff; vd->m1y = my[1]; |
365 |
|
|
vd->m2x = mx[2] & 0xff; vd->m2y = my[2]; |
366 |
|
|
vd->m3x = mx[3] & 0xff; vd->m3y = my[3]; |
367 |
|
|
vd->m4x = mx[4] & 0xff; vd->m4y = my[4]; |
368 |
|
|
vd->m5x = mx[5] & 0xff; vd->m5y = my[5]; |
369 |
|
|
vd->m6x = mx[6] & 0xff; vd->m6y = my[6]; |
370 |
|
|
vd->m7x = mx[7] & 0xff; vd->m7y = my[7]; |
371 |
|
|
vd->mx8 = mx8; |
372 |
|
|
|
373 |
|
|
vd->ctrl1 = (ctrl1 & 0x7f) | ((raster_y & 0x100) >> 1); |
374 |
|
|
vd->raster = raster_y & 0xff; |
375 |
|
|
vd->lpx = lpx; vd->lpy = lpy; |
376 |
|
|
vd->ctrl2 = ctrl2; |
377 |
|
|
vd->vbase = vbase; |
378 |
|
|
vd->irq_flag = irq_flag; |
379 |
|
|
vd->irq_mask = irq_mask; |
380 |
|
|
|
381 |
|
|
vd->me = me; vd->mxe = mxe; vd->mye = mye; vd->mdp = mdp; vd->mmc = mmc; |
382 |
|
|
vd->mm = clx_spr; vd->md = clx_bgr; |
383 |
|
|
|
384 |
|
|
vd->ec = ec; |
385 |
|
|
vd->b0c = b0c; vd->b1c = b1c; vd->b2c = b2c; vd->b3c = b3c; |
386 |
|
|
vd->mm0 = mm0; vd->mm1 = mm1; |
387 |
|
|
vd->m0c = sc[0]; |
388 |
|
|
vd->m1c = sc[1]; |
389 |
|
|
vd->m2c = sc[2]; |
390 |
|
|
vd->m3c = sc[3]; |
391 |
|
|
vd->m4c = sc[4]; |
392 |
|
|
vd->m5c = sc[5]; |
393 |
|
|
vd->m6c = sc[6]; |
394 |
|
|
vd->m7c = sc[7]; |
395 |
|
|
|
396 |
|
|
vd->pad0 = 0; |
397 |
|
|
vd->irq_raster = irq_raster; |
398 |
|
|
vd->vc = vc; |
399 |
|
|
vd->vc_base = vc_base; |
400 |
|
|
vd->rc = rc; |
401 |
|
|
vd->spr_dma = spr_dma_on; |
402 |
|
|
vd->spr_disp = spr_disp_on; |
403 |
|
|
for (i=0; i<8; i++) { |
404 |
|
|
vd->mc[i] = mc[i]; |
405 |
|
|
vd->mc_base[i] = mc_base[i]; |
406 |
|
|
} |
407 |
|
|
vd->display_state = display_state; |
408 |
|
|
vd->bad_line = raster_y >= FIRST_DMA_LINE && raster_y <= LAST_DMA_LINE && ((raster_y & 7) == y_scroll) && bad_lines_enabled; |
409 |
|
|
vd->bad_line_enable = bad_lines_enabled; |
410 |
|
|
vd->lp_triggered = lp_triggered; |
411 |
|
|
vd->border_on = border_on; |
412 |
|
|
|
413 |
|
|
vd->bank_base = cia_vabase; |
414 |
|
|
vd->matrix_base = ((vbase & 0xf0) << 6) | cia_vabase; |
415 |
|
|
vd->char_base = ((vbase & 0x0e) << 10) | cia_vabase; |
416 |
|
|
vd->bitmap_base = ((vbase & 0x08) << 10) | cia_vabase; |
417 |
|
|
for (i=0; i<8; i++) |
418 |
|
|
vd->sprite_base[i] = spr_ptr[i] | cia_vabase; |
419 |
|
|
|
420 |
|
|
vd->cycle = cycle; |
421 |
|
|
vd->raster_x = raster_x; |
422 |
|
|
vd->ml_index = ml_index; |
423 |
|
|
vd->ref_cnt = ref_cnt; |
424 |
|
|
vd->last_vic_byte = LastVICByte; |
425 |
|
|
vd->ud_border_on = ud_border_on; |
426 |
|
|
} |
427 |
|
|
|
428 |
|
|
|
429 |
|
|
/* |
430 |
|
|
* Set VIC state (only works if in VBlank) |
431 |
|
|
*/ |
432 |
|
|
|
433 |
|
|
void MOS6569::SetState(MOS6569State *vd) |
434 |
|
|
{ |
435 |
|
|
int i, j; |
436 |
|
|
|
437 |
|
|
mx[0] = vd->m0x; my[0] = vd->m0y; |
438 |
|
|
mx[1] = vd->m1x; my[1] = vd->m1y; |
439 |
|
|
mx[2] = vd->m2x; my[2] = vd->m2y; |
440 |
|
|
mx[3] = vd->m3x; my[3] = vd->m3y; |
441 |
|
|
mx[4] = vd->m4x; my[4] = vd->m4y; |
442 |
|
|
mx[5] = vd->m5x; my[5] = vd->m5y; |
443 |
|
|
mx[6] = vd->m6x; my[6] = vd->m6y; |
444 |
|
|
mx[7] = vd->m7x; my[7] = vd->m7y; |
445 |
|
|
mx8 = vd->mx8; |
446 |
|
|
for (i=0, j=1; i<8; i++, j<<=1) { |
447 |
|
|
if (mx8 & j) |
448 |
|
|
mx[i] |= 0x100; |
449 |
|
|
else |
450 |
|
|
mx[i] &= 0xff; |
451 |
|
|
} |
452 |
|
|
|
453 |
|
|
ctrl1 = vd->ctrl1; |
454 |
|
|
ctrl2 = vd->ctrl2; |
455 |
|
|
x_scroll = ctrl2 & 7; |
456 |
|
|
y_scroll = ctrl1 & 7; |
457 |
|
|
if (ctrl1 & 8) { |
458 |
|
|
dy_start = ROW25_YSTART; |
459 |
|
|
dy_stop = ROW25_YSTOP; |
460 |
|
|
} else { |
461 |
|
|
dy_start = ROW24_YSTART; |
462 |
|
|
dy_stop = ROW24_YSTOP; |
463 |
|
|
} |
464 |
|
|
display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4; |
465 |
|
|
|
466 |
|
|
raster_y = 0; |
467 |
|
|
lpx = vd->lpx; lpy = vd->lpy; |
468 |
|
|
|
469 |
|
|
vbase = vd->vbase; |
470 |
|
|
cia_vabase = vd->bank_base; |
471 |
|
|
matrix_base = (vbase & 0xf0) << 6; |
472 |
|
|
char_base = (vbase & 0x0e) << 10; |
473 |
|
|
bitmap_base = (vbase & 0x08) << 10; |
474 |
|
|
|
475 |
|
|
irq_flag = vd->irq_flag; |
476 |
|
|
irq_mask = vd->irq_mask; |
477 |
|
|
|
478 |
|
|
me = vd->me; mxe = vd->mxe; mye = vd->mye; mdp = vd->mdp; mmc = vd->mmc; |
479 |
|
|
clx_spr = vd->mm; clx_bgr = vd->md; |
480 |
|
|
|
481 |
|
|
ec = vd->ec; |
482 |
|
|
ec_color = colors[ec]; |
483 |
|
|
|
484 |
|
|
b0c = vd->b0c; b1c = vd->b1c; b2c = vd->b2c; b3c = vd->b3c; |
485 |
|
|
b0c_color = colors[b0c]; |
486 |
|
|
b1c_color = colors[b1c]; |
487 |
|
|
b2c_color = colors[b2c]; |
488 |
|
|
b3c_color = colors[b3c]; |
489 |
|
|
|
490 |
|
|
mm0 = vd->mm0; mm1 = vd->mm1; |
491 |
|
|
mm0_color = colors[mm0]; |
492 |
|
|
mm1_color = colors[mm1]; |
493 |
|
|
|
494 |
|
|
sc[0] = vd->m0c; sc[1] = vd->m1c; |
495 |
|
|
sc[2] = vd->m2c; sc[3] = vd->m3c; |
496 |
|
|
sc[4] = vd->m4c; sc[5] = vd->m5c; |
497 |
|
|
sc[6] = vd->m6c; sc[7] = vd->m7c; |
498 |
|
|
for (i=0; i<8; i++) |
499 |
|
|
spr_color[i] = colors[sc[i]]; |
500 |
|
|
|
501 |
|
|
irq_raster = vd->irq_raster; |
502 |
|
|
vc = vd->vc; |
503 |
|
|
vc_base = vd->vc_base; |
504 |
|
|
rc = vd->rc; |
505 |
|
|
spr_dma_on = vd->spr_dma; |
506 |
|
|
spr_disp_on = vd->spr_disp; |
507 |
|
|
for (i=0; i<8; i++) { |
508 |
|
|
mc[i] = vd->mc[i]; |
509 |
|
|
mc_base[i] = vd->mc_base[i]; |
510 |
|
|
spr_ptr[i] = vd->sprite_base[i] & 0x3fff; |
511 |
|
|
} |
512 |
|
|
display_state = vd->display_state; |
513 |
|
|
bad_lines_enabled = vd->bad_line_enable; |
514 |
|
|
lp_triggered = vd->lp_triggered; |
515 |
|
|
border_on = vd->border_on; |
516 |
|
|
|
517 |
|
|
cycle = vd->cycle; |
518 |
|
|
raster_x = vd->raster_x; |
519 |
|
|
ml_index = vd->ml_index; |
520 |
|
|
ref_cnt = vd->ref_cnt; |
521 |
|
|
LastVICByte = vd->last_vic_byte; |
522 |
|
|
ud_border_on = vd->ud_border_on; |
523 |
|
|
} |
524 |
|
|
|
525 |
|
|
|
526 |
|
|
/* |
527 |
|
|
* Trigger raster IRQ |
528 |
|
|
*/ |
529 |
|
|
|
530 |
|
|
#ifdef GLOBAL_VARS |
531 |
|
|
static inline void raster_irq(void) |
532 |
|
|
#else |
533 |
|
|
inline void MOS6569::raster_irq(void) |
534 |
|
|
#endif |
535 |
|
|
{ |
536 |
|
|
irq_flag |= 0x01; |
537 |
|
|
if (irq_mask & 0x01) { |
538 |
|
|
irq_flag |= 0x80; |
539 |
|
|
the_cpu->TriggerVICIRQ(); |
540 |
|
|
} |
541 |
|
|
} |
542 |
|
|
|
543 |
|
|
|
544 |
|
|
/* |
545 |
|
|
* Read from VIC register |
546 |
|
|
*/ |
547 |
|
|
|
548 |
|
|
uint8 MOS6569::ReadRegister(uint16 adr) |
549 |
|
|
{ |
550 |
|
|
switch (adr) { |
551 |
|
|
case 0x00: case 0x02: case 0x04: case 0x06: |
552 |
|
|
case 0x08: case 0x0a: case 0x0c: case 0x0e: |
553 |
|
|
return mx[adr >> 1]; |
554 |
|
|
|
555 |
|
|
case 0x01: case 0x03: case 0x05: case 0x07: |
556 |
|
|
case 0x09: case 0x0b: case 0x0d: case 0x0f: |
557 |
|
|
return my[adr >> 1]; |
558 |
|
|
|
559 |
|
|
case 0x10: // Sprite X position MSB |
560 |
|
|
return mx8; |
561 |
|
|
|
562 |
|
|
case 0x11: // Control register 1 |
563 |
|
|
return (ctrl1 & 0x7f) | ((raster_y & 0x100) >> 1); |
564 |
|
|
|
565 |
|
|
case 0x12: // Raster counter |
566 |
|
|
return raster_y; |
567 |
|
|
|
568 |
|
|
case 0x13: // Light pen X |
569 |
|
|
return lpx; |
570 |
|
|
|
571 |
|
|
case 0x14: // Light pen Y |
572 |
|
|
return lpy; |
573 |
|
|
|
574 |
|
|
case 0x15: // Sprite enable |
575 |
|
|
return me; |
576 |
|
|
|
577 |
|
|
case 0x16: // Control register 2 |
578 |
|
|
return ctrl2 | 0xc0; |
579 |
|
|
|
580 |
|
|
case 0x17: // Sprite Y expansion |
581 |
|
|
return mye; |
582 |
|
|
|
583 |
|
|
case 0x18: // Memory pointers |
584 |
|
|
return vbase | 0x01; |
585 |
|
|
|
586 |
|
|
case 0x19: // IRQ flags |
587 |
|
|
return irq_flag | 0x70; |
588 |
|
|
|
589 |
|
|
case 0x1a: // IRQ mask |
590 |
|
|
return irq_mask | 0xf0; |
591 |
|
|
|
592 |
|
|
case 0x1b: // Sprite data priority |
593 |
|
|
return mdp; |
594 |
|
|
|
595 |
|
|
case 0x1c: // Sprite multicolor |
596 |
|
|
return mmc; |
597 |
|
|
|
598 |
|
|
case 0x1d: // Sprite X expansion |
599 |
|
|
return mxe; |
600 |
|
|
|
601 |
|
|
case 0x1e:{ // Sprite-sprite collision |
602 |
|
|
uint8 ret = clx_spr; |
603 |
|
|
clx_spr = 0; // Read and clear |
604 |
|
|
return ret; |
605 |
|
|
} |
606 |
|
|
|
607 |
|
|
case 0x1f:{ // Sprite-background collision |
608 |
|
|
uint8 ret = clx_bgr; |
609 |
|
|
clx_bgr = 0; // Read and clear |
610 |
|
|
return ret; |
611 |
|
|
} |
612 |
|
|
|
613 |
|
|
case 0x20: return ec | 0xf0; |
614 |
|
|
case 0x21: return b0c | 0xf0; |
615 |
|
|
case 0x22: return b1c | 0xf0; |
616 |
|
|
case 0x23: return b2c | 0xf0; |
617 |
|
|
case 0x24: return b3c | 0xf0; |
618 |
|
|
case 0x25: return mm0 | 0xf0; |
619 |
|
|
case 0x26: return mm1 | 0xf0; |
620 |
|
|
|
621 |
|
|
case 0x27: case 0x28: case 0x29: case 0x2a: |
622 |
|
|
case 0x2b: case 0x2c: case 0x2d: case 0x2e: |
623 |
|
|
return sc[adr - 0x27] | 0xf0; |
624 |
|
|
|
625 |
|
|
default: |
626 |
|
|
return 0xff; |
627 |
|
|
} |
628 |
|
|
} |
629 |
|
|
|
630 |
|
|
|
631 |
|
|
/* |
632 |
|
|
* Write to VIC register |
633 |
|
|
*/ |
634 |
|
|
|
635 |
|
|
void MOS6569::WriteRegister(uint16 adr, uint8 byte) |
636 |
|
|
{ |
637 |
|
|
switch (adr) { |
638 |
|
|
case 0x00: case 0x02: case 0x04: case 0x06: |
639 |
|
|
case 0x08: case 0x0a: case 0x0c: case 0x0e: |
640 |
|
|
mx[adr >> 1] = (mx[adr >> 1] & 0xff00) | byte; |
641 |
|
|
break; |
642 |
|
|
|
643 |
|
|
case 0x10:{ |
644 |
|
|
int i, j; |
645 |
|
|
mx8 = byte; |
646 |
|
|
for (i=0, j=1; i<8; i++, j<<=1) { |
647 |
|
|
if (mx8 & j) |
648 |
|
|
mx[i] |= 0x100; |
649 |
|
|
else |
650 |
|
|
mx[i] &= 0xff; |
651 |
|
|
} |
652 |
|
|
break; |
653 |
|
|
} |
654 |
|
|
|
655 |
|
|
case 0x01: case 0x03: case 0x05: case 0x07: |
656 |
|
|
case 0x09: case 0x0b: case 0x0d: case 0x0f: |
657 |
|
|
my[adr >> 1] = byte; |
658 |
|
|
break; |
659 |
|
|
|
660 |
|
|
case 0x11:{ // Control register 1 |
661 |
|
|
ctrl1 = byte; |
662 |
|
|
y_scroll = byte & 7; |
663 |
|
|
|
664 |
|
|
uint16 new_irq_raster = (irq_raster & 0xff) | ((byte & 0x80) << 1); |
665 |
|
|
if (irq_raster != new_irq_raster && raster_y == new_irq_raster) |
666 |
|
|
raster_irq(); |
667 |
|
|
irq_raster = new_irq_raster; |
668 |
|
|
|
669 |
|
|
if (byte & 8) { |
670 |
|
|
dy_start = ROW25_YSTART; |
671 |
|
|
dy_stop = ROW25_YSTOP; |
672 |
|
|
} else { |
673 |
|
|
dy_start = ROW24_YSTART; |
674 |
|
|
dy_stop = ROW24_YSTOP; |
675 |
|
|
} |
676 |
|
|
|
677 |
|
|
// In line $30, the DEN bit controls if Bad Lines can occur |
678 |
|
|
if (raster_y == 0x30 && byte & 0x10) |
679 |
|
|
bad_lines_enabled = true; |
680 |
|
|
|
681 |
|
|
// Bad Line condition? |
682 |
|
|
is_bad_line = (raster_y >= FIRST_DMA_LINE && raster_y <= LAST_DMA_LINE && ((raster_y & 7) == y_scroll) && bad_lines_enabled); |
683 |
|
|
|
684 |
|
|
display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4; |
685 |
|
|
break; |
686 |
|
|
} |
687 |
|
|
|
688 |
|
|
case 0x12:{ // Raster counter |
689 |
|
|
uint16 new_irq_raster = (irq_raster & 0xff00) | byte; |
690 |
|
|
if (irq_raster != new_irq_raster && raster_y == new_irq_raster) |
691 |
|
|
raster_irq(); |
692 |
|
|
irq_raster = new_irq_raster; |
693 |
|
|
break; |
694 |
|
|
} |
695 |
|
|
|
696 |
|
|
case 0x15: // Sprite enable |
697 |
|
|
me = byte; |
698 |
|
|
break; |
699 |
|
|
|
700 |
|
|
case 0x16: // Control register 2 |
701 |
|
|
ctrl2 = byte; |
702 |
|
|
x_scroll = byte & 7; |
703 |
|
|
display_idx = ((ctrl1 & 0x60) | (ctrl2 & 0x10)) >> 4; |
704 |
|
|
break; |
705 |
|
|
|
706 |
|
|
case 0x17: // Sprite Y expansion |
707 |
|
|
mye = byte; |
708 |
|
|
spr_exp_y |= ~byte; |
709 |
|
|
break; |
710 |
|
|
|
711 |
|
|
case 0x18: // Memory pointers |
712 |
|
|
vbase = byte; |
713 |
|
|
matrix_base = (byte & 0xf0) << 6; |
714 |
|
|
char_base = (byte & 0x0e) << 10; |
715 |
|
|
bitmap_base = (byte & 0x08) << 10; |
716 |
|
|
break; |
717 |
|
|
|
718 |
|
|
case 0x19: // IRQ flags |
719 |
|
|
irq_flag = irq_flag & (~byte & 0x0f); |
720 |
|
|
if (irq_flag & irq_mask) // Set master bit if allowed interrupt still pending |
721 |
|
|
irq_flag |= 0x80; |
722 |
|
|
else |
723 |
|
|
the_cpu->ClearVICIRQ(); // Else clear interrupt |
724 |
|
|
break; |
725 |
|
|
|
726 |
|
|
case 0x1a: // IRQ mask |
727 |
|
|
irq_mask = byte & 0x0f; |
728 |
|
|
if (irq_flag & irq_mask) { // Trigger interrupt if pending and now allowed |
729 |
|
|
irq_flag |= 0x80; |
730 |
|
|
the_cpu->TriggerVICIRQ(); |
731 |
|
|
} else { |
732 |
|
|
irq_flag &= 0x7f; |
733 |
|
|
the_cpu->ClearVICIRQ(); |
734 |
|
|
} |
735 |
|
|
break; |
736 |
|
|
|
737 |
|
|
case 0x1b: // Sprite data priority |
738 |
|
|
mdp = byte; |
739 |
|
|
break; |
740 |
|
|
|
741 |
|
|
case 0x1c: // Sprite multicolor |
742 |
|
|
mmc = byte; |
743 |
|
|
break; |
744 |
|
|
|
745 |
|
|
case 0x1d: // Sprite X expansion |
746 |
|
|
mxe = byte; |
747 |
|
|
break; |
748 |
|
|
|
749 |
|
|
case 0x20: ec_color = colors[ec = byte]; break; |
750 |
|
|
case 0x21: b0c_color = colors[b0c = byte]; break; |
751 |
|
|
case 0x22: b1c_color = colors[b1c = byte]; break; |
752 |
|
|
case 0x23: b2c_color = colors[b2c = byte]; break; |
753 |
|
|
case 0x24: b3c_color = colors[b3c = byte]; break; |
754 |
|
|
case 0x25: mm0_color = colors[mm0 = byte]; break; |
755 |
|
|
case 0x26: mm1_color = colors[mm1 = byte]; break; |
756 |
|
|
|
757 |
|
|
case 0x27: case 0x28: case 0x29: case 0x2a: |
758 |
|
|
case 0x2b: case 0x2c: case 0x2d: case 0x2e: |
759 |
|
|
spr_color[adr - 0x27] = colors[sc[adr - 0x27] = byte]; |
760 |
|
|
break; |
761 |
|
|
} |
762 |
|
|
} |
763 |
|
|
|
764 |
|
|
|
765 |
|
|
/* |
766 |
|
|
* CIA VA14/15 has changed |
767 |
|
|
*/ |
768 |
|
|
|
769 |
|
|
void MOS6569::ChangedVA(uint16 new_va) |
770 |
|
|
{ |
771 |
|
|
cia_vabase = new_va << 14; |
772 |
|
|
WriteRegister(0x18, vbase); // Force update of memory pointers |
773 |
|
|
} |
774 |
|
|
|
775 |
|
|
|
776 |
|
|
/* |
777 |
|
|
* Trigger lightpen interrupt, latch lightpen coordinates |
778 |
|
|
*/ |
779 |
|
|
|
780 |
|
|
void MOS6569::TriggerLightpen(void) |
781 |
|
|
{ |
782 |
|
|
if (!lp_triggered) { // Lightpen triggers only once per frame |
783 |
|
|
lp_triggered = true; |
784 |
|
|
|
785 |
|
|
lpx = raster_x >> 1; // Latch current coordinates |
786 |
|
|
lpy = raster_y; |
787 |
|
|
|
788 |
|
|
irq_flag |= 0x08; // Trigger IRQ |
789 |
|
|
if (irq_mask & 0x08) { |
790 |
|
|
irq_flag |= 0x80; |
791 |
|
|
the_cpu->TriggerVICIRQ(); |
792 |
|
|
} |
793 |
|
|
} |
794 |
|
|
} |
795 |
|
|
|
796 |
|
|
|
797 |
|
|
/* |
798 |
|
|
* Read a byte from the VIC's address space |
799 |
|
|
*/ |
800 |
|
|
|
801 |
|
|
#ifdef GLOBAL_VARS |
802 |
|
|
static inline uint8 read_byte(uint16 adr) |
803 |
|
|
#else |
804 |
|
|
inline uint8 MOS6569::read_byte(uint16 adr) |
805 |
|
|
#endif |
806 |
|
|
{ |
807 |
|
|
uint16 va = adr | cia_vabase; |
808 |
|
|
if ((va & 0x7000) == 0x1000) |
809 |
|
|
#ifdef GLOBAL_VARS |
810 |
|
|
return the_vic->LastVICByte = char_rom[va & 0x0fff]; |
811 |
|
|
#else |
812 |
|
|
return LastVICByte = char_rom[va & 0x0fff]; |
813 |
|
|
#endif |
814 |
|
|
else |
815 |
|
|
#ifdef GLOBAL_VARS |
816 |
|
|
return the_vic->LastVICByte = ram[va]; |
817 |
|
|
#else |
818 |
|
|
return LastVICByte = ram[va]; |
819 |
|
|
#endif |
820 |
|
|
} |
821 |
|
|
|
822 |
|
|
|
823 |
|
|
/* |
824 |
|
|
* Quick memset of 8 bytes |
825 |
|
|
*/ |
826 |
|
|
|
827 |
|
|
inline void memset8(uint8 *p, uint8 c) |
828 |
|
|
{ |
829 |
|
|
p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = c; |
830 |
|
|
} |
831 |
|
|
|
832 |
|
|
|
833 |
|
|
/* |
834 |
|
|
* Video matrix access |
835 |
|
|
*/ |
836 |
|
|
|
837 |
|
|
#ifdef __i386 |
838 |
|
|
inline |
839 |
|
|
#endif |
840 |
|
|
#ifdef GLOBAL_VARS |
841 |
|
|
static void matrix_access(void) |
842 |
|
|
#else |
843 |
|
|
void MOS6569::matrix_access(void) |
844 |
|
|
#endif |
845 |
|
|
{ |
846 |
|
|
if (the_cpu->BALow) { |
847 |
|
|
if (the_c64->CycleCounter-first_ba_cycle < 3) |
848 |
|
|
matrix_line[ml_index] = color_line[ml_index] = 0xff; |
849 |
|
|
else { |
850 |
|
|
uint16 adr = (vc & 0x03ff) | matrix_base; |
851 |
|
|
matrix_line[ml_index] = read_byte(adr); |
852 |
|
|
color_line[ml_index] = color_ram[adr & 0x03ff]; |
853 |
|
|
} |
854 |
|
|
} |
855 |
|
|
} |
856 |
|
|
|
857 |
|
|
|
858 |
|
|
/* |
859 |
|
|
* Graphics data access |
860 |
|
|
*/ |
861 |
|
|
|
862 |
|
|
#ifdef __i386 |
863 |
|
|
inline |
864 |
|
|
#endif |
865 |
|
|
#ifdef GLOBAL_VARS |
866 |
|
|
static void graphics_access(void) |
867 |
|
|
#else |
868 |
|
|
void MOS6569::graphics_access(void) |
869 |
|
|
#endif |
870 |
|
|
{ |
871 |
|
|
if (display_state) { |
872 |
|
|
|
873 |
|
|
uint16 adr; |
874 |
|
|
if (ctrl1 & 0x20) // Bitmap |
875 |
|
|
adr = ((vc & 0x03ff) << 3) | bitmap_base | rc; |
876 |
|
|
else // Text |
877 |
|
|
adr = (matrix_line[ml_index] << 3) | char_base | rc; |
878 |
|
|
if (ctrl1 & 0x40) // ECM |
879 |
|
|
adr &= 0xf9ff; |
880 |
|
|
gfx_data = read_byte(adr); |
881 |
|
|
char_data = matrix_line[ml_index]; |
882 |
|
|
color_data = color_line[ml_index]; |
883 |
|
|
ml_index++; |
884 |
|
|
vc++; |
885 |
|
|
|
886 |
|
|
} else { |
887 |
|
|
|
888 |
|
|
// Display is off |
889 |
|
|
gfx_data = read_byte(ctrl1 & 0x40 ? 0x39ff : 0x3fff); |
890 |
|
|
char_data = color_data = 0; |
891 |
|
|
} |
892 |
|
|
} |
893 |
|
|
|
894 |
|
|
|
895 |
|
|
/* |
896 |
|
|
* Background display (8 pixels) |
897 |
|
|
*/ |
898 |
|
|
|
899 |
|
|
#ifdef GLOBAL_VARS |
900 |
|
|
static void draw_background(void) |
901 |
|
|
#else |
902 |
|
|
void MOS6569::draw_background(void) |
903 |
|
|
#endif |
904 |
|
|
{ |
905 |
|
|
uint8 *p = chunky_ptr; |
906 |
|
|
uint8 c; |
907 |
|
|
|
908 |
|
|
if (!draw_this_line) |
909 |
|
|
return; |
910 |
|
|
|
911 |
|
|
switch (display_idx) { |
912 |
|
|
case 0: // Standard text |
913 |
|
|
case 1: // Multicolor text |
914 |
|
|
case 3: // Multicolor bitmap |
915 |
|
|
c = b0c_color; |
916 |
|
|
break; |
917 |
|
|
case 2: // Standard bitmap |
918 |
|
|
c = colors[last_char_data]; |
919 |
|
|
break; |
920 |
|
|
case 4: // ECM text |
921 |
|
|
if (last_char_data & 0x80) |
922 |
|
|
if (last_char_data & 0x40) |
923 |
|
|
c = b3c_color; |
924 |
|
|
else |
925 |
|
|
c = b2c_color; |
926 |
|
|
else |
927 |
|
|
if (last_char_data & 0x40) |
928 |
|
|
c = b1c_color; |
929 |
|
|
else |
930 |
|
|
c = b0c_color; |
931 |
|
|
break; |
932 |
|
|
default: |
933 |
|
|
c = colors[0]; |
934 |
|
|
break; |
935 |
|
|
} |
936 |
|
|
memset8(p, c); |
937 |
|
|
} |
938 |
|
|
|
939 |
|
|
|
940 |
|
|
/* |
941 |
|
|
* Graphics display (8 pixels) |
942 |
|
|
*/ |
943 |
|
|
|
944 |
|
|
#ifdef __i386 |
945 |
|
|
inline |
946 |
|
|
#endif |
947 |
|
|
#ifdef GLOBAL_VARS |
948 |
|
|
static void draw_graphics(void) |
949 |
|
|
#else |
950 |
|
|
void MOS6569::draw_graphics(void) |
951 |
|
|
#endif |
952 |
|
|
{ |
953 |
|
|
uint8 *p = chunky_ptr + x_scroll; |
954 |
|
|
uint8 c[4], data; |
955 |
|
|
|
956 |
|
|
if (!draw_this_line) |
957 |
|
|
return; |
958 |
|
|
if (ud_border_on) { |
959 |
|
|
draw_background(); |
960 |
|
|
return; |
961 |
|
|
} |
962 |
|
|
|
963 |
|
|
switch (display_idx) { |
964 |
|
|
|
965 |
|
|
case 0: // Standard text |
966 |
|
|
c[0] = b0c_color; |
967 |
|
|
c[1] = colors[color_data]; |
968 |
|
|
goto draw_std; |
969 |
|
|
|
970 |
|
|
case 1: // Multicolor text |
971 |
|
|
if (color_data & 8) { |
972 |
|
|
c[0] = b0c_color; |
973 |
|
|
c[1] = b1c_color; |
974 |
|
|
c[2] = b2c_color; |
975 |
|
|
c[3] = colors[color_data & 7]; |
976 |
|
|
goto draw_multi; |
977 |
|
|
} else { |
978 |
|
|
c[0] = b0c_color; |
979 |
|
|
c[1] = colors[color_data]; |
980 |
|
|
goto draw_std; |
981 |
|
|
} |
982 |
|
|
|
983 |
|
|
case 2: // Standard bitmap |
984 |
|
|
c[0] = colors[char_data]; |
985 |
|
|
c[1] = colors[char_data >> 4]; |
986 |
|
|
goto draw_std; |
987 |
|
|
|
988 |
|
|
case 3: // Multicolor bitmap |
989 |
|
|
c[0]= b0c_color; |
990 |
|
|
c[1] = colors[char_data >> 4]; |
991 |
|
|
c[2] = colors[char_data]; |
992 |
|
|
c[3] = colors[color_data]; |
993 |
|
|
goto draw_multi; |
994 |
|
|
|
995 |
|
|
case 4: // ECM text |
996 |
|
|
if (char_data & 0x80) |
997 |
|
|
if (char_data & 0x40) |
998 |
|
|
c[0] = b3c_color; |
999 |
|
|
else |
1000 |
|
|
c[0] = b2c_color; |
1001 |
|
|
else |
1002 |
|
|
if (char_data & 0x40) |
1003 |
|
|
c[0] = b1c_color; |
1004 |
|
|
else |
1005 |
|
|
c[0] = b0c_color; |
1006 |
|
|
c[1] = colors[color_data]; |
1007 |
|
|
goto draw_std; |
1008 |
|
|
|
1009 |
|
|
case 5: // Invalid multicolor text |
1010 |
|
|
memset8(p, colors[0]); |
1011 |
|
|
if (color_data & 8) { |
1012 |
|
|
fore_mask_ptr[0] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) >> x_scroll; |
1013 |
|
|
fore_mask_ptr[1] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) << (8-x_scroll); |
1014 |
|
|
} else { |
1015 |
|
|
fore_mask_ptr[0] |= gfx_data >> x_scroll; |
1016 |
|
|
fore_mask_ptr[1] |= gfx_data << (7-x_scroll); |
1017 |
|
|
} |
1018 |
|
|
return; |
1019 |
|
|
|
1020 |
|
|
case 6: // Invalid standard bitmap |
1021 |
|
|
memset8(p, colors[0]); |
1022 |
|
|
fore_mask_ptr[0] |= gfx_data >> x_scroll; |
1023 |
|
|
fore_mask_ptr[1] |= gfx_data << (7-x_scroll); |
1024 |
|
|
return; |
1025 |
|
|
|
1026 |
|
|
case 7: // Invalid multicolor bitmap |
1027 |
|
|
memset8(p, colors[0]); |
1028 |
|
|
fore_mask_ptr[0] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) >> x_scroll; |
1029 |
|
|
fore_mask_ptr[1] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) << (8-x_scroll); |
1030 |
|
|
return; |
1031 |
|
|
|
1032 |
|
|
default: // Can't happen |
1033 |
|
|
return; |
1034 |
|
|
} |
1035 |
|
|
|
1036 |
|
|
draw_std: |
1037 |
|
|
|
1038 |
|
|
fore_mask_ptr[0] |= gfx_data >> x_scroll; |
1039 |
|
|
fore_mask_ptr[1] |= gfx_data << (7-x_scroll); |
1040 |
|
|
|
1041 |
|
|
data = gfx_data; |
1042 |
|
|
p[7] = c[data & 1]; data >>= 1; |
1043 |
|
|
p[6] = c[data & 1]; data >>= 1; |
1044 |
|
|
p[5] = c[data & 1]; data >>= 1; |
1045 |
|
|
p[4] = c[data & 1]; data >>= 1; |
1046 |
|
|
p[3] = c[data & 1]; data >>= 1; |
1047 |
|
|
p[2] = c[data & 1]; data >>= 1; |
1048 |
|
|
p[1] = c[data & 1]; data >>= 1; |
1049 |
|
|
p[0] = c[data]; |
1050 |
|
|
return; |
1051 |
|
|
|
1052 |
|
|
draw_multi: |
1053 |
|
|
|
1054 |
|
|
fore_mask_ptr[0] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) >> x_scroll; |
1055 |
|
|
fore_mask_ptr[1] |= ((gfx_data & 0xaa) | (gfx_data & 0xaa) >> 1) << (8-x_scroll); |
1056 |
|
|
|
1057 |
|
|
data = gfx_data; |
1058 |
|
|
p[7] = p[6] = c[data & 3]; data >>= 2; |
1059 |
|
|
p[5] = p[4] = c[data & 3]; data >>= 2; |
1060 |
|
|
p[3] = p[2] = c[data & 3]; data >>= 2; |
1061 |
|
|
p[1] = p[0] = c[data]; |
1062 |
|
|
return; |
1063 |
|
|
} |
1064 |
|
|
|
1065 |
|
|
|
1066 |
|
|
/* |
1067 |
|
|
* Sprite display |
1068 |
|
|
*/ |
1069 |
|
|
|
1070 |
|
|
#ifdef GLOBAL_VARS |
1071 |
|
|
inline static void draw_sprites(void) |
1072 |
|
|
#else |
1073 |
|
|
inline void MOS6569::draw_sprites(void) |
1074 |
|
|
#endif |
1075 |
|
|
{ |
1076 |
|
|
int i; |
1077 |
|
|
int snum, sbit; // Sprite number/bit mask |
1078 |
|
|
int spr_coll=0, gfx_coll=0; |
1079 |
|
|
|
1080 |
|
|
// Clear sprite collision buffer |
1081 |
|
|
{ |
1082 |
|
|
uint32 *lp = (uint32 *)spr_coll_buf - 1; |
1083 |
|
|
for (i=0; i<DISPLAY_X/4; i++) |
1084 |
|
|
*++lp = 0; |
1085 |
|
|
} |
1086 |
|
|
|
1087 |
|
|
// Loop for all sprites |
1088 |
|
|
for (snum=0, sbit=1; snum<8; snum++, sbit<<=1) { |
1089 |
|
|
|
1090 |
|
|
// Is sprite visible? |
1091 |
|
|
if ((spr_draw & sbit) && mx[snum] <= DISPLAY_X-32) { |
1092 |
|
|
#ifdef __POWERPC__ |
1093 |
|
|
uint8 *p = (uint8 *)chunky_tmp + mx[snum] + 8; |
1094 |
|
|
#else |
1095 |
|
|
uint8 *p = chunky_line_start + mx[snum] + 8; |
1096 |
|
|
#endif |
1097 |
|
|
uint8 *q = spr_coll_buf + mx[snum] + 8; |
1098 |
|
|
uint8 color = spr_color[snum]; |
1099 |
|
|
|
1100 |
|
|
// Fetch sprite data and mask |
1101 |
|
|
uint32 sdata = (spr_draw_data[snum][0] << 24) | (spr_draw_data[snum][1] << 16) | (spr_draw_data[snum][2] << 8); |
1102 |
|
|
|
1103 |
|
|
int spr_mask_pos = mx[snum] + 8; // Sprite bit position in fore_mask_buf |
1104 |
|
|
|
1105 |
|
|
uint8 *fmbp = fore_mask_buf + (spr_mask_pos / 8); |
1106 |
|
|
int sshift = spr_mask_pos & 7; |
1107 |
|
|
uint32 fore_mask = (((*(fmbp+0) << 24) | (*(fmbp+1) << 16) | (*(fmbp+2) << 8) |
1108 |
|
|
| (*(fmbp+3))) << sshift) | (*(fmbp+4) >> (8-sshift)); |
1109 |
|
|
|
1110 |
|
|
if (mxe & sbit) { // X-expanded |
1111 |
|
|
if (mx[snum] > DISPLAY_X-56) |
1112 |
|
|
continue; |
1113 |
|
|
|
1114 |
|
|
uint32 sdata_l = 0, sdata_r = 0, fore_mask_r; |
1115 |
|
|
fore_mask_r = (((*(fmbp+4) << 24) | (*(fmbp+5) << 16) | (*(fmbp+6) << 8) |
1116 |
|
|
| (*(fmbp+7))) << sshift) | (*(fmbp+8) >> (8-sshift)); |
1117 |
|
|
|
1118 |
|
|
if (mmc & sbit) { // Multicolor mode |
1119 |
|
|
uint32 plane0_l, plane0_r, plane1_l, plane1_r; |
1120 |
|
|
|
1121 |
|
|
// Expand sprite data |
1122 |
|
|
sdata_l = MultiExpTable[sdata >> 24 & 0xff] << 16 | MultiExpTable[sdata >> 16 & 0xff]; |
1123 |
|
|
sdata_r = MultiExpTable[sdata >> 8 & 0xff] << 16; |
1124 |
|
|
|
1125 |
|
|
// Convert sprite chunky pixels to bitplanes |
1126 |
|
|
plane0_l = (sdata_l & 0x55555555) | (sdata_l & 0x55555555) << 1; |
1127 |
|
|
plane1_l = (sdata_l & 0xaaaaaaaa) | (sdata_l & 0xaaaaaaaa) >> 1; |
1128 |
|
|
plane0_r = (sdata_r & 0x55555555) | (sdata_r & 0x55555555) << 1; |
1129 |
|
|
plane1_r = (sdata_r & 0xaaaaaaaa) | (sdata_r & 0xaaaaaaaa) >> 1; |
1130 |
|
|
|
1131 |
|
|
// Collision with graphics? |
1132 |
|
|
if ((fore_mask & (plane0_l | plane1_l)) || (fore_mask_r & (plane0_r | plane1_r))) { |
1133 |
|
|
gfx_coll |= sbit; |
1134 |
|
|
if (mdp & sbit) { |
1135 |
|
|
plane0_l &= ~fore_mask; // Mask sprite if in background |
1136 |
|
|
plane1_l &= ~fore_mask; |
1137 |
|
|
plane0_r &= ~fore_mask_r; |
1138 |
|
|
plane1_r &= ~fore_mask_r; |
1139 |
|
|
} |
1140 |
|
|
} |
1141 |
|
|
|
1142 |
|
|
// Paint sprite |
1143 |
|
|
for (i=0; i<32; i++, plane0_l<<=1, plane1_l<<=1) { |
1144 |
|
|
uint8 col; |
1145 |
|
|
if (plane1_l & 0x80000000) { |
1146 |
|
|
if (plane0_l & 0x80000000) |
1147 |
|
|
col = mm1_color; |
1148 |
|
|
else |
1149 |
|
|
col = color; |
1150 |
|
|
} else { |
1151 |
|
|
if (plane0_l & 0x80000000) |
1152 |
|
|
col = mm0_color; |
1153 |
|
|
else |
1154 |
|
|
continue; |
1155 |
|
|
} |
1156 |
|
|
if (q[i]) |
1157 |
|
|
spr_coll |= q[i] | sbit; |
1158 |
|
|
else { |
1159 |
|
|
p[i] = col; |
1160 |
|
|
q[i] = sbit; |
1161 |
|
|
} |
1162 |
|
|
} |
1163 |
|
|
for (; i<48; i++, plane0_r<<=1, plane1_r<<=1) { |
1164 |
|
|
uint8 col; |
1165 |
|
|
if (plane1_r & 0x80000000) { |
1166 |
|
|
if (plane0_r & 0x80000000) |
1167 |
|
|
col = mm1_color; |
1168 |
|
|
else |
1169 |
|
|
col = color; |
1170 |
|
|
} else { |
1171 |
|
|
if (plane0_r & 0x80000000) |
1172 |
|
|
col = mm0_color; |
1173 |
|
|
else |
1174 |
|
|
continue; |
1175 |
|
|
} |
1176 |
|
|
if (q[i]) |
1177 |
|
|
spr_coll |= q[i] | sbit; |
1178 |
|
|
else { |
1179 |
|
|
p[i] = col; |
1180 |
|
|
q[i] = sbit; |
1181 |
|
|
} |
1182 |
|
|
} |
1183 |
|
|
|
1184 |
|
|
} else { // Standard mode |
1185 |
|
|
|
1186 |
|
|
// Expand sprite data |
1187 |
|
|
sdata_l = ExpTable[sdata >> 24 & 0xff] << 16 | ExpTable[sdata >> 16 & 0xff]; |
1188 |
|
|
sdata_r = ExpTable[sdata >> 8 & 0xff] << 16; |
1189 |
|
|
|
1190 |
|
|
// Collision with graphics? |
1191 |
|
|
if ((fore_mask & sdata_l) || (fore_mask_r & sdata_r)) { |
1192 |
|
|
gfx_coll |= sbit; |
1193 |
|
|
if (mdp & sbit) { |
1194 |
|
|
sdata_l &= ~fore_mask; // Mask sprite if in background |
1195 |
|
|
sdata_r &= ~fore_mask_r; |
1196 |
|
|
} |
1197 |
|
|
} |
1198 |
|
|
|
1199 |
|
|
// Paint sprite |
1200 |
|
|
for (i=0; i<32; i++, sdata_l<<=1) |
1201 |
|
|
if (sdata_l & 0x80000000) { |
1202 |
|
|
if (q[i]) // Collision with sprite? |
1203 |
|
|
spr_coll |= q[i] | sbit; |
1204 |
|
|
else { // Draw pixel if no collision |
1205 |
|
|
p[i] = color; |
1206 |
|
|
q[i] = sbit; |
1207 |
|
|
} |
1208 |
|
|
} |
1209 |
|
|
for (; i<48; i++, sdata_r<<=1) |
1210 |
|
|
if (sdata_r & 0x80000000) { |
1211 |
|
|
if (q[i]) // Collision with sprite? |
1212 |
|
|
spr_coll |= q[i] | sbit; |
1213 |
|
|
else { // Draw pixel if no collision |
1214 |
|
|
p[i] = color; |
1215 |
|
|
q[i] = sbit; |
1216 |
|
|
} |
1217 |
|
|
} |
1218 |
|
|
} |
1219 |
|
|
|
1220 |
|
|
} else { // Unexpanded |
1221 |
|
|
|
1222 |
|
|
if (mmc & sbit) { // Multicolor mode |
1223 |
|
|
uint32 plane0, plane1; |
1224 |
|
|
|
1225 |
|
|
// Convert sprite chunky pixels to bitplanes |
1226 |
|
|
plane0 = (sdata & 0x55555555) | (sdata & 0x55555555) << 1; |
1227 |
|
|
plane1 = (sdata & 0xaaaaaaaa) | (sdata & 0xaaaaaaaa) >> 1; |
1228 |
|
|
|
1229 |
|
|
// Collision with graphics? |
1230 |
|
|
if (fore_mask & (plane0 | plane1)) { |
1231 |
|
|
gfx_coll |= sbit; |
1232 |
|
|
if (mdp & sbit) { |
1233 |
|
|
plane0 &= ~fore_mask; // Mask sprite if in background |
1234 |
|
|
plane1 &= ~fore_mask; |
1235 |
|
|
} |
1236 |
|
|
} |
1237 |
|
|
|
1238 |
|
|
// Paint sprite |
1239 |
|
|
for (i=0; i<24; i++, plane0<<=1, plane1<<=1) { |
1240 |
|
|
uint8 col; |
1241 |
|
|
if (plane1 & 0x80000000) { |
1242 |
|
|
if (plane0 & 0x80000000) |
1243 |
|
|
col = mm1_color; |
1244 |
|
|
else |
1245 |
|
|
col = color; |
1246 |
|
|
} else { |
1247 |
|
|
if (plane0 & 0x80000000) |
1248 |
|
|
col = mm0_color; |
1249 |
|
|
else |
1250 |
|
|
continue; |
1251 |
|
|
} |
1252 |
|
|
if (q[i]) |
1253 |
|
|
spr_coll |= q[i] | sbit; |
1254 |
|
|
else { |
1255 |
|
|
p[i] = col; |
1256 |
|
|
q[i] = sbit; |
1257 |
|
|
} |
1258 |
|
|
} |
1259 |
|
|
|
1260 |
|
|
} else { // Standard mode |
1261 |
|
|
|
1262 |
|
|
// Collision with graphics? |
1263 |
|
|
if (fore_mask & sdata) { |
1264 |
|
|
gfx_coll |= sbit; |
1265 |
|
|
if (mdp & sbit) |
1266 |
|
|
sdata &= ~fore_mask; // Mask sprite if in background |
1267 |
|
|
} |
1268 |
|
|
|
1269 |
|
|
// Paint sprite |
1270 |
|
|
for (i=0; i<24; i++, sdata<<=1) |
1271 |
|
|
if (sdata & 0x80000000) { |
1272 |
|
|
if (q[i]) { // Collision with sprite? |
1273 |
|
|
spr_coll |= q[i] | sbit; |
1274 |
|
|
} else { // Draw pixel if no collision |
1275 |
|
|
p[i] = color; |
1276 |
|
|
q[i] = sbit; |
1277 |
|
|
} |
1278 |
|
|
} |
1279 |
|
|
} |
1280 |
|
|
} |
1281 |
|
|
} |
1282 |
|
|
} |
1283 |
|
|
|
1284 |
|
|
if (ThePrefs.SpriteCollisions) { |
1285 |
|
|
|
1286 |
|
|
// Check sprite-sprite collisions |
1287 |
|
|
if (clx_spr) |
1288 |
|
|
clx_spr |= spr_coll; |
1289 |
|
|
else { |
1290 |
|
|
clx_spr |= spr_coll; |
1291 |
|
|
irq_flag |= 0x04; |
1292 |
|
|
if (irq_mask & 0x04) { |
1293 |
|
|
irq_flag |= 0x80; |
1294 |
|
|
the_cpu->TriggerVICIRQ(); |
1295 |
|
|
} |
1296 |
|
|
} |
1297 |
|
|
|
1298 |
|
|
// Check sprite-background collisions |
1299 |
|
|
if (clx_bgr) |
1300 |
|
|
clx_bgr |= gfx_coll; |
1301 |
|
|
else { |
1302 |
|
|
clx_bgr |= gfx_coll; |
1303 |
|
|
irq_flag |= 0x02; |
1304 |
|
|
if (irq_mask & 0x02) { |
1305 |
|
|
irq_flag |= 0x80; |
1306 |
|
|
the_cpu->TriggerVICIRQ(); |
1307 |
|
|
} |
1308 |
|
|
} |
1309 |
|
|
} |
1310 |
|
|
} |
1311 |
|
|
|
1312 |
|
|
|
1313 |
|
|
#ifdef __POWERPC__ |
1314 |
|
|
static asm void fastcopy(register uchar *dst, register uchar *src); |
1315 |
|
|
static asm void fastcopy(register uchar *dst, register uchar *src) |
1316 |
|
|
{ |
1317 |
|
|
lfd fp0,0(src) |
1318 |
|
|
lfd fp1,8(src) |
1319 |
|
|
lfd fp2,16(src) |
1320 |
|
|
lfd fp3,24(src) |
1321 |
|
|
lfd fp4,32(src) |
1322 |
|
|
lfd fp5,40(src) |
1323 |
|
|
lfd fp6,48(src) |
1324 |
|
|
lfd fp7,56(src) |
1325 |
|
|
addi src,src,64 |
1326 |
|
|
stfd fp0,0(dst) |
1327 |
|
|
stfd fp1,8(dst) |
1328 |
|
|
stfd fp2,16(dst) |
1329 |
|
|
stfd fp3,24(dst) |
1330 |
|
|
stfd fp4,32(dst) |
1331 |
|
|
stfd fp5,40(dst) |
1332 |
|
|
stfd fp6,48(dst) |
1333 |
|
|
stfd fp7,56(dst) |
1334 |
|
|
addi dst,dst,64 |
1335 |
|
|
|
1336 |
|
|
lfd fp0,0(src) |
1337 |
|
|
lfd fp1,8(src) |
1338 |
|
|
lfd fp2,16(src) |
1339 |
|
|
lfd fp3,24(src) |
1340 |
|
|
lfd fp4,32(src) |
1341 |
|
|
lfd fp5,40(src) |
1342 |
|
|
lfd fp6,48(src) |
1343 |
|
|
lfd fp7,56(src) |
1344 |
|
|
addi src,src,64 |
1345 |
|
|
stfd fp0,0(dst) |
1346 |
|
|
stfd fp1,8(dst) |
1347 |
|
|
stfd fp2,16(dst) |
1348 |
|
|
stfd fp3,24(dst) |
1349 |
|
|
stfd fp4,32(dst) |
1350 |
|
|
stfd fp5,40(dst) |
1351 |
|
|
stfd fp6,48(dst) |
1352 |
|
|
stfd fp7,56(dst) |
1353 |
|
|
addi dst,dst,64 |
1354 |
|
|
|
1355 |
|
|
lfd fp0,0(src) |
1356 |
|
|
lfd fp1,8(src) |
1357 |
|
|
lfd fp2,16(src) |
1358 |
|
|
lfd fp3,24(src) |
1359 |
|
|
lfd fp4,32(src) |
1360 |
|
|
lfd fp5,40(src) |
1361 |
|
|
lfd fp6,48(src) |
1362 |
|
|
lfd fp7,56(src) |
1363 |
|
|
addi src,src,64 |
1364 |
|
|
stfd fp0,0(dst) |
1365 |
|
|
stfd fp1,8(dst) |
1366 |
|
|
stfd fp2,16(dst) |
1367 |
|
|
stfd fp3,24(dst) |
1368 |
|
|
stfd fp4,32(dst) |
1369 |
|
|
stfd fp5,40(dst) |
1370 |
|
|
stfd fp6,48(dst) |
1371 |
|
|
stfd fp7,56(dst) |
1372 |
|
|
addi dst,dst,64 |
1373 |
|
|
|
1374 |
|
|
lfd fp0,0(src) |
1375 |
|
|
lfd fp1,8(src) |
1376 |
|
|
lfd fp2,16(src) |
1377 |
|
|
lfd fp3,24(src) |
1378 |
|
|
lfd fp4,32(src) |
1379 |
|
|
lfd fp5,40(src) |
1380 |
|
|
lfd fp6,48(src) |
1381 |
|
|
lfd fp7,56(src) |
1382 |
|
|
addi src,src,64 |
1383 |
|
|
stfd fp0,0(dst) |
1384 |
|
|
stfd fp1,8(dst) |
1385 |
|
|
stfd fp2,16(dst) |
1386 |
|
|
stfd fp3,24(dst) |
1387 |
|
|
stfd fp4,32(dst) |
1388 |
|
|
stfd fp5,40(dst) |
1389 |
|
|
stfd fp6,48(dst) |
1390 |
|
|
stfd fp7,56(dst) |
1391 |
|
|
addi dst,dst,64 |
1392 |
|
|
|
1393 |
|
|
lfd fp0,0(src) |
1394 |
|
|
lfd fp1,8(src) |
1395 |
|
|
lfd fp2,16(src) |
1396 |
|
|
lfd fp3,24(src) |
1397 |
|
|
lfd fp4,32(src) |
1398 |
|
|
lfd fp5,40(src) |
1399 |
|
|
lfd fp6,48(src) |
1400 |
|
|
lfd fp7,56(src) |
1401 |
|
|
addi src,src,64 |
1402 |
|
|
stfd fp0,0(dst) |
1403 |
|
|
stfd fp1,8(dst) |
1404 |
|
|
stfd fp2,16(dst) |
1405 |
|
|
stfd fp3,24(dst) |
1406 |
|
|
stfd fp4,32(dst) |
1407 |
|
|
stfd fp5,40(dst) |
1408 |
|
|
stfd fp6,48(dst) |
1409 |
|
|
stfd fp7,56(dst) |
1410 |
|
|
addi dst,dst,64 |
1411 |
|
|
|
1412 |
|
|
lfd fp0,0(src) |
1413 |
|
|
lfd fp1,8(src) |
1414 |
|
|
lfd fp2,16(src) |
1415 |
|
|
lfd fp3,24(src) |
1416 |
|
|
lfd fp4,32(src) |
1417 |
|
|
lfd fp5,40(src) |
1418 |
|
|
lfd fp6,48(src) |
1419 |
|
|
lfd fp7,56(src) |
1420 |
|
|
addi src,src,64 |
1421 |
|
|
stfd fp0,0(dst) |
1422 |
|
|
stfd fp1,8(dst) |
1423 |
|
|
stfd fp2,16(dst) |
1424 |
|
|
stfd fp3,24(dst) |
1425 |
|
|
stfd fp4,32(dst) |
1426 |
|
|
stfd fp5,40(dst) |
1427 |
|
|
stfd fp6,48(dst) |
1428 |
|
|
stfd fp7,56(dst) |
1429 |
|
|
addi dst,dst,64 |
1430 |
|
|
blr |
1431 |
|
|
} |
1432 |
|
|
#endif |
1433 |
|
|
|
1434 |
|
|
|
1435 |
|
|
/* |
1436 |
|
|
* Emulate one clock cycle, returns true if new raster line has started |
1437 |
|
|
*/ |
1438 |
|
|
|
1439 |
|
|
// Set BA low |
1440 |
|
|
#define SetBALow \ |
1441 |
|
|
if (!the_cpu->BALow) { \ |
1442 |
|
|
first_ba_cycle = the_c64->CycleCounter; \ |
1443 |
|
|
the_cpu->BALow = true; \ |
1444 |
|
|
} |
1445 |
|
|
|
1446 |
|
|
// Turn on display if Bad Line |
1447 |
|
|
#define DisplayIfBadLine \ |
1448 |
|
|
if (is_bad_line) \ |
1449 |
|
|
display_state = true; |
1450 |
|
|
|
1451 |
|
|
// Turn on display and matrix access if Bad Line |
1452 |
|
|
#define FetchIfBadLine \ |
1453 |
|
|
if (is_bad_line) { \ |
1454 |
|
|
display_state = true; \ |
1455 |
|
|
SetBALow; \ |
1456 |
|
|
} |
1457 |
|
|
|
1458 |
|
|
// Turn on display and matrix access and reset RC if Bad Line |
1459 |
|
|
#define RCIfBadLine \ |
1460 |
|
|
if (is_bad_line) { \ |
1461 |
|
|
display_state = true; \ |
1462 |
|
|
rc = 0; \ |
1463 |
|
|
SetBALow; \ |
1464 |
|
|
} |
1465 |
|
|
|
1466 |
|
|
// Idle access |
1467 |
|
|
#define IdleAccess \ |
1468 |
|
|
read_byte(0x3fff) |
1469 |
|
|
|
1470 |
|
|
// Refresh access |
1471 |
|
|
#define RefreshAccess \ |
1472 |
|
|
read_byte(0x3f00 | ref_cnt--) |
1473 |
|
|
|
1474 |
|
|
// Turn on sprite DMA if necessary |
1475 |
|
|
#define CheckSpriteDMA \ |
1476 |
|
|
mask = 1; \ |
1477 |
|
|
for (i=0; i<8; i++, mask<<=1) \ |
1478 |
|
|
if ((me & mask) && (raster_y & 0xff) == my[i]) { \ |
1479 |
|
|
spr_dma_on |= mask; \ |
1480 |
|
|
mc_base[i] = 0; \ |
1481 |
|
|
if (mye & mask) \ |
1482 |
|
|
spr_exp_y &= ~mask; \ |
1483 |
|
|
} |
1484 |
|
|
|
1485 |
|
|
// Fetch sprite data pointer |
1486 |
|
|
#define SprPtrAccess(num) \ |
1487 |
|
|
spr_ptr[num] = read_byte(matrix_base | 0x03f8 | num) << 6; |
1488 |
|
|
|
1489 |
|
|
// Fetch sprite data, increment data counter |
1490 |
|
|
#define SprDataAccess(num, bytenum) \ |
1491 |
|
|
if (spr_dma_on & (1 << num)) { \ |
1492 |
|
|
spr_data[num][bytenum] = read_byte(mc[num] & 0x3f | spr_ptr[num]); \ |
1493 |
|
|
mc[num]++; \ |
1494 |
|
|
} else if (bytenum == 1) \ |
1495 |
|
|
IdleAccess; |
1496 |
|
|
|
1497 |
|
|
// Sample border color and increment chunky_ptr and fore_mask_ptr |
1498 |
|
|
#define SampleBorder \ |
1499 |
|
|
if (draw_this_line) { \ |
1500 |
|
|
if (border_on) \ |
1501 |
|
|
border_color_sample[cycle-13] = ec_color; \ |
1502 |
|
|
chunky_ptr += 8; \ |
1503 |
|
|
fore_mask_ptr++; \ |
1504 |
|
|
} |
1505 |
|
|
|
1506 |
|
|
|
1507 |
|
|
bool MOS6569::EmulateCycle(void) |
1508 |
|
|
{ |
1509 |
|
|
uint8 mask; |
1510 |
|
|
int i; |
1511 |
|
|
|
1512 |
|
|
switch (cycle) { |
1513 |
|
|
|
1514 |
|
|
// Fetch sprite pointer 3, increment raster counter, trigger raster IRQ, |
1515 |
|
|
// test for Bad Line, reset BA if sprites 3 and 4 off, read data of sprite 3 |
1516 |
|
|
case 1: |
1517 |
|
|
if (raster_y == TOTAL_RASTERS-1) |
1518 |
|
|
|
1519 |
|
|
// Trigger VBlank in cycle 2 |
1520 |
|
|
vblanking = true; |
1521 |
|
|
|
1522 |
|
|
else { |
1523 |
|
|
|
1524 |
|
|
// Increment raster counter |
1525 |
|
|
raster_y++; |
1526 |
|
|
|
1527 |
|
|
// Trigger raster IRQ if IRQ line reached |
1528 |
|
|
if (raster_y == irq_raster) |
1529 |
|
|
raster_irq(); |
1530 |
|
|
|
1531 |
|
|
// In line $30, the DEN bit controls if Bad Lines can occur |
1532 |
|
|
if (raster_y == 0x30) |
1533 |
|
|
bad_lines_enabled = ctrl1 & 0x10; |
1534 |
|
|
|
1535 |
|
|
// Bad Line condition? |
1536 |
|
|
is_bad_line = (raster_y >= FIRST_DMA_LINE && raster_y <= LAST_DMA_LINE && ((raster_y & 7) == y_scroll) && bad_lines_enabled); |
1537 |
|
|
|
1538 |
|
|
// Don't draw all lines, hide some at the top and bottom |
1539 |
|
|
draw_this_line = (raster_y >= FIRST_DISP_LINE && raster_y <= LAST_DISP_LINE && !frame_skipped); |
1540 |
|
|
} |
1541 |
|
|
|
1542 |
|
|
// First sample of border state |
1543 |
|
|
border_on_sample[0] = border_on; |
1544 |
|
|
|
1545 |
|
|
SprPtrAccess(3); |
1546 |
|
|
SprDataAccess(3, 0); |
1547 |
|
|
DisplayIfBadLine; |
1548 |
|
|
if (!(spr_dma_on & 0x18)) |
1549 |
|
|
the_cpu->BALow = false; |
1550 |
|
|
break; |
1551 |
|
|
|
1552 |
|
|
// Set BA for sprite 5, read data of sprite 3 |
1553 |
|
|
case 2: |
1554 |
|
|
if (vblanking) { |
1555 |
|
|
|
1556 |
|
|
// Vertical blank, reset counters |
1557 |
|
|
raster_y = vc_base = 0; |
1558 |
|
|
ref_cnt = 0xff; |
1559 |
|
|
lp_triggered = vblanking = false; |
1560 |
|
|
|
1561 |
|
|
if (!(frame_skipped = --skip_counter)) |
1562 |
|
|
skip_counter = ThePrefs.SkipFrames; |
1563 |
|
|
|
1564 |
|
|
the_c64->VBlank(!frame_skipped); |
1565 |
|
|
|
1566 |
|
|
// Get bitmap pointer for next frame. This must be done |
1567 |
|
|
// after calling the_c64->VBlank() because the preferences |
1568 |
|
|
// and screen configuration may have been changed there |
1569 |
|
|
chunky_line_start = the_display->BitmapBase(); |
1570 |
|
|
xmod = the_display->BitmapXMod(); |
1571 |
|
|
|
1572 |
|
|
// Trigger raster IRQ if IRQ in line 0 |
1573 |
|
|
if (irq_raster == 0) |
1574 |
|
|
raster_irq(); |
1575 |
|
|
|
1576 |
|
|
} |
1577 |
|
|
|
1578 |
|
|
// Our output goes here |
1579 |
|
|
#ifdef __POWERPC__ |
1580 |
|
|
chunky_ptr = (uint8 *)chunky_tmp; |
1581 |
|
|
#else |
1582 |
|
|
chunky_ptr = chunky_line_start; |
1583 |
|
|
#endif |
1584 |
|
|
|
1585 |
|
|
// Clear foreground mask |
1586 |
|
|
memset(fore_mask_buf, 0, DISPLAY_X/8); |
1587 |
|
|
fore_mask_ptr = fore_mask_buf; |
1588 |
|
|
|
1589 |
|
|
SprDataAccess(3,1); |
1590 |
|
|
SprDataAccess(3,2); |
1591 |
|
|
DisplayIfBadLine; |
1592 |
|
|
if (spr_dma_on & 0x20) |
1593 |
|
|
SetBALow; |
1594 |
|
|
break; |
1595 |
|
|
|
1596 |
|
|
// Fetch sprite pointer 4, reset BA is sprite 4 and 5 off |
1597 |
|
|
case 3: |
1598 |
|
|
SprPtrAccess(4); |
1599 |
|
|
SprDataAccess(4, 0); |
1600 |
|
|
DisplayIfBadLine; |
1601 |
|
|
if (!(spr_dma_on & 0x30)) |
1602 |
|
|
the_cpu->BALow = false; |
1603 |
|
|
break; |
1604 |
|
|
|
1605 |
|
|
// Set BA for sprite 6, read data of sprite 4 |
1606 |
|
|
case 4: |
1607 |
|
|
SprDataAccess(4, 1); |
1608 |
|
|
SprDataAccess(4, 2); |
1609 |
|
|
DisplayIfBadLine; |
1610 |
|
|
if (spr_dma_on & 0x40) |
1611 |
|
|
SetBALow; |
1612 |
|
|
break; |
1613 |
|
|
|
1614 |
|
|
// Fetch sprite pointer 5, reset BA if sprite 5 and 6 off |
1615 |
|
|
case 5: |
1616 |
|
|
SprPtrAccess(5); |
1617 |
|
|
SprDataAccess(5, 0); |
1618 |
|
|
DisplayIfBadLine; |
1619 |
|
|
if (!(spr_dma_on & 0x60)) |
1620 |
|
|
the_cpu->BALow = false; |
1621 |
|
|
break; |
1622 |
|
|
|
1623 |
|
|
// Set BA for sprite 7, read data of sprite 5 |
1624 |
|
|
case 6: |
1625 |
|
|
SprDataAccess(5, 1); |
1626 |
|
|
SprDataAccess(5, 2); |
1627 |
|
|
DisplayIfBadLine; |
1628 |
|
|
if (spr_dma_on & 0x80) |
1629 |
|
|
SetBALow; |
1630 |
|
|
break; |
1631 |
|
|
|
1632 |
|
|
// Fetch sprite pointer 6, reset BA if sprite 6 and 7 off |
1633 |
|
|
case 7: |
1634 |
|
|
SprPtrAccess(6); |
1635 |
|
|
SprDataAccess(6, 0); |
1636 |
|
|
DisplayIfBadLine; |
1637 |
|
|
if (!(spr_dma_on & 0xc0)) |
1638 |
|
|
the_cpu->BALow = false; |
1639 |
|
|
break; |
1640 |
|
|
|
1641 |
|
|
// Read data of sprite 6 |
1642 |
|
|
case 8: |
1643 |
|
|
SprDataAccess(6, 1); |
1644 |
|
|
SprDataAccess(6, 2); |
1645 |
|
|
DisplayIfBadLine; |
1646 |
|
|
break; |
1647 |
|
|
|
1648 |
|
|
// Fetch sprite pointer 7, reset BA if sprite 7 off |
1649 |
|
|
case 9: |
1650 |
|
|
SprPtrAccess(7); |
1651 |
|
|
SprDataAccess(7, 0); |
1652 |
|
|
DisplayIfBadLine; |
1653 |
|
|
if (!(spr_dma_on & 0x80)) |
1654 |
|
|
the_cpu->BALow = false; |
1655 |
|
|
break; |
1656 |
|
|
|
1657 |
|
|
// Read data of sprite 7 |
1658 |
|
|
case 10: |
1659 |
|
|
SprDataAccess(7, 1); |
1660 |
|
|
SprDataAccess(7, 2); |
1661 |
|
|
DisplayIfBadLine; |
1662 |
|
|
break; |
1663 |
|
|
|
1664 |
|
|
// Refresh, reset BA |
1665 |
|
|
case 11: |
1666 |
|
|
RefreshAccess; |
1667 |
|
|
DisplayIfBadLine; |
1668 |
|
|
the_cpu->BALow = false; |
1669 |
|
|
break; |
1670 |
|
|
|
1671 |
|
|
// Refresh, turn on matrix access if Bad Line |
1672 |
|
|
case 12: |
1673 |
|
|
RefreshAccess; |
1674 |
|
|
FetchIfBadLine; |
1675 |
|
|
break; |
1676 |
|
|
|
1677 |
|
|
// Refresh, turn on matrix access if Bad Line, reset raster_x, graphics display starts here |
1678 |
|
|
case 13: |
1679 |
|
|
draw_background(); |
1680 |
|
|
SampleBorder; |
1681 |
|
|
RefreshAccess; |
1682 |
|
|
FetchIfBadLine; |
1683 |
|
|
raster_x = 0xfffc; |
1684 |
|
|
break; |
1685 |
|
|
|
1686 |
|
|
// Refresh, VCBASE->VCCOUNT, turn on matrix access and reset RC if Bad Line |
1687 |
|
|
case 14: |
1688 |
|
|
draw_background(); |
1689 |
|
|
SampleBorder; |
1690 |
|
|
RefreshAccess; |
1691 |
|
|
RCIfBadLine; |
1692 |
|
|
vc = vc_base; |
1693 |
|
|
break; |
1694 |
|
|
|
1695 |
|
|
// Refresh and matrix access, increment mc_base by 2 if y expansion flipflop is set |
1696 |
|
|
case 15: |
1697 |
|
|
draw_background(); |
1698 |
|
|
SampleBorder; |
1699 |
|
|
RefreshAccess; |
1700 |
|
|
FetchIfBadLine; |
1701 |
|
|
|
1702 |
|
|
for (i=0; i<8; i++) |
1703 |
|
|
if (spr_exp_y & (1 << i)) |
1704 |
|
|
mc_base[i] += 2; |
1705 |
|
|
|
1706 |
|
|
ml_index = 0; |
1707 |
|
|
matrix_access(); |
1708 |
|
|
break; |
1709 |
|
|
|
1710 |
|
|
// Graphics and matrix access, increment mc_base by 1 if y expansion flipflop is set |
1711 |
|
|
// and check if sprite DMA can be turned off |
1712 |
|
|
case 16: |
1713 |
|
|
draw_background(); |
1714 |
|
|
SampleBorder; |
1715 |
|
|
graphics_access(); |
1716 |
|
|
FetchIfBadLine; |
1717 |
|
|
|
1718 |
|
|
mask = 1; |
1719 |
|
|
for (i=0; i<8; i++, mask<<=1) { |
1720 |
|
|
if (spr_exp_y & mask) |
1721 |
|
|
mc_base[i]++; |
1722 |
|
|
if ((mc_base[i] & 0x3f) == 0x3f) |
1723 |
|
|
spr_dma_on &= ~mask; |
1724 |
|
|
} |
1725 |
|
|
|
1726 |
|
|
matrix_access(); |
1727 |
|
|
break; |
1728 |
|
|
|
1729 |
|
|
// Graphics and matrix access, turn off border in 40 column mode, display window starts here |
1730 |
|
|
case 17: |
1731 |
|
|
if (ctrl2 & 8) { |
1732 |
|
|
if (raster_y == dy_stop) |
1733 |
|
|
ud_border_on = true; |
1734 |
|
|
else { |
1735 |
|
|
if (ctrl1 & 0x10) { |
1736 |
|
|
if (raster_y == dy_start) |
1737 |
|
|
border_on = ud_border_on = false; |
1738 |
|
|
else |
1739 |
|
|
if (!ud_border_on) |
1740 |
|
|
border_on = false; |
1741 |
|
|
} else |
1742 |
|
|
if (!ud_border_on) |
1743 |
|
|
border_on = false; |
1744 |
|
|
} |
1745 |
|
|
} |
1746 |
|
|
|
1747 |
|
|
// Second sample of border state |
1748 |
|
|
border_on_sample[1] = border_on; |
1749 |
|
|
|
1750 |
|
|
draw_background(); |
1751 |
|
|
draw_graphics(); |
1752 |
|
|
SampleBorder; |
1753 |
|
|
graphics_access(); |
1754 |
|
|
FetchIfBadLine; |
1755 |
|
|
matrix_access(); |
1756 |
|
|
break; |
1757 |
|
|
|
1758 |
|
|
// Turn off border in 38 column mode |
1759 |
|
|
case 18: |
1760 |
|
|
if (!(ctrl2 & 8)) { |
1761 |
|
|
if (raster_y == dy_stop) |
1762 |
|
|
ud_border_on = true; |
1763 |
|
|
else { |
1764 |
|
|
if (ctrl1 & 0x10) { |
1765 |
|
|
if (raster_y == dy_start) |
1766 |
|
|
border_on = ud_border_on = false; |
1767 |
|
|
else |
1768 |
|
|
if (!ud_border_on) |
1769 |
|
|
border_on = false; |
1770 |
|
|
} else |
1771 |
|
|
if (!ud_border_on) |
1772 |
|
|
border_on = false; |
1773 |
|
|
} |
1774 |
|
|
} |
1775 |
|
|
|
1776 |
|
|
// Third sample of border state |
1777 |
|
|
border_on_sample[2] = border_on; |
1778 |
|
|
|
1779 |
|
|
// Falls through |
1780 |
|
|
|
1781 |
|
|
// Graphics and matrix access |
1782 |
|
|
case 19: case 20: case 21: case 22: case 23: case 24: |
1783 |
|
|
case 25: case 26: case 27: case 28: case 29: case 30: |
1784 |
|
|
case 31: case 32: case 33: case 34: case 35: case 36: |
1785 |
|
|
case 37: case 38: case 39: case 40: case 41: case 42: |
1786 |
|
|
case 43: case 44: case 45: case 46: case 47: case 48: |
1787 |
|
|
case 49: case 50: case 51: case 52: case 53: case 54: // Gnagna... |
1788 |
|
|
draw_graphics(); |
1789 |
|
|
SampleBorder; |
1790 |
|
|
graphics_access(); |
1791 |
|
|
FetchIfBadLine; |
1792 |
|
|
matrix_access(); |
1793 |
|
|
last_char_data = char_data; |
1794 |
|
|
break; |
1795 |
|
|
|
1796 |
|
|
// Last graphics access, turn off matrix access, turn on sprite DMA if Y coordinate is |
1797 |
|
|
// right and sprite is enabled, handle sprite y expansion, set BA for sprite 0 |
1798 |
|
|
case 55: |
1799 |
|
|
draw_graphics(); |
1800 |
|
|
SampleBorder; |
1801 |
|
|
graphics_access(); |
1802 |
|
|
DisplayIfBadLine; |
1803 |
|
|
|
1804 |
|
|
// Invert y expansion flipflop if bit in MYE is set |
1805 |
|
|
mask = 1; |
1806 |
|
|
for (i=0; i<8; i++, mask<<=1) |
1807 |
|
|
if (mye & mask) |
1808 |
|
|
spr_exp_y ^= mask; |
1809 |
|
|
CheckSpriteDMA; |
1810 |
|
|
|
1811 |
|
|
if (spr_dma_on & 0x01) { // Don't remove these braces! |
1812 |
|
|
SetBALow; |
1813 |
|
|
} else |
1814 |
|
|
the_cpu->BALow = false; |
1815 |
|
|
break; |
1816 |
|
|
|
1817 |
|
|
// Turn on border in 38 column mode, turn on sprite DMA if Y coordinate is right and |
1818 |
|
|
// sprite is enabled, set BA for sprite 0, display window ends here |
1819 |
|
|
case 56: |
1820 |
|
|
if (!(ctrl2 & 8)) |
1821 |
|
|
border_on = true; |
1822 |
|
|
|
1823 |
|
|
// Fourth sample of border state |
1824 |
|
|
border_on_sample[3] = border_on; |
1825 |
|
|
|
1826 |
|
|
draw_graphics(); |
1827 |
|
|
SampleBorder; |
1828 |
|
|
IdleAccess; |
1829 |
|
|
DisplayIfBadLine; |
1830 |
|
|
CheckSpriteDMA; |
1831 |
|
|
|
1832 |
|
|
if (spr_dma_on & 0x01) |
1833 |
|
|
SetBALow; |
1834 |
|
|
break; |
1835 |
|
|
|
1836 |
|
|
// Turn on border in 40 column mode, set BA for sprite 1, paint sprites |
1837 |
|
|
case 57: |
1838 |
|
|
if (ctrl2 & 8) |
1839 |
|
|
border_on = true; |
1840 |
|
|
|
1841 |
|
|
// Fifth sample of border state |
1842 |
|
|
border_on_sample[4] = border_on; |
1843 |
|
|
|
1844 |
|
|
// Sample spr_disp_on and spr_data for sprite drawing |
1845 |
|
|
if ((spr_draw = spr_disp_on)) |
1846 |
|
|
memcpy(spr_draw_data, spr_data, 8*4); |
1847 |
|
|
|
1848 |
|
|
// Turn off sprite display if DMA is off |
1849 |
|
|
mask = 1; |
1850 |
|
|
for (i=0; i<8; i++, mask<<=1) |
1851 |
|
|
if ((spr_disp_on & mask) && !(spr_dma_on & mask)) |
1852 |
|
|
spr_disp_on &= ~mask; |
1853 |
|
|
|
1854 |
|
|
draw_background(); |
1855 |
|
|
SampleBorder; |
1856 |
|
|
IdleAccess; |
1857 |
|
|
DisplayIfBadLine; |
1858 |
|
|
if (spr_dma_on & 0x02) |
1859 |
|
|
SetBALow; |
1860 |
|
|
break; |
1861 |
|
|
|
1862 |
|
|
// Fetch sprite pointer 0, mc_base->mc, turn on sprite display if necessary, |
1863 |
|
|
// turn off display if RC=7, read data of sprite 0 |
1864 |
|
|
case 58: |
1865 |
|
|
draw_background(); |
1866 |
|
|
SampleBorder; |
1867 |
|
|
|
1868 |
|
|
mask = 1; |
1869 |
|
|
for (i=0; i<8; i++, mask<<=1) { |
1870 |
|
|
mc[i] = mc_base[i]; |
1871 |
|
|
if ((spr_dma_on & mask) && (raster_y & 0xff) == my[i]) |
1872 |
|
|
spr_disp_on |= mask; |
1873 |
|
|
} |
1874 |
|
|
SprPtrAccess(0); |
1875 |
|
|
SprDataAccess(0, 0); |
1876 |
|
|
|
1877 |
|
|
if (rc == 7) { |
1878 |
|
|
vc_base = vc; |
1879 |
|
|
display_state = false; |
1880 |
|
|
} |
1881 |
|
|
if (is_bad_line || display_state) { |
1882 |
|
|
display_state = true; |
1883 |
|
|
rc = (rc + 1) & 7; |
1884 |
|
|
} |
1885 |
|
|
break; |
1886 |
|
|
|
1887 |
|
|
// Set BA for sprite 2, read data of sprite 0 |
1888 |
|
|
case 59: |
1889 |
|
|
draw_background(); |
1890 |
|
|
SampleBorder; |
1891 |
|
|
SprDataAccess(0, 1); |
1892 |
|
|
SprDataAccess(0, 2); |
1893 |
|
|
DisplayIfBadLine; |
1894 |
|
|
if (spr_dma_on & 0x04) |
1895 |
|
|
SetBALow; |
1896 |
|
|
break; |
1897 |
|
|
|
1898 |
|
|
// Fetch sprite pointer 1, reset BA if sprite 1 and 2 off, graphics display ends here |
1899 |
|
|
case 60: |
1900 |
|
|
draw_background(); |
1901 |
|
|
SampleBorder; |
1902 |
|
|
|
1903 |
|
|
if (draw_this_line) { |
1904 |
|
|
|
1905 |
|
|
// Draw sprites |
1906 |
|
|
if (spr_draw && ThePrefs.SpritesOn) |
1907 |
|
|
draw_sprites(); |
1908 |
|
|
|
1909 |
|
|
// Draw border |
1910 |
|
|
#ifdef __POWERPC__ |
1911 |
|
|
if (border_on_sample[0]) |
1912 |
|
|
for (i=0; i<4; i++) |
1913 |
|
|
memset8((uint8 *)chunky_tmp+i*8, border_color_sample[i]); |
1914 |
|
|
if (border_on_sample[1]) |
1915 |
|
|
memset8((uint8 *)chunky_tmp+4*8, border_color_sample[4]); |
1916 |
|
|
if (border_on_sample[2]) |
1917 |
|
|
for (i=5; i<43; i++) |
1918 |
|
|
memset8((uint8 *)chunky_tmp+i*8, border_color_sample[i]); |
1919 |
|
|
if (border_on_sample[3]) |
1920 |
|
|
memset8((uint8 *)chunky_tmp+43*8, border_color_sample[43]); |
1921 |
|
|
if (border_on_sample[4]) |
1922 |
|
|
for (i=44; i<DISPLAY_X/8; i++) |
1923 |
|
|
memset8((uint8 *)chunky_tmp+i*8, border_color_sample[i]); |
1924 |
|
|
#else |
1925 |
|
|
if (border_on_sample[0]) |
1926 |
|
|
for (i=0; i<4; i++) |
1927 |
|
|
memset8(chunky_line_start+i*8, border_color_sample[i]); |
1928 |
|
|
if (border_on_sample[1]) |
1929 |
|
|
memset8(chunky_line_start+4*8, border_color_sample[4]); |
1930 |
|
|
if (border_on_sample[2]) |
1931 |
|
|
for (i=5; i<43; i++) |
1932 |
|
|
memset8(chunky_line_start+i*8, border_color_sample[i]); |
1933 |
|
|
if (border_on_sample[3]) |
1934 |
|
|
memset8(chunky_line_start+43*8, border_color_sample[43]); |
1935 |
|
|
if (border_on_sample[4]) |
1936 |
|
|
for (i=44; i<DISPLAY_X/8; i++) |
1937 |
|
|
memset8(chunky_line_start+i*8, border_color_sample[i]); |
1938 |
|
|
#endif |
1939 |
|
|
|
1940 |
|
|
#ifdef __POWERPC__ |
1941 |
|
|
// Copy temporary buffer to bitmap |
1942 |
|
|
fastcopy(chunky_line_start, (uint8 *)chunky_tmp); |
1943 |
|
|
#endif |
1944 |
|
|
|
1945 |
|
|
// Increment pointer in chunky buffer |
1946 |
|
|
chunky_line_start += xmod; |
1947 |
|
|
} |
1948 |
|
|
|
1949 |
|
|
SprPtrAccess(1); |
1950 |
|
|
SprDataAccess(1, 0); |
1951 |
|
|
DisplayIfBadLine; |
1952 |
|
|
if (!(spr_dma_on & 0x06)) |
1953 |
|
|
the_cpu->BALow = false; |
1954 |
|
|
break; |
1955 |
|
|
|
1956 |
|
|
// Set BA for sprite 3, read data of sprite 1 |
1957 |
|
|
case 61: |
1958 |
|
|
SprDataAccess(1, 1); |
1959 |
|
|
SprDataAccess(1, 2); |
1960 |
|
|
DisplayIfBadLine; |
1961 |
|
|
if (spr_dma_on & 0x08) |
1962 |
|
|
SetBALow; |
1963 |
|
|
break; |
1964 |
|
|
|
1965 |
|
|
// Read sprite pointer 2, reset BA if sprite 2 and 3 off, read data of sprite 2 |
1966 |
|
|
case 62: |
1967 |
|
|
SprPtrAccess(2); |
1968 |
|
|
SprDataAccess(2, 0); |
1969 |
|
|
DisplayIfBadLine; |
1970 |
|
|
if (!(spr_dma_on & 0x0c)) |
1971 |
|
|
the_cpu->BALow = false; |
1972 |
|
|
break; |
1973 |
|
|
|
1974 |
|
|
// Set BA for sprite 4, read data of sprite 2 |
1975 |
|
|
case 63: |
1976 |
|
|
SprDataAccess(2, 1); |
1977 |
|
|
SprDataAccess(2, 2); |
1978 |
|
|
DisplayIfBadLine; |
1979 |
|
|
|
1980 |
|
|
if (raster_y == dy_stop) |
1981 |
|
|
ud_border_on = true; |
1982 |
|
|
else |
1983 |
|
|
if (ctrl1 & 0x10 && raster_y == dy_start) |
1984 |
|
|
ud_border_on = false; |
1985 |
|
|
|
1986 |
|
|
if (spr_dma_on & 0x10) |
1987 |
|
|
SetBALow; |
1988 |
|
|
|
1989 |
|
|
// Last cycle |
1990 |
|
|
raster_x += 8; |
1991 |
|
|
cycle = 1; |
1992 |
|
|
return true; |
1993 |
|
|
} |
1994 |
|
|
|
1995 |
|
|
// Next cycle |
1996 |
|
|
raster_x += 8; |
1997 |
|
|
cycle++; |
1998 |
|
|
return false; |
1999 |
|
|
} |