1 /***************************************************************************
2 
3   atarigen.c
4 
5   General functions for mid-to-late 80's Atari raster games.
6 
7 ***************************************************************************/
8 
9 
10 #include "driver.h"
11 #include "atarigen.h"
12 #include "cpu/m6502/m6502.h"
13 
14 
15 /*--------------------------------------------------------------------------
16 
17 	Atari generic interrupt model (required)
18 
19 		atarigen_scanline_int_state - state of the scanline interrupt line
20 		atarigen_sound_int_state - state of the sound interrupt line
21 		atarigen_video_int_state - state of the video interrupt line
22 
23 		atarigen_int_callback - called when the interrupt state changes
24 
25 		atarigen_interrupt_reset - resets & initializes the interrupt state
26 		atarigen_update_interrupts - forces the interrupts to be reevaluted
27 
28 		atarigen_scanline_int_set - scanline interrupt initialization
29 		atarigen_scanline_int_gen - scanline interrupt generator
30 		atarigen_scanline_int_ack_w - scanline interrupt acknowledgement
31 
32 		atarigen_sound_int_gen - sound interrupt generator
33 		atarigen_sound_int_ack_w - sound interrupt acknowledgement
34 
35 		atarigen_video_int_gen - video interrupt generator
36 		atarigen_video_int_ack_w - video interrupt acknowledgement
37 
38 --------------------------------------------------------------------------*/
39 
40 /* globals */
41 int atarigen_scanline_int_state;
42 int atarigen_sound_int_state;
43 int atarigen_video_int_state;
44 
45 /* statics */
46 static atarigen_int_callback update_int_callback;
47 static void *scanline_interrupt_timer;
48 
49 /* prototypes */
50 static void scanline_interrupt_callback(int param);
51 
52 
53 /*
54  *	Interrupt initialization
55  *
56  *	Resets the various interrupt states.
57  *
58  */
59 
atarigen_interrupt_reset(atarigen_int_callback update_int)60 void atarigen_interrupt_reset(atarigen_int_callback update_int)
61 {
62 	/* set the callback */
63 	update_int_callback = update_int;
64 
65 	/* reset the interrupt states */
66 	atarigen_video_int_state = atarigen_sound_int_state = atarigen_scanline_int_state = 0;
67 	scanline_interrupt_timer = NULL;
68 }
69 
70 
71 /*
72  *	Update interrupts
73  *
74  *	Forces the interrupt callback to be called with the current VBLANK and sound interrupt states.
75  *
76  */
77 
atarigen_update_interrupts(void)78 void atarigen_update_interrupts(void)
79 {
80 	(*update_int_callback)();
81 }
82 
83 
84 
85 /*
86  *	Scanline interrupt initialization
87  *
88  *	Sets the scanline when the next scanline interrupt should be generated.
89  *
90  */
91 
atarigen_scanline_int_set(int scanline)92 void atarigen_scanline_int_set(int scanline)
93 {
94 	if (scanline_interrupt_timer)
95 		timer_remove(scanline_interrupt_timer);
96 	scanline_interrupt_timer = timer_set(cpu_getscanlinetime(scanline), 0, scanline_interrupt_callback);
97 }
98 
99 
100 /*
101  *	Scanline interrupt generator
102  *
103  *	Standard interrupt routine which sets the scanline interrupt state.
104  *
105  */
106 
atarigen_scanline_int_gen(void)107 int atarigen_scanline_int_gen(void)
108 {
109 	atarigen_scanline_int_state = 1;
110 	(*update_int_callback)();
111 	return 0;
112 }
113 
114 
115 /*
116  *	Scanline interrupt acknowledge write handler
117  *
118  *	Resets the state of the scanline interrupt.
119  *
120  */
121 
WRITE_HANDLER(atarigen_scanline_int_ack_w)122 WRITE_HANDLER( atarigen_scanline_int_ack_w )
123 {
124 	atarigen_scanline_int_state = 0;
125 	(*update_int_callback)();
126 }
127 
128 
129 /*
130  *	Sound interrupt generator
131  *
132  *	Standard interrupt routine which sets the sound interrupt state.
133  *
134  */
135 
atarigen_sound_int_gen(void)136 int atarigen_sound_int_gen(void)
137 {
138 	atarigen_sound_int_state = 1;
139 	(*update_int_callback)();
140 	return 0;
141 }
142 
143 
144 /*
145  *	Sound interrupt acknowledge write handler
146  *
147  *	Resets the state of the sound interrupt.
148  *
149  */
150 
WRITE_HANDLER(atarigen_sound_int_ack_w)151 WRITE_HANDLER( atarigen_sound_int_ack_w )
152 {
153 	atarigen_sound_int_state = 0;
154 	(*update_int_callback)();
155 }
156 
157 
158 /*
159  *	Video interrupt generator
160  *
161  *	Standard interrupt routine which sets the video interrupt state.
162  *
163  */
164 
atarigen_video_int_gen(void)165 int atarigen_video_int_gen(void)
166 {
167 	atarigen_video_int_state = 1;
168 	(*update_int_callback)();
169 	return 0;
170 }
171 
172 
173 /*
174  *	Video interrupt acknowledge write handler
175  *
176  *	Resets the state of the video interrupt.
177  *
178  */
179 
WRITE_HANDLER(atarigen_video_int_ack_w)180 WRITE_HANDLER( atarigen_video_int_ack_w )
181 {
182 	atarigen_video_int_state = 0;
183 	(*update_int_callback)();
184 }
185 
186 
187 /*
188  *	Scanline interrupt generator
189  *
190  *	Signals an interrupt.
191  *
192  */
193 
scanline_interrupt_callback(int param)194 static void scanline_interrupt_callback(int param)
195 {
196 	/* generate the interrupt */
197 	atarigen_scanline_int_gen();
198 
199 	/* set a new timer to go off at the same scan line next frame */
200 	scanline_interrupt_timer = timer_set(TIME_IN_HZ(Machine->drv->frames_per_second), 0, scanline_interrupt_callback);
201 }
202 
203 
204 
205 /*--------------------------------------------------------------------------
206 
207 	EEPROM I/O (optional)
208 
209 		atarigen_eeprom_default - pointer to compressed default data
210 		atarigen_eeprom - pointer to base of EEPROM memory
211 		atarigen_eeprom_size - size of EEPROM memory
212 
213 		atarigen_eeprom_reset - resets the EEPROM system
214 
215 		atarigen_eeprom_enable_w - write handler to enable EEPROM access
216 		atarigen_eeprom_w - write handler for EEPROM data (low byte)
217 		atarigen_eeprom_r - read handler for EEPROM data (low byte)
218 
219 		atarigen_nvram_handler - load/save EEPROM data
220 
221 --------------------------------------------------------------------------*/
222 
223 /* globals */
224 const UINT16 *atarigen_eeprom_default;
225 UINT8 *atarigen_eeprom;
226 size_t atarigen_eeprom_size;
227 
228 /* statics */
229 static UINT8 unlocked;
230 
231 /* prototypes */
232 static void decompress_eeprom_word(const UINT16 *data);
233 static void decompress_eeprom_byte(const UINT16 *data);
234 
235 
236 /*
237  *	EEPROM reset
238  *
239  *	Makes sure that the unlocked state is cleared when we reset.
240  *
241  */
242 
atarigen_eeprom_reset(void)243 void atarigen_eeprom_reset(void)
244 {
245 	unlocked = 0;
246 }
247 
248 
249 /*
250  *	EEPROM enable write handler
251  *
252  *	Any write to this handler will allow one byte to be written to the
253  *	EEPROM data area the next time.
254  *
255  */
256 
WRITE_HANDLER(atarigen_eeprom_enable_w)257 WRITE_HANDLER( atarigen_eeprom_enable_w )
258 {
259 	unlocked = 1;
260 }
261 
262 
263 /*
264  *	EEPROM write handler (low byte of word)
265  *
266  *	Writes a "word" to the EEPROM, which is almost always accessed via
267  *	the low byte of the word only. If the EEPROM hasn't been unlocked,
268  *	the write attempt is ignored.
269  *
270  */
271 
WRITE_HANDLER(atarigen_eeprom_w)272 WRITE_HANDLER( atarigen_eeprom_w )
273 {
274 	if (!unlocked)
275 		return;
276 
277 	COMBINE_WORD_MEM(&atarigen_eeprom[offset], data);
278 	unlocked = 0;
279 }
280 
281 
282 /*
283  *	EEPROM read handler (low byte of word)
284  *
285  *	Reads a "word" from the EEPROM, which is almost always accessed via
286  *	the low byte of the word only.
287  *
288  */
289 
READ_HANDLER(atarigen_eeprom_r)290 READ_HANDLER( atarigen_eeprom_r )
291 {
292 	return READ_WORD(&atarigen_eeprom[offset]) | 0xff00;
293 }
294 
READ_HANDLER(atarigen_eeprom_upper_r)295 READ_HANDLER( atarigen_eeprom_upper_r )
296 {
297 	return READ_WORD(&atarigen_eeprom[offset]) | 0x00ff;
298 }
299 
300 
301 /*
302  *	Standard high score load
303  *
304  *	Loads the EEPROM data as a "high score".
305  *
306  */
307 
atarigen_nvram_handler(void * file,int read_or_write)308 void atarigen_nvram_handler(void *file,int read_or_write)
309 {
310 	if (read_or_write)
311 		osd_fwrite(file, atarigen_eeprom, atarigen_eeprom_size);
312 	else
313 	{
314 		if (file)
315 			osd_fread(file, atarigen_eeprom, atarigen_eeprom_size);
316 		else
317 		{
318 			/* all 0xff's work for most games */
319 			memset(atarigen_eeprom, 0xff, atarigen_eeprom_size);
320 
321 			/* anything else must be decompressed */
322 			if (atarigen_eeprom_default)
323 			{
324 				if (atarigen_eeprom_default[0] == 0)
325 					decompress_eeprom_byte(atarigen_eeprom_default + 1);
326 				else
327 					decompress_eeprom_word(atarigen_eeprom_default + 1);
328 			}
329 		}
330 	}
331 }
332 
333 
334 
335 /*
336  *	Decompress word-based EEPROM data
337  *
338  *	Used for decompressing EEPROM data that has every other byte invalid.
339  *
340  */
341 
decompress_eeprom_word(const UINT16 * data)342 void decompress_eeprom_word(const UINT16 *data)
343 {
344 	UINT16 *dest = (UINT16 *)atarigen_eeprom;
345 	UINT16 value;
346 
347 	while ((value = *data++) != 0)
348 	{
349 		int count = (value >> 8);
350 		value = (value << 8) | (value & 0xff);
351 
352 		while (count--)
353 		{
354 			WRITE_WORD(dest, value);
355 			dest++;
356 		}
357 	}
358 }
359 
360 
361 /*
362  *	Decompress byte-based EEPROM data
363  *
364  *	Used for decompressing EEPROM data that is byte-packed.
365  *
366  */
367 
decompress_eeprom_byte(const UINT16 * data)368 void decompress_eeprom_byte(const UINT16 *data)
369 {
370 	UINT8 *dest = (UINT8 *)atarigen_eeprom;
371 	UINT16 value;
372 
373 	while ((value = *data++) != 0)
374 	{
375 		int count = (value >> 8);
376 		value = (value << 8) | (value & 0xff);
377 
378 		while (count--)
379 			*dest++ = value;
380 	}
381 }
382 
383 
384 
385 /*--------------------------------------------------------------------------
386 
387 	Slapstic I/O (optional)
388 
389 		atarigen_slapstic - pointer to base of slapstic memory
390 
391 		atarigen_slapstic_init - select and initialize the slapstic handlers
392 		atarigen_slapstic_reset - resets the slapstic state
393 
394 		atarigen_slapstic_w - write handler for slapstic data
395 		atarigen_slapstic_r - read handler for slapstic data
396 
397 		slapstic_init - low-level init routine
398 		slapstic_reset - low-level reset routine
399 		slapstic_bank - low-level routine to return the current bank
400 		slapstic_tweak - low-level tweak routine
401 
402 --------------------------------------------------------------------------*/
403 
404 /* globals */
405 static UINT8 atarigen_slapstic_num;
406 static UINT8 *atarigen_slapstic;
407 
408 
409 /*
410  *	Slapstic initialization
411  *
412  *	Installs memory handlers for the slapstic and sets the chip number.
413  *
414  */
415 
atarigen_slapstic_init(int cpunum,int base,int chipnum)416 void atarigen_slapstic_init(int cpunum, int base, int chipnum)
417 {
418 	atarigen_slapstic_num = chipnum;
419 	atarigen_slapstic = NULL;
420 	if (chipnum)
421 	{
422 		slapstic_init(chipnum);
423 		atarigen_slapstic = (UINT8*)install_mem_read_handler(cpunum, base, base + 0x7fff, atarigen_slapstic_r);
424 		atarigen_slapstic = (UINT8*)install_mem_write_handler(cpunum, base, base + 0x7fff, atarigen_slapstic_w);
425 	}
426 }
427 
428 
429 /*
430  *	Slapstic initialization
431  *
432  *	Makes the selected slapstic number active and resets its state.
433  *
434  */
435 
atarigen_slapstic_reset(void)436 void atarigen_slapstic_reset(void)
437 {
438 	if (atarigen_slapstic_num)
439 		slapstic_reset();
440 }
441 
442 
443 /*
444  *	Slapstic write handler
445  *
446  *	Assuming that the slapstic sits in ROM memory space, we just simply
447  *	tweak the slapstic at this address and do nothing more.
448  *
449  */
450 
WRITE_HANDLER(atarigen_slapstic_w)451 WRITE_HANDLER( atarigen_slapstic_w )
452 {
453 	slapstic_tweak(offset / 2);
454 }
455 
456 
457 /*
458  *	Slapstic read handler
459  *
460  *	Tweaks the slapstic at the appropriate address and then reads a
461  *	word from the underlying memory.
462  *
463  */
464 
READ_HANDLER(atarigen_slapstic_r)465 READ_HANDLER( atarigen_slapstic_r )
466 {
467 	int bank = slapstic_tweak(offset / 2) * 0x2000;
468 	return READ_WORD(&atarigen_slapstic[bank + (offset & 0x1fff)]);
469 }
470 
471 
472 
473 
474 /***********************************************************************************************/
475 /***********************************************************************************************/
476 /***********************************************************************************************/
477 /***********************************************************************************************/
478 /***********************************************************************************************/
479 
480 
481 
482 /*--------------------------------------------------------------------------
483 
484 	Sound I/O
485 
486 		atarigen_sound_io_reset - reset the sound I/O system
487 
488 		atarigen_6502_irq_gen - standard 6502 IRQ interrupt generator
489 		atarigen_6502_irq_ack_r - standard 6502 IRQ interrupt acknowledgement
490 		atarigen_6502_irq_ack_w - standard 6502 IRQ interrupt acknowledgement
491 
492 		atarigen_ym2151_irq_gen - YM2151 sound IRQ generator
493 
494 		atarigen_sound_w - Main CPU -> sound CPU data write (low byte)
495 		atarigen_sound_r - Sound CPU -> main CPU data read (low byte)
496 		atarigen_sound_upper_w - Main CPU -> sound CPU data write (high byte)
497 		atarigen_sound_upper_r - Sound CPU -> main CPU data read (high byte)
498 
499 		atarigen_sound_reset_w - 6502 CPU reset
500 		atarigen_6502_sound_w - Sound CPU -> main CPU data write
501 		atarigen_6502_sound_r - Main CPU -> sound CPU data read
502 
503 --------------------------------------------------------------------------*/
504 
505 /* constants */
506 #define SOUND_INTERLEAVE_RATE		TIME_IN_USEC(50)
507 #define SOUND_INTERLEAVE_REPEAT		20
508 
509 /* globals */
510 int atarigen_cpu_to_sound_ready;
511 int atarigen_sound_to_cpu_ready;
512 
513 /* statics */
514 static UINT8 sound_cpu_num;
515 static UINT8 atarigen_cpu_to_sound;
516 static UINT8 atarigen_sound_to_cpu;
517 static UINT8 timed_int;
518 static UINT8 ym2151_int;
519 
520 /* prototypes */
521 static void update_6502_irq(void);
522 static void sound_comm_timer(int reps_left);
523 static void delayed_sound_reset(int param);
524 static void delayed_sound_w(int param);
525 static void delayed_6502_sound_w(int param);
526 
527 
528 /*
529  *	Sound I/O reset
530  *
531  *	Resets the state of the sound I/O.
532  *
533  */
534 
atarigen_sound_io_reset(int cpu_num)535 void atarigen_sound_io_reset(int cpu_num)
536 {
537 	/* remember which CPU is the sound CPU */
538 	sound_cpu_num = cpu_num;
539 
540 	/* reset the internal interrupts states */
541 	timed_int = ym2151_int = 0;
542 
543 	/* reset the sound I/O states */
544 	atarigen_cpu_to_sound = atarigen_sound_to_cpu = 0;
545 	atarigen_cpu_to_sound_ready = atarigen_sound_to_cpu_ready = 0;
546 }
547 
548 
549 /*
550  *	6502 IRQ generator
551  *
552  *	Generates an IRQ signal to the 6502 sound processor.
553  *
554  */
555 
atarigen_6502_irq_gen(void)556 int atarigen_6502_irq_gen(void)
557 {
558 	timed_int = 1;
559 	update_6502_irq();
560 	return 0;
561 }
562 
563 
564 /*
565  *	6502 IRQ acknowledgement
566  *
567  *	Resets the IRQ signal to the 6502 sound processor. Both reads and writes can be used.
568  *
569  */
570 
READ_HANDLER(atarigen_6502_irq_ack_r)571 READ_HANDLER( atarigen_6502_irq_ack_r )
572 {
573 	timed_int = 0;
574 	update_6502_irq();
575 	return 0;
576 }
577 
WRITE_HANDLER(atarigen_6502_irq_ack_w)578 WRITE_HANDLER( atarigen_6502_irq_ack_w )
579 {
580 	timed_int = 0;
581 	update_6502_irq();
582 }
583 
584 
585 /*
586  *	YM2151 IRQ generation
587  *
588  *	Sets the state of the YM2151's IRQ line.
589  *
590  */
591 
atarigen_ym2151_irq_gen(int irq)592 void atarigen_ym2151_irq_gen(int irq)
593 {
594 	ym2151_int = irq;
595 	update_6502_irq();
596 }
597 
598 
599 /*
600  *	Sound CPU write handler
601  *
602  *	Write handler which resets the sound CPU in response.
603  *
604  */
605 
WRITE_HANDLER(atarigen_sound_reset_w)606 WRITE_HANDLER( atarigen_sound_reset_w )
607 {
608 	timer_set(TIME_NOW, 0, delayed_sound_reset);
609 }
610 
611 
612 /*
613  *	Sound CPU reset handler
614  *
615  *	Resets the state of the sound CPU manually.
616  *
617  */
618 
atarigen_sound_reset(void)619 void atarigen_sound_reset(void)
620 {
621 	timer_set(TIME_NOW, 1, delayed_sound_reset);
622 }
623 
624 
625 /*
626  *	Main -> sound CPU data write handlers
627  *
628  *	Handles communication from the main CPU to the sound CPU. Two versions are provided,
629  *	one with the data byte in the low 8 bits, and one with the data byte in the upper 8
630  *	bits.
631  *
632  */
633 
WRITE_HANDLER(atarigen_sound_w)634 WRITE_HANDLER( atarigen_sound_w )
635 {
636 	if (!(data & 0x00ff0000))
637 		timer_set(TIME_NOW, data & 0xff, delayed_sound_w);
638 }
639 
WRITE_HANDLER(atarigen_sound_upper_w)640 WRITE_HANDLER( atarigen_sound_upper_w )
641 {
642 	if (!(data & 0xff000000))
643 		timer_set(TIME_NOW, (data >> 8) & 0xff, delayed_sound_w);
644 }
645 
646 
647 /*
648  *	Sound -> main CPU data read handlers
649  *
650  *	Handles reading data communicated from the sound CPU to the main CPU. Two versions
651  *	are provided, one with the data byte in the low 8 bits, and one with the data byte
652  *	in the upper 8 bits.
653  *
654  */
655 
READ_HANDLER(atarigen_sound_r)656 READ_HANDLER( atarigen_sound_r )
657 {
658 	atarigen_sound_to_cpu_ready = 0;
659 	atarigen_sound_int_ack_w(0, 0);
660 	return atarigen_sound_to_cpu | 0xff00;
661 }
662 
READ_HANDLER(atarigen_sound_upper_r)663 READ_HANDLER( atarigen_sound_upper_r )
664 {
665 	atarigen_sound_to_cpu_ready = 0;
666 	atarigen_sound_int_ack_w(0, 0);
667 	return (atarigen_sound_to_cpu << 8) | 0x00ff;
668 }
669 
670 
671 /*
672  *	Sound -> main CPU data write handler
673  *
674  *	Handles communication from the sound CPU to the main CPU.
675  *
676  */
677 
WRITE_HANDLER(atarigen_6502_sound_w)678 WRITE_HANDLER( atarigen_6502_sound_w )
679 {
680 	timer_set(TIME_NOW, data, delayed_6502_sound_w);
681 }
682 
683 
684 /*
685  *	Main -> sound CPU data read handler
686  *
687  *	Handles reading data communicated from the main CPU to the sound CPU.
688  *
689  */
690 
READ_HANDLER(atarigen_6502_sound_r)691 READ_HANDLER( atarigen_6502_sound_r )
692 {
693 	atarigen_cpu_to_sound_ready = 0;
694 	cpu_set_nmi_line(sound_cpu_num, CLEAR_LINE);
695 	return atarigen_cpu_to_sound;
696 }
697 
698 
699 /*
700  *	6502 IRQ state updater
701  *
702  *	Called whenever the IRQ state changes. An interrupt is generated if
703  *	either atarigen_6502_irq_gen() was called, or if the YM2151 generated
704  *	an interrupt via the atarigen_ym2151_irq_gen() callback.
705  *
706  */
707 
update_6502_irq(void)708 void update_6502_irq(void)
709 {
710 	if (timed_int || ym2151_int)
711 		cpu_set_irq_line(sound_cpu_num, M6502_INT_IRQ, ASSERT_LINE);
712 	else
713 		cpu_set_irq_line(sound_cpu_num, M6502_INT_IRQ, CLEAR_LINE);
714 }
715 
716 
717 /*
718  *	Sound communications timer
719  *
720  *	Set whenever a command is written from the main CPU to the sound CPU, in order to
721  *	temporarily bump up the interleave rate. This helps ensure that communications
722  *	between the two CPUs works properly.
723  *
724  */
725 
sound_comm_timer(int reps_left)726 static void sound_comm_timer(int reps_left)
727 {
728 	if (--reps_left)
729 		timer_set(SOUND_INTERLEAVE_RATE, reps_left, sound_comm_timer);
730 }
731 
732 
733 /*
734  *	Sound CPU reset timer
735  *
736  *	Synchronizes the sound reset command between the two CPUs.
737  *
738  */
739 
delayed_sound_reset(int param)740 static void delayed_sound_reset(int param)
741 {
742 	/* unhalt and reset the sound CPU */
743 	if (param == 0)
744 	{
745 		cpu_set_halt_line(sound_cpu_num, CLEAR_LINE);
746 		cpu_set_reset_line(sound_cpu_num, PULSE_LINE);
747 	}
748 
749 	/* reset the sound write state */
750 	atarigen_sound_to_cpu_ready = 0;
751 	atarigen_sound_int_ack_w(0, 0);
752 }
753 
754 
755 /*
756  *	Main -> sound data write timer
757  *
758  *	Synchronizes a data write from the main CPU to the sound CPU.
759  *
760  */
761 
delayed_sound_w(int param)762 static void delayed_sound_w(int param)
763 {
764 	/* warn if we missed something */
765 	//if (atarigen_cpu_to_sound_ready)
766 	//	logerror("Missed command from 68010\n");
767 
768 	/* set up the states and signal an NMI to the sound CPU */
769 	atarigen_cpu_to_sound = param;
770 	atarigen_cpu_to_sound_ready = 1;
771 	cpu_set_nmi_line(sound_cpu_num, ASSERT_LINE);
772 
773 	/* allocate a high frequency timer until a response is generated */
774 	/* the main CPU is *very* sensistive to the timing of the response */
775 	timer_set(SOUND_INTERLEAVE_RATE, SOUND_INTERLEAVE_REPEAT, sound_comm_timer);
776 }
777 
778 
779 /*
780  *	Sound -> main data write timer
781  *
782  *	Synchronizes a data write from the sound CPU to the main CPU.
783  *
784  */
785 
delayed_6502_sound_w(int param)786 static void delayed_6502_sound_w(int param)
787 {
788 	/* warn if we missed something */
789 	//if (atarigen_sound_to_cpu_ready)
790 	//	logerror("Missed result from 6502\n");
791 
792 	/* set up the states and signal the sound interrupt to the main CPU */
793 	atarigen_sound_to_cpu = param;
794 	atarigen_sound_to_cpu_ready = 1;
795 	atarigen_sound_int_gen();
796 }
797 
798 
799 
800 /*--------------------------------------------------------------------------
801 
802 	Misc sound helpers
803 
804 		atarigen_init_6502_speedup - installs 6502 speedup cheat handler
805 		atarigen_set_ym2151_vol - set the volume of the 2151 chip
806 		atarigen_set_ym2413_vol - set the volume of the 2151 chip
807 		atarigen_set_pokey_vol - set the volume of the POKEY chip(s)
808 		atarigen_set_tms5220_vol - set the volume of the 5220 chip
809 		atarigen_set_oki6295_vol - set the volume of the OKI6295
810 
811 --------------------------------------------------------------------------*/
812 
813 /* statics */
814 static UINT8 *speed_a, *speed_b;
815 static UINT32 speed_pc;
816 
817 /* prototypes */
818 static READ_HANDLER( m6502_speedup_r );
819 
820 
821 /*
822  *	6502 CPU speedup cheat installer
823  *
824  *	Installs a special read handler to catch the main spin loop in the
825  *	6502 sound code. The addresses accessed seem to be the same across
826  *	a large number of games, though the PC shifts.
827  *
828  */
829 
atarigen_init_6502_speedup(int cpunum,int compare_pc1,int compare_pc2)830 void atarigen_init_6502_speedup(int cpunum, int compare_pc1, int compare_pc2)
831 {
832 	UINT8 *memory = memory_region(REGION_CPU1+cpunum);
833 	int address_low, address_high;
834 
835 	/* determine the pointer to the first speed check location */
836 	address_low = memory[compare_pc1 + 1] | (memory[compare_pc1 + 2] << 8);
837 	address_high = memory[compare_pc1 + 4] | (memory[compare_pc1 + 5] << 8);
838 	//if (address_low != address_high - 1)
839 	//	logerror("Error: address %04X does not point to a speedup location!", compare_pc1);
840 	speed_a = &memory[address_low];
841 
842 	/* determine the pointer to the second speed check location */
843 	address_low = memory[compare_pc2 + 1] | (memory[compare_pc2 + 2] << 8);
844 	address_high = memory[compare_pc2 + 4] | (memory[compare_pc2 + 5] << 8);
845 	//if (address_low != address_high - 1)
846 	//	logerror("Error: address %04X does not point to a speedup location!", compare_pc2);
847 	speed_b = &memory[address_low];
848 
849 	/* install a handler on the second address */
850 	speed_pc = compare_pc2;
851 	install_mem_read_handler(cpunum, address_low, address_low, m6502_speedup_r);
852 }
853 
854 
855 /*
856  *	Set the YM2151 volume
857  *
858  *	What it says.
859  *
860  */
861 
atarigen_set_ym2151_vol(int volume)862 void atarigen_set_ym2151_vol(int volume)
863 {
864 	int ch;
865 
866 	for (ch = 0; ch < MIXER_MAX_CHANNELS; ch++)
867 	{
868 		const char *name = mixer_get_name(ch);
869 		if (name && strstr(name, "2151"))
870 			mixer_set_volume(ch, volume);
871 	}
872 }
873 
874 
875 /*
876  *	Set the YM2413 volume
877  *
878  *	What it says.
879  *
880  */
881 
atarigen_set_ym2413_vol(int volume)882 void atarigen_set_ym2413_vol(int volume)
883 {
884 	int ch;
885 
886 	for (ch = 0; ch < MIXER_MAX_CHANNELS; ch++)
887 	{
888 		const char *name = mixer_get_name(ch);
889 		if (name && strstr(name, "3812"))/*"2413")) -- need this change until 2413 stands alone */
890 			mixer_set_volume(ch, volume);
891 	}
892 }
893 
894 
895 /*
896  *	Set the POKEY volume
897  *
898  *	What it says.
899  *
900  */
901 
atarigen_set_pokey_vol(int volume)902 void atarigen_set_pokey_vol(int volume)
903 {
904 	int ch;
905 
906 	for (ch = 0; ch < MIXER_MAX_CHANNELS; ch++)
907 	{
908 		const char *name = mixer_get_name(ch);
909 		if (name && strstr(name, "POKEY"))
910 			mixer_set_volume(ch, volume);
911 	}
912 }
913 
914 
915 /*
916  *	Set the TMS5220 volume
917  *
918  *	What it says.
919  *
920  */
921 
atarigen_set_tms5220_vol(int volume)922 void atarigen_set_tms5220_vol(int volume)
923 {
924 	int ch;
925 
926 	for (ch = 0; ch < MIXER_MAX_CHANNELS; ch++)
927 	{
928 		const char *name = mixer_get_name(ch);
929 		if (name && strstr(name, "5220"))
930 			mixer_set_volume(ch, volume);
931 	}
932 }
933 
934 
935 /*
936  *	Set the OKI6295 volume
937  *
938  *	What it says.
939  *
940  */
941 
atarigen_set_oki6295_vol(int volume)942 void atarigen_set_oki6295_vol(int volume)
943 {
944 	int ch;
945 
946 	for (ch = 0; ch < MIXER_MAX_CHANNELS; ch++)
947 	{
948 		const char *name = mixer_get_name(ch);
949 		if (name && strstr(name, "6295"))
950 			mixer_set_volume(ch, volume);
951 	}
952 }
953 
954 
955 /*
956  *	Generic 6502 CPU speedup handler
957  *
958  *	Special shading renderer that runs any pixels under pen 1 through a lookup table.
959  *
960  */
961 
READ_HANDLER(m6502_speedup_r)962 static READ_HANDLER( m6502_speedup_r )
963 {
964 	int result = speed_b[0];
965 
966 	if (cpu_getpreviouspc() == speed_pc && speed_a[0] == speed_a[1] && result == speed_b[1])
967 		cpu_spinuntil_int();
968 
969 	return result;
970 }
971 
972 
973 
974 
975 /***********************************************************************************************/
976 /***********************************************************************************************/
977 /***********************************************************************************************/
978 /***********************************************************************************************/
979 /***********************************************************************************************/
980 
981 
982 
983 /* general video globals */
984 UINT8 *atarigen_playfieldram;
985 UINT8 *atarigen_playfield2ram;
986 UINT8 *atarigen_playfieldram_color;
987 UINT8 *atarigen_playfield2ram_color;
988 UINT8 *atarigen_spriteram;
989 UINT8 *atarigen_alpharam;
990 UINT8 *atarigen_vscroll;
991 UINT8 *atarigen_hscroll;
992 
993 size_t atarigen_playfieldram_size;
994 size_t atarigen_playfield2ram_size;
995 size_t atarigen_spriteram_size;
996 size_t atarigen_alpharam_size;
997 
998 
999 
1000 /*--------------------------------------------------------------------------
1001 
1002 	Video scanline timing
1003 
1004 		atarigen_scanline_timer_reset - call to reset the system
1005 
1006 --------------------------------------------------------------------------*/
1007 
1008 /* statics */
1009 static atarigen_scanline_callback scanline_callback;
1010 static int scanlines_per_callback;
1011 static timer_tm scanline_callback_period;
1012 static int last_scanline;
1013 
1014 /* prototypes */
1015 static void vblank_timer(int param);
1016 static void scanline_timer(int scanline);
1017 
1018 /*
1019  *	Scanline timer callback
1020  *
1021  *	Called once every n scanlines to generate the periodic callback to the main system.
1022  *
1023  */
1024 
atarigen_scanline_timer_reset(atarigen_scanline_callback update_graphics,int frequency)1025 void atarigen_scanline_timer_reset(atarigen_scanline_callback update_graphics, int frequency)
1026 {
1027 	/* set the scanline callback */
1028 	scanline_callback = update_graphics;
1029 	scanline_callback_period = (timer_tm)frequency * cpu_getscanlineperiod();
1030 	scanlines_per_callback = frequency;
1031 
1032 	/* compute the last scanline */
1033 	last_scanline = (int)(TIME_IN_HZ(Machine->drv->frames_per_second) / cpu_getscanlineperiod());
1034 
1035 	/* set a timer to go off on the next VBLANK */
1036 	timer_set(cpu_getscanlinetime(Machine->drv->screen_height), 0, vblank_timer);
1037 }
1038 
1039 
1040 /*
1041  *	VBLANK timer callback
1042  *
1043  *	Called once every VBLANK to prime the scanline timers.
1044  *
1045  */
1046 
vblank_timer(int param)1047 static void vblank_timer(int param)
1048 {
1049 	/* set a timer to go off at scanline 0 */
1050 	timer_set(TIME_IN_USEC(Machine->drv->vblank_duration), 0, scanline_timer);
1051 
1052 	/* set a timer to go off on the next VBLANK */
1053 	timer_set(cpu_getscanlinetime(Machine->drv->screen_height), 1, vblank_timer);
1054 }
1055 
1056 
1057 /*
1058  *	Scanline timer callback
1059  *
1060  *	Called once every n scanlines to generate the periodic callback to the main system.
1061  *
1062  */
1063 
scanline_timer(int scanline)1064 static void scanline_timer(int scanline)
1065 {
1066 	/* if this is scanline 0, we reset the MO and playfield system */
1067 	if (scanline == 0)
1068 	{
1069 		atarigen_mo_reset();
1070 		atarigen_pf_reset();
1071 		atarigen_pf2_reset();
1072 	}
1073 
1074 	/* callback */
1075 	if (scanline_callback)
1076 	{
1077 		(*scanline_callback)(scanline);
1078 
1079 		/* generate another? */
1080 		scanline += scanlines_per_callback;
1081 		if (scanline < last_scanline && scanlines_per_callback)
1082 			timer_set(scanline_callback_period, scanline, scanline_timer);
1083 	}
1084 }
1085 
1086 
1087 
1088 /*--------------------------------------------------------------------------
1089 
1090 	Video Controller I/O: used in Shuuz, Thunderjaws, Relief Pitcher, Off the Wall
1091 
1092 		atarigen_video_control_data - pointer to base of control memory
1093 		atarigen_video_control_latch1 - latch #1 value (-1 means disabled)
1094 		atarigen_video_control_latch2 - latch #2 value (-1 means disabled)
1095 
1096 		atarigen_video_control_reset - initializes the video controller
1097 
1098 		atarigen_video_control_w - write handler for the video controller
1099 		atarigen_video_control_r - read handler for the video controller
1100 
1101 --------------------------------------------------------------------------*/
1102 
1103 /* globals */
1104 UINT8 *atarigen_video_control_data;
1105 struct atarigen_video_control_state_desc atarigen_video_control_state;
1106 
1107 /* statics */
1108 static int actual_video_control_latch1;
1109 static int actual_video_control_latch2;
1110 
1111 
1112 /*
1113  *	Video controller initialization
1114  *
1115  *	Resets the state of the video controller.
1116  *
1117  */
1118 
atarigen_video_control_reset(void)1119 void atarigen_video_control_reset(void)
1120 {
1121 	/* clear the RAM we use */
1122 	memset(atarigen_video_control_data, 0, 0x40);
1123 	memset(&atarigen_video_control_state, 0, sizeof(atarigen_video_control_state));
1124 
1125 	/* reset the latches */
1126 	atarigen_video_control_state.latch1 = atarigen_video_control_state.latch2 = -1;
1127 	actual_video_control_latch1 = actual_video_control_latch2 = -1;
1128 }
1129 
1130 
1131 /*
1132  *	Video controller update
1133  *
1134  *	Copies the data from the specified location once/frame into the video controller registers
1135  *
1136  */
1137 
atarigen_video_control_update(const UINT8 * data)1138 void atarigen_video_control_update(const UINT8 *data)
1139 {
1140 	int i;
1141 
1142 	/* echo all the commands to the video controller */
1143 	for (i = 0; i < 0x38; i += 2)
1144 		if (READ_WORD(&data[i]))
1145 			atarigen_video_control_w(i, READ_WORD(&data[i]));
1146 
1147 	/* use this for debugging the video controller values */
1148 #if 0
1149 	if (keyboard_pressed(KEYCODE_8))
1150 	{
1151 		static FILE *out;
1152 		if (!out) out = fopen("scroll.log", "w");
1153 		if (out)
1154 		{
1155 			for (i = 0; i < 64; i++)
1156 				fprintf(out, "%04X ", READ_WORD(&data[2 * i]));
1157 			fprintf(out, "\n");
1158 		}
1159 	}
1160 #endif
1161 }
1162 
1163 
1164 /*
1165  *	Video controller write
1166  *
1167  *	Handles an I/O write to the video controller.
1168  *
1169  */
1170 
WRITE_HANDLER(atarigen_video_control_w)1171 WRITE_HANDLER( atarigen_video_control_w )
1172 {
1173 	int oldword = READ_WORD(&atarigen_video_control_data[offset]);
1174 	int newword = COMBINE_WORD(oldword, data);
1175 	WRITE_WORD(&atarigen_video_control_data[offset], newword);
1176 
1177 	/* switch off the offset */
1178 	switch (offset)
1179 	{
1180 		/* set the scanline interrupt here */
1181 		case 0x06:
1182 			if (oldword != newword)
1183 				atarigen_scanline_int_set(newword & 0x1ff);
1184 			break;
1185 
1186 		/* latch enable */
1187 		case 0x14:
1188 
1189 			/* reset the latches when disabled */
1190 			if (!(newword & 0x0080))
1191 				atarigen_video_control_state.latch1 = atarigen_video_control_state.latch2 = -1;
1192 			else
1193 				atarigen_video_control_state.latch1 = actual_video_control_latch1,
1194 				atarigen_video_control_state.latch2 = actual_video_control_latch2;
1195 
1196 			/* check for rowscroll enable */
1197 			atarigen_video_control_state.rowscroll_enable = (newword & 0x2000) >> 13;
1198 
1199 			/* check for palette banking */
1200 			atarigen_video_control_state.palette_bank = ((newword & 0x0400) >> 10) ^ 1;
1201 			break;
1202 
1203 		/* indexed parameters */
1204 		case 0x20: case 0x22: case 0x24: case 0x26:
1205 		case 0x28: case 0x2a: case 0x2c: case 0x2e:
1206 		case 0x30: case 0x32: case 0x34: case 0x36:
1207 			switch (newword & 15)
1208 			{
1209 				case 9:
1210 					atarigen_video_control_state.sprite_xscroll = (newword >> 7) & 0x1ff;
1211 					break;
1212 
1213 				case 10:
1214 					atarigen_video_control_state.pf2_xscroll = (newword >> 7) & 0x1ff;
1215 					break;
1216 
1217 				case 11:
1218 					atarigen_video_control_state.pf1_xscroll = (newword >> 7) & 0x1ff;
1219 					break;
1220 
1221 				case 13:
1222 					atarigen_video_control_state.sprite_yscroll = (newword >> 7) & 0x1ff;
1223 					break;
1224 
1225 				case 14:
1226 					atarigen_video_control_state.pf2_yscroll = (newword >> 7) & 0x1ff;
1227 					break;
1228 
1229 				case 15:
1230 					atarigen_video_control_state.pf1_yscroll = (newword >> 7) & 0x1ff;
1231 					break;
1232 			}
1233 			break;
1234 
1235 		/* latch 1 value */
1236 		case 0x38:
1237 			actual_video_control_latch1 = newword;
1238 			actual_video_control_latch2 = -1;
1239 			if (READ_WORD(&atarigen_video_control_data[0x14]) & 0x80)
1240 				atarigen_video_control_state.latch1 = actual_video_control_latch1;
1241 			break;
1242 
1243 		/* latch 2 value */
1244 		case 0x3a:
1245 			actual_video_control_latch1 = -1;
1246 			actual_video_control_latch2 = newword;
1247 			if (READ_WORD(&atarigen_video_control_data[0x14]) & 0x80)
1248 				atarigen_video_control_state.latch2 = actual_video_control_latch2;
1249 			break;
1250 
1251 		/* scanline IRQ ack here */
1252 		case 0x3c:
1253 			atarigen_scanline_int_ack_w(0, 0);
1254 			break;
1255 
1256 		/* log anything else */
1257 		case 0x00:
1258 		default:
1259 			//if (oldword != newword)
1260 			//	logerror("video_control_w(%02X, %04X) ** [prev=%04X]\n", offset, newword, oldword);
1261 			break;
1262 	}
1263 }
1264 
1265 
1266 /*
1267  *	Video controller read
1268  *
1269  *	Handles an I/O read from the video controller.
1270  *
1271  */
1272 
READ_HANDLER(atarigen_video_control_r)1273 READ_HANDLER( atarigen_video_control_r )
1274 {
1275 	//logerror("video_control_r(%02X)\n", offset);
1276 
1277 	/* a read from offset 0 returns the current scanline */
1278 	/* also sets bit 0x4000 if we're in VBLANK */
1279 	if (offset == 0)
1280 	{
1281 		int result = cpu_getscanline();
1282 
1283 		if (result > 255)
1284 			result = 255;
1285 		if (result > Machine->visible_area.max_y)
1286 			result |= 0x4000;
1287 
1288 		return result;
1289 	}
1290 	else
1291 		return READ_WORD(&atarigen_video_control_data[offset]);
1292 }
1293 
1294 
1295 
1296 /*--------------------------------------------------------------------------
1297 
1298 	Motion object rendering
1299 
1300 		atarigen_mo_desc - description of the M.O. layout
1301 
1302 		atarigen_mo_callback - called back for each M.O. during processing
1303 
1304 		atarigen_mo_init - initializes and configures the M.O. list walker
1305 		atarigen_mo_free - frees all memory allocated by atarigen_mo_init
1306 		atarigen_mo_reset - reset for a new frame (use only if not using interrupt system)
1307 		atarigen_mo_update - updates the M.O. list for the given scanline
1308 		atarigen_mo_process - processes the current list
1309 
1310 --------------------------------------------------------------------------*/
1311 
1312 /* statics */
1313 static struct atarigen_mo_desc modesc;
1314 
1315 static UINT16 *molist;
1316 static UINT16 *molist_end;
1317 static UINT16 *molist_last;
1318 static UINT16 *molist_upper_bound;
1319 
1320 
1321 /*
1322  *	Motion object render initialization
1323  *
1324  *	Allocates memory for the motion object display cache.
1325  *
1326  */
1327 
atarigen_mo_init(const struct atarigen_mo_desc * source_desc)1328 int atarigen_mo_init(const struct atarigen_mo_desc *source_desc)
1329 {
1330 	modesc = *source_desc;
1331 	if (modesc.entrywords == 0) modesc.entrywords = 4;
1332 	modesc.entrywords++;
1333 
1334 	/* make sure everything is free */
1335 	atarigen_mo_free();
1336 
1337 	/* allocate memory for the cached list */
1338 	molist = (UINT16*)malloc(modesc.maxcount * 2 * modesc.entrywords * (Machine->drv->screen_height / 8));
1339 	if (!molist)
1340 		return 1;
1341 	molist_upper_bound = molist + (modesc.maxcount * modesc.entrywords * (Machine->drv->screen_height / 8));
1342 
1343 	/* initialize the end/last pointers */
1344 	atarigen_mo_reset();
1345 
1346 	return 0;
1347 }
1348 
1349 
1350 /*
1351  *	Motion object render free
1352  *
1353  *	Frees all data allocated for the motion objects.
1354  *
1355  */
1356 
atarigen_mo_free(void)1357 void atarigen_mo_free(void)
1358 {
1359 	if (molist)
1360 		free(molist);
1361 	molist = NULL;
1362 }
1363 
1364 
1365 /*
1366  *	Motion object render reset
1367  *
1368  *	Resets the motion object system for a new frame. Note that this is automatically called
1369  *	if you're using the scanline timing system.
1370  *
1371  */
1372 
atarigen_mo_reset(void)1373 void atarigen_mo_reset(void)
1374 {
1375 	molist_end = molist;
1376 	molist_last = NULL;
1377 }
1378 
1379 
1380 /*
1381  *	Motion object updater
1382  *
1383  *	Parses the current motion object list, caching all entries.
1384  *
1385  */
1386 
atarigen_mo_update(const UINT8 * base,int link,int scanline)1387 void atarigen_mo_update(const UINT8 *base, int link, int scanline)
1388 {
1389 	int entryskip = modesc.entryskip, wordskip = modesc.wordskip, wordcount = modesc.entrywords - 1;
1390 	UINT8 spritevisit[ATARIGEN_MAX_MAXCOUNT];
1391 	UINT16 *data, *data_start, *prev_data;
1392 	int match = 0;
1393 
1394 	/* set up local pointers */
1395 	data_start = data = molist_end;
1396 	prev_data = molist_last;
1397 
1398 	/* if the last list entries were on the same scanline, overwrite them */
1399 	if (prev_data)
1400 	{
1401 		if (*prev_data == scanline)
1402 			data_start = data = prev_data;
1403 		else
1404 			match = 1;
1405 	}
1406 
1407 	/* visit all the sprites and copy their data into the display list */
1408 	memset(spritevisit, 0, modesc.linkmask + 1);
1409 	while (!spritevisit[link])
1410 	{
1411 		const UINT8 *modata = &base[link * entryskip];
1412 		UINT16 tempdata[16];
1413 		int temp, i;
1414 
1415 		/* bounds checking */
1416 		if (data >= molist_upper_bound)
1417 		{
1418 			//logerror("Motion object list exceeded maximum\n");
1419 			break;
1420 		}
1421 
1422 		/* start with the scanline */
1423 		*data++ = scanline;
1424 
1425 		/* add the data words */
1426 		for (i = temp = 0; i < wordcount; i++, temp += wordskip)
1427 			tempdata[i] = *data++ = READ_WORD(&modata[temp]);
1428 
1429 		/* is this one to ignore? (note that ignore is predecremented by 4) */
1430 		if (tempdata[modesc.ignoreword] == 0xffff)
1431 			data -= wordcount + 1;
1432 
1433 		/* update our match status */
1434 		else if (match)
1435 		{
1436 			prev_data++;
1437 			for (i = 0; i < wordcount; i++)
1438 				if (*prev_data++ != tempdata[i])
1439 				{
1440 					match = 0;
1441 					break;
1442 				}
1443 		}
1444 
1445 		/* link to the next object */
1446 		spritevisit[link] = 1;
1447 		if (modesc.linkword >= 0)
1448 			link = (tempdata[modesc.linkword] >> modesc.linkshift) & modesc.linkmask;
1449 		else
1450 			link = (link + 1) & modesc.linkmask;
1451 	}
1452 
1453 	/* if we didn't match the last set of entries, update the counters */
1454 	if (!match)
1455 	{
1456 		molist_end = data;
1457 		molist_last = data_start;
1458 	}
1459 }
1460 
1461 
1462 /*
1463  *	Motion object updater using SLIPs
1464  *
1465  *	Updates motion objects using a SLIP read from a table, assuming a 512-pixel high playfield.
1466  *
1467  */
1468 
atarigen_mo_update_slip_512(const UINT8 * base,int scroll,int scanline,const UINT8 * slips)1469 void atarigen_mo_update_slip_512(const UINT8 *base, int scroll, int scanline, const UINT8 *slips)
1470 {
1471 	/* catch a fractional character off the top of the screen */
1472 	if (scanline == 0 && (scroll & 7) != 0)
1473 	{
1474 		int pfscanline = scroll & 0x1f8;
1475 		int link = (READ_WORD(&slips[2 * (pfscanline / 8)]) >> modesc.linkshift) & modesc.linkmask;
1476 		atarigen_mo_update(base, link, 0);
1477 	}
1478 
1479 	/* if we're within screen bounds, grab the next batch of MO's and process */
1480 	if (scanline < Machine->drv->screen_height)
1481 	{
1482 		int pfscanline = (scanline + scroll + 7) & 0x1f8;
1483 		int link = (READ_WORD(&slips[2 * (pfscanline / 8)]) >> modesc.linkshift) & modesc.linkmask;
1484 		atarigen_mo_update(base, link, (pfscanline - scroll) & 0x1ff);
1485 	}
1486 }
1487 
1488 
1489 /*
1490  *	Motion object processor
1491  *
1492  *	Processes the cached motion object entries.
1493  *
1494  */
1495 
atarigen_mo_process(atarigen_mo_callback callback,void * param)1496 void atarigen_mo_process(atarigen_mo_callback callback, void *param)
1497 {
1498 	UINT16 *base = molist;
1499 	int last_start_scan = -1;
1500 	struct rectangle clip;
1501 
1502 	/* create a clipping rectangle so that only partial sections are updated at a time */
1503 	clip.min_x = 0;
1504 	clip.max_x = Machine->drv->screen_width - 1;
1505 
1506 	/* loop over the list until the end */
1507 	while (base < molist_end)
1508 	{
1509 		UINT16 *data, *first, *last;
1510 		int start_scan = base[0], step;
1511 
1512 		last_start_scan = start_scan;
1513 		clip.min_y = start_scan;
1514 
1515 		/* look for an entry whose scanline start is different from ours; that's our bottom */
1516 		for (data = base; data < molist_end; data += modesc.entrywords)
1517 			if (*data != start_scan)
1518 			{
1519 				clip.max_y = *data;
1520 				break;
1521 			}
1522 
1523 		/* if we didn't find any additional regions, go until the bottom of the screen */
1524 		if (data == molist_end)
1525 			clip.max_y = Machine->drv->screen_height - 1;
1526 
1527 		/* set the start and end points */
1528 		if (modesc.reverse)
1529 		{
1530 			first = data - modesc.entrywords;
1531 			last = base - modesc.entrywords;
1532 			step = -modesc.entrywords;
1533 		}
1534 		else
1535 		{
1536 			first = base;
1537 			last = data;
1538 			step = modesc.entrywords;
1539 		}
1540 
1541 		/* update the base */
1542 		base = data;
1543 
1544 		/* render the mos */
1545 		for (data = first; data != last; data += step)
1546 			(*callback)(&data[1], &clip, param);
1547 	}
1548 }
1549 
1550 
1551 
1552 /*--------------------------------------------------------------------------
1553 
1554 	RLE Motion object rendering/decoding
1555 
1556 		atarigen_rle_init - prescans the RLE objects
1557 		atarigen_rle_free - frees all memory allocated by atarigen_rle_init
1558 		atarigen_rle_render - render an RLE-compressed motion object
1559 
1560 --------------------------------------------------------------------------*/
1561 
1562 /* globals */
1563 int atarigen_rle_count;
1564 struct atarigen_rle_descriptor *atarigen_rle_info;
1565 
1566 /* statics */
1567 static UINT8 rle_region;
1568 static UINT8 rle_bpp[8];
1569 static UINT16 *rle_table[8];
1570 static UINT16 *rle_colortable;
1571 
1572 /* prototypes */
1573 static int build_rle_tables(void);
1574 static void prescan_rle(int which);
1575 static void draw_rle_zoom(struct osd_bitmap *bitmap, const struct atarigen_rle_descriptor *gfx,
1576 		UINT32 color, int flipy, int sx, int sy, int scalex, int scaley,
1577 		const struct rectangle *clip);
1578 static void draw_rle_zoom_16(struct osd_bitmap *bitmap, const struct atarigen_rle_descriptor *gfx,
1579 		UINT32 color, int flipy, int sx, int sy, int scalex, int scaley,
1580 		const struct rectangle *clip);
1581 static void draw_rle_zoom_hflip(struct osd_bitmap *bitmap, const struct atarigen_rle_descriptor *gfx,
1582 		UINT32 color, int flipy, int sx, int sy, int scalex, int scaley,
1583 		const struct rectangle *clip);
1584 static void draw_rle_zoom_hflip_16(struct osd_bitmap *bitmap, const struct atarigen_rle_descriptor *gfx,
1585 		UINT32 color, int flipy, int sx, int sy, int scalex, int scaley,
1586 		const struct rectangle *clip);
1587 
1588 /*
1589  *	RLE motion object initialization
1590  *
1591  *	Pre-parses the motion object list and potentially pre-decompresses the data.
1592  *
1593  */
1594 
atarigen_rle_init(int region,int colorbase)1595 int atarigen_rle_init(int region, int colorbase)
1596 {
1597 	const UINT16 *base = (const UINT16 *)memory_region(region);
1598 	int lowest_address = memory_region_length(region);
1599 	int i;
1600 
1601 	rle_region = region;
1602 	rle_colortable = &Machine->remapped_colortable[colorbase];
1603 
1604 	/* build and allocate the tables */
1605 	if (build_rle_tables())
1606 		return 1;
1607 
1608 	/* first determine the lowest address of all objects */
1609 	for (i = 0; i < lowest_address; i += 4)
1610 	{
1611 		int offset = ((base[i + 2] & 0xff) << 16) | base[i + 3];
1612 		if (offset > i && offset < lowest_address)
1613 			lowest_address = offset;
1614 	}
1615 
1616 	/* that determines how many objects */
1617 	atarigen_rle_count = lowest_address / 4;
1618 	atarigen_rle_info = (struct atarigen_rle_descriptor*)malloc(sizeof(struct atarigen_rle_descriptor) * atarigen_rle_count);
1619 	if (!atarigen_rle_info)
1620 	{
1621 		atarigen_rle_free();
1622 		return 1;
1623 	}
1624 	memset(atarigen_rle_info, 0, sizeof(struct atarigen_rle_descriptor) * atarigen_rle_count);
1625 
1626 	/* now loop through and prescan the objects */
1627 	for (i = 0; i < atarigen_rle_count; i++)
1628 		prescan_rle(i);
1629 
1630 	return 0;
1631 }
1632 
1633 
1634 /*
1635  *	RLE motion object free
1636  *
1637  *	Frees all memory allocated to track the motion objects.
1638  *
1639  */
1640 
atarigen_rle_free(void)1641 void atarigen_rle_free(void)
1642 {
1643 	/* free the info data */
1644 	if (atarigen_rle_info)
1645 		free(atarigen_rle_info);
1646 	atarigen_rle_info = NULL;
1647 
1648 	/* free the tables */
1649 	if (rle_table[0])
1650 		free(rle_table[0]);
1651 	memset(rle_table, 0, sizeof(rle_table));
1652 }
1653 
1654 
1655 /*
1656  *	RLE motion object render
1657  *
1658  *	Renders a compressed motion object.
1659  *
1660  */
1661 
atarigen_rle_render(struct osd_bitmap * bitmap,struct atarigen_rle_descriptor * info,int color,int hflip,int vflip,int x,int y,int xscale,int yscale,const struct rectangle * clip)1662 void atarigen_rle_render(struct osd_bitmap *bitmap, struct atarigen_rle_descriptor *info, int color, int hflip, int vflip,
1663 	int x, int y, int xscale, int yscale, const struct rectangle *clip)
1664 {
1665 	int scaled_xoffs = (xscale * info->xoffs) >> 12;
1666 	int scaled_yoffs = (yscale * info->yoffs) >> 12;
1667 
1668 	/* we're hflipped, account for it */
1669 	if (hflip) scaled_xoffs = ((xscale * info->width) >> 12) - scaled_xoffs;
1670 
1671 	/* adjust for the x and y offsets */
1672 	x -= scaled_xoffs;
1673 	y -= scaled_yoffs;
1674 
1675 	/* bail on a NULL object */
1676 	if (!info->data)
1677 		return;
1678 
1679 	/* 16-bit case */
1680 	if (bitmap->depth == 16)
1681 	{
1682 		if (!hflip)
1683 			draw_rle_zoom_16(bitmap, info, color, vflip, x, y, xscale << 4, yscale << 4, clip);
1684 		else
1685 			draw_rle_zoom_hflip_16(bitmap, info, color, vflip, x, y, xscale << 4, yscale << 4, clip);
1686 	}
1687 
1688 	/* 8-bit case */
1689 	else
1690 	{
1691 		if (!hflip)
1692 			draw_rle_zoom(bitmap, info, color, vflip, x, y, xscale << 4, yscale << 4, clip);
1693 		else
1694 			draw_rle_zoom_hflip(bitmap, info, color, vflip, x, y, xscale << 4, yscale << 4, clip);
1695 	}
1696 }
1697 
1698 
1699 /*
1700  *	Builds internally-used tables
1701  *
1702  *	Special two-byte tables with the upper byte giving the count and the lower
1703  *	byte giving the pixel value.
1704  *
1705  */
1706 
build_rle_tables(void)1707 static int build_rle_tables(void)
1708 {
1709 	UINT16 *base;
1710 	int i;
1711 
1712 	/* allocate all 5 tables */
1713 	base = (UINT16*)malloc(0x500 * sizeof(UINT16));
1714 	if (!base)
1715 		return 1;
1716 
1717 	/* assign the tables */
1718 	rle_table[0] = &base[0x000];
1719 	rle_table[1] = &base[0x100];
1720 	rle_table[2] = rle_table[3] = &base[0x200];
1721 	rle_table[4] = rle_table[6] = &base[0x300];
1722 	rle_table[5] = rle_table[7] = &base[0x400];
1723 
1724 	/* set the bpps */
1725 	rle_bpp[0] = 4;
1726 	rle_bpp[1] = rle_bpp[2] = rle_bpp[3] = 5;
1727 	rle_bpp[4] = rle_bpp[5] = rle_bpp[6] = rle_bpp[7] = 6;
1728 
1729 	/* build the 4bpp table */
1730 	for (i = 0; i < 256; i++)
1731 		rle_table[0][i] = (((i & 0xf0) + 0x10) << 4) | (i & 0x0f);
1732 
1733 	/* build the 5bpp table */
1734 	for (i = 0; i < 256; i++)
1735 		rle_table[2][i] = (((i & 0xe0) + 0x20) << 3) | (i & 0x1f);
1736 
1737 	/* build the special 5bpp table */
1738 	for (i = 0; i < 256; i++)
1739 	{
1740 		if ((i & 0x0f) == 0)
1741 			rle_table[1][i] = (((i & 0xf0) + 0x10) << 4) | (i & 0x0f);
1742 		else
1743 			rle_table[1][i] = (((i & 0xe0) + 0x20) << 3) | (i & 0x1f);
1744 	}
1745 
1746 	/* build the 6bpp table */
1747 	for (i = 0; i < 256; i++)
1748 		rle_table[5][i] = (((i & 0xc0) + 0x40) << 2) | (i & 0x3f);
1749 
1750 	/* build the special 6bpp table */
1751 	for (i = 0; i < 256; i++)
1752 	{
1753 		if ((i & 0x0f) == 0)
1754 			rle_table[4][i] = (((i & 0xf0) + 0x10) << 4) | (i & 0x0f);
1755 		else
1756 			rle_table[4][i] = (((i & 0xc0) + 0x40) << 2) | (i & 0x3f);
1757 	}
1758 
1759 	return 0;
1760 }
1761 
1762 
1763 /*
1764  *	Prescans an RLE-compressed object
1765  *
1766  *	Determines the pen usage, width, height, and other data for an RLE object.
1767  *
1768  */
1769 
prescan_rle(int which)1770 static void prescan_rle(int which)
1771 {
1772 	UINT16 *base = (UINT16 *)&memory_region(rle_region)[which * 8];
1773 	struct atarigen_rle_descriptor *rle_data = &atarigen_rle_info[which];
1774 	UINT32 usage = 0, usage_hi = 0;
1775 	int width = 0, height, flags, offset;
1776 	const UINT16 *table;
1777 
1778 	/* look up the offset */
1779 	rle_data->xoffs = (INT16)base[0];
1780 	rle_data->yoffs = (INT16)base[1];
1781 
1782 	/* determine the depth and table */
1783 	flags = base[2];
1784 	rle_data->bpp = rle_bpp[(flags >> 8) & 7];
1785 	table = rle_data->table = rle_table[(flags >> 8) & 7];
1786 
1787 	/* determine the starting offset */
1788 	offset = ((base[2] & 0xff) << 16) | base[3];
1789 	rle_data->data = base = (UINT16 *)&memory_region(rle_region)[offset * 2];
1790 
1791 	/* make sure it's valid */
1792 	if (offset < which * 4 || offset > memory_region_length(rle_region))
1793 	{
1794 		memset(rle_data, 0, sizeof(*rle_data));
1795 		return;
1796 	}
1797 
1798 	/* first pre-scan to determine the width and height */
1799 	for (height = 0; height < 1024; height++)
1800 	{
1801 		int tempwidth = 0;
1802 		int entry_count = *base++;
1803 
1804 		/* if the high bit is set, assume we're inverted */
1805 		if (entry_count & 0x8000)
1806 		{
1807 			entry_count ^= 0xffff;
1808 
1809 			/* also change the ROM data so we don't have to do this again at runtime */
1810 			base[-1] ^= 0xffff;
1811 		}
1812 
1813 		/* we're done when we hit 0 */
1814 		if (entry_count == 0)
1815 			break;
1816 
1817 		/* track the width */
1818 		while (entry_count--)
1819 		{
1820 			int word = *base++;
1821 			int count, value;
1822 
1823 			/* decode the low byte first */
1824 			count = table[word & 0xff];
1825 			value = count & 0xff;
1826 			tempwidth += count >> 8;
1827 			if (value < 32)
1828 				usage |= 1 << value;
1829 			else
1830 				usage_hi |= 1 << (value - 32);
1831 
1832 			/* decode the upper byte second */
1833 			count = table[word >> 8];
1834 			value = count & 0xff;
1835 			tempwidth += count >> 8;
1836 			if (value < 32)
1837 				usage |= 1 << value;
1838 			else
1839 				usage_hi |= 1 << (value - 32);
1840 		}
1841 
1842 		/* only remember the max */
1843 		if (tempwidth > width) width = tempwidth;
1844 	}
1845 
1846 	/* fill in the data */
1847 	rle_data->width = width;
1848 	rle_data->height = height;
1849 	rle_data->pen_usage = usage;
1850 	rle_data->pen_usage_hi = usage_hi;
1851 }
1852 
1853 
1854 /*
1855  *	Draw a compressed RLE object
1856  *
1857  *	What it says. RLE decoding is performed on the fly to an 8-bit bitmap.
1858  *
1859  */
1860 
draw_rle_zoom(struct osd_bitmap * bitmap,const struct atarigen_rle_descriptor * gfx,UINT32 color,int flipy,int sx,int sy,int scalex,int scaley,const struct rectangle * clip)1861 void draw_rle_zoom(struct osd_bitmap *bitmap, const struct atarigen_rle_descriptor *gfx,
1862 		UINT32 color, int flipy, int sx, int sy, int scalex, int scaley,
1863 		const struct rectangle *clip)
1864 {
1865 	const UINT16 *palette = &rle_colortable[color];
1866 	const UINT16 *row_start = gfx->data;
1867 	const UINT16 *table = gfx->table;
1868 	volatile int current_row = 0;
1869 
1870 	int scaled_width = (scalex * gfx->width + 0x7fff) >> 16;
1871 	int scaled_height = (scaley * gfx->height + 0x7fff) >> 16;
1872 
1873 	int pixels_to_skip = 0, xclipped = 0;
1874 	int dx, dy, ex, ey;
1875 	int y, sourcey;
1876 
1877 	/* make sure we didn't end up with 0 */
1878 	if (scaled_width == 0) scaled_width = 1;
1879 	if (scaled_height == 0) scaled_height = 1;
1880 
1881 	/* compute the remaining parameters */
1882 	dx = (gfx->width << 16) / scaled_width;
1883 	dy = (gfx->height << 16) / scaled_height;
1884 	ex = sx + scaled_width - 1;
1885 	ey = sy + scaled_height - 1;
1886 	sourcey = dy / 2;
1887 
1888 	/* left edge clip */
1889 	if (sx < clip->min_x)
1890 		pixels_to_skip = clip->min_x - sx, xclipped = 1;
1891 	if (sx > clip->max_x)
1892 		return;
1893 
1894 	/* right edge clip */
1895 	if (ex > clip->max_x)
1896 		ex = clip->max_x, xclipped = 1;
1897 	else if (ex < clip->min_x)
1898 		return;
1899 
1900 	/* top edge clip */
1901 	if (sy < clip->min_y)
1902 	{
1903 		sourcey += (clip->min_y - sy) * dy;
1904 		sy = clip->min_y;
1905 	}
1906 	else if (sy > clip->max_y)
1907 		return;
1908 
1909 	/* bottom edge clip */
1910 	if (ey > clip->max_y)
1911 		ey = clip->max_y;
1912 	else if (ey < clip->min_y)
1913 		return;
1914 
1915 	/* loop top to bottom */
1916 	for (y = sy; y <= ey; y++, sourcey += dy)
1917 	{
1918 		UINT8 *dest = &bitmap->line[y][sx];
1919 		int j, sourcex = dx / 2, rle_end = 0;
1920 		const UINT16 *base;
1921 		int entry_count;
1922 
1923 		/* loop until we hit the row we're on */
1924 		for ( ; current_row != (sourcey >> 16); current_row++)
1925 			row_start += 1 + *row_start;
1926 
1927 		/* grab our starting parameters from this row */
1928 		base = row_start;
1929 		entry_count = *base++;
1930 
1931 		/* non-clipped case */
1932 		if (!xclipped)
1933 		{
1934 			/* decode the pixels */
1935 			for (j = 0; j < entry_count; j++)
1936 			{
1937 				int word = *base++;
1938 				int count, value;
1939 
1940 				/* decode the low byte first */
1941 				count = table[word & 0xff];
1942 				value = count & 0xff;
1943 				rle_end += (count & 0xff00) << 8;
1944 
1945 				/* store copies of the value until we pass the end of this chunk */
1946 				if (value)
1947 				{
1948 					value = palette[value];
1949 					while (sourcex < rle_end)
1950 						*dest++ = value, sourcex += dx;
1951 				}
1952 				else
1953 				{
1954 					while (sourcex < rle_end)
1955 						dest++, sourcex += dx;
1956 				}
1957 
1958 				/* decode the upper byte second */
1959 				count = table[word >> 8];
1960 				value = count & 0xff;
1961 				rle_end += (count & 0xff00) << 8;
1962 
1963 				/* store copies of the value until we pass the end of this chunk */
1964 				if (value)
1965 				{
1966 					value = palette[value];
1967 					while (sourcex < rle_end)
1968 						*dest++ = value, sourcex += dx;
1969 				}
1970 				else
1971 				{
1972 					while (sourcex < rle_end)
1973 						dest++, sourcex += dx;
1974 				}
1975 			}
1976 		}
1977 
1978 		/* clipped case */
1979 		else
1980 		{
1981 			const UINT8 *end = &bitmap->line[y][ex];
1982 			int to_be_skipped = pixels_to_skip;
1983 
1984 			/* decode the pixels */
1985 			for (j = 0; j < entry_count && dest <= end; j++)
1986 			{
1987 				int word = *base++;
1988 				int count, value;
1989 
1990 				/* decode the low byte first */
1991 				count = table[word & 0xff];
1992 				value = count & 0xff;
1993 				rle_end += (count & 0xff00) << 8;
1994 
1995 				/* store copies of the value until we pass the end of this chunk */
1996 				if (to_be_skipped)
1997 				{
1998 					while (to_be_skipped && sourcex < rle_end)
1999 						dest++, sourcex += dx, to_be_skipped--;
2000 					if (to_be_skipped) goto next1;
2001 				}
2002 				if (value)
2003 				{
2004 					value = palette[value];
2005 					while (sourcex < rle_end && dest <= end)
2006 						*dest++ = value, sourcex += dx;
2007 				}
2008 				else
2009 				{
2010 					while (sourcex < rle_end)
2011 						dest++, sourcex += dx;
2012 				}
2013 
2014 			next1:
2015 				/* decode the upper byte second */
2016 				count = table[word >> 8];
2017 				value = count & 0xff;
2018 				rle_end += (count & 0xff00) << 8;
2019 
2020 				/* store copies of the value until we pass the end of this chunk */
2021 				if (to_be_skipped)
2022 				{
2023 					while (to_be_skipped && sourcex < rle_end)
2024 						dest++, sourcex += dx, to_be_skipped--;
2025 					if (to_be_skipped) goto next2;
2026 				}
2027 				if (value)
2028 				{
2029 					value = palette[value];
2030 					while (sourcex < rle_end && dest <= end)
2031 						*dest++ = value, sourcex += dx;
2032 				}
2033 				else
2034 				{
2035 					while (sourcex < rle_end)
2036 						dest++, sourcex += dx;
2037 				}
2038 			next2:
2039 				;
2040 			}
2041 		}
2042 	}
2043 }
2044 
2045 
2046 /*
2047  *	Draw a compressed RLE object
2048  *
2049  *	What it says. RLE decoding is performed on the fly to a 16-bit bitmap.
2050  *
2051  */
2052 
draw_rle_zoom_16(struct osd_bitmap * bitmap,const struct atarigen_rle_descriptor * gfx,UINT32 color,int flipy,int sx,int sy,int scalex,int scaley,const struct rectangle * clip)2053 void draw_rle_zoom_16(struct osd_bitmap *bitmap, const struct atarigen_rle_descriptor *gfx,
2054 		UINT32 color, int flipy, int sx, int sy, int scalex, int scaley,
2055 		const struct rectangle *clip)
2056 {
2057 	const UINT16 *palette = &rle_colortable[color];
2058 	const UINT16 *row_start = gfx->data;
2059 	const UINT16 *table = gfx->table;
2060 	volatile int current_row = 0;
2061 
2062 	int scaled_width = (scalex * gfx->width + 0x7fff) >> 16;
2063 	int scaled_height = (scaley * gfx->height + 0x7fff) >> 16;
2064 
2065 	int pixels_to_skip = 0, xclipped = 0;
2066 	int dx, dy, ex, ey;
2067 	int y, sourcey;
2068 
2069 	/* make sure we didn't end up with 0 */
2070 	if (scaled_width == 0) scaled_width = 1;
2071 	if (scaled_height == 0) scaled_height = 1;
2072 
2073 	/* compute the remaining parameters */
2074 	dx = (gfx->width << 16) / scaled_width;
2075 	dy = (gfx->height << 16) / scaled_height;
2076 	ex = sx + scaled_width - 1;
2077 	ey = sy + scaled_height - 1;
2078 	sourcey = dy / 2;
2079 
2080 	/* left edge clip */
2081 	if (sx < clip->min_x)
2082 		pixels_to_skip = clip->min_x - sx, xclipped = 1;
2083 	if (sx > clip->max_x)
2084 		return;
2085 
2086 	/* right edge clip */
2087 	if (ex > clip->max_x)
2088 		ex = clip->max_x, xclipped = 1;
2089 	else if (ex < clip->min_x)
2090 		return;
2091 
2092 	/* top edge clip */
2093 	if (sy < clip->min_y)
2094 	{
2095 		sourcey += (clip->min_y - sy) * dy;
2096 		sy = clip->min_y;
2097 	}
2098 	else if (sy > clip->max_y)
2099 		return;
2100 
2101 	/* bottom edge clip */
2102 	if (ey > clip->max_y)
2103 		ey = clip->max_y;
2104 	else if (ey < clip->min_y)
2105 		return;
2106 
2107 	/* loop top to bottom */
2108 	for (y = sy; y <= ey; y++, sourcey += dy)
2109 	{
2110 		UINT16 *dest = (UINT16 *)&bitmap->line[y][sx * 2];
2111 		int j, sourcex = dx / 2, rle_end = 0;
2112 		const UINT16 *base;
2113 		int entry_count;
2114 
2115 		/* loop until we hit the row we're on */
2116 		for ( ; current_row != (sourcey >> 16); current_row++)
2117 			row_start += 1 + *row_start;
2118 
2119 		/* grab our starting parameters from this row */
2120 		base = row_start;
2121 		entry_count = *base++;
2122 
2123 		/* non-clipped case */
2124 		if (!xclipped)
2125 		{
2126 			/* decode the pixels */
2127 			for (j = 0; j < entry_count; j++)
2128 			{
2129 				int word = *base++;
2130 				int count, value;
2131 
2132 				/* decode the low byte first */
2133 				count = table[word & 0xff];
2134 				value = count & 0xff;
2135 				rle_end += (count & 0xff00) << 8;
2136 
2137 				/* store copies of the value until we pass the end of this chunk */
2138 				if (value)
2139 				{
2140 					value = palette[value];
2141 					while (sourcex < rle_end)
2142 						*dest++ = value, sourcex += dx;
2143 				}
2144 				else
2145 				{
2146 					while (sourcex < rle_end)
2147 						dest++, sourcex += dx;
2148 				}
2149 
2150 				/* decode the upper byte second */
2151 				count = table[word >> 8];
2152 				value = count & 0xff;
2153 				rle_end += (count & 0xff00) << 8;
2154 
2155 				/* store copies of the value until we pass the end of this chunk */
2156 				if (value)
2157 				{
2158 					value = palette[value];
2159 					while (sourcex < rle_end)
2160 						*dest++ = value, sourcex += dx;
2161 				}
2162 				else
2163 				{
2164 					while (sourcex < rle_end)
2165 						dest++, sourcex += dx;
2166 				}
2167 			}
2168 		}
2169 
2170 		/* clipped case */
2171 		else
2172 		{
2173 			const UINT16 *end = (const UINT16 *)&bitmap->line[y][ex * 2];
2174 			int to_be_skipped = pixels_to_skip;
2175 
2176 			/* decode the pixels */
2177 			for (j = 0; j < entry_count && dest <= end; j++)
2178 			{
2179 				int word = *base++;
2180 				int count, value;
2181 
2182 				/* decode the low byte first */
2183 				count = table[word & 0xff];
2184 				value = count & 0xff;
2185 				rle_end += (count & 0xff00) << 8;
2186 
2187 				/* store copies of the value until we pass the end of this chunk */
2188 				if (to_be_skipped)
2189 				{
2190 					while (to_be_skipped && sourcex < rle_end)
2191 						dest++, sourcex += dx, to_be_skipped--;
2192 					if (to_be_skipped) goto next3;
2193 				}
2194 				if (value)
2195 				{
2196 					value = palette[value];
2197 					while (sourcex < rle_end && dest <= end)
2198 						*dest++ = value, sourcex += dx;
2199 				}
2200 				else
2201 				{
2202 					while (sourcex < rle_end)
2203 						dest++, sourcex += dx;
2204 				}
2205 
2206 			next3:
2207 				/* decode the upper byte second */
2208 				count = table[word >> 8];
2209 				value = count & 0xff;
2210 				rle_end += (count & 0xff00) << 8;
2211 
2212 				/* store copies of the value until we pass the end of this chunk */
2213 				if (to_be_skipped)
2214 				{
2215 					while (to_be_skipped && sourcex < rle_end)
2216 						dest++, sourcex += dx, to_be_skipped--;
2217 					if (to_be_skipped) goto next4;
2218 				}
2219 				if (value)
2220 				{
2221 					value = palette[value];
2222 					while (sourcex < rle_end && dest <= end)
2223 						*dest++ = value, sourcex += dx;
2224 				}
2225 				else
2226 				{
2227 					while (sourcex < rle_end)
2228 						dest++, sourcex += dx;
2229 				}
2230 			next4:
2231 				;
2232 			}
2233 		}
2234 	}
2235 }
2236 
2237 
2238 /*
2239  *	Draw a horizontally-flipped RLE-compressed object
2240  *
2241  *	What it says. RLE decoding is performed on the fly to an 8-bit bitmap.
2242  *
2243  */
2244 
draw_rle_zoom_hflip(struct osd_bitmap * bitmap,const struct atarigen_rle_descriptor * gfx,UINT32 color,int flipy,int sx,int sy,int scalex,int scaley,const struct rectangle * clip)2245 void draw_rle_zoom_hflip(struct osd_bitmap *bitmap, const struct atarigen_rle_descriptor *gfx,
2246 		UINT32 color, int flipy, int sx, int sy, int scalex, int scaley,
2247 		const struct rectangle *clip)
2248 {
2249 	const UINT16 *palette = &rle_colortable[color];
2250 	const UINT16 *row_start = gfx->data;
2251 	const UINT16 *table = gfx->table;
2252 	volatile int current_row = 0;
2253 
2254 	int scaled_width = (scalex * gfx->width + 0x7fff) >> 16;
2255 	int scaled_height = (scaley * gfx->height + 0x7fff) >> 16;
2256 	int pixels_to_skip = 0, xclipped = 0;
2257 	int dx, dy, ex, ey;
2258 	int y, sourcey;
2259 
2260 	/* make sure we didn't end up with 0 */
2261 	if (scaled_width == 0) scaled_width = 1;
2262 	if (scaled_height == 0) scaled_height = 1;
2263 
2264 	/* compute the remaining parameters */
2265 	dx = (gfx->width << 16) / scaled_width;
2266 	dy = (gfx->height << 16) / scaled_height;
2267 	ex = sx + scaled_width - 1;
2268 	ey = sy + scaled_height - 1;
2269 	sourcey = dy / 2;
2270 
2271 	/* left edge clip */
2272 	if (sx < clip->min_x)
2273 		sx = clip->min_x, xclipped = 1;
2274 	if (sx > clip->max_x)
2275 		return;
2276 
2277 	/* right edge clip */
2278 	if (ex > clip->max_x)
2279 		pixels_to_skip = ex - clip->max_x, xclipped = 1;
2280 	else if (ex < clip->min_x)
2281 		return;
2282 
2283 	/* top edge clip */
2284 	if (sy < clip->min_y)
2285 	{
2286 		sourcey += (clip->min_y - sy) * dy;
2287 		sy = clip->min_y;
2288 	}
2289 	else if (sy > clip->max_y)
2290 		return;
2291 
2292 	/* bottom edge clip */
2293 	if (ey > clip->max_y)
2294 		ey = clip->max_y;
2295 	else if (ey < clip->min_y)
2296 		return;
2297 
2298 	/* loop top to bottom */
2299 	for (y = sy; y <= ey; y++, sourcey += dy)
2300 	{
2301 		UINT8 *dest = &bitmap->line[y][ex];
2302 		int j, sourcex = dx / 2, rle_end = 0;
2303 		const UINT16 *base;
2304 		int entry_count;
2305 
2306 		/* loop until we hit the row we're on */
2307 		for ( ; current_row != (sourcey >> 16); current_row++)
2308 			row_start += 1 + *row_start;
2309 
2310 		/* grab our starting parameters from this row */
2311 		base = row_start;
2312 		entry_count = *base++;
2313 
2314 		/* non-clipped case */
2315 		if (!xclipped)
2316 		{
2317 			/* decode the pixels */
2318 			for (j = 0; j < entry_count; j++)
2319 			{
2320 				int word = *base++;
2321 				int count, value;
2322 
2323 				/* decode the low byte first */
2324 				count = table[word & 0xff];
2325 				value = count & 0xff;
2326 				rle_end += (count & 0xff00) << 8;
2327 
2328 				/* store copies of the value until we pass the end of this chunk */
2329 				if (value)
2330 				{
2331 					value = palette[value];
2332 					while (sourcex < rle_end)
2333 						*dest-- = value, sourcex += dx;
2334 				}
2335 				else
2336 				{
2337 					while (sourcex < rle_end)
2338 						dest--, sourcex += dx;
2339 				}
2340 
2341 				/* decode the upper byte second */
2342 				count = table[word >> 8];
2343 				value = count & 0xff;
2344 				rle_end += (count & 0xff00) << 8;
2345 
2346 				/* store copies of the value until we pass the end of this chunk */
2347 				if (value)
2348 				{
2349 					value = palette[value];
2350 					while (sourcex < rle_end)
2351 						*dest-- = value, sourcex += dx;
2352 				}
2353 				else
2354 				{
2355 					while (sourcex < rle_end)
2356 						dest--, sourcex += dx;
2357 				}
2358 			}
2359 		}
2360 
2361 		/* clipped case */
2362 		else
2363 		{
2364 			const UINT8 *start = &bitmap->line[y][sx];
2365 			int to_be_skipped = pixels_to_skip;
2366 
2367 			/* decode the pixels */
2368 			for (j = 0; j < entry_count && dest >= start; j++)
2369 			{
2370 				int word = *base++;
2371 				int count, value;
2372 
2373 				/* decode the low byte first */
2374 				count = table[word & 0xff];
2375 				value = count & 0xff;
2376 				rle_end += (count & 0xff00) << 8;
2377 
2378 				/* store copies of the value until we pass the end of this chunk */
2379 				if (to_be_skipped)
2380 				{
2381 					while (to_be_skipped && sourcex < rle_end)
2382 						dest--, sourcex += dx, to_be_skipped--;
2383 					if (to_be_skipped) goto next1;
2384 				}
2385 				if (value)
2386 				{
2387 					value = palette[value];
2388 					while (sourcex < rle_end && dest >= start)
2389 						*dest-- = value, sourcex += dx;
2390 				}
2391 				else
2392 				{
2393 					while (sourcex < rle_end)
2394 						dest--, sourcex += dx;
2395 				}
2396 
2397 			next1:
2398 				/* decode the upper byte second */
2399 				count = table[word >> 8];
2400 				value = count & 0xff;
2401 				rle_end += (count & 0xff00) << 8;
2402 
2403 				/* store copies of the value until we pass the end of this chunk */
2404 				if (to_be_skipped)
2405 				{
2406 					while (to_be_skipped && sourcex < rle_end)
2407 						dest--, sourcex += dx, to_be_skipped--;
2408 					if (to_be_skipped) goto next2;
2409 				}
2410 				if (value)
2411 				{
2412 					value = palette[value];
2413 					while (sourcex < rle_end && dest >= start)
2414 						*dest-- = value, sourcex += dx;
2415 				}
2416 				else
2417 				{
2418 					while (sourcex < rle_end)
2419 						dest--, sourcex += dx;
2420 				}
2421 			next2:
2422 				;
2423 			}
2424 		}
2425 	}
2426 }
2427 
2428 
2429 /*
2430  *	Draw a horizontally-flipped RLE-compressed object
2431  *
2432  *	What it says. RLE decoding is performed on the fly to a 16-bit bitmap.
2433  *
2434  */
2435 
draw_rle_zoom_hflip_16(struct osd_bitmap * bitmap,const struct atarigen_rle_descriptor * gfx,UINT32 color,int flipy,int sx,int sy,int scalex,int scaley,const struct rectangle * clip)2436 void draw_rle_zoom_hflip_16(struct osd_bitmap *bitmap, const struct atarigen_rle_descriptor *gfx,
2437 		UINT32 color, int flipy, int sx, int sy, int scalex, int scaley,
2438 		const struct rectangle *clip)
2439 {
2440 	const UINT16 *palette = &rle_colortable[color];
2441 	const UINT16 *row_start = gfx->data;
2442 	const UINT16 *table = gfx->table;
2443 	volatile int current_row = 0;
2444 
2445 	int scaled_width = (scalex * gfx->width + 0x7fff) >> 16;
2446 	int scaled_height = (scaley * gfx->height + 0x7fff) >> 16;
2447 	int pixels_to_skip = 0, xclipped = 0;
2448 	int dx, dy, ex, ey;
2449 	int y, sourcey;
2450 
2451 	/* make sure we didn't end up with 0 */
2452 	if (scaled_width == 0) scaled_width = 1;
2453 	if (scaled_height == 0) scaled_height = 1;
2454 
2455 	/* compute the remaining parameters */
2456 	dx = (gfx->width << 16) / scaled_width;
2457 	dy = (gfx->height << 16) / scaled_height;
2458 	ex = sx + scaled_width - 1;
2459 	ey = sy + scaled_height - 1;
2460 	sourcey = dy / 2;
2461 
2462 	/* left edge clip */
2463 	if (sx < clip->min_x)
2464 		sx = clip->min_x, xclipped = 1;
2465 	if (sx > clip->max_x)
2466 		return;
2467 
2468 	/* right edge clip */
2469 	if (ex > clip->max_x)
2470 		pixels_to_skip = ex - clip->max_x, xclipped = 1;
2471 	else if (ex < clip->min_x)
2472 		return;
2473 
2474 	/* top edge clip */
2475 	if (sy < clip->min_y)
2476 	{
2477 		sourcey += (clip->min_y - sy) * dy;
2478 		sy = clip->min_y;
2479 	}
2480 	else if (sy > clip->max_y)
2481 		return;
2482 
2483 	/* bottom edge clip */
2484 	if (ey > clip->max_y)
2485 		ey = clip->max_y;
2486 	else if (ey < clip->min_y)
2487 		return;
2488 
2489 	/* loop top to bottom */
2490 	for (y = sy; y <= ey; y++, sourcey += dy)
2491 	{
2492 		UINT16 *dest = (UINT16 *)&bitmap->line[y][ex * 2];
2493 		int j, sourcex = dx / 2, rle_end = 0;
2494 		const UINT16 *base;
2495 		int entry_count;
2496 
2497 		/* loop until we hit the row we're on */
2498 		for ( ; current_row != (sourcey >> 16); current_row++)
2499 			row_start += 1 + *row_start;
2500 
2501 		/* grab our starting parameters from this row */
2502 		base = row_start;
2503 		entry_count = *base++;
2504 
2505 		/* non-clipped case */
2506 		if (!xclipped)
2507 		{
2508 			/* decode the pixels */
2509 			for (j = 0; j < entry_count; j++)
2510 			{
2511 				int word = *base++;
2512 				int count, value;
2513 
2514 				/* decode the low byte first */
2515 				count = table[word & 0xff];
2516 				value = count & 0xff;
2517 				rle_end += (count & 0xff00) << 8;
2518 
2519 				/* store copies of the value until we pass the end of this chunk */
2520 				if (value)
2521 				{
2522 					value = palette[value];
2523 					while (sourcex < rle_end)
2524 						*dest-- = value, sourcex += dx;
2525 				}
2526 				else
2527 				{
2528 					while (sourcex < rle_end)
2529 						dest--, sourcex += dx;
2530 				}
2531 
2532 				/* decode the upper byte second */
2533 				count = table[word >> 8];
2534 				value = count & 0xff;
2535 				rle_end += (count & 0xff00) << 8;
2536 
2537 				/* store copies of the value until we pass the end of this chunk */
2538 				if (value)
2539 				{
2540 					value = palette[value];
2541 					while (sourcex < rle_end)
2542 						*dest-- = value, sourcex += dx;
2543 				}
2544 				else
2545 				{
2546 					while (sourcex < rle_end)
2547 						dest--, sourcex += dx;
2548 				}
2549 			}
2550 		}
2551 
2552 		/* clipped case */
2553 		else
2554 		{
2555 			const UINT16 *start = (const UINT16 *)&bitmap->line[y][sx * 2];
2556 			int to_be_skipped = pixels_to_skip;
2557 
2558 			/* decode the pixels */
2559 			for (j = 0; j < entry_count && dest >= start; j++)
2560 			{
2561 				int word = *base++;
2562 				int count, value;
2563 
2564 				/* decode the low byte first */
2565 				count = table[word & 0xff];
2566 				value = count & 0xff;
2567 				rle_end += (count & 0xff00) << 8;
2568 
2569 				/* store copies of the value until we pass the end of this chunk */
2570 				if (to_be_skipped)
2571 				{
2572 					while (to_be_skipped && sourcex < rle_end)
2573 						dest--, sourcex += dx, to_be_skipped--;
2574 					if (to_be_skipped) goto next3;
2575 				}
2576 				if (value)
2577 				{
2578 					value = palette[value];
2579 					while (sourcex < rle_end && dest >= start)
2580 						*dest-- = value, sourcex += dx;
2581 				}
2582 				else
2583 				{
2584 					while (sourcex < rle_end)
2585 						dest--, sourcex += dx;
2586 				}
2587 
2588 			next3:
2589 				/* decode the upper byte second */
2590 				count = table[word >> 8];
2591 				value = count & 0xff;
2592 				rle_end += (count & 0xff00) << 8;
2593 
2594 				/* store copies of the value until we pass the end of this chunk */
2595 				if (to_be_skipped)
2596 				{
2597 					while (to_be_skipped && sourcex < rle_end)
2598 						dest--, sourcex += dx, to_be_skipped--;
2599 					if (to_be_skipped) goto next4;
2600 				}
2601 				if (value)
2602 				{
2603 					value = palette[value];
2604 					while (sourcex < rle_end && dest >= start)
2605 						*dest-- = value, sourcex += dx;
2606 				}
2607 				else
2608 				{
2609 					while (sourcex < rle_end)
2610 						dest--, sourcex += dx;
2611 				}
2612 			next4:
2613 				;
2614 			}
2615 		}
2616 	}
2617 }
2618 
2619 
2620 /*--------------------------------------------------------------------------
2621 
2622 	Playfield rendering
2623 
2624 		atarigen_pf_state - data block describing the playfield
2625 
2626 		atarigen_pf_callback - called back for each chunk during processing
2627 
2628 		atarigen_pf_init - initializes and configures the playfield state
2629 		atarigen_pf_free - frees all memory allocated by atarigen_pf_init
2630 		atarigen_pf_reset - reset for a new frame (use only if not using interrupt system)
2631 		atarigen_pf_update - updates the playfield state for the given scanline
2632 		atarigen_pf_process - processes the current list of parameters
2633 
2634 		atarigen_pf2_init - same as above but for a second playfield
2635 		atarigen_pf2_free - same as above but for a second playfield
2636 		atarigen_pf2_reset - same as above but for a second playfield
2637 		atarigen_pf2_update - same as above but for a second playfield
2638 		atarigen_pf2_process - same as above but for a second playfield
2639 
2640 --------------------------------------------------------------------------*/
2641 
2642 /* types */
2643 struct playfield_data
2644 {
2645 	struct osd_bitmap *bitmap;
2646 	UINT8 *dirty;
2647 	UINT8 *visit;
2648 
2649 	int tilewidth;
2650 	int tileheight;
2651 	int tilewidth_shift;
2652 	int tileheight_shift;
2653 	int xtiles_mask;
2654 	int ytiles_mask;
2655 
2656 	int entries;
2657 	int *scanline;
2658 	struct atarigen_pf_state *state;
2659 	struct atarigen_pf_state *last_state;
2660 };
2661 
2662 /* globals */
2663 struct osd_bitmap *atarigen_pf_bitmap;
2664 UINT8 *atarigen_pf_dirty;
2665 UINT8 *atarigen_pf_visit;
2666 
2667 struct osd_bitmap *atarigen_pf2_bitmap;
2668 UINT8 *atarigen_pf2_dirty;
2669 UINT8 *atarigen_pf2_visit;
2670 
2671 struct osd_bitmap *atarigen_pf_overrender_bitmap;
2672 UINT16 atarigen_overrender_colortable[32];
2673 
2674 /* statics */
2675 static struct playfield_data playfield;
2676 static struct playfield_data playfield2;
2677 
2678 /* prototypes */
2679 static int internal_pf_init(struct playfield_data *pf, const struct atarigen_pf_desc *source_desc);
2680 static void internal_pf_free(struct playfield_data *pf);
2681 static void internal_pf_reset(struct playfield_data *pf);
2682 static void internal_pf_update(struct playfield_data *pf, const struct atarigen_pf_state *state, int scanline);
2683 static void internal_pf_process(struct playfield_data *pf, atarigen_pf_callback callback, void *param, const struct rectangle *clip);
2684 static int compute_shift(int size);
2685 static int compute_mask(int count);
2686 
2687 
2688 /*
2689  *	Playfield render initialization
2690  *
2691  *	Allocates memory for the playfield and initializes all structures.
2692  *
2693  */
2694 
internal_pf_init(struct playfield_data * pf,const struct atarigen_pf_desc * source_desc)2695 static int internal_pf_init(struct playfield_data *pf, const struct atarigen_pf_desc *source_desc)
2696 {
2697 	/* allocate the bitmap */
2698 	if (!source_desc->noscroll)
2699 		pf->bitmap = bitmap_alloc(source_desc->tilewidth * source_desc->xtiles,
2700 									source_desc->tileheight * source_desc->ytiles);
2701 	else
2702 		pf->bitmap = bitmap_alloc(Machine->drv->screen_width,
2703 									Machine->drv->screen_height);
2704 	if (!pf->bitmap)
2705 		return 1;
2706 
2707 	/* allocate the dirty tile map */
2708 	pf->dirty = (UINT8*)malloc(source_desc->xtiles * source_desc->ytiles);
2709 	if (!pf->dirty)
2710 	{
2711 		internal_pf_free(pf);
2712 		return 1;
2713 	}
2714 	memset(pf->dirty, 0xff, source_desc->xtiles * source_desc->ytiles);
2715 
2716 	/* allocate the visitation map */
2717 	pf->visit = (UINT8*)malloc(source_desc->xtiles * source_desc->ytiles);
2718 	if (!pf->visit)
2719 	{
2720 		internal_pf_free(pf);
2721 		return 1;
2722 	}
2723 
2724 	/* allocate the list of scanlines */
2725 	pf->scanline = (int*)malloc(source_desc->ytiles * source_desc->tileheight * sizeof(int));
2726 	if (!pf->scanline)
2727 	{
2728 		internal_pf_free(pf);
2729 		return 1;
2730 	}
2731 
2732 	/* allocate the list of parameters */
2733 	pf->state = (struct atarigen_pf_state*)malloc(source_desc->ytiles * source_desc->tileheight * sizeof(struct atarigen_pf_state));
2734 	if (!pf->state)
2735 	{
2736 		internal_pf_free(pf);
2737 		return 1;
2738 	}
2739 
2740 	/* copy the basic data */
2741 	pf->tilewidth = source_desc->tilewidth;
2742 	pf->tileheight = source_desc->tileheight;
2743 	pf->tilewidth_shift = compute_shift(source_desc->tilewidth);
2744 	pf->tileheight_shift = compute_shift(source_desc->tileheight);
2745 	pf->xtiles_mask = compute_mask(source_desc->xtiles);
2746 	pf->ytiles_mask = compute_mask(source_desc->ytiles);
2747 
2748 	/* initialize the last state to all zero */
2749 	pf->last_state = pf->state;
2750 	memset(pf->last_state, 0, sizeof(*pf->last_state));
2751 
2752 	/* reset */
2753 	internal_pf_reset(pf);
2754 
2755 	return 0;
2756 }
2757 
atarigen_pf_init(const struct atarigen_pf_desc * source_desc)2758 int atarigen_pf_init(const struct atarigen_pf_desc *source_desc)
2759 {
2760 	int result = internal_pf_init(&playfield, source_desc);
2761 	if (!result)
2762 	{
2763 		/* allocate the overrender bitmap */
2764 		atarigen_pf_overrender_bitmap = bitmap_alloc(Machine->drv->screen_width, Machine->drv->screen_height);
2765 		if (!atarigen_pf_overrender_bitmap)
2766 		{
2767 			internal_pf_free(&playfield);
2768 			return 1;
2769 		}
2770 
2771 		atarigen_pf_bitmap = playfield.bitmap;
2772 		atarigen_pf_dirty = playfield.dirty;
2773 		atarigen_pf_visit = playfield.visit;
2774 	}
2775 	return result;
2776 }
2777 
atarigen_pf2_init(const struct atarigen_pf_desc * source_desc)2778 int atarigen_pf2_init(const struct atarigen_pf_desc *source_desc)
2779 {
2780 	int result = internal_pf_init(&playfield2, source_desc);
2781 	if (!result)
2782 	{
2783 		atarigen_pf2_bitmap = playfield2.bitmap;
2784 		atarigen_pf2_dirty = playfield2.dirty;
2785 		atarigen_pf2_visit = playfield2.visit;
2786 	}
2787 	return result;
2788 }
2789 
2790 
2791 /*
2792  *	Playfield render free
2793  *
2794  *	Frees all memory allocated by the playfield system.
2795  *
2796  */
2797 
internal_pf_free(struct playfield_data * pf)2798 static void internal_pf_free(struct playfield_data *pf)
2799 {
2800 	if (pf->bitmap)
2801 		bitmap_free(pf->bitmap);
2802 	pf->bitmap = NULL;
2803 
2804 	if (pf->dirty)
2805 		free(pf->dirty);
2806 	pf->dirty = NULL;
2807 
2808 	if (pf->visit)
2809 		free(pf->visit);
2810 	pf->visit = NULL;
2811 
2812 	if (pf->scanline)
2813 		free(pf->scanline);
2814 	pf->scanline = NULL;
2815 
2816 	if (pf->state)
2817 		free(pf->state);
2818 	pf->state = NULL;
2819 }
2820 
atarigen_pf_free(void)2821 void atarigen_pf_free(void)
2822 {
2823 	internal_pf_free(&playfield);
2824 
2825 	/* free the overrender bitmap */
2826 	if (atarigen_pf_overrender_bitmap)
2827 		bitmap_free(atarigen_pf_overrender_bitmap);
2828 	atarigen_pf_overrender_bitmap = NULL;
2829 }
2830 
atarigen_pf2_free(void)2831 void atarigen_pf2_free(void)
2832 {
2833 	internal_pf_free(&playfield2);
2834 }
2835 
2836 
2837 /*
2838  *	Playfield render reset
2839  *
2840  *	Resets the playfield system for a new frame. Note that this is automatically called
2841  *	if you're using the interrupt system.
2842  *
2843  */
2844 
internal_pf_reset(struct playfield_data * pf)2845 void internal_pf_reset(struct playfield_data *pf)
2846 {
2847 	/* verify memory has been allocated -- we're called even if we're not used */
2848 	if (pf->scanline && pf->state)
2849 	{
2850 		pf->entries = 0;
2851 		internal_pf_update(pf, pf->last_state, 0);
2852 	}
2853 }
2854 
atarigen_pf_reset(void)2855 void atarigen_pf_reset(void)
2856 {
2857 	internal_pf_reset(&playfield);
2858 }
2859 
atarigen_pf2_reset(void)2860 void atarigen_pf2_reset(void)
2861 {
2862 	internal_pf_reset(&playfield2);
2863 }
2864 
2865 
2866 /*
2867  *	Playfield render update
2868  *
2869  *	Sets the parameters for a given scanline.
2870  *
2871  */
2872 
internal_pf_update(struct playfield_data * pf,const struct atarigen_pf_state * state,int scanline)2873 void internal_pf_update(struct playfield_data *pf, const struct atarigen_pf_state *state, int scanline)
2874 {
2875 	if (pf->entries > 0)
2876 	{
2877 		/* if the current scanline matches the previous one, just overwrite */
2878 		if (pf->scanline[pf->entries - 1] == scanline)
2879 			pf->entries--;
2880 
2881 		/* if the current data matches the previous data, ignore it */
2882 		else if (pf->last_state->hscroll == state->hscroll &&
2883 				 pf->last_state->vscroll == state->vscroll &&
2884 				 pf->last_state->param[0] == state->param[0] &&
2885 				 pf->last_state->param[1] == state->param[1])
2886 			return;
2887 	}
2888 
2889 	/* remember this entry as the last set of parameters */
2890 	pf->last_state = &pf->state[pf->entries];
2891 
2892 	/* copy in the data */
2893 	pf->scanline[pf->entries] = scanline;
2894 	pf->state[pf->entries++] = *state;
2895 
2896 	/* set the final scanline to be huge -- it will be clipped during processing */
2897 	pf->scanline[pf->entries] = 100000;
2898 }
2899 
atarigen_pf_update(const struct atarigen_pf_state * state,int scanline)2900 void atarigen_pf_update(const struct atarigen_pf_state *state, int scanline)
2901 {
2902 	internal_pf_update(&playfield, state, scanline);
2903 }
2904 
atarigen_pf2_update(const struct atarigen_pf_state * state,int scanline)2905 void atarigen_pf2_update(const struct atarigen_pf_state *state, int scanline)
2906 {
2907 	internal_pf_update(&playfield2, state, scanline);
2908 }
2909 
2910 
2911 /*
2912  *	Playfield render process
2913  *
2914  *	Processes the playfield in chunks.
2915  *
2916  */
2917 
internal_pf_process(struct playfield_data * pf,atarigen_pf_callback callback,void * param,const struct rectangle * clip)2918 void internal_pf_process(struct playfield_data *pf, atarigen_pf_callback callback, void *param, const struct rectangle *clip)
2919 {
2920 	struct rectangle curclip;
2921 	struct rectangle tiles;
2922 	int y;
2923 
2924 	/* preinitialization */
2925 	curclip.min_x = clip->min_x;
2926 	curclip.max_x = clip->max_x;
2927 
2928 	/* loop over all entries */
2929 	for (y = 0; y < pf->entries; y++)
2930 	{
2931 		struct atarigen_pf_state *current = &pf->state[y];
2932 
2933 		/* determine the clip rect */
2934 		curclip.min_y = pf->scanline[y];
2935 		curclip.max_y = pf->scanline[y + 1] - 1;
2936 
2937 		/* skip if we're clipped out */
2938 		if (curclip.min_y > clip->max_y || curclip.max_y < clip->min_y)
2939 			continue;
2940 
2941 		/* clip the clipper */
2942 		if (curclip.min_y < clip->min_y)
2943 			curclip.min_y = clip->min_y;
2944 		if (curclip.max_y > clip->max_y)
2945 			curclip.max_y = clip->max_y;
2946 
2947 		/* determine the tile rect */
2948 		tiles.min_x = ((current->hscroll + curclip.min_x) >> pf->tilewidth_shift) & pf->xtiles_mask;
2949 		tiles.max_x = ((current->hscroll + curclip.max_x + pf->tilewidth) >> pf->tilewidth_shift) & pf->xtiles_mask;
2950 		tiles.min_y = ((current->vscroll + curclip.min_y) >> pf->tileheight_shift) & pf->ytiles_mask;
2951 		tiles.max_y = ((current->vscroll + curclip.max_y + pf->tileheight) >> pf->tileheight_shift) & pf->ytiles_mask;
2952 
2953 		/* call the callback */
2954 		(*callback)(&curclip, &tiles, current, param);
2955 	}
2956 }
2957 
atarigen_pf_process(atarigen_pf_callback callback,void * param,const struct rectangle * clip)2958 void atarigen_pf_process(atarigen_pf_callback callback, void *param, const struct rectangle *clip)
2959 {
2960 	internal_pf_process(&playfield, callback, param, clip);
2961 }
2962 
atarigen_pf2_process(atarigen_pf_callback callback,void * param,const struct rectangle * clip)2963 void atarigen_pf2_process(atarigen_pf_callback callback, void *param, const struct rectangle *clip)
2964 {
2965 	internal_pf_process(&playfield2, callback, param, clip);
2966 }
2967 
2968 
2969 /*
2970  *	Shift value computer
2971  *
2972  *	Determines the log2(value).
2973  *
2974  */
2975 
compute_shift(int size)2976 static int compute_shift(int size)
2977 {
2978 	int i;
2979 
2980 	/* loop until we shift to zero */
2981 	for (i = 0; i < 32; i++)
2982 		if (!(size >>= 1))
2983 			break;
2984 	return i;
2985 }
2986 
2987 
2988 /*
2989  *	Mask computer
2990  *
2991  *	Determines the best mask to use for the given value.
2992  *
2993  */
2994 
compute_mask(int count)2995 static int compute_mask(int count)
2996 {
2997 	int shift = compute_shift(count);
2998 
2999 	/* simple case - count is an even power of 2 */
3000 	if (count == (1 << shift))
3001 		return count - 1;
3002 
3003 	/* slightly less simple case - round up to the next power of 2 */
3004 	else
3005 		return (1 << (shift + 1)) - 1;
3006 }
3007 
3008 
3009 
3010 
3011 
3012 /*--------------------------------------------------------------------------
3013 
3014 	Misc Video stuff
3015 
3016 		atarigen_get_hblank - returns the current HBLANK state
3017 		atarigen_halt_until_hblank_0_w - write handler for a HBLANK halt
3018 		atarigen_666_paletteram_w - 6-6-6 special RGB paletteram handler
3019 		atarigen_expanded_666_paletteram_w - byte version of above
3020 
3021 --------------------------------------------------------------------------*/
3022 
3023 /* prototypes */
3024 static void unhalt_cpu(int param);
3025 
3026 
3027 /*
3028  *	Compute HBLANK state
3029  *
3030  *	Returns a guesstimate about the current HBLANK state, based on the assumption that
3031  *	HBLANK represents 10% of the scanline period.
3032  *
3033  */
3034 
atarigen_get_hblank(void)3035 int atarigen_get_hblank(void)
3036 {
3037 	return (cpu_gethorzbeampos() > (Machine->drv->screen_width * 9 / 10));
3038 }
3039 
3040 
3041 /*
3042  *	Halt CPU 0 until HBLANK
3043  *
3044  *	What it says.
3045  *
3046  */
3047 
WRITE_HANDLER(atarigen_halt_until_hblank_0_w)3048 WRITE_HANDLER( atarigen_halt_until_hblank_0_w )
3049 {
3050 	/* halt the CPU until the next HBLANK */
3051 	int hpos = cpu_gethorzbeampos();
3052 	int hblank = Machine->drv->screen_width * 9 / 10;
3053 	float fraction;
3054 
3055 	/* if we're in hblank, set up for the next one */
3056 	if (hpos >= hblank)
3057 		hblank += Machine->drv->screen_width;
3058 
3059 	/* halt and set a timer to wake up */
3060 	fraction = (float)(hblank - hpos) / (float)Machine->drv->screen_width;
3061 	timer_set(cpu_getscanlineperiod() * fraction, 0, unhalt_cpu);
3062 	cpu_set_halt_line(0, ASSERT_LINE);
3063 }
3064 
3065 
3066 /*
3067  *	6-6-6 RGB palette RAM handler
3068  *
3069  *	What it says.
3070  *
3071  */
3072 
WRITE_HANDLER(atarigen_666_paletteram_w)3073 WRITE_HANDLER( atarigen_666_paletteram_w )
3074 {
3075 	int oldword = READ_WORD(&paletteram[offset]);
3076 	int newword = COMBINE_WORD(oldword,data);
3077 	WRITE_WORD(&paletteram[offset],newword);
3078 
3079 	{
3080 		int r, g, b;
3081 
3082 		r = ((newword >> 9) & 0x3e) | ((newword >> 15) & 1);
3083 		g = ((newword >> 4) & 0x3e) | ((newword >> 15) & 1);
3084 		b = ((newword << 1) & 0x3e) | ((newword >> 15) & 1);
3085 
3086 		r = (r << 2) | (r >> 4);
3087 		g = (g << 2) | (g >> 4);
3088 		b = (b << 2) | (b >> 4);
3089 
3090 		palette_change_color(offset / 2, r, g, b);
3091 	}
3092 }
3093 
3094 
3095 /*
3096  *	6-6-6 RGB expanded palette RAM handler
3097  *
3098  *	What it says.
3099  *
3100  */
3101 
WRITE_HANDLER(atarigen_expanded_666_paletteram_w)3102 WRITE_HANDLER( atarigen_expanded_666_paletteram_w )
3103 {
3104 	COMBINE_WORD_MEM(&paletteram[offset], data);
3105 
3106 	if (!(data & 0xff000000))
3107 	{
3108 		int palentry = offset / 4;
3109 		int newword = (READ_WORD(&paletteram[palentry * 4]) & 0xff00) | (READ_WORD(&paletteram[palentry * 4 + 2]) >> 8);
3110 
3111 		int r, g, b;
3112 
3113 		r = ((newword >> 9) & 0x3e) | ((newword >> 15) & 1);
3114 		g = ((newword >> 4) & 0x3e) | ((newword >> 15) & 1);
3115 		b = ((newword << 1) & 0x3e) | ((newword >> 15) & 1);
3116 
3117 		r = (r << 2) | (r >> 4);
3118 		g = (g << 2) | (g >> 4);
3119 		b = (b << 2) | (b >> 4);
3120 
3121 		palette_change_color(palentry & 0x1ff, r, g, b);
3122 	}
3123 }
3124 
3125 
3126 /*
3127  *	CPU unhalter
3128  *
3129  *	Timer callback to release the CPU from a halted state.
3130  *
3131  */
3132 
unhalt_cpu(int param)3133 static void unhalt_cpu(int param)
3134 {
3135 	cpu_set_halt_line(param, CLEAR_LINE);
3136 }
3137 
3138 
3139 
3140 /*--------------------------------------------------------------------------
3141 
3142 	General stuff
3143 
3144 		atarigen_show_slapstic_message - display warning about slapstic
3145 		atarigen_show_sound_message - display warning about coins
3146 		atarigen_update_messages - update messages
3147 
3148 --------------------------------------------------------------------------*/
3149 
3150 /* statics */
3151 static char *message_text[10];
3152 static int message_countdown;
3153 
3154 /*
3155  *	Display a warning message about slapstic protection
3156  *
3157  *	What it says.
3158  *
3159  */
3160 
atarigen_show_slapstic_message(void)3161 void atarigen_show_slapstic_message(void)
3162 {
3163 	message_text[0] = "There are known problems with";
3164 	message_text[1] = "later levels of this game due";
3165 	message_text[2] = "to incomplete slapstic emulation.";
3166 	message_text[3] = "You have been warned.";
3167 	message_text[4] = NULL;
3168 	message_countdown = 15 * Machine->drv->frames_per_second;
3169 }
3170 
3171 
3172 /*
3173  *	Display a warning message about sound being disabled
3174  *
3175  *	What it says.
3176  *
3177  */
3178 
atarigen_show_sound_message(void)3179 void atarigen_show_sound_message(void)
3180 {
3181 	if (Machine->sample_rate == 0)
3182 	{
3183 		message_text[0] = "This game may have trouble accepting";
3184 		message_text[1] = "coins, or may even behave strangely,";
3185 		message_text[2] = "because you have disabled sound.";
3186 		message_text[3] = NULL;
3187 		message_countdown = 15 * Machine->drv->frames_per_second;
3188 	}
3189 }
3190 
3191 
3192 /*
3193  *	Update on-screen messages
3194  *
3195  *	What it says.
3196  *
3197  */
3198 
atarigen_update_messages(void)3199 void atarigen_update_messages(void)
3200 {
3201 	if (message_countdown && message_text[0])
3202 	{
3203 		int maxwidth = 0;
3204 		int lines, x, y, i, j;
3205 
3206 		/* first count lines and determine the maximum width */
3207 		for (lines = 0; lines < 10; lines++)
3208 		{
3209 			if (!message_text[lines]) break;
3210 			x = strlen(message_text[lines]);
3211 			if (x > maxwidth) maxwidth = x;
3212 		}
3213 		maxwidth += 2;
3214 
3215 		/* determine y offset */
3216 		x = (Machine->uiwidth - Machine->uifontwidth * maxwidth) / 2;
3217 		y = (Machine->uiheight - Machine->uifontheight * (lines + 2)) / 2;
3218 
3219 		/* draw a row of spaces at the top and bottom */
3220 		for (i = 0; i < maxwidth; i++)
3221 		{
3222 			ui_text(Machine->scrbitmap, " ", x + i * Machine->uifontwidth, y);
3223 			ui_text(Machine->scrbitmap, " ", x + i * Machine->uifontwidth, y + (lines + 1) * Machine->uifontheight);
3224 		}
3225 		y += Machine->uifontheight;
3226 
3227 		/* draw the message */
3228 		for (i = 0; i < lines; i++)
3229 		{
3230 			int width = strlen(message_text[i]) * Machine->uifontwidth;
3231 			int dx = (Machine->uifontwidth * maxwidth - width) / 2;
3232 
3233 			for (j = 0; j < dx; j += Machine->uifontwidth)
3234 			{
3235 				ui_text(Machine->scrbitmap, " ", x + j, y);
3236 				ui_text(Machine->scrbitmap, " ", x + (maxwidth - 1) * Machine->uifontwidth - j, y);
3237 			}
3238 
3239 			ui_text(Machine->scrbitmap, message_text[i], x + dx, y);
3240 			y += Machine->uifontheight;
3241 		}
3242 
3243 		/* decrement the counter */
3244 		message_countdown--;
3245 
3246 		/* if a coin is inserted, make the message go away */
3247 		if (keyboard_pressed(KEYCODE_5) || keyboard_pressed(KEYCODE_6) ||
3248 		    keyboard_pressed(KEYCODE_7) || keyboard_pressed(KEYCODE_8))
3249 			message_countdown = 0;
3250 	}
3251 	else
3252 		message_text[0] = NULL;
3253 }
3254 
3255 
3256