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