1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3 /* */
4 
5 #include "emu.h"
6 #include "k053936.h"
7 
8 #define VERBOSE 0
9 #include "logmacro.h"
10 
11 
12 // Localized K053936/ROZ+
13 #define K053936_MAX_CHIPS 2
14 
15 static rectangle K053936_cliprect[K053936_MAX_CHIPS];
16 static int K053936_offset[K053936_MAX_CHIPS][2] = {{0,0},{0,0}};
17 static int K053936_clip_enabled[K053936_MAX_CHIPS] = {0,0};
18 static int K053936_wraparound[K053936_MAX_CHIPS];
19 
20 
21 
22 
23 /***************************************************************************/
24 /*                                                                         */
25 /*                                 053936                                  */
26 /*                                                                         */
27 /***************************************************************************/
28 
29 /*
30 
31 053936
32 ------
33 Evolution of the 051316. The data bus is 16-bit instead of 8-bit.
34 When used in "simple" mode it can generate the same effects of the 051316, but it
35 doesn't have internal tilemap RAM, so it just generates a couple of X/Y coordinates
36 indicating the pixel to display at each moment. Therefore, the tilemap and tile
37 sizes are not fixed.
38 The important addition over the 051316 is 512x4 words of internal RAM used to control
39 rotation and zoom scanline by scanline instead that on the whole screen, allowing for
40 effects like linescroll (Super Slams) or 3D rotation of the tilemap (Golfing Greats,
41 Premier Soccer).
42 
43 control registers
44 000 X counter starting value / 256
45 001 Y counter starting value / 256
46 002 ["simple" mode only] amount to add to the X counter after each line (0 = no rotation)
47 003 ["simple" mode only] amount to add to the Y counter after each line
48 004 ["simple" mode only] amount to add to the X counter after each horizontal pixel
49 005 ["simple" mode only] amount to add to the Y counter after each horizontal pixel (0 = no rotation)
50 006 x------- -------- when set, register (line*4)+2 must be multiplied by 256
51     -x------ -------- when set, registers 002 and 003 must be multiplied by 256
52     --xxxxxx -------- clipping for the generated address? usually 3F, Premier Soccer
53                       sets it to 07 before penalty kicks
54     -------- x------- when set, register (line*4)+3 must be multiplied by 256
55     -------- -x------ when set, registers 004 and 005 must be multiplied by 256
56     -------- --xxxxxx clipping for the generated address? usually 3F, Premier Soccer
57                       sets it to 0F before penalty kicks
58 007 -------- -x------ enable "super" mode
59     -------- --x----- unknown (enable address clipping from register 006?)
60     -------- ---x---- unknown
61     -------- ------x- (not sure) enable clipping with registers 008-00b
62 008 min x screen coordinate to draw to (only when enabled by register 7)
63 009 max x screen coordinate to draw to (only when enabled by register 7)
64 00a min y screen coordinate to draw to (only when enabled by register 7)
65 00b max y screen coordinate to draw to (only when enabled by register 7)
66 00c unknown
67 00d unknown
68 00e unknown
69 00f unknown
70 
71 additional control from extra RAM:
72 (line*4)+0 X counter starting value / 256 (add to register 000)
73 (line*4)+1 Y counter starting value / 256 (add to register 001)
74 (line*4)+2 amount to add to the X counter after each horizontal pixel
75 (line*4)+3 amount to add to the Y counter after each horizontal pixel
76 
77 */
78 
79 
80 
81 
K053936_zoom_draw(int chip,uint16_t * ctrl,uint16_t * linectrl,screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect,tilemap_t * tmap,int flags,uint32_t priority,int glfgreat_hack)82 static void K053936_zoom_draw(int chip,uint16_t *ctrl,uint16_t *linectrl, screen_device &screen, bitmap_ind16 &bitmap,const rectangle &cliprect,tilemap_t *tmap,int flags,uint32_t priority, int glfgreat_hack)
83 {
84 	if (!tmap)
85 		return;
86 
87 	if (ctrl[0x07] & 0x0040)
88 	{
89 		uint32_t startx,starty;
90 		int incxx,incxy;
91 		rectangle my_clip;
92 		int y,maxy;
93 
94 		// Racin' Force will get to here if glfgreat_hack is enabled, and it ends
95 		// up setting a maximum y value of '13', thus causing nothing to be drawn.
96 		// It looks like the roz output should be flipped somehow as it seems to be
97 		// displaying the wrong areas of the tilemap and is rendered upside down,
98 		// although due to the additional post-processing the voxel renderer performs
99 		// it's difficult to know what the output SHOULD be.  (hold W in Racin' Force
100 		// to see the chip output)
101 
102 		if (((ctrl[0x07] & 0x0002) && ctrl[0x09]) && (glfgreat_hack))   /* wrong, but fixes glfgreat */
103 		{
104 			my_clip.min_x = ctrl[0x08] + K053936_offset[chip][0]+2;
105 			my_clip.max_x = ctrl[0x09] + K053936_offset[chip][0]+2 - 1;
106 			if (my_clip.min_x < cliprect.min_x)
107 				my_clip.min_x = cliprect.min_x;
108 			if (my_clip.max_x > cliprect.max_x)
109 				my_clip.max_x = cliprect.max_x;
110 
111 			y = ctrl[0x0a] + K053936_offset[chip][1]-2;
112 			if (y < cliprect.min_y)
113 				y = cliprect.min_y;
114 			maxy = ctrl[0x0b] + K053936_offset[chip][1]-2 - 1;
115 			if (maxy > cliprect.max_y)
116 				maxy = cliprect.max_y;
117 
118 		}
119 		else
120 		{
121 			my_clip.min_x = cliprect.min_x;
122 			my_clip.max_x = cliprect.max_x;
123 
124 			y = cliprect.min_y;
125 			maxy = cliprect.max_y;
126 		}
127 
128 		while (y <= maxy)
129 		{
130 			uint16_t *lineaddr = linectrl + 4*((y - K053936_offset[chip][1]) & 0x1ff);
131 			my_clip.min_y = my_clip.max_y = y;
132 
133 			startx = 256 * (int16_t)(lineaddr[0] + ctrl[0x00]);
134 			starty = 256 * (int16_t)(lineaddr[1] + ctrl[0x01]);
135 			incxx  =       (int16_t)(lineaddr[2]);
136 			incxy  =       (int16_t)(lineaddr[3]);
137 
138 			if (ctrl[0x06] & 0x8000) incxx *= 256;
139 			if (ctrl[0x06] & 0x0080) incxy *= 256;
140 
141 			startx -= K053936_offset[chip][0] * incxx;
142 			starty -= K053936_offset[chip][0] * incxy;
143 
144 			tmap->draw_roz(screen, bitmap, my_clip, startx << 5,starty << 5,
145 					incxx << 5,incxy << 5,0,0,
146 					K053936_wraparound[chip],
147 					flags,priority);
148 
149 			y++;
150 		}
151 	}
152 	else    /* "simple" mode */
153 	{
154 		uint32_t startx,starty;
155 		int incxx,incxy,incyx,incyy;
156 
157 		startx = 256 * (int16_t)(ctrl[0x00]);
158 		starty = 256 * (int16_t)(ctrl[0x01]);
159 		incyx  =       (int16_t)(ctrl[0x02]);
160 		incyy  =       (int16_t)(ctrl[0x03]);
161 		incxx  =       (int16_t)(ctrl[0x04]);
162 		incxy  =       (int16_t)(ctrl[0x05]);
163 
164 		if (ctrl[0x06] & 0x4000) { incyx *= 256; incyy *= 256; }
165 		if (ctrl[0x06] & 0x0040) { incxx *= 256; incxy *= 256; }
166 
167 		startx -= K053936_offset[chip][1] * incyx;
168 		starty -= K053936_offset[chip][1] * incyy;
169 
170 		startx -= K053936_offset[chip][0] * incxx;
171 		starty -= K053936_offset[chip][0] * incxy;
172 
173 		tmap->draw_roz(screen, bitmap, cliprect, startx << 5,starty << 5,
174 				incxx << 5,incxy << 5,incyx << 5,incyy << 5,
175 				K053936_wraparound[chip],
176 				flags,priority);
177 	}
178 
179 #if 0
180 if (machine.input().code_pressed(KEYCODE_D))
181 	popmessage("%04x %04x %04x %04x\n%04x %04x %04x %04x\n%04x %04x %04x %04x\n%04x %04x %04x %04x",
182 			ctrl[0x00],
183 			ctrl[0x01],
184 			ctrl[0x02],
185 			ctrl[0x03],
186 			ctrl[0x04],
187 			ctrl[0x05],
188 			ctrl[0x06],
189 			ctrl[0x07],
190 			ctrl[0x08],
191 			ctrl[0x09],
192 			ctrl[0x0a],
193 			ctrl[0x0b],
194 			ctrl[0x0c],
195 			ctrl[0x0d],
196 			ctrl[0x0e],
197 			ctrl[0x0f]);
198 #endif
199 }
200 
201 
K053936_0_zoom_draw(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect,tilemap_t * tmap,int flags,uint32_t priority,int glfgreat_hack)202 void K053936_0_zoom_draw(screen_device &screen, bitmap_ind16 &bitmap,const rectangle &cliprect,tilemap_t *tmap,int flags,uint32_t priority, int glfgreat_hack)
203 {
204 	uint16_t *ctrl = reinterpret_cast<uint16_t *>(tmap->machine().root_device().memshare("k053936_0_ctrl")->ptr());
205 	uint16_t *linectrl = reinterpret_cast<uint16_t *>(tmap->machine().root_device().memshare("k053936_0_line")->ptr());
206 	K053936_zoom_draw(0,ctrl,linectrl,screen,bitmap,cliprect,tmap,flags,priority, glfgreat_hack);
207 }
208 
K053936_wraparound_enable(int chip,int status)209 void K053936_wraparound_enable(int chip, int status)
210 {
211 	K053936_wraparound[chip] = status;
212 }
213 
214 
K053936_set_offset(int chip,int xoffs,int yoffs)215 void K053936_set_offset(int chip, int xoffs, int yoffs)
216 {
217 	K053936_offset[chip][0] = xoffs;
218 	K053936_offset[chip][1] = yoffs;
219 }
220 
221 
222 
223 
224 /***************************************************************************/
225 /*                                                                         */
226 /*                                 053936                                  */
227 /*                                                                         */
228 /***************************************************************************/
229 
230 DEFINE_DEVICE_TYPE(K053936, k053936_device, "k053936", "K053936 Video Controller")
231 
k053936_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)232 k053936_device::k053936_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
233 	: device_t(mconfig, K053936, tag, owner, clock),
234 	m_ctrl(nullptr),
235 	m_linectrl(nullptr),
236 	m_wrap(0),
237 	m_xoff(0),
238 	m_yoff(0)
239 {
240 }
241 
242 //-------------------------------------------------
243 //  device_start - device-specific startup
244 //-------------------------------------------------
245 
device_start()246 void k053936_device::device_start()
247 {
248 	m_ctrl = make_unique_clear<uint16_t[]>(0x20);
249 	m_linectrl = make_unique_clear<uint16_t[]>(0x4000);
250 
251 	save_pointer(NAME(m_ctrl), 0x20);
252 	save_pointer(NAME(m_linectrl), 0x4000);
253 }
254 
255 //-------------------------------------------------
256 //  device_reset - device-specific reset
257 //-------------------------------------------------
258 
device_reset()259 void k053936_device::device_reset()
260 {
261 	memset(m_ctrl.get(), 0, 0x20);
262 }
263 
264 
265 /*****************************************************************************
266     DEVICE HANDLERS
267 *****************************************************************************/
268 
ctrl_w(offs_t offset,uint16_t data,uint16_t mem_mask)269 void k053936_device::ctrl_w(offs_t offset, uint16_t data, uint16_t mem_mask)
270 {
271 	COMBINE_DATA(&m_ctrl[offset]);
272 }
273 
ctrl_r(offs_t offset)274 uint16_t k053936_device::ctrl_r(offs_t offset)
275 {
276 	return m_ctrl[offset];
277 }
278 
linectrl_w(offs_t offset,uint16_t data,uint16_t mem_mask)279 void k053936_device::linectrl_w(offs_t offset, uint16_t data, uint16_t mem_mask)
280 {
281 	COMBINE_DATA(&m_linectrl[offset]);
282 }
283 
linectrl_r(offs_t offset)284 uint16_t k053936_device::linectrl_r(offs_t offset)
285 {
286 	return m_linectrl[offset];
287 }
288 
289 // there is another implementation of this in  video/konamigx.c (!)
290 //  why? shall they be merged?
zoom_draw(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect,tilemap_t * tmap,int flags,uint32_t priority,int glfgreat_hack)291 void k053936_device::zoom_draw( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, tilemap_t *tmap, int flags, uint32_t priority, int glfgreat_hack )
292 {
293 	if (!tmap)
294 		return;
295 
296 	if (m_ctrl[0x07] & 0x0040)
297 	{
298 		uint32_t startx, starty;
299 		int incxx, incxy;
300 		rectangle my_clip;
301 		int y, maxy;
302 
303 		// Racin' Force will get to here if glfgreat_hack is enabled, and it ends
304 		// up setting a maximum y value of '13', thus causing nothing to be drawn.
305 		// It looks like the roz output should be flipped somehow as it seems to be
306 		// displaying the wrong areas of the tilemap and is rendered upside down,
307 		// although due to the additional post-processing the voxel renderer performs
308 		// it's difficult to know what the output SHOULD be.  (hold W in Racin' Force
309 		// to see the chip output)
310 
311 		if (((m_ctrl[0x07] & 0x0002) && m_ctrl[0x09]) && (glfgreat_hack)) /* wrong, but fixes glfgreat */
312 		{
313 			my_clip.min_x = m_ctrl[0x08] + m_xoff + 2;
314 			my_clip.max_x = m_ctrl[0x09] + m_xoff + 2 - 1;
315 			if (my_clip.min_x < cliprect.min_x)
316 				my_clip.min_x = cliprect.min_x;
317 			if (my_clip.max_x > cliprect.max_x)
318 				my_clip.max_x = cliprect.max_x;
319 
320 			y = m_ctrl[0x0a] + m_yoff - 2;
321 			if (y < cliprect.min_y)
322 				y = cliprect.min_y;
323 			maxy = m_ctrl[0x0b] + m_yoff - 2 - 1;
324 			if (maxy > cliprect.max_y)
325 				maxy = cliprect.max_y;
326 		}
327 		else
328 		{
329 			my_clip.min_x = cliprect.min_x;
330 			my_clip.max_x = cliprect.max_x;
331 
332 			y = cliprect.min_y;
333 			maxy = cliprect.max_y;
334 		}
335 
336 		while (y <= maxy)
337 		{
338 			uint16_t *lineaddr = m_linectrl.get() + 4 * ((y - m_yoff) & 0x1ff);
339 
340 			my_clip.min_y = my_clip.max_y = y;
341 
342 			startx = 256 * (int16_t)(lineaddr[0] + m_ctrl[0x00]);
343 			starty = 256 * (int16_t)(lineaddr[1] + m_ctrl[0x01]);
344 			incxx  =       (int16_t)(lineaddr[2]);
345 			incxy  =       (int16_t)(lineaddr[3]);
346 
347 			if (m_ctrl[0x06] & 0x8000)
348 				incxx *= 256;
349 
350 			if (m_ctrl[0x06] & 0x0080)
351 				incxy *= 256;
352 
353 			startx -= m_xoff * incxx;
354 			starty -= m_xoff * incxy;
355 
356 			tmap->draw_roz(screen, bitmap, my_clip, startx << 5,starty << 5,
357 					incxx << 5,incxy << 5,0,0,
358 					m_wrap,
359 					flags,priority);
360 
361 			y++;
362 		}
363 	}
364 	else    /* "simple" mode */
365 	{
366 		uint32_t startx, starty;
367 		int incxx, incxy, incyx, incyy;
368 
369 		startx = 256 * (int16_t)(m_ctrl[0x00]);
370 		starty = 256 * (int16_t)(m_ctrl[0x01]);
371 		incyx  =       (int16_t)(m_ctrl[0x02]);
372 		incyy  =       (int16_t)(m_ctrl[0x03]);
373 		incxx  =       (int16_t)(m_ctrl[0x04]);
374 		incxy  =       (int16_t)(m_ctrl[0x05]);
375 
376 		if (m_ctrl[0x06] & 0x4000)
377 		{
378 			incyx *= 256;
379 			incyy *= 256;
380 		}
381 
382 		if (m_ctrl[0x06] & 0x0040)
383 		{
384 			incxx *= 256;
385 			incxy *= 256;
386 		}
387 
388 		startx -= m_yoff * incyx;
389 		starty -= m_yoff * incyy;
390 
391 		startx -= m_xoff * incxx;
392 		starty -= m_xoff * incxy;
393 
394 		tmap->draw_roz(screen, bitmap, cliprect, startx << 5,starty << 5,
395 				incxx << 5,incxy << 5,incyx << 5,incyy << 5,
396 				m_wrap,
397 				flags,priority);
398 	}
399 
400 #if 0
401 if (machine.input().code_pressed(KEYCODE_D))
402 	popmessage("%04x %04x %04x %04x\n%04x %04x %04x %04x\n%04x %04x %04x %04x\n%04x %04x %04x %04x",
403 			m_ctrl[0x00],
404 			m_ctrl[0x01],
405 			m_ctrl[0x02],
406 			m_ctrl[0x03],
407 			m_ctrl[0x04],
408 			m_ctrl[0x05],
409 			m_ctrl[0x06],
410 			m_ctrl[0x07],
411 			m_ctrl[0x08],
412 			m_ctrl[0x09],
413 			m_ctrl[0x0a],
414 			m_ctrl[0x0b],
415 			m_ctrl[0x0c],
416 			m_ctrl[0x0d],
417 			m_ctrl[0x0e],
418 			m_ctrl[0x0f]);
419 #endif
420 }
421 
zoom_draw(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect,tilemap_t * tmap,int flags,uint32_t priority,int glfgreat_hack)422 void k053936_device::zoom_draw( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, tilemap_t *tmap, int flags, uint32_t priority, int glfgreat_hack )
423 {
424 	if (!tmap)
425 		return;
426 
427 	if (m_ctrl[0x07] & 0x0040)
428 	{
429 		uint32_t startx, starty;
430 		int incxx, incxy;
431 		rectangle my_clip;
432 		int y, maxy;
433 
434 		// Racin' Force will get to here if glfgreat_hack is enabled, and it ends
435 		// up setting a maximum y value of '13', thus causing nothing to be drawn.
436 		// It looks like the roz output should be flipped somehow as it seems to be
437 		// displaying the wrong areas of the tilemap and is rendered upside down,
438 		// although due to the additional post-processing the voxel renderer performs
439 		// it's difficult to know what the output SHOULD be.  (hold W in Racin' Force
440 		// to see the chip output)
441 
442 		if (((m_ctrl[0x07] & 0x0002) && m_ctrl[0x09]) && (glfgreat_hack)) /* wrong, but fixes glfgreat */
443 		{
444 			my_clip.min_x = m_ctrl[0x08] + m_xoff + 2;
445 			my_clip.max_x = m_ctrl[0x09] + m_xoff + 2 - 1;
446 			if (my_clip.min_x < cliprect.min_x)
447 				my_clip.min_x = cliprect.min_x;
448 			if (my_clip.max_x > cliprect.max_x)
449 				my_clip.max_x = cliprect.max_x;
450 
451 			y = m_ctrl[0x0a] + m_yoff - 2;
452 			if (y < cliprect.min_y)
453 				y = cliprect.min_y;
454 			maxy = m_ctrl[0x0b] + m_yoff - 2 - 1;
455 			if (maxy > cliprect.max_y)
456 				maxy = cliprect.max_y;
457 		}
458 		else
459 		{
460 			my_clip.min_x = cliprect.min_x;
461 			my_clip.max_x = cliprect.max_x;
462 
463 			y = cliprect.min_y;
464 			maxy = cliprect.max_y;
465 		}
466 
467 		while (y <= maxy)
468 		{
469 			uint16_t *lineaddr = m_linectrl.get() + 4 * ((y - m_yoff) & 0x1ff);
470 
471 			my_clip.min_y = my_clip.max_y = y;
472 
473 			startx = 256 * (int16_t)(lineaddr[0] + m_ctrl[0x00]);
474 			starty = 256 * (int16_t)(lineaddr[1] + m_ctrl[0x01]);
475 			incxx  =       (int16_t)(lineaddr[2]);
476 			incxy  =       (int16_t)(lineaddr[3]);
477 
478 			if (m_ctrl[0x06] & 0x8000)
479 				incxx *= 256;
480 
481 			if (m_ctrl[0x06] & 0x0080)
482 				incxy *= 256;
483 
484 			startx -= m_xoff * incxx;
485 			starty -= m_xoff * incxy;
486 
487 			tmap->draw_roz(screen, bitmap, my_clip, startx << 5,starty << 5,
488 					incxx << 5,incxy << 5,0,0,
489 					m_wrap,
490 					flags,priority);
491 
492 			y++;
493 		}
494 	}
495 	else    /* "simple" mode */
496 	{
497 		uint32_t startx, starty;
498 		int incxx, incxy, incyx, incyy;
499 
500 		startx = 256 * (int16_t)(m_ctrl[0x00]);
501 		starty = 256 * (int16_t)(m_ctrl[0x01]);
502 		incyx  =       (int16_t)(m_ctrl[0x02]);
503 		incyy  =       (int16_t)(m_ctrl[0x03]);
504 		incxx  =       (int16_t)(m_ctrl[0x04]);
505 		incxy  =       (int16_t)(m_ctrl[0x05]);
506 
507 		if (m_ctrl[0x06] & 0x4000)
508 		{
509 			incyx *= 256;
510 			incyy *= 256;
511 		}
512 
513 		if (m_ctrl[0x06] & 0x0040)
514 		{
515 			incxx *= 256;
516 			incxy *= 256;
517 		}
518 
519 		startx -= m_yoff * incyx;
520 		starty -= m_yoff * incyy;
521 
522 		startx -= m_xoff * incxx;
523 		starty -= m_xoff * incxy;
524 
525 		tmap->draw_roz(screen, bitmap, cliprect, startx << 5,starty << 5,
526 				incxx << 5,incxy << 5,incyx << 5,incyy << 5,
527 				m_wrap,
528 				flags,priority);
529 	}
530 }
531 
532 
533 
534 
K053936GP_set_offset(int chip,int xoffs,int yoffs)535 void K053936GP_set_offset(int chip, int xoffs, int yoffs) { K053936_offset[chip][0] = xoffs; K053936_offset[chip][1] = yoffs; }
536 
K053936GP_clip_enable(int chip,int status)537 void K053936GP_clip_enable(int chip, int status) { K053936_clip_enabled[chip] = status; }
538 
K053936GP_set_cliprect(int chip,int minx,int maxx,int miny,int maxy)539 void K053936GP_set_cliprect(int chip, int minx, int maxx, int miny, int maxy)
540 {
541 	rectangle &cliprect = K053936_cliprect[chip];
542 	cliprect.set(minx, maxx, miny, maxy);
543 }
544 
K053936GP_copyroz32clip(running_machine & machine,bitmap_rgb32 & dst_bitmap,bitmap_ind16 & src_bitmap,const rectangle & dst_cliprect,const rectangle & src_cliprect,uint32_t _startx,uint32_t _starty,int _incxx,int _incxy,int _incyx,int _incyy,int tilebpp,int blend,int alpha,int clip,int pixeldouble_output,palette_device & palette)545 static inline void K053936GP_copyroz32clip( running_machine &machine,
546 		bitmap_rgb32 &dst_bitmap, bitmap_ind16 &src_bitmap,
547 		const rectangle &dst_cliprect, const rectangle &src_cliprect,
548 		uint32_t _startx,uint32_t _starty,int _incxx,int _incxy,int _incyx,int _incyy,
549 		int tilebpp, int blend, int alpha, int clip, int pixeldouble_output, palette_device &palette )
550 {
551 	static const int colormask[8]={1,3,7,0xf,0x1f,0x3f,0x7f,0xff};
552 	int cy, cx;
553 	int ecx;
554 	int src_pitch, incxy, incxx;
555 	int src_minx, src_maxx, src_miny, src_maxy, cmask;
556 	uint16_t *src_base;
557 	size_t src_size;
558 
559 	const pen_t *pal_base;
560 	int dst_ptr;
561 	int dst_size;
562 	int dst_base2;
563 
564 	int tx, dst_pitch;
565 	uint32_t *dst_base;
566 	int starty, incyy, startx, incyx, ty, sx, sy;
567 
568 	incxy = _incxy; incxx = _incxx; incyy = _incyy; incyx = _incyx;
569 	starty = _starty; startx = _startx;
570 
571 	if (clip) // set source clip range to some extreme values when disabled
572 	{
573 		src_minx = src_cliprect.min_x;
574 		src_maxx = src_cliprect.max_x;
575 		src_miny = src_cliprect.min_y;
576 		src_maxy = src_cliprect.max_y;
577 	}
578 	// this simply isn't safe to do!
579 	else { src_minx = src_miny = -0x10000; src_maxx = src_maxy = 0x10000; }
580 
581 	// set target clip range
582 	sx = dst_cliprect.min_x;
583 	tx = dst_cliprect.max_x - sx + 1;
584 	sy = dst_cliprect.min_y;
585 	ty = dst_cliprect.max_y - sy + 1;
586 
587 	startx += sx * incxx + sy * incyx;
588 	starty += sx * incxy + sy * incyy;
589 
590 	// adjust entry points and other loop constants
591 	dst_pitch = dst_bitmap.rowpixels();
592 	dst_base = &dst_bitmap.pix(0);
593 	dst_base2 = sy * dst_pitch + sx + tx;
594 	ecx = tx = -tx;
595 
596 	tilebpp = (tilebpp-1) & 7;
597 	pal_base = palette.pens();
598 	cmask = colormask[tilebpp];
599 
600 	src_pitch = src_bitmap.rowpixels();
601 	src_base = &src_bitmap.pix(0);
602 	src_size = src_bitmap.width() * src_bitmap.height();
603 	dst_size = dst_bitmap.width() * dst_bitmap.height();
604 	dst_ptr = 0;//dst_base;
605 	cy = starty;
606 	cx = startx;
607 
608 	if (blend > 0)
609 	{
610 		dst_ptr += dst_pitch;      // draw blended
611 		starty += incyy;
612 		startx += incyx;
613 
614 		do {
615 			do {
616 				int srcx = (cx >> 16) & 0x1fff;
617 				int srcy = (cy >> 16) & 0x1fff;
618 				int pixel;
619 				uint32_t offs;
620 				offs = srcy * src_pitch + srcx;
621 
622 				cx += incxx;
623 				cy += incxy;
624 
625 				if (offs>=src_size)
626 					continue;
627 
628 				if (srcx < src_minx || srcx > src_maxx || srcy < src_miny || srcy > src_maxy)
629 					continue;
630 
631 				pixel = src_base[offs];
632 				if (!(pixel & cmask))
633 					continue;
634 
635 				if ((dst_ptr+ecx+dst_base2)<dst_size) dst_base[dst_ptr+ecx+dst_base2] = alpha_blend_r32(pal_base[pixel], dst_base[dst_ptr+ecx+dst_base2], alpha);
636 
637 				if (pixeldouble_output)
638 				{
639 					ecx++;
640 					if ((dst_ptr+ecx+dst_base2)<dst_size) dst_base[dst_ptr+ecx+dst_base2] = alpha_blend_r32(pal_base[pixel], dst_base[dst_ptr+ecx+dst_base2], alpha);
641 				}
642 			}
643 			while (++ecx < 0);
644 
645 			ecx = tx;
646 			dst_ptr += dst_pitch;
647 			cy = starty; starty += incyy;
648 			cx = startx; startx += incyx;
649 		} while (--ty);
650 	}
651 	else    //  draw solid
652 	{
653 		dst_ptr += dst_pitch;
654 		starty += incyy;
655 		startx += incyx;
656 
657 		do {
658 			do {
659 				int srcx = (cx >> 16) & 0x1fff;
660 				int srcy = (cy >> 16) & 0x1fff;
661 				int pixel;
662 				uint32_t offs;
663 
664 				offs = srcy * src_pitch + srcx;
665 
666 				cx += incxx;
667 				cy += incxy;
668 
669 				if (offs>=src_size)
670 					continue;
671 
672 				if (srcx < src_minx || srcx > src_maxx || srcy < src_miny || srcy > src_maxy)
673 					continue;
674 
675 				pixel = src_base[offs];
676 				if (!(pixel & cmask))
677 					continue;
678 
679 
680 
681 				if ((dst_ptr+ecx+dst_base2)<dst_size) dst_base[dst_ptr+ecx+dst_base2] = pal_base[pixel];
682 
683 				if (pixeldouble_output)
684 				{
685 					ecx++;
686 					if ((dst_ptr+ecx+dst_base2)<dst_size) dst_base[dst_ptr+ecx+dst_base2] = pal_base[pixel];
687 				}
688 			}
689 			while (++ecx < 0);
690 
691 			ecx = tx;
692 			dst_ptr += dst_pitch;
693 			cy = starty; starty += incyy;
694 			cx = startx; startx += incyx;
695 		} while (--ty);
696 	}
697 }
698 
699 // adapted from generic K053936_zoom_draw()
K053936GP_zoom_draw(running_machine & machine,int chip,uint16_t * ctrl,uint16_t * linectrl,bitmap_rgb32 & bitmap,const rectangle & cliprect,tilemap_t * tmap,int tilebpp,int blend,int alpha,int pixeldouble_output,palette_device & palette)700 static void K053936GP_zoom_draw(running_machine &machine,
701 		int chip, uint16_t *ctrl, uint16_t *linectrl,
702 		bitmap_rgb32 &bitmap, const rectangle &cliprect, tilemap_t *tmap,
703 		int tilebpp, int blend, int alpha, int pixeldouble_output, palette_device &palette)
704 {
705 	uint16_t *lineaddr;
706 
707 	rectangle my_clip;
708 	uint32_t startx, starty;
709 	int incxx, incxy, incyx, incyy, y, maxy, clip;
710 
711 	bitmap_ind16 &src_bitmap = tmap->pixmap();
712 	rectangle &src_cliprect = K053936_cliprect[chip];
713 	clip = K053936_clip_enabled[chip];
714 
715 	if (ctrl[0x07] & 0x0040)    /* "super" mode */
716 	{
717 		my_clip.min_x = cliprect.min_x;
718 		my_clip.max_x = cliprect.max_x;
719 		y = cliprect.min_y;
720 		maxy = cliprect.max_y;
721 
722 		while (y <= maxy)
723 		{
724 			lineaddr = linectrl + ( ((y - K053936_offset[chip][1]) & 0x1ff) << 2);
725 			my_clip.min_y = my_clip.max_y = y;
726 
727 			startx = (int16_t)(lineaddr[0] + ctrl[0x00]) << 8;
728 			starty = (int16_t)(lineaddr[1] + ctrl[0x01]) << 8;
729 			incxx  = (int16_t)(lineaddr[2]);
730 			incxy  = (int16_t)(lineaddr[3]);
731 
732 			if (ctrl[0x06] & 0x8000) incxx <<= 8;
733 			if (ctrl[0x06] & 0x0080) incxy <<= 8;
734 
735 			startx -= K053936_offset[chip][0] * incxx;
736 			starty -= K053936_offset[chip][0] * incxy;
737 
738 			K053936GP_copyroz32clip(machine,
739 					bitmap, src_bitmap, my_clip, src_cliprect,
740 					startx<<5, starty<<5, incxx<<5, incxy<<5, 0, 0,
741 					tilebpp, blend, alpha, clip, pixeldouble_output, palette);
742 			y++;
743 		}
744 	}
745 	else    /* "simple" mode */
746 	{
747 		startx = (int16_t)(ctrl[0x00]) << 8;
748 		starty = (int16_t)(ctrl[0x01]) << 8;
749 		incyx  = (int16_t)(ctrl[0x02]);
750 		incyy  = (int16_t)(ctrl[0x03]);
751 		incxx  = (int16_t)(ctrl[0x04]);
752 		incxy  = (int16_t)(ctrl[0x05]);
753 
754 		if (ctrl[0x06] & 0x4000) { incyx <<= 8; incyy <<= 8; }
755 		if (ctrl[0x06] & 0x0040) { incxx <<= 8; incxy <<= 8; }
756 
757 		startx -= K053936_offset[chip][1] * incyx;
758 		starty -= K053936_offset[chip][1] * incyy;
759 
760 		startx -= K053936_offset[chip][0] * incxx;
761 		starty -= K053936_offset[chip][0] * incxy;
762 
763 		K053936GP_copyroz32clip(machine,
764 				bitmap, src_bitmap, cliprect, src_cliprect,
765 				startx<<5, starty<<5, incxx<<5, incxy<<5, incyx<<5, incyy<<5,
766 				tilebpp, blend, alpha, clip, pixeldouble_output, palette);
767 	}
768 }
769 
K053936GP_0_zoom_draw(running_machine & machine,bitmap_rgb32 & bitmap,const rectangle & cliprect,tilemap_t * tmap,int tilebpp,int blend,int alpha,int pixeldouble_output,uint16_t * temp_m_k053936_0_ctrl_16,uint16_t * temp_m_k053936_0_linectrl_16,uint16_t * temp_m_k053936_0_ctrl,uint16_t * temp_m_k053936_0_linectrl,palette_device & palette)770 void K053936GP_0_zoom_draw(running_machine &machine, bitmap_rgb32 &bitmap, const rectangle &cliprect,
771 		tilemap_t *tmap, int tilebpp, int blend, int alpha, int pixeldouble_output, uint16_t* temp_m_k053936_0_ctrl_16, uint16_t* temp_m_k053936_0_linectrl_16,uint16_t* temp_m_k053936_0_ctrl, uint16_t* temp_m_k053936_0_linectrl, palette_device &palette)
772 {
773 	if (temp_m_k053936_0_ctrl_16)
774 	{
775 		K053936GP_zoom_draw(machine, 0,temp_m_k053936_0_ctrl_16,temp_m_k053936_0_linectrl_16,bitmap,cliprect,tmap,tilebpp,blend,alpha, pixeldouble_output, palette);
776 	}
777 	else
778 	{
779 		K053936GP_zoom_draw(machine, 0,temp_m_k053936_0_ctrl,temp_m_k053936_0_linectrl,bitmap,cliprect,tmap,tilebpp,blend,alpha, pixeldouble_output, palette);
780 	}
781 }
782