1 /*
2 * blitter.cpp - Atari Blitter emulation code
3 *
4 * Copyright (c) 2001-2004 Petr Stehlik of ARAnyM dev team (see AUTHORS)
5 *
6 * Based on work by Martin Griffiths for the STonX, see below.
7 *
8 * This file is part of the ARAnyM project which builds a new and powerful
9 * TOS/FreeMiNT compatible virtual machine running on almost any hardware.
10 *
11 * ARAnyM is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * ARAnyM is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with ARAnyM; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25 /*
26 * Blitter Emulator,
27 * Martin Griffiths, 1995/96.
28 *
29 * Here lies the Atari Blitter Emulator - The 'Blitter' chip is found in
30 * the STE/MegaSTE and provides a very fast BitBlit in hardware.
31 *
32 * The hardware registers for this chip lie at addresses $ff8a00 - $ff8a3c,
33 * There seems to be a mirror for $ff8a30 used in TOS 1.02 at $ff7f30.
34 *
35 */
36
37
38 #undef BLITTER_MEMMOVE // when defined it replaces complicated logic of word-by-word copying by simple and fast memmove()
39 #undef BLITTER_SDLBLIT // when defined it accelerates screen to screen blits with host VGA hardware accelerated routines (using SDL_BlitSurface)
40
41 #include "sysdeps.h"
42 #include "hardware.h"
43 #include "cpu_emulation.h"
44 #include "memory-uae.h"
45 #include "blitter.h"
46 #include "icio.h"
47
48 #define DEBUG 0
49 #include "debug.h"
50
51 #include "SDL_compat.h"
52
53 #if DEBUG
54 #define SHOWPARAMS \
55 { fprintf(stderr,"Source Address:%X\n",source_addr); \
56 fprintf(stderr," Dest Address:%X\n",dest_addr); \
57 fprintf(stderr," X count:%X\n",x_count); \
58 fprintf(stderr," Y count:%X\n",y_count); \
59 fprintf(stderr,"Words per line:%X\n",x_count ? x_count : 65536); \
60 fprintf(stderr,"Lines per blok:%X\n",y_count ? y_count : 65536); \
61 fprintf(stderr," Source X inc:%X\n",source_x_inc); \
62 fprintf(stderr," Dest X inc:%X\n",dest_x_inc); \
63 fprintf(stderr," Source Y inc:%X\n",source_y_inc); \
64 fprintf(stderr," Dest Y inc:%X\n",dest_y_inc); \
65 fprintf(stderr,"HOP:%2X OP:%X\n",hop,op); \
66 fprintf(stderr," source SKEW:%X\n",skewreg); \
67 fprintf(stderr," endmask 1:%X\n",end_mask_1); \
68 fprintf(stderr," endmask 2:%X\n",end_mask_2); \
69 fprintf(stderr," endmask 3:%X\n",end_mask_3); \
70 fprintf(stderr," linenum:%X\n",line_num); \
71 if (NFSR) fprintf(stderr,"NFSR is Set!\n"); \
72 if (FXSR) fprintf(stderr,"FXSR is Set!\n"); \
73 }
74 #endif
75
76 typedef uint16 UW;
77 typedef uint8 UB;
78 typedef char B;
79
80 #define ADDR(a) (a)
81
BLITTER(memptr addr,uint32 size)82 BLITTER::BLITTER(memptr addr, uint32 size) : BASE_IO(addr, size)
83 {
84 reset();
85 }
86
reset()87 void BLITTER::reset()
88 {
89 // halftone_ram[16];
90 end_mask_1 = end_mask_2 = end_mask_3 = 0;
91 NFSR = FXSR = 0;
92 x_count = y_count = 0;
93 hop = op = line_num = skewreg = 0;
94 halftone_curroffset = halftone_direction = 0;
95 source_x_inc = source_y_inc = dest_x_inc = dest_y_inc = 0;
96 source_addr = 0;
97 dest_addr = 0;
98 blit = false;
99 }
100
LM_UW(memptr addr)101 UW BLITTER::LM_UW(memptr addr) {
102 return ReadAtariInt16(addr); //??
103 }
104
SM_UW(memptr addr,UW value)105 void BLITTER::SM_UW(memptr addr, UW value) {
106 if (addr <= 0x800 || (addr >= 0x0e00000 && addr < 0x1000000)) {
107 D(bug("Blitter tried to write to %06lx", addr));
108 return;
109 }
110 WriteAtariInt16(addr, value); //??
111 }
112
113
114 #define HOP_OPS(_fn_name,_op,_do_source_shift,_get_source_data,_shifted_hopd_data, _do_halftone_inc) \
115 static void _fn_name ( BLITTER& b ) \
116 { \
117 register unsigned int skew = (unsigned int) b.skewreg & 15; \
118 register unsigned int source_buffer=0; \
119 if (b.hop & 1) { \
120 if (b.line_num & 0x20) \
121 b.halftone_curroffset = b.skewreg & 15; \
122 else \
123 b.halftone_curroffset = b.line_num & 15; \
124 if (b.dest_y_inc >= 0) \
125 b.halftone_direction = 1; \
126 else \
127 b.halftone_direction = -1; \
128 } \
129 do \
130 { register UW x,dst_data,opd_data; \
131 if (b.FXSR) \
132 { _do_source_shift; \
133 _get_source_data; \
134 b.source_addr += b.source_x_inc; \
135 } \
136 _do_source_shift; \
137 _get_source_data; \
138 dst_data = b.LM_UW(ADDR(b.dest_addr)); \
139 opd_data = _shifted_hopd_data; \
140 b.SM_UW(ADDR(b.dest_addr),(dst_data & ~b.end_mask_1) | (_op & b.end_mask_1)); \
141 for(x=0 ; x<b.x_count-2 ; x++) \
142 { b.source_addr += b.source_x_inc; \
143 b.dest_addr += b.dest_x_inc; \
144 _do_source_shift; \
145 _get_source_data; \
146 dst_data = b.LM_UW(ADDR(b.dest_addr)); \
147 opd_data = _shifted_hopd_data; \
148 b.SM_UW(ADDR(b.dest_addr),(dst_data & ~b.end_mask_2) | (_op & b.end_mask_2)); \
149 } \
150 if (b.x_count >= 2) \
151 { b.dest_addr += b.dest_x_inc; \
152 _do_source_shift; \
153 if ( (!b.NFSR) || ((~(0xffff>>skew)) > b.end_mask_3) )\
154 { b.source_addr += b.source_x_inc; \
155 _get_source_data; \
156 } \
157 dst_data = b.LM_UW(ADDR(b.dest_addr)); \
158 opd_data = _shifted_hopd_data; \
159 b.SM_UW(ADDR(b.dest_addr),(((UW)dst_data) & ~b.end_mask_3) | (_op & b.end_mask_3));\
160 } \
161 b.source_addr += b.source_y_inc; \
162 b.dest_addr += b.dest_y_inc; \
163 _do_halftone_inc; \
164 (void) opd_data; \
165 (void) dst_data; \
166 } while (--b.y_count > 0); \
167 };
168
169
170 /*
171 * Some macros fixed:
172 * operations, that don't need a source, may not access the source address;
173 * the source address isn't even set up by the BIOS.
174 * This includes all HOP_0 operations (source is all ones),
175 * all HOP_1 operations (source is halftone only),
176 * and operations 0, 5, 10 and 15
177 */
178 #define _HOP_0 0xffff
179 #define _HOP_1 b.halftone_ram[b.halftone_curroffset]
180 #define _HOP_2 (source_buffer >> skew)
181 #define _HOP_3 (source_buffer >> skew) & b.halftone_ram[b.halftone_curroffset]
182
183 #define _HOP_INC b.halftone_curroffset = (b.halftone_curroffset + b.halftone_direction) & 15
184
185 #define _SRC_READ_N source_buffer |= ((unsigned int) b.LM_UW(ADDR(b.source_addr)) << 16)
186 #define _SRC_READ_P source_buffer |= ((unsigned int) b.LM_UW(ADDR(b.source_addr)))
187
188 HOP_OPS(_HOP_0_OP_00_N,(0), source_buffer >>=16, ;, _HOP_0, ;)
189 HOP_OPS(_HOP_0_OP_01_N,(opd_data & dst_data), source_buffer >>=16, ;, _HOP_0, ;)
190 HOP_OPS(_HOP_0_OP_02_N,(opd_data & ~dst_data), source_buffer >>=16, ;, _HOP_0, ;)
191 HOP_OPS(_HOP_0_OP_03_N,(opd_data), source_buffer >>=16, ;, _HOP_0, ;)
192 HOP_OPS(_HOP_0_OP_04_N,(~opd_data & dst_data), source_buffer >>=16, ;, _HOP_0, ;)
193 HOP_OPS(_HOP_0_OP_05_N,(dst_data), source_buffer >>=16, ;, _HOP_0, ;)
194 HOP_OPS(_HOP_0_OP_06_N,(opd_data ^ dst_data), source_buffer >>=16, ;, _HOP_0, ;)
195 HOP_OPS(_HOP_0_OP_07_N,(opd_data | dst_data), source_buffer >>=16, ;, _HOP_0, ;)
196 HOP_OPS(_HOP_0_OP_08_N,(~opd_data & ~dst_data), source_buffer >>=16, ;, _HOP_0, ;)
197 HOP_OPS(_HOP_0_OP_09_N,(~opd_data ^ dst_data), source_buffer >>=16, ;, _HOP_0, ;)
198 HOP_OPS(_HOP_0_OP_10_N,(~dst_data), source_buffer >>=16, ;, _HOP_0, ;)
199 HOP_OPS(_HOP_0_OP_11_N,(opd_data | ~dst_data), source_buffer >>=16, ;, _HOP_0, ;)
200 HOP_OPS(_HOP_0_OP_12_N,(~opd_data), source_buffer >>=16, ;, _HOP_0, ;)
201 HOP_OPS(_HOP_0_OP_13_N,(~opd_data | dst_data), source_buffer >>=16, ;, _HOP_0, ;)
202 HOP_OPS(_HOP_0_OP_14_N,(~opd_data | ~dst_data), source_buffer >>=16, ;, _HOP_0, ;)
203 HOP_OPS(_HOP_0_OP_15_N,(0xffff), source_buffer >>=16, ;, _HOP_0, ;)
204
205 HOP_OPS(_HOP_1_OP_00_N,(0), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
206 HOP_OPS(_HOP_1_OP_01_N,(opd_data & dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
207 HOP_OPS(_HOP_1_OP_02_N,(opd_data & ~dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
208 HOP_OPS(_HOP_1_OP_03_N,(opd_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
209 HOP_OPS(_HOP_1_OP_04_N,(~opd_data & dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
210 HOP_OPS(_HOP_1_OP_05_N,(dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
211 HOP_OPS(_HOP_1_OP_06_N,(opd_data ^ dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
212 HOP_OPS(_HOP_1_OP_07_N,(opd_data | dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
213 HOP_OPS(_HOP_1_OP_08_N,(~opd_data & ~dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
214 HOP_OPS(_HOP_1_OP_09_N,(~opd_data ^ dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
215 HOP_OPS(_HOP_1_OP_10_N,(~dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
216 HOP_OPS(_HOP_1_OP_11_N,(opd_data | ~dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
217 HOP_OPS(_HOP_1_OP_12_N,(~opd_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
218 HOP_OPS(_HOP_1_OP_13_N,(~opd_data | dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
219 HOP_OPS(_HOP_1_OP_14_N,(~opd_data | ~dst_data), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
220 HOP_OPS(_HOP_1_OP_15_N,(0xffff), source_buffer >>=16, ;, _HOP_1, _HOP_INC)
221
222 HOP_OPS(_HOP_2_OP_00_N,(0), source_buffer >>=16, ;, _HOP_2, ;)
223 HOP_OPS(_HOP_2_OP_01_N,(opd_data & dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
224 HOP_OPS(_HOP_2_OP_02_N,(opd_data & ~dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
225 HOP_OPS(_HOP_2_OP_03_N,(opd_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
226 HOP_OPS(_HOP_2_OP_04_N,(~opd_data & dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
227 HOP_OPS(_HOP_2_OP_05_N,(dst_data), source_buffer >>=16, ;, _HOP_2, ;)
228 HOP_OPS(_HOP_2_OP_06_N,(opd_data ^ dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
229 HOP_OPS(_HOP_2_OP_07_N,(opd_data | dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
230 HOP_OPS(_HOP_2_OP_08_N,(~opd_data & ~dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
231 HOP_OPS(_HOP_2_OP_09_N,(~opd_data ^ dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
232 HOP_OPS(_HOP_2_OP_10_N,(~dst_data), source_buffer >>=16, ;, _HOP_2, ;)
233 HOP_OPS(_HOP_2_OP_11_N,(opd_data | ~dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
234 HOP_OPS(_HOP_2_OP_12_N,(~opd_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
235 HOP_OPS(_HOP_2_OP_13_N,(~opd_data | dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
236 HOP_OPS(_HOP_2_OP_14_N,(~opd_data | ~dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_2, ;)
237 HOP_OPS(_HOP_2_OP_15_N,(0xffff), source_buffer >>=16, ;, _HOP_2, ;)
238
239 HOP_OPS(_HOP_3_OP_00_N,(0), source_buffer >>=16, ;, _HOP_3, _HOP_INC)
240 HOP_OPS(_HOP_3_OP_01_N,(opd_data & dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
241 HOP_OPS(_HOP_3_OP_02_N,(opd_data & ~dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
242 HOP_OPS(_HOP_3_OP_03_N,(opd_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
243 HOP_OPS(_HOP_3_OP_04_N,(~opd_data & dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
244 HOP_OPS(_HOP_3_OP_05_N,(dst_data), source_buffer >>=16, ;, _HOP_3, _HOP_INC)
245 HOP_OPS(_HOP_3_OP_06_N,(opd_data ^ dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
246 HOP_OPS(_HOP_3_OP_07_N,(opd_data | dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
247 HOP_OPS(_HOP_3_OP_08_N,(~opd_data & ~dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
248 HOP_OPS(_HOP_3_OP_09_N,(~opd_data ^ dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
249 HOP_OPS(_HOP_3_OP_10_N,(~dst_data), source_buffer >>=16, ;, _HOP_3, _HOP_INC)
250 HOP_OPS(_HOP_3_OP_11_N,(opd_data | ~dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
251 HOP_OPS(_HOP_3_OP_12_N,(~opd_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
252 HOP_OPS(_HOP_3_OP_13_N,(~opd_data | dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
253 HOP_OPS(_HOP_3_OP_14_N,(~opd_data | ~dst_data), source_buffer >>=16, _SRC_READ_N, _HOP_3, _HOP_INC)
254 HOP_OPS(_HOP_3_OP_15_N,(0xffff), source_buffer >>=16, ;, _HOP_3, _HOP_INC)
255
256
257 HOP_OPS(_HOP_0_OP_00_P,(0), source_buffer <<=16, ;, _HOP_0, ;)
258 HOP_OPS(_HOP_0_OP_01_P,(opd_data & dst_data), source_buffer <<=16, ;, _HOP_0, ;)
259 HOP_OPS(_HOP_0_OP_02_P,(opd_data & ~dst_data), source_buffer <<=16, ;, _HOP_0, ;)
260 HOP_OPS(_HOP_0_OP_03_P,(opd_data), source_buffer <<=16, ;, _HOP_0, ;)
261 HOP_OPS(_HOP_0_OP_04_P,(~opd_data & dst_data), source_buffer <<=16, ;, _HOP_0, ;)
262 HOP_OPS(_HOP_0_OP_05_P,(dst_data), source_buffer <<=16, ;, _HOP_0, ;)
263 HOP_OPS(_HOP_0_OP_06_P,(opd_data ^ dst_data), source_buffer <<=16, ;, _HOP_0, ;)
264 HOP_OPS(_HOP_0_OP_07_P,(opd_data | dst_data), source_buffer <<=16, ;, _HOP_0, ;)
265 HOP_OPS(_HOP_0_OP_08_P,(~opd_data & ~dst_data), source_buffer <<=16, ;, _HOP_0, ;)
266 HOP_OPS(_HOP_0_OP_09_P,(~opd_data ^ dst_data), source_buffer <<=16, ;, _HOP_0, ;)
267 HOP_OPS(_HOP_0_OP_10_P,(~dst_data), source_buffer <<=16, ;, _HOP_0, ;)
268 HOP_OPS(_HOP_0_OP_11_P,(opd_data | ~dst_data), source_buffer <<=16, ;, _HOP_0, ;)
269 HOP_OPS(_HOP_0_OP_12_P,(~opd_data), source_buffer <<=16, ;, _HOP_0, ;)
270 HOP_OPS(_HOP_0_OP_13_P,(~opd_data | dst_data), source_buffer <<=16, ;, _HOP_0, ;)
271 HOP_OPS(_HOP_0_OP_14_P,(~opd_data | ~dst_data), source_buffer <<=16, ;, _HOP_0, ;)
272 HOP_OPS(_HOP_0_OP_15_P,(0xffff), source_buffer <<=16, ;, _HOP_0, ;)
273
274 HOP_OPS(_HOP_1_OP_00_P,(0), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
275 HOP_OPS(_HOP_1_OP_01_P,(opd_data & dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
276 HOP_OPS(_HOP_1_OP_02_P,(opd_data & ~dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
277 HOP_OPS(_HOP_1_OP_03_P,(opd_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
278 HOP_OPS(_HOP_1_OP_04_P,(~opd_data & dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
279 HOP_OPS(_HOP_1_OP_05_P,(dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
280 HOP_OPS(_HOP_1_OP_06_P,(opd_data ^ dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
281 HOP_OPS(_HOP_1_OP_07_P,(opd_data | dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
282 HOP_OPS(_HOP_1_OP_08_P,(~opd_data & ~dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
283 HOP_OPS(_HOP_1_OP_09_P,(~opd_data ^ dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
284 HOP_OPS(_HOP_1_OP_10_P,(~dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
285 HOP_OPS(_HOP_1_OP_11_P,(opd_data | ~dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
286 HOP_OPS(_HOP_1_OP_12_P,(~opd_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
287 HOP_OPS(_HOP_1_OP_13_P,(~opd_data | dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
288 HOP_OPS(_HOP_1_OP_14_P,(~opd_data | ~dst_data), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
289 HOP_OPS(_HOP_1_OP_15_P,(0xffff), source_buffer <<=16, ;, _HOP_1, _HOP_INC)
290
291 HOP_OPS(_HOP_2_OP_00_P,(0), source_buffer <<=16, ;, _HOP_2, ;)
292 HOP_OPS(_HOP_2_OP_01_P,(opd_data & dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
293 HOP_OPS(_HOP_2_OP_02_P,(opd_data & ~dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
294 HOP_OPS(_HOP_2_OP_03_P,(opd_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
295 HOP_OPS(_HOP_2_OP_04_P,(~opd_data & dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
296 HOP_OPS(_HOP_2_OP_05_P,(dst_data), source_buffer <<=16, ;, _HOP_2, ;)
297 HOP_OPS(_HOP_2_OP_06_P,(opd_data ^ dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
298 HOP_OPS(_HOP_2_OP_07_P,(opd_data | dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
299 HOP_OPS(_HOP_2_OP_08_P,(~opd_data & ~dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
300 HOP_OPS(_HOP_2_OP_09_P,(~opd_data ^ dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
301 HOP_OPS(_HOP_2_OP_10_P,(~dst_data), source_buffer <<=16, ;, _HOP_2, ;)
302 HOP_OPS(_HOP_2_OP_11_P,(opd_data | ~dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
303 HOP_OPS(_HOP_2_OP_12_P,(~opd_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
304 HOP_OPS(_HOP_2_OP_13_P,(~opd_data | dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
305 HOP_OPS(_HOP_2_OP_14_P,(~opd_data | ~dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_2, ;)
306 HOP_OPS(_HOP_2_OP_15_P,(0xffff), source_buffer <<=16, ;, _HOP_2, ;)
307
308 HOP_OPS(_HOP_3_OP_00_P,(0), source_buffer <<=16, ;, _HOP_3, _HOP_INC)
309 HOP_OPS(_HOP_3_OP_01_P,(opd_data & dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
310 HOP_OPS(_HOP_3_OP_02_P,(opd_data & ~dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
311 HOP_OPS(_HOP_3_OP_03_P,(opd_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
312 HOP_OPS(_HOP_3_OP_04_P,(~opd_data & dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
313 HOP_OPS(_HOP_3_OP_05_P,(dst_data), source_buffer <<=16, ;, _HOP_3, _HOP_INC)
314 HOP_OPS(_HOP_3_OP_06_P,(opd_data ^ dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
315 HOP_OPS(_HOP_3_OP_07_P,(opd_data | dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
316 HOP_OPS(_HOP_3_OP_08_P,(~opd_data & ~dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
317 HOP_OPS(_HOP_3_OP_09_P,(~opd_data ^ dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
318 HOP_OPS(_HOP_3_OP_10_P,(~dst_data), source_buffer <<=16, ;, _HOP_3, _HOP_INC)
319 HOP_OPS(_HOP_3_OP_11_P,(opd_data | ~dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
320 HOP_OPS(_HOP_3_OP_12_P,(~opd_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
321 HOP_OPS(_HOP_3_OP_13_P,(~opd_data | dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
322 HOP_OPS(_HOP_3_OP_14_P,(~opd_data | ~dst_data), source_buffer <<=16, _SRC_READ_P, _HOP_3, _HOP_INC)
323 HOP_OPS(_HOP_3_OP_15_P,(0xffff), source_buffer <<=16, ;, _HOP_3, _HOP_INC)
324
325
326
_hop_2_op_03_p(BLITTER & b)327 void _hop_2_op_03_p( BLITTER& b )
328 {
329 #ifdef BLITTER_MEMMOVE
330 if (getVIDEL ()->getBpp() == 16) {
331 #ifdef BLITTER_SDLBLIT
332 if (b.source_addr >= ARANYMVRAMSTART && b.dest_addr >= ARANYMVRAMSTART) {
333 SDL_Rect src, dest;
334 int src_offset = b.source_addr - ARANYMVRAMSTART;
335 int dest_offset = b.dest_addr - ARANYMVRAMSTART;
336 int VidelScreenWidth = getVIDEL ()->getScreenWidth();
337 src.x = (src_offset % (2*VidelScreenWidth))/2;
338 src.y = (src_offset / (2*VidelScreenWidth));
339 src.w = dest.w = b.x_count;
340 src.h = dest.h = b.y_count;
341 dest.x = (dest_offset % (2*VidelScreenWidth))/2;
342 dest.y = (dest_offset / (2*VidelScreenWidth));
343 SDL_Surface *surf = SDL_GetVideoSurface();
344 SDL_BlitSurface(surf, &src, surf, &dest);
345 b.source_addr += (((b.x_count-1)*b.source_x_inc)+b.source_y_inc)*b.y_count;
346 b.dest_addr += (((b.x_count-1)*b.dest_x_inc)+b.dest_y_inc)*b.y_count;
347 b.y_count = 0;
348 return;
349 }
350 #endif /* BLITTER_SDLBLIT */
351 do
352 {
353 memmove(phys_get_real_address(b.dest_addr), phys_get_real_address(b.source_addr), b.x_count*2);
354 b.source_addr += ((b.x_count-1)*b.source_x_inc)+b.source_y_inc;
355 b.dest_addr += ((b.x_count-1)*b.dest_x_inc)+b.dest_y_inc;
356 } while (--b.y_count > 0);
357 }
358 else
359 #endif /* BLITTER_MEMMOVE */
360 _HOP_2_OP_03_P( b );
361 }
362
_hop_2_op_03_n(BLITTER & b)363 void _hop_2_op_03_n( BLITTER& b )
364 {
365 #ifdef BLITTER_MEMMOVE
366 if (getVIDEL ()->getBpp() == 16) {
367 b.source_addr += ((b.x_count-1)*b.source_x_inc);
368 b.dest_addr += ((b.x_count-1)*b.dest_x_inc);
369 #ifdef BLITTER_SDLBLIT
370 if (b.source_addr >= ARANYMVRAMSTART && b.dest_addr >= ARANYMVRAMSTART) {
371 b.source_addr += (((b.x_count)*b.source_x_inc)+b.source_y_inc)*b.y_count;
372 b.dest_addr += (((b.x_count-1)*b.dest_x_inc)+b.dest_y_inc)*b.y_count;
373 SDL_Rect src, dest;
374 int src_offset = b.source_addr - ARANYMVRAMSTART;
375 int dest_offset = b.dest_addr - ARANYMVRAMSTART;
376 int VidelScreenWidth = getVIDEL ()->getScreenWidth();
377 src.x = (src_offset % (2*VidelScreenWidth))/2;
378 src.y = (src_offset / (2*VidelScreenWidth));
379 src.w = dest.w = b.x_count;
380 src.h = dest.h = b.y_count;
381 dest.x = (dest_offset % (2*VidelScreenWidth))/2;
382 dest.y = (dest_offset / (2*VidelScreenWidth));
383 SDL_Surface *surf = SDL_GetVideoSurface();
384 SDL_BlitSurface(surf, &src, surf, &dest);
385 b.y_count = 0;
386 return;
387 }
388 #endif /* BLITTER_SDLBLIT */
389 do
390 {
391 memmove(phys_get_real_address(b.dest_addr), phys_get_real_address(b.source_addr), b.x_count*2);
392 b.source_addr += ((b.x_count)*b.source_x_inc)+b.source_y_inc;
393 b.dest_addr += ((b.x_count-1)*b.dest_x_inc)+b.dest_y_inc;
394 } while (--b.y_count > 0);
395 }
396 else
397 #endif /* BLITTER_MEMMOVE */
398 _HOP_2_OP_03_N( b );
399 }
400
401
402
403 static void (*const do_hop_op_N[4][16])( BLITTER& ) = {
404 { _HOP_0_OP_00_N, _HOP_0_OP_01_N, _HOP_0_OP_02_N, _HOP_0_OP_03_N, _HOP_0_OP_04_N, _HOP_0_OP_05_N, _HOP_0_OP_06_N, _HOP_0_OP_07_N, _HOP_0_OP_08_N, _HOP_0_OP_09_N, _HOP_0_OP_10_N, _HOP_0_OP_11_N, _HOP_0_OP_12_N, _HOP_0_OP_13_N, _HOP_0_OP_14_N, _HOP_0_OP_15_N },
405 { _HOP_1_OP_00_N, _HOP_1_OP_01_N, _HOP_1_OP_02_N, _HOP_1_OP_03_N, _HOP_1_OP_04_N, _HOP_1_OP_05_N, _HOP_1_OP_06_N, _HOP_1_OP_07_N, _HOP_1_OP_08_N, _HOP_1_OP_09_N, _HOP_1_OP_10_N, _HOP_1_OP_11_N, _HOP_1_OP_12_N, _HOP_1_OP_13_N, _HOP_1_OP_14_N, _HOP_1_OP_15_N },
406 { _HOP_2_OP_00_N, _HOP_2_OP_01_N, _HOP_2_OP_02_N, _hop_2_op_03_n, _HOP_2_OP_04_N, _HOP_2_OP_05_N, _HOP_2_OP_06_N, _HOP_2_OP_07_N, _HOP_2_OP_08_N, _HOP_2_OP_09_N, _HOP_2_OP_10_N, _HOP_2_OP_11_N, _HOP_2_OP_12_N, _HOP_2_OP_13_N, _HOP_2_OP_14_N, _HOP_2_OP_15_N },
407 { _HOP_3_OP_00_N, _HOP_3_OP_01_N, _HOP_3_OP_02_N, _HOP_3_OP_03_N, _HOP_3_OP_04_N, _HOP_3_OP_05_N, _HOP_3_OP_06_N, _HOP_3_OP_07_N, _HOP_3_OP_08_N, _HOP_3_OP_09_N, _HOP_3_OP_10_N, _HOP_3_OP_11_N, _HOP_3_OP_12_N, _HOP_3_OP_13_N, _HOP_3_OP_14_N, _HOP_3_OP_15_N }
408 };
409
410 static void (*const do_hop_op_P[4][16])( BLITTER& ) = {
411 { _HOP_0_OP_00_P, _HOP_0_OP_01_P, _HOP_0_OP_02_P, _HOP_0_OP_03_P, _HOP_0_OP_04_P, _HOP_0_OP_05_P, _HOP_0_OP_06_P, _HOP_0_OP_07_P, _HOP_0_OP_08_P, _HOP_0_OP_09_P, _HOP_0_OP_10_P, _HOP_0_OP_11_P, _HOP_0_OP_12_P, _HOP_0_OP_13_P, _HOP_0_OP_14_P, _HOP_0_OP_15_P },
412 { _HOP_1_OP_00_P, _HOP_1_OP_01_P, _HOP_1_OP_02_P, _HOP_1_OP_03_P, _HOP_1_OP_04_P, _HOP_1_OP_05_P, _HOP_1_OP_06_P, _HOP_1_OP_07_P, _HOP_1_OP_08_P, _HOP_1_OP_09_P, _HOP_1_OP_10_P, _HOP_1_OP_11_P, _HOP_1_OP_12_P, _HOP_1_OP_13_P, _HOP_1_OP_14_P, _HOP_1_OP_15_P },
413 { _HOP_2_OP_00_P, _HOP_2_OP_01_P, _HOP_2_OP_02_P, _hop_2_op_03_p, _HOP_2_OP_04_P, _HOP_2_OP_05_P, _HOP_2_OP_06_P, _HOP_2_OP_07_P, _HOP_2_OP_08_P, _HOP_2_OP_09_P, _HOP_2_OP_10_P, _HOP_2_OP_11_P, _HOP_2_OP_12_P, _HOP_2_OP_13_P, _HOP_2_OP_14_P, _HOP_2_OP_15_P },
414 { _HOP_3_OP_00_P, _HOP_3_OP_01_P, _HOP_3_OP_02_P, _HOP_3_OP_03_P, _HOP_3_OP_04_P, _HOP_3_OP_05_P, _HOP_3_OP_06_P, _HOP_3_OP_07_P, _HOP_3_OP_08_P, _HOP_3_OP_09_P, _HOP_3_OP_10_P, _HOP_3_OP_11_P, _HOP_3_OP_12_P, _HOP_3_OP_13_P, _HOP_3_OP_14_P, _HOP_3_OP_15_P }
415 };
416
417
handleRead(memptr addr)418 uint8 BLITTER::handleRead(memptr addr) {
419 addr -= getHWoffset();
420
421 D(bug("Blitter read byte from register %x at %06x", addr+getHWoffset(), showPC()));
422 switch(addr) {
423 case 0x3a: return hop;
424 case 0x3b: return op;
425 case 0x3c: return LOAD_B_ff8a3c();
426 case 0x3d: return skewreg;
427 }
428
429 panicbug("Blitter tried to read byte from register %x at %06x", addr+getHWoffset(), showPC());
430
431 return 0;
432 }
433
handleReadW(uaecptr addr)434 uae_u16 BLITTER::handleReadW(uaecptr addr) {
435 addr -= getHWoffset();
436
437 D(bug("Blitter read word from register %x at %06x", addr+getHWoffset(), showPC()));
438 if (addr < 0x20) {
439 return halftone_ram[addr / 2];
440 }
441
442 switch(addr) {
443 case 0x20: return source_x_inc;
444 case 0x22: return source_y_inc;
445 case 0x24: return (source_addr >> 16) & 0xffff;
446 case 0x26: return (source_addr) & 0xffff;
447 case 0x28: return end_mask_1;
448 case 0x2a: return end_mask_2;
449 case 0x2c: return end_mask_3;
450 case 0x2e: return dest_x_inc;
451 case 0x30: return dest_y_inc;
452 case 0x32: return (dest_addr >> 16) & 0xffff;
453 case 0x34: return (dest_addr) & 0xffff;
454 case 0x36: return x_count;
455 case 0x38: return y_count;
456 case 0x3a: // fallthrough
457 case 0x3c: return BASE_IO::handleReadW(addr+getHWoffset());
458 }
459
460 panicbug("Blitter tried to read word from register %x at %06x", addr+getHWoffset(), showPC());
461
462 return 0;
463 }
464
handleReadL(uaecptr addr)465 uae_u32 BLITTER::handleReadL(uaecptr addr) {
466 addr -= getHWoffset();
467
468 D(bug("Blitter read long from register %x at %06x", addr+getHWoffset(), showPC()));
469 if (addr < 0x20) {
470 return BASE_IO::handleReadL(addr+getHWoffset());
471 }
472
473 switch(addr) {
474 case 0x24: return source_addr;
475 case 0x32: return dest_addr;
476 }
477
478 panicbug("Blitter tried to read long word from register %x at %06x", addr+getHWoffset(), showPC());
479
480 return 0;
481 }
482
handleWrite(memptr addr,uint8 value)483 void BLITTER::handleWrite(memptr addr, uint8 value) {
484 addr -= getHWoffset();
485
486 D(bug("Blitter write byte $%02x to register %x at %06x", value, addr+getHWoffset(), showPC()));
487 switch(addr) {
488 case 0x3a: STORE_B_ff8a3a(value); break;
489 case 0x3b: STORE_B_ff8a3b(value); break;
490 case 0x3c: STORE_B_ff8a3c(value); break;
491 case 0x3d: STORE_B_ff8a3d(value); break;
492 default:
493 panicbug("Blitter tried to write byte $%02x to register %x at %06x", value, addr+getHWoffset(), showPC());
494 }
495
496 if (blit) {
497 Do_Blit();
498 blit = false;
499 }
500 }
501
handleWriteW(uaecptr addr,uint16 value)502 void BLITTER::handleWriteW(uaecptr addr, uint16 value) {
503 addr -= getHWoffset();
504
505 D(bug("Blitter write word $%04x to register %x at %06x", value, addr+getHWoffset(), showPC()));
506 if (addr < 0x20) {
507 halftone_ram[addr / 2] = value;
508 return;
509 }
510
511 switch(addr) {
512 case 0x20: source_x_inc = value; break;
513 case 0x22: source_y_inc = value; break;
514 case 0x24: source_addr = (source_addr & 0x0000ffff) | (value << 16); source_addr_backup = source_addr; break;
515 case 0x26: source_addr = (source_addr & 0xffff0000) | (value & 0xfffe); source_addr_backup = source_addr; break;
516 case 0x28: end_mask_1 = value; break;
517 case 0x2a: end_mask_2 = value; break;
518 case 0x2c: end_mask_3 = value; break;
519 case 0x2e: dest_x_inc = value; break;
520 case 0x30: dest_y_inc = value; break;
521 case 0x32: dest_addr = (dest_addr & 0x0000ffff) | (value << 16); dest_addr_backup = dest_addr; break;
522 case 0x34: dest_addr = (dest_addr & 0xffff0000) | (value & 0xfffe); dest_addr_backup = dest_addr; break;
523 case 0x36: x_count = value; break;
524 case 0x38: y_count = value; break;
525 case 0x3a: STORE_B_ff8a3a(value >> 8); STORE_B_ff8a3b(value); break;
526 case 0x3c: STORE_B_ff8a3c(value >> 8); STORE_B_ff8a3d(value); break;
527 default:
528 panicbug("Blitter tried to write word $%04x to register %x at %06x", value, addr+getHWoffset(), showPC());
529 }
530
531 if (blit) {
532 Do_Blit();
533 blit = false;
534 }
535 }
536
handleWriteL(uaecptr addr,uint32 value)537 void BLITTER::handleWriteL(uaecptr addr, uint32 value) {
538 addr -= getHWoffset();
539 D(bug("Blitter write long $%08x to register %x at %06x", value, addr+getHWoffset(), showPC()));
540 switch(addr) {
541 case 0x24:
542 D(bug("Blitter sets source to $%08lx at $%08lx", value, showPC()));
543 source_addr = value & 0xfffffffe;
544 source_addr_backup = source_addr;
545 break;
546 case 0x32:
547 D(bug("Blitter sets dest to $%08lx at $%08lx", value, showPC()));
548 dest_addr = value & 0xfffffffe;
549 dest_addr_backup = dest_addr;
550 break;
551 default: BASE_IO::handleWriteL(addr+getHWoffset(), value); break;
552 }
553
554 }
555
LOAD_B_ff8a3c(void)556 B BLITTER::LOAD_B_ff8a3c(void)
557 {
558 return line_num & 0x3f;
559 }
560
STORE_B_ff8a3a(B v)561 void BLITTER::STORE_B_ff8a3a(B v)
562 { hop = v & 3; /* h/ware reg masks out the top 6 bits! */
563 }
564
STORE_B_ff8a3b(B v)565 void BLITTER::STORE_B_ff8a3b(B v)
566 { op = v & 15; /* h/ware reg masks out the top 4 bits! */
567 }
568
STORE_B_ff8a3c(B v)569 void BLITTER::STORE_B_ff8a3c(B v)
570 { // 765_3210 Line-Number
571 line_num = (UB) v & 0x3f;
572 if ((y_count !=0) && (v & 0x80)) /* Busy bit set and lines to blit? */
573 blit = true;
574 }
575
STORE_B_ff8a3d(B v)576 void BLITTER::STORE_B_ff8a3d(B v)
577 { // 76__3210 Skew
578 NFSR = (v & 0x40) != 0;
579 FXSR = (v & 0x80) != 0;
580 skewreg = (unsigned char) v & 0xcf; /* h/ware reg mask %11001111 !*/
581 }
582
583
Do_Blit(void)584 void BLITTER::Do_Blit(void)
585 {
586 D(bug("Blitter started at %06x", showPC()));
587 #if DEBUG
588 SHOWPARAMS;
589 #endif
590
591 if (source_addr != source_addr_backup) {
592 D(bug("Blitter starts with obsolete source addr $%08lx, should be $%08lx", source_addr, source_addr_backup));
593 source_addr = source_addr_backup;
594 }
595 if (dest_addr != dest_addr_backup) {
596 D(bug("Blitter starts with obsolete dest addr $%08lx, should be $%08lx", dest_addr, dest_addr_backup));
597 dest_addr = dest_addr_backup;
598 }
599
600 /*
601 * do not check source address if is not used in operation
602 */
603 if (hop != 0 && /* source is all ones */
604 hop != 1 && /* source is halftone only */
605 op != 0 && /* result is all zeroes */
606 op != 5 && /* result is destination */
607 op != 10 && /* result is ~destination */
608 op != 15 && /* result is all ones */
609 (source_addr <= 0x800 || (source_addr >= 0x0e80000 && source_addr < 0x1000000))) {
610 panicbug("Blitter Source address out of range: $%08x", source_addr);
611 return;
612 }
613 if (dest_addr <= 0x800 || (dest_addr >= 0x0e00000 && dest_addr < 0x1000000)) {
614 panicbug("Blitter Destination address out of range: $%08x", dest_addr);
615 return;
616 }
617
618 if (source_x_inc < 0) {
619 do_hop_op_N[hop][op]( *this );
620 }
621 else {
622 do_hop_op_P[hop][op]( *this );
623 }
624 }
625