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