2005-03-02 23:49:38 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Gameboy emulator based on gnuboy
|
|
|
|
*
|
|
|
|
* All files in this archive are subject to the GNU General Public License.
|
|
|
|
* See the file COPYING in the source tree root for full license agreement.
|
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
#include "plugin.h"
|
|
|
|
#include "loader.h"
|
|
|
|
#include "rockmacros.h"
|
|
|
|
|
2006-01-15 18:20:18 +00:00
|
|
|
PLUGIN_HEADER
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2005-03-03 13:50:09 +00:00
|
|
|
#ifdef USE_IRAM
|
|
|
|
extern char iramcopy[];
|
|
|
|
extern char iramstart[];
|
|
|
|
extern char iramend[];
|
2006-01-08 22:50:14 +00:00
|
|
|
extern char iedata[];
|
|
|
|
extern char iend[];
|
2005-03-03 13:50:09 +00:00
|
|
|
#endif
|
|
|
|
|
2005-03-02 23:49:38 +00:00
|
|
|
/* here is a global api struct pointer. while not strictly necessary,
|
|
|
|
it's nice not to have to pass the api pointer in all function calls
|
|
|
|
in the plugin */
|
|
|
|
struct plugin_api* rb;
|
|
|
|
int shut,cleanshut;
|
|
|
|
char *errormsg;
|
|
|
|
int gnuboy_main(char *rom);
|
2005-03-28 00:00:24 +00:00
|
|
|
void pcm_close(void);
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2006-01-20 13:05:52 +00:00
|
|
|
#define optionname "options"
|
|
|
|
|
2005-03-02 23:49:38 +00:00
|
|
|
void die(char *message, ...)
|
|
|
|
{
|
|
|
|
shut=1;
|
|
|
|
errormsg=message;
|
|
|
|
}
|
|
|
|
|
2005-04-05 11:33:58 +00:00
|
|
|
void *audio_bufferbase;
|
|
|
|
void *audio_bufferpointer;
|
|
|
|
unsigned int audio_buffer_free;
|
2005-03-02 23:49:38 +00:00
|
|
|
|
|
|
|
void *my_malloc(size_t size)
|
|
|
|
{
|
|
|
|
void *alloc;
|
|
|
|
|
2005-04-05 11:33:58 +00:00
|
|
|
if (size + 4 > audio_buffer_free)
|
2005-03-02 23:49:38 +00:00
|
|
|
return 0;
|
2005-04-05 11:33:58 +00:00
|
|
|
alloc = audio_bufferpointer;
|
|
|
|
audio_bufferpointer += size + 4;
|
|
|
|
audio_buffer_free -= size + 4;
|
2005-03-02 23:49:38 +00:00
|
|
|
return alloc;
|
|
|
|
}
|
|
|
|
|
2005-09-28 17:36:42 +00:00
|
|
|
/* Using #define isn't enough with GCC 4.0.1 */
|
|
|
|
|
|
|
|
void* memcpy(void* dst, const void* src, size_t size)
|
|
|
|
{
|
|
|
|
return rb->memcpy(dst, src, size);
|
|
|
|
}
|
|
|
|
|
2005-03-02 23:49:38 +00:00
|
|
|
void setmallocpos(void *pointer)
|
|
|
|
{
|
2005-04-05 11:33:58 +00:00
|
|
|
audio_bufferpointer = pointer;
|
|
|
|
audio_buffer_free = audio_bufferpointer - audio_bufferbase;
|
2005-03-02 23:49:38 +00:00
|
|
|
}
|
|
|
|
|
2006-01-20 13:05:52 +00:00
|
|
|
void setoptions (void) {
|
|
|
|
int fd;
|
|
|
|
DIR* dir;
|
|
|
|
char optionsave[sizeof(savedir)+sizeof(optionname)];
|
|
|
|
|
|
|
|
dir=opendir(savedir);
|
|
|
|
if(!dir)
|
|
|
|
mkdir(savedir,0);
|
|
|
|
else
|
|
|
|
closedir(dir);
|
|
|
|
|
|
|
|
snprintf(optionsave, sizeof(optionsave), "%s/%s", savedir, optionname);
|
|
|
|
|
|
|
|
fd = open(optionsave, O_RDONLY);
|
|
|
|
if(fd < 0) // no options to read, set defaults
|
|
|
|
{
|
|
|
|
#if (CONFIG_KEYPAD == IRIVER_H100_PAD)
|
|
|
|
options.A=BUTTON_ON;
|
|
|
|
options.B=BUTTON_OFF;
|
|
|
|
options.START=BUTTON_REC;
|
|
|
|
options.SELECT=BUTTON_SELECT;
|
|
|
|
options.MENU=BUTTON_MODE;
|
|
|
|
|
|
|
|
#elif (CONFIG_KEYPAD == IRIVER_H300_PAD)
|
|
|
|
options.A=BUTTON_REC;
|
|
|
|
options.B=BUTTON_MODE;
|
|
|
|
options.START=BUTTON_ON;
|
|
|
|
options.SELECT=BUTTON_SELECT;
|
|
|
|
options.MENU=BUTTON_OFF;
|
|
|
|
|
|
|
|
#elif CONFIG_KEYPAD == RECORDER_PAD
|
|
|
|
options.A=BUTTON_F1;
|
|
|
|
options.B=BUTTON_F2;
|
|
|
|
options.START=BUTTON_F3;
|
|
|
|
options.SELECT=BUTTON_PLAY;
|
|
|
|
options.MENU=BUTTON_OFF;
|
|
|
|
|
2006-01-20 20:59:07 +00:00
|
|
|
#elif CONFIG_KEYPAD == IPOD_4G_PAD
|
|
|
|
options.A=BUTTON_NONE;
|
|
|
|
options.B=BUTTON_NONE;
|
|
|
|
options.START=BUTTON_SELECT;
|
|
|
|
options.SELECT=BUTTON_NONE;
|
|
|
|
options.MENU=(BUTTON_SELECT | BUTTON_REPEAT);
|
|
|
|
|
2006-01-20 13:05:52 +00:00
|
|
|
#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
|
|
|
|
options.A=BUTTON_PLAY;
|
|
|
|
options.B=BUTTON_EQ;
|
|
|
|
options.START=BUTTON_MODE;
|
|
|
|
options.SELECT=(BUTTON_SELECT | BUTTON_REL);
|
|
|
|
options.MENU=(BUTTON_SELECT | BUTTON_REPEAT);
|
2006-03-02 13:28:24 +00:00
|
|
|
|
|
|
|
#elif CONFIG_KEYPAD == GIGABEAT_PAD
|
|
|
|
options.A=BUTTON_VOL_UP;
|
|
|
|
options.B=BUTTON_VOL_DOWN;
|
|
|
|
options.START=BUTTON_POWER;
|
|
|
|
options.SELECT=BUTTON_SELECT;
|
|
|
|
options.MENU=BUTTON_MENU;
|
2006-01-20 13:05:52 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
options.maxskip=4;
|
|
|
|
options.fps=0;
|
|
|
|
options.showstats=0;
|
|
|
|
options.fullscreen=1;
|
|
|
|
options.sound=1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
read(fd,&options, sizeof(options));
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void savesettings(void)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
char optionsave[sizeof(savedir)+sizeof(optionname)];
|
|
|
|
|
|
|
|
snprintf(optionsave, sizeof(optionsave), "%s/%s", savedir, optionname);
|
|
|
|
fd = open(optionsave, O_WRONLY|O_CREAT|O_TRUNC);
|
|
|
|
write(fd,&options, sizeof(options));
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
2005-03-02 23:49:38 +00:00
|
|
|
/* this is the plugin entry point */
|
|
|
|
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
|
|
|
{
|
|
|
|
/* if you are using a global api pointer, don't forget to copy it!
|
|
|
|
otherwise you will get lovely "I04: IllInstr" errors... :-) */
|
|
|
|
rb = api;
|
2005-03-07 21:41:10 +00:00
|
|
|
|
2006-01-10 21:55:56 +00:00
|
|
|
rb->lcd_setfont(0);
|
2006-01-15 18:20:18 +00:00
|
|
|
|
2005-03-07 21:41:10 +00:00
|
|
|
if (!parameter) {
|
|
|
|
rb->splash(HZ*3, true, "Play gameboy ROM file! (.gb/.gbc)");
|
|
|
|
return PLUGIN_OK;
|
|
|
|
}
|
2005-06-29 18:54:56 +00:00
|
|
|
|
|
|
|
audio_bufferbase = audio_bufferpointer
|
2005-12-02 08:08:54 +00:00
|
|
|
= rb->plugin_get_audio_buffer((int *)&audio_buffer_free);
|
2005-06-28 21:19:40 +00:00
|
|
|
#if MEM <= 8 && !defined(SIMULATOR)
|
2006-01-16 18:51:12 +00:00
|
|
|
/* loaded as an overlay plugin, protect from overwriting ourselves */
|
|
|
|
if ((unsigned)(plugin_start_addr - (unsigned char *)audio_bufferbase)
|
2005-06-29 18:54:56 +00:00
|
|
|
< audio_buffer_free)
|
2006-01-16 18:51:12 +00:00
|
|
|
audio_buffer_free = plugin_start_addr - (unsigned char *)audio_bufferbase;
|
2005-06-28 21:19:40 +00:00
|
|
|
#endif
|
2006-01-20 13:05:52 +00:00
|
|
|
setoptions();
|
2005-03-03 13:50:09 +00:00
|
|
|
#ifdef USE_IRAM
|
2005-03-07 21:41:10 +00:00
|
|
|
memcpy(iramstart, iramcopy, iramend-iramstart);
|
2006-01-08 22:50:14 +00:00
|
|
|
memset(iedata, 0, iend - iedata);
|
2005-03-03 13:50:09 +00:00
|
|
|
#endif
|
2005-03-02 23:49:38 +00:00
|
|
|
shut=0;
|
|
|
|
cleanshut=0;
|
|
|
|
|
|
|
|
/* now go ahead and have fun! */
|
2005-03-03 19:54:47 +00:00
|
|
|
/* rb->splash(HZ*2, true, "Rockboy v0.3"); */
|
|
|
|
/* rb->lcd_clear_display(); */
|
2005-03-02 23:49:38 +00:00
|
|
|
gnuboy_main(parameter);
|
|
|
|
|
|
|
|
if(shut&&!cleanshut) {
|
2006-01-20 13:05:52 +00:00
|
|
|
rb->splash(HZ/2, true, errormsg);
|
2005-03-02 23:49:38 +00:00
|
|
|
return PLUGIN_ERROR;
|
|
|
|
}
|
2005-03-28 00:00:24 +00:00
|
|
|
pcm_close();
|
2006-01-20 13:05:52 +00:00
|
|
|
rb->splash(HZ/2, true, "Shutting down");
|
|
|
|
|
|
|
|
savesettings();
|
2005-03-02 23:49:38 +00:00
|
|
|
|
|
|
|
cleanup();
|
|
|
|
|
2005-03-28 00:00:24 +00:00
|
|
|
|
2005-03-02 23:49:38 +00:00
|
|
|
return PLUGIN_OK;
|
|
|
|
}
|