Index: pacbox.c =================================================================== --- pacbox.c (revision 15887) +++ pacbox.c (working copy) @@ -28,11 +28,17 @@ #include "pacbox_lcd.h" #include "lib/configfile.h" #include "lib/oldmenuapi.h" +#ifdef PACBOX_AUDIO_ENABLED +#include "lib/playback_control.h" +#endif PLUGIN_HEADER +#ifndef PACBOX_AUDIO_ENABLED PLUGIN_IRAM_DECLARE +#endif -struct plugin_api* rb; +/* cachealign data that is used by cop (or both cpu and cop) */ +struct plugin_api* rb PACBOX_ALIGN; struct pacman_settings { int difficulty; @@ -42,9 +48,32 @@ int showfps; }; -static struct pacman_settings settings; -static struct pacman_settings old_settings; +/* initial/default settings */ +static struct pacman_settings settings PACBOX_ALIGN = { + 0, /* difficulty=0 ==> Normal difficulty */ + 2, /* numlives=2 ==> 3 lives */ + 0, /* bonus=0 ==> bonus at 10000 points */ + 0, /* ghostnames=0 ==> Normal names */ + 0 /* showfps=0 ==> Do not show FPS */ +}; +static struct pacman_settings old_settings PACBOX_ALIGN; + +static struct { + long start_time, end_time; + long video_frames; +} game_info PACBOX_ALIGN; + +/* A buffer to render Pacman's 244x288 screen into */ +static unsigned char video_buffer[ScreenWidth*ScreenHeight] CACHEALIGN_AT_LEAST_ATTR(16); + +#ifdef PACBOX_ON_COP +/* data beyond this point is used by cpu only, but pad to + be extra safe that following data doesn't share cache + lines with cop */ +static bool _dummy_cachealign_end PACBOX_ALIGN; +#endif + #define SETTINGS_VERSION 1 #define SETTINGS_MIN_VERSION 1 #define SETTINGS_FILENAME "pacbox.cfg" @@ -106,12 +135,6 @@ return romsLoaded; } -/* A buffer to render Pacman's 244x288 screen into */ -static unsigned char video_buffer[ScreenWidth*ScreenHeight] __attribute__ ((aligned (16))); - -static long start_time; -static long video_frames = 0; - static int dipDifficulty[] = { DipDifficulty_Normal, DipDifficulty_Hard }; static int dipLives[] = { DipLives_1, DipLives_2, DipLives_3, DipLives_5 }; static int dipBonus[] = { DipBonus_10000, DipBonus_15000, DipBonus_20000, @@ -170,6 +193,9 @@ }; static const struct menu_item items[] = { +#ifdef PACBOX_AUDIO_ENABLED + { "Audio Playback", NULL }, +#endif { "Difficulty", NULL }, { "Pacmen Per Game", NULL }, { "Bonus Life", NULL }, @@ -179,6 +205,19 @@ { "Quit", NULL }, }; + enum menu_item_id { +#ifdef PACBOX_AUDIO_ENABLED + MRES_AUDIO, +#endif + MRES_DIFFICULTY, + MRES_PACMEN_PER_GAME, + MRES_BONUS_LIFE, + MRES_GHOST_NAMES, + MRES_DISPLAY_FPS, + MRES_RESTART, + MRES_QUIT + }; + m = menu_init(rb, items, sizeof(items) / sizeof(*items), NULL, NULL, NULL, NULL); @@ -189,7 +228,12 @@ switch(result) { - case 0: +#ifdef PACBOX_AUDIO_ENABLED + case MRES_AUDIO: + playback_control(rb); + break; +#endif + case MRES_DIFFICULTY: new_setting=settings.difficulty; rb->set_option("Difficulty", &new_setting, INT, difficulty_options , 2, NULL); @@ -198,7 +242,7 @@ need_restart=true; } break; - case 1: + case MRES_PACMEN_PER_GAME: new_setting=settings.numlives; rb->set_option("Pacmen Per Game", &new_setting, INT, numlives_options , 4, NULL); @@ -207,7 +251,7 @@ need_restart=true; } break; - case 2: + case MRES_BONUS_LIFE: new_setting=settings.bonus; rb->set_option("Bonus Life", &new_setting, INT, bonus_options , 4, NULL); @@ -216,7 +260,7 @@ need_restart=true; } break; - case 3: + case MRES_GHOST_NAMES: new_setting=settings.ghostnames; rb->set_option("Ghost Names", &new_setting, INT, ghostname_options , 2, NULL); @@ -225,11 +269,11 @@ need_restart=true; } break; - case 4: /* Show FPS */ + case MRES_DISPLAY_FPS: rb->set_option("Display FPS",&settings.showfps,INT, noyes, 2, NULL); break; - case 5: /* Restart */ + case MRES_RESTART: need_restart=true; menu_quit=1; break; @@ -250,23 +294,27 @@ restart game usb connected */ - return (result==6); + return (result==MRES_QUIT); } /* - Runs the game engine for one frame. + Runs the game engine for one frame at a time + and keeps the game sync'd to the desired framerate + Loops until the Menu key is pressed (game is Quit via menu) */ -static int gameProc( void ) +static void gameProc( void ) { - int x; int fps; char str[80]; int status; - long end_time; int frame_counter = 0; int yield_counter = 0; - + + long start_time = game_info.start_time; + long end_time; + long video_frames = game_info.video_frames; + while (1) { /* Run the machine for one frame (1/60th second) */ @@ -287,15 +335,9 @@ || status == PACMAN_RC_MENU #endif ) { - end_time = *rb->current_tick; - x = pacbox_menu(); - rb->lcd_clear_display(); -#ifdef HAVE_REMOTE_LCD - rb->lcd_remote_clear_display(); - rb->lcd_remote_update(); -#endif - if (x == 1) { return 1; } - start_time += *rb->current_tick-end_time; + game_info.end_time = *rb->current_tick; + game_info.video_frames = video_frames; + return; } #ifdef PACMAN_HAS_REMOTE @@ -344,28 +386,34 @@ if (settings.showfps) { fps = (video_frames*HZ*100) / (*rb->current_tick-start_time); - rb->snprintf(str,sizeof(str),"%d.%02d / %d fps ", + rb->snprintf(str,sizeof(str)-1,"%d.%02d / %d fps ", fps/100,fps%100,FPS); + str[sizeof(str)-1] = '\0'; rb->lcd_putsxy(0,0,str); } rb->lcd_update(); - /* Keep the framerate at Pacman's 60fps */ + /* Keep the framerate at Pacman's 60fps */ end_time = start_time + (video_frames*HZ)/FPS; while (TIME_BEFORE(*rb->current_tick,end_time)) { rb->sleep(1); } } } - return 0; + + return; } enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { (void)parameter; + + CACHE_FUNCTION_WRAPPERS(api) +#ifndef PACBOX_AUDIO_ENABLED PLUGIN_IRAM_INIT(api) +#endif rb = api; #ifdef HAVE_ADJUSTABLE_CPU_FREQ @@ -377,13 +425,6 @@ rb->lcd_clear_display(); rb->lcd_update(); - /* Set the default settings */ - settings.difficulty = 0; /* Normal */ - settings.numlives = 2; /* 3 lives */ - settings.bonus = 0; /* 10000 points */ - settings.ghostnames = 0; /* Normal names */ - settings.showfps = 0; /* Do not show FPS */ - configfile_init(rb); if (configfile_load(SETTINGS_FILENAME, config, @@ -406,11 +447,32 @@ init_PacmanMachine(settings_to_dip(settings)); /* Load the romset */ - if (loadROMS()) { - start_time = *rb->current_tick-1; - - gameProc(); - + if (loadROMS()) + { + game_info.start_time = *rb->current_tick-1; + bool quit = false; + + while(!quit) { +#ifdef PACBOX_ON_COP + flush_icache(); + rb->switch_core(1); +#endif + gameProc(); +#ifdef PACBOX_ON_COP + flush_icache(); + rb->switch_core(0); +#endif + /* gameProc returns when menu key combo is pressed */ + rb->yield(); + quit = pacbox_menu(); + rb->lcd_clear_display(); +#ifdef HAVE_REMOTE_LCD + rb->lcd_remote_clear_display(); + rb->lcd_remote_update(); +#endif + game_info.start_time += *rb->current_tick-1 - game_info.end_time; + } + /* Save the user settings if they have changed */ if (rb->memcmp(&settings,&old_settings,sizeof(settings))!=0) { rb->splash(0, "Saving settings..."); Index: arcade.c =================================================================== --- arcade.c (revision 15887) +++ arcade.c (working copy) @@ -26,6 +26,7 @@ #include "hardware.h" #include #include "plugin.h" +#include "pacbox.h" extern struct plugin_api* rb; @@ -43,7 +44,7 @@ } #endif -unsigned char color_data_[256] = { +unsigned char color_data_[256] PACBOX_ALIGN = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0x05, @@ -78,6 +79,15 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +/* Putting this in IRAM actually slows down the iPods, but is good for + the Coldfire +*/ +#ifdef CPU_COLDFIRE +fb_data palette[256] PACBOX_ALIGN IBSS_ATTR; /* Color palette */ +#else +fb_data palette[256]; /* Color palette */ +#endif + unsigned char palette_data_[0x20] = { 0x00, 0x07, 0x66, 0xef, 0x00, 0xf8, 0xea, 0x6f, 0x00, 0x3f, 0x00, 0xc9, 0x38, 0xaa, 0xaf, 0xf6, @@ -92,16 +102,6 @@ FlipXY = 0x03 }; -/* Putting this in IRAM actually slows down the iPods, but is good for - the Coldfire -*/ -#ifdef CPU_COLDFIRE -fb_data palette[256] IBSS_ATTR; /* Color palette */ -#else -fb_data palette[256]; /* Color palette */ -#endif - - void init_PacmanMachine(int dip) { int i; @@ -617,3 +617,7 @@ return result; } +#ifdef PACBOX_ON_COP +static bool _dummy_cachealign_end PACBOX_ALIGN; +static bool _dummy_cachealign_end_bss PACBOX_IBSS PACBOX_ALIGN; +#endif Index: pacbox.h =================================================================== --- pacbox.h (revision 15887) +++ pacbox.h (working copy) @@ -167,4 +167,29 @@ #define FPS 20 #endif +/* Can we run the emulator on a separate thread on cop? + The only advantage of doing so is to enable audio codecs to run on the + main cpu. Note that doing so requires turning off the iram usage + of pacbox, since codecs use iram, so may not be appropriate to turn + on for all dual core targets */ +#if defined(IPOD_VIDEO) +#define PACBOX_ON_COP #endif + +#if defined (PACBOX_ON_COP) || defined (TOSHIBA_GIGABEAT_F) +#define PACBOX_AUDIO_ENABLED +#endif + +#ifdef PACBOX_ON_COP +#define PACBOX_IBSS __attribute__ ((section(".bss"))) +#define PACBOX_IDATA +#define PACBOX_ICODE .text +#define PACBOX_ALIGN CACHEALIGN_ATTR +#else +#define PACBOX_IBSS IBSS_ATTR +#define PACBOX_IDATA IDATA_ATTR +#define PACBOX_ICODE .icode +#define PACBOX_ALIGN +#endif + +#endif Index: z80.c =================================================================== --- z80.c (revision 15887) +++ z80.c (working copy) @@ -26,9 +26,10 @@ #include "hardware.h" #include "z80.h" #include "z80_internal.h" +#include "pacbox.h" // Table with parity, sign and zero flags precomputed for each byte value -unsigned char PSZ_[256] IDATA_ATTR = { +unsigned char PSZ_[256] PACBOX_ALIGN PACBOX_IDATA = { Zero|Parity, 0, 0, Parity, 0, Parity, Parity, 0, 0, Parity, Parity, 0, Parity, 0, 0, Parity, 0, Parity, Parity, 0, Parity, 0, 0, Parity, Parity, 0, 0, Parity, 0, Parity, Parity, 0, 0, Parity, Parity, 0, Parity, 0, 0, Parity, Parity, 0, 0, Parity, 0, Parity, Parity, 0, @@ -76,33 +77,39 @@ /** */ unsigned do_opcode_xycb( unsigned xy ); -unsigned iflags_ IBSS_ATTR; // Interrupt mode (bits 0 and 1) and flags -unsigned cycles_ IBSS_ATTR; // Number of CPU cycles elapsed so far +unsigned iflags_ PACBOX_ALIGN PACBOX_IBSS ; // Interrupt mode (bits 0 and 1) and flags +unsigned cycles_ PACBOX_IBSS ; // Number of CPU cycles elapsed so far // Registers -unsigned char B IBSS_ATTR; //@- B register -unsigned char C IBSS_ATTR; //@- C register -unsigned char D IBSS_ATTR; //@- D register -unsigned char E IBSS_ATTR; //@- E register -unsigned char H IBSS_ATTR; //@- H register -unsigned char L IBSS_ATTR; //@- L register -unsigned char A IBSS_ATTR; //@- A register (accumulator) -unsigned char F IBSS_ATTR; //@- Flags register -unsigned char B1 IBSS_ATTR; //@- Alternate B register (B') -unsigned char C1 IBSS_ATTR; //@- Alternate C register (C') -unsigned char D1 IBSS_ATTR; //@- Alternate D register (D') -unsigned char E1 IBSS_ATTR; //@- Alternate E register (E') -unsigned char H1 IBSS_ATTR; //@- Alternate H register (H') -unsigned char L1 IBSS_ATTR; //@- Alternate L register (L') -unsigned char A1 IBSS_ATTR; //@- Alternate A register (A') -unsigned char F1 IBSS_ATTR; //@- Alternate flags register (F') -unsigned IX IBSS_ATTR; //@- Index register X -unsigned IY IBSS_ATTR; //@- Index register Y -unsigned PC IBSS_ATTR; //@- Program counter -unsigned SP IBSS_ATTR; //@- Stack pointer -unsigned char I IBSS_ATTR; //@- Interrupt register -unsigned char R IBSS_ATTR; //@- Refresh register +unsigned char B PACBOX_IBSS ; //@- B register +unsigned char C PACBOX_IBSS ; //@- C register +unsigned char D PACBOX_IBSS ; //@- D register +unsigned char E PACBOX_IBSS ; //@- E register +unsigned char H PACBOX_IBSS ; //@- H register +unsigned char L PACBOX_IBSS ; //@- L register +unsigned char A PACBOX_IBSS ; //@- A register (accumulator) +unsigned char F PACBOX_IBSS ; //@- Flags register +unsigned char B1 PACBOX_IBSS ; //@- Alternate B register (B') +unsigned char C1 PACBOX_IBSS ; //@- Alternate C register (C') +unsigned char D1 PACBOX_IBSS ; //@- Alternate D register (D') +unsigned char E1 PACBOX_IBSS ; //@- Alternate E register (E') +unsigned char H1 PACBOX_IBSS ; //@- Alternate H register (H') +unsigned char L1 PACBOX_IBSS ; //@- Alternate L register (L') +unsigned char A1 PACBOX_IBSS ; //@- Alternate A register (A') +unsigned char F1 PACBOX_IBSS ; //@- Alternate flags register (F') +unsigned IX PACBOX_IBSS ; //@- Index register X +unsigned IY PACBOX_IBSS ; //@- Index register Y +unsigned PC PACBOX_IBSS ; //@- Program counter +unsigned SP PACBOX_IBSS ; //@- Stack pointer +unsigned char I PACBOX_IBSS ; //@- Interrupt register +unsigned char R PACBOX_IBSS ; //@- Refresh register +#ifdef PACBOX_ON_COP +// We want to ensure anything is aligned to cache boundaries, +// to prevent the case that a single cache line could be used by +// both cop+cpu. +bool _dummy_align PACBOX_IBSS PACBOX_ALIGN; +#endif /** Returns the 16 bit register BC. */ @@ -605,7 +612,7 @@ return buf - buffer; } -OpcodeInfo OpInfoCB_[256] = { +OpcodeInfo OpInfoCB_[256] PACBOX_ALIGN = { { &opcode_cb_00, 8 }, // RLC B { &opcode_cb_01, 8 }, // RLC C { &opcode_cb_02, 8 }, // RLC D @@ -2144,7 +2151,7 @@ A |= (unsigned char) (1 << 7); } -OpcodeInfo OpInfoDD_[256] = { +OpcodeInfo OpInfoDD_[256] PACBOX_ALIGN = { { 0, 0 }, // 0x00 { 0, 0 }, // 0x01 { 0, 0 }, // 0x02 @@ -2870,7 +2877,7 @@ SP = IX; } -OpcodeInfo OpInfoED_[256] = { +OpcodeInfo OpInfoED_[256] PACBOX_ALIGN = { { 0, 0 }, // 0x00 { 0, 0 }, // 0x01 { 0, 0 }, // 0x02 @@ -3669,7 +3676,7 @@ } } -OpcodeInfo OpInfoFD_[256] = { +OpcodeInfo OpInfoFD_[256] PACBOX_ALIGN = { { 0, 0 }, // 0x00 { 0, 0 }, // 0x01 { 0, 0 }, // 0x02 @@ -4395,7 +4402,7 @@ SP = IY; } -OpcodeInfoXY OpInfoXYCB_[256] = { +OpcodeInfoXY OpInfoXYCB_[256] PACBOX_ALIGN = { { &opcode_xycb_00, 20 }, // LD B, RLC (IX + d) { &opcode_xycb_01, 20 }, // LD C, RLC (IX + d) { &opcode_xycb_02, 20 }, // LD D, RLC (IX + d) @@ -6115,7 +6122,7 @@ writeByte( xy, A ); } -OpcodeInfo OpInfo_[256] = { +OpcodeInfo OpInfo_[256] PACBOX_ALIGN = { { &opcode_00, 4 }, // NOP { &opcode_01, 10 }, // LD BC,nn { &opcode_02, 7 }, // LD (BC),A @@ -8055,4 +8062,3 @@ } } } - Index: pacbox_arm.S =================================================================== --- pacbox_arm.S (revision 15887) +++ pacbox_arm.S (working copy) @@ -19,7 +19,7 @@ #include "pacbox.h" - .section .icode,"ax",%progbits + .section PACBOX_ICODE,"ax",%progbits .global blit_display /* void blit_display(fb_data* lcd_framebuffer, unsigned char* vbuf) Index: hardware.c =================================================================== --- hardware.c (revision 15887) +++ hardware.c (working copy) @@ -24,25 +24,31 @@ #include "plugin.h" #include "hardware.h" +#include "pacbox.h" extern struct plugin_api* rb; /* The main data for Pacman */ -unsigned char ram_[20*1024] IBSS_ATTR; // ROM (16K) and RAM (4K) -unsigned char charset_rom_[4*1024] IBSS_ATTR; // Character set ROM (4K) -unsigned char spriteset_rom_[4*1024] IBSS_ATTR; // Sprite set ROM (4K) -unsigned char dirty_[1024] IBSS_ATTR; -unsigned char video_mem_[1024] IBSS_ATTR; // Video memory (1K) -unsigned char color_mem_[1024] IBSS_ATTR; // Color memory (1K) -unsigned char charmap_[256*8*8] IBSS_ATTR; /* Character data for 256 8x8 characters */ +#ifdef PACBOX_ON_COP +static bool _dummy_cachealign_start CACHEALIGN_ATTR; +static bool _dummy_cachealign_start_bss PACBOX_IBSS CACHEALIGN_ATTR; +#endif + +unsigned char ram_[20*1024] PACBOX_IBSS ; // ROM (16K) and RAM (4K) +unsigned char charset_rom_[4*1024] PACBOX_IBSS ; // Character set ROM (4K) +unsigned char spriteset_rom_[4*1024] PACBOX_IBSS ; // Sprite set ROM (4K) +unsigned char dirty_[1024] PACBOX_IBSS ; +unsigned char video_mem_[1024] PACBOX_IBSS ; // Video memory (1K) +unsigned char color_mem_[1024] PACBOX_IBSS ; // Color memory (1K) +unsigned char charmap_[256*8*8] PACBOX_IBSS ; /* Character data for 256 8x8 characters */ unsigned char spritemap_[64*16*16]; /* Sprite data for 64 16x16 sprites */ -unsigned char output_devices_ IBSS_ATTR; /* Output flip-flops set by the game program */ -unsigned char interrupt_vector_ IBSS_ATTR; -unsigned coin_counter_ IBSS_ATTR; -unsigned char port1_ IBSS_ATTR; -unsigned char port2_ IBSS_ATTR; -unsigned char dip_switches_ IBSS_ATTR; +unsigned char output_devices_ PACBOX_IBSS ; /* Output flip-flops set by the game program */ +unsigned char interrupt_vector_ PACBOX_IBSS ; +unsigned coin_counter_ PACBOX_IBSS ; +unsigned char port1_ PACBOX_IBSS ; +unsigned char port2_ PACBOX_IBSS ; +unsigned char dip_switches_ PACBOX_IBSS ; /* Internal tables and structures for faster access to data */ struct PacmanSprite sprites_[8]; /* Sprites */ @@ -195,3 +201,8 @@ output_devices_ &= ~bit; } } + +#ifdef PACBOX_ON_COP +static bool _dummy_cachealign_end CACHEALIGN_ATTR; +static bool _dummy_cachealign_end_bss PACBOX_IBSS CACHEALIGN_ATTR; +#endif