1 /***************************************************************************
2 
3 	Art & Magic hardware
4 
5 ***************************************************************************/
6 
7 #include "driver.h"
8 #include "cpu/tms34010/tms34010.h"
9 #include "cpu/tms34010/34010ops.h"
10 #include "artmagic.h"
11 
12 
13 #define INSTANT_BLIT		1
14 
15 
16 data16_t *artmagic_vram0;
17 data16_t *artmagic_vram1;
18 
19 /* decryption parameters */
20 int artmagic_xor[16], artmagic_is_stoneball;
21 
22 static UINT16 *blitter_base;
23 static UINT32 blitter_mask;
24 static UINT16 blitter_data[8];
25 static UINT8 blitter_page;
26 
27 #if (!INSTANT_BLIT)
28 static double blitter_busy_until;
29 #endif
30 
31 
32 
33 /*************************************
34  *
35  *	Inlines
36  *
37  *************************************/
38 
address_to_vram(offs_t * address)39 static INLINE UINT16 *address_to_vram(offs_t *address)
40 {
41 	offs_t original = *address;
42 	*address = TOWORD(original & 0x001fffff);
43 	if (original >= 0x00000000 && original < 0x001fffff)
44 		return artmagic_vram0;
45 	else if (original >= 0x00400000 && original < 0x005fffff)
46 		return artmagic_vram1;
47 	return NULL;
48 }
49 
50 
51 
52 /*************************************
53  *
54  *	Video start
55  *
56  *************************************/
57 
VIDEO_START(artmagic)58 VIDEO_START( artmagic )
59 {
60 	blitter_base = (UINT16 *)memory_region(REGION_GFX1);
61 	blitter_mask = memory_region_length(REGION_GFX1)/2 - 1;
62 	return 0;
63 }
64 
65 
66 
67 /*************************************
68  *
69  *	Shift register transfers
70  *
71  *************************************/
72 
artmagic_to_shiftreg(offs_t address,data16_t * data)73 void artmagic_to_shiftreg(offs_t address, data16_t *data)
74 {
75 	UINT16 *vram = address_to_vram(&address);
76 	if (vram)
77 		memcpy(data, &vram[address], TOBYTE(0x2000));
78 }
79 
80 
artmagic_from_shiftreg(offs_t address,data16_t * data)81 void artmagic_from_shiftreg(offs_t address, data16_t *data)
82 {
83 	UINT16 *vram = address_to_vram(&address);
84 	if (vram)
85 		memcpy(&vram[address], data, TOBYTE(0x2000));
86 }
87 
88 
89 
90 /*************************************
91  *
92  *	Custom blitter
93  *
94  *************************************/
95 
execute_blit(void)96 static void execute_blit(void)
97 {
98 	UINT16 *dest = blitter_page ? artmagic_vram0 : artmagic_vram1;
99 	int offset = ((blitter_data[1] & 0xff) << 16) | blitter_data[0];
100 	int color = (blitter_data[1] >> 4) & 0xf0;
101 	int x = (INT16)blitter_data[2];
102 	int y = (INT16)blitter_data[3];
103 	int maskx = blitter_data[6] & 0xff;
104 	int masky = blitter_data[6] >> 8;
105 	int w = ((blitter_data[7] & 0xff) + 1) * 4;
106 	int h = (blitter_data[7] >> 8) + 1;
107 	int i, j, sx, sy, last;
108 
109 #if 0
110 {
111 	static UINT32 hit_list[50000];
112 	static int hit_index;
113 	static FILE *f;
114 
115 	logerror("%08X:Blit from %06X to (%d,%d) %dx%d -- %04X %04X %04X %04X %04X %04X %04X %04X\n",
116 				activecpu_get_pc(), offset, x, y, w, h,
117 				blitter_data[0], blitter_data[1],
118 				blitter_data[2], blitter_data[3],
119 				blitter_data[4], blitter_data[5],
120 				blitter_data[6], blitter_data[7]);
121 
122 	if (!f) f = fopen("artmagic.log", "w");
123 
124 	for (i = 0; i < hit_index; i++)
125 		if (hit_list[i] == offset)
126 			break;
127 	if (i == hit_index)
128 	{
129 		int tempoffs = offset;
130 		hit_list[hit_index++] = offset;
131 
132 		fprintf(f, "----------------------\n"
133 				   "%08X:Blit from %06X to (%d,%d) %dx%d -- %04X %04X %04X %04X %04X %04X %04X %04X\n",
134 					activecpu_get_pc(), offset, x, y, w, h,
135 					blitter_data[0], blitter_data[1],
136 					blitter_data[2], blitter_data[3],
137 					blitter_data[4], blitter_data[5],
138 					blitter_data[6], blitter_data[7]);
139 
140 		fprintf(f, "\t");
141 		for (i = 0; i < h; i++)
142 		{
143 			for (j = 0; j < w; j += 4)
144 				fprintf(f, "%04X ", blitter_base[tempoffs++]);
145 			fprintf(f, "\n\t");
146 		}
147 		fprintf(f, "\n\t");
148 		tempoffs = offset;
149 		for (i = 0; i < h; i++)
150 		{
151 			last = 0;
152 			if (i == 0)	/* first line */
153 			{
154 				/* ultennis, stonebal */
155 				last ^= (blitter_data[7] & 0x0001);
156 				if (artmagic_is_stoneball)
157 					last ^= ((blitter_data[0] & 0x0020) >> 3);
158 				else	/* ultennis */
159 					last ^= ((blitter_data[0] & 0x0040) >> 4);
160 
161 				/* cheesech */
162 				last ^= ((blitter_data[7] & 0x0400) >> 9);
163 				last ^= ((blitter_data[0] & 0x2000) >> 10);
164 			}
165 			else	/* following lines */
166 			{
167 				int val = blitter_base[tempoffs];
168 
169 				/* ultennis, stonebal */
170 				last ^= 4;
171 				last ^= ((val & 0x0400) >> 8);
172 				last ^= ((val & 0x5000) >> 12);
173 
174 				/* cheesech */
175 				last ^= 8;
176 				last ^= ((val & 0x0800) >> 8);
177 				last ^= ((val & 0xa000) >> 12);
178 			}
179 
180 			for (j = 0; j < w; j += 4)
181 			{
182 				static const char hex[] = ".123456789ABCDEF";
183 				int val = blitter_base[tempoffs++];
184 				int p1, p2, p3, p4;
185 				p1 = last = ((val ^ artmagic_xor[last]) >>  0) & 0xf;
186 				p2 = last = ((val ^ artmagic_xor[last]) >>  4) & 0xf;
187 				p3 = last = ((val ^ artmagic_xor[last]) >>  8) & 0xf;
188 				p4 = last = ((val ^ artmagic_xor[last]) >> 12) & 0xf;
189 				fprintf(f, "%c%c%c%c ", hex[p1], hex[p2], hex[p3], hex[p4]);
190 			}
191 			fprintf(f, "\n\t");
192 		}
193 		fprintf(f, "\n");
194 	}
195 }
196 #endif
197 
198 	profiler_mark(PROFILER_VIDEO);
199 
200 	last = 0;
201 	sy = y;
202 	for (i = 0; i < h; i++)
203 	{
204 		if ((i & 1) || !((masky << ((i/2) & 7)) & 0x80))
205 		{
206 			if (sy >= 0 && sy < 256)
207 			{
208 				int tsy = sy * TOWORD(0x2000);
209 				sx = x;
210 
211 				/* The first pixel of every line doesn't have a previous pixel
212 				   to depend on, so it takes the "feed" from other bits.
213 				   The very first pixel blitted is also treated differently.
214 
215 				   ultennis/stonebal use a different encryption from cheesech,
216 				   however the former only need to set bits 0 and 2 of the
217 				   feed (the others are irrelevant), while the latter only
218 				   bits 1 and 3, so I can handle both at the same time.
219 				 */
220 				last = 0;
221 				if (i == 0)	/* first line */
222 				{
223 					/* ultennis, stonebal */
224 					last ^= (blitter_data[7] & 0x0001);
225 					if (artmagic_is_stoneball)
226 						last ^= ((blitter_data[0] & 0x0020) >> 3);
227 					else	/* ultennis */
228 						last ^= (((blitter_data[0] + 1) & 0x0040) >> 4);
229 
230 					/* cheesech */
231 					last ^= ((blitter_data[7] & 0x0400) >> 9);
232 					last ^= ((blitter_data[0] & 0x2000) >> 10);
233 				}
234 				else	/* following lines */
235 				{
236 					int val = blitter_base[offset & blitter_mask];
237 
238 					/* ultennis, stonebal */
239 					last ^= 4;
240 					last ^= ((val & 0x0400) >> 8);
241 					last ^= ((val & 0x5000) >> 12);
242 
243 					/* cheesech */
244 					last ^= 8;
245 					last ^= ((val & 0x0800) >> 8);
246 					last ^= ((val & 0xa000) >> 12);
247 				}
248 
249 				for (j = 0; j < w; j += 4)
250 				{
251 					UINT16 val = blitter_base[(offset + j/4) & blitter_mask];
252 					if (sx < 508)
253 					{
254 						if (h == 1 && artmagic_is_stoneball)
255 							last = ((val) >>  0) & 0xf;
256 						else
257 							last = ((val ^ artmagic_xor[last]) >>  0) & 0xf;
258 						if (!((maskx << ((j/2) & 7)) & 0x80))
259 						{
260 							if (last && sx >= 0 && sx < 512)
261 								dest[tsy + sx] = color | (last);
262 							sx++;
263 						}
264 
265 						if (h == 1 && artmagic_is_stoneball)
266 							last = ((val) >>  4) & 0xf;
267 						else
268 							last = ((val ^ artmagic_xor[last]) >>  4) & 0xf;
269 						{
270 							if (last && sx >= 0 && sx < 512)
271 								dest[tsy + sx] = color | (last);
272 							sx++;
273 						}
274 
275 						if (h == 1 && artmagic_is_stoneball)
276 							last = ((val) >>  8) & 0xf;
277 						else
278 							last = ((val ^ artmagic_xor[last]) >>  8) & 0xf;
279 						if (!((maskx << ((j/2) & 7)) & 0x40))
280 						{
281 							if (last && sx >= 0 && sx < 512)
282 								dest[tsy + sx] = color | (last);
283 							sx++;
284 						}
285 
286 						if (h == 1 && artmagic_is_stoneball)
287 							last = ((val) >> 12) & 0xf;
288 						else
289 							last = ((val ^ artmagic_xor[last]) >> 12) & 0xf;
290 						{
291 							if (last && sx >= 0 && sx < 512)
292 								dest[tsy + sx] = color | (last);
293 							sx++;
294 						}
295 					}
296 				}
297 			}
298 			sy++;
299 		}
300 		offset += w/4;
301 	}
302 
303 	profiler_mark(PROFILER_END);
304 
305 #if (!INSTANT_BLIT)
306 	blitter_busy_until = timer_get_time() + (w*h*TIME_IN_NSEC(20));
307 #endif
308 }
309 
310 
READ16_HANDLER(artmagic_blitter_r)311 READ16_HANDLER( artmagic_blitter_r )
312 {
313 	/*
314 		bit 1 is a busy flag; loops tightly if clear
315 		bit 2 is tested in a similar fashion
316 		bit 4 reflects the page
317 	*/
318 	UINT16 result = 0xffef | (blitter_page << 4);
319 #if (!INSTANT_BLIT)
320 	if (timer_get_time() < blitter_busy_until)
321 		result ^= 6;
322 #endif
323 	return result;
324 }
325 
326 
WRITE16_HANDLER(artmagic_blitter_w)327 WRITE16_HANDLER( artmagic_blitter_w )
328 {
329 	COMBINE_DATA(&blitter_data[offset]);
330 
331 	/* offset 3 triggers the blit */
332 	if (offset == 3)
333 		execute_blit();
334 
335 	/* offset 4 contains the target page */
336 	else if (offset == 4)
337 		blitter_page = (data >> 1) & 1;
338 }
339 
340 
341 
342 /*************************************
343  *
344  *	Video update
345  *
346  *************************************/
347 
VIDEO_UPDATE(artmagic)348 VIDEO_UPDATE( artmagic )
349 {
350 	UINT32 offset, dpytap;
351 	UINT16 *vram;
352 	int x, y;
353 
354 	/* get the current parameters */
355 	cpuintrf_push_context(0);
356 	offset = (~tms34010_get_DPYSTRT(0) & 0xfff0) << 8;
357 	dpytap = tms34010_io_register_r(REG_DPYTAP, 0);
358 	cpuintrf_pop_context();
359 
360 	/* compute the base and offset */
361 	vram = address_to_vram(&offset);
362 	if (!vram || tms34010_io_display_blanked(0))
363 	{
364 		fillbitmap(bitmap, get_black_pen(), cliprect);
365 		return;
366 	}
367 	offset += cliprect->min_y * TOWORD(0x2000);
368 	offset += dpytap;
369 
370 	/* render the bitmap */
371 	for (y = cliprect->min_y; y <= cliprect->max_y; y++)
372 	{
373 		UINT16 *dest = (UINT16 *)bitmap->base + y * bitmap->rowpixels;
374 		for (x = cliprect->min_x; x <= cliprect->max_x; x++)
375 			dest[x] = vram[(offset + x) & TOWORD(0x1fffff)] & 0xff;
376 		offset += TOWORD(0x2000);
377 	}
378 }
379