/*
GP2X minimal library by rlyeh, 2005.
Thanks to Squidge and Robster!
*/
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <linux/fb.h>
int memdev;
u16 *memdd;
void gp2x_reg_init(void)
{
memdev = open("/dev/mem", O_RDWR);
memdd=(u16 *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000);
}
#define gp2x_reg_read(addr) memdd[addr >> 1]
#define gp2x_reg_write(addr, data) memdd[addr >> 1]=data
/*
GP2X Video library w/ double buffering by rlyeh, 2005.
Thanks to Squidge and Robster for the help!
*/
u16 *gp2x_screen[2], *screen;
u32 gp2x_screenc=0,fbdev[2],smem_start[2];
void gp2x_video_flip (void)
{
u32 nBufferAddress=smem_start[gp2x_screenc];
screen=gp2x_screen[gp2x_screenc^=1];
gp2x_reg_write (0x290E, (unsigned short)(nBufferAddress & 0xffff));
gp2x_reg_write (0x2910, (unsigned short)(nBufferAddress >> 16));
gp2x_reg_write (0x2912, (unsigned short)(nBufferAddress & 0xffff));
gp2x_reg_write (0x2914, (unsigned short)(nBufferAddress >> 16));
}
void gp2x_video_init (void)
{
struct fb_fix_screeninfo fixed_info;
fbdev[0]=open("/dev/fb0", O_RDWR);
fbdev[1]=open("/dev/fb1", O_RDWR);
ioctl (fbdev[0], FBIOGET_FSCREENINFO, &fixed_info);
smem_start[0]=fixed_info.smem_start;
gp2x_screen[0]=(u16 *)mmap(0, 320*240*sizeof(u16), PROT_WRITE, MAP_SHARED, fbdev[0], 0);
ioctl (fbdev[1], FBIOGET_FSCREENINFO, &fixed_info);
smem_start[1]=fixed_info.smem_start;
gp2x_screen[1]=(u16 *)mmap(0, 320*240*sizeof(u16), PROT_WRITE, MAP_SHARED, fbdev[1], 0);
gp2x_video_flip();
gp2x_video_flip();
}
/*
GP2x joystick library by rlyeh, 2005.
Thanks to Squidge for his previous work!
*/
#define GP2X_UP (0x01)
#define GP2X_LEFT (0x04)
#define GP2X_DOWN (0x10)
#define GP2X_RIGHT (0x40)
#define GP2X_START (1<<8)
#define GP2X_SELECT (1<<9)
#define GP2X_L (1<<10)
#define GP2X_R (1<<11)
#define GP2X_A (1<<12)
#define GP2X_B (1<<13)
#define GP2X_X (1<<14)
#define GP2X_Y (1<<15)
#define GP2X_VOLM (1<<22)
#define GP2X_VOLP (1<<23)
#define GP2X_PUSH (1<<27)
u32 gp2x_joystick_read(void)
{
u32 value=(gp2x_reg_read(0x1198) & 0x00FF);
if(value==0xFD) value=0xFA;
if(value==0xF7) value=0xEB;
if(value==0F) value=0xAF;
if(value==0x7F) value=0xBE;
return ~((gp2x_reg_read(0x1184) & 0xFF00) | value | (gp2x_reg_read(0x1186) << 16));
}
/*
GP2x soundring buffer library by rlyeh, 2005.
*/
#define SOUND_DEVICE_BUFFSIZE (44100/60)
int sound_fd=0;
u32 sound_numsamples, sound_samplesize;
s16 sound_fd_buffer[SOUND_DEVICE_BUFFSIZE*4];
u32 gp2x_sound_init(u32 rate, u32 bits, u32 stereo)
{
int tmp;
if ( sound_fd ) { close(sound_fd); sound_fd=0; }
/* Open sound device */
if ( (sound_fd = open( "/dev/dsp", O_WRONLY )) < 0 )
return (sound_fd = 0);
/* Setting signed 16-bit format */
tmp = (bits == 16 ? AFMT_S16_LE : AFMT_U8);
if ( ioctl(sound_fd, SNDCTL_DSP_SETFMT, &tmp) < 0 )
{ close(sound_fd); return (sound_fd = 0); }
/* Setting stereo mode */
tmp = stereo;
if ( ioctl(sound_fd, SNDCTL_DSP_STEREO, &tmp) < 0 )
{ close(sound_fd); return (sound_fd = 0); }
/* Setting sample rate */
tmp = rate;
if ( ioctl(sound_fd, SNDCTL_DSP_SPEED, &tmp) < 0 )
{ close(sound_fd); return (sound_fd = 0); }
sound_numsamples=SOUND_DEVICE_BUFFSIZE/(44100/rate);
sound_samplesize=sound_numsamples << (stereo + (bits==16));
/* Successful */
return 1;
}
void gp2x_sound_deinit(void)
{
if ( sound_fd ) close(sound_fd);
}
void gp2x_sound_play(void)
{
if( sound_fd )
{
sound_frame(NULL, &sound_fd_buffer[0], sound_numsamples);
write( sound_fd, &sound_fd_buffer[0], sound_samplesize);
}
}
/*
GP2X misc options by rlyeh, 2005.
*/
void gp2x_backtomenu(void)
{
chdir("/usr/gp2x");
execl("gp2xmenu",NULL);
}
void gp2x_deinit(void)
{
//SDL_Quit(); //I use it for timers
gp2x_sound_deinit();
close(memdev);
close(fbdev[0]);
close(fbdev[1]);
}
void gp2x_init(u32 rate, u32 bits, u32 stereo)
{
gp2x_reg_init();
gp2x_sound_init(rate, bits, stereo);
gp2x_video_init();
//SDL_Init(0); //I use it for timers
}
/*
EXAMPLE
=======
now supply your own function for 16 bits, stereo:
void sound_frame(void *blah, void *bufferg, int samples)
{
signed short *buffer=(signed short *)bufferg;
while(samples--)
{
*buffer++=0; //Left channel
*buffer++=0; //Right channel
}
}
or for 8 bits, mono:
void sound_frame(void *blah, void *bufferg, int samples)
{
unsigned char *buffer=(unsigned char *)bufferg;
while(samples--)
{
*buffer++=0; //Central channel
}
}
and done...
int main(int argc, char *argv[])
{
gp2x_init(44100,16,1);
while(1)
{
screen[160+120*320]=0xFFFF; //pixel is RGB:565
gp2x_video_flip();
}
gp2x_deinit();
}
*/
---------------------------------------
copyed in http://www.emulnation.info/retrodev/
GP2X minimal library by rlyeh, 2005.
Thanks to Squidge and Robster!
*/
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <linux/fb.h>
int memdev;
u16 *memdd;
void gp2x_reg_init(void)
{
memdev = open("/dev/mem", O_RDWR);
memdd=(u16 *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000);
}
#define gp2x_reg_read(addr) memdd[addr >> 1]
#define gp2x_reg_write(addr, data) memdd[addr >> 1]=data
/*
GP2X Video library w/ double buffering by rlyeh, 2005.
Thanks to Squidge and Robster for the help!
*/
u16 *gp2x_screen[2], *screen;
u32 gp2x_screenc=0,fbdev[2],smem_start[2];
void gp2x_video_flip (void)
{
u32 nBufferAddress=smem_start[gp2x_screenc];
screen=gp2x_screen[gp2x_screenc^=1];
gp2x_reg_write (0x290E, (unsigned short)(nBufferAddress & 0xffff));
gp2x_reg_write (0x2910, (unsigned short)(nBufferAddress >> 16));
gp2x_reg_write (0x2912, (unsigned short)(nBufferAddress & 0xffff));
gp2x_reg_write (0x2914, (unsigned short)(nBufferAddress >> 16));
}
void gp2x_video_init (void)
{
struct fb_fix_screeninfo fixed_info;
fbdev[0]=open("/dev/fb0", O_RDWR);
fbdev[1]=open("/dev/fb1", O_RDWR);
ioctl (fbdev[0], FBIOGET_FSCREENINFO, &fixed_info);
smem_start[0]=fixed_info.smem_start;
gp2x_screen[0]=(u16 *)mmap(0, 320*240*sizeof(u16), PROT_WRITE, MAP_SHARED, fbdev[0], 0);
ioctl (fbdev[1], FBIOGET_FSCREENINFO, &fixed_info);
smem_start[1]=fixed_info.smem_start;
gp2x_screen[1]=(u16 *)mmap(0, 320*240*sizeof(u16), PROT_WRITE, MAP_SHARED, fbdev[1], 0);
gp2x_video_flip();
gp2x_video_flip();
}
/*
GP2x joystick library by rlyeh, 2005.
Thanks to Squidge for his previous work!
*/
#define GP2X_UP (0x01)
#define GP2X_LEFT (0x04)
#define GP2X_DOWN (0x10)
#define GP2X_RIGHT (0x40)
#define GP2X_START (1<<8)
#define GP2X_SELECT (1<<9)
#define GP2X_L (1<<10)
#define GP2X_R (1<<11)
#define GP2X_A (1<<12)
#define GP2X_B (1<<13)
#define GP2X_X (1<<14)
#define GP2X_Y (1<<15)
#define GP2X_VOLM (1<<22)
#define GP2X_VOLP (1<<23)
#define GP2X_PUSH (1<<27)
u32 gp2x_joystick_read(void)
{
u32 value=(gp2x_reg_read(0x1198) & 0x00FF);
if(value==0xFD) value=0xFA;
if(value==0xF7) value=0xEB;
if(value==0F) value=0xAF;
if(value==0x7F) value=0xBE;
return ~((gp2x_reg_read(0x1184) & 0xFF00) | value | (gp2x_reg_read(0x1186) << 16));
}
/*
GP2x soundring buffer library by rlyeh, 2005.
*/
#define SOUND_DEVICE_BUFFSIZE (44100/60)
int sound_fd=0;
u32 sound_numsamples, sound_samplesize;
s16 sound_fd_buffer[SOUND_DEVICE_BUFFSIZE*4];
u32 gp2x_sound_init(u32 rate, u32 bits, u32 stereo)
{
int tmp;
if ( sound_fd ) { close(sound_fd); sound_fd=0; }
/* Open sound device */
if ( (sound_fd = open( "/dev/dsp", O_WRONLY )) < 0 )
return (sound_fd = 0);
/* Setting signed 16-bit format */
tmp = (bits == 16 ? AFMT_S16_LE : AFMT_U8);
if ( ioctl(sound_fd, SNDCTL_DSP_SETFMT, &tmp) < 0 )
{ close(sound_fd); return (sound_fd = 0); }
/* Setting stereo mode */
tmp = stereo;
if ( ioctl(sound_fd, SNDCTL_DSP_STEREO, &tmp) < 0 )
{ close(sound_fd); return (sound_fd = 0); }
/* Setting sample rate */
tmp = rate;
if ( ioctl(sound_fd, SNDCTL_DSP_SPEED, &tmp) < 0 )
{ close(sound_fd); return (sound_fd = 0); }
sound_numsamples=SOUND_DEVICE_BUFFSIZE/(44100/rate);
sound_samplesize=sound_numsamples << (stereo + (bits==16));
/* Successful */
return 1;
}
void gp2x_sound_deinit(void)
{
if ( sound_fd ) close(sound_fd);
}
void gp2x_sound_play(void)
{
if( sound_fd )
{
sound_frame(NULL, &sound_fd_buffer[0], sound_numsamples);
write( sound_fd, &sound_fd_buffer[0], sound_samplesize);
}
}
/*
GP2X misc options by rlyeh, 2005.
*/
void gp2x_backtomenu(void)
{
chdir("/usr/gp2x");
execl("gp2xmenu",NULL);
}
void gp2x_deinit(void)
{
//SDL_Quit(); //I use it for timers
gp2x_sound_deinit();
close(memdev);
close(fbdev[0]);
close(fbdev[1]);
}
void gp2x_init(u32 rate, u32 bits, u32 stereo)
{
gp2x_reg_init();
gp2x_sound_init(rate, bits, stereo);
gp2x_video_init();
//SDL_Init(0); //I use it for timers
}
/*
EXAMPLE
=======
now supply your own function for 16 bits, stereo:
void sound_frame(void *blah, void *bufferg, int samples)
{
signed short *buffer=(signed short *)bufferg;
while(samples--)
{
*buffer++=0; //Left channel
*buffer++=0; //Right channel
}
}
or for 8 bits, mono:
void sound_frame(void *blah, void *bufferg, int samples)
{
unsigned char *buffer=(unsigned char *)bufferg;
while(samples--)
{
*buffer++=0; //Central channel
}
}
and done...
int main(int argc, char *argv[])
{
gp2x_init(44100,16,1);
while(1)
{
screen[160+120*320]=0xFFFF; //pixel is RGB:565
gp2x_video_flip();
}
gp2x_deinit();
}
*/
---------------------------------------
copyed in http://www.emulnation.info/retrodev/