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