From cf218e33eca3abcc1067b9e78f1c82510bfe7c69 Mon Sep 17 00:00:00 2001 From: Linus Nielsen Feltzing Date: Tue, 10 Jan 2006 21:55:56 +0000 Subject: Patch #1401999 by Karl Kurbjun - Rockboy color, sound support, and speedups git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8324 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/rockboy/emu.c | 2 +- apps/plugins/rockboy/lcd-gb.h | 2 +- apps/plugins/rockboy/lcd.c | 34 +++++++++---- apps/plugins/rockboy/loader.c | 4 +- apps/plugins/rockboy/menu.c | 74 ++++++++++++++++++++++++++- apps/plugins/rockboy/pcm.h | 2 +- apps/plugins/rockboy/rbsound.c | 102 ++++++++++++++----------------------- apps/plugins/rockboy/rockboy.c | 2 + apps/plugins/rockboy/rockmacros.h | 3 ++ apps/plugins/rockboy/sound.c | 11 ++-- apps/plugins/rockboy/sys_rockbox.c | 59 +++++++++++++++------ docs/CREDITS | 1 + 12 files changed, 195 insertions(+), 101 deletions(-) diff --git a/apps/plugins/rockboy/emu.c b/apps/plugins/rockboy/emu.c index 57385f8e5f..cf37d9b2b8 100644 --- a/apps/plugins/rockboy/emu.c +++ b/apps/plugins/rockboy/emu.c @@ -73,7 +73,7 @@ void emu_run(void) #if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(true); #endif - while(shut==0) + while(!shut) { cpu_emulate(2280); while (R_LY > 0 && R_LY < 144) diff --git a/apps/plugins/rockboy/lcd-gb.h b/apps/plugins/rockboy/lcd-gb.h index 14d7ee49e0..9f1b890c17 100644 --- a/apps/plugins/rockboy/lcd-gb.h +++ b/apps/plugins/rockboy/lcd-gb.h @@ -21,7 +21,7 @@ struct scan #elif LCD_DEPTH == 2 byte buf[4][256]; #elif LCD_DEPTH > 4 - byte buf[1][256]; + byte buf[256]; #endif byte pal1[128]; un16 pal2[64]; diff --git a/apps/plugins/rockboy/lcd.c b/apps/plugins/rockboy/lcd.c index 883c4952fc..4cd4ddc04c 100644 --- a/apps/plugins/rockboy/lcd.c +++ b/apps/plugins/rockboy/lcd.c @@ -19,7 +19,13 @@ struct scan scan IBSS_ATTR; #define BG (scan.bg) #define WND (scan.wnd) + +#if LCD_DEPTH ==16 +#define BUF (scan.buf) +#else #define BUF (scan.buf[scanline_ind]) +#endif + #define PRI (scan.pri) #define PAL1 (scan.pal1) @@ -55,7 +61,10 @@ static int rgb332; static int sprsort = 1; static int sprdebug; -static int scanline_ind=0,insync=0; +static int insync=0; +#if LCD_DEPTH < 16 +static int scanline_ind=0; +#endif #define DEF_PAL { 0x98d0e0, 0x68a0b0, 0x60707C, 0x2C3C3C } @@ -930,7 +939,7 @@ void lcd_refreshline(void) -/* +#if HAVE_LCD_COLOR static void updatepalette(int i) { int c, r, g, b, y, u, v, rr, gg; @@ -964,7 +973,7 @@ static void updatepalette(int i) | (u<> fb.cc[0].r) << fb.cc[0].l; g = (g >> fb.cc[1].r) << fb.cc[1].l; @@ -996,13 +1005,16 @@ static void updatepalette(int i) PAL4[i] = c; break; } -}*/ +} +#endif void pal_write(int i, byte b) { if (lcd.pal[i] == b) return; lcd.pal[i] = b; -// updatepalette(i>>1); +#if LCD_DEPTH ==16 + updatepalette(i>>1); +#endif } void pal_write_dmg(int i, int mapnum, byte d) @@ -1043,7 +1055,9 @@ void vram_dirty(void) void pal_dirty(void) { -// int i; +#if LCD_DEPTH ==16 + int i; +#endif if (!hw.cgb) { @@ -1052,8 +1066,10 @@ void pal_dirty(void) pal_write_dmg(64, 2, R_OBP0); pal_write_dmg(72, 3, R_OBP1); } -// for (i = 0; i < 64; i++) -// updatepalette(i); +#if LCD_DEPTH ==16 + for (i = 0; i < 64; i++) + updatepalette(i); +#endif } void lcd_reset(void) diff --git a/apps/plugins/rockboy/loader.c b/apps/plugins/rockboy/loader.c index 53839d6150..0a8eaba13f 100644 --- a/apps/plugins/rockboy/loader.c +++ b/apps/plugins/rockboy/loader.c @@ -86,7 +86,7 @@ static char *savedir = "/.rockbox/rockboy"; static int saveslot; static int forcebatt, nobatt; -static int forcedmg; +static int forcedmg, gbamode; static int memfill = -1, memrand = -1; @@ -181,7 +181,7 @@ int rom_load(void) c = header[0x0143]; hw.cgb = ((c == 0x80) || (c == 0xc0)) && !forcedmg; - hw.gba = 0; //(hw.cgb && gbamode); + hw.gba = (hw.cgb && gbamode); close(fd); diff --git a/apps/plugins/rockboy/menu.c b/apps/plugins/rockboy/menu.c index 50f86c3408..140e7a28b1 100644 --- a/apps/plugins/rockboy/menu.c +++ b/apps/plugins/rockboy/menu.c @@ -67,11 +67,33 @@ static const char *slot_menu[] = { #define OPT_MENU_TITLE "Options" typedef enum { + OM_ITEM_FS, + OM_ITEM_SOUND, OM_ITEM_BACK, OM_MENU_LAST } OptMenuItem; static const char *opt_menu[] = { + "Frameskip", + "Sound ON/OFF", + "Previous Menu..." +}; + +#define FS_MENU_TITLE "Frameskip" +typedef enum { + FS_ITEM_FS0, + FS_ITEM_FS1, + FS_ITEM_FS2, + FS_ITEM_FS3, + FS_ITEM_BACK, + FS_MENU_LAST +} FSMenuItem; + +static const char *fs_menu[] = { + "Skip 0 Frames", + "Skip 1 Frames", + "Skip 2 Frames", + "Skip 3 Frames", "Previous Menu..." }; @@ -90,6 +112,8 @@ int do_user_menu(void) { int mi, ret, num_items; bool done = false; + pcm_init(); + /* set defaults */ ret = 0; /* return value */ mi = 0; /* initial menu selection */ @@ -119,7 +143,7 @@ int do_user_menu(void) { break; } } - + rb->lcd_clear_display(); /* return somethin' */ return ret; } @@ -314,6 +338,42 @@ static void do_slot_menu(bool is_load) { } } +static void do_fs_menu(void) { + int mi, ret, num_items; + bool done = false; + + /* set defaults */ + ret = 0; /* return value */ + mi = 0; /* initial menu selection */ + num_items = sizeof(fs_menu) / sizeof(char*); + + /* loop until we should exit menu */ + while (!done) { + /* get item selection */ + mi = do_menu(FS_MENU_TITLE, (char**) fs_menu, num_items, mi); + + /* handle selected menu item */ + switch (mi) { + case MENU_CANCEL: + case FS_ITEM_BACK: + done = true; + break; + case FS_ITEM_FS0: + frameskip=0; + break; + case FS_ITEM_FS1: + frameskip=1; + break; + case FS_ITEM_FS2: + frameskip=2; + break; + case FS_ITEM_FS3: + frameskip=3; + break; + } + } +} + static void do_opt_menu(void) { int mi, num_items; bool done = false; @@ -324,8 +384,18 @@ static void do_opt_menu(void) { while (!done) { mi = do_menu(OPT_MENU_TITLE, (char**) opt_menu, num_items, mi); - if (mi == MENU_CANCEL || mi == OM_ITEM_BACK) + switch (mi) { + case OM_ITEM_FS: + do_fs_menu(); + break; + case OM_ITEM_SOUND: + sound=!sound; + break; + case MENU_CANCEL: + case OM_ITEM_BACK: done = true; + break; + } } } diff --git a/apps/plugins/rockboy/pcm.h b/apps/plugins/rockboy/pcm.h index 742f0e5a95..3719933520 100644 --- a/apps/plugins/rockboy/pcm.h +++ b/apps/plugins/rockboy/pcm.h @@ -9,7 +9,7 @@ struct pcm { int hz, len; int stereo; - short *buf; + byte *buf; int pos; }; diff --git a/apps/plugins/rockboy/rbsound.c b/apps/plugins/rockboy/rbsound.c index 139c33d037..b68a053f77 100644 --- a/apps/plugins/rockboy/rbsound.c +++ b/apps/plugins/rockboy/rbsound.c @@ -5,117 +5,89 @@ struct pcm pcm; -#define BUF_SIZE (8192) -#define DMA_PORTION (1024) - -static short buf1_unal[(BUF_SIZE / sizeof(short)) + 2]; // to make sure 4 byte aligned +bool sound = 1; +#define N_BUFS 4 +#define BUF_SIZE 1024 rcvar_t pcm_exports[] = { RCV_END }; -/*#if CONFIG_CODEC == SWCODEC && !defined(SIMULATOR) - * disabled cause it crashes with current audio implementation.. no sound. - */ -#if 0 -static short* buf1; +#if CONFIG_CODEC == SWCODEC && !defined(SIMULATOR) -static short front_buf[512]; +static int curbuf,gmcurbuf; -static short* last_back_pos; +static byte *buf=0; +static short *gmbuf; static bool newly_started; -static int turns; void pcm_init(void) { - buf1 = (signed short*)((((unsigned int)buf1_unal) >> 2) << 2); /* here i just make sure that buffer is aligned to 4 bytes*/ + if(!sound) return; + newly_started = true; - last_back_pos = buf1; - turns = 0; pcm.hz = 11025; pcm.stereo = 1; - pcm.buf = front_buf; - pcm.len = (sizeof(front_buf)) / sizeof(short); /* length in shorts, not bytes */ - pcm.pos = 0; + pcm.len = BUF_SIZE; + if(!buf){ + buf = my_malloc(pcm.len * N_BUFS); + gmbuf = my_malloc(pcm.len * N_BUFS*sizeof (short)); + pcm.buf = buf; + pcm.pos = 0; + curbuf = gmcurbuf= 0; + } rb->pcm_play_stop(); - rb->pcm_set_frequency(11025); - rb->pcm_set_volume(200); + rb->pcm_set_frequency(11025); // 44100 22050 11025 } void pcm_close(void) { memset(&pcm, 0, sizeof pcm); newly_started = true; - last_back_pos = buf1; rb->pcm_play_stop(); + rb->pcm_set_frequency(44100); } void get_more(unsigned char** start, long* size) { - int length; - unsigned int sar = (unsigned int)SAR0; - length = ((unsigned int)buf1) + BUF_SIZE - sar; - - if(turns > 0) - { - newly_started = true; - last_back_pos = buf1; - turns = 0; - return; - } /* sound will stop if no one feeds data*/ - - if(length <= 0) - { - *start = (unsigned char*)buf1; - *size = DMA_PORTION; - turns++; - } - else - { - *start = (unsigned char*)sar; - if(length > DMA_PORTION) - *size = DMA_PORTION; - else - *size = length; - } - + *start = (unsigned char*)(&gmbuf[pcm.len*curbuf]); + *size = BUF_SIZE*sizeof(short); } int pcm_submit(void) { - while( (turns < 0) && ((((unsigned int)last_back_pos) + pcm.pos * sizeof(short)) > ((unsigned int)SAR0)) && !newly_started) rb->yield(); /* wait until data is passed through DAC or until exit*/ - int shorts_left = ((((unsigned int)buf1) + BUF_SIZE) - ((unsigned int)last_back_pos)) / sizeof(short); - if( shorts_left >= pcm.pos ) - { - memcpy(last_back_pos,pcm.buf,pcm.pos * sizeof(short)); - last_back_pos = &last_back_pos[pcm.pos]; + register int i; + + if (!sound) { + pcm.pos = 0; + return 0; } - else - { - int last_pos = shorts_left; - memcpy(last_back_pos,pcm.buf,shorts_left * sizeof(short)); - last_back_pos = buf1; - shorts_left = pcm.pos - shorts_left; - memcpy(last_back_pos,&pcm.buf[last_pos],shorts_left * sizeof(short)); - last_back_pos = &buf1[shorts_left]; - turns--; + + if (pcm.pos >= pcm.len) { + curbuf = (curbuf + 1) % N_BUFS; + pcm.buf = buf + pcm.len * curbuf; + pcm.pos = 0; + + // gotta convert the 8 bit buffer to 16 + for(i=0; ipcm_play_data((unsigned char*)buf1,pcm.pos * sizeof(short),&get_more); + rb->pcm_play_data(&get_more); newly_started = false; } - pcm.pos = 0; return 1; } #else +static byte buf1_unal[(BUF_SIZE / sizeof(short)) + 2]; // to make sure 4 byte aligned void pcm_init(void) { pcm.hz = 11025; diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c index 56773879fa..fc004e752d 100644 --- a/apps/plugins/rockboy/rockboy.c +++ b/apps/plugins/rockboy/rockboy.c @@ -102,6 +102,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) otherwise you will get lovely "I04: IllInstr" errors... :-) */ rb = api; + rb->lcd_setfont(0); + if (!parameter) { rb->splash(HZ*3, true, "Play gameboy ROM file! (.gb/.gbc)"); return PLUGIN_OK; diff --git a/apps/plugins/rockboy/rockmacros.h b/apps/plugins/rockboy/rockmacros.h index 9e902e7dca..c68223d478 100644 --- a/apps/plugins/rockboy/rockmacros.h +++ b/apps/plugins/rockboy/rockmacros.h @@ -92,3 +92,6 @@ void savestate(int fd); /* Using #define isn't enough with GCC 4.0.1 */ void* memcpy(void* dst, const void* src, size_t size); + +extern int frameskip; +extern bool sound; diff --git a/apps/plugins/rockboy/sound.c b/apps/plugins/rockboy/sound.c index accfda2540..58cbe542f9 100644 --- a/apps/plugins/rockboy/sound.c +++ b/apps/plugins/rockboy/sound.c @@ -158,9 +158,10 @@ void sound_reset(void) sound_off(); } - void sound_mix(void) { + + if (!sound) return; int s, l, r, f, n; if (!RATE || cpu.snd < RATE) return; @@ -275,10 +276,10 @@ void sound_mix(void) pcm_submit(); if (pcm.stereo) { - pcm.buf[pcm.pos++] = (signed short)(l * 256); - pcm.buf[pcm.pos++] = (signed short)(r * 256); + pcm.buf[pcm.pos++] = l+128; + pcm.buf[pcm.pos++] = r+128; } - else pcm.buf[pcm.pos++] = (signed short)((r+l) * 128); + else pcm.buf[pcm.pos++] = ((l+r)>>1)+128; } } R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3); @@ -288,6 +289,7 @@ void sound_mix(void) byte sound_read(byte r) { + if(!sound) return 0; sound_mix(); /* printf("read %02X: %02X\n", r, REG(r)); */ return REG(r); @@ -344,6 +346,7 @@ void s4_init(void) void sound_write(byte r, byte b) { + if(!sound) return; #if 0 static void *timer; if (!timer) timer = sys_timer(); diff --git a/apps/plugins/rockboy/sys_rockbox.c b/apps/plugins/rockboy/sys_rockbox.c index b6408d53dc..b8bb65e6fc 100644 --- a/apps/plugins/rockboy/sys_rockbox.c +++ b/apps/plugins/rockboy/sys_rockbox.c @@ -25,6 +25,8 @@ #include "hw.h" #include "config.h" +int frameskip; + rcvar_t joy_exports[] = { RCV_END @@ -52,14 +54,20 @@ void joy_close(void) { } -#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ - (CONFIG_KEYPAD == IRIVER_H300_PAD) +#if (CONFIG_KEYPAD == IRIVER_H100_PAD) #define ROCKBOY_PAD_A BUTTON_ON #define ROCKBOY_PAD_B BUTTON_OFF #define ROCKBOY_PAD_START BUTTON_REC #define ROCKBOY_PAD_SELECT BUTTON_SELECT #define ROCKBOY_MENU BUTTON_MODE +#elif (CONFIG_KEYPAD == IRIVER_H300_PAD) +#define ROCKBOY_PAD_A BUTTON_REC +#define ROCKBOY_PAD_B BUTTON_MODE +#define ROCKBOY_PAD_START BUTTON_ON +#define ROCKBOY_PAD_SELECT BUTTON_SELECT +#define ROCKBOY_MENU BUTTON_OFF + #elif CONFIG_KEYPAD == RECORDER_PAD #define ROCKBOY_PAD_A BUTTON_F1 #define ROCKBOY_PAD_B BUTTON_F2 @@ -71,10 +79,11 @@ void joy_close(void) unsigned int oldbuttonstate = 0, newbuttonstate,holdbutton; +int released, pressed; + void ev_poll(void) { event_t ev; - int released, pressed; newbuttonstate = rb->button_status(); released = ~newbuttonstate & oldbuttonstate; pressed = newbuttonstate & ~oldbuttonstate; @@ -141,31 +150,49 @@ void vid_setpal(int i, int r, int g, int b) (void)b; } -void vid_begin(void) +void vid_begin(void) // This frameskip code is borrowed from the GNUboyCE project { + static int skip = 0; + skip = (skip + 1) % (frameskip > 0 ? frameskip + 1 : 1); + fb.enabled = skip == 0; } void vid_init(void) { - fb.pelsize=1; // 8 bit framebuffer.. (too much.. but lowest gnuboy will support.. so yea... fb.h=144; fb.w=160; fb.pitch=160; fb.enabled=1; fb.dirty=0; fb.mode=3; -} -#ifdef HAVE_LCD_COLOR -static const fb_data my_pal[4] = { - LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY, LCD_BLACK -}; + frameskip=2; + +#if defined(HAVE_LCD_COLOR) + fb.pelsize=2; // 16 bit framebuffer + + fb.indexed = 0; // no palette on lcd + fb.cc[0].r = 3; // 8-5 (wasted bits on red) + fb.cc[0].l = 11; //this is the offset to the R bits (16-5) + fb.cc[1].r = 2; // 8-6 (wasted bits on green) + fb.cc[1].l = 5; // This is the offset to the G bits (16-5-6) + fb.cc[2].r = 3; // 8-5 (wasted bits on red) + fb.cc[2].l = 0; // This is the offset to the B bits (16-5-6-5) + fb.cc[3].r = 0; // no alpha + fb.cc[3].l = 0; + fb.yuv = 0; // not in yuv format +#else // ***** NEED TO LOOK INTO THIS MORE FOR THE H100 (Should be able to get rid of some IFDEF's elsewhere) + fb.pelsize=1; // 8 bit framebuffer.. (too much.. but lowest gnuboy will support.. so yea... #endif +} +fb_data *frameb; void vid_update(int scanline) { - int cnt=0,scanline_remapped; - fb_data *frameb; + register int cnt=0; +#if LCD_HEIGHT < 144 + int scanline_remapped; +#endif #if (LCD_HEIGHT == 64) && (LCD_DEPTH == 1) /* Archos */ int balance = 0; if (fb.mode==1) @@ -258,11 +285,11 @@ void vid_update(int scanline) } rb->lcd_update_rect(0, scanline & ~3, LCD_WIDTH, 4); #elif (LCD_HEIGHT >= 144) && defined(HAVE_LCD_COLOR) /* iriver H3x0, colour iPod */ - scanline_remapped = scanline + (LCD_HEIGHT-144)/2; - frameb = rb->lcd_framebuffer + scanline_remapped * LCD_WIDTH + (LCD_WIDTH-160)/2; + frameb = rb->lcd_framebuffer + (scanline + (LCD_HEIGHT-144)/2) * LCD_WIDTH + (LCD_WIDTH-160)/2;; while (cnt < 160) - *frameb++ = my_pal[scan.buf[0][cnt++]&0x3]; - rb->lcd_update_rect((LCD_WIDTH-160)/2, scanline_remapped, 160, 1); + *frameb++ = scan.pal2[scan.buf[cnt++]]; + if(scanline==143) + rb->lcd_update(); // this seems faster then doing individual scanlines #endif /* LCD_HEIGHT */ } diff --git a/docs/CREDITS b/docs/CREDITS index 66f366a84f..2e15a6b986 100644 --- a/docs/CREDITS +++ b/docs/CREDITS @@ -156,3 +156,4 @@ Nathan Hand Nick Lanham Sebastian Henriksen Martin Scarratt +Karl Kurbjun -- cgit v1.2.3