A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 683 lines 21 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Pacbox - a Pacman Emulator for Rockbox 11 * 12 * Based on PIE - Pacman Instructional Emulator 13 * 14 * Copyright (c) 1997-2003,2004 Alessandro Scotti 15 * http://www.ascotti.org/ 16 * 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. 21 * 22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 23 * KIND, either express or implied. 24 * 25 ****************************************************************************/ 26 27#include "pacbox.h" 28#include "arcade.h" 29#include "hardware.h" 30#include "wsg3.h" 31#include <string.h> 32#include "plugin.h" 33 34#ifndef HAVE_LCD_COLOR 35/* Convert RGB888 to 2-bit greyscale - logic taken from bmp2rb.c */ 36static fb_data rgb_to_gray(unsigned int r, unsigned int g, unsigned int b) 37{ 38 int brightness = ( 2*r + 4*g + b ); 39 if( r == 0 && g == 0 && b == 0 ) 40 return 3; 41 42 brightness = (brightness/450); 43 if( brightness > 2 ) return 0; 44 else return 2-brightness; 45} 46#endif 47 48static 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 81}; 82 83static 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 88}; 89 90enum { 91 Normal = 0x00, 92 FlipY = 0x01, 93 FlipX = 0x02, 94 FlipXY = 0x03 95}; 96 97// Namco 3-channel Wave Sound Generator wave data (8 waveforms with 32 4-bit entries each) 98static unsigned char default_sound_prom[] = 99{ 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, 132}; 133 134/* Putting this in IRAM actually slows down the iPods, but is good for 135 the Coldfire 136*/ 137#ifdef CPU_COLDFIRE 138fb_data palette[256] IBSS_ATTR; /* Color palette */ 139#else 140fb_data palette[256]; /* Color palette */ 141#endif 142 143 144void init_PacmanMachine(int dip) 145{ 146 int i; 147 148 /* Initialize the CPU and the RAM */ 149 z80_reset(); 150 rb->memset( &ram_[0x4000], 0xFF, 0x1000 ); 151 152 /* Initialize the WSG3 */ 153 wsg3_init(SoundClock); 154 155 /* Set the sound PROM to the default values for the original Namco chip */ 156 wsg3_set_sound_prom(default_sound_prom); 157 158 /* Initialize parameters */ 159 port1_ = 0xFF; 160 port2_ = 0xFF; 161 coin_counter_ = 0; 162 163 /* Reset the machine */ 164 reset_PacmanMachine(); 165 166 /* Set the DIP switches to a default configuration */ 167 setDipSwitches( dip ); 168 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 */ 172 173 for( i=0x000; i<0x400; i++ ) { 174 int x, y; 175 176 if( i < 0x040 ) { 177 x = 29 - (i & 0x1F); 178 y = 34 + (i >> 5); 179 } 180 else if( i >= 0x3C0 ) { 181 x = 29 - (i & 0x1F); 182 y = ((i-0x3C0) >> 5); 183 } 184 else { 185 x = 27 - ((i-0x40) >> 5); 186 y = 2 + ((i-0x40) & 0x1F); 187 } 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; 192 } 193} 194 195void reset_PacmanMachine(void) 196{ 197 int i; 198 199 z80_reset(); 200 output_devices_ = 0; 201 interrupt_vector_ = 0; 202 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_) ); 207 208 for( i=0; i<8; i++ ) { 209 sprites_[i].color = 0; 210 sprites_[i].x = ScreenWidth; 211 } 212} 213 214/* 215 Run the machine for one frame. 216*/ 217int run(void) 218{ 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) */ 222 223 unsigned extraCycles = z80_run( CpuCyclesPerFrame ); 224 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 */ 227 228 setCycles( extraCycles ); 229 230 /* If interrupts are enabled, force a CPU interrupt with the vector 231 set by the program */ 232 233 if( output_devices_ & InterruptEnabled ) { 234 z80_interrupt( interrupt_vector_ ); 235 } 236 237 return 0; 238} 239 240/** Returns the status of the coin lockout door. */ 241static unsigned char getCoinLockout(void) { 242 return output_devices_ & CoinLockout ? 1 : 0; 243} 244 245static void decodeCharByte( unsigned char b, unsigned char * charbuf, int charx, int chary, int charwidth ) 246{ 247 int i; 248 249 for( i=3; i>=0; i-- ) { 250 charbuf[charx+(chary+i)*charwidth] = (b & 1) | ((b >> 3) & 2); 251 b >>= 1; 252 } 253} 254 255static void decodeCharLine( unsigned char * src, unsigned char * charbuf, int charx, int chary, int charwidth ) 256{ 257 int x; 258 259 for( x=7; x>=0; x-- ) { 260 decodeCharByte( *src++, charbuf, x+charx, chary, charwidth ); 261 } 262} 263 264static void decodeCharSet( unsigned char * mem, unsigned char * charset ) 265{ 266 int i; 267 268 for( i=0; i<256; i++ ) { 269 unsigned char * src = mem + 16*i; 270 unsigned char * dst = charset + 64*i; 271 272 decodeCharLine( src, dst, 0, 4, 8 ); 273 decodeCharLine( src+8, dst, 0, 0, 8 ); 274 } 275} 276 277static void decodeSprites( unsigned char * mem, unsigned char * sprite_data ) 278{ 279 int i; 280 281 for( i=0; i<64; i++ ) { 282 unsigned char * src = mem + i*64; 283 unsigned char * dst = sprite_data + 256*i; 284 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 ); 293 } 294} 295 296/* 297 Decode one byte from the encoded color palette. 298 299 An encoded palette byte contains RGB information bit-packed as follows: 300 301 bit: 7 6 5 4 3 2 1 0 302 color: b b g g g r r r 303*/ 304static unsigned decodePaletteByte( unsigned char value ) 305{ 306 unsigned bit0, bit1, bit2; 307 unsigned red, green, blue; 308 309 bit0 = (value >> 0) & 0x01; 310 bit1 = (value >> 1) & 0x01; 311 bit2 = (value >> 2) & 0x01; 312 red = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; 313 314 bit0 = (value >> 3) & 0x01; 315 bit1 = (value >> 4) & 0x01; 316 bit2 = (value >> 5) & 0x01; 317 green = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; 318 319 bit0 = 0; 320 bit1 = (value >> 6) & 0x01; 321 bit2 = (value >> 7) & 0x01; 322 blue = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; 323 324 return (blue << 16 ) | (green << 8) | red; 325} 326 327void decodeROMs(void) 328{ 329 unsigned decoded_palette[0x20]; 330 unsigned c; 331 332 int i; 333 334 decodeCharSet( charset_rom_, charmap_ ); 335 decodeSprites( spriteset_rom_, spritemap_ ); 336 337 for( i=0x00; i<0x20; i++ ) { 338 decoded_palette[i] = decodePaletteByte( palette_data_[i] ); 339 } 340 for( i=0; i<256; i++ ) { 341 c = decoded_palette[ color_data_[i] & 0x0F ]; 342#ifdef HAVE_LCD_COLOR 343 palette[i] = FB_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 351 } 352 353#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) 354 rb->lcd_pal256_update_pal(palette); 355#endif 356} 357 358static void getDeviceInfo( enum InputDevice device, unsigned char * mask, unsigned char ** port ) 359{ 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 377 }; 378 379 *mask = MaskInfo[device]; 380 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; 405 } 406} 407 408static enum InputDeviceMode getDeviceMode( enum InputDevice device ) 409{ 410 unsigned char mask; 411 unsigned char * port; 412 413 getDeviceInfo( device, &mask, &port ); 414 415 return (*port & mask) == 0 ? DeviceOn : DeviceOff; 416} 417 418/* 419 Fire an input event, telling the emulator for example 420 that the joystick has been released from the down position. 421*/ 422void setDeviceMode( enum InputDevice device, enum InputDeviceMode mode ) 423{ 424 if( (getCoinLockout() == 0) && ((device == CoinSlot_1)||(device == CoinSlot_2)||(device == Switch_AddCredit)) ) { 425 // Coin slots are locked, ignore command and exit 426 return; 427 } 428 429 unsigned char mask; 430 unsigned char * port; 431 432 getDeviceInfo( device, &mask, &port ); 433 434 if( mode == DeviceOn ) 435 *port &= ~mask; 436 else if( mode == DeviceOff ) 437 *port |= mask; 438 else if( mode == DeviceToggle ) 439 *port ^= mask; 440} 441 442void setDipSwitches( unsigned value ) { 443 dip_switches_ = (unsigned char) value; 444 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 ); 448} 449 450unsigned getDipSwitches(void) { 451 unsigned result = dip_switches_; 452 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; 456 457 return result; 458} 459 460#if defined (CPU_COLDFIRE) 461extern void drawChar( unsigned char * buffer, int index, int ox, int oy, int color ); 462#else 463static inline void drawChar( unsigned char * buffer, int index, int ox, int oy, int color ) 464{ 465 int x,y; 466 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; 471 472 if( color == 0 ) 473 { 474 for( y=7; y>=0; y-- ) 475 { 476 rb->memset( buffer, 0, 8 ); 477 buffer += ScreenWidth; 478 }; 479 return; 480 }; 481 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; 488 } 489 buffer -= ScreenWidth + 8; // Go to the next line 490 } 491 } 492 else { 493 for( y=7; y>=0; y-- ) { 494 for( x=7; x>=0; x-- ) { 495 *buffer++ = (*chrmap++) + color; 496 } 497 buffer += ScreenWidth - 8; // Go to the next line 498 } 499 } 500} 501#endif 502 503static inline void drawSprite( unsigned char * buffer, int index ) 504{ 505 struct PacmanSprite ps = sprites_[index]; 506 int x,y; 507 char * s, * s2; 508 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; 512 } 513 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; 517 518 // Prepare variables for drawing 519 int color = (ps.color & 0x3F)*4; 520 unsigned char * spritemap_base = spritemap_ + ((ps.n & 0x3F)*256); 521 522 buffer += ScreenWidth*ps.y; 523 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; 533 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; 543 } 544 } 545 buffer += ScreenWidth; 546 s2 += 16; 547 } 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; 555 } 556 } 557 buffer += ScreenWidth; 558 s2 -= 16; 559 } 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; 567 } 568 } 569 buffer += ScreenWidth; 570 s2 += 16; 571 } 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; 579 } 580 } 581 buffer += ScreenWidth; 582 s2 -= 16; 583 } 584 } 585} 586 587/* 588 Draw the video into the specified buffer. 589*/ 590bool renderBackground( unsigned char * buffer ) 591{ 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; 597 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++; 610 } 611 } 612 } 613 } 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++; 625 } 626 } 627 } 628 } 629 630 return changed; 631} 632 633void renderSprites( unsigned char * buffer ) 634{ 635 int i; 636 637 // ...then add the sprites 638 for( i=7; i>=0; i-- ) { 639 drawSprite( buffer, i ); 640 } 641} 642 643void playSound( int16_t * buf, int len ) 644{ 645 /* Clear the buffer */ 646 memset( buf, 0, sizeof (int16_t)*len); 647 648 /* Exit now if sound is disabled */ 649 if( (output_devices_ & SoundEnabled) == 0 ) 650 return; 651 652 /* Let the chip play the sound */ 653 wsg3_play_sound( buf, len ); 654} 655 656/* Enables/disables the speed hack. */ 657/* rockbox: not used 658int setSpeedHack( int enabled ) 659{ 660 int result = 0; 661 662 if( enabled ) { 663 if( (ram_[0x180B] == 0xBE) && (ram_[0x1FFD] == 0x00) ) { 664 // Patch the ROM to activate the speed hack 665 ram_[0x180B] = 0x01; // Activate speed hack 666 ram_[0x1FFD] = 0xBD; // Fix ROM checksum 667 668 result = 1; 669 } 670 } 671 else { 672 if( (ram_[0x180B] == 0x01) && (ram_[0x1FFD] == 0xBD) ) { 673 // Restore the patched ROM locations 674 ram_[0x180B] = 0xBE; 675 ram_[0x1FFD] = 0x00; 676 677 result = 1; 678 } 679 } 680 681 return result; 682} 683*/