Enable game sounds in PacBox. Sound is OFF by default but can be enabled from the...
[kugel-rb.git] / apps / plugins / pacbox / arcade.c
blobecf6d10af8333a434922c5e379d339b30316b40a
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Pacbox - a Pacman Emulator for Rockbox
12 * Based on PIE - Pacman Instructional Emulator
14 * Copyright (c) 1997-2003,2004 Alessandro Scotti
15 * http://www.ascotti.org/
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
25 ****************************************************************************/
27 #include "pacbox.h"
28 #include "arcade.h"
29 #include "hardware.h"
30 #include "wsg3.h"
31 #include <string.h>
32 #include "plugin.h"
34 #ifndef HAVE_LCD_COLOR
35 /* Convert RGB888 to 2-bit greyscale - logic taken from bmp2rb.c */
36 static fb_data rgb_to_gray(unsigned int r, unsigned int g, unsigned int b)
38 int brightness = ( 2*r + 4*g + b );
39 if( r == 0 && g == 0 && b == 0 )
40 return 3;
42 brightness = (brightness/450);
43 if( brightness > 2 ) return 0;
44 else return 2-brightness;
46 #endif
48 unsigned char color_data_[256] = {
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0x01,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0x03,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0x05,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0x07,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x09,
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x01, 0x0c, 0x0f,
57 0x00, 0x0e, 0x00, 0x0b, 0x00, 0x0c, 0x0b, 0x0e,
58 0x00, 0x0c, 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x01, 0x02, 0x0f, 0x00, 0x07, 0x0c, 0x02,
60 0x00, 0x09, 0x06, 0x0f, 0x00, 0x0d, 0x0c, 0x0f,
61 0x00, 0x05, 0x03, 0x09, 0x00, 0x0f, 0x0b, 0x00,
62 0x00, 0x0e, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x0b,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0e, 0x01,
64 0x00, 0x0f, 0x0b, 0x0e, 0x00, 0x0e, 0x00, 0x0f,
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
83 unsigned char palette_data_[0x20] = {
84 0x00, 0x07, 0x66, 0xef, 0x00, 0xf8, 0xea, 0x6f,
85 0x00, 0x3f, 0x00, 0xc9, 0x38, 0xaa, 0xaf, 0xf6,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
90 enum {
91 Normal = 0x00,
92 FlipY = 0x01,
93 FlipX = 0x02,
94 FlipXY = 0x03
97 // Namco 3-channel Wave Sound Generator wave data (8 waveforms with 32 4-bit entries each)
98 static unsigned char default_sound_prom[] =
100 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0D, 0x0E,
101 0x0E, 0x0E, 0x0D, 0x0D, 0x0C, 0x0B, 0x0A, 0x09,
102 0x07, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x00,
103 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05,
104 0x07, 0x0C, 0x0E, 0x0E, 0x0D, 0x0B, 0x09, 0x0A,
105 0x0B, 0x0B, 0x0A, 0x09, 0x06, 0x04, 0x03, 0x05,
106 0x07, 0x09, 0x0B, 0x0A, 0x08, 0x05, 0x04, 0x03,
107 0x03, 0x04, 0x05, 0x03, 0x01, 0x00, 0x00, 0x02,
108 0x07, 0x0A, 0x0C, 0x0D, 0x0E, 0x0D, 0x0C, 0x0A,
109 0x07, 0x04, 0x02, 0x01, 0x00, 0x01, 0x02, 0x04,
110 0x07, 0x0B, 0x0D, 0x0E, 0x0D, 0x0B, 0x07, 0x03,
111 0x01, 0x00, 0x01, 0x03, 0x07, 0x0E, 0x07, 0x00,
112 0x07, 0x0D, 0x0B, 0x08, 0x0B, 0x0D, 0x09, 0x06,
113 0x0B, 0x0E, 0x0C, 0x07, 0x09, 0x0A, 0x06, 0x02,
114 0x07, 0x0C, 0x08, 0x04, 0x05, 0x07, 0x02, 0x00,
115 0x03, 0x08, 0x05, 0x01, 0x03, 0x06, 0x03, 0x01,
116 0x00, 0x08, 0x0F, 0x07, 0x01, 0x08, 0x0E, 0x07,
117 0x02, 0x08, 0x0D, 0x07, 0x03, 0x08, 0x0C, 0x07,
118 0x04, 0x08, 0x0B, 0x07, 0x05, 0x08, 0x0A, 0x07,
119 0x06, 0x08, 0x09, 0x07, 0x07, 0x08, 0x08, 0x07,
120 0x07, 0x08, 0x06, 0x09, 0x05, 0x0A, 0x04, 0x0B,
121 0x03, 0x0C, 0x02, 0x0D, 0x01, 0x0E, 0x00, 0x0F,
122 0x00, 0x0F, 0x01, 0x0E, 0x02, 0x0D, 0x03, 0x0C,
123 0x04, 0x0B, 0x05, 0x0A, 0x06, 0x09, 0x07, 0x08,
124 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
125 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
126 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
127 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
128 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
129 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
130 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
131 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
134 /* Putting this in IRAM actually slows down the iPods, but is good for
135 the Coldfire
137 #ifdef CPU_COLDFIRE
138 fb_data palette[256] IBSS_ATTR; /* Color palette */
139 #else
140 fb_data palette[256]; /* Color palette */
141 #endif
144 void init_PacmanMachine(int dip)
146 int i;
148 /* Initialize the CPU and the RAM */
149 z80_reset();
150 rb->memset( &ram_[0x4000], 0xFF, 0x1000 );
152 /* Initialize the WSG3 */
153 wsg3_init(SoundClock);
155 /* Set the sound PROM to the default values for the original Namco chip */
156 wsg3_set_sound_prom(default_sound_prom);
158 /* Initialize parameters */
159 port1_ = 0xFF;
160 port2_ = 0xFF;
161 coin_counter_ = 0;
163 /* Reset the machine */
164 reset_PacmanMachine();
166 /* Set the DIP switches to a default configuration */
167 setDipSwitches( dip );
169 /* Initialize the video character translation tables: video memory has a
170 very peculiar arrangement in Pacman so we precompute a few tables to
171 move around faster */
173 for( i=0x000; i<0x400; i++ ) {
174 int x, y;
176 if( i < 0x040 ) {
177 x = 29 - (i & 0x1F);
178 y = 34 + (i >> 5);
180 else if( i >= 0x3C0 ) {
181 x = 29 - (i & 0x1F);
182 y = ((i-0x3C0) >> 5);
184 else {
185 x = 27 - ((i-0x40) >> 5);
186 y = 2 + ((i-0x40) & 0x1F);
188 if( (y >= 0) && (y < 36) && (x >= 0) && (x < 28) )
189 vchar_to_i_[i] = y*28 + x;
190 else
191 vchar_to_i_[i] = 0x3FF;
195 void reset_PacmanMachine(void)
197 int i;
199 z80_reset();
200 output_devices_ = 0;
201 interrupt_vector_ = 0;
203 rb->memset( ram_+0x4000, 0, 0x1000 );
204 rb->memset( color_mem_, 0, sizeof(color_mem_) );
205 rb->memset( video_mem_, 0, sizeof(video_mem_) );
206 rb->memset( dirty_, 0, sizeof(dirty_) );
208 for( i=0; i<8; i++ ) {
209 sprites_[i].color = 0;
210 sprites_[i].x = ScreenWidth;
215 Run the machine for one frame.
217 int run(void)
219 /* Run until the CPU has executed the number of cycles per frame
220 (the function returns the number of "extra" cycles spent by the
221 last instruction but that is not really important here) */
223 unsigned extraCycles = z80_run( CpuCyclesPerFrame );
225 /* Reset the CPU cycle counter to make sure it doesn't overflow,
226 also take into account the extra cycles from the previous run */
228 setCycles( extraCycles );
230 /* If interrupts are enabled, force a CPU interrupt with the vector
231 set by the program */
233 if( output_devices_ & InterruptEnabled ) {
234 z80_interrupt( interrupt_vector_ );
237 return 0;
240 /** Returns the status of the coin lockout door. */
241 unsigned char getCoinLockout(void) {
242 return output_devices_ & CoinLockout ? 1 : 0;
245 static void decodeCharByte( unsigned char b, unsigned char * charbuf, int charx, int chary, int charwidth )
247 int i;
249 for( i=3; i>=0; i-- ) {
250 charbuf[charx+(chary+i)*charwidth] = (b & 1) | ((b >> 3) & 2);
251 b >>= 1;
255 static void decodeCharLine( unsigned char * src, unsigned char * charbuf, int charx, int chary, int charwidth )
257 int x;
259 for( x=7; x>=0; x-- ) {
260 decodeCharByte( *src++, charbuf, x+charx, chary, charwidth );
264 static void decodeCharSet( unsigned char * mem, unsigned char * charset )
266 int i;
268 for( i=0; i<256; i++ ) {
269 unsigned char * src = mem + 16*i;
270 unsigned char * dst = charset + 64*i;
272 decodeCharLine( src, dst, 0, 4, 8 );
273 decodeCharLine( src+8, dst, 0, 0, 8 );
277 static void decodeSprites( unsigned char * mem, unsigned char * sprite_data )
279 int i;
281 for( i=0; i<64; i++ ) {
282 unsigned char * src = mem + i*64;
283 unsigned char * dst = sprite_data + 256*i;
285 decodeCharLine( src , dst, 8, 12, 16 );
286 decodeCharLine( src+ 8, dst, 8, 0, 16 );
287 decodeCharLine( src+16, dst, 8, 4, 16 );
288 decodeCharLine( src+24, dst, 8, 8, 16 );
289 decodeCharLine( src+32, dst, 0, 12, 16 );
290 decodeCharLine( src+40, dst, 0, 0, 16 );
291 decodeCharLine( src+48, dst, 0, 4, 16 );
292 decodeCharLine( src+56, dst, 0, 8, 16 );
297 Decode one byte from the encoded color palette.
299 An encoded palette byte contains RGB information bit-packed as follows:
301 bit: 7 6 5 4 3 2 1 0
302 color: b b g g g r r r
304 static unsigned decodePaletteByte( unsigned char value )
306 unsigned bit0, bit1, bit2;
307 unsigned red, green, blue;
309 bit0 = (value >> 0) & 0x01;
310 bit1 = (value >> 1) & 0x01;
311 bit2 = (value >> 2) & 0x01;
312 red = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
314 bit0 = (value >> 3) & 0x01;
315 bit1 = (value >> 4) & 0x01;
316 bit2 = (value >> 5) & 0x01;
317 green = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
319 bit0 = 0;
320 bit1 = (value >> 6) & 0x01;
321 bit2 = (value >> 7) & 0x01;
322 blue = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
324 return (blue << 16 ) | (green << 8) | red;
327 void decodeROMs(void)
329 unsigned decoded_palette[0x20];
330 unsigned c;
332 int i;
334 decodeCharSet( charset_rom_, charmap_ );
335 decodeSprites( spriteset_rom_, spritemap_ );
337 for( i=0x00; i<0x20; i++ ) {
338 decoded_palette[i] = decodePaletteByte( palette_data_[i] );
340 for( i=0; i<256; i++ ) {
341 c = decoded_palette[ color_data_[i] & 0x0F ];
342 #ifdef HAVE_LCD_COLOR
343 palette[i] = LCD_RGBPACK((unsigned char) (c),
344 (unsigned char) (c >> 8),
345 (unsigned char) (c >> 16));
346 #else
347 palette[i] = rgb_to_gray((unsigned char) (c),
348 (unsigned char) (c >> 8),
349 (unsigned char) (c >> 16) );
350 #endif
353 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
354 rb->lcd_pal256_update_pal(palette);
355 #endif
358 void getDeviceInfo( enum InputDevice device, unsigned char * mask, unsigned char ** port )
360 static unsigned char MaskInfo[] = {
361 0x01 , // Joy1_Up
362 0x02 , // Joy1_Left
363 0x04 , // Joy1_Right
364 0x08 , // Joy1_Down
365 0x10 , // Switch_RackAdvance
366 0x20 , // CoinSlot_1
367 0x40 , // CoinSlot_2
368 0x80 , // Switch_AddCredit
369 0x01 , // Joy2_Up
370 0x02 , // Joy2_Left
371 0x04 , // Joy2_Right
372 0x08 , // Joy2_Down
373 0x10 , // Switch_Test
374 0x20 , // Key_OnePlayer
375 0x40 , // Key_TwoPlayers
376 0x80 // Switch_CocktailMode
379 *mask = MaskInfo[device];
381 switch( device ) {
382 case Joy1_Up:
383 case Joy1_Left:
384 case Joy1_Right:
385 case Joy1_Down:
386 case Switch_RackAdvance:
387 case CoinSlot_1:
388 case CoinSlot_2:
389 case Switch_AddCredit:
390 *port = &port1_;
391 break;
392 case Joy2_Up:
393 case Joy2_Left:
394 case Joy2_Right:
395 case Joy2_Down:
396 case Switch_Test:
397 case Key_OnePlayer:
398 case Key_TwoPlayers:
399 case Switch_CocktailMode:
400 *port = &port2_;
401 break;
402 default:
403 *port = 0;
404 break;
408 enum InputDeviceMode getDeviceMode( enum InputDevice device )
410 unsigned char mask;
411 unsigned char * port;
413 getDeviceInfo( device, &mask, &port );
415 return (*port & mask) == 0 ? DeviceOn : DeviceOff;
419 Fire an input event, telling the emulator for example
420 that the joystick has been released from the down position.
422 void setDeviceMode( enum InputDevice device, enum InputDeviceMode mode )
424 if( (getCoinLockout() == 0) && ((device == CoinSlot_1)||(device == CoinSlot_2)||(device == Switch_AddCredit)) ) {
425 // Coin slots are locked, ignore command and exit
426 return;
429 unsigned char mask;
430 unsigned char * port;
432 getDeviceInfo( device, &mask, &port );
434 if( mode == DeviceOn )
435 *port &= ~mask;
436 else if( mode == DeviceOff )
437 *port |= mask;
438 else if( mode == DeviceToggle )
439 *port ^= mask;
442 void setDipSwitches( unsigned value ) {
443 dip_switches_ = (unsigned char) value;
445 setDeviceMode( Switch_RackAdvance, value & DipRackAdvance_Auto ? DeviceOn : DeviceOff );
446 setDeviceMode( Switch_Test, value & DipMode_Test ? DeviceOn : DeviceOff );
447 setDeviceMode( Switch_CocktailMode, value & DipCabinet_Cocktail ? DeviceOn : DeviceOff );
450 unsigned getDipSwitches(void) {
451 unsigned result = dip_switches_;
453 if( getDeviceMode(Switch_RackAdvance) == DeviceOn ) result |= DipRackAdvance_Auto;
454 if( getDeviceMode(Switch_Test) == DeviceOn ) result |= DipMode_Test;
455 if( getDeviceMode(Switch_CocktailMode) == DeviceOn ) result |= DipCabinet_Cocktail;
457 return result;
460 #if defined (CPU_COLDFIRE)
461 extern void drawChar( unsigned char * buffer, int index, int ox, int oy, int color );
462 #else
463 static inline void drawChar( unsigned char * buffer, int index, int ox, int oy, int color )
465 int x,y;
467 /* Make the index point to the character offset into the character table */
468 unsigned char * chrmap = charmap_ + index*64;
469 buffer += ox + oy*224; /* Make the buffer point to the character position*/
470 color = (color & 0x3F)*4;
472 if( color == 0 )
474 for( y=7; y>=0; y-- )
476 rb->memset( buffer, 0, 8 );
477 buffer += ScreenWidth;
479 return;
482 if( output_devices_ & FlipScreen ) {
483 // Flip character
484 buffer += 7*ScreenWidth;
485 for( y=7; y>=0; y-- ) {
486 for( x=7; x>=0; x-- ) {
487 *buffer++ = (*chrmap++) + color;
489 buffer -= ScreenWidth + 8; // Go to the next line
492 else {
493 for( y=7; y>=0; y-- ) {
494 for( x=7; x>=0; x-- ) {
495 *buffer++ = (*chrmap++) + color;
497 buffer += ScreenWidth - 8; // Go to the next line
501 #endif
503 inline void drawSprite( unsigned char * buffer, int index )
505 struct PacmanSprite ps = sprites_[index];
506 int x,y;
507 char * s, * s2;
509 // Exit now if sprite not visible at all
510 if( (ps.color == 0) || (ps.x >= ScreenWidth) || (ps.y < 16) || (ps.y >= (ScreenHeight-32)) ) {
511 return;
514 // Clip the sprite coordinates to cut the parts that fall off the screen
515 int start_x = (ps.x < 0) ? 0 : ps.x;
516 int end_x = (ps.x < (ScreenWidth-16)) ? ps.x+15 : ScreenWidth-1;
518 // Prepare variables for drawing
519 int color = (ps.color & 0x3F)*4;
520 unsigned char * spritemap_base = spritemap_ + ((ps.n & 0x3F)*256);
522 buffer += ScreenWidth*ps.y;
524 dirty_[(start_x >> 3) + (ps.y >> 3)*28] = 1;
525 dirty_[(start_x >> 3) + 1 + (ps.y >> 3)*28] = 1;
526 dirty_[(end_x >> 3) + (ps.y >> 3)*28] = 1;
527 dirty_[(start_x >> 3) + ((ps.y >> 3)+1)*28] = 1;
528 dirty_[(start_x >> 3) + 1 + ((ps.y >> 3)+1)*28] = 1;
529 dirty_[(end_x >> 3) + ((ps.y >> 3)+1)*28] = 1;
530 dirty_[(start_x >> 3) + ((ps.y+15) >> 3)*28] = 1;
531 dirty_[(start_x >> 3) + 1 + ((ps.y+15) >> 3)*28] = 1;
532 dirty_[(end_x >> 3) + ((ps.y+15) >> 3)*28] = 1;
534 // Draw the 16x16 sprite
535 if( ps.mode == 0 ) { // Normal
536 s2 = spritemap_base + start_x-ps.x;
537 // Draw the 16x16 sprite
538 for( y=15; y>=0; y-- ) {
539 s = s2;
540 for( x=start_x; x<=end_x; x++, s++ ) {
541 if( *s ) {
542 buffer[x] = color + *s;
545 buffer += ScreenWidth;
546 s2 += 16;
548 } else if( ps.mode == 1 ) { // Flip Y
549 s2 = spritemap_base + start_x-ps.x + 240;
550 for( y=15; y>=0; y-- ) {
551 s = s2;
552 for( x=start_x; x<=end_x; x++, s++ ) {
553 if( *s ) {
554 buffer[x] = color + *s;
557 buffer += ScreenWidth;
558 s2 -= 16;
560 } else if( ps.mode == 2 ) { // Flip X
561 s2 = spritemap_base + 15 + ps.x-start_x;
562 for( y=15; y>=-0; y-- ) {
563 s = s2;
564 for( x=start_x; x<=end_x; x++, s-- ) {
565 if( *s ) {
566 buffer[x] = color + *s;
569 buffer += ScreenWidth;
570 s2 += 16;
572 } else { // Flip X and Y
573 s2 = spritemap_base + 255 + ps.x-start_x;
574 for( y=15; y>=0; y-- ) {
575 s = s2;
576 for( x=start_x; x<=end_x; x++, s-- ) {
577 if( *s ) {
578 buffer[x] = color + *s;
581 buffer += ScreenWidth;
582 s2 -= 16;
588 Draw the video into the specified buffer.
590 bool renderBackground( unsigned char * buffer )
592 unsigned char * video = video_mem_;
593 unsigned char * color = color_mem_;
594 unsigned char * dirty = dirty_;
595 int x,y;
596 bool changed=false;
598 // Draw the background first...
599 if( output_devices_ & FlipScreen ) {
600 for( y=ScreenHeight-CharHeight; y>=0; y-=CharHeight ) {
601 for( x=ScreenWidth-CharWidth; x>=0; x-=CharWidth ) {
602 if (*dirty) {
603 drawChar( buffer, *video++, x, y, *color++ );
604 *(dirty++)=0;
605 changed=true;
606 } else {
607 dirty++;
608 video++;
609 color++;
614 else {
615 for( y=0; y<ScreenHeight; y+=CharHeight ) {
616 for( x=0; x<ScreenWidth; x+=CharWidth ) {
617 if (*dirty) {
618 drawChar( buffer, *video++, x, y, *color++ );
619 *(dirty++)=0;
620 changed=true;
621 } else {
622 dirty++;
623 video++;
624 color++;
630 return changed;
633 void renderSprites( unsigned char * buffer )
635 int i;
637 // ...then add the sprites
638 for( i=7; i>=0; i-- ) {
639 drawSprite( buffer, i );
643 void playSound( int * buf, int len )
645 /* Clear the buffer */
646 memset( buf, 0, sizeof (int)*len);
648 /* Exit now if sound is disabled */
649 if( (output_devices_ & SoundEnabled) == 0 )
650 return;
652 /* Let the chip play the sound */
653 wsg3_play_sound( buf, len );
656 /* Enables/disables the speed hack. */
657 int setSpeedHack( int enabled )
659 int result = 0;
661 if( enabled ) {
662 if( (ram_[0x180B] == 0xBE) && (ram_[0x1FFD] == 0x00) ) {
663 // Patch the ROM to activate the speed hack
664 ram_[0x180B] = 0x01; // Activate speed hack
665 ram_[0x1FFD] = 0xBD; // Fix ROM checksum
667 result = 1;
670 else {
671 if( (ram_[0x180B] == 0x01) && (ram_[0x1FFD] == 0xBD) ) {
672 // Restore the patched ROM locations
673 ram_[0x180B] = 0xBE;
674 ram_[0x1FFD] = 0x00;
676 result = 1;
680 return result;