1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Linus Nielsen Feltzing 2006-01-10 21:55:56 +00:00
parent 640eeabfe1
commit cf218e33ec
12 changed files with 196 additions and 102 deletions

View file

@ -73,7 +73,7 @@ void emu_run(void)
#if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ) #if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
rb->cpu_boost(true); rb->cpu_boost(true);
#endif #endif
while(shut==0) while(!shut)
{ {
cpu_emulate(2280); cpu_emulate(2280);
while (R_LY > 0 && R_LY < 144) while (R_LY > 0 && R_LY < 144)

View file

@ -21,7 +21,7 @@ struct scan
#elif LCD_DEPTH == 2 #elif LCD_DEPTH == 2
byte buf[4][256]; byte buf[4][256];
#elif LCD_DEPTH > 4 #elif LCD_DEPTH > 4
byte buf[1][256]; byte buf[256];
#endif #endif
byte pal1[128]; byte pal1[128];
un16 pal2[64]; un16 pal2[64];

View file

@ -19,7 +19,13 @@ struct scan scan IBSS_ATTR;
#define BG (scan.bg) #define BG (scan.bg)
#define WND (scan.wnd) #define WND (scan.wnd)
#if LCD_DEPTH ==16
#define BUF (scan.buf)
#else
#define BUF (scan.buf[scanline_ind]) #define BUF (scan.buf[scanline_ind])
#endif
#define PRI (scan.pri) #define PRI (scan.pri)
#define PAL1 (scan.pal1) #define PAL1 (scan.pal1)
@ -55,7 +61,10 @@ static int rgb332;
static int sprsort = 1; static int sprsort = 1;
static int sprdebug; 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 } #define DEF_PAL { 0x98d0e0, 0x68a0b0, 0x60707C, 0x2C3C3C }
@ -930,7 +939,7 @@ void lcd_refreshline(void)
/* #if HAVE_LCD_COLOR
static void updatepalette(int i) static void updatepalette(int i)
{ {
int c, r, g, b, y, u, v, rr, gg; int c, r, g, b, y, u, v, rr, gg;
@ -964,7 +973,7 @@ static void updatepalette(int i)
| (u<<fb.cc[1].l) | (v<<fb.cc[2].l); | (u<<fb.cc[1].l) | (v<<fb.cc[2].l);
return; return;
} }
/*
if (fb.indexed) if (fb.indexed)
{ {
pal_release(PAL1[i]); pal_release(PAL1[i]);
@ -973,7 +982,7 @@ static void updatepalette(int i)
PAL2[i] = (c<<8) | c; PAL2[i] = (c<<8) | c;
PAL4[i] = (c<<24) | (c<<16) | (c<<8) | c; PAL4[i] = (c<<24) | (c<<16) | (c<<8) | c;
return; return;
} }*/
r = (r >> fb.cc[0].r) << fb.cc[0].l; r = (r >> fb.cc[0].r) << fb.cc[0].l;
g = (g >> fb.cc[1].r) << fb.cc[1].l; g = (g >> fb.cc[1].r) << fb.cc[1].l;
@ -996,13 +1005,16 @@ static void updatepalette(int i)
PAL4[i] = c; PAL4[i] = c;
break; break;
} }
}*/ }
#endif
void pal_write(int i, byte b) void pal_write(int i, byte b)
{ {
if (lcd.pal[i] == b) return; if (lcd.pal[i] == b) return;
lcd.pal[i] = b; 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) void pal_write_dmg(int i, int mapnum, byte d)
@ -1043,7 +1055,9 @@ void vram_dirty(void)
void pal_dirty(void) void pal_dirty(void)
{ {
// int i; #if LCD_DEPTH ==16
int i;
#endif
if (!hw.cgb) if (!hw.cgb)
{ {
@ -1052,8 +1066,10 @@ void pal_dirty(void)
pal_write_dmg(64, 2, R_OBP0); pal_write_dmg(64, 2, R_OBP0);
pal_write_dmg(72, 3, R_OBP1); pal_write_dmg(72, 3, R_OBP1);
} }
// for (i = 0; i < 64; i++) #if LCD_DEPTH ==16
// updatepalette(i); for (i = 0; i < 64; i++)
updatepalette(i);
#endif
} }
void lcd_reset(void) void lcd_reset(void)

View file

@ -86,7 +86,7 @@ static char *savedir = "/.rockbox/rockboy";
static int saveslot; static int saveslot;
static int forcebatt, nobatt; static int forcebatt, nobatt;
static int forcedmg; static int forcedmg, gbamode;
static int memfill = -1, memrand = -1; static int memfill = -1, memrand = -1;
@ -181,7 +181,7 @@ int rom_load(void)
c = header[0x0143]; c = header[0x0143];
hw.cgb = ((c == 0x80) || (c == 0xc0)) && !forcedmg; hw.cgb = ((c == 0x80) || (c == 0xc0)) && !forcedmg;
hw.gba = 0; //(hw.cgb && gbamode); hw.gba = (hw.cgb && gbamode);
close(fd); close(fd);

View file

@ -67,11 +67,33 @@ static const char *slot_menu[] = {
#define OPT_MENU_TITLE "Options" #define OPT_MENU_TITLE "Options"
typedef enum { typedef enum {
OM_ITEM_FS,
OM_ITEM_SOUND,
OM_ITEM_BACK, OM_ITEM_BACK,
OM_MENU_LAST OM_MENU_LAST
} OptMenuItem; } OptMenuItem;
static const char *opt_menu[] = { 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..." "Previous Menu..."
}; };
@ -90,6 +112,8 @@ int do_user_menu(void) {
int mi, ret, num_items; int mi, ret, num_items;
bool done = false; bool done = false;
pcm_init();
/* set defaults */ /* set defaults */
ret = 0; /* return value */ ret = 0; /* return value */
mi = 0; /* initial menu selection */ mi = 0; /* initial menu selection */
@ -119,7 +143,7 @@ int do_user_menu(void) {
break; break;
} }
} }
rb->lcd_clear_display();
/* return somethin' */ /* return somethin' */
return ret; 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) { static void do_opt_menu(void) {
int mi, num_items; int mi, num_items;
bool done = false; bool done = false;
@ -324,8 +384,18 @@ static void do_opt_menu(void) {
while (!done) { while (!done) {
mi = do_menu(OPT_MENU_TITLE, (char**) opt_menu, num_items, mi); 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; done = true;
break;
}
} }
} }

View file

@ -9,7 +9,7 @@ struct pcm
{ {
int hz, len; int hz, len;
int stereo; int stereo;
short *buf; byte *buf;
int pos; int pos;
}; };

View file

@ -5,117 +5,89 @@
struct pcm pcm; struct pcm pcm;
#define BUF_SIZE (8192) bool sound = 1;
#define DMA_PORTION (1024) #define N_BUFS 4
#define BUF_SIZE 1024
static short buf1_unal[(BUF_SIZE / sizeof(short)) + 2]; // to make sure 4 byte aligned
rcvar_t pcm_exports[] = rcvar_t pcm_exports[] =
{ {
RCV_END RCV_END
}; };
/*#if CONFIG_CODEC == SWCODEC && !defined(SIMULATOR) #if CONFIG_CODEC == SWCODEC && !defined(SIMULATOR)
* disabled cause it crashes with current audio implementation.. no sound.
*/
#if 0
static short* buf1;
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 bool newly_started;
static int turns;
void pcm_init(void) 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; newly_started = true;
last_back_pos = buf1;
turns = 0;
pcm.hz = 11025; pcm.hz = 11025;
pcm.stereo = 1; 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_play_stop();
rb->pcm_set_frequency(11025); rb->pcm_set_frequency(11025); // 44100 22050 11025
rb->pcm_set_volume(200);
} }
void pcm_close(void) void pcm_close(void)
{ {
memset(&pcm, 0, sizeof pcm); memset(&pcm, 0, sizeof pcm);
newly_started = true; newly_started = true;
last_back_pos = buf1;
rb->pcm_play_stop(); rb->pcm_play_stop();
rb->pcm_set_frequency(44100);
} }
void get_more(unsigned char** start, long* size) void get_more(unsigned char** start, long* size)
{ {
int length; *start = (unsigned char*)(&gmbuf[pcm.len*curbuf]);
unsigned int sar = (unsigned int)SAR0; *size = BUF_SIZE*sizeof(short);
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;
}
} }
int pcm_submit(void) 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*/ register int i;
int shorts_left = ((((unsigned int)buf1) + BUF_SIZE) - ((unsigned int)last_back_pos)) / sizeof(short);
if( shorts_left >= pcm.pos ) if (!sound) {
{ pcm.pos = 0;
memcpy(last_back_pos,pcm.buf,pcm.pos * sizeof(short)); return 0;
last_back_pos = &last_back_pos[pcm.pos];
} }
else
{ if (pcm.pos >= pcm.len) {
int last_pos = shorts_left; curbuf = (curbuf + 1) % N_BUFS;
memcpy(last_back_pos,pcm.buf,shorts_left * sizeof(short)); pcm.buf = buf + pcm.len * curbuf;
last_back_pos = buf1; pcm.pos = 0;
shorts_left = pcm.pos - shorts_left;
memcpy(last_back_pos,&pcm.buf[last_pos],shorts_left * sizeof(short)); // gotta convert the 8 bit buffer to 16
last_back_pos = &buf1[shorts_left]; for(i=0; i<pcm.len;i++)
turns--; gmbuf[i+pcm.len*curbuf] = (pcm.buf[i]<<8)-0x8000;
} }
if(newly_started) if(newly_started)
{ {
rb->pcm_play_data((unsigned char*)buf1,pcm.pos * sizeof(short),&get_more); rb->pcm_play_data(&get_more);
newly_started = false; newly_started = false;
} }
pcm.pos = 0;
return 1; return 1;
} }
#else #else
static byte buf1_unal[(BUF_SIZE / sizeof(short)) + 2]; // to make sure 4 byte aligned
void pcm_init(void) void pcm_init(void)
{ {
pcm.hz = 11025; pcm.hz = 11025;

View file

@ -102,6 +102,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
otherwise you will get lovely "I04: IllInstr" errors... :-) */ otherwise you will get lovely "I04: IllInstr" errors... :-) */
rb = api; rb = api;
rb->lcd_setfont(0);
if (!parameter) { if (!parameter) {
rb->splash(HZ*3, true, "Play gameboy ROM file! (.gb/.gbc)"); rb->splash(HZ*3, true, "Play gameboy ROM file! (.gb/.gbc)");
return PLUGIN_OK; return PLUGIN_OK;

View file

@ -92,3 +92,6 @@ void savestate(int fd);
/* Using #define isn't enough with GCC 4.0.1 */ /* Using #define isn't enough with GCC 4.0.1 */
void* memcpy(void* dst, const void* src, size_t size); void* memcpy(void* dst, const void* src, size_t size);
extern int frameskip;
extern bool sound;

View file

@ -158,9 +158,10 @@ void sound_reset(void)
sound_off(); sound_off();
} }
void sound_mix(void) void sound_mix(void)
{ {
if (!sound) return;
int s, l, r, f, n; int s, l, r, f, n;
if (!RATE || cpu.snd < RATE) return; if (!RATE || cpu.snd < RATE) return;
@ -275,10 +276,10 @@ void sound_mix(void)
pcm_submit(); pcm_submit();
if (pcm.stereo) if (pcm.stereo)
{ {
pcm.buf[pcm.pos++] = (signed short)(l * 256); pcm.buf[pcm.pos++] = l+128;
pcm.buf[pcm.pos++] = (signed short)(r * 256); 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); 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) byte sound_read(byte r)
{ {
if(!sound) return 0;
sound_mix(); sound_mix();
/* printf("read %02X: %02X\n", r, REG(r)); */ /* printf("read %02X: %02X\n", r, REG(r)); */
return REG(r); return REG(r);
@ -344,6 +346,7 @@ void s4_init(void)
void sound_write(byte r, byte b) void sound_write(byte r, byte b)
{ {
if(!sound) return;
#if 0 #if 0
static void *timer; static void *timer;
if (!timer) timer = sys_timer(); if (!timer) timer = sys_timer();

View file

@ -25,6 +25,8 @@
#include "hw.h" #include "hw.h"
#include "config.h" #include "config.h"
int frameskip;
rcvar_t joy_exports[] = rcvar_t joy_exports[] =
{ {
RCV_END RCV_END
@ -52,14 +54,20 @@ void joy_close(void)
{ {
} }
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ #if (CONFIG_KEYPAD == IRIVER_H100_PAD)
(CONFIG_KEYPAD == IRIVER_H300_PAD)
#define ROCKBOY_PAD_A BUTTON_ON #define ROCKBOY_PAD_A BUTTON_ON
#define ROCKBOY_PAD_B BUTTON_OFF #define ROCKBOY_PAD_B BUTTON_OFF
#define ROCKBOY_PAD_START BUTTON_REC #define ROCKBOY_PAD_START BUTTON_REC
#define ROCKBOY_PAD_SELECT BUTTON_SELECT #define ROCKBOY_PAD_SELECT BUTTON_SELECT
#define ROCKBOY_MENU BUTTON_MODE #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 #elif CONFIG_KEYPAD == RECORDER_PAD
#define ROCKBOY_PAD_A BUTTON_F1 #define ROCKBOY_PAD_A BUTTON_F1
#define ROCKBOY_PAD_B BUTTON_F2 #define ROCKBOY_PAD_B BUTTON_F2
@ -71,10 +79,11 @@ void joy_close(void)
unsigned int oldbuttonstate = 0, newbuttonstate,holdbutton; unsigned int oldbuttonstate = 0, newbuttonstate,holdbutton;
int released, pressed;
void ev_poll(void) void ev_poll(void)
{ {
event_t ev; event_t ev;
int released, pressed;
newbuttonstate = rb->button_status(); newbuttonstate = rb->button_status();
released = ~newbuttonstate & oldbuttonstate; released = ~newbuttonstate & oldbuttonstate;
pressed = newbuttonstate & ~oldbuttonstate; pressed = newbuttonstate & ~oldbuttonstate;
@ -141,31 +150,49 @@ void vid_setpal(int i, int r, int g, int b)
(void)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) void vid_init(void)
{ {
fb.pelsize=1; // 8 bit framebuffer.. (too much.. but lowest gnuboy will support.. so yea...
fb.h=144; fb.h=144;
fb.w=160; fb.w=160;
fb.pitch=160; fb.pitch=160;
fb.enabled=1; fb.enabled=1;
fb.dirty=0; fb.dirty=0;
fb.mode=3; fb.mode=3;
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
} }
#ifdef HAVE_LCD_COLOR fb_data *frameb;
static const fb_data my_pal[4] = {
LCD_WHITE, LCD_LIGHTGRAY, LCD_DARKGRAY, LCD_BLACK
};
#endif
void vid_update(int scanline) void vid_update(int scanline)
{ {
int cnt=0,scanline_remapped; register int cnt=0;
fb_data *frameb; #if LCD_HEIGHT < 144
int scanline_remapped;
#endif
#if (LCD_HEIGHT == 64) && (LCD_DEPTH == 1) /* Archos */ #if (LCD_HEIGHT == 64) && (LCD_DEPTH == 1) /* Archos */
int balance = 0; int balance = 0;
if (fb.mode==1) if (fb.mode==1)
@ -258,11 +285,11 @@ void vid_update(int scanline)
} }
rb->lcd_update_rect(0, scanline & ~3, LCD_WIDTH, 4); rb->lcd_update_rect(0, scanline & ~3, LCD_WIDTH, 4);
#elif (LCD_HEIGHT >= 144) && defined(HAVE_LCD_COLOR) /* iriver H3x0, colour iPod */ #elif (LCD_HEIGHT >= 144) && defined(HAVE_LCD_COLOR) /* iriver H3x0, colour iPod */
scanline_remapped = scanline + (LCD_HEIGHT-144)/2; frameb = rb->lcd_framebuffer + (scanline + (LCD_HEIGHT-144)/2) * LCD_WIDTH + (LCD_WIDTH-160)/2;;
frameb = rb->lcd_framebuffer + scanline_remapped * LCD_WIDTH + (LCD_WIDTH-160)/2;
while (cnt < 160) while (cnt < 160)
*frameb++ = my_pal[scan.buf[0][cnt++]&0x3]; *frameb++ = scan.pal2[scan.buf[cnt++]];
rb->lcd_update_rect((LCD_WIDTH-160)/2, scanline_remapped, 160, 1); if(scanline==143)
rb->lcd_update(); // this seems faster then doing individual scanlines
#endif /* LCD_HEIGHT */ #endif /* LCD_HEIGHT */
} }

View file

@ -156,3 +156,4 @@ Nathan Hand
Nick Lanham Nick Lanham
Sebastian Henriksen Sebastian Henriksen
Martin Scarratt Martin Scarratt
Karl Kurbjun