initial import

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@2 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2006-12-19 20:53:21 +00:00
parent 2cadbd5e56
commit cc68a136aa
341 changed files with 180839 additions and 0 deletions

93
platform/gp2x/940.c Normal file
View file

@ -0,0 +1,93 @@
#include "940shared.h"
/* this code assumes that we live @ 0x3000000 bank */
//static volatile unsigned short *gp2x_memregs = (void *) 0x0xbd000000;
//static volatile unsigned long *gp2x_memregl = (void *) 0x0xbd000000;
static _940_data_t *shared_data = (_940_data_t *) 0x100000;
static _940_ctl_t *shared_ctl = (_940_ctl_t *) 0x200000;
YM2612 *ym2612_940;
int *mix_buffer;
// from init.s
void wait_irq(void);
void spend_cycles(int c);
void cache_clean(void);
void cache_clean_flush(void);
// asm volatile ("mov r0, #0" ::: "r0");
// asm volatile ("mcr p15, 0, r0, c7, c6, 0" ::: "r0"); /* flush dcache */
// asm volatile ("mcr p15, 0, r0, c7, c10, 4" ::: "r0"); /* drain write buffer */
void Main940(int startvector)
{
ym2612_940 = &shared_data->ym2612;
mix_buffer = shared_data->mix_buffer;
// debug
shared_ctl->vstarts[startvector]++;
asm volatile ("mcr p15, 0, r0, c7, c10, 4" ::: "r0");
/* unmask IRQs */
for (;; shared_ctl->loopc++)
{
/*
while (!shared_ctl->busy)
{
//shared_ctl->waitc++;
spend_cycles(256);
}
*/
if (!shared_ctl->busy)
{
wait_irq();
}
switch (shared_ctl->job)
{
case JOB940_YM2612INIT:
shared_ctl->writebuff0[0] = shared_ctl->writebuff1[0] = 0xffff;
YM2612Init_(shared_ctl->baseclock, shared_ctl->rate);
break;
case JOB940_YM2612RESETCHIP:
YM2612ResetChip_();
break;
case JOB940_PICOSTATELOAD:
YM2612PicoStateLoad_();
break;
case JOB940_YM2612UPDATEONE: {
int i, dw, *wbuff;
if (shared_ctl->writebuffsel == 1) {
wbuff = (int *) shared_ctl->writebuff1;
} else {
wbuff = (int *) shared_ctl->writebuff0;
}
/* playback all writes */
for (i = 2048/2; i > 0; i--) {
UINT16 d;
dw = *wbuff++;
d = dw;
if (d == 0xffff) break;
YM2612Write_(d >> 8, d);
d = (dw>>16);
if (d == 0xffff) break;
YM2612Write_(d >> 8, d);
}
YM2612UpdateOne_(0, shared_ctl->length, shared_ctl->stereo);
// cache_clean_flush();
cache_clean();
// asm volatile ("mov r0, #0" ::: "r0");
// asm volatile ("mcr p15, 0, r0, c7, c10, 4" ::: "r0"); /* drain write buffer, should be done on nonbuffered write */
break;
}
}
shared_ctl->busy = 0;
}
}

View file

@ -0,0 +1,451 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include "940shared.h"
#include "gp2x.h"
#include "emu.h"
#include "menu.h"
#include "asmutils.h"
/* we will need some gp2x internals here */
extern volatile unsigned short *gp2x_memregs; /* from minimal library rlyeh */
extern volatile unsigned long *gp2x_memregl;
static unsigned char *shared_mem = 0;
static _940_data_t *shared_data = 0;
static _940_ctl_t *shared_ctl = 0;
int crashed_940 = 0;
/***********************************************************/
#define MAXOUT (+32767)
#define MINOUT (-32768)
/* limitter */
#define Limit(val, max,min) { \
if ( val > max ) val = max; \
else if ( val < min ) val = min; \
}
/* these will be managed locally on our side */
extern int *ym2612_dacen;
extern INT32 *ym2612_dacout;
extern void *ym2612_regs;
static UINT8 *REGS = 0; /* we will also keep local copy of regs for savestates and such */
static INT32 addr_A1; /* address line A1 */
static int dacen;
static INT32 dacout;
static UINT8 ST_address; /* address register */
static UINT8 ST_status; /* status flag */
static UINT8 ST_mode; /* mode CSM / 3SLOT */
static int ST_TA; /* timer a */
static int ST_TAC; /* timer a maxval */
static int ST_TAT; /* timer a ticker */
static UINT8 ST_TB; /* timer b */
static int ST_TBC; /* timer b maxval */
static int ST_TBT; /* timer b ticker */
static int writebuff_ptr = 0;
/* OPN Mode Register Write */
static void set_timers( int v )
{
/* b7 = CSM MODE */
/* b6 = 3 slot mode */
/* b5 = reset b */
/* b4 = reset a */
/* b3 = timer enable b */
/* b2 = timer enable a */
/* b1 = load b */
/* b0 = load a */
ST_mode = v;
/* reset Timer b flag */
if( v & 0x20 )
ST_status &= ~2;
/* reset Timer a flag */
if( v & 0x10 )
ST_status &= ~1;
}
/* YM2612 write */
/* a = address */
/* v = value */
/* returns 1 if sample affecting state changed */
int YM2612Write_940(unsigned int a, unsigned int v)
{
int addr; //, ret=1;
v &= 0xff; /* adjust to 8 bit bus */
a &= 3;
switch( a ) {
case 0: /* address port 0 */
ST_address = v;
addr_A1 = 0;
//ret=0;
break;
case 1: /* data port 0 */
if (addr_A1 != 0) {
return 0; /* verified on real YM2608 */
}
addr = ST_address;
REGS[addr] = v;
switch( addr & 0xf0 )
{
case 0x20: /* 0x20-0x2f Mode */
switch( addr )
{
case 0x24: { // timer A High 8
int TAnew = (ST_TA & 0x03)|(((int)v)<<2);
if(ST_TA != TAnew) {
// we should reset ticker only if new value is written. Outrun requires this.
ST_TA = TAnew;
ST_TAC = (1024-TAnew)*18;
ST_TAT = 0;
}
return 0;
}
case 0x25: { // timer A Low 2
int TAnew = (ST_TA & 0x3fc)|(v&3);
if(ST_TA != TAnew) {
ST_TA = TAnew;
ST_TAC = (1024-TAnew)*18;
ST_TAT = 0;
}
return 0;
}
case 0x26: // timer B
if(ST_TB != v) {
ST_TB = v;
ST_TBC = (256-v)<<4;
ST_TBC *= 18;
ST_TBT = 0;
}
return 0;
case 0x27: /* mode, timer control */
set_timers( v );
break; // other side needs ST.mode for 3slot mode
case 0x2a: /* DAC data (YM2612) */
dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */
return 0;
case 0x2b: /* DAC Sel (YM2612) */
/* b7 = dac enable */
dacen = v & 0x80;
break; // other side has to know this
default:
break;
}
break;
}
break;
case 2: /* address port 1 */
ST_address = v;
addr_A1 = 1;
//ret=0;
break;
case 3: /* data port 1 */
if (addr_A1 != 1) {
return 0; /* verified on real YM2608 */
}
addr = ST_address | 0x100;
REGS[addr] = v;
break;
}
if(currentConfig.EmuOpt & 4) {
/* queue this write for 940 */
if (writebuff_ptr < 2047) {
if (shared_ctl->writebuffsel == 1) {
shared_ctl->writebuff0[writebuff_ptr++] = (a<<8)|v;
} else {
shared_ctl->writebuff1[writebuff_ptr++] = (a<<8)|v;
}
} else {
printf("warning: writebuff_ptr > 2047\n");
}
}
return 0; // cause the engine to do updates once per frame only
}
UINT8 YM2612Read_940(void)
{
return ST_status;
}
int YM2612PicoTick_940(int n)
{
//int ret = 0;
// timer A
if(ST_mode & 0x01 && (ST_TAT+=64*n) >= ST_TAC) {
ST_TAT -= ST_TAC;
if(ST_mode & 0x04) ST_status |= 1;
// CSM mode total level latch and auto key on
/* FIXME
if(ST_mode & 0x80) {
CSMKeyControll( &(ym2612_940->CH[2]) ); // Vectorman2, etc.
ret = 1;
}
*/
}
// timer B
if(ST_mode & 0x02 && (ST_TBT+=64*n) >= ST_TBC) {
ST_TBT -= ST_TBC;
if(ST_mode & 0x08) ST_status |= 2;
}
return 0;
}
static void wait_busy_940(void)
{
int i;
#if 0
printf("940 busy, entering wait loop.. (cnt: %i, wc: %i, ve: ", shared_ctl->loopc, shared_ctl->waitc);
for (i = 0; i < 8; i++)
printf("%i ", shared_ctl->vstarts[i]);
printf(")\n");
for (i = 0; shared_ctl->busy; i++)
{
spend_cycles(1024); /* needs tuning */
}
printf("wait iterations: %i\n", i);
#else
for (i = 0; shared_ctl->busy && i < 0x10000; i++)
spend_cycles(4*1024);
if (i < 0x10000) return;
/* 940 crashed */
printf("940 crashed (cnt: %i, wc: %i, ve: ", shared_ctl->loopc, shared_ctl->waitc);
for (i = 0; i < 8; i++)
printf("%i ", shared_ctl->vstarts[i]);
printf(")\n");
strcpy(menuErrorMsg, "940 crashed.");
engineState = PGS_Menu;
crashed_940 = 1;
#endif
}
static void add_job_940(int job)
{
shared_ctl->job = job;
shared_ctl->busy = 1;
gp2x_memregs[0x3B3E>>1] = 0xffff; // cause an IRQ for 940
}
void YM2612PicoStateLoad_940(void)
{
int i, old_A1 = addr_A1;
if (shared_ctl->busy) wait_busy_940();
// feed all the registers and update internal state
for(i = 0; i < 0x100; i++) {
YM2612Write_940(0, i);
YM2612Write_940(1, REGS[i]);
}
for(i = 0; i < 0x100; i++) {
YM2612Write_940(2, i);
YM2612Write_940(3, REGS[i|0x100]);
}
addr_A1 = old_A1;
add_job_940(JOB940_PICOSTATELOAD);
}
static void internal_reset(void)
{
writebuff_ptr = 0;
ST_mode = 0;
ST_status = 0; /* normal mode */
ST_TA = 0;
ST_TAC = 0;
ST_TB = 0;
ST_TBC = 0;
dacen = 0;
}
extern char **g_argv;
/* none of the functions in this file should be called before this one */
void YM2612Init_940(int baseclock, int rate)
{
printf("YM2612Init_940()\n");
//printf("sizeof(*shared_data): %i (%x)\n", sizeof(*shared_data), sizeof(*shared_data));
//printf("sizeof(*shared_ctl): %i (%x)\n", sizeof(*shared_ctl), sizeof(*shared_ctl));
Reset940(1);
Pause940(1);
gp2x_memregs[0x3B46>>1] = 0xffff; // clear pending DUALCPU interrupts for 940
gp2x_memregs[0x3B42>>1] = 0xffff; // enable DUALCPU interrupts for 940
gp2x_memregl[0x4508>>2] = ~(1<<26); // unmask DUALCPU ints in the undocumented 940's interrupt controller
if (shared_mem == NULL)
{
shared_mem = (unsigned char *) mmap(0, 0x210000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0x3000000);
if(shared_mem == MAP_FAILED)
{
printf("mmap(shared_data) failed with %i\n", errno);
exit(1);
}
shared_data = (_940_data_t *) (shared_mem+0x100000);
/* this area must not get buffered on either side */
shared_ctl = (_940_ctl_t *) (shared_mem+0x200000);
crashed_940 = 1;
}
if (crashed_940)
{
unsigned char ucData[1024];
int nRead, i, nLen = 0;
char binpath[1024];
FILE *fp;
strncpy(binpath, g_argv[0], 1023);
binpath[1023] = 0;
for (i = strlen(binpath); i > 0; i--)
if (binpath[i] == '/') { binpath[i] = 0; break; }
strcat(binpath, "/code940.bin");
fp = fopen(binpath, "rb");
if(!fp)
{
memset(gp2x_screen, 0, 320*240);
gp2x_text_out8(10, 100, "failed to open required file:");
gp2x_text_out8(10, 110, "code940.bin");
gp2x_video_flip();
printf("failed to open %s\n", binpath);
exit(1);
}
while(1)
{
nRead = fread(ucData, 1, 1024, fp);
if(nRead <= 0)
break;
memcpy(shared_mem + nLen, ucData, nRead);
nLen += nRead;
}
fclose(fp);
crashed_940 = 0;
}
memset(shared_data, 0, sizeof(*shared_data));
memset(shared_ctl, 0, sizeof(*shared_ctl));
REGS = YM2612GetRegs();
ym2612_dacen = &dacen;
ym2612_dacout = &dacout;
internal_reset();
/* now cause 940 to init it's ym2612 stuff */
shared_ctl->baseclock = baseclock;
shared_ctl->rate = rate;
shared_ctl->job = JOB940_YM2612INIT;
shared_ctl->busy = 1;
/* start the 940 */
Reset940(0);
Pause940(0);
// YM2612ResetChip_940(); // will be done on JOB940_YM2612INIT
}
void YM2612ResetChip_940(void)
{
printf("YM2612ResetChip_940()\n");
if (shared_data == NULL) {
printf("YM2612ResetChip_940: reset before init?\n");
return;
}
if (shared_ctl->busy) wait_busy_940();
internal_reset();
add_job_940(JOB940_YM2612RESETCHIP);
}
void YM2612UpdateOne_940(short *buffer, int length, int stereo)
{
int i, *mix_buffer = shared_data->mix_buffer;
//printf("YM2612UpdateOne_940()\n");
if (shared_ctl->busy) wait_busy_940();
//printf("940 (cnt: %i, wc: %i, ve: ", shared_ctl->loopc, shared_ctl->waitc);
//for (i = 0; i < 8; i++)
// printf("%i ", shared_ctl->vstarts[i]);
//printf(")\n");
/* mix data from previous go */
if (stereo) {
int *mb = mix_buffer;
for (i = length; i > 0; i--) {
int l, r;
l = r = *buffer;
l += *mb++, r += *mb++;
Limit( l, MAXOUT, MINOUT );
Limit( r, MAXOUT, MINOUT );
*buffer++ = l; *buffer++ = r;
}
} else {
for (i = 0; i < length; i++) {
int l = mix_buffer[i];
l += buffer[i];
Limit( l, MAXOUT, MINOUT );
buffer[i] = l;
}
}
//printf("new writes: %i\n", writebuff_ptr);
if (shared_ctl->writebuffsel == 1) {
shared_ctl->writebuff0[writebuff_ptr] = 0xffff;
} else {
shared_ctl->writebuff1[writebuff_ptr] = 0xffff;
}
writebuff_ptr = 0;
/* give 940 another job */
shared_ctl->writebuffsel ^= 1;
shared_ctl->length = length;
shared_ctl->stereo = stereo;
add_job_940(JOB940_YM2612UPDATEONE);
//spend_cycles(512);
//printf("SRCPND: %08lx, INTMODE: %08lx, INTMASK: %08lx, INTPEND: %08lx\n",
// gp2x_memregl[0x4500>>2], gp2x_memregl[0x4504>>2], gp2x_memregl[0x4508>>2], gp2x_memregl[0x4510>>2]);
}

View file

@ -0,0 +1,9 @@
void YM2612Init_940(int baseclock, int rate);
void YM2612ResetChip_940(void);
void YM2612UpdateOne_940(short *buffer, int length, int stereo);
int YM2612Write_940(unsigned int a, unsigned int v);
unsigned char YM2612Read_940(void);
int YM2612PicoTick_940(int n);
void YM2612PicoStateLoad_940(void);

174
platform/gp2x/940init.s Normal file
View file

@ -0,0 +1,174 @@
.global code940
code940: @ interrupt table:
b .b_reset @ reset
b .b_undef @ undefined instructions
b .b_swi @ software interrupt
b .b_pabort @ prefetch abort
b .b_dabort @ data abort
b .b_reserved @ reserved
b .b_irq @ IRQ
b .b_fiq @ FIQ
@ test
.b_reset:
mov r12, #0
b .Begin
.b_undef:
mov r12, #1
b .Begin
.b_swi:
mov r12, #2
b .Begin
.b_pabort:
mov r12, #3
b .Begin
.b_dabort:
mov r12, #4
b .Begin
.b_reserved:
mov r12, #5
b .Begin
.b_irq:
mov r12, #6
mov sp, #0x100000 @ reset stack
sub sp, sp, #4
mov r1, #0xbd000000 @ assume we live @ 0x3000000 bank
orr r2, r1, #0x3B00
orr r2, r2, #0x0046
mvn r3, #0
strh r3, [r2] @ clear any pending interrupts from the DUALCPU unit
orr r2, r1, #0x4500
str r3, [r2] @ clear all pending interrupts in irq controller's SRCPND register
orr r2, r2, #0x0010
str r3, [r2] @ clear all pending interrupts in irq controller's INTPND register
b .Enter
.b_fiq:
mov r12, #7
b .Begin
.Begin:
mov sp, #0x100000 @ set the stack top (1M)
sub sp, sp, #4 @ minus 4
@ set up memory region 0 -- the whole 4GB address space
mov r0, #(0x1f<<1)|1 @ region data
mcr p15, 0, r0, c6, c0, 0 @ opcode2 ~ data/instr
mcr p15, 0, r0, c6, c0, 1
@ set up region 1 which is the first 2 megabytes.
mov r0, #(0x14<<1)|1 @ region data
mcr p15, 0, r0, c6, c1, 0
mcr p15, 0, r0, c6, c1, 1
@ set up region 2: 64k 0x200000-0x210000
mov r0, #(0x0f<<1)|1
orr r0, r0, #0x200000
mcr p15, 0, r0, c6, c2, 0
mcr p15, 0, r0, c6, c2, 1
@ set up region 3: 64k 0xbd000000-0xbd010000 (hw control registers)
mov r0, #(0x0f<<1)|1
orr r0, r0, #0xbd000000
mcr p15, 0, r0, c6, c3, 0
mcr p15, 0, r0, c6, c3, 1
@ set region 1 to be cacheable (so the first 2M will be cacheable)
mov r0, #2
mcr p15, 0, r0, c2, c0, 0
mcr p15, 0, r0, c2, c0, 1
@ set region 1 to be bufferable too (only data)
mcr p15, 0, r0, c3, c0, 0
@ set protection, allow accsess only to regions 1 and 2
mov r0, #(3<<6)|(3<<4)|(3<<2)|(0) @ data: [full, full, full, no access] for regions [3 2 1 0]
mcr p15, 0, r0, c5, c0, 0
mov r0, #(0<<6)|(0<<4)|(3<<2)|(0) @ instructions: [no access, no, full, no]
mcr p15, 0, r0, c5, c0, 1
mrc p15, 0, r0, c1, c0, 0 @ fetch current control reg
orr r0, r0, #1 @ 0x00000001: enable protection unit
orr r0, r0, #4 @ 0x00000004: enable D cache
orr r0, r0, #0x1000 @ 0x00001000: enable I cache
orr r0, r0, #0xC0000000 @ 0xC0000000: async+fastbus
mcr p15, 0, r0, c1, c0, 0 @ set control reg
@ flush (invalidate) the cache (just in case)
mov r0, #0
mcr p15, 0, r0, c7, c6, 0
.Enter:
mov r0, r12
bl Main940
@ we should never get here
.b_deadloop:
b .b_deadloop
@ so asm utils are also defined here:
.global spend_cycles @ c
spend_cycles:
mov r0, r0, lsr #2 @ 4 cycles/iteration
sub r0, r0, #2 @ entry/exit/init
.sc_loop:
subs r0, r0, #1
bpl .sc_loop
bx lr
@ clean-flush function from ARM940T technical reference manual
.global cache_clean_flush
cache_clean_flush:
mov r1, #0 @ init line counter
ccf_outer_loop:
mov r0, #0 @ segment counter
ccf_inner_loop:
orr r2, r1, r0 @ make segment and line address
mcr p15, 0, r2, c7, c14, 2 @ clean and flush that line
add r0, r0, #0x10 @ incremet secment counter
cmp r0, #0x40 @ complete all 4 segments?
bne ccf_inner_loop
add r1, r1, #0x04000000 @ increment line counter
cmp r1, #0 @ complete all lines?
bne ccf_outer_loop
bx lr
@ clean-only version
.global cache_clean
cache_clean:
mov r1, #0 @ init line counter
cf_outer_loop:
mov r0, #0 @ segment counter
cf_inner_loop:
orr r2, r1, r0 @ make segment and line address
mcr p15, 0, r2, c7, c10, 2 @ clean that line
add r0, r0, #0x10 @ incremet secment counter
cmp r0, #0x40 @ complete all 4 segments?
bne cf_inner_loop
add r1, r1, #0x04000000 @ increment line counter
cmp r1, #0 @ complete all lines?
bne cf_outer_loop
bx lr
.global wait_irq
wait_irq:
mrs r0, cpsr
bic r0, r0, #0x80
msr cpsr_c, r0 @ enable interrupts
mov r0, #0
mcr p15, 0, r0, c7, c0, 4 @ wait for IRQ
@ mcr p15, 0, r0, c15, c8, 2
b .b_reserved
.pool

33
platform/gp2x/940shared.h Normal file
View file

@ -0,0 +1,33 @@
#include "../../Pico/sound/ym2612.h"
enum _940_job_t {
JOB940_YM2612INIT = 1,
JOB940_YM2612RESETCHIP,
JOB940_YM2612UPDATEONE,
JOB940_PICOSTATELOAD,
JOB940_NUMJOBS
};
typedef struct
{
YM2612 ym2612; /* current state of the emulated YM2612 */
int mix_buffer[44100/50*2]; /* this is where the YM2612 samples will be mixed to */
} _940_data_t;
typedef struct
{
int job; /* a job for second core */
int busy; /* busy status of the 940 core */
int length; /* number of samples to mix (882 max) */
int stereo; /* mix samples as stereo, doubles sample count automatically */
int baseclock; /* ym2612 settings */
int rate;
int writebuffsel; /* which write buffer to use (from 940 side) */
UINT16 writebuff0[2048]; /* 1024 for savestates, 1024 extra */
UINT16 writebuff1[2048];
int vstarts[8]; /* debug: number of starts from each of 8 vectors */
int loopc; /* debug: main loop counter */
int waitc; /* debug: wait loop counter */
} _940_ctl_t;

191
platform/gp2x/Makefile Normal file
View file

@ -0,0 +1,191 @@
# you may or may not need to change this
#devkit_path = x:/stuff/dev/devkitgp2x/
devkit_path = /usr/local/devkitPro/devkitGP2X/
lgcc_path = $(devkit_path)lib/gcc/arm-linux/4.0.3/
CROSS = arm-linux-
#CROSS = $(devkit_path)bin/arm-linux-
# settings
dprint = 1
#mz80 = 1
#debug_cyclone = 1
asm_memory = 1
asm_render = 1
asm_ym2612 = 1
#profile = 1
#use_musashi = 1
#up = 1
DEFINC = -I../.. -I. -D__GP2X__ -D_UNZIP_SUPPORT # -DBENCHMARK
COPT_COMMON = -static -s -O3 -ftracer -fstrength-reduce -Wall -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math
ifeq "$(profile)" "1"
COPT_COMMON += -fprofile-generate
endif
ifeq "$(profile)" "2"
COPT_COMMON += -fprofile-use
endif
COPT = $(COPT_COMMON) -mtune=arm920t
ASOPT = -mcpu=arm920t -mfloat-abi=soft
GCC = $(CROSS)gcc
STRIP = $(CROSS)strip
AS = $(CROSS)as
LD = $(CROSS)ld
OBJCOPY = $(CROSS)objcopy
# frontend
OBJS += main.o menu.o gp2x.o usbjoy.o emu.o squidgehack.o asmutils.o cpuctrl.o
# 940 core control
OBJS += 940ctl_ym2612.o
# Pico
OBJS += ../../Pico/Area.o ../../Pico/Cart.o ../../Pico/Utils.o ../../Pico/Memory.o ../../Pico/Misc.o \
../../Pico/Pico.o ../../Pico/Sek.o ../../Pico/VideoPort.o ../../Pico/Draw2.o ../../Pico/Draw.o
# asm stuff
ifeq "$(asm_render)" "1"
DEFINC += -D_ASM_DRAW_C
OBJS += ../../Pico/draw_asm.o ../../Pico/draw2_asm.o
endif
ifeq "$(asm_memory)" "1"
DEFINC += -D_ASM_MEMORY_C
OBJS += ../../Pico/memory_asm.o
endif
ifeq "$(asm_ym2612)" "1"
DEFINC += -D_ASM_YM2612_C
OBJS += ../../Pico/sound/ym2612_asm.o
endif
# Pico - sound
OBJS += ../../Pico/sound/sound.o ../../Pico/sound/sn76496.o ../../Pico/sound/ym2612.o
# zlib
OBJS += ../../zlib/gzio.o ../../zlib/inffast.o ../../zlib/inflate.o ../../zlib/inftrees.o ../../zlib/trees.o \
../../zlib/deflate.o ../../zlib/crc32.o ../../zlib/adler32.o ../../zlib/zutil.o ../../zlib/compress.o
# unzip
OBJS += ../../unzip/unzip.o
# CPU cores
ifeq "$(use_musashi)" "1"
DEFINC += -DEMU_M68K
OBJS += _build\m68kcpu.o _build\m68kopac.o _build\m68kopdm.o _build\m68kopnz.o _build\m68kops.o
else
DEFINC += -DEMU_C68K
OBJS += ../../cpu/Cyclone/proj/Cyclone.o
endif
# drz80/mz80
ifeq "$(mz80)" "1"
DEFINC += -D_USE_MZ80
OBJS += ../../cpu/mz80/mz80.o
else
DEFINC += -D_USE_DRZ80
OBJS += ../../cpu/DrZ80/drz80.o
endif
all: PicoDrive.gpe code940.bin
PicoDrive.gpe : $(OBJS)
@echo $@
@$(GCC) $(COPT) $(OBJS) $(PRELIBS) -lm -o $@
@$(STRIP) $@
# @$(GCC) $(COPT) $(OBJS) $(PRELIBS) -lm -o PicoDrive_.gpe
# @gpecomp PicoDrive_.gpe $@
ifeq "$(up)" "1"
@cmd //C copy $@ \\\\10.0.1.2\\gp2x\\mnt\\sd\\games\\PicoDrive\\
endif
up: up940
@cmd //C copy PicoDrive.gpe \\\\10.0.1.2\\gp2x\\mnt\\sd\\games\\PicoDrive\\
up940:
@cmd //C copy code940.bin \\\\10.0.1.2\\gp2x\\mnt\\sd\\games\\PicoDrive\\
testrefr.gpe : test.o gp2x.o asmutils.o
@echo $@
@$(GCC) $(COPT) $^ $(PRELIBS) -o $@
@$(STRIP) $@
.c.o:
@echo $<
@$(GCC) $(COPT) $(DEFINC) -c $< -o $@
.s.o:
@echo $<
@$(GCC) $(COPT) $(DEFINC) -c $< -o $@
../../Pico/draw_asm.o : ../../Pico/Draw.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
../../Pico/draw2_asm.o : ../../Pico/Draw2.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
../../Pico/memory_asm.o : ../../Pico/Memory.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
../../Pico/sound/ym2612_asm.o : ../../Pico/sound/ym2612.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
# build Cyclone
../../cpu/Cyclone/proj/Cyclone.s :
@echo building Cyclone...
@make -C ../../cpu/Cyclone/proj -f Makefile.linux
# stuff for 940 core
# init, emu_control, emu
OBJS940 += 940init.o 940.o 940ym2612.o
# the asm code seems to be faster when run on 920, but not on 940 for some reason
# OBJS940 += ../../Pico/sound/ym2612_asm.o
# uClibc library code
OBJS940 += uClibc/memset.o uClibc/s_floor.o uClibc/e_pow.o uClibc/e_sqrt.o uClibc/s_fabs.o
OBJS940 += uClibc/s_scalbn.o uClibc/s_copysign.o uClibc/k_sin.o uClibc/k_cos.o uClibc/s_sin.o
OBJS940 += uClibc/e_rem_pio2.o uClibc/k_rem_pio2.o uClibc/e_log.o uClibc/wrappers.o
code940.bin : code940.gpe
@echo $@
@$(OBJCOPY) -O binary $< $@
code940.gpe : $(OBJS940)
@echo $@
@$(LD) -static -e code940 -Ttext 0x0 $^ -L$(lgcc_path) -lgcc -o $@
940ym2612.o : ../../Pico/sound/ym2612.c
@echo $@
@$(GCC) $(COPT_COMMON) -mtune=arm940t $(DEFINC) -DEXTERNAL_YM2612 -c $< -o $@
# cleanup
clean: clean_pd clean_940
tidy: tidy_pd tidy_940
clean_pd: tidy_pd
@$(RM) PicoDrive.gpe
tidy_pd:
@$(RM) $(OBJS)
# @make -C ../../cpu/Cyclone/proj -f Makefile.linux clean
clean_940: tidy_940
@$(RM) code940.bin
tidy_940:
@$(RM) code940.gpe $(OBJS940)
clean_prof:
find ../.. -name '*.gcno' -delete
find ../.. -name '*.gcda' -delete
# test
usbjoy.o : usbjoy.c
@echo $<
@$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@
../../Pico/Cart.o : ../../Pico/Cart.c
@echo $<
@$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@
../../zlib/trees.o : ../../zlib/trees.c
@echo $<
@$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@
uClibc/e_pow.o : uClibc/e_pow.c
@echo $<
@$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@
uClibc/e_sqrt.o : uClibc/e_sqrt.c
@echo $<
@$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@

12
platform/gp2x/asmutils.h Normal file
View file

@ -0,0 +1,12 @@
// (c) Copyright 2006 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
void vidConvCpyRGB32 (void *to, void *from, int pixels);
void vidConvCpyRGB32sh(void *to, void *from, int pixels);
void vidConvCpyRGB32hi(void *to, void *from, int pixels);
void vidCpyM2_40col(void *dest, void *src);
void vidCpyM2_32col(void *dest, void *src);
void vidCpyM2_32col_nobord(void *dest, void *src);
void spend_cycles(int c); // utility

210
platform/gp2x/asmutils.s Normal file
View file

@ -0,0 +1,210 @@
@ some color conversion and blitting routines
@ (c) Copyright 2006, notaz
@ All Rights Reserved
@ Convert 0000bbb0 ggg0rrr0 0000bbb0 ggg0rrr0
@ to 00000000 rrr00000 ggg00000 bbb00000 ...
@ lr = 0x00e000e0, out: r3=lower_pix, r2=higher_pix; trashes rin
@ if sh==2, r8=0x00404040 (sh!=0 destroys flags!)
.macro convRGB32_2 rin sh=0
and r2, lr, \rin, lsr #4 @ blue
and r3, \rin, lr
orr r2, r2, r3, lsl #8 @ g0b0g0b0
mov r3, r2, lsl #16 @ g0b00000
and \rin,lr, \rin, ror #12 @ 00r000r0 (reversed)
orr r3, r3, \rin, lsr #16 @ g0b000r0
.if \sh == 1
mov r3, r3, ror #17 @ shadow mode
.elseif \sh == 2
adds r3, r3, #0x40000000 @ green
orrcs r3, r3, #0xe0000000
mov r3, r3, ror #8
adds r3, r3, #0x40000000
orrcs r3, r3, #0xe0000000
mov r3, r3, ror #16
adds r3, r3, #0x40000000
orrcs r3, r3, #0xe0000000
mov r3, r3, ror #24
.else
mov r3, r3, ror #16 @ r3=low
.endif
orr r3, r3, r3, lsr #3
str r3, [r0], #4
mov r2, r2, lsr #16
orr r2, r2, \rin, lsl #16
.if \sh == 1
mov r2, r2, lsr #1
.elseif \sh == 2
mov r2, r2, ror #8
adds r2, r2, #0x40000000 @ blue
orrcs r2, r2, #0xe0000000
mov r2, r2, ror #8
adds r2, r2, #0x40000000
orrcs r2, r2, #0xe0000000
mov r2, r2, ror #8
adds r2, r2, #0x40000000
orrcs r2, r2, #0xe0000000
mov r2, r2, ror #8
.endif
orr r2, r2, r2, lsr #3
str r2, [r0], #4
.endm
.global vidConvCpyRGB32 @ void *to, void *from, int pixels
vidConvCpyRGB32:
stmfd sp!, {r4-r7,lr}
mov r12, r2, lsr #3 @ repeats
mov lr, #0x00e00000
orr lr, lr, #0x00e0
.loopRGB32:
subs r12, r12, #1
ldmia r1!, {r4-r7}
convRGB32_2 r4
convRGB32_2 r5
convRGB32_2 r6
convRGB32_2 r7
bgt .loopRGB32
ldmfd sp!, {r4-r7,lr}
bx lr
.global vidConvCpyRGB32sh @ void *to, void *from, int pixels
vidConvCpyRGB32sh:
stmfd sp!, {r4-r7,lr}
mov r12, r2, lsr #3 @ repeats
mov lr, #0x00e00000
orr lr, lr, #0x00e0
.loopRGB32sh:
subs r12, r12, #1
ldmia r1!, {r4-r7}
convRGB32_2 r4, 1
convRGB32_2 r5, 1
convRGB32_2 r6, 1
convRGB32_2 r7, 1
bgt .loopRGB32sh
ldmfd sp!, {r4-r7,lr}
bx lr
.global vidConvCpyRGB32hi @ void *to, void *from, int pixels
vidConvCpyRGB32hi:
stmfd sp!, {r4-r7,lr}
mov r12, r2, lsr #3 @ repeats
mov lr, #0x00e00000
orr lr, lr, #0x00e0
.loopRGB32hi:
ldmia r1!, {r4-r7}
convRGB32_2 r4, 2
convRGB32_2 r5, 2
convRGB32_2 r6, 2
convRGB32_2 r7, 2
subs r12, r12, #1
bgt .loopRGB32hi
ldmfd sp!, {r4-r7,lr}
bx lr
@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ mode2 blitter for 40 cols
.global vidCpyM2_40col @ void *dest, void *src
vidCpyM2_40col:
stmfd sp!, {r4-r6,lr}
mov r12, #224 @ lines
add r1, r1, #8
vidCpyM2_40_loop_out:
mov r6, #10
vidCpyM2_40_loop:
subs r6, r6, #1
ldmia r1!, {r2-r5}
stmia r0!, {r2-r5}
ldmia r1!, {r2-r5}
stmia r0!, {r2-r5}
bne vidCpyM2_40_loop
subs r12,r12,#1
add r1, r1, #8
bne vidCpyM2_40_loop_out
ldmfd sp!, {r4-r6,lr}
bx lr
@ mode2 blitter for 32 cols
.global vidCpyM2_32col @ void *dest, void *src
vidCpyM2_32col:
stmfd sp!, {r4-r6,lr}
mov r12, #224 @ lines
add r1, r1, #8
add r0, r0, #32
vidCpyM2_32_loop_out:
mov r6, #8
vidCpyM2_32_loop:
subs r6, r6, #1
ldmia r1!, {r2-r5}
stmia r0!, {r2-r5}
ldmia r1!, {r2-r5}
stmia r0!, {r2-r5}
bne vidCpyM2_32_loop
subs r12,r12,#1
add r0, r0, #64
add r1, r1, #8+64
bne vidCpyM2_32_loop_out
ldmfd sp!, {r4-r6,lr}
bx lr
@ mode2 blitter for 32 cols with no borders
.global vidCpyM2_32col_nobord @ void *dest, void *src
vidCpyM2_32col_nobord:
stmfd sp!, {r4-r6,lr}
mov r12, #224 @ lines
add r1, r1, #8
b vidCpyM2_32_loop_out
@ test
.global spend_cycles @ c
spend_cycles:
mov r0, r0, lsr #2 @ 4 cycles/iteration
sub r0, r0, #2 @ entry/exit/init
.sc_loop:
subs r0, r0, #1
bpl .sc_loop
bx lr

138
platform/gp2x/config.txt Normal file
View file

@ -0,0 +1,138 @@
As PicoDrive is multiplatform emulator, this is GP2X specific part of readme
about configuration.
Configuration
-------------
1. "Renderer"
8bit fast:
This enables alternative heavily optimized tile-based renderer, which renders
pixels not line-by-line (this is what accurate renderers do), but in 8x8 tiles,
which is much faster. But because of the way it works it can't render any
mid-frame image changes (raster effects), so it is useful only with some games.
Other two are accurate line-based renderers. The 8bit is faster but does not
run well with some games like Street Racer.
2. "Accurate timing"
This adds some more emulation precision, but slows the emulation down. Whithout
this option some games do not boot (Red Zone for example), others have sound
problems.
3. "Accurate sprites"
This option improves emulation of sprite priorities, it also enables emulation
of sprite collision bit. If you see one sprite being drawn incorrectly above
the other (often seen in Sonic 3D Blast), you can enable this to fix the problem.
This only works with the default renderer (see first option).
4. "Show FPS"
Self-explanatory. Format is XX/YY, where XX is the number of rendered frames and
YY is the number of emulated frames per second.
5. "Frameskip"
How many frames to skip rendering before displaying another.
"Auto" is recommended.
6. "Enable sound"
Does what it says. You must enable at least YM2612 or SN76496 (in advanced options,
see below) for this to make sense.
7. "Sound Quality"
Sound rate and stereo mode. If you want 44100Hz sound, it is recommended to enable
the second core (next option).
8. "Use ARM940 core for sound"
This option causes PicoDrive to use ARM940T core (GP2X's second CPU) for sound
(i.e. to generate YM2612 samples) to improve performance noticeably.
9. "6 button pad"
If you enable this, games will think that 6 button gamepad is connected. If you
go and reconfigure your keys, you will be able to bind X,Y,Z and mode actions.
10. "Genesis Region"
This option lets you force the game to think it is running on machine from the
specified region.
11. "Use SRAM savestates"
This will automatically read/write SRAM savestates for games which are using them.
SRAM is saved whenever you pause your game or exit the emulator.
12. "GP2X CPU clocks"
Here you can change clocks of both GP2X's CPUs. Larger values increase performance.
There is no separate option for the second CPU because both CPUs use the same clock
source. Setting this option to 200 will cause PicoDrive NOT to change GP2X's clocks
at all.
13. "[advanced options]"
Enters advanced options menu (see below).
14. "Save cfg as default"
If you save your config here it will be loaded on next ROM load, but only if there
is no game specific config saved (which will be loaded in that case).
15. "Save cfg for current game only"
Whenever you load current ROM again these settings will be loaded (squidgehack and
RAM settings will not take effect until emulator is restarted).
Advanced configuration
----------------------
Enter [advanced options] in config menu to see these options.
1. "Scale 32 column mode"
This enables hardware scaling for lower-res genesis mode (where width is
32 8-pixel tiles, instead of 40 in other mode).
2. "Gamma correction"
Alters image gamma through GP2X hardware. Larger values make image to look brighter,
lower - darker (default is 1.0).
3. "Emulate Z80"
Enables emulation of Z80 chip, which was mostly used to drive the other sound chips.
Some games do complex sync with it, so you must enable it even if you don't use
sound to be able to play them.
4. "Emulate YM2612 (FM)"
This enables emulation of six-channel FM sound synthesizer chip, which was used to
produce sound effects and music.
5. "Emulate SN76496 (PSG)"
This enables emulation of additional sound chip for additional effects.
Note: if you change sound settings AFTER loading a ROM, you may need to reset
game to get sound. This is because most games initialize sound chips on
startup, and this data is lost when sound chips are being enabled/disabled.
6. "gzip savestates"
This will always apply gzip compression on your savestates, allowing you to
save some space and load/save time.
7. "USB joy controls player X"
If you are able to use USB joysticks with your GP2X, this options selects which
player the joystick controls.
8. "Don't save config on exit"
This will disable config autowrite on exit (which might cause SD card corruption
according to DaveC).
9. "craigix's RAM timings"
This overclocks the GP2X RAM chips, but may cause instability. Recommended if you
use the second core for sound. Needs emulator restart to take effect.
See this thread:
http://www.gp32x.com/board/index.php?showtopic=32319
10. "squidgehack"
Well known way to improve the GP2X performance. You must restart the emulator
for the change of this option to take effect.
Key configuration
-----------------
When you select "Configure controls" from the menu, you enter a key configuration
mode, where you use SELECT to change an action, and then press a key you like to
bind to that action. You can press the same key again to unbind. Select "DONE"
action and press any key to finish.

156
platform/gp2x/cpuctrl.c Normal file
View file

@ -0,0 +1,156 @@
/* cpuctrl for GP2X
Copyright (C) 2005 Hermes/PS2Reality
the gamma-routine was provided by theoddbot
parts (c) Rlyehs Work & (C) 2006 god_at_hell
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <sys/mman.h>
#include <math.h>
#include "cpuctrl.h"
/* system registers */
static struct
{
unsigned short SYSCLKENREG,SYSCSETREG,FPLLVSETREG,DUALINT920,DUALINT940,DUALCTRL940,MEMTIMEX0,MEMTIMEX1;
}
system_reg;
static unsigned short dispclockdiv;
static volatile unsigned short *MEM_REG;
#define SYS_CLK_FREQ 7372800
void cpuctrl_init(void)
{
extern volatile unsigned short *gp2x_memregs; /* from minimal library rlyeh */
MEM_REG=&gp2x_memregs[0];
system_reg.SYSCSETREG=MEM_REG[0x91c>>1];
system_reg.FPLLVSETREG=MEM_REG[0x912>>1];
system_reg.SYSCLKENREG=MEM_REG[0x904>>1];
system_reg.DUALINT920=MEM_REG[0x3B40>>1];
system_reg.DUALINT940=MEM_REG[0x3B42>>1];
system_reg.DUALCTRL940=MEM_REG[0x3B48>>1];
system_reg.MEMTIMEX0=MEM_REG[0x3802>>1];
system_reg.MEMTIMEX1=MEM_REG[0x3804>>1];
dispclockdiv=MEM_REG[0x924>>1];
}
void cpuctrl_deinit(void)
{
MEM_REG[0x91c>>1]=system_reg.SYSCSETREG;
MEM_REG[0x910>>1]=system_reg.FPLLVSETREG;
MEM_REG[0x3B40>>1]=system_reg.DUALINT920;
MEM_REG[0x3B42>>1]=system_reg.DUALINT940;
MEM_REG[0x3B48>>1]=system_reg.DUALCTRL940;
MEM_REG[0x904>>1]=system_reg.SYSCLKENREG;
MEM_REG[0x924>>1]=dispclockdiv;
MEM_REG[0x3802>>1]=system_reg.MEMTIMEX0;
MEM_REG[0x3804>>1]=system_reg.MEMTIMEX1 /*| 0x9000*/;
}
void set_display_clock_div(unsigned div)
{
div=((div & 63) | 64)<<8;
MEM_REG[0x924>>1]=(MEM_REG[0x924>>1] & ~(255<<8)) | div;
}
void set_FCLK(unsigned MHZ)
{
unsigned v;
unsigned mdiv,pdiv=3,scale=0;
MHZ*=1000000;
mdiv=(MHZ*pdiv)/SYS_CLK_FREQ;
mdiv=((mdiv-8)<<8) & 0xff00;
pdiv=((pdiv-2)<<2) & 0xfc;
scale&=3;
v=mdiv | pdiv | scale;
MEM_REG[0x910>>1]=v;
}
void set_920_Div(unsigned short div)
{
unsigned short v;
v = MEM_REG[0x91c>>1] & (~0x3);
MEM_REG[0x91c>>1] = (div & 0x7) | v;
}
void set_DCLK_Div( unsigned short div )
{
unsigned short v;
v = (unsigned short)( MEM_REG[0x91c>>1] & (~(0x7 << 6)) );
MEM_REG[0x91c>>1] = ((div & 0x7) << 6) | v;
}
/*
void Disable_940(void)
{
MEM_REG[0x3B42>>1];
MEM_REG[0x3B42>>1]=0;
MEM_REG[0x3B46>>1]=0xffff;
MEM_REG[0x3B48>>1]|= (1 << 7);
MEM_REG[0x904>>1]&=0xfffe;
}
*/
void set_RAM_Timings(int tRC, int tRAS, int tWR, int tMRD, int tRFC, int tRP, int tRCD)
{
tRC -= 1; tRAS -= 1; tWR -= 1; tMRD -= 1; tRFC -= 1; tRP -= 1; tRCD -= 1; // ???
MEM_REG[0x3802>>1] = ((tMRD & 0xF) << 12) | ((tRFC & 0xF) << 8) | ((tRP & 0xF) << 4) | (tRCD & 0xF);
MEM_REG[0x3804>>1] = /*0x9000 |*/ ((tRC & 0xF) << 8) | ((tRAS & 0xF) << 4) | (tWR & 0xF);
}
/*
void gp2x_video_wait_vsync(void)
{
MEM_REG[0x2846>>1]=(MEM_REG[0x2846>>1] | 0x20) & ~2;
while(!(MEM_REG[0x2846>>1] & 2));
}
*/
void set_gamma(int g100)
{
float gamma = (float) g100 / 100;
int i;
//printf ("set gamma = %f\r\n",gamma);
gamma = 1/gamma;
//enable gamma
MEM_REG[0x2880>>1]&=~(1<<12);
MEM_REG[0x295C>>1]=0;
for(i=0; i<256; i++)
{
unsigned char g;
unsigned short s;
g =(unsigned char)(255.0*pow(i/255.0,gamma));
s = (g<<8) | g;
MEM_REG[0x295E>>1]= s;
MEM_REG[0x295E>>1]= g;
}
}

View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

16
platform/gp2x/cpuctrl.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef __CPUCTRL_H__
#define __CPUCTRL_H__
extern void cpuctrl_init(void); /* call this at first */
extern void save_system_regs(void); /* save some registers */
extern void cpuctrl_deinit(void);
extern void set_display_clock_div(unsigned div);
extern void set_FCLK(unsigned MHZ); /* adjust the clock frequency (in Mhz units) */
extern void set_920_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */
extern void set_DCLK_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */
//extern void Disable_940(void); /* 940t down */
//extern void gp2x_video_wait_vsync(void);
extern void set_RAM_Timings(int tRC, int tRAS, int tWR, int tMRD, int tRFC, int tRP, int tRCD);
extern void set_gamma(int g100);
#endif

1121
platform/gp2x/emu.c Normal file

File diff suppressed because it is too large Load diff

46
platform/gp2x/emu.h Normal file
View file

@ -0,0 +1,46 @@
// (c) Copyright 2006 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
// engine states
enum TPicoGameState {
PGS_Paused = 1,
PGS_Running,
PGS_Quit,
PGS_KeyConfig,
PGS_ReloadRom,
PGS_Menu,
};
typedef struct {
char lastRomFile[512];
int EmuOpt; // LSb->MSb: use_sram, show_fps, enable_sound, gzip_saves,
// squidgehack, save_cfg_on_exit, <unused>, 16_bit_mode
// craigix_ram, confirm_save
int PicoOpt; // used for config saving only, see Pico.h
int PsndRate; // ditto
int PicoRegion; // ditto
int Frameskip;
int CPUclock;
int KeyBinds[32];
int volume;
int gamma;
int JoyBinds[4][32];
} currentConfig_t;
extern char romFileName[];
extern int engineState;
extern currentConfig_t currentConfig;
int emu_ReloadRom(void);
void emu_Init(void);
void emu_Deinit(void);
int emu_SaveLoadGame(int load, int sram);
void emu_Loop(void);
void emu_ResetGame(void);
int emu_ReadConfig(int game);
int emu_WriteConfig(int game);

311
platform/gp2x/gp2x.c Normal file
View file

@ -0,0 +1,311 @@
/**
* All this is mostly based on rlyeh's minimal library.
* Copied here to review all his code and understand what's going on.
**/
/*
GP2X minimal library v0.A by rlyeh, (c) 2005. emulnation.info@rlyeh (swap it!)
Thanks to Squidge, Robster, snaff, Reesy and NK, for the help & previous work! :-)
License
=======
Free for non-commercial projects (it would be nice receiving a mail from you).
Other cases, ask me first.
GamePark Holdings is not allowed to use this library and/or use parts from it.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <fcntl.h>
#include <errno.h>
#include "gp2x.h"
#include "usbjoy.h"
volatile unsigned short *gp2x_memregs;
//static
volatile unsigned long *gp2x_memregl;
static void *gp2x_screens[4];
static int screensel = 0;
//static
int memdev = 0;
static int sounddev = 0, mixerdev = 0;
void *gp2x_screen;
#define FRAMEBUFF_ADDR0 0x4000000-640*480
#define FRAMEBUFF_ADDR1 0x4000000-640*480*2
#define FRAMEBUFF_ADDR2 0x4000000-640*480*3
#define FRAMEBUFF_ADDR3 0x4000000-640*480*4
static const int gp2x_screenaddrs[] = { FRAMEBUFF_ADDR0, FRAMEBUFF_ADDR1, FRAMEBUFF_ADDR2, FRAMEBUFF_ADDR3 };
/* video stuff */
void gp2x_video_flip(void)
{
unsigned int address = gp2x_screenaddrs[screensel&3];
/* test */
/* {
int i; char *p=gp2x_screen;
for (i=0; i < 240; i++) { memset(p+i*320, 0, 32); }
}*/
gp2x_memregs[0x290E>>1]=(unsigned short)(address);
gp2x_memregs[0x2910>>1]=(unsigned short)(address >> 16);
gp2x_memregs[0x2912>>1]=(unsigned short)(address);
gp2x_memregs[0x2914>>1]=(unsigned short)(address >> 16);
// jump to other buffer:
gp2x_screen = gp2x_screens[++screensel&3];
}
void gp2x_video_changemode(int bpp)
{
gp2x_memregs[0x28DA>>1]=(((bpp+1)/8)<<9)|0xAB; /*8/15/16/24bpp...*/
gp2x_memregs[0x290C>>1]=320*((bpp+1)/8); /*line width in bytes*/
gp2x_memset_all_buffers(0, 0, 640*480);
gp2x_video_flip();
}
void gp2x_video_setpalette(int *pal, int len)
{
unsigned short *g=(unsigned short *)pal;
volatile unsigned short *memreg = &gp2x_memregs[0x295A>>1];
gp2x_memregs[0x2958>>1] = 0;
len *= 2;
while(len--) *memreg=*g++;
}
// TV Compatible function //
void gp2x_video_RGB_setscaling(int W, int H)
{
float escalaw, escalah;
int bpp = (gp2x_memregs[0x28DA>>1]>>9)&0x3;
escalaw = 1024.0; // RGB Horiz LCD
escalah = 320.0; // RGB Vert LCD
if(gp2x_memregs[0x2800>>1]&0x100) //TV-Out
{
escalaw=489.0; // RGB Horiz TV (PAL, NTSC)
if (gp2x_memregs[0x2818>>1] == 287) //PAL
escalah=274.0; // RGB Vert TV PAL
else if (gp2x_memregs[0x2818>>1] == 239) //NTSC
escalah=331.0; // RGB Vert TV NTSC
}
// scale horizontal
gp2x_memregs[0x2906>>1]=(unsigned short)((float)escalaw *(W/320.0));
// scale vertical
gp2x_memregl[0x2908>>2]=(unsigned long)((float)escalah *bpp *(H/240.0));
}
/* LCD updates @ 80Hz? */
void gp2x_video_wait_vsync(void)
{
gp2x_memregs[0x2846>>1] = 0x20|2; //(gp2x_memregs[0x2846>>1] | 0x20) & ~2;
while(!(gp2x_memregs[0x2846>>1] & 2));// usleep(1);
}
void gp2x_memcpy_all_buffers(void *data, int offset, int len)
{
memcpy((char *)gp2x_screens[0] + offset, data, len);
memcpy((char *)gp2x_screens[1] + offset, data, len);
memcpy((char *)gp2x_screens[2] + offset, data, len);
memcpy((char *)gp2x_screens[3] + offset, data, len);
}
void gp2x_memset_all_buffers(int offset, int byte, int len)
{
memset((char *)gp2x_screens[0] + offset, byte, len);
memset((char *)gp2x_screens[1] + offset, byte, len);
memset((char *)gp2x_screens[2] + offset, byte, len);
memset((char *)gp2x_screens[3] + offset, byte, len);
}
unsigned long gp2x_joystick_read(int allow_usb_joy)
{
int i;
unsigned long value=(gp2x_memregs[0x1198>>1] & 0x00FF);
if(value==0xFD) value=0xFA;
if(value==0xF7) value=0xEB;
if(value==0xDF) value=0xAF;
if(value==0x7F) value=0xBE;
value = ~((gp2x_memregs[0x1184>>1] & 0xFF00) | value | (gp2x_memregs[0x1186>>1] << 16));
if (allow_usb_joy && num_of_joys > 0) {
// check the usb joy as well..
gp2x_usbjoy_update();
for (i = 0; i < num_of_joys; i++)
value |= gp2x_usbjoy_check(i);
}
return value;
}
static int s_oldrate = 0, s_oldbits = 0, s_oldstereo = 0;
void gp2x_start_sound(int rate, int bits, int stereo)
{
int frag = 0, bsize, buffers;
// if no settings change, we don't need to do anything
if (rate == s_oldrate && s_oldbits == bits && s_oldstereo == stereo) return;
if (sounddev > 0) close(sounddev);
sounddev = open("/dev/dsp", O_WRONLY|O_ASYNC);
if (sounddev == -1)
printf("open(\"/dev/dsp\") failed with %i\n", errno);
ioctl(sounddev, SNDCTL_DSP_SPEED, &rate);
ioctl(sounddev, SNDCTL_DSP_SETFMT, &bits);
ioctl(sounddev, SNDCTL_DSP_STEREO, &stereo);
// calculate buffer size
buffers = 16;
bsize = rate / 32;
if (rate > 22050) { bsize*=4; buffers*=2; } // 44k mode seems to be very demanding
while ((bsize>>=1)) frag++;
frag |= buffers<<16; // 16 buffers
ioctl(sounddev, SNDCTL_DSP_SETFRAGMENT, &frag);
printf("gp2x_set_sound: %i/%ibit/%s, %i buffers of %i bytes\n",
rate, bits, stereo?"stereo":"mono", frag>>16, 1<<(frag&0xffff));
s_oldrate = rate; s_oldbits = bits; s_oldstereo = stereo;
usleep(100000);
}
void gp2x_sound_write(void *buff, int len)
{
write(sounddev, buff, len);
}
void gp2x_sound_volume(int l, int r)
{
l=l<0?0:l; l=l>255?255:l; r=r<0?0:r; r=r>255?255:r;
l<<=8; l|=r;
ioctl(mixerdev, SOUND_MIXER_WRITE_PCM, &l); /*SOUND_MIXER_WRITE_VOLUME*/
}
/* 940 */
void Pause940(int yes)
{
if(yes)
gp2x_memregs[0x0904>>1] &= 0xFFFE;
else
gp2x_memregs[0x0904>>1] |= 1;
}
void Reset940(int yes)
{
gp2x_memregs[0x3B48>>1] = ((yes&1) << 7) | (0x03); /* bank=3 */
}
/* common */
void gp2x_init(void)
{
printf("entering init()\n"); fflush(stdout);
memdev = open("/dev/mem", O_RDWR);
if (memdev == -1)
{
printf("open(\"/dev/mem\") failed with %i\n", errno);
exit(1);
}
gp2x_memregs = mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000);
printf("memregs are @ %p\n", gp2x_memregs);
if(gp2x_memregs == MAP_FAILED)
{
printf("mmap(memregs) failed with %i\n", errno);
exit(1);
}
gp2x_memregl = (unsigned long *) gp2x_memregs;
gp2x_screens[3] = mmap(0, 640*480*4, PROT_WRITE, MAP_SHARED, memdev, FRAMEBUFF_ADDR3);
if(gp2x_screens[3] == MAP_FAILED)
{
printf("mmap(gp2x_screen) failed with %i\n", errno);
exit(1);
}
printf("framebuffers point to %p\n", gp2x_screens[3]);
gp2x_screens[2] = (char *) gp2x_screens[3]+640*480;
gp2x_screens[1] = (char *) gp2x_screens[2]+640*480;
gp2x_screens[0] = (char *) gp2x_screens[1]+640*480;
gp2x_screen = gp2x_screens[0];
screensel = 0;
// snd
mixerdev = open("/dev/mixer", O_RDWR);
if (mixerdev == -1)
printf("open(\"/dev/mixer\") failed with %i\n", errno);
/* init usb joys -GnoStiC */
gp2x_usbjoy_init();
printf("exitting init()\n"); fflush(stdout);
}
char *ext_menu = 0, *ext_state = 0;
void gp2x_deinit(void)
{
Reset940(1);
Pause940(1);
gp2x_video_changemode(15);
munmap(gp2x_screens[0], 640*480*4);
munmap((void *)gp2x_memregs, 0x10000);
close(memdev);
close(mixerdev);
if (sounddev > 0) close(sounddev);
gp2x_usbjoy_deinit();
printf("all done, running ");
// Zaq121's alternative frontend support from MAME
if(ext_menu && ext_state) {
printf("%s -state %s\n", ext_menu, ext_state);
execl(ext_menu, ext_menu, "-state", ext_state, NULL);
} else if(ext_menu) {
printf("%s\n", ext_menu);
execl(ext_menu, ext_menu, NULL);
} else {
printf("gp2xmenu\n");
chdir("/usr/gp2x");
execl("gp2xmenu", "gp2xmenu", NULL);
}
}

40
platform/gp2x/gp2x.h Normal file
View file

@ -0,0 +1,40 @@
#ifndef __GP2X_H__
#define __GP2X_H__
void gp2x_init(void);
void gp2x_deinit(void);
/* video */
void gp2x_video_flip(void);
void gp2x_video_changemode(int bpp);
void gp2x_video_setpalette(int *pal, int len);
void gp2x_video_RGB_setscaling(int W, int H);
void gp2x_video_wait_vsync(void);
void gp2x_memcpy_all_buffers(void *data, int offset, int len);
void gp2x_memset_all_buffers(int offset, int byte, int len);
/* sound */
void gp2x_start_sound(int rate, int bits, int stereo);
void gp2x_sound_write(void *buff, int len);
void gp2x_sound_volume(int l, int r);
/* joy */
unsigned long gp2x_joystick_read(int allow_usb_joy);
/* 940 core */
void Pause940(int yes);
void Reset940(int yes);
extern void *gp2x_screen;
extern int memdev;
enum { GP2X_UP=0x1, GP2X_LEFT=0x4, GP2X_DOWN=0x10, GP2X_RIGHT=0x40,
GP2X_START=1<<8, GP2X_SELECT=1<<9, GP2X_L=1<<10, GP2X_R=1<<11,
GP2X_A=1<<12, GP2X_B=1<<13, GP2X_X=1<<14, GP2X_Y=1<<15,
GP2X_VOL_UP=1<<23, GP2X_VOL_DOWN=1<<22, GP2X_PUSH=1<<27 };
#endif

143
platform/gp2x/main.c Normal file
View file

@ -0,0 +1,143 @@
// (c) Copyright 2006 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <strings.h>
#include <linux/limits.h>
#include "gp2x.h"
#include "menu.h"
#include "emu.h"
#include "version.h"
#include "squidgehack.h"
#include "cpuctrl.h"
extern char *ext_menu, *ext_state;
extern int select_exits;
extern char *PicoConfigFile;
int mmuhack_status = 0;
char **g_argv;
void parse_cmd_line(int argc, char *argv[])
{
int x, unrecognized = 0;
for(x = 1; x < argc; x++)
{
if(argv[x][0] == '-')
{
if(strcasecmp(argv[x], "-menu") == 0) {
if(x+1 < argc) { ++x; ext_menu = argv[x]; } /* External Frontend: Program Name */
}
else if(strcasecmp(argv[x], "-state") == 0) {
if(x+1 < argc) { ++x; ext_state = argv[x]; } /* External Frontend: Arguments */
}
else if(strcasecmp(argv[x], "-config") == 0) {
if(x+1 < argc) { ++x; PicoConfigFile = argv[x]; }
}
else if(strcasecmp(argv[x], "-selectexit") == 0) {
select_exits = 1;
}
else {
unrecognized = 1;
break;
}
} else {
/* External Frontend: ROM Name */
FILE *f;
strncpy(romFileName, argv[x], PATH_MAX);
romFileName[PATH_MAX-1] = 0;
f = fopen(romFileName, "rb");
if (f) fclose(f);
else unrecognized = 1;
engineState = PGS_ReloadRom;
break;
}
}
if (unrecognized) {
printf("\n\n\nPicoDrive v" VERSION " (c) notaz, 2006\n");
printf("usage: %s [options] [romfile]\n", argv[0]);
printf( "options:\n"
"-menu <menu_path> launch a custom program on exit instead of default gp2xmenu\n"
"-state <param> pass '-state param' to the menu program\n"
"-config <file> use specified config file instead of default 'picoconfig.bin'\n"
" see currentConfig_t structure in emu.h for the file format\n"
"-selectexit pressing SELECT will exit the emu and start 'menu_path'\n");
}
}
int main(int argc, char *argv[])
{
g_argv = argv;
emu_ReadConfig(0);
gp2x_init();
if (currentConfig.EmuOpt&0x10) {
int ret = mmuhack();
printf("squidge hack code finished and returned %i\n", ret); fflush(stdout);
mmuhack_status = ret;
}
cpuctrl_init();
Reset940(1);
Pause940(1);
if (currentConfig.EmuOpt&0x100) {
printf("setting RAM timings.. "); fflush(stdout);
// craigix: --trc 6 --tras 4 --twr 1 --tmrd 1 --trfc 1 --trp 2 --trcd 2
set_RAM_Timings(6, 4, 1, 1, 1, 2, 2);
printf("done.\n"); fflush(stdout);
}
emu_Init();
engineState = PGS_Menu;
if (argc > 1)
parse_cmd_line(argc, argv);
for (;;)
{
switch (engineState)
{
case PGS_Menu:
menu_loop();
break;
case PGS_ReloadRom:
if (emu_ReloadRom())
engineState = PGS_Running;
else {
printf("PGS_ReloadRom == 0\n");
engineState = PGS_Menu;
}
break;
case PGS_Running:
emu_Loop();
break;
case PGS_Quit:
goto endloop;
default:
printf("engine got into unknown state (%i), exitting\n", engineState);
goto endloop;
}
}
endloop:
emu_Deinit();
cpuctrl_deinit();
gp2x_deinit();
if(mmuhack_status)
mmuunhack();
return 0;
}

992
platform/gp2x/menu.c Normal file
View file

@ -0,0 +1,992 @@
// (c) Copyright 2006 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <dirent.h>
#include "gp2x.h"
#include "emu.h"
#include "menu.h"
#include "usbjoy.h"
#include "version.h"
#include "Pico/PicoInt.h"
#ifndef _DIRENT_HAVE_D_TYPE
#error "need d_type for file browser
#endif
extern char *actionNames[];
extern char romFileName[PATH_MAX];
extern char *rom_data;
extern int mmuhack_status;
extern int state_slot;
static char *gp2xKeyNames[] = {
"UP", "???", "LEFT", "???", "DOWN", "???", "RIGHT", "???",
"START", "SELECT", "L", "R", "A", "B", "X", "Y",
"???", "???", "???", "???", "???", "???", "VOL DOWN", "VOL UP",
"???", "???", "???", "PUSH", "???", "???", "???", "???"
};
char menuErrorMsg[40] = {0, };
static unsigned char fontdata8x8[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x3C,0x42,0x99,0xBD,0xBD,0x99,0x42,0x3C,0x3C,0x42,0x81,0x81,0x81,0x81,0x42,0x3C,
0xFE,0x82,0x8A,0xD2,0xA2,0x82,0xFE,0x00,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x64,0x74,0x7C,0x38,0x00,0x00,
0x80,0xC0,0xF0,0xFC,0xF0,0xC0,0x80,0x00,0x01,0x03,0x0F,0x3F,0x0F,0x03,0x01,0x00,
0x18,0x3C,0x7E,0x18,0x7E,0x3C,0x18,0x00,0xEE,0xEE,0xEE,0xCC,0x00,0xCC,0xCC,0x00,
0x00,0x00,0x30,0x68,0x78,0x30,0x00,0x00,0x00,0x38,0x64,0x74,0x7C,0x38,0x00,0x00,
0x3C,0x66,0x7A,0x7A,0x7E,0x7E,0x3C,0x00,0x0E,0x3E,0x3A,0x22,0x26,0x6E,0xE4,0x40,
0x18,0x3C,0x7E,0x3C,0x3C,0x3C,0x3C,0x00,0x3C,0x3C,0x3C,0x3C,0x7E,0x3C,0x18,0x00,
0x08,0x7C,0x7E,0x7E,0x7C,0x08,0x00,0x00,0x10,0x3E,0x7E,0x7E,0x3E,0x10,0x00,0x00,
0x58,0x2A,0xDC,0xC8,0xDC,0x2A,0x58,0x00,0x24,0x66,0xFF,0xFF,0x66,0x24,0x00,0x00,
0x00,0x10,0x10,0x38,0x38,0x7C,0xFE,0x00,0xFE,0x7C,0x38,0x38,0x10,0x10,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x18,0x00,0x18,0x18,0x00,
0x6C,0x6C,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x7C,0x28,0x7C,0x28,0x00,0x00,
0x10,0x38,0x60,0x38,0x0C,0x78,0x10,0x00,0x40,0xA4,0x48,0x10,0x24,0x4A,0x04,0x00,
0x18,0x34,0x18,0x3A,0x6C,0x66,0x3A,0x00,0x18,0x18,0x20,0x00,0x00,0x00,0x00,0x00,
0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x00,0x0C,0x06,0x06,0x06,0x06,0x06,0x0C,0x00,
0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,
0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x00,0x00,
0x38,0x4C,0xC6,0xC6,0xC6,0x64,0x38,0x00,0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00,
0x7C,0xC6,0x0E,0x3C,0x78,0xE0,0xFE,0x00,0x7E,0x0C,0x18,0x3C,0x06,0xC6,0x7C,0x00,
0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x00,0xFC,0xC0,0xFC,0x06,0x06,0xC6,0x7C,0x00,
0x3C,0x60,0xC0,0xFC,0xC6,0xC6,0x7C,0x00,0xFE,0xC6,0x0C,0x18,0x30,0x30,0x30,0x00,
0x78,0xC4,0xE4,0x78,0x86,0x86,0x7C,0x00,0x7C,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00,
0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x18,0x18,0x30,
0x1C,0x38,0x70,0xE0,0x70,0x38,0x1C,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,
0x70,0x38,0x1C,0x0E,0x1C,0x38,0x70,0x00,0x7C,0xC6,0xC6,0x1C,0x18,0x00,0x18,0x00,
0x3C,0x42,0x99,0xA1,0xA5,0x99,0x42,0x3C,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00,
0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00,0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00,
0xF8,0xCC,0xC6,0xC6,0xC6,0xCC,0xF8,0x00,0xFE,0xC0,0xC0,0xFC,0xC0,0xC0,0xFE,0x00,
0xFE,0xC0,0xC0,0xFC,0xC0,0xC0,0xC0,0x00,0x3E,0x60,0xC0,0xCE,0xC6,0x66,0x3E,0x00,
0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,
0x06,0x06,0x06,0x06,0xC6,0xC6,0x7C,0x00,0xC6,0xCC,0xD8,0xF0,0xF8,0xDC,0xCE,0x00,
0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0x00,
0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
0xFC,0xC6,0xC6,0xC6,0xFC,0xC0,0xC0,0x00,0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x7A,0x00,
0xFC,0xC6,0xC6,0xCE,0xF8,0xDC,0xCE,0x00,0x78,0xCC,0xC0,0x7C,0x06,0xC6,0x7C,0x00,
0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
0xC6,0xC6,0xC6,0xEE,0x7C,0x38,0x10,0x00,0xC6,0xC6,0xD6,0xFE,0xFE,0xEE,0xC6,0x00,
0xC6,0xEE,0x3C,0x38,0x7C,0xEE,0xC6,0x00,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00,
0xFE,0x0E,0x1C,0x38,0x70,0xE0,0xFE,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,
0x60,0x60,0x30,0x18,0x0C,0x06,0x06,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,
0x18,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,
0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x3E,0x66,0x66,0x3C,0x00,
0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x00,
0x06,0x3E,0x66,0x66,0x66,0x66,0x3E,0x00,0x00,0x3C,0x66,0x66,0x7E,0x60,0x3C,0x00,
0x1C,0x30,0x78,0x30,0x30,0x30,0x30,0x00,0x00,0x3E,0x66,0x66,0x66,0x3E,0x06,0x3C,
0x60,0x7C,0x76,0x66,0x66,0x66,0x66,0x00,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x00,
0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x38,0x60,0x60,0x66,0x6C,0x78,0x6C,0x66,0x00,
0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0xEC,0xFE,0xFE,0xFE,0xD6,0xC6,0x00,
0x00,0x7C,0x76,0x66,0x66,0x66,0x66,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00,
0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60,0x00,0x3E,0x66,0x66,0x66,0x3E,0x06,0x06,
0x00,0x7E,0x70,0x60,0x60,0x60,0x60,0x00,0x00,0x3C,0x60,0x3C,0x06,0x66,0x3C,0x00,
0x30,0x78,0x30,0x30,0x30,0x30,0x1C,0x00,0x00,0x66,0x66,0x66,0x66,0x6E,0x3E,0x00,
0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0xC6,0xD6,0xFE,0xFE,0x7C,0x6C,0x00,
0x00,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,0x00,0x66,0x66,0x66,0x66,0x3E,0x06,0x3C,
0x00,0x7E,0x0C,0x18,0x30,0x60,0x7E,0x00,0x0E,0x18,0x0C,0x38,0x0C,0x18,0x0E,0x00,
0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x70,0x18,0x30,0x1C,0x30,0x18,0x70,0x00,
0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x10,0x28,0x10,0x54,0xAA,0x44,0x00,0x00,
};
static void gp2x_text(unsigned char *screen, int x, int y, char *text, int color)
{
int i,l;
screen = screen + x + y*320;
for (i = 0; i < strlen(text); i++)
{
for (l=0;l<8;l++)
{
if(fontdata8x8[((text[i])*8)+l]&0x80) screen[l*320+0]=color;
if(fontdata8x8[((text[i])*8)+l]&0x40) screen[l*320+1]=color;
if(fontdata8x8[((text[i])*8)+l]&0x20) screen[l*320+2]=color;
if(fontdata8x8[((text[i])*8)+l]&0x10) screen[l*320+3]=color;
if(fontdata8x8[((text[i])*8)+l]&0x08) screen[l*320+4]=color;
if(fontdata8x8[((text[i])*8)+l]&0x04) screen[l*320+5]=color;
if(fontdata8x8[((text[i])*8)+l]&0x02) screen[l*320+6]=color;
if(fontdata8x8[((text[i])*8)+l]&0x01) screen[l*320+7]=color;
}
screen += 8;
}
}
// draws white text to current bbp15 screen
void gp2x_text_out15(int x, int y, char *text)
{
int i,l;
unsigned short *screen = gp2x_screen;
screen = screen + x + y*320;
for (i = 0; i < strlen(text); i++)
{
for (l=0;l<8;l++)
{
if(fontdata8x8[((text[i])*8)+l]&0x80) screen[l*320+0]=0xffff;
if(fontdata8x8[((text[i])*8)+l]&0x40) screen[l*320+1]=0xffff;
if(fontdata8x8[((text[i])*8)+l]&0x20) screen[l*320+2]=0xffff;
if(fontdata8x8[((text[i])*8)+l]&0x10) screen[l*320+3]=0xffff;
if(fontdata8x8[((text[i])*8)+l]&0x08) screen[l*320+4]=0xffff;
if(fontdata8x8[((text[i])*8)+l]&0x04) screen[l*320+5]=0xffff;
if(fontdata8x8[((text[i])*8)+l]&0x02) screen[l*320+6]=0xffff;
if(fontdata8x8[((text[i])*8)+l]&0x01) screen[l*320+7]=0xffff;
}
screen += 8;
}
}
void gp2x_text_out8(int x, int y, char *texto, ...)
{
va_list args;
char buffer[512];
va_start(args,texto);
vsprintf(buffer,texto,args);
va_end(args);
gp2x_text(gp2x_screen,x,y,buffer,1);
}
void gp2x_text_out8_2(int x, int y, char *texto, int color)
{
gp2x_text(gp2x_screen, x, y, texto, color);
}
void gp2x_text_out8_lim(int x, int y, char *texto, int max)
{
char buffer[320/8+1];
strncpy(buffer, texto, 320/8);
if (max > 320/8) max = 320/8;
if (max < 0) max = 0;
buffer[max] = 0;
gp2x_text(gp2x_screen,x,y,buffer,1);
}
static unsigned long inp_prev = 0;
static int inp_prevjoy = 0;
static unsigned long wait_for_input(unsigned long interesting)
{
unsigned long ret;
static int repeats = 0, wait = 300*1000;
int release = 0, i;
if (repeats == 5 || repeats == 15 || repeats == 30) wait /= 2;
for (i = 0; i < 6 && inp_prev == gp2x_joystick_read(1); i++) {
if(i == 0) repeats++;
usleep(wait/6);
}
while ( !((ret = gp2x_joystick_read(1)) & interesting) ) {
usleep(50000);
release = 1;
}
if (release || ret != inp_prev) {
repeats = 0;
wait = 300*1000;
}
inp_prev = ret;
inp_prevjoy = 0;
// we don't need diagonals in menus
if ((ret&GP2X_UP) && (ret&GP2X_LEFT)) ret &= ~GP2X_LEFT;
if ((ret&GP2X_UP) && (ret&GP2X_RIGHT)) ret &= ~GP2X_RIGHT;
if ((ret&GP2X_DOWN) && (ret&GP2X_LEFT)) ret &= ~GP2X_LEFT;
if ((ret&GP2X_DOWN) && (ret&GP2X_RIGHT)) ret &= ~GP2X_RIGHT;
return ret;
}
static unsigned long input2_read(unsigned long interesting, int *joy)
{
unsigned long ret;
int i;
do
{
*joy = 0;
if ((ret = gp2x_joystick_read(0) & interesting)) break;
gp2x_usbjoy_update();
for (i = 0; i < num_of_joys; i++) {
ret = gp2x_usbjoy_check2(i);
if (ret) { *joy = i + 1; break; }
}
if (ret) break;
}
while(0);
return ret;
}
// similar to wait_for_input(), but returns joy num
static unsigned long wait_for_input_usbjoy(unsigned long interesting, int *joy)
{
unsigned long ret;
const int wait = 300*1000;
int i;
if (inp_prevjoy == 0) inp_prev &= interesting;
for (i = 0; i < 6; i++) {
ret = input2_read(interesting, joy);
if (*joy != inp_prevjoy || ret != inp_prev) break;
usleep(wait/6);
}
while ( !(ret = input2_read(interesting, joy)) ) {
usleep(50000);
}
inp_prev = ret;
inp_prevjoy = *joy;
return ret;
}
// -------------- ROM selector --------------
static void draw_dirlist(char *curdir, struct dirent **namelist, int n, int sel)
{
int start, i, pos;
start = 12 - sel;
n--; // exclude current dir (".")
memset(gp2x_screen, 0, 320*240);
if(start - 2 >= 0)
gp2x_text_out8_lim(14, (start - 2)*10, curdir, 38);
for (i = 0; i < n; i++) {
pos = start + i;
if (pos < 0) continue;
if (pos > 23) break;
if (namelist[i+1]->d_type == DT_DIR) {
gp2x_text_out8_lim(14, pos*10, "/", 1);
gp2x_text_out8_lim(14+8, pos*10, namelist[i+1]->d_name, 37);
} else {
gp2x_text_out8_lim(14, pos*10, namelist[i+1]->d_name, 38);
}
}
gp2x_text_out8(5, 120, ">");
gp2x_video_flip();
}
static int scandir_cmp(const void *p1, const void *p2)
{
struct dirent **d1 = (struct dirent **)p1, **d2 = (struct dirent **)p2;
if ((*d1)->d_type == (*d2)->d_type) return alphasort(d1, d2);
if ((*d1)->d_type == DT_DIR) return -1; // put before
if ((*d2)->d_type == DT_DIR) return 1;
return alphasort(d1, d2);
}
static char *romsel_loop(char *curr_path)
{
struct dirent **namelist;
DIR *dir;
int n, sel = 0;
unsigned long inp = 0;
char *ret = NULL, *fname = NULL;
// is this a dir or a full path?
if ((dir = opendir(curr_path))) {
closedir(dir);
} else {
char *p;
for (p = curr_path + strlen(curr_path) - 1; p > curr_path && *p != '/'; p--);
*p = 0;
fname = p+1;
}
n = scandir(curr_path, &namelist, 0, scandir_cmp);
if (n < 0) {
// try root
n = scandir(curr_path, &namelist, 0, scandir_cmp);
if (n < 0) {
// oops, we failed
printf("dir: "); printf(curr_path); printf("\n");
perror("scandir");
return NULL;
}
}
// try to find sel
if (fname != NULL) {
int i;
for (i = 1; i < n; i++) {
if (strcmp(namelist[i]->d_name, fname) == 0) {
sel = i - 1;
break;
}
}
}
for (;;)
{
draw_dirlist(curr_path, namelist, n, sel);
inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT|GP2X_B|GP2X_X);
if(inp & GP2X_UP ) { sel--; if (sel < 0) sel = n-2; }
if(inp & GP2X_DOWN) { sel++; if (sel > n-2) sel = 0; }
if(inp & GP2X_LEFT) { sel-=10; if (sel < 0) sel = 0; }
if(inp & GP2X_RIGHT) { sel+=10; if (sel > n-2) sel = n-2; }
if(inp & GP2X_B) { // enter dir/select
again:
if (namelist[sel+1]->d_type == DT_REG) {
strcpy(romFileName, curr_path);
strcat(romFileName, "/");
strcat(romFileName, namelist[sel+1]->d_name);
ret = romFileName;
break;
} else if (namelist[sel+1]->d_type == DT_DIR) {
int newlen = strlen(curr_path) + strlen(namelist[sel+1]->d_name) + 2;
char *p, *newdir = malloc(newlen);
if (strcmp(namelist[sel+1]->d_name, "..") == 0) {
char *start = curr_path;
p = start + strlen(start) - 1;
while (*p == '/' && p > start) p--;
while (*p != '/' && p > start) p--;
if (p <= start) strcpy(newdir, "/");
else { strncpy(newdir, start, p-start); newdir[p-start] = 0; }
} else {
strcpy(newdir, curr_path);
p = newdir + strlen(newdir) - 1;
while (*p == '/' && p >= newdir) *p-- = 0;
strcat(newdir, "/");
strcat(newdir, namelist[sel+1]->d_name);
}
ret = romsel_loop(newdir);
free(newdir);
break;
} else {
// unknown file type, happens on NTFS mounts. Try to guess.
FILE *tstf; int tmp;
strcpy(romFileName, curr_path);
strcat(romFileName, "/");
strcat(romFileName, namelist[sel+1]->d_name);
tstf = fopen(romFileName, "rb");
if (tstf != NULL)
{
if (fread(&tmp, 1, 1, tstf) > 0 || ferror(tstf) == 0)
namelist[sel+1]->d_type = DT_REG;
else namelist[sel+1]->d_type = DT_DIR;
fclose(tstf);
goto again;
}
}
}
if(inp & GP2X_X) break; // cancel
}
if (n > 0) {
while(n--) free(namelist[n]);
free(namelist);
}
return ret;
}
// -------------- key config --------------
static char *usb_joy_key_name(int joy, int num)
{
static char name[16];
switch (num)
{
case 0: sprintf(name, "Joy%i UP", joy); break;
case 1: sprintf(name, "Joy%i DOWN", joy); break;
case 2: sprintf(name, "Joy%i LEFT", joy); break;
case 3: sprintf(name, "Joy%i RIGHT", joy); break;
default:sprintf(name, "Joy%i b%i", joy, num-3); break;
}
return name;
}
static void draw_key_config(int curr_act, int is_p2)
{
char strkeys[32*5];
int joy, i;
strkeys[0] = 0;
for (i = 0; i < 32; i++)
{
if (currentConfig.KeyBinds[i] & (1 << curr_act))
{
if (curr_act < 16 && (currentConfig.KeyBinds[i] & (1 << 16)) != (is_p2 << 16)) continue;
if (strkeys[0]) { strcat(strkeys, " + "); strcat(strkeys, gp2xKeyNames[i]); break; }
else strcpy(strkeys, gp2xKeyNames[i]);
}
}
for (joy = 0; joy < num_of_joys; joy++)
{
for (i = 0; i < 32; i++)
{
if (currentConfig.JoyBinds[joy][i] & (1 << curr_act))
{
if (curr_act < 16 && (currentConfig.JoyBinds[joy][i] & (1 << 16)) != (is_p2 << 16)) continue;
if (strkeys[0]) {
strcat(strkeys, ", "); strcat(strkeys, usb_joy_key_name(joy + 1, i));
break;
}
else strcpy(strkeys, usb_joy_key_name(joy + 1, i));
}
}
}
memset(gp2x_screen, 0, 320*240);
gp2x_text_out8(60, 40, "Action: %s", actionNames[curr_act]);
gp2x_text_out8(60, 60, "Keys: %s", strkeys);
gp2x_text_out8(30, 180, "Use SELECT to change action");
gp2x_text_out8(30, 190, "Press a key to bind/unbind");
gp2x_text_out8(30, 200, "Select \"Done\" action and");
gp2x_text_out8(30, 210, " press any key to finish");
gp2x_video_flip();
}
static void key_config_loop(int is_p2)
{
int curr_act = 0, joy = 0, i;
unsigned long inp = 0;
for (;;)
{
draw_key_config(curr_act, is_p2);
inp = wait_for_input_usbjoy(CONFIGURABLE_KEYS, &joy);
// printf("got %08lX from joy %i\n", inp, joy);
if (joy == 0) {
if (inp & GP2X_SELECT) {
curr_act++;
while (!actionNames[curr_act] && curr_act < 32) curr_act++;
if (curr_act > 31) curr_act = 0;
}
inp &= CONFIGURABLE_KEYS;
inp &= ~GP2X_SELECT;
}
if (curr_act == 31 && inp) break;
if (joy == 0) {
for (i = 0; i < 32; i++)
if (inp & (1 << i)) {
currentConfig.KeyBinds[i] ^= (1 << curr_act);
if (is_p2) currentConfig.KeyBinds[i] |= (1 << 16); // player 2 flag
else currentConfig.KeyBinds[i] &= ~(1 << 16);
}
} else {
for (i = 0; i < 32; i++)
if (inp & (1 << i)) {
currentConfig.JoyBinds[joy-1][i] ^= (1 << curr_act);
if (is_p2) currentConfig.JoyBinds[joy-1][i] |= (1 << 16);
else currentConfig.JoyBinds[joy-1][i] &= ~(1 << 16);
}
}
}
}
static void draw_kc_sel(int menu_sel)
{
int tl_x = 25+40, tl_y = 60, y, i;
char joyname[36];
y = tl_y;
memset(gp2x_screen, 0, 320*240);
gp2x_text_out8(tl_x, y, "Player 1");
gp2x_text_out8(tl_x, (y+=10), "Player 2");
gp2x_text_out8(tl_x, (y+=10), "Done");
// draw cursor
gp2x_text_out8(tl_x - 16, tl_y + menu_sel*10, ">");
tl_x = 25;
gp2x_text_out8(tl_x, (y=110), "USB joys detected:");
if (num_of_joys > 0) {
for (i = 0; i < num_of_joys; i++) {
strncpy(joyname, joy_name(joys[i]), 33); joyname[33] = 0;
gp2x_text_out8(tl_x, (y+=10), "%i: %s", i+1, joyname);
}
} else {
gp2x_text_out8(tl_x, (y+=10), "none");
}
gp2x_video_flip();
}
static void kc_sel_loop(void)
{
int menu_sel = 2, menu_sel_max = 2;
unsigned long inp = 0;
for(;;)
{
draw_kc_sel(menu_sel);
inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_B|GP2X_X);
if(inp & GP2X_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; }
if(inp & GP2X_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; }
if(inp & GP2X_B) {
switch (menu_sel) {
case 0: key_config_loop(0); return;
case 1: key_config_loop(1); return;
default: return;
}
}
if(inp & GP2X_X) return;
}
}
// --------- advanced options ----------
// order must match that of currentConfig_t
struct {
int EmuOpt;
int PicoOpt;
int PsndRate;
int PicoRegion;
int Frameskip;
int CPUclock;
} tmp_opts;
int tmp_gamma;
static void draw_amenu_options(int menu_sel)
{
int tl_x = 25, tl_y = 60, y;
char *mms = mmuhack_status ? "active) " : "inactive)";
y = tl_y;
memset(gp2x_screen, 0, 320*240);
gp2x_text_out8(tl_x, y, "Scale 32 column mode %s", (tmp_opts.PicoOpt&0x100)?"ON":"OFF"); // 0
gp2x_text_out8(tl_x, (y+=10), "Gamma correction %i.%02i", tmp_gamma / 100, tmp_gamma%100); // 1
gp2x_text_out8(tl_x, (y+=10), "Emulate Z80 %s", (tmp_opts.PicoOpt&0x004)?"ON":"OFF"); // 2
gp2x_text_out8(tl_x, (y+=10), "Emulate YM2612 (FM) %s", (tmp_opts.PicoOpt&0x001)?"ON":"OFF"); // 3
gp2x_text_out8(tl_x, (y+=10), "Emulate SN76496 (PSG) %s", (tmp_opts.PicoOpt&0x002)?"ON":"OFF"); // 4
gp2x_text_out8(tl_x, (y+=10), "gzip savestates %s", (tmp_opts.EmuOpt &0x008)?"ON":"OFF"); // 5
gp2x_text_out8(tl_x, (y+=10), "Don't save config on exit %s", (tmp_opts.EmuOpt &0x020)?"ON":"OFF"); // 6
gp2x_text_out8(tl_x, (y+=10), "needs restart:");
gp2x_text_out8(tl_x, (y+=10), "craigix's RAM timings %s", (tmp_opts.EmuOpt &0x100)?"ON":"OFF"); // 8
gp2x_text_out8(tl_x, (y+=10), "squidgehack (now %s %s", mms, (tmp_opts.EmuOpt &0x010)?"ON":"OFF"); // 9
gp2x_text_out8(tl_x, (y+=10), "Done");
// draw cursor
gp2x_text_out8(tl_x - 16, tl_y + menu_sel*10, ">");
gp2x_video_flip();
}
static void amenu_loop_options(void)
{
int menu_sel = 0, menu_sel_max = 11;
unsigned long inp = 0;
for(;;)
{
draw_amenu_options(menu_sel);
inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT|GP2X_B|GP2X_X|GP2X_A);
if(inp & GP2X_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; }
if(inp & GP2X_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; }
if((inp& GP2X_B)||(inp&GP2X_LEFT)||(inp&GP2X_RIGHT)) { // toggleable options
switch (menu_sel) {
case 0: tmp_opts.PicoOpt^=0x100; break;
case 2: tmp_opts.PicoOpt^=0x004; break;
case 3: tmp_opts.PicoOpt^=0x001; break;
case 4: tmp_opts.PicoOpt^=0x002; break;
case 5: tmp_opts.EmuOpt ^=0x008; break;
case 6: tmp_opts.EmuOpt ^=0x020; break;
case 8: tmp_opts.EmuOpt ^=0x100; break;
case 9: tmp_opts.EmuOpt ^=0x010; break;
case 10: return;
}
}
if(inp & (GP2X_X|GP2X_A)) return;
if(inp & (GP2X_LEFT|GP2X_RIGHT)) { // multi choise
switch (menu_sel) {
case 1:
while ((inp = gp2x_joystick_read(1)) & (GP2X_LEFT|GP2X_RIGHT)) {
tmp_gamma += (inp & GP2X_LEFT) ? -1 : 1;
if (tmp_gamma < 1) tmp_gamma = 1;
if (tmp_gamma > 300) tmp_gamma = 300;
draw_amenu_options(menu_sel);
usleep(18*1000);
}
break;
}
}
}
}
// -------------- options --------------
static char *region_name(unsigned int code)
{
char *names[] = { "Auto", "Japan NTSC", "Japan PAL", "USA", "Europe" };
int i = 0;
code <<= 1;
while((code >>=1)) i++;
if (i > 4) return "unknown";
return names[i];
}
static void draw_menu_options(int menu_sel)
{
int tl_x = 25, tl_y = 40, y;
char monostereo[8], strframeskip[8], *strrend;
strcpy(monostereo, (tmp_opts.PicoOpt&0x08)?"stereo":"mono");
if (tmp_opts.Frameskip < 0)
strcpy(strframeskip, "Auto");
else sprintf(strframeskip, "%i", tmp_opts.Frameskip);
if (tmp_opts.PicoOpt&0x10) {
strrend = " 8bit fast";
} else if (tmp_opts.EmuOpt&0x80) {
strrend = "16bit accurate";
} else {
strrend = " 8bit accurate";
}
y = tl_y;
memset(gp2x_screen, 0, 320*240);
gp2x_text_out8(tl_x, y, "Renderer: %s", strrend); // 0
gp2x_text_out8(tl_x, (y+=10), "Accurate timing (slower) %s", (tmp_opts.PicoOpt&0x040)?"ON":"OFF"); // 1
gp2x_text_out8(tl_x, (y+=10), "Accurate sprites (slower) %s", (tmp_opts.PicoOpt&0x080)?"ON":"OFF"); // 2
gp2x_text_out8(tl_x, (y+=10), "Show FPS %s", (tmp_opts.EmuOpt &0x002)?"ON":"OFF"); // 3
gp2x_text_out8(tl_x, (y+=10), "Frameskip %s", strframeskip);
gp2x_text_out8(tl_x, (y+=10), "Enable sound %s", (tmp_opts.EmuOpt &0x004)?"ON":"OFF"); // 5
gp2x_text_out8(tl_x, (y+=10), "Sound Quality: %5iHz %s", tmp_opts.PsndRate, monostereo);
gp2x_text_out8(tl_x, (y+=10), "Use ARM940 core for sound %s", (tmp_opts.PicoOpt&0x200)?"ON":"OFF"); // 7
gp2x_text_out8(tl_x, (y+=10), "6 button pad %s", (tmp_opts.PicoOpt&0x020)?"ON":"OFF"); // 8
gp2x_text_out8(tl_x, (y+=10), "Genesis Region: %s", region_name(tmp_opts.PicoRegion));
gp2x_text_out8(tl_x, (y+=10), "Use SRAM savestates %s", (tmp_opts.EmuOpt &0x001)?"ON":"OFF"); // 10
gp2x_text_out8(tl_x, (y+=10), "Confirm save overwrites %s", (tmp_opts.EmuOpt &0x200)?"ON":"OFF"); // 11
gp2x_text_out8(tl_x, (y+=10), "Save slot %i", state_slot); // 12
gp2x_text_out8(tl_x, (y+=10), "GP2X CPU clocks %iMhz", tmp_opts.CPUclock);
gp2x_text_out8(tl_x, (y+=10), "[advanced options]");
gp2x_text_out8(tl_x, (y+=10), "Save cfg as default");
if (rom_data)
gp2x_text_out8(tl_x, (y+=10), "Save cfg for current game only");
// draw cursor
gp2x_text_out8(tl_x - 16, tl_y + menu_sel*10, ">");
gp2x_video_flip();
}
static int sndrate_prevnext(int rate, int dir)
{
int i, rates[] = { 8000, 11025, 16000, 22050, 44100 };
for (i = 0; i < 5; i++)
if (rates[i] == rate) break;
i += dir ? 1 : -1;
if (i > 4) return dir ? 44100 : 22050;
if (i < 0) return dir ? 11025 : 8000;
return rates[i];
}
static void menu_options_save(void)
{
memcpy(&currentConfig.EmuOpt, &tmp_opts.EmuOpt, sizeof(tmp_opts));
currentConfig.gamma = tmp_gamma;
PicoOpt = currentConfig.PicoOpt;
PsndRate = currentConfig.PsndRate;
PicoRegionOverride = currentConfig.PicoRegion;
if (PicoOpt & 0x20) {
actionNames[ 8] = "Z"; actionNames[ 9] = "Y";
actionNames[10] = "X"; actionNames[11] = "MODE";
} else {
actionNames[8] = actionNames[9] = actionNames[10] = actionNames[11] = 0;
}
}
static void menu_loop_options(void)
{
int menu_sel = 0, menu_sel_max = 15;
unsigned long inp = 0;
if (rom_data) menu_sel_max++;
memcpy(&tmp_opts.EmuOpt, &currentConfig.EmuOpt, sizeof(tmp_opts));
tmp_gamma = currentConfig.gamma;
tmp_opts.PicoOpt = PicoOpt;
tmp_opts.PsndRate = PsndRate;
tmp_opts.PicoRegion = PicoRegionOverride;
for(;;)
{
draw_menu_options(menu_sel);
inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT|GP2X_B|GP2X_X|GP2X_A);
if(inp & GP2X_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; }
if(inp & GP2X_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; }
if((inp& GP2X_B)||(inp&GP2X_LEFT)||(inp&GP2X_RIGHT)) { // toggleable options
switch (menu_sel) {
case 1: tmp_opts.PicoOpt^=0x040; break;
case 2: tmp_opts.PicoOpt^=0x080; break;
case 3: tmp_opts.EmuOpt ^=0x002; break;
case 5: tmp_opts.EmuOpt ^=0x004; break;
case 7: tmp_opts.PicoOpt^=0x200; break;
case 8: tmp_opts.PicoOpt^=0x020; break;
case 10: tmp_opts.EmuOpt ^=0x001; break;
case 11: tmp_opts.EmuOpt ^=0x200; break;
case 14: amenu_loop_options(); break;
case 15: // done (save)
menu_options_save();
emu_WriteConfig(0);
return;
case 16: // done (save for current game)
menu_options_save();
emu_WriteConfig(1);
return;
}
}
if(inp & GP2X_X) return; // done (no save)
if(inp & GP2X_A) {
menu_options_save();
return; // done (save)
}
if(inp & (GP2X_LEFT|GP2X_RIGHT)) { // multi choise
switch (menu_sel) {
case 0:
if (inp & GP2X_LEFT) {
if ( tmp_opts.PicoOpt&0x10) tmp_opts.PicoOpt&= ~0x10;
else if (!(tmp_opts.EmuOpt &0x80))tmp_opts.EmuOpt |= 0x80;
else if ( tmp_opts.EmuOpt &0x80) break;
} else {
if ( tmp_opts.PicoOpt&0x10) break;
else if (!(tmp_opts.EmuOpt &0x80))tmp_opts.PicoOpt|= 0x10;
else if ( tmp_opts.EmuOpt &0x80) tmp_opts.EmuOpt &= ~0x80;
}
break;
case 4:
tmp_opts.Frameskip += (inp & GP2X_LEFT) ? -1 : 1;
if (tmp_opts.Frameskip < 0) tmp_opts.Frameskip = -1;
if (tmp_opts.Frameskip > 32) tmp_opts.Frameskip = 32;
break;
case 6:
if ((inp & GP2X_RIGHT) && tmp_opts.PsndRate == 44100 && !(tmp_opts.PicoOpt&0x08)) {
tmp_opts.PsndRate = 8000; tmp_opts.PicoOpt|= 0x08;
} else if ((inp & GP2X_LEFT) && tmp_opts.PsndRate == 8000 && (tmp_opts.PicoOpt&0x08)) {
tmp_opts.PsndRate = 44100; tmp_opts.PicoOpt&=~0x08;
} else tmp_opts.PsndRate = sndrate_prevnext(tmp_opts.PsndRate, inp & GP2X_RIGHT);
break;
case 9:
if (inp & GP2X_RIGHT) {
if (tmp_opts.PicoRegion) tmp_opts.PicoRegion<<=1; else tmp_opts.PicoRegion=1;
if (tmp_opts.PicoRegion > 8) tmp_opts.PicoRegion = 8;
} else tmp_opts.PicoRegion>>=1;
break;
case 12:
if (inp & GP2X_RIGHT) {
state_slot++; if (state_slot > 9) state_slot = 0;
} else {state_slot--; if (state_slot < 0) state_slot = 9;
}
break;
case 13:
while ((inp = gp2x_joystick_read(1)) & (GP2X_LEFT|GP2X_RIGHT)) {
tmp_opts.CPUclock += (inp & GP2X_LEFT) ? -1 : 1;
if (tmp_opts.CPUclock < 1) tmp_opts.CPUclock = 1;
draw_menu_options(menu_sel);
usleep(50*1000);
}
break;
}
}
}
}
// -------------- credits --------------
static void draw_menu_credits(void)
{
int tl_x = 15, tl_y = 70, y;
memset(gp2x_screen, 0, 320*240);
gp2x_text_out8(tl_x, 20, "PicoDrive v" VERSION " (c) notaz, 2006");
y = tl_y;
gp2x_text_out8(tl_x, y, "Credits:");
gp2x_text_out8(tl_x, (y+=10), "Dave: Cyclone 68000 core,");
gp2x_text_out8(tl_x, (y+=10), " base code of PicoDrive");
gp2x_text_out8(tl_x, (y+=10), "Reesy & FluBBa: DrZ80 core");
gp2x_text_out8(tl_x, (y+=10), "MAME devs: YM2612 and SN76496 cores");
gp2x_text_out8(tl_x, (y+=10), "Charles MacDonald: Genesis hw docs");
gp2x_text_out8(tl_x, (y+=10), "Stephane Dallongeville:");
gp2x_text_out8(tl_x, (y+=10), " opensource Gens");
gp2x_text_out8(tl_x, (y+=10), "Haze: Genesis hw info");
gp2x_text_out8(tl_x, (y+=10), "rlyeh and others: minimal SDK");
gp2x_text_out8(tl_x, (y+=10), "Squidge: squidgehack");
gp2x_text_out8(tl_x, (y+=10), "Dzz: ARM940 sample");
gp2x_text_out8(tl_x, (y+=10), "GnoStiC / Puck2099: USB joystick");
gp2x_text_out8(tl_x, (y+=10), "craigix: GP2X hardware");
gp2x_video_flip();
}
// -------------- root menu --------------
static void draw_menu_root(int menu_sel)
{
int tl_x = 70, tl_y = 70, y;
memset(gp2x_screen, 0, 320*240);
gp2x_text_out8(tl_x, 20, "PicoDrive v" VERSION);
y = tl_y;
if (rom_data) {
gp2x_text_out8(tl_x, y, "Resume game");
gp2x_text_out8(tl_x, (y+=10), "Save State");
gp2x_text_out8(tl_x, (y+=10), "Load State");
gp2x_text_out8(tl_x, (y+=10), "Reset game");
} else {
y += 30;
}
gp2x_text_out8(tl_x, (y+=10), "Load new ROM");
gp2x_text_out8(tl_x, (y+=10), "Change options");
gp2x_text_out8(tl_x, (y+=10), "Configure controls");
gp2x_text_out8(tl_x, (y+=10), "Credits");
gp2x_text_out8(tl_x, (y+=10), "Exit");
// draw cursor
gp2x_text_out8(tl_x - 16, tl_y + menu_sel*10, ">");
// error
if (menuErrorMsg[0]) gp2x_text_out8(5, 226, menuErrorMsg);
gp2x_video_flip();
}
static void menu_loop_root(void)
{
int menu_sel = 4, menu_sel_max = 8, menu_sel_min = 4;
unsigned long inp = 0;
char curr_path[PATH_MAX], *selfname;
FILE *tstf;
if ( (tstf = fopen(currentConfig.lastRomFile, "rb")) )
{
fclose(tstf);
strcpy(curr_path, currentConfig.lastRomFile);
}
else
{
getcwd(curr_path, PATH_MAX);
}
if (rom_data) menu_sel = menu_sel_min = 0;
for(;;)
{
draw_menu_root(menu_sel);
inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_B|GP2X_X|GP2X_SELECT);
if(inp & GP2X_UP ) { menu_sel--; if (menu_sel < menu_sel_min) menu_sel = menu_sel_max; }
if(inp & GP2X_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = menu_sel_min; }
if(inp &(GP2X_SELECT|GP2X_X)){
if (rom_data) {
while (gp2x_joystick_read(1) & (GP2X_SELECT|GP2X_X)) usleep(50*1000); // wait until select is released
engineState = PGS_Running;
break;
}
}
if(inp & GP2X_B ) {
switch (menu_sel) {
case 0: // resume game
if (rom_data) { engineState = PGS_Running; return; }
break;
case 1: // save state
if (rom_data) {
if(emu_SaveLoadGame(0, 0)) {
strcpy(menuErrorMsg, "save failed");
continue;
}
engineState = PGS_Running;
return;
}
break;
case 2: // load state
if (rom_data) {
if(emu_SaveLoadGame(1, 0)) {
strcpy(menuErrorMsg, "load failed");
continue;
}
engineState = PGS_Running;
return;
}
break;
case 3: // reset game
if (rom_data) {
emu_ResetGame();
engineState = PGS_Running;
return;
}
break;
case 4: // select rom
selfname = romsel_loop(curr_path);
if (selfname) {
printf("selected file: %s\n", selfname);
strncpy(currentConfig.lastRomFile, selfname, sizeof(currentConfig.lastRomFile)-1);
currentConfig.lastRomFile[sizeof(currentConfig.lastRomFile)-1] = 0;
engineState = PGS_ReloadRom;
}
return;
case 5: // options
menu_loop_options();
break;
case 6: // controls
kc_sel_loop();
break;
case 7: // credits
draw_menu_credits();
usleep(500*1000);
inp = wait_for_input(GP2X_B|GP2X_X);
break;
case 8: // exit
engineState = PGS_Quit;
return;
}
}
menuErrorMsg[0] = 0; // clear error msg
}
}
void menu_loop(void)
{
int pal[2];
// switch to 8bpp
gp2x_video_changemode(8);
gp2x_video_RGB_setscaling(320, 240);
// set pal
pal[0] = 0;
pal[1] = 0x00ffffff;
gp2x_video_setpalette(pal, 2);
menu_loop_root();
menuErrorMsg[0] = 0;
}

16
platform/gp2x/menu.h Normal file
View file

@ -0,0 +1,16 @@
// (c) Copyright 2006 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
extern char menuErrorMsg[40];
void gp2x_text_out8 (int x, int y, char *texto, ...);
void gp2x_text_out15 (int x, int y, char *text);
void gp2x_text_out8_2(int x, int y, char *texto, int color);
void menu_loop(void);
#define CONFIGURABLE_KEYS \
(GP2X_UP|GP2X_DOWN|GP2X_LEFT|GP2X_RIGHT|GP2X_A|GP2X_B|GP2X_X|GP2X_Y| \
GP2X_START|GP2X_SELECT|GP2X_L|GP2X_R|GP2X_PUSH|GP2X_VOL_UP|GP2X_VOL_DOWN)

104
platform/gp2x/mmuhack.c Normal file
View file

@ -0,0 +1,104 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <asm/memory.h>
#define MMUHACK_MINOR 225
#define DEVICE_NAME "mmuhack"
#if __GNUC__ == 3
#include <linux/version.h>
static const char __module_kernel_version_gcc3[] __attribute__((__used__)) __attribute__((section(".modinfo"))) =
"kernel_version=" UTS_RELEASE;
#endif
static ssize_t mmuhack_open(struct inode *inode, struct file *filp)
{
unsigned int *pgtable;
unsigned int *cpt;
int i, j;
int ttb;
int ret = -EFAULT;
// get the pointer to the translation table base...
asm volatile(
"stmdb sp!, {r0}\n\t"
"mrc p15, 0, r0, c2, c0, 0\n\t"
"mov %0, r0\n\t"
"ldmia sp!, {r0}\n\t": "=r"(ttb)
);
pgtable = __va(ttb);
for (i = 0; i < 4096; i ++) if ( (pgtable[i] & 3) == 1 ) {
cpt = __va(pgtable[i] & 0xfffffc00);
for (j = 0; j < 256; j ++) {/*
if ( (cpt[j] & 0xfe00000f) == 0x02000002 ) {
// set C and B bits in upper 32MB memory area...
printk("Set C&B bits %08x\n",cpt[j]);
cpt[j] |= 0xFFC;
ret = 0;
}
*/
if (((cpt[j] & 0xff000000) == 0x02000000) && ((cpt[j] & 12)==0) )
{
//printk("Set C&B bits %08x\n",cpt[j]);
cpt[j] |= 0xFFC;
}
//if ((a>=0x31 && a<=0x36) && ((cpt[i] & 12)==0))
if (((cpt[j] & 0xff000000) == 0x03000000) && ((cpt[j] & 12)==0))
{
//printk("Set C&B bits %08x\n",cpt[j]);
//printf("SDL c and b bits not set, overwriting\n");
cpt[j] |= 0xFFC;
}
}
}
// drain the write buffer and flush the tlb caches...
asm volatile(
"stmdb sp!, {r0}\n\t"
"mov r0, #0\n\t"
"mcr 15, 0, r0, cr7, cr10, 4\n\t"
"mcr 15, 0, r0, cr8, cr7, 0\n\t"
"ldmia sp!, {r0}\n\t"
);
if (ret == 0)
printk("MMU hack applied.\n");
return 0;
}
static struct file_operations mmuhack_fops = {
owner: THIS_MODULE,
open: mmuhack_open,
};
static struct miscdevice mmuhack = {
MMUHACK_MINOR, DEVICE_NAME, &mmuhack_fops
};
static int __init mmuhack_init(void)
{
misc_register(&mmuhack);
/*
printk("MMSP2 MMU Hack module.\n");
*/
return 0;
}
static void __exit mmuhack_exit(void)
{
misc_deregister(&mmuhack);
/*
printk(KERN_ALERT "MMU Hack module removed.\n");
*/
}
module_init(mmuhack_init);
module_exit(mmuhack_exit);

View file

@ -0,0 +1,4 @@
Squidge's MMU Hack modularized.
Original code by Squidge.
Module by Annonymous?
Slightly modified by me to suit my need.

View file

@ -0,0 +1,18 @@
// port specific settings
#ifndef PORT_CONFIG_H
#define PORT_CONFIG_H
#define CPU_CALL
// draw2.c
#define START_ROW 0 // which row of tiles to start rendering at?
#define END_ROW 28 // ..end
// pico.c
#define CAN_HANDLE_240_LINES 1
//#define dprintf(f,...) printf(f"\n",##__VA_ARGS__)
#define dprintf(x...)
#endif //PORT_CONFIG_H

View file

@ -0,0 +1,8 @@
@ .equiv START_ROW, 1
@ .equiv END_ROW, 27
@ one row means 8 pixels. If above example was used, (27-1)*8=208 lines would be rendered.
.equiv START_ROW, 0
.equiv END_ROW, 28
@ this should be set to one only for GP2X port
.equiv EXTERNAL_YM2612, 1

View file

@ -0,0 +1,45 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
extern char **g_argv;
/* Call this MMU Hack kernel module after doing mmap, and before doing memset*/
int mmuhack(void)
{
char kocmd[1024];
int i, mmufd = open("/dev/mmuhack", O_RDWR);
if(mmufd < 0) {
strcpy(kocmd, "/sbin/insmod ");
strncpy(kocmd+13, g_argv[0], 1023-13);
kocmd[1023] = 0;
for (i = strlen(kocmd); i > 0; i--)
if (kocmd[i] == '/') { kocmd[i] = 0; break; }
strcat(kocmd, "/mmuhack.o");
printf("Installing NK's kernel module for Squidge MMU Hack (%s)...\n", kocmd);
system(kocmd);
mmufd = open("/dev/mmuhack", O_RDWR);
}
if(mmufd < 0) return 0;
close(mmufd);
return 1;
}
/* Unload MMU Hack kernel module after closing all memory devices*/
int mmuunhack(void)
{
int ret;
printf("Removing NK's kernel module for Squidge MMU Hack... "); fflush(stdout);
ret = system("/sbin/rmmod mmuhack");
printf("done (%i)\n", ret);
return ret;
}

View file

@ -0,0 +1,7 @@
#ifndef __MMUHACK__
#define __MMUHACK__
extern int mmuhack(void);
extern int mmuunhack(void);
#endif /* __MMUHACK__ */

37
platform/gp2x/test.c Normal file
View file

@ -0,0 +1,37 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include "gp2x.h"
void spend_cycles(int c);
int main(void)
{
struct timeval tval; // timing
int thissec = 0, frames_done = 0;
gp2x_init();
for (;;)
{
gettimeofday(&tval, 0);
if(thissec != tval.tv_sec)
{
thissec = tval.tv_sec;
printf("frames_done: %i\n", frames_done);
frames_done = 0;
}
//gp2x_video_wait_vsync();
//usleep(1); // sleeps a minimum of ~20ms
//gp2x_video_flip(); // can be called ~430000 times/sec
spend_cycles(1000);
frames_done++;
}
}

View file

@ -0,0 +1,16 @@
The routines included in this math library are derived from the
math library for Apple's MacOS X/Darwin math library, which was
itself swiped from FreeBSD. The original copyright information
is as follows:
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Developed at SunPro, a Sun Microsystems, Inc. business.
Permission to use, copy, modify, and distribute this
software is freely granted, provided that this notice
is preserved.
It has been ported to work with uClibc and generally behave
by Erik Andersen <andersen@codepoet.org>
22 May, 2001

View file

@ -0,0 +1,147 @@
/* @(#)e_log.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_log.c,v 1.8 1995/05/10 20:45:49 jtc Exp $";
#endif
/* __ieee754_log(x)
* Return the logrithm of x
*
* Method :
* 1. Argument Reduction: find k and f such that
* x = 2^k * (1+f),
* where sqrt(2)/2 < 1+f < sqrt(2) .
*
* 2. Approximation of log(1+f).
* Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
* = 2s + 2/3 s**3 + 2/5 s**5 + .....,
* = 2s + s*R
* We use a special Reme algorithm on [0,0.1716] to generate
* a polynomial of degree 14 to approximate R The maximum error
* of this polynomial approximation is bounded by 2**-58.45. In
* other words,
* 2 4 6 8 10 12 14
* R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
* (the values of Lg1 to Lg7 are listed in the program)
* and
* | 2 14 | -58.45
* | Lg1*s +...+Lg7*s - R(z) | <= 2
* | |
* Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
* In order to guarantee error in log below 1ulp, we compute log
* by
* log(1+f) = f - s*(f - R) (if f is not too large)
* log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
*
* 3. Finally, log(x) = k*ln2 + log(1+f).
* = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
* Here ln2 is split into two floating point number:
* ln2_hi + ln2_lo,
* where n*ln2_hi is always exact for |n| < 2000.
*
* Special cases:
* log(x) is NaN with signal if x < 0 (including -INF) ;
* log(+INF) is +INF; log(0) is -INF with signal;
* log(NaN) is that NaN with no signal.
*
* Accuracy:
* according to an error analysis, the error is always less than
* 1 ulp (unit in the last place).
*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
#ifdef __STDC__
static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __ieee754_log(double x)
#else
double __ieee754_log(x)
double x;
#endif
{
double hfsq,f,s,z,R,w,t1,t2,dk;
int32_t k,hx,i,j;
u_int32_t lx;
EXTRACT_WORDS(hx,lx,x);
k=0;
if (hx < 0x00100000) { /* x < 2**-1022 */
if (((hx&0x7fffffff)|lx)==0)
return -two54/zero; /* log(+-0)=-inf */
if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
k -= 54; x *= two54; /* subnormal number, scale up x */
GET_HIGH_WORD(hx,x);
}
if (hx >= 0x7ff00000) return x+x;
k += (hx>>20)-1023;
hx &= 0x000fffff;
i = (hx+0x95f64)&0x100000;
SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */
k += (i>>20);
f = x-1.0;
if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */
if(f==zero) {if(k==0) return zero; else {dk=(double)k;
return dk*ln2_hi+dk*ln2_lo;}
}
R = f*f*(0.5-0.33333333333333333*f);
if(k==0) return f-R; else {dk=(double)k;
return dk*ln2_hi-((R-dk*ln2_lo)-f);}
}
s = f/(2.0+f);
dk = (double)k;
z = s*s;
i = hx-0x6147a;
w = z*z;
j = 0x6b851-hx;
t1= w*(Lg2+w*(Lg4+w*Lg6));
t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
i |= j;
R = t2+t1;
if(i>0) {
hfsq=0.5*f*f;
if(k==0) return f-(hfsq-s*(hfsq+R)); else
return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
} else {
if(k==0) return f-s*(f-R); else
return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
}
}

View file

@ -0,0 +1,308 @@
/* @(#)e_pow.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_pow.c,v 1.9 1995/05/12 04:57:32 jtc Exp $";
#endif
/* __ieee754_pow(x,y) return x**y
*
* n
* Method: Let x = 2 * (1+f)
* 1. Compute and return log2(x) in two pieces:
* log2(x) = w1 + w2,
* where w1 has 53-24 = 29 bit trailing zeros.
* 2. Perform y*log2(x) = n+y' by simulating muti-precision
* arithmetic, where |y'|<=0.5.
* 3. Return x**y = 2**n*exp(y'*log2)
*
* Special cases:
* 1. (anything) ** 0 is 1
* 2. (anything) ** 1 is itself
* 3. (anything) ** NAN is NAN
* 4. NAN ** (anything except 0) is NAN
* 5. +-(|x| > 1) ** +INF is +INF
* 6. +-(|x| > 1) ** -INF is +0
* 7. +-(|x| < 1) ** +INF is +0
* 8. +-(|x| < 1) ** -INF is +INF
* 9. +-1 ** +-INF is NAN
* 10. +0 ** (+anything except 0, NAN) is +0
* 11. -0 ** (+anything except 0, NAN, odd integer) is +0
* 12. +0 ** (-anything except 0, NAN) is +INF
* 13. -0 ** (-anything except 0, NAN, odd integer) is +INF
* 14. -0 ** (odd integer) = -( +0 ** (odd integer) )
* 15. +INF ** (+anything except 0,NAN) is +INF
* 16. +INF ** (-anything except 0,NAN) is +0
* 17. -INF ** (anything) = -0 ** (-anything)
* 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
* 19. (-anything except 0 and inf) ** (non-integer) is NAN
*
* Accuracy:
* pow(x,y) returns x**y nearly rounded. In particular
* pow(integer,integer)
* always returns the correct integer provided it is
* representable.
*
* Constants :
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
bp[] = {1.0, 1.5,},
dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
zero = 0.0,
one = 1.0,
two = 2.0,
two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
huge = 1.0e300,
tiny = 1.0e-300,
/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
#ifdef __STDC__
double __ieee754_pow(double x, double y)
#else
double __ieee754_pow(x,y)
double x, y;
#endif
{
double z,ax,z_h,z_l,p_h,p_l;
double y1,t1,t2,r,s,t,u,v,w;
int32_t i,j,k,yisint,n;
int32_t hx,hy,ix,iy;
u_int32_t lx,ly;
EXTRACT_WORDS(hx,lx,x);
EXTRACT_WORDS(hy,ly,y);
ix = hx&0x7fffffff; iy = hy&0x7fffffff;
/* y==zero: x**0 = 1 */
if((iy|ly)==0) return one;
/* +-NaN return x+y */
if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0)))
return x+y;
/* determine if y is an odd int when x < 0
* yisint = 0 ... y is not an integer
* yisint = 1 ... y is an odd int
* yisint = 2 ... y is an even int
*/
yisint = 0;
if(hx<0) {
if(iy>=0x43400000) yisint = 2; /* even integer y */
else if(iy>=0x3ff00000) {
k = (iy>>20)-0x3ff; /* exponent */
if(k>20) {
j = ly>>(52-k);
if((j<<(52-k))==ly) yisint = 2-(j&1);
} else if(ly==0) {
j = iy>>(20-k);
if((j<<(20-k))==iy) yisint = 2-(j&1);
}
}
}
/* special value of y */
if(ly==0) {
if (iy==0x7ff00000) { /* y is +-inf */
if(((ix-0x3ff00000)|lx)==0)
return y - y; /* inf**+-1 is NaN */
else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
return (hy>=0)? y: zero;
else /* (|x|<1)**-,+inf = inf,0 */
return (hy<0)?-y: zero;
}
if(iy==0x3ff00000) { /* y is +-1 */
if(hy<0) return one/x; else return x;
}
if(hy==0x40000000) return x*x; /* y is 2 */
if(hy==0x3fe00000) { /* y is 0.5 */
if(hx>=0) /* x >= +0 */
return __ieee754_sqrt(x);
}
}
ax = fabs(x);
/* special value of x */
if(lx==0) {
if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
z = ax; /*x is +-0,+-inf,+-1*/
if(hy<0) z = one/z; /* z = (1/|x|) */
if(hx<0) {
if(((ix-0x3ff00000)|yisint)==0) {
z = (z-z)/(z-z); /* (-1)**non-int is NaN */
} else if(yisint==1)
z = -z; /* (x<0)**odd = -(|x|**odd) */
}
return z;
}
}
/* (x<0)**(non-int) is NaN */
if(((((u_int32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x);
/* |y| is huge */
if(iy>0x41e00000) { /* if |y| > 2**31 */
if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */
if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
}
/* over/underflow if x is not close to one */
if(ix<0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
if(ix>0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
/* now |1-x| is tiny <= 2**-20, suffice to compute
log(x) by x-x^2/2+x^3/3-x^4/4 */
t = x-1; /* t has 20 trailing zeros */
w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
u = ivln2_h*t; /* ivln2_h has 21 sig. bits */
v = t*ivln2_l-w*ivln2;
t1 = u+v;
SET_LOW_WORD(t1,0);
t2 = v-(t1-u);
} else {
double s2,s_h,s_l,t_h,t_l;
n = 0;
/* take care subnormal number */
if(ix<0x00100000)
{ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); }
n += ((ix)>>20)-0x3ff;
j = ix&0x000fffff;
/* determine interval */
ix = j|0x3ff00000; /* normalize ix */
if(j<=0x3988E) k=0; /* |x|<sqrt(3/2) */
else if(j<0xBB67A) k=1; /* |x|<sqrt(3) */
else {k=0;n+=1;ix -= 0x00100000;}
SET_HIGH_WORD(ax,ix);
/* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
v = one/(ax+bp[k]);
s = u*v;
s_h = s;
SET_LOW_WORD(s_h,0);
/* t_h=ax+bp[k] High */
t_h = zero;
SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18));
t_l = ax - (t_h-bp[k]);
s_l = v*((u-s_h*t_h)-s_h*t_l);
/* compute log(ax) */
s2 = s*s;
r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
r += s_l*(s_h+s);
s2 = s_h*s_h;
t_h = 3.0+s2+r;
SET_LOW_WORD(t_h,0);
t_l = r-((t_h-3.0)-s2);
/* u+v = s*(1+...) */
u = s_h*t_h;
v = s_l*t_h+t_l*s;
/* 2/(3log2)*(s+...) */
p_h = u+v;
SET_LOW_WORD(p_h,0);
p_l = v-(p_h-u);
z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
z_l = cp_l*p_h+p_l*cp+dp_l[k];
/* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
t = (double)n;
t1 = (((z_h+z_l)+dp_h[k])+t);
SET_LOW_WORD(t1,0);
t2 = z_l-(((t1-t)-dp_h[k])-z_h);
}
s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
if(((((u_int32_t)hx>>31)-1)|(yisint-1))==0)
s = -one;/* (-ve)**(odd int) */
/* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
y1 = y;
SET_LOW_WORD(y1,0);
p_l = (y-y1)*t1+y*t2;
p_h = y1*t1;
z = p_l+p_h;
EXTRACT_WORDS(j,i,z);
if (j>=0x40900000) { /* z >= 1024 */
if(((j-0x40900000)|i)!=0) /* if z > 1024 */
return s*huge*huge; /* overflow */
else {
if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */
}
} else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */
if(((j-0xc090cc00)|i)!=0) /* z < -1075 */
return s*tiny*tiny; /* underflow */
else {
if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */
}
}
/*
* compute 2**(p_h+p_l)
*/
i = j&0x7fffffff;
k = (i>>20)-0x3ff;
n = 0;
if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */
n = j+(0x00100000>>(k+1));
k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */
t = zero;
SET_HIGH_WORD(t,n&~(0x000fffff>>k));
n = ((n&0x000fffff)|0x00100000)>>(20-k);
if(j<0) n = -n;
p_h -= t;
}
t = p_l+p_h;
SET_LOW_WORD(t,0);
u = t*lg2_h;
v = (p_l-(t-p_h))*lg2+t*lg2_l;
z = u+v;
w = v-(z-u);
t = z*z;
t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
r = (z*t1)/(t1-two)-(w+z*w);
z = one-(r-z);
GET_HIGH_WORD(j,z);
j += (n<<20);
if((j>>20)<=0) z = scalbn(z,n); /* subnormal output */
else SET_HIGH_WORD(z,j);
return s*z;
}

View file

@ -0,0 +1,183 @@
/* @(#)e_rem_pio2.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_rem_pio2.c,v 1.8 1995/05/10 20:46:02 jtc Exp $";
#endif
/* __ieee754_rem_pio2(x,y)
*
* return the remainder of x rem pi/2 in y[0]+y[1]
* use __kernel_rem_pio2()
*/
#include "math.h"
#include "math_private.h"
/*
* Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
*/
#ifdef __STDC__
static const int32_t two_over_pi[] = {
#else
static int32_t two_over_pi[] = {
#endif
0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
};
#ifdef __STDC__
static const int32_t npio2_hw[] = {
#else
static int32_t npio2_hw[] = {
#endif
0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
0x404858EB, 0x404921FB,
};
/*
* invpio2: 53 bits of 2/pi
* pio2_1: first 33 bit of pi/2
* pio2_1t: pi/2 - pio2_1
* pio2_2: second 33 bit of pi/2
* pio2_2t: pi/2 - (pio2_1+pio2_2)
* pio2_3: third 33 bit of pi/2
* pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
*/
#ifdef __STDC__
static const double
#else
static double
#endif
zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
#ifdef __STDC__
int32_t __ieee754_rem_pio2(double x, double *y)
#else
int32_t __ieee754_rem_pio2(x,y)
double x,y[];
#endif
{
double z=0.0,w,t,r,fn;
double tx[3];
int32_t e0,i,j,nx,n,ix,hx;
u_int32_t low;
GET_HIGH_WORD(hx,x); /* high word of x */
ix = hx&0x7fffffff;
if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */
{y[0] = x; y[1] = 0; return 0;}
if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */
if(hx>0) {
z = x - pio2_1;
if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */
y[0] = z - pio2_1t;
y[1] = (z-y[0])-pio2_1t;
} else { /* near pi/2, use 33+33+53 bit pi */
z -= pio2_2;
y[0] = z - pio2_2t;
y[1] = (z-y[0])-pio2_2t;
}
return 1;
} else { /* negative x */
z = x + pio2_1;
if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */
y[0] = z + pio2_1t;
y[1] = (z-y[0])+pio2_1t;
} else { /* near pi/2, use 33+33+53 bit pi */
z += pio2_2;
y[0] = z + pio2_2t;
y[1] = (z-y[0])+pio2_2t;
}
return -1;
}
}
if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
t = fabs(x);
n = (int32_t) (t*invpio2+half);
fn = (double)n;
r = t-fn*pio2_1;
w = fn*pio2_1t; /* 1st round good to 85 bit */
if(n<32&&ix!=npio2_hw[n-1]) {
y[0] = r-w; /* quick check no cancellation */
} else {
u_int32_t high;
j = ix>>20;
y[0] = r-w;
GET_HIGH_WORD(high,y[0]);
i = j-((high>>20)&0x7ff);
if(i>16) { /* 2nd iteration needed, good to 118 */
t = r;
w = fn*pio2_2;
r = t-w;
w = fn*pio2_2t-((t-r)-w);
y[0] = r-w;
GET_HIGH_WORD(high,y[0]);
i = j-((high>>20)&0x7ff);
if(i>49) { /* 3rd iteration need, 151 bits acc */
t = r; /* will cover all possible cases */
w = fn*pio2_3;
r = t-w;
w = fn*pio2_3t-((t-r)-w);
y[0] = r-w;
}
}
}
y[1] = (r-y[0])-w;
if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
else return n;
}
/*
* all other (large) arguments
*/
if(ix>=0x7ff00000) { /* x is inf or NaN */
y[0]=y[1]=x-x; return 0;
}
/* set z = scalbn(|x|,ilogb(x)-23) */
GET_LOW_WORD(low,x);
SET_LOW_WORD(z,low);
e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */
SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20)));
for(i=0;i<2;i++) {
tx[i] = (double)((int32_t)(z));
z = (z-tx[i])*two24;
}
tx[2] = z;
nx = 3;
while(tx[nx-1]==zero) nx--; /* skip zero term */
n = __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi);
if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
return n;
}

View file

@ -0,0 +1,453 @@
/* @(#)e_sqrt.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_sqrt.c,v 1.8 1995/05/10 20:46:17 jtc Exp $";
#endif
/* __ieee754_sqrt(x)
* Return correctly rounded sqrt.
* ------------------------------------------
* | Use the hardware sqrt if you have one |
* ------------------------------------------
* Method:
* Bit by bit method using integer arithmetic. (Slow, but portable)
* 1. Normalization
* Scale x to y in [1,4) with even powers of 2:
* find an integer k such that 1 <= (y=x*2^(2k)) < 4, then
* sqrt(x) = 2^k * sqrt(y)
* 2. Bit by bit computation
* Let q = sqrt(y) truncated to i bit after binary point (q = 1),
* i 0
* i+1 2
* s = 2*q , and y = 2 * ( y - q ). (1)
* i i i i
*
* To compute q from q , one checks whether
* i+1 i
*
* -(i+1) 2
* (q + 2 ) <= y. (2)
* i
* -(i+1)
* If (2) is false, then q = q ; otherwise q = q + 2 .
* i+1 i i+1 i
*
* With some algebric manipulation, it is not difficult to see
* that (2) is equivalent to
* -(i+1)
* s + 2 <= y (3)
* i i
*
* The advantage of (3) is that s and y can be computed by
* i i
* the following recurrence formula:
* if (3) is false
*
* s = s , y = y ; (4)
* i+1 i i+1 i
*
* otherwise,
* -i -(i+1)
* s = s + 2 , y = y - s - 2 (5)
* i+1 i i+1 i i
*
* One may easily use induction to prove (4) and (5).
* Note. Since the left hand side of (3) contain only i+2 bits,
* it does not necessary to do a full (53-bit) comparison
* in (3).
* 3. Final rounding
* After generating the 53 bits result, we compute one more bit.
* Together with the remainder, we can decide whether the
* result is exact, bigger than 1/2ulp, or less than 1/2ulp
* (it will never equal to 1/2ulp).
* The rounding mode can be detected by checking whether
* huge + tiny is equal to huge, and whether huge - tiny is
* equal to huge for some floating point number "huge" and "tiny".
*
* Special cases:
* sqrt(+-0) = +-0 ... exact
* sqrt(inf) = inf
* sqrt(-ve) = NaN ... with invalid signal
* sqrt(NaN) = NaN ... with invalid signal for signaling NaN
*
* Other methods : see the appended file at the end of the program below.
*---------------
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double one = 1.0, tiny=1.0e-300;
#else
static double one = 1.0, tiny=1.0e-300;
#endif
#ifdef __STDC__
double __ieee754_sqrt(double x)
#else
double __ieee754_sqrt(x)
double x;
#endif
{
double z;
int32_t sign = (int)0x80000000;
int32_t ix0,s0,q,m,t,i;
u_int32_t r,t1,s1,ix1,q1;
EXTRACT_WORDS(ix0,ix1,x);
/* take care of Inf and NaN */
if((ix0&0x7ff00000)==0x7ff00000) {
return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
sqrt(-inf)=sNaN */
}
/* take care of zero */
if(ix0<=0) {
if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
else if(ix0<0)
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
}
/* normalize x */
m = (ix0>>20);
if(m==0) { /* subnormal x */
while(ix0==0) {
m -= 21;
ix0 |= (ix1>>11); ix1 <<= 21;
}
for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
m -= i-1;
ix0 |= (ix1>>(32-i));
ix1 <<= i;
}
m -= 1023; /* unbias exponent */
ix0 = (ix0&0x000fffff)|0x00100000;
if(m&1){ /* odd m, double x to make it even */
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
}
m >>= 1; /* m = [m/2] */
/* generate sqrt(x) bit by bit */
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
r = 0x00200000; /* r = moving bit from right to left */
while(r!=0) {
t = s0+r;
if(t<=ix0) {
s0 = t+r;
ix0 -= t;
q += r;
}
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
r>>=1;
}
r = sign;
while(r!=0) {
t1 = s1+r;
t = s0;
if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
s1 = t1+r;
if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
ix0 -= t;
if (ix1 < t1) ix0 -= 1;
ix1 -= t1;
q1 += r;
}
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
r>>=1;
}
/* use floating add to find out rounding direction */
if((ix0|ix1)!=0) {
z = one-tiny; /* trigger inexact flag */
if (z>=one) {
z = one+tiny;
if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;}
else if (z>one) {
if (q1==(u_int32_t)0xfffffffe) q+=1;
q1+=2;
} else
q1 += (q1&1);
}
}
ix0 = (q>>1)+0x3fe00000;
ix1 = q1>>1;
if ((q&1)==1) ix1 |= sign;
ix0 += (m <<20);
INSERT_WORDS(z,ix0,ix1);
return z;
}
/*
Other methods (use floating-point arithmetic)
-------------
(This is a copy of a drafted paper by Prof W. Kahan
and K.C. Ng, written in May, 1986)
Two algorithms are given here to implement sqrt(x)
(IEEE double precision arithmetic) in software.
Both supply sqrt(x) correctly rounded. The first algorithm (in
Section A) uses newton iterations and involves four divisions.
The second one uses reciproot iterations to avoid division, but
requires more multiplications. Both algorithms need the ability
to chop results of arithmetic operations instead of round them,
and the INEXACT flag to indicate when an arithmetic operation
is executed exactly with no roundoff error, all part of the
standard (IEEE 754-1985). The ability to perform shift, add,
subtract and logical AND operations upon 32-bit words is needed
too, though not part of the standard.
A. sqrt(x) by Newton Iteration
(1) Initial approximation
Let x0 and x1 be the leading and the trailing 32-bit words of
a floating point number x (in IEEE double format) respectively
1 11 52 ...widths
------------------------------------------------------
x: |s| e | f |
------------------------------------------------------
msb lsb msb lsb ...order
------------------------ ------------------------
x0: |s| e | f1 | x1: | f2 |
------------------------ ------------------------
By performing shifts and subtracts on x0 and x1 (both regarded
as integers), we obtain an 8-bit approximation of sqrt(x) as
follows.
k := (x0>>1) + 0x1ff80000;
y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits
Here k is a 32-bit integer and T1[] is an integer array containing
correction terms. Now magically the floating value of y (y's
leading 32-bit word is y0, the value of its trailing word is 0)
approximates sqrt(x) to almost 8-bit.
Value of T1:
static int T1[32]= {
0, 1024, 3062, 5746, 9193, 13348, 18162, 23592,
29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215,
83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581,
16499, 12183, 8588, 5674, 3403, 1742, 661, 130,};
(2) Iterative refinement
Apply Heron's rule three times to y, we have y approximates
sqrt(x) to within 1 ulp (Unit in the Last Place):
y := (y+x/y)/2 ... almost 17 sig. bits
y := (y+x/y)/2 ... almost 35 sig. bits
y := y-(y-x/y)/2 ... within 1 ulp
Remark 1.
Another way to improve y to within 1 ulp is:
y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x)
y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x)
2
(x-y )*y
y := y + 2* ---------- ...within 1 ulp
2
3y + x
This formula has one division fewer than the one above; however,
it requires more multiplications and additions. Also x must be
scaled in advance to avoid spurious overflow in evaluating the
expression 3y*y+x. Hence it is not recommended uless division
is slow. If division is very slow, then one should use the
reciproot algorithm given in section B.
(3) Final adjustment
By twiddling y's last bit it is possible to force y to be
correctly rounded according to the prevailing rounding mode
as follows. Let r and i be copies of the rounding mode and
inexact flag before entering the square root program. Also we
use the expression y+-ulp for the next representable floating
numbers (up and down) of y. Note that y+-ulp = either fixed
point y+-1, or multiply y by nextafter(1,+-inf) in chopped
mode.
I := FALSE; ... reset INEXACT flag I
R := RZ; ... set rounding mode to round-toward-zero
z := x/y; ... chopped quotient, possibly inexact
If(not I) then { ... if the quotient is exact
if(z=y) {
I := i; ... restore inexact flag
R := r; ... restore rounded mode
return sqrt(x):=y.
} else {
z := z - ulp; ... special rounding
}
}
i := TRUE; ... sqrt(x) is inexact
If (r=RN) then z=z+ulp ... rounded-to-nearest
If (r=RP) then { ... round-toward-+inf
y = y+ulp; z=z+ulp;
}
y := y+z; ... chopped sum
y0:=y0-0x00100000; ... y := y/2 is correctly rounded.
I := i; ... restore inexact flag
R := r; ... restore rounded mode
return sqrt(x):=y.
(4) Special cases
Square root of +inf, +-0, or NaN is itself;
Square root of a negative number is NaN with invalid signal.
B. sqrt(x) by Reciproot Iteration
(1) Initial approximation
Let x0 and x1 be the leading and the trailing 32-bit words of
a floating point number x (in IEEE double format) respectively
(see section A). By performing shifs and subtracts on x0 and y0,
we obtain a 7.8-bit approximation of 1/sqrt(x) as follows.
k := 0x5fe80000 - (x0>>1);
y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits
Here k is a 32-bit integer and T2[] is an integer array
containing correction terms. Now magically the floating
value of y (y's leading 32-bit word is y0, the value of
its trailing word y1 is set to zero) approximates 1/sqrt(x)
to almost 7.8-bit.
Value of T2:
static int T2[64]= {
0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866,
0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f,
0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d,
0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0,
0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989,
0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd,
0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e,
0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,};
(2) Iterative refinement
Apply Reciproot iteration three times to y and multiply the
result by x to get an approximation z that matches sqrt(x)
to about 1 ulp. To be exact, we will have
-1ulp < sqrt(x)-z<1.0625ulp.
... set rounding mode to Round-to-nearest
y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x)
y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x)
... special arrangement for better accuracy
z := x*y ... 29 bits to sqrt(x), with z*y<1
z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x)
Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that
(a) the term z*y in the final iteration is always less than 1;
(b) the error in the final result is biased upward so that
-1 ulp < sqrt(x) - z < 1.0625 ulp
instead of |sqrt(x)-z|<1.03125ulp.
(3) Final adjustment
By twiddling y's last bit it is possible to force y to be
correctly rounded according to the prevailing rounding mode
as follows. Let r and i be copies of the rounding mode and
inexact flag before entering the square root program. Also we
use the expression y+-ulp for the next representable floating
numbers (up and down) of y. Note that y+-ulp = either fixed
point y+-1, or multiply y by nextafter(1,+-inf) in chopped
mode.
R := RZ; ... set rounding mode to round-toward-zero
switch(r) {
case RN: ... round-to-nearest
if(x<= z*(z-ulp)...chopped) z = z - ulp; else
if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp;
break;
case RZ:case RM: ... round-to-zero or round-to--inf
R:=RP; ... reset rounding mod to round-to-+inf
if(x<z*z ... rounded up) z = z - ulp; else
if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp;
break;
case RP: ... round-to-+inf
if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else
if(x>z*z ...chopped) z = z+ulp;
break;
}
Remark 3. The above comparisons can be done in fixed point. For
example, to compare x and w=z*z chopped, it suffices to compare
x1 and w1 (the trailing parts of x and w), regarding them as
two's complement integers.
...Is z an exact square root?
To determine whether z is an exact square root of x, let z1 be the
trailing part of z, and also let x0 and x1 be the leading and
trailing parts of x.
If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0
I := 1; ... Raise Inexact flag: z is not exact
else {
j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2
k := z1 >> 26; ... get z's 25-th and 26-th
fraction bits
I := i or (k&j) or ((k&(j+j+1))!=(x1&3));
}
R:= r ... restore rounded mode
return sqrt(x):=z.
If multiplication is cheaper then the foregoing red tape, the
Inexact flag can be evaluated by
I := i;
I := (z*z!=x) or I.
Note that z*z can overwrite I; this value must be sensed if it is
True.
Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be
zero.
--------------------
z1: | f2 |
--------------------
bit 31 bit 0
Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd
or even of logb(x) have the following relations:
-------------------------------------------------
bit 27,26 of z1 bit 1,0 of x1 logb(x)
-------------------------------------------------
00 00 odd and even
01 01 even
10 10 odd
10 00 even
11 01 even
-------------------------------------------------
(4) Special cases (see (4) of Section A).
*/

View file

@ -0,0 +1,96 @@
/* @(#)k_cos.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_cos.c,v 1.8 1995/05/10 20:46:22 jtc Exp $";
#endif
/*
* __kernel_cos( x, y )
* kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
* Input x is assumed to be bounded by ~pi/4 in magnitude.
* Input y is the tail of x.
*
* Algorithm
* 1. Since cos(-x) = cos(x), we need only to consider positive x.
* 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
* 3. cos(x) is approximated by a polynomial of degree 14 on
* [0,pi/4]
* 4 14
* cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
* where the remez error is
*
* | 2 4 6 8 10 12 14 | -58
* |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2
* | |
*
* 4 6 8 10 12 14
* 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then
* cos(x) = 1 - x*x/2 + r
* since cos(x+y) ~ cos(x) - sin(x)*y
* ~ cos(x) - x*y,
* a correction term is necessary in cos(x) and hence
* cos(x+y) = 1 - (x*x/2 - (r - x*y))
* For better accuracy when x > 0.3, let qx = |x|/4 with
* the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
* Then
* cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)).
* Note that 1-qx and (x*x/2-qx) is EXACT here, and the
* magnitude of the latter is at least a quarter of x*x/2,
* thus, reducing the rounding error in the subtraction.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
#ifdef __STDC__
double __kernel_cos(double x, double y)
#else
double __kernel_cos(x, y)
double x,y;
#endif
{
double a,hz,z,r,qx;
int32_t ix;
GET_HIGH_WORD(ix,x);
ix &= 0x7fffffff; /* ix = |x|'s high word*/
if(ix<0x3e400000) { /* if x < 2**27 */
if(((int)x)==0) return one; /* generate inexact */
}
z = x*x;
r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
if(ix < 0x3FD33333) /* if |x| < 0.3 */
return one - (0.5*z - (z*r - x*y));
else {
if(ix > 0x3fe90000) { /* x > 0.78125 */
qx = 0.28125;
} else {
INSERT_WORDS(qx,ix-0x00200000,0); /* x/4 */
}
hz = 0.5*z-qx;
a = one-qx;
return a - (hz - (z*r-x*y));
}
}

View file

@ -0,0 +1,320 @@
/* @(#)k_rem_pio2.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_rem_pio2.c,v 1.7 1995/05/10 20:46:25 jtc Exp $";
#endif
/*
* __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
* double x[],y[]; int e0,nx,prec; int ipio2[];
*
* __kernel_rem_pio2 return the last three digits of N with
* y = x - N*pi/2
* so that |y| < pi/2.
*
* The method is to compute the integer (mod 8) and fraction parts of
* (2/pi)*x without doing the full multiplication. In general we
* skip the part of the product that are known to be a huge integer (
* more accurately, = 0 mod 8 ). Thus the number of operations are
* independent of the exponent of the input.
*
* (2/pi) is represented by an array of 24-bit integers in ipio2[].
*
* Input parameters:
* x[] The input value (must be positive) is broken into nx
* pieces of 24-bit integers in double precision format.
* x[i] will be the i-th 24 bit of x. The scaled exponent
* of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
* match x's up to 24 bits.
*
* Example of breaking a double positive z into x[0]+x[1]+x[2]:
* e0 = ilogb(z)-23
* z = scalbn(z,-e0)
* for i = 0,1,2
* x[i] = floor(z)
* z = (z-x[i])*2**24
*
*
* y[] ouput result in an array of double precision numbers.
* The dimension of y[] is:
* 24-bit precision 1
* 53-bit precision 2
* 64-bit precision 2
* 113-bit precision 3
* The actual value is the sum of them. Thus for 113-bit
* precison, one may have to do something like:
*
* long double t,w,r_head, r_tail;
* t = (long double)y[2] + (long double)y[1];
* w = (long double)y[0];
* r_head = t+w;
* r_tail = w - (r_head - t);
*
* e0 The exponent of x[0]
*
* nx dimension of x[]
*
* prec an integer indicating the precision:
* 0 24 bits (single)
* 1 53 bits (double)
* 2 64 bits (extended)
* 3 113 bits (quad)
*
* ipio2[]
* integer array, contains the (24*i)-th to (24*i+23)-th
* bit of 2/pi after binary point. The corresponding
* floating value is
*
* ipio2[i] * 2^(-24(i+1)).
*
* External function:
* double scalbn(), floor();
*
*
* Here is the description of some local variables:
*
* jk jk+1 is the initial number of terms of ipio2[] needed
* in the computation. The recommended value is 2,3,4,
* 6 for single, double, extended,and quad.
*
* jz local integer variable indicating the number of
* terms of ipio2[] used.
*
* jx nx - 1
*
* jv index for pointing to the suitable ipio2[] for the
* computation. In general, we want
* ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
* is an integer. Thus
* e0-3-24*jv >= 0 or (e0-3)/24 >= jv
* Hence jv = max(0,(e0-3)/24).
*
* jp jp+1 is the number of terms in PIo2[] needed, jp = jk.
*
* q[] double array with integral value, representing the
* 24-bits chunk of the product of x and 2/pi.
*
* q0 the corresponding exponent of q[0]. Note that the
* exponent for q[i] would be q0-24*i.
*
* PIo2[] double precision array, obtained by cutting pi/2
* into 24 bits chunks.
*
* f[] ipio2[] in floating point
*
* iq[] integer array by breaking up q[] in 24-bits chunk.
*
* fq[] final product of x*(2/pi) in fq[0],..,fq[jk]
*
* ih integer. If >0 it indicates q[] is >= 0.5, hence
* it also indicates the *sign* of the result.
*
*/
/*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const int init_jk[] = {2,3,4,6}; /* initial value for jk */
#else
static int init_jk[] = {2,3,4,6};
#endif
#ifdef __STDC__
static const double PIo2[] = {
#else
static double PIo2[] = {
#endif
1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
};
#ifdef __STDC__
static const double
#else
static double
#endif
zero = 0.0,
one = 1.0,
two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
#ifdef __STDC__
int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2)
#else
int __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
double x[], y[]; int e0,nx,prec; int32_t ipio2[];
#endif
{
int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
double z,fw,f[20],fq[20],q[20];
/* initialize jk*/
jk = init_jk[prec];
jp = jk;
/* determine jx,jv,q0, note that 3>q0 */
jx = nx-1;
jv = (e0-3)/24; if(jv<0) jv=0;
q0 = e0-24*(jv+1);
/* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
j = jv-jx; m = jx+jk;
for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j];
/* compute q[0],q[1],...q[jk] */
for (i=0;i<=jk;i++) {
for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
}
jz = jk;
recompute:
/* distill q[] into iq[] reversingly */
for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
fw = (double)((int32_t)(twon24* z));
iq[i] = (int32_t)(z-two24*fw);
z = q[j-1]+fw;
}
/* compute n */
z = scalbn(z,q0); /* actual value of z */
z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */
n = (int32_t) z;
z -= (double)n;
ih = 0;
if(q0>0) { /* need iq[jz-1] to determine n */
i = (iq[jz-1]>>(24-q0)); n += i;
iq[jz-1] -= i<<(24-q0);
ih = iq[jz-1]>>(23-q0);
}
else if(q0==0) ih = iq[jz-1]>>23;
else if(z>=0.5) ih=2;
if(ih>0) { /* q > 0.5 */
n += 1; carry = 0;
for(i=0;i<jz ;i++) { /* compute 1-q */
j = iq[i];
if(carry==0) {
if(j!=0) {
carry = 1; iq[i] = 0x1000000- j;
}
} else iq[i] = 0xffffff - j;
}
if(q0>0) { /* rare case: chance is 1 in 12 */
switch(q0) {
case 1:
iq[jz-1] &= 0x7fffff; break;
case 2:
iq[jz-1] &= 0x3fffff; break;
}
}
if(ih==2) {
z = one - z;
if(carry!=0) z -= scalbn(one,q0);
}
}
/* check if recomputation is needed */
if(z==zero) {
j = 0;
for (i=jz-1;i>=jk;i--) j |= iq[i];
if(j==0) { /* need recomputation */
for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */
for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */
f[jx+i] = (double) ipio2[jv+i];
for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
q[i] = fw;
}
jz += k;
goto recompute;
}
}
/* chop off zero terms */
if(z==0.0) {
jz -= 1; q0 -= 24;
while(iq[jz]==0) { jz--; q0-=24;}
} else { /* break z into 24-bit if necessary */
z = scalbn(z,-q0);
if(z>=two24) {
fw = (double)((int32_t)(twon24*z));
iq[jz] = (int32_t)(z-two24*fw);
jz += 1; q0 += 24;
iq[jz] = (int32_t) fw;
} else iq[jz] = (int32_t) z ;
}
/* convert integer "bit" chunk to floating-point value */
fw = scalbn(one,q0);
for(i=jz;i>=0;i--) {
q[i] = fw*(double)iq[i]; fw*=twon24;
}
/* compute PIo2[0,...,jp]*q[jz,...,0] */
for(i=jz;i>=0;i--) {
for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
fq[jz-i] = fw;
}
/* compress fq[] into y[] */
switch(prec) {
case 0:
fw = 0.0;
for (i=jz;i>=0;i--) fw += fq[i];
y[0] = (ih==0)? fw: -fw;
break;
case 1:
case 2:
fw = 0.0;
for (i=jz;i>=0;i--) fw += fq[i];
y[0] = (ih==0)? fw: -fw;
fw = fq[0]-fw;
for (i=1;i<=jz;i++) fw += fq[i];
y[1] = (ih==0)? fw: -fw;
break;
case 3: /* painful */
for (i=jz;i>0;i--) {
fw = fq[i-1]+fq[i];
fq[i] += fq[i-1]-fw;
fq[i-1] = fw;
}
for (i=jz;i>1;i--) {
fw = fq[i-1]+fq[i];
fq[i] += fq[i-1]-fw;
fq[i-1] = fw;
}
for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
if(ih==0) {
y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
} else {
y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
}
}
return n&7;
}

View file

@ -0,0 +1,79 @@
/* @(#)k_sin.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_sin.c,v 1.8 1995/05/10 20:46:31 jtc Exp $";
#endif
/* __kernel_sin( x, y, iy)
* kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
* Input x is assumed to be bounded by ~pi/4 in magnitude.
* Input y is the tail of x.
* Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
*
* Algorithm
* 1. Since sin(-x) = -sin(x), we need only to consider positive x.
* 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
* 3. sin(x) is approximated by a polynomial of degree 13 on
* [0,pi/4]
* 3 13
* sin(x) ~ x + S1*x + ... + S6*x
* where
*
* |sin(x) 2 4 6 8 10 12 | -58
* |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2
* | x |
*
* 4. sin(x+y) = sin(x) + sin'(x')*y
* ~ sin(x) + (1-x*x/2)*y
* For better accuracy, let
* 3 2 2 2 2
* r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
* then 3 2
* sin(x) = x + (S1*x + (x *(r-y/2)+y))
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
#ifdef __STDC__
double __kernel_sin(double x, double y, int iy)
#else
double __kernel_sin(x, y, iy)
double x,y; int iy; /* iy=0 if y is zero */
#endif
{
double z,r,v;
int32_t ix;
GET_HIGH_WORD(ix,x);
ix &= 0x7fffffff; /* high word of x */
if(ix<0x3e400000) /* |x| < 2**-27 */
{if((int)x==0) return x;} /* generate inexact */
z = x*x;
v = z*x;
r = S2+z*(S3+z*(S4+z*(S5+z*S6)));
if(iy==0) return x+v*(S1+z*r);
else return x-((z*(half*y-v*r)-y)-v*S1);
}

View file

@ -0,0 +1,15 @@
#include <sys/types.h>
int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2);
double __kernel_sin(double x, double y, int iy);
double __kernel_cos(double x, double y);
double __ieee754_pow(double x, double y);
double __ieee754_sqrt(double x);
double __ieee754_log(double x);
int32_t __ieee754_rem_pio2(double x, double *y);
double fabs(double x);
double scalbn(double x, int n);
double copysign(double x, double y);
double floor(double x);

View file

@ -0,0 +1,129 @@
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* from: @(#)fdlibm.h 5.1 93/09/24
* $Id: math_private.h,v 1.3 2004/02/09 07:10:38 andersen Exp $
*/
#ifndef _MATH_PRIVATE_H_
#define _MATH_PRIVATE_H_
#include <endian.h>
#include <sys/types.h>
/* The original fdlibm code used statements like:
n0 = ((*(int*)&one)>>29)^1; * index of high word *
ix0 = *(n0+(int*)&x); * high word of x *
ix1 = *((1-n0)+(int*)&x); * low word of x *
to dig two 32 bit words out of the 64 bit IEEE floating point
value. That is non-ANSI, and, moreover, the gcc instruction
scheduler gets it wrong. We instead use the following macros.
Unlike the original code, we determine the endianness at compile
time, not at run time; I don't see much benefit to selecting
endianness at run time. */
/* A union which permits us to convert between a double and two 32 bit
ints. */
/*
* Math on arm is special:
* For FPA, float words are always big-endian.
* For VFP, floats words follow the memory system mode.
*/
#if (__BYTE_ORDER == __BIG_ENDIAN) || \
(!defined(__VFP_FP__) && (defined(__arm__) || defined(__thumb__)))
typedef union
{
double value;
struct
{
u_int32_t msw;
u_int32_t lsw;
} parts;
} ieee_double_shape_type;
#else
typedef union
{
double value;
struct
{
u_int32_t lsw;
u_int32_t msw;
} parts;
} ieee_double_shape_type;
#endif
/* Get two 32 bit ints from a double. */
#define EXTRACT_WORDS(ix0,ix1,d) \
do { \
ieee_double_shape_type ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.parts.msw; \
(ix1) = ew_u.parts.lsw; \
} while (0)
/* Get the more significant 32 bit int from a double. */
#define GET_HIGH_WORD(i,d) \
do { \
ieee_double_shape_type gh_u; \
gh_u.value = (d); \
(i) = gh_u.parts.msw; \
} while (0)
/* Get the less significant 32 bit int from a double. */
#define GET_LOW_WORD(i,d) \
do { \
ieee_double_shape_type gl_u; \
gl_u.value = (d); \
(i) = gl_u.parts.lsw; \
} while (0)
/* Set a double from two 32 bit ints. */
#define INSERT_WORDS(d,ix0,ix1) \
do { \
ieee_double_shape_type iw_u; \
iw_u.parts.msw = (ix0); \
iw_u.parts.lsw = (ix1); \
(d) = iw_u.value; \
} while (0)
/* Set the more significant 32 bits of a double from an int. */
#define SET_HIGH_WORD(d,v) \
do { \
ieee_double_shape_type sh_u; \
sh_u.value = (d); \
sh_u.parts.msw = (v); \
(d) = sh_u.value; \
} while (0)
/* Set the less significant 32 bits of a double from an int. */
#define SET_LOW_WORD(d,v) \
do { \
ieee_double_shape_type sl_u; \
sl_u.value = (d); \
sl_u.parts.lsw = (v); \
(d) = sl_u.value; \
} while (0)
#endif /* _MATH_PRIVATE_H_ */

View file

@ -0,0 +1,72 @@
/* Copyright (C) 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Philip Blundell <philb@gnu.org>
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
@ #include <sys/syscall.h>
.text
.global memset
.type memset,%function
.align 4
memset:
mov a4, a1
cmp a3, $8 @ at least 8 bytes to do?
blt 2f
orr a2, a2, a2, lsl $8
orr a2, a2, a2, lsl $16
1:
tst a4, $3 @ aligned yet?
strneb a2, [a4], $1
subne a3, a3, $1
bne 1b
mov ip, a2
1:
cmp a3, $8 @ 8 bytes still to do?
blt 2f
stmia a4!, {a2, ip}
sub a3, a3, $8
cmp a3, $8 @ 8 bytes still to do?
blt 2f
stmia a4!, {a2, ip}
sub a3, a3, $8
cmp a3, $8 @ 8 bytes still to do?
blt 2f
stmia a4!, {a2, ip}
sub a3, a3, $8
cmp a3, $8 @ 8 bytes still to do?
stmgeia a4!, {a2, ip}
subge a3, a3, $8
bge 1b
2:
movs a3, a3 @ anything left?
moveq pc, lr @ nope
rsb a3, a3, $7
add pc, pc, a3, lsl $2
mov r0, r0
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
mov pc, lr
.size memset,.-memset;

View file

@ -0,0 +1,39 @@
/* @(#)s_copysign.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_copysign.c,v 1.8 1995/05/10 20:46:57 jtc Exp $";
#endif
/*
* copysign(double x, double y)
* copysign(x,y) returns a value with the magnitude of x and
* with the sign bit of y.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
double copysign(double x, double y)
#else
double copysign(x,y)
double x,y;
#endif
{
u_int32_t hx,hy;
GET_HIGH_WORD(hx,x);
GET_HIGH_WORD(hy,y);
SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000));
return x;
}

View file

@ -0,0 +1,35 @@
/* @(#)s_fabs.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_fabs.c,v 1.7 1995/05/10 20:47:13 jtc Exp $";
#endif
/*
* fabs(x) returns the absolute value of x.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
double fabs(double x)
#else
double fabs(x)
double x;
#endif
{
u_int32_t high;
GET_HIGH_WORD(high,x);
SET_HIGH_WORD(x,high&0x7fffffff);
return x;
}

View file

@ -0,0 +1,81 @@
/* @(#)s_floor.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_floor.c,v 1.8 1995/05/10 20:47:20 jtc Exp $";
#endif
/*
* floor(x)
* Return x rounded toward -inf to integral value
* Method:
* Bit twiddling.
* Exception:
* Inexact flag raised if x not equal to floor(x).
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double huge = 1.0e300;
#else
static double huge = 1.0e300;
#endif
#ifdef __STDC__
double floor(double x)
#else
double floor(x)
double x;
#endif
{
int32_t i0,i1,j0;
u_int32_t i,j;
EXTRACT_WORDS(i0,i1,x);
j0 = ((i0>>20)&0x7ff)-0x3ff;
if(j0<20) {
if(j0<0) { /* raise inexact if x != 0 */
if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
if(i0>=0) {i0=i1=0;}
else if(((i0&0x7fffffff)|i1)!=0)
{ i0=0xbff00000;i1=0;}
}
} else {
i = (0x000fffff)>>j0;
if(((i0&i)|i1)==0) return x; /* x is integral */
if(huge+x>0.0) { /* raise inexact flag */
if(i0<0) i0 += (0x00100000)>>j0;
i0 &= (~i); i1=0;
}
}
} else if (j0>51) {
if(j0==0x400) return x+x; /* inf or NaN */
else return x; /* x is integral */
} else {
i = ((u_int32_t)(0xffffffff))>>(j0-20);
if((i1&i)==0) return x; /* x is integral */
if(huge+x>0.0) { /* raise inexact flag */
if(i0<0) {
if(j0==20) i0+=1;
else {
j = i1+(1<<(52-j0));
if(j<i1) i0 +=1 ; /* got a carry */
i1=j;
}
}
i1 &= (~i);
}
}
INSERT_WORDS(x,i0,i1);
return x;
}

View file

@ -0,0 +1,67 @@
/* @(#)s_scalbn.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_scalbn.c,v 1.8 1995/05/10 20:48:08 jtc Exp $";
#endif
/*
* scalbn (double x, int n)
* scalbn(x,n) returns x* 2**n computed by exponent
* manipulation rather than by actually performing an
* exponentiation or a multiplication.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
huge = 1.0e+300,
tiny = 1.0e-300;
#ifdef __STDC__
double scalbn (double x, int n)
#else
double scalbn (x,n)
double x; int n;
#endif
{
int32_t k,hx,lx;
EXTRACT_WORDS(hx,lx,x);
k = (hx&0x7ff00000)>>20; /* extract exponent */
if (k==0) { /* 0 or subnormal x */
if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
x *= two54;
GET_HIGH_WORD(hx,x);
k = ((hx&0x7ff00000)>>20) - 54;
if (n< -50000) return tiny*x; /*underflow*/
}
if (k==0x7ff) return x+x; /* NaN or Inf */
k = k+n;
if (k > 0x7fe) return huge*copysign(huge,x); /* overflow */
if (k > 0) /* normal result */
{SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
if (k <= -54) {
if (n > 50000) /* in case integer overflow in n+k */
return huge*copysign(huge,x); /*overflow*/
else return tiny*copysign(tiny,x); /*underflow*/
}
k += 54; /* subnormal result */
SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
return x*twom54;
}

View file

@ -0,0 +1,82 @@
/* @(#)s_sin.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_sin.c,v 1.7 1995/05/10 20:48:15 jtc Exp $";
#endif
/* sin(x)
* Return sine function of x.
*
* kernel function:
* __kernel_sin ... sine function on [-pi/4,pi/4]
* __kernel_cos ... cose function on [-pi/4,pi/4]
* __ieee754_rem_pio2 ... argument reduction routine
*
* Method.
* Let S,C and T denote the sin, cos and tan respectively on
* [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
* in [-pi/4 , +pi/4], and let n = k mod 4.
* We have
*
* n sin(x) cos(x) tan(x)
* ----------------------------------------------------------
* 0 S C T
* 1 C -S -1/T
* 2 -S -C T
* 3 -C S -1/T
* ----------------------------------------------------------
*
* Special cases:
* Let trig be any of sin, cos, or tan.
* trig(+-INF) is NaN, with signals;
* trig(NaN) is that NaN;
*
* Accuracy:
* TRIG(x) returns trig(x) nearly rounded
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
double sin(double x)
#else
double sin(x)
double x;
#endif
{
double y[2],z=0.0;
int32_t n, ix;
/* High word of x. */
GET_HIGH_WORD(ix,x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0);
/* sin(Inf or NaN) is NaN */
else if (ix>=0x7ff00000) return x-x;
/* argument reduction needed */
else {
n = __ieee754_rem_pio2(x,y);
switch(n&3) {
case 0: return __kernel_sin(y[0],y[1],1);
case 1: return __kernel_cos(y[0],y[1]);
case 2: return -__kernel_sin(y[0],y[1],1);
default:
return -__kernel_cos(y[0],y[1]);
}
}
}

View file

@ -0,0 +1,12 @@
#include "math.h"
double pow(double x, double y)
{
return __ieee754_pow(x, y);
}
double log(double x)
{
return __ieee754_log(x);
}

424
platform/gp2x/usbjoy.c Normal file
View file

@ -0,0 +1,424 @@
/* Title: USB Joystick library
Version 0.2
Written by Puck2099 (puck2099@gmail.com), (c) 2006.
<http://www.gp32wip.com>
If you use this library or a part of it, please, let it know.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h> /* For the definition of NULL */
#include <sys/types.h> // For Device open
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h> // For Device read
#include <string.h>
#include <limits.h> /* For the definition of PATH_MAX */
#include <linux/joystick.h>
#include "usbjoy.h"
/*
Function: joy_open
Opens a USB joystick and fills its information.
Parameters:
joynumber - Joystick's identifier (0 reserved for GP2X's builtin Joystick).
Returns:
Filled usbjoy structure.
*/
struct usbjoy *joy_open(int joynumber)
{
int fd;
char path [128];
struct usbjoy * joy = NULL;
struct js_event event;
static char insmod_done = 0;
// notaz: on my system I get unresolved input_* symbols, so have to 'insmod input' too
// also we should insmod only once, not on every joy_open() call.
if (!insmod_done) {
system ("insmod input");
system ("insmod joydev"); // Loads joydev module
insmod_done = 1;
}
if (joynumber == 0) {
}
else if (joynumber > 0) {
sprintf (path, "/dev/input/js%d", joynumber-1);
fd = open(path, O_RDONLY, 0);
if (fd > 0) {
joy = (struct usbjoy *) malloc(sizeof(*joy));
if (joy == NULL) { close(fd); return NULL; }
memset(joy, 0, sizeof(*joy));
// Set the joystick to non-blocking read mode
fcntl(fd, F_SETFL, O_NONBLOCK);
// notaz: maybe we should flush init events now.
// My pad returns axis as active when I plug it in, which is kind of annoying.
while (read(fd, &event, sizeof(event)) > 0);
// Joystick's file descriptor
joy->fd = fd;
// Joystick's name
ioctl(joy->fd, JSIOCGNAME(128*sizeof(char)), joy->name);
// Joystick's device
strcpy(joy->device, path);
// Joystick's buttons
ioctl(joy->fd, JSIOCGBUTTONS, &joy->numbuttons);
// Joystick's axes
ioctl(joy->fd, JSIOCGAXES, &joy->numaxes);
// Joystick's type (derived from name)
if (strncasecmp(joy->name, "logitech", strlen("logitech")) == 0)
joy->type = JOY_TYPE_LOGITECH;
else joy->type = JOY_TYPE_GENERIC;
} else {
// printf ("ERROR: No Joystick found\n");
}
}
return joy;
}
/*
Function: joy_name
Returns Joystick's name.
Parameters:
joy - Selected joystick.
Returns:
Joystick's name or NULL if <usbjoy> struct is empty.
*/
char * joy_name (struct usbjoy * joy) {
if (joy != NULL) return joy->name;
else return NULL;
}
/*
Function: joy_device
Returns Joystick's device.
Parameters:
joy - Selected joystick.
Returns:
Joystick's device or NULL if <usbjoy> struct is empty.
*/
char * joy_device (struct usbjoy * joy) {
if (joy != NULL) return joy->device;
else return NULL;
}
/*
Function: joy_buttons
Returns Joystick's buttons number.
Parameters:
joy - Selected joystick.
Returns:
Joystick's buttons or 0 if <usbjoy> struct is empty.
*/
int joy_buttons (struct usbjoy * joy) {
if (joy != NULL) return joy->numbuttons;
else return 0;
}
/*
Function: joy_axes
Returns Joystick's axes number.
Parameters:
joy - Selected joystick.
Returns:
Joystick's axes or 0 if <usbjoy> struct is empty.
*/
int joy_axes (struct usbjoy * joy) {
if (joy != NULL) return joy->numaxes;
else return 0;
}
/*
Function: joy_update
Updates Joystick's internal information (<statebuttons> and <stateaxes> fields).
Parameters:
joy - Selected joystick.
Returns:
0 - No events registered (no need to update).
1 - Events registered (a button or axe has been pushed).
-1 - Error: <usbjoy> struct is empty.
*/
int joy_update (struct usbjoy * joy) {
struct js_event events[0xff];
int i, len;
int event = 0;
if (joy != NULL) {
if ((len=read(joy->fd, events, (sizeof events))) >0) {
len /= sizeof(events[0]);
for ( i=0; i<len; ++i ) {
switch (events[i].type & ~JS_EVENT_INIT) {
case JS_EVENT_AXIS:
if (events[i].number == 0) {
if (events[i].value == 0) joy->stateaxes[JOYLEFT] = joy->stateaxes[JOYRIGHT] = 0;
else if (events[i].value < 0) joy->stateaxes[JOYLEFT] = 1;
else joy->stateaxes[JOYRIGHT] = 1;
}
else if (events[i].number == 1) {
if (events[i].value == 0) joy->stateaxes[JOYUP] = joy->stateaxes[JOYDOWN] = 0;
else if (events[i].value < 0) joy->stateaxes[JOYUP] = 1;
else joy->stateaxes[JOYDOWN] = 1;
}
event = 1;
break;
case JS_EVENT_BUTTON:
joy->statebuttons[events[i].number] = events[i].value;
event = 1;
break;
default:
break;
}
}
}
}
else {
event = -1;
}
return event;
}
/*
Function: joy_getbutton
Returns Joystick's button information.
Parameters:
button - Button which value you want to know (from 0 to 31).
joy - Selected joystick.
Returns:
0 - Button NOT pushed.
1 - Button pushed.
-1 - Error: <usbjoy> struct is empty.
*/
int joy_getbutton (int button, struct usbjoy * joy) {
if (joy != NULL) {
if (button < joy_buttons(joy)) return joy->statebuttons[button];
else return 0;
}
else return -1;
}
/*
Function: joy_getaxe
Returns Joystick's axes information.
Parameters:
axe - Axe which value you want to know (see <Axes values>).
joy - Selected joystick.
Returns:
0 - Direction NOT pushed.
1 - Direction pushed.
-1 - Error: <usbjoy> struct is empty.
*/
int joy_getaxe (int axe, struct usbjoy * joy) {
if (joy != NULL) {
if (axe < 4) return joy->stateaxes[axe];
else return 0;
}
else return -1;
}
/*
Function: joy_close
Closes selected joystick's file descriptor and detroys it's fields.
Parameters:
joy - Selected joystick.
Returns:
0 - Joystick successfully closed.
-1 - Error: <usbjoy> struct is empty.
*/
int joy_close (struct usbjoy * joy) {
if (joy != NULL) {
close (joy->fd);
free (joy);
return 0;
}
else return -1;
}
/*********************************************************************/
/* GP2X USB Joystick Handling -GnoStiC */
/*********************************************************************/
#include "gp2x.h"
int num_of_joys = 0;
struct usbjoy *joys[4];
void gp2x_usbjoy_init (void) {
/* Open available joysticks -GnoStiC */
int i, n = 0;
printf("\n");
for (i = 0; i < 4; i++) {
joys[n] = joy_open(i+1);
if (joys[n] && joy_buttons(joys[n]) > 0) {
printf ("+-Joystick %d: \"%s\", buttons = %i\n", i+1, joy_name(joys[n]), joy_buttons(joys[n]));
n++;
}
}
num_of_joys = n;
printf("Found %d Joystick(s)\n",num_of_joys);
}
void gp2x_usbjoy_update (void) {
/* Update Joystick Event Cache */
int q, foo;
for (q=0; q < num_of_joys; q++) {
foo = joy_update (joys[q]);
}
}
int gp2x_usbjoy_check (int joyno) {
/* Check Joystick */
int q, joyExKey = 0;
struct usbjoy *joy = joys[joyno];
if (joy != NULL) {
if (joy_getaxe(JOYUP, joy)) { joyExKey |= GP2X_UP; }
if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= GP2X_DOWN; }
if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= GP2X_LEFT; }
if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= GP2X_RIGHT; }
/* loop through joy buttons to check if they are pushed */
for (q=0; q<joy_buttons (joy); q++) {
if (joy_getbutton (q, joy)) {
if (joy->type == JOY_TYPE_LOGITECH) {
switch (q) {
case 0: joyExKey |= GP2X_A; break;
case 1: joyExKey |= GP2X_X; break;
case 2: joyExKey |= GP2X_B; break;
case 3: joyExKey |= GP2X_Y; break;
}
} else {
switch (q) {
case 0: joyExKey |= GP2X_Y; break;
case 1: joyExKey |= GP2X_B; break;
case 2: joyExKey |= GP2X_X; break;
case 3: joyExKey |= GP2X_A; break;
}
}
switch (q) {
case 4: joyExKey |= GP2X_L; break;
case 5: joyExKey |= GP2X_R; break;
case 6: joyExKey |= GP2X_L; break; /* left shoulder button 2 */
case 7: joyExKey |= GP2X_R; break; /* right shoulder button 2 */
case 8: joyExKey |= GP2X_SELECT;break;
case 9: joyExKey |= GP2X_START; break;
case 10: joyExKey |= GP2X_PUSH; break;
case 11: joyExKey |= GP2X_PUSH; break;
}
}
}
}
return joyExKey;
}
int gp2x_usbjoy_check2 (int joyno) {
/* Check Joystick, don't map to gp2x joy */
int q, to, joyExKey = 0;
struct usbjoy *joy = joys[joyno];
if (joy != NULL) {
if (joy_getaxe(JOYUP, joy)) { joyExKey |= 1 << 0; }
if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= 1 << 1; }
if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= 1 << 2; }
if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= 1 << 3; }
/* loop through joy buttons to check if they are pushed */
to = joy->numbuttons;
if (to > 32-4) to = 32-4;
for (q=0; q < to; q++)
if (joy->statebuttons[q]) joyExKey |= 1 << (q+4);
}
return joyExKey;
}
void gp2x_usbjoy_deinit (void) {
int i;
for (i=0; i<num_of_joys; i++) {
joy_close (joys[i]);
}
num_of_joys = 0;
}

241
platform/gp2x/usbjoy.h Normal file
View file

@ -0,0 +1,241 @@
/* Title: USB Joystick library
Version 0.2
Written by Puck2099 (puck2099@gmail.com), (c) 2006.
<http://www.gp32wip.com>
If you use this library or a part of it, please, let it know.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef USBJOY_H
#define USBJOY_H
/* notaz: my Logitech has different button layout, and I want it to match gptx's */
typedef enum {
JOY_TYPE_GENERIC,
JOY_TYPE_LOGITECH
} joy_type;
/*
Enumeration: Axes values
This enumeration contains shortcuts to the values used on axes.
Constants:
JOYUP - Joystick Up
JOYDOWN - Joystick Down
JOYLEFT - Joystick Left
JOYRIGHT - Joystick Right
See also:
<joy_getaxe>
*/
#define JOYUP (0)
#define JOYDOWN (1)
#define JOYLEFT (2)
#define JOYRIGHT (3)
/*
Struct: usbjoy
Contains all Joystick needed information.
Fields:
fd - File descriptor used.
name - Joystick's name.
device - /dev/input/jsX device.
numbuttons - Joystick's buttons.
numaxes - Joystick's axes.
numhats - Joystick's hats.
statebuttons - Current state of each button.
stateaxes - Current state of each direction.
*/
struct usbjoy {
int fd;
char name [128];
char device [128];
int numbuttons;
int numaxes;
int numhats;
int statebuttons[32];
int stateaxes[4];
joy_type type;
};
/*
Function: joy_open
Opens a USB joystick and fills its information.
Parameters:
joynumber - Joystick's identifier (0 reserved for GP2X's builtin Joystick).
Returns:
Filled usbjoy structure.
*/
struct usbjoy * joy_open (int joynumber);
/*
Function: joy_name
Returns Joystick's name.
Parameters:
joy - Selected joystick.
Returns:
Joystick's name or NULL if <usbjoy> struct is empty.
*/
char * joy_name (struct usbjoy * joy);
/*
Function: joy_device
Returns Joystick's device.
Parameters:
joy - Selected joystick.
Returns:
Joystick's device or NULL if <usbjoy> struct is empty.
*/
char * joy_device (struct usbjoy * joy);
/*
Function: joy_buttons
Returns Joystick's buttons number.
Parameters:
joy - Selected joystick.
Returns:
Joystick's buttons or 0 if <usbjoy> struct is empty.
*/
int joy_buttons (struct usbjoy * joy);
/*
Function: joy_axes
Returns Joystick's axes number.
Parameters:
joy - Selected joystick.
Returns:
Joystick's axes or 0 if <usbjoy> struct is empty.
*/
int joy_axes (struct usbjoy * joy);
/*
Function: joy_update
Updates Joystick's internal information (<statebuttons> and <stateaxes> fields).
Parameters:
joy - Selected joystick.
Returns:
0 - No events registered (no need to update).
1 - Events registered (a button or axe has been pushed).
-1 - Error: <usbjoy> struct is empty.
*/
int joy_update (struct usbjoy * joy);
/*
Function: joy_getbutton
Returns Joystick's button information.
Parameters:
button - Button which value you want to know (from 0 to 31).
joy - Selected joystick.
Returns:
0 - Button NOT pushed.
1 - Button pushed.
-1 - Error: <usbjoy> struct is empty.
*/
int joy_getbutton (int button, struct usbjoy * joy);
/*
Function: joy_getaxe
Returns Joystick's axes information.
Parameters:
axe - Axe which value you want to know (see <Axes values>).
joy - Selected joystick.
Returns:
0 - Direction NOT pushed.
1 - Direction pushed.
-1 - Error: <usbjoy> struct is empty.
*/
int joy_getaxe (int axe, struct usbjoy * joy);
/*
Function: joy_close
Closes selected joystick's file descriptor and detroys it's fields.
Parameters:
joy - Selected joystick.
Returns:
0 - Joystick successfully closed.
-1 - Error: <usbjoy> struct is empty.
*/
int joy_close (struct usbjoy * joy);
/* gp2x stuff */
extern int num_of_joys;
extern struct usbjoy *joys[4];
void gp2x_usbjoy_update(void);
void gp2x_usbjoy_init(void);
int gp2x_usbjoy_check(int joyno);
int gp2x_usbjoy_check2(int joyno);
void gp2x_usbjoy_deinit(void);
#endif // USBJOY_H

2
platform/gp2x/version.h Normal file
View file

@ -0,0 +1,2 @@
#define VERSION "0.964"

View file

@ -0,0 +1,112 @@
/* faked 940 code just uses local copy of ym2612 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include "../../Pico/sound/ym2612.h"
#include "../gp2x/gp2x.h"
#include "../gp2x/emu.h"
#include "../gp2x/menu.h"
static YM2612 ym2612;
YM2612 *ym2612_940 = &ym2612;
int mix_buffer_[44100/50*2]; /* this is where the YM2612 samples will be mixed to */
int *mix_buffer = mix_buffer_;
/***********************************************************/
#define MAXOUT (+32767)
#define MINOUT (-32768)
/* limitter */
#define Limit(val, max,min) { \
if ( val > max ) val = max; \
else if ( val < min ) val = min; \
}
int YM2612Write_940(unsigned int a, unsigned int v)
{
YM2612Write_(a, v);
return 0; // cause the engine to do updates once per frame only
}
UINT8 YM2612Read_940(void)
{
return YM2612Read_();
}
int YM2612PicoTick_940(int n)
{
YM2612PicoTick_(n);
return 0;
}
void YM2612PicoStateLoad_940(void)
{
int i;
YM2612PicoStateLoad_();
for(i = 0; i < 0x100; i++) {
YM2612Write_(0, i);
YM2612Write_(1, ym2612.REGS[i]);
}
for(i = 0; i < 0x100; i++) {
YM2612Write_(2, i);
YM2612Write_(3, ym2612.REGS[i|0x100]);
}
}
void YM2612Init_940(int baseclock, int rate)
{
YM2612Init_(baseclock, rate);
}
void YM2612ResetChip_940(void)
{
YM2612ResetChip_();
}
void YM2612UpdateOne_940(short *buffer, int length, int stereo)
{
int i;
YM2612UpdateOne_(buffer, length, stereo);
/* mix data */
if (stereo) {
int *mb = mix_buffer;
for (i = length; i > 0; i--) {
int l, r;
l = r = *buffer;
l += *mb++, r += *mb++;
Limit( l, MAXOUT, MINOUT );
Limit( r, MAXOUT, MINOUT );
*buffer++ = l; *buffer++ = r;
}
} else {
for (i = 0; i < length; i++) {
int l = mix_buffer[i];
l += buffer[i];
Limit( l, MAXOUT, MINOUT );
buffer[i] = l;
}
}
}

91
platform/linux/Makefile Normal file
View file

@ -0,0 +1,91 @@
# settings
dprint = 1
# profile = 1
DEFINC = -I../.. -I. -D__GP2X__ -D_UNZIP_SUPPORT # -DBENCHMARK
GCC = gcc
STRIP = strip
AS = gcc
ifeq "$(profile)" "1"
COPT_COMMON = -s -O3 -ftracer -fstrength-reduce -Wall -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math -fprofile-generate # -static
COPT = $(COPT_COMMON) # -mtune=arm920t
else
COPT = -ggdb -Wall -fno-strict-aliasing # -pg -O3 -ftracer -fstrength-reduce -funroll-loops -fomit-frame-pointer -ffast-math
COPT_COMMON = $(COPT)
endif
# gtk
COPT += `pkg-config --cflags gtk+-2.0`
LDFLAGS += `pkg-config --libs gtk+-2.0`
COPT += `pkg-config --cflags gthread-2.0`
LDFLAGS += `pkg-config --libs gthread-2.0`
# frontend
OBJS += ../gp2x/main.o ../gp2x/menu.o ../gp2x/emu.o ../gp2x/usbjoy.o blit.o gp2x.o 940ctl_ym2612.o
# Pico
OBJS += ../../Pico/Area.o ../../Pico/Cart.o ../../Pico/Utils.o ../../Pico/Memory.o ../../Pico/Misc.o \
../../Pico/Pico.o ../../Pico/Sek.o ../../Pico/VideoPort.o ../../Pico/Draw2.o ../../Pico/Draw.o
# Pico - CD
OBJS += ../../Pico/cd/Pico.o ../../Pico/cd/Memory.o ../../Pico/cd/Sek.o ../../Pico/cd/LC89510.o \
../../Pico/cd/cd_sys.o
# Pico - sound
OBJS += ../../Pico/sound/sound.o ../../Pico/sound/sn76496.o ../../Pico/sound/ym2612.o
# zlib
OBJS += ../../zlib/gzio.o ../../zlib/inffast.o ../../zlib/inflate.o ../../zlib/inftrees.o ../../zlib/trees.o \
../../zlib/deflate.o ../../zlib/crc32.o ../../zlib/adler32.o ../../zlib/zutil.o ../../zlib/compress.o
# unzip
OBJS += ../../unzip/unzip.o
# CPU cores
DEFINC += -DEMU_M68K
OBJS += ../../cpu/musashi/m68kcpu.o ../../cpu/musashi/m68kopac.o ../../cpu/musashi/m68kopdm.o \
../../cpu/musashi/m68kopnz.o ../../cpu/musashi/m68kops.o
# mz80
DEFINC += -D_USE_MZ80
OBJS += ../../cpu/mz80/mz80.o
# faked asm
#DEFINC += -D_ASM_DRAW_C
#DEFINC += -D_ASM_MEMORY_C
#DEFINC += -D_ASM_YM2612_C
OBJS += fakedasm.o
all: PicoDrive
clean: tidy
@$(RM) PicoDrive
tidy:
@$(RM) $(OBJS)
@make -C ../../cpu/mz80/ clean
PicoDrive : $(OBJS)
@echo $@
@$(GCC) $(COPT) $(OBJS) $(LDFLAGS) -lm -o $@
../../cpu/mz80/mz80.o : ../../cpu/mz80/mz80.asm
@echo $@
@nasm -f elf $< -o $@
../../cpu/mz80/mz80.asm :
@make -C ../../cpu/mz80/
.c.o:
@echo $<
@$(GCC) $(COPT) $(DEFINC) -c $< -o $@
.s.o:
@echo $<
@$(GCC) $(COPT) $(DEFINC) -c $< -o $@
../../Pico/sound/ym2612.o : ../../Pico/sound/ym2612.c
@echo $@
@$(GCC) $(COPT_COMMON) $(DEFINC) -DEXTERNAL_YM2612 -c $< -o $@ # -mtune=arm940t
# faked asm
../../Pico/Draw.o : ../../Pico/Draw.c
@echo $<
@$(GCC) $(COPT) $(DEFINC) -D_ASM_DRAW_C -c $< -o $@

4
platform/linux/README Normal file
View file

@ -0,0 +1,4 @@
This port tries to emulate gp2x environment on a standard linux box for testing
(i.e. to be able to use things like valgrind and efence, gcc runtime
optimizations, etc.).

81
platform/linux/blit.c Normal file
View file

@ -0,0 +1,81 @@
// Convert 0000bbb0 ggg0rrr0 0000bbb0 ggg0rrr0
// to 00000000 rrr00000 ggg00000 bbb00000 ...
void vidConvCpyRGB32 (void *to, void *from, int pixels)
{
unsigned short *ps = from;
unsigned int *pd = to;
for (; pixels; pixels--, ps++, pd++)
{
*pd = ((*ps<<20)&0xe00000) | ((*ps<<8)&0xe000) | ((*ps>>4)&0xe0);
*pd |= *pd >> 3;
}
}
void vidConvCpyRGB32sh(void *to, void *from, int pixels)
{
unsigned short *ps = from;
unsigned int *pd = to;
for (; pixels; pixels--, ps++, pd++)
{
*pd = ((*ps<<20)&0xe00000) | ((*ps<<8)&0xe000) | ((*ps>>4)&0xe0);
*pd >>= 1;
*pd |= *pd >> 3;
}
}
void vidConvCpyRGB32hi(void *to, void *from, int pixels)
{
unsigned short *ps = from;
unsigned int *pd = to;
for (; pixels; pixels--, ps++, pd++)
{
*pd = ((*ps<<20)&0xe00000) | ((*ps<<8)&0xe000) | ((*ps>>4)&0xe0);
continue;
*pd += 0x00404040;
if (*pd & 0x01000000) *pd |= 0x00e00000;
if (*pd & 0x00010000) *pd |= 0x0000e000;
if (*pd & 0x00000100) *pd |= 0x000000e0;
*pd &= 0x00e0e0e0;
*pd |= *pd >> 3;
}
}
void vidCpyM2_40col(void *dest, void *src)
{
unsigned char *pd = dest, *ps = src;
int i, u;
for (i = 0; i < 224; i++)
{
ps += 8;
for (u = 0; u < 320; u++)
*pd++ = *ps++;
}
}
void vidCpyM2_32col(void *dest, void *src)
{
unsigned char *pd = dest, *ps = src;
int i, u;
for (i = 0; i < 224; i++)
{
ps += 8;
pd += 32;
for (u = 0; u < 256; u++)
*pd++ = *ps++;
ps += 64;
pd += 32;
}
}
void vidCpyM2_32col_nobord(void *dest, void *src)
{
vidCpyM2_32col(dest, src);
}

667
platform/linux/fakedasm.c Normal file
View file

@ -0,0 +1,667 @@
// This is part of Pico Library
// (c) Copyright 2004 Dave, All rights reserved.
// (c) Copyright 2006 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include "../../Pico/PicoInt.h"
#undef blockcpy
extern unsigned short DefOutBuff[320*2];
extern unsigned char HighCol[8+320+8];
extern char HighSprZ[320+8+8]; // Z-buffer for accurate sprites and shadow/hilight mode
// (if bit 7 == 0, sh caused by tile; if bit 6 == 0 pixel must be shadowed, else hilighted, if bit5 == 1)
// lsb->msb: moved sprites, all window tiles don't use same priority, accurate sprites (copied from PicoOpt), interlace
// dirty sprites, sonic mode
extern int rendstatus;
extern int Scanline; // Scanline
struct TileStrip
{
int nametab; // Position in VRAM of name table (for this tile line)
int line; // Line number in pixels 0x000-0x3ff within the virtual tilemap
int hscroll; // Horizontal scroll value in pixels for the line
int xmask; // X-Mask (0x1f - 0x7f) for horizontal wraparound in the tilemap
int *hc; // cache for high tile codes and their positions
int cells; // cells (tiles) to draw (32 col mode doesn't need to update whole 320)
};
// utility
void *blockcpy(void *dst, const void *src, size_t n)
{
return memcpy(dst, src, n);
}
void blockcpy_or(void *dst, void *src, size_t n, int pat)
{
unsigned char *pd = dst, *ps = src;
for (; n; n--)
*pd++ = (unsigned char) (*ps++ | pat);
}
static int TileNorm(int sx,int addr,int pal)
{
unsigned char *pd = HighCol+sx;
unsigned int pack=0; unsigned int t=0;
pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels
if (pack)
{
t=pack&0x0000f000; if (t) pd[0]=(unsigned char)(pal|(t>>12));
t=pack&0x00000f00; if (t) pd[1]=(unsigned char)(pal|(t>> 8));
t=pack&0x000000f0; if (t) pd[2]=(unsigned char)(pal|(t>> 4));
t=pack&0x0000000f; if (t) pd[3]=(unsigned char)(pal|(t ));
t=pack&0xf0000000; if (t) pd[4]=(unsigned char)(pal|(t>>28));
t=pack&0x0f000000; if (t) pd[5]=(unsigned char)(pal|(t>>24));
t=pack&0x00f00000; if (t) pd[6]=(unsigned char)(pal|(t>>20));
t=pack&0x000f0000; if (t) pd[7]=(unsigned char)(pal|(t>>16));
return 0;
}
return 1; // Tile blank
}
static int TileFlip(int sx,int addr,int pal)
{
unsigned char *pd = HighCol+sx;
unsigned int pack=0; unsigned int t=0;
pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels
if (pack)
{
t=pack&0x000f0000; if (t) pd[0]=(unsigned char)(pal|(t>>16));
t=pack&0x00f00000; if (t) pd[1]=(unsigned char)(pal|(t>>20));
t=pack&0x0f000000; if (t) pd[2]=(unsigned char)(pal|(t>>24));
t=pack&0xf0000000; if (t) pd[3]=(unsigned char)(pal|(t>>28));
t=pack&0x0000000f; if (t) pd[4]=(unsigned char)(pal|(t ));
t=pack&0x000000f0; if (t) pd[5]=(unsigned char)(pal|(t>> 4));
t=pack&0x00000f00; if (t) pd[6]=(unsigned char)(pal|(t>> 8));
t=pack&0x0000f000; if (t) pd[7]=(unsigned char)(pal|(t>>12));
return 0;
}
return 1; // Tile blank
}
// tile renderers for hacky operator sprite support
#define sh_pix(x) \
if(!t); \
else if(t==0xe) pd[x]=(unsigned char)((pd[x]&0x3f)|0x80); /* hilight */ \
else if(t==0xf) pd[x]=(unsigned char)((pd[x]&0x3f)|0xc0); /* shadow */ \
else pd[x]=(unsigned char)(pal|t);
static int TileNormSH(int sx,int addr,int pal)
{
unsigned int pack=0; unsigned int t=0;
unsigned char *pd = HighCol+sx;
pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels
if (pack)
{
t=(pack&0x0000f000)>>12; sh_pix(0);
t=(pack&0x00000f00)>> 8; sh_pix(1);
t=(pack&0x000000f0)>> 4; sh_pix(2);
t=(pack&0x0000000f) ; sh_pix(3);
t=(pack&0xf0000000)>>28; sh_pix(4);
t=(pack&0x0f000000)>>24; sh_pix(5);
t=(pack&0x00f00000)>>20; sh_pix(6);
t=(pack&0x000f0000)>>16; sh_pix(7);
return 0;
}
return 1; // Tile blank
}
static int TileFlipSH(int sx,int addr,int pal)
{
unsigned int pack=0; unsigned int t=0;
unsigned char *pd = HighCol+sx;
pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels
if (pack)
{
t=(pack&0x000f0000)>>16; sh_pix(0);
t=(pack&0x00f00000)>>20; sh_pix(1);
t=(pack&0x0f000000)>>24; sh_pix(2);
t=(pack&0xf0000000)>>28; sh_pix(3);
t=(pack&0x0000000f) ; sh_pix(4);
t=(pack&0x000000f0)>> 4; sh_pix(5);
t=(pack&0x00000f00)>> 8; sh_pix(6);
t=(pack&0x0000f000)>>12; sh_pix(7);
return 0;
}
return 1; // Tile blank
}
// --------------------------------------------
static void DrawStrip(struct TileStrip *ts, int sh)
{
int tilex=0,dx=0,ty=0,code=0,addr=0,cells;
int oldcode=-1,blank=-1; // The tile we know is blank
int pal=0;
// Draw tiles across screen:
tilex=(-ts->hscroll)>>3;
ty=(ts->line&7)<<1; // Y-Offset into tile
dx=((ts->hscroll-1)&7)+1;
cells = ts->cells;
if(dx != 8) cells++; // have hscroll, need to draw 1 cell more
for (; cells; dx+=8,tilex++,cells--)
{
int zero=0;
code=Pico.vram[ts->nametab+(tilex&ts->xmask)];
if (code==blank) continue;
if (code>>15) { // high priority tile
int cval = code | (dx<<16) | (ty<<25);
if(code&0x1000) cval^=7<<26;
*ts->hc++ = cval; // cache it
continue;
}
if (code!=oldcode) {
oldcode = code;
// Get tile address/2:
addr=(code&0x7ff)<<4;
addr+=ty;
if (code&0x1000) addr^=0xe; // Y-flip
// pal=Pico.cram+((code>>9)&0x30);
pal=((code>>9)&0x30)|(sh<<6);
}
if (code&0x0800) zero=TileFlip(dx,addr,pal);
else zero=TileNorm(dx,addr,pal);
if (zero) blank=code; // We know this tile is blank now
}
// terminate the cache list
*ts->hc = 0;
}
static void DrawStripVSRam(struct TileStrip *ts, int plane)
{
int tilex=0,dx=0,ty=0,code=0,addr=0,cell=0,nametabadd=0;
int oldcode=-1,blank=-1; // The tile we know is blank
int pal=0,scan=Scanline;
// Draw tiles across screen:
tilex=(-ts->hscroll)>>3;
dx=((ts->hscroll-1)&7)+1;
if(dx != 8) {
int vscroll, line;
cell--; // have hscroll, start with negative cell
// also calculate intial VS stuff
vscroll=Pico.vsram[plane];
// Find the line in the name table
line=(vscroll+scan)&ts->line&0xffff; // ts->line is really ymask ..
nametabadd=(line>>3)<<(ts->line>>24); // .. and shift[width]
ty=(line&7)<<1; // Y-Offset into tile
}
for (; cell < ts->cells; dx+=8,tilex++,cell++)
{
int zero=0;
if((cell&1)==0) {
int line,vscroll;
vscroll=Pico.vsram[plane+(cell&~1)];
// Find the line in the name table
line=(vscroll+scan)&ts->line&0xffff; // ts->line is really ymask ..
nametabadd=(line>>3)<<(ts->line>>24); // .. and shift[width]
ty=(line&7)<<1; // Y-Offset into tile
}
code=Pico.vram[ts->nametab+nametabadd+(tilex&ts->xmask)];
if (code==blank) continue;
if (code>>15) { // high priority tile
int cval = code | (dx<<16) | (ty<<25);
if(code&0x1000) cval^=7<<26;
*ts->hc++ = cval; // cache it
continue;
}
if (code!=oldcode) {
oldcode = code;
// Get tile address/2:
addr=(code&0x7ff)<<4;
if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip
// pal=Pico.cram+((code>>9)&0x30);
pal=((code>>9)&0x30);
}
if (code&0x0800) zero=TileFlip(dx,addr,pal);
else zero=TileNorm(dx,addr,pal);
if (zero) blank=code; // We know this tile is blank now
}
// terminate the cache list
*ts->hc = 0;
}
static void DrawStripInterlace(struct TileStrip *ts)
{
int tilex=0,dx=0,ty=0,code=0,addr=0,cells;
int oldcode=-1,blank=-1; // The tile we know is blank
int pal=0;
// Draw tiles across screen:
tilex=(-ts->hscroll)>>3;
ty=(ts->line&15)<<1; // Y-Offset into tile
dx=((ts->hscroll-1)&7)+1;
cells = ts->cells;
if(dx != 8) cells++; // have hscroll, need to draw 1 cell more
for (; cells; dx+=8,tilex++,cells--)
{
int zero=0;
code=Pico.vram[ts->nametab+(tilex&ts->xmask)];
if (code==blank) continue;
if (code>>15) { // high priority tile
int cval = (code&0xfc00) | (dx<<16) | (ty<<25);
cval|=(code&0x3ff)<<1;
if(code&0x1000) cval^=0xf<<26;
*ts->hc++ = cval; // cache it
continue;
}
if (code!=oldcode) {
oldcode = code;
// Get tile address/2:
addr=(code&0x7ff)<<5;
if (code&0x1000) addr+=30-ty; else addr+=ty; // Y-flip
// pal=Pico.cram+((code>>9)&0x30);
pal=((code>>9)&0x30);
}
if (code&0x0800) zero=TileFlip(dx,addr,pal);
else zero=TileNorm(dx,addr,pal);
if (zero) blank=code; // We know this tile is blank now
}
// terminate the cache list
*ts->hc = 0;
}
// --------------------------------------------
void DrawLayer(int plane, int *hcache, int maxcells, int sh)
{
struct PicoVideo *pvid=&Pico.video;
const char shift[4]={5,6,5,7}; // 32,64 or 128 sized tilemaps (2 is invalid)
struct TileStrip ts;
int width, height, ymask;
int vscroll, htab;
ts.hc=hcache;
ts.cells=maxcells;
// Work out the TileStrip to draw
// Work out the name table size: 32 64 or 128 tiles (0-3)
width=pvid->reg[16];
height=(width>>4)&3; width&=3;
ts.xmask=(1<<shift[width])-1; // X Mask in tiles (0x1f-0x7f)
ymask=(height<<8)|0xff; // Y Mask in pixels
if(width == 1) ymask&=0x1ff;
else if(width>1) ymask =0x0ff;
// Find name table:
if (plane==0) ts.nametab=(pvid->reg[2]&0x38)<< 9; // A
else ts.nametab=(pvid->reg[4]&0x07)<<12; // B
htab=pvid->reg[13]<<9; // Horizontal scroll table address
if ( pvid->reg[11]&2) htab+=Scanline<<1; // Offset by line
if ((pvid->reg[11]&1)==0) htab&=~0xf; // Offset by tile
htab+=plane; // A or B
// Get horizontal scroll value, will be masked later
ts.hscroll=Pico.vram[htab&0x7fff];
if((pvid->reg[12]&6) == 6) {
// interlace mode 2
vscroll=Pico.vsram[plane]; // Get vertical scroll value
// Find the line in the name table
ts.line=(vscroll+(Scanline<<1))&((ymask<<1)|1);
ts.nametab+=(ts.line>>4)<<shift[width];
DrawStripInterlace(&ts);
} else if( pvid->reg[11]&4) {
// shit, we have 2-cell column based vscroll
// luckily this doesn't happen too often
ts.line=ymask|(shift[width]<<24); // save some stuff instead of line
DrawStripVSRam(&ts, plane);
} else {
vscroll=Pico.vsram[plane]; // Get vertical scroll value
// Find the line in the name table
ts.line=(vscroll+Scanline)&ymask;
ts.nametab+=(ts.line>>3)<<shift[width];
DrawStrip(&ts, sh);
}
}
// --------------------------------------------
// tstart & tend are tile pair numbers
void DrawWindow(int tstart, int tend, int prio, int sh) // int *hcache
{
struct PicoVideo *pvid=&Pico.video;
int tilex=0,ty=0,nametab,code=0;
int blank=-1; // The tile we know is blank
// Find name table line:
if (pvid->reg[12]&1)
{
nametab=(pvid->reg[3]&0x3c)<<9; // 40-cell mode
nametab+=(Scanline>>3)<<6;
}
else
{
nametab=(pvid->reg[3]&0x3e)<<9; // 32-cell mode
nametab+=(Scanline>>3)<<5;
}
tilex=tstart<<1;
tend<<=1;
ty=(Scanline&7)<<1; // Y-Offset into tile
if(!(rendstatus&2)) {
// check the first tile code
code=Pico.vram[nametab+tilex];
// if the whole window uses same priority (what is often the case), we may be able to skip this field
if((code>>15) != prio) return;
}
// Draw tiles across screen:
for (; tilex < tend; tilex++)
{
int addr=0,zero=0;
int pal;
code=Pico.vram[nametab+tilex];
if(code==blank) continue;
if((code>>15) != prio) {
rendstatus|=2;
continue;
}
pal=((code>>9)&0x30);
if(sh) {
int tmp, *zb = (int *)(HighCol+8+(tilex<<3));
if(prio) {
tmp = *zb;
if(!(tmp&0x00000080)) tmp&=~0x000000c0; if(!(tmp&0x00008000)) tmp&=~0x0000c000;
if(!(tmp&0x00800000)) tmp&=~0x00c00000; if(!(tmp&0x80000000)) tmp&=~0xc0000000;
*zb++=tmp; tmp = *zb;
if(!(tmp&0x00000080)) tmp&=~0x000000c0; if(!(tmp&0x00008000)) tmp&=~0x0000c000;
if(!(tmp&0x00800000)) tmp&=~0x00c00000; if(!(tmp&0x80000000)) tmp&=~0xc0000000;
*zb++=tmp;
} else {
pal |= 0x40;
}
}
// Get tile address/2:
addr=(code&0x7ff)<<4;
if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip
if (code&0x0800) zero=TileFlip(8+(tilex<<3),addr,pal);
else zero=TileNorm(8+(tilex<<3),addr,pal);
if (zero) blank=code; // We know this tile is blank now
}
// terminate the cache list
//*hcache = 0;
}
// --------------------------------------------
void DrawTilesFromCache(int *hc, int sh)
{
int code, addr, zero, dx;
int pal;
short blank=-1; // The tile we know is blank
// *ts->hc++ = code | (dx<<16) | (ty<<25); // cache it
while((code=*hc++)) {
if(!sh && (short)code == blank) continue;
// Get tile address/2:
addr=(code&0x7ff)<<4;
addr+=(unsigned int)code>>25; // y offset into tile
dx=(code>>16)&0x1ff;
if(sh) {
unsigned char *zb = HighCol+dx;
if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;
if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;
if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;
if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;
}
pal=((code>>9)&0x30);
if (code&0x0800) zero=TileFlip(dx,addr,pal);
else zero=TileNorm(dx,addr,pal);
if(zero) blank=(short)code;
}
}
// --------------------------------------------
// Index + 0 : hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size
// Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8
void DrawSprite(int *sprite, int **hc, int sh)
{
int width=0,height=0;
int row=0,code=0;
int pal;
int tile=0,delta=0;
int sx, sy;
int (*fTileFunc)(int sx,int addr,int pal);
// parse the sprite data
sy=sprite[0];
code=sprite[1];
sx=code>>16; // X
width=sy>>28;
height=(sy>>24)&7; // Width and height in tiles
sy=(sy<<16)>>16; // Y
row=Scanline-sy; // Row of the sprite we are on
if (code&0x1000) row=(height<<3)-1-row; // Flip Y
tile=code&0x7ff; // Tile number
tile+=row>>3; // Tile number increases going down
delta=height; // Delta to increase tile by going right
if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X
tile<<=4; tile+=(row&7)<<1; // Tile address
if(code&0x8000) { // high priority - cache it
*(*hc)++ = (tile<<16)|((code&0x0800)<<5)|((sx<<6)&0x0000ffc0)|((code>>9)&0x30)|((sprite[0]>>16)&0xf);
} else {
delta<<=4; // Delta of address
pal=((code>>9)&0x30)|(sh<<6);
if(sh && (code&0x6000) == 0x6000) {
if(code&0x0800) fTileFunc=TileFlipSH;
else fTileFunc=TileNormSH;
} else {
if(code&0x0800) fTileFunc=TileFlip;
else fTileFunc=TileNorm;
}
for (; width; width--,sx+=8,tile+=delta)
{
if(sx<=0) continue;
if(sx>=328) break; // Offscreen
tile&=0x7fff; // Clip tile address
fTileFunc(sx,tile,pal);
}
}
}
void DrawSpritesFromCache(int *hc, int sh)
{
int code, tile, sx, delta, width;
int pal;
int (*fTileFunc)(int sx,int addr,int pal);
// *(*hc)++ = (tile<<16)|((code&0x0800)<<5)|((sx<<6)&0x0000ffc0)|((code>>9)&0x30)|((sprite[0]>>24)&0xf);
while((code=*hc++)) {
pal=(code&0x30);
delta=code&0xf;
width=delta>>2; delta&=3;
width++; delta++; // Width and height in tiles
if (code&0x10000) delta=-delta; // Flip X
delta<<=4;
tile=((unsigned int)code>>17)<<1;
sx=(code<<16)>>22; // sx can be negative (start offscreen), so sign extend
if(sh && pal == 0x30) { //
if(code&0x10000) fTileFunc=TileFlipSH;
else fTileFunc=TileNormSH;
} else {
if(code&0x10000) fTileFunc=TileFlip;
else fTileFunc=TileNorm;
}
for (; width; width--,sx+=8,tile+=delta)
{
if(sx<=0) continue;
if(sx>=328) break; // Offscreen
tile&=0x7fff; // Clip tile address
fTileFunc(sx,tile,pal);
}
}
}
void BackFill(int reg7, int sh)
{
unsigned int back=0;
unsigned int *pd=NULL,*end=NULL;
// Start with a blank scanline (background colour):
back=reg7&0x3f;
back|=sh<<6;
back|=back<<8;
back|=back<<16;
pd= (unsigned int *)(HighCol+8);
end=(unsigned int *)(HighCol+8+320);
do { pd[0]=pd[1]=pd[2]=pd[3]=back; pd+=4; } while (pd<end);
}
// --------------------------------------------
extern unsigned short HighPal[0x100];
void FinalizeLineBGR444(int sh)
{
unsigned short *pd=DrawLineDest;
unsigned char *ps=HighCol+8;
unsigned short *pal=Pico.cram;
int len, i, t;
if (Pico.video.reg[12]&1) {
len = 320;
} else {
if(!(PicoOpt&0x100)) pd+=32;
len = 256;
}
if(sh) {
pal=HighPal;
if(Pico.m.dirtyPal) {
blockcpy(pal, Pico.cram, 0x40*2);
// shadowed pixels
for(i = 0x3f; i >= 0; i--)
pal[0x40|i] = pal[0xc0|i] = (unsigned short)((pal[i]>>1)&0x0777);
// hilighted pixels
for(i = 0x3f; i >= 0; i--) {
t=pal[i]&0xeee;t+=0x444;if(t&0x10)t|=0xe;if(t&0x100)t|=0xe0;if(t&0x1000)t|=0xe00;t&=0xeee;
pal[0x80|i]=(unsigned short)t;
}
Pico.m.dirtyPal = 0;
}
}
for(i = 0; i < len; i++)
pd[i] = pal[ps[i]];
}
void FinalizeLineRGB555(int sh)
{
unsigned short *pd=DrawLineDest;
unsigned char *ps=HighCol+8;
unsigned short *pal=HighPal;
int len, i, t, dirtyPal = Pico.m.dirtyPal;
if(dirtyPal) {
unsigned short *ppal=Pico.cram;
for(i = 0x3f; i >= 0; i--)
pal[i] = (unsigned short) (((ppal[i]&0x00f)<<12)|((ppal[i]&0x0f0)<<3)|((ppal[i]&0xf00)>>7));
Pico.m.dirtyPal = 0;
}
if (Pico.video.reg[12]&1) {
len = 320;
} else {
if(!(PicoOpt&0x100)) pd+=32;
len = 256;
}
if(sh) {
if(dirtyPal) {
// shadowed pixels
for(i = 0x3f; i >= 0; i--)
pal[0x40|i] = pal[0xc0|i] = (unsigned short)((pal[i]>>1)&0x738e);
// hilighted pixels
for(i = 0x3f; i >= 0; i--) {
t=pal[i]&0xe71c;t+=0x4208;if(t&0x20)t|=0x1c;if(t&0x800)t|=0x700;if(t&0x10000)t|=0xe000;t&=0xe71c;
pal[0x80|i]=(unsigned short)t;
}
}
}
for(i = 0; i < len; i++)
pd[i] = pal[ps[i]];
}

384
platform/linux/gp2x.c Normal file
View file

@ -0,0 +1,384 @@
/* faking/emulating gp2x.c by using gtk */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <gtk/gtk.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <fcntl.h>
#include <errno.h>
#include "../gp2x/emu.h"
#include "../gp2x/gp2x.h"
#include "../gp2x/usbjoy.h"
#include "../gp2x/version.h"
void *gp2x_screen;
static int current_bpp = 8;
static int current_pal[256];
static unsigned long current_keys = 0;
static int sounddev = 0, mixerdev = 0;
static const char *verstring = "PicoDrive " VERSION;
// dummies
char *ext_menu = 0, *ext_state = 0;
/* gtk */
struct gtk_global_struct
{
GtkWidget *window;
GtkWidget *pixmap1;
} gtk_items;
static gboolean delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
{
return FALSE;
}
static void destroy (GtkWidget *widget, gpointer data)
{
gtk_main_quit ();
}
static gint key_press_event (GtkWidget *widget, GdkEventKey *event)
{
switch (event->hardware_keycode)
{
case 0x62: current_keys |= GP2X_UP; break;
case 0x68: current_keys |= GP2X_DOWN; break;
case 0x64: current_keys |= GP2X_LEFT; break;
case 0x66: current_keys |= GP2X_RIGHT; break;
case 0x24: current_keys |= GP2X_START; break; // enter
case 0x23: current_keys |= GP2X_SELECT;break; // ]
case 0x34: current_keys |= GP2X_A; break; // z
case 0x35: current_keys |= GP2X_X; break; // x
case 0x36: current_keys |= GP2X_B; break; // c
case 0x37: current_keys |= GP2X_Y; break; // v
case 0x27: current_keys |= GP2X_L; break; // s
case 0x28: current_keys |= GP2X_R; break; // d
case 0x29: current_keys |= GP2X_PUSH; break; // f
case 0x18: current_keys |= GP2X_VOL_DOWN;break; // q
case 0x19: current_keys |= GP2X_VOL_UP;break; // w
}
return 0;
}
static gint key_release_event (GtkWidget *widget, GdkEventKey *event)
{
switch (event->hardware_keycode)
{
case 0x62: current_keys &= ~GP2X_UP; break;
case 0x68: current_keys &= ~GP2X_DOWN; break;
case 0x64: current_keys &= ~GP2X_LEFT; break;
case 0x66: current_keys &= ~GP2X_RIGHT; break;
case 0x24: current_keys &= ~GP2X_START; break; // enter
case 0x23: current_keys &= ~GP2X_SELECT;break; // ]
case 0x34: current_keys &= ~GP2X_A; break; // z
case 0x35: current_keys &= ~GP2X_X; break; // x
case 0x36: current_keys &= ~GP2X_B; break; // c
case 0x37: current_keys &= ~GP2X_Y; break; // v
case 0x27: current_keys &= ~GP2X_L; break; // s
case 0x28: current_keys &= ~GP2X_R; break; // d
case 0x29: current_keys &= ~GP2X_PUSH; break; // f
case 0x18: current_keys &= ~GP2X_VOL_DOWN;break; // q
case 0x19: current_keys &= ~GP2X_VOL_UP;break; // w
}
return 0;
}
static void *gtk_threadf(void *none)
{
gtk_main();
printf("linux: gtk thread finishing\n");
engineState = PGS_Quit;
return NULL;
}
static void gtk_initf(void)
{
int argc = 0;
char *argv[] = { "" };
GtkWidget *box;
pthread_t gtk_thread;
g_thread_init (NULL);
gdk_threads_init ();
gdk_set_locale ();
gtk_init (&argc, (char ***) &argv);
/* create new window */
gtk_items.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (gtk_items.window), "delete_event",
G_CALLBACK (delete_event), NULL);
g_signal_connect (G_OBJECT (gtk_items.window), "destroy",
G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (gtk_items.window), "key_press_event",
G_CALLBACK (key_press_event), NULL);
g_signal_connect (G_OBJECT (gtk_items.window), "key_release_event",
G_CALLBACK (key_release_event), NULL);
gtk_container_set_border_width (GTK_CONTAINER (gtk_items.window), 2);
gtk_window_set_title ((GtkWindow *) gtk_items.window, verstring);
box = gtk_hbox_new(FALSE, 0);
gtk_widget_show(box);
gtk_container_add (GTK_CONTAINER (gtk_items.window), box);
/* live pixmap */
gtk_items.pixmap1 = gtk_image_new ();
gtk_container_add (GTK_CONTAINER (box), gtk_items.pixmap1);
gtk_widget_show (gtk_items.pixmap1);
gtk_widget_set_size_request (gtk_items.pixmap1, 320, 240);
gtk_widget_show (gtk_items.window);
// pthread_mutex_init (&thr_mutex, NULL);
// pthread_mutex_lock (&thr_mutex);
// pthread_mutex_init (&scanner_muttex, NULL);
pthread_create(&gtk_thread, NULL, gtk_threadf, NULL);
}
void finalize_image(guchar *pixels, gpointer data)
{
free(pixels);
}
/* --- */
void gp2x_init(void)
{
printf("entering init()\n"); fflush(stdout);
gp2x_screen = malloc(320*240*2 + 320*2);
// snd
mixerdev = open("/dev/mixer", O_RDWR);
if (mixerdev == -1)
printf("open(\"/dev/mixer\") failed with %i\n", errno);
gtk_initf();
gp2x_usbjoy_init();
printf("exitting init()\n"); fflush(stdout);
}
void gp2x_deinit(void)
{
free(gp2x_screen);
if (sounddev > 0) close(sounddev);
close(mixerdev);
gp2x_usbjoy_deinit();
}
/* video */
void gp2x_video_flip(void)
{
GdkPixbuf *pixbuf;
unsigned char *image;
int i;
gdk_threads_enter();
image = malloc (320*240*3);
if (image == NULL)
{
gdk_threads_leave();
return;
}
if (current_bpp == 8)
{
unsigned char *pixels = gp2x_screen;
int pix;
for (i = 0; i < 320*240; i++)
{
pix = current_pal[pixels[i]];
image[3 * i + 0] = pix >> 16;
image[3 * i + 1] = pix >> 8;
image[3 * i + 2] = pix;
}
}
else
{
unsigned short *pixels = gp2x_screen;
for (i = 0; i < 320*240; i++)
{
/* in: rrrr rggg gggb bbbb */
/* out: rrrr r000 gggg gg00 bbbb b000 */
image[3 * i + 0] = (pixels[i] >> 8) & 0xf8;
image[3 * i + 1] = (pixels[i] >> 3) & 0xfc;
image[3 * i + 2] = (pixels[i] << 3);
}
}
pixbuf = gdk_pixbuf_new_from_data (image, GDK_COLORSPACE_RGB,
FALSE, 8, 320, 240, 320*3, finalize_image, NULL);
gtk_image_set_from_pixbuf (GTK_IMAGE (gtk_items.pixmap1), pixbuf);
g_object_unref (pixbuf);
gdk_threads_leave();
}
void gp2x_video_changemode(int bpp)
{
current_bpp = bpp;
}
void gp2x_video_setpalette(int *pal, int len)
{
memcpy(current_pal, pal, len*4);
}
void gp2x_video_RGB_setscaling(int W, int H)
{
}
void gp2x_memcpy_all_buffers(void *data, int offset, int len)
{
memcpy((char *)gp2x_screen + offset, data, len);
}
void gp2x_memset_all_buffers(int offset, int byte, int len)
{
memset((char *)gp2x_screen + offset, byte, len);
}
/* sound */
static int s_oldrate = 0, s_oldbits = 0, s_oldstereo = 0;
void gp2x_start_sound(int rate, int bits, int stereo)
{
int frag = 0, bsize, buffers;
// if no settings change, we don't need to do anything
if (rate == s_oldrate && s_oldbits == bits && s_oldstereo == stereo) return;
if (sounddev > 0) close(sounddev);
sounddev = open("/dev/dsp", O_WRONLY|O_ASYNC);
if (sounddev == -1)
printf("open(\"/dev/dsp\") failed with %i\n", errno);
ioctl(sounddev, SNDCTL_DSP_SPEED, &rate);
ioctl(sounddev, SNDCTL_DSP_SETFMT, &bits);
ioctl(sounddev, SNDCTL_DSP_STEREO, &stereo);
// calculate buffer size
buffers = 16;
bsize = rate / 32;
if (rate > 22050) { bsize*=4; buffers*=2; } // 44k mode seems to be very demanding
while ((bsize>>=1)) frag++;
frag |= buffers<<16; // 16 buffers
ioctl(sounddev, SNDCTL_DSP_SETFRAGMENT, &frag);
printf("gp2x_set_sound: %i/%ibit/%s, %i buffers of %i bytes\n",
rate, bits, stereo?"stereo":"mono", frag>>16, 1<<(frag&0xffff));
s_oldrate = rate; s_oldbits = bits; s_oldstereo = stereo;
}
void gp2x_sound_write(void *buff, int len)
{
write(sounddev, buff, len);
}
void gp2x_sound_volume(int l, int r)
{
l=l<0?0:l; l=l>255?255:l; r=r<0?0:r; r=r>255?255:r;
l<<=8; l|=r;
ioctl(mixerdev, SOUND_MIXER_WRITE_PCM, &l); /*SOUND_MIXER_WRITE_VOLUME*/
}
/* joy */
unsigned long gp2x_joystick_read(int allow_usb_joy)
{
unsigned long value = current_keys;
int i;
if (allow_usb_joy && num_of_joys > 0) {
// check the usb joy as well..
gp2x_usbjoy_update();
for (i = 0; i < num_of_joys; i++)
value |= gp2x_usbjoy_check(i);
}
return value;
}
/* 940 */
int crashed_940 = 0;
void Pause940(int yes)
{
}
void Reset940(int yes)
{
}
/* faking gp2x cpuctrl.c */
void cpuctrl_init(void)
{
}
void cpuctrl_deinit(void)
{
}
void set_FCLK(unsigned MHZ)
{
}
void Disable_940(void)
{
}
void gp2x_video_wait_vsync(void)
{
}
void set_RAM_Timings(int tRC, int tRAS, int tWR, int tMRD, int tRFC, int tRP, int tRCD)
{
}
void set_gamma(int g100)
{
}
/* squidgehack.c */
int mmuhack(void)
{
return 0;
}
int mmuunhack(void)
{
return 0;
}
/* misc */
void spend_cycles(int c)
{
usleep(c/*/200*/);
}

View file

@ -0,0 +1,19 @@
// port specific settings
#ifndef PORT_CONFIG_H
#define PORT_CONFIG_H
#define CPU_CALL
// draw2.c
#define START_ROW 0 // which row of tiles to start rendering at?
#define END_ROW 28 // ..end
// pico.c
#define CAN_HANDLE_240_LINES 1
#define dprintf(f,...) printf(f"\n",##__VA_ARGS__)
//#define dprintf(x...)
#endif //PORT_CONFIG_H

301
platform/readme.txt Normal file
View file

@ -0,0 +1,301 @@
About
-----
This version of PicoDrive is another enhanced version of Dave's
Megadrive / Genesis emulator for Pocket PC. The original Dave's code was
heavily modified (including Cyclone core), parts of it were rewritten in
asm, many features added, accuracy increased. This version is aimed at
ARM-based handheld devices, so ports exist for GP2X handheld console,
Symbian smartphones and PocketPC devices.
How to make it run
------------------
GP2X:
Copy PicoDrive.gpe, code940.bin and mmuhack.o to any place in your filesystem
(all 3 files must be in the same directory) and run PicoDrive.gpe.
Then load a ROM and enjoy!
Symbian:
Select PicoDrive from application (tools) menu and run it. That's it!
All:
If you have any problems (game does not boot, sound is glitchy, broken graphics),
make sure you enable "Accurate timing", "Emulate Z80" and then disable
"Fast renderer". This way you will get the best compatibility this emulator can
provide.
Configuration
-------------
See config.txt file.
Problems / limitations
----------------------
* 32x, Sega CD, SVP are not emulated.
* Various VDP quirks (window bug, scroll size 2, etc.) are not emulated,
as very few games use this.
* Some games don't work or have glitches because of inaccurate timing and sync
between the emulated chips.
Credits
-------
This emulator uses code from these people/projects:
Dave
Cyclone 68000 core, Pico emulation library
Homepage: http://www.finalburn.com/
notaz
GP2X port, Cyclone 68000 hacks, lots of additional coding (see changelog).
Reesy & FluBBa
DrZ80, the Z80 emulator written in ARM assembly.
Homepage: http://reesy.gp32x.de/
Tatsuyuki Satoh, Jarek Burczynski, MultiArcadeMachineEmulator development
software implementation of Yamaha FM sound generator
MultiArcadeMachineEmulator (MAME) development
Texas Instruments SN76489 / SN76496 programmable tone /noise generator
Homepage: http://www.mame.net/
Additional thanks
-----------------
* Charles MacDonald (http://cgfm2.emuviews.com/) for old but still very useful
info about genesis hardware.
* Stéphane Dallongeville for creating Gens and making it open-source.
* Steve Snake for all that he has done for Genesis emulation scene.
* Bart Trzynadlowski for his SSFII and 68000 docs.
* Haze for his research (http://haze.mameworld.info).
* Mark and Jean-loup for zlib library.
* Anyone else I forgot. You know who you are.
GP2X:
* rlyeh and all the other people behind the minimal library.
* Squidge for his famous squidgehack(tm).
* Dzz for his ARM940 sample code.
* GnoStiC & Puck2099 for USB joystick support.
* Hermes PS2R, god_at_hell for the CpuCtrl library.
* craigix for supplying the GP2X hardware and making this port possible.
Symbian:
* Peter van Sebille for his various open-source Symbian projects to learn from.
* Steve Fischer for his open-source Motorola projects.
* The development team behind "Symbian GCC Improvement Project"
(http://www.inf.u-szeged.hu/symbian-gcc/) for their updated pre-SymbianOS9
compile tools.
* AnotherGuest for all his Symbian stuff and support.
* Inder for the icons.
Changelog
---------
0.964
* GP2X: Fixed a sound buffer underflow issue on lower sample rate modes, which was
happening for NTSC games and causing sound clicks.
* GP2X: Redone key config to better support USB joysticks (now multiple joysticks
should be useable and configurable).
+ GP2X: Added save confirmation option.
+ GP2X: Added 940 CPU crash detection.
+ ALL: UIQ3 port added.
0.963
* GP2X: Gamma-reset-on-entering-menu bug fixed.
* GP2X: Recompiled PicoDrive with gcc profiling option set as described here:
http://www.gp32x.com/board/index.php?showtopic=28490
0.962
* GP2X: Fixed an issue with incorrect sounds in some games when dualcore operation
was enabled (for example punch sound in SOR).
* GP2X: Limited max volume to 90, because higher values often cause distortions.
* GP2X: Fixed a bug with lower res scaling.
* GP2X: Gamma is now reset on exit.
0.96
* ALL: Severely optimized MAME's YM2612 core, part of it is now rewritten in asm.
+ GP2X: The YM2612's code now can be run in GP2X's ARM940T CPU, what causes large
performance increase.
* ALL: Accurate renderers are slightly faster now.
+ GP2X: Using quadruple buffering instead of doublebuffer now, also updated
framelimitter, this should eliminate some scrolling and tearing problems.
* GP2X: Fixed some flickering issues of 8bit accurate renderer.
+ GP2X: craigix's RAM timings now can be enabled in the menu (see advanced options).
+ GP2X: Added ability to save config for specific games only.
+ GP2X: Gamma control added (using GP2X's hardware capabilities for this).
* GP2X: Volume keys are now configurable.
+ GP2X: GnoStiC added USB joystick support, I made it possible to use it for
player 2 control (currently untested).
* GP2X: squidgehack is now applied through kernel module (cleaner way).
0.95
* ALL: Fixed a bug in sprite renderer which was causing slowdowns for some games.
+ GP2X: Added command line support
+ GP2X: Added optional hardware scaling for lower-res games like Shining Force.
* ALL: Sound chips are now sampled 2 times per frame. This fixed some games which
had missing sounds (Vectorman 2 1st level, Thunder Force 3 water level,
etc.).
+ ALL: Added another accurate 8-bit renderer which is slightly faster and made it
default.
0.945
+ GP2X: Added frame limiter for frameskipped modes.
* GP2X: Increased brightness a bit (unused pixel bits now also contain data).
* GP2X: Suidgehack was not applied correctly (was applied before allocating some
high memory and had no effect).
0.94
+ Added GP2X port.
* Improved interrupt timing, Mazin Saga and Burning Force now works.
* Rewritten renderer code to better suit GP2X, should be faster on other
ports too.
+ Added support for banking used by 12-in-1 and 4-in-1 ROMs (thanks Haze).
+ Added some protection device faking, used by some unlicensed games like
Super Bubble Bobble, King of Fighters, Elf Wor, ... (thanks to Haze again)
+ Added primitive Virtua Racing SVP faking, so menus can be seen now.
0.93
* Fixed a problem with P900/P910 key configuration in FC mode.
* Improved shadow/hilight mode emulation. Still not perfect, but should be
enough for most games.
+ Save state slots added.
+ Region selector added.
0.92
VDP changes:
* VDP emulation is now more accurate (fixes flickering in Chase HQ II,
Super Hang-On and some other problems in other games).
* HV counter emulation is now much more accurate. Fixes the Asterix games,
line in Road Rash 3, etc.
* Minor sprite and layer scroll masking bugs fixed.
+ Added partial interlace mode renderer (Sonic 2 vs mode)
* Fixed a crash in both renderers when certain size window layers were used.
+ Added emulation of shadow/hilight operator sprites. Other shadow/hilight
effects are still unemulated.
+ Sprite emulation is more accurate, sprite limit is emulated.
+ Added "accurate sprites" option, which always draws sprites in correct
order and emulates sprite collision bit, but is significantly slower.
Emulation changes:
* Improved interrupt handling, added deferred interrupt emulation
(Lemmings, etc).
+ Added serial EEPROM SRAM support (Wonder Boy in Monster World,
Megaman - The Wily Wars and many EA sports games like NBA Jam).
+ Implemented ROM banking for Super Street Fighter II - The New Challengers
* Updated to the latest version of DrZ80 core, integrated memory handlers
in it for better performance. A noticeable performance increase, but save
states may not work from the previous version (you can only use them with
sound disabled in that case).
+ SRAM word read handler was using incorrect byte order, fixed.
Changes in Cyclone 0.0086:
+ Added missing CHK opcode handler (used by SeaQuest DSV).
+ Added missing TAS opcode handler (Gargoyles,Bubba N Stix,...). As in real genesis,
memory write-back phase is ignored (but can be enabled in config.h if needed).
+ Added missing NBCD and TRAPV opcode handlers.
+ Added missing addressing mode for CMP/EOR.
+ Added some minor optimizations.
- Removed 216 handlers for 2927 opcodes which were generated for invalid addressing modes.
+ Fixed flags for ASL, NEG, NEGX, DIVU, ADDX, SUBX, ROXR.
+ Bugs fixed in MOVEP, LINK, ADDQ, DIVS handlers.
* Undocumented flags for CHK, ABCD, SBCD and NBCD are now emulated the same way as in Musashi.
+ Added Uninitialized Interrupt emulation.
+ Altered timing for about half of opcodes to match Musashi's.
0.80
* Nearly all VDP code was rewritten in ARM asm. Gives ~10-25% performance
increase (depends on game).
* Optimized 32-column renderer not to render tiles offscreen, games which
use 32-column display (like Shining Force) run ~50% faster.
+ Added new "Alternative renderer", which gives another ~30-45% performance
increase (in addition to mentioned above), but works only with some games,
because it is missing some features (it uses tile-based renderering
instead of default line-based and disables H-ints).
+ Added "fit2" display mode for all FC gamers. It always uses 208x146 for
P800 and 208x208 for all other phones.
+ Added volume control for Motorolas (experimental).
VDP changes:
+ Added support for vertical window (used by Vapor Trail, Mercs, GRIND
Stormer and others).
+ Added sprite masking (hiding), adds some speed.
+ Added preliminary H counter emulation. Comix Zone and Sonic 3D Blast
special stage are now playable.
+ Added column based vertical scrolling (Gunstar Heroes battleship level,
Sonic and Knuckles lava boss, etc).
Emulation changes:
+ Re-added and improved Z80 faking when Z80 is disabled. Many games now can
be played without enabling Z80 (Lost Vikings, Syndicate, etc), but some
still need it (International Superstar Soccer Deluxe).
* Improved ym2612 timers, Outrun music plays at correct speed, voices in
Earthworm Jim play better, more games play sound.
* I/O registers now remember their values (needed for Pirates! Gold)
+ Added support for 6 button pad.
Changes in Cyclone 0.0083wip:
+ Added missing CHK opcode (used by SeaQuest DSV).
+ Added missing TAS opcode (Gargoyles). As in real genesis, write-back phase
is ignored (but is enabled for other systems).
Backported stuff from Snes9x:
* Fixed Pxxx jog up/down which were not working in game.
+ Added an option to gzip save states to save space.
+ The emulator now pauses whenever it is loosing focus, so it will now pause
when alarm/ponecall/battery low/... windows come up.
- Removed 'pause on phonecall' feature, as it is no longer needed.
+ Video fix for asian A1000s.
0.70
* Started using tools from "Symbian GCC Improvement Project", which give
considerable speed increase (~4fps in "center 90" mode).
* Rewrote some drawing routines in ARM assembly (gives ~6 more fps in
"center 90" mode).
* Minor improvement to 0 and 180 "fit" modes. Now they look slightly better
and are faster.
* Minor stability improvements (emulator is less likely to crash).
+ Added some background for OSD text for better readability.
+ Added Pal/NTSC detection. This is needed for proper sound speed.
+ Implemented Reesy's DrZ80 Z80 emu. Made some changes to it with hope to make
it faster.
+ Implemented ym2612 emu from the MAME project. Runs well but sometimes sounds
a bit weird. Could be a little faster, so made some changes too.
+ Implemented SN76489 emu from the MAME project.
+ Added two separate sound output methods (mediaserver and cmaudiofb) with
autodetection (needs testing).
* Fixed VDP DMA fill emulation (as described in Charles MacDonald's docs),
fixes Contra and some other games.
0.301
Launcher:
* Launcher now starts emulation process from current directory,
not from hardcoded paths.
* Improved 'pause on call' feature, should hopefully work with Motorola phones.
0.30
Initial release.
Disclaimer
----------
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

BIN
platform/s60/.rnd Normal file

Binary file not shown.

15
platform/s60/ABLD.BAT Normal file
View file

@ -0,0 +1,15 @@
@ECHO OFF
REM Bldmake-generated batch file - ABLD.BAT
REM ** DO NOT EDIT **
perl -S ABLD.PL \PICODRIVE\S60\ %1 %2 %3 %4 %5 %6 %7 %8 %9
if errorlevel==1 goto CheckPerl
goto End
:CheckPerl
perl -v >NUL
if errorlevel==1 echo Is Perl, version 5.003_07 or later, installed?
goto End
:End

View file

@ -0,0 +1,16 @@
PATH=\s60v1\epoc32\tools\;\s60v1\epoc32\gcc\bin\;C:\winnt\system32;C:\winnt;C:\winnt\System32\Wbem;C:\Program Files\ATI Technologies\ATI Control Panel;C:\Program Files\Common Files\Adaptec Shared\System;C:\Perl\bin;\s60v1\epoc32\tools;c:\MSVC6\VC98\Bin;C:\s60v1\epoc32\tools\nokia_compiler\Symbian_Tools\Command_Line_Tools;C:\Program Files\CSL Arm Toolchain\arm-none-symbianelf\bin;C:\Program Files\CSL Arm Toolchain\bin
# EPOC DEFINITIONS
EPOCBLD = \s60v1\EPOC32\BUILD\PICODRIVE\S60\PICO\WINS\ #
EPOCTRG = \s60v1\EPOC32\RELEASE\WINS\ #
EPOCLIB = \s60v1\EPOC32\RELEASE\WINS\ #
EPOCLINK = \s60v1\EPOC32\RELEASE\WINS\ #
EPOCSTATLINK = \s60v1\EPOC32\RELEASE\WINS\ #
RECREATEWORKSPACE :
cd \PICODRIVE\S60
perl -S makmake.pl -D \PICODRIVE\S60\PICO.MMP VC6

View file

@ -0,0 +1,152 @@
# Microsoft Developer Studio Project File - Name="PICODRIVE" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=PICODRIVE - Win32 Uni Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "PICODRIVE.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "PICODRIVE.mak" CFG="PICODRIVE - Win32 Uni Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "PICODRIVE - Win32 Uni Release" (based on\
"Win32 (x86) Dynamic-Link Library")
!MESSAGE "PICODRIVE - Win32 Uni Debug" (based on\
"Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "PICODRIVE - Win32 Uni Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\Win32_U0"
# PROP BASE Intermediate_Dir ".\Win32_U0"
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "\s60v1\EPOC32\RELEASE\WINS\UDEB"
# PROP Intermediate_Dir "\s60v1\EPOC32\BUILD\PICODRIVE\S60\PICODRIVES60\WINS\UDEB"
# ADD CPP /nologo /Zp4 /MDd /W4 /Zi /Od /X /I "\PICODRIVE\PICO" /I "\PICODRIVE\PICO\SOUND" /I "\PICODRIVE\S60" /I "\PICODRIVE" /I "\s60v1\EPOC32\INCLUDE" /I "\s60v1\EPOC32\INCLUDE\LIBC" /D "__SYMBIAN32__" /D "__VC32__" /D "__WINS__" /D "__AVKON_ELAF__" /D "__DLL__" /D "_DEBUG" /D "_UNICODE" /FR /Fd"\s60v1\EPOC32\RELEASE\WINS\UDEB\Z\SYSTEM\APPS\PICODRIVES60\PICODRIVE.PDB" /GF /c
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 /machine:IX86
# ADD LINK32 "\s60v1\EPOC32\RELEASE\WINS\UDEB\EDLL.LIB" "\s60v1\EPOC32\RELEASE\WINS\UDEB\pico.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\a68k.obj" "\s60v1\EPOC32\RELEASE\WINS\UDEB\mz80_asm.obj" "\s60v1\EPOC32\RELEASE\WINS\UDEB\cone.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\eikcore.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\mediaclientaudiostream.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\euser.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\zlib.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\efsrv.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\estlib.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\fbscli.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\estor.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\eikcoctl.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\ws32.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\avkon.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\bafl.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\bitgdi.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\eikdlg.lib" "\s60v1\EPOC32\BUILD\PICODRIVE\S60\PICODRIVES60\WINS\UDEB\PICODRIVE.exp" /nologo /entry:"_E32Dll" /subsystem:windows /dll /pdb:"\s60v1\EPOC32\RELEASE\WINS\UDEB\Z\SYSTEM\APPS\PICODRIVES60\PICODRIVE.pdb" /debug /machine:IX86 /nodefaultlib /include:"?_E32Dll@@YGHPAXI0@Z" /out:"\s60v1\EPOC32\RELEASE\WINS\UDEB\Z\SYSTEM\APPS\PICODRIVES60\PICODRIVE.DLL" /WARN:3
# SUBTRACT LINK32 /pdb:none
# Begin Special Build Tool
SOURCE=$(InputPath)
PreLink_Cmds=echo Doing first-stage link by name\
nmake -nologo -f "\PICODRIVE\S60\PICODRIVES60.SUP.MAKE" PRELINKUDEB\
if errorlevel 1 nmake -nologo -f "\PICODRIVE\S60\PICODRIVES60.SUP.MAKE" STOPLINKUDEB
PostBuild_Cmds=nmake -nologo -f "\PICODRIVE\S60\PICODRIVES60.SUP.MAKE" POSTBUILDUDEB
# End Special Build Tool
!ELSEIF "$(CFG)" == "PICODRIVE - Win32 Uni Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\Win32_Un"
# PROP BASE Intermediate_Dir ".\Win32_Un"
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "\s60v1\EPOC32\RELEASE\WINS\UREL"
# PROP Intermediate_Dir "\s60v1\EPOC32\BUILD\PICODRIVE\S60\PICODRIVES60\WINS\UREL"
# ADD CPP /nologo /Zp4 /MD /W4 /O1 /Op /X /I "\PICODRIVE\PICO" /I "\PICODRIVE\PICO\SOUND" /I "\PICODRIVE\S60" /I "\PICODRIVE" /I "\s60v1\EPOC32\INCLUDE" /I "\s60v1\EPOC32\INCLUDE\LIBC" /D "__SYMBIAN32__" /D "__VC32__" /D "__WINS__" /D "__AVKON_ELAF__" /D "__DLL__" /D "NDEBUG" /D "_UNICODE" /GF /c
# ADD MTL /nologo /mktyplib203 /D /win32
# ADD BASE RSC /l 0x809
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 /machine:IX86
# ADD LINK32 "\s60v1\EPOC32\RELEASE\WINS\UREL\EDLL.LIB" "\s60v1\EPOC32\RELEASE\WINS\UREL\pico.lib" "\s60v1\EPOC32\RELEASE\WINS\UREL\a68k.obj" "\s60v1\EPOC32\RELEASE\WINS\UREL\mz80_asm.obj" "\s60v1\EPOC32\RELEASE\WINS\UDEB\cone.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\eikcore.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\mediaclientaudiostream.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\euser.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\zlib.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\efsrv.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\estlib.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\fbscli.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\estor.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\eikcoctl.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\ws32.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\avkon.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\bafl.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\bitgdi.lib" "\s60v1\EPOC32\RELEASE\WINS\UDEB\eikdlg.lib" "\s60v1\EPOC32\BUILD\PICODRIVE\S60\PICODRIVES60\WINS\UREL\PICODRIVE.exp" /nologo /entry:"_E32Dll" /subsystem:windows /dll /machine:IX86 /nodefaultlib /include:"?_E32Dll@@YGHPAXI0@Z" /out:"\s60v1\EPOC32\RELEASE\WINS\UREL\Z\SYSTEM\APPS\PICODRIVES60\PICODRIVE.DLL" /WARN:3
# Begin Special Build Tool
SOURCE=$(InputPath)
PreLink_Cmds=echo Doing first-stage link by name\
nmake -nologo -f "\PICODRIVE\S60\PICODRIVES60.SUP.MAKE" PRELINKUREL\
if errorlevel 1 nmake -nologo -f "\PICODRIVE\S60\PICODRIVES60.SUP.MAKE" STOPLINKUREL
PostBuild_Cmds=nmake -nologo -f "\PICODRIVE\S60\PICODRIVES60.SUP.MAKE" POSTBUILDUREL
# End Special Build Tool
!ENDIF
# Begin Target
# Name "PICODRIVE - Win32 Uni Debug"
# Name "PICODRIVE - Win32 Uni Release"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
# Begin Source File
SOURCE=\PICODRIVE\Unzip.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\S60\Picodrive.uid.cpp
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\S60\Picodriveexe.cpp
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\S60\Picodrives60.mmp
# PROP Exclude_From_Build 1
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=\PICODRIVE\PICO\Ggenie.h
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Pico.h
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\Unzip.h
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\S60\Normalvideo.inl
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\S60\Interpolatevideo.inl
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\S60\Picodriveexe.h
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Picoint.h
# End Source File
# End Group
# End Target
# End Project

View file

@ -0,0 +1,169 @@
PATH=\s60v1\epoc32\tools\;\s60v1\epoc32\gcc\bin\;C:\winnt\system32;C:\winnt;C:\winnt\System32\Wbem;C:\Program Files\ATI Technologies\ATI Control Panel;C:\Program Files\Common Files\Adaptec Shared\System;C:\Perl\bin;\s60v1\epoc32\tools;c:\MSVC6\VC98\Bin;C:\s60v1\epoc32\tools\nokia_compiler\Symbian_Tools\Command_Line_Tools;C:\Program Files\CSL Arm Toolchain\arm-none-symbianelf\bin;C:\Program Files\CSL Arm Toolchain\bin
# EPOC DEFINITIONS
EPOCBLD = \s60v1\EPOC32\BUILD\PICODRIVE\S60\PICODRIVES60\WINS\ #
EPOCTRG = \s60v1\EPOC32\RELEASE\WINS\ #
EPOCLIB = \s60v1\EPOC32\RELEASE\WINS\ #
EPOCLINK = \s60v1\EPOC32\RELEASE\WINS\ #
EPOCSTATLINK = \s60v1\EPOC32\RELEASE\WINS\ #
EPOCBLDUDEB = $(EPOCBLD)UDEB
EPOCTRGUDEB = $(EPOCTRG)UDEB
EPOCLIBUDEB = $(EPOCLIB)UDEB
EPOCLINKUDEB = $(EPOCLINK)UDEB
EPOCSTATLINKUDEB = $(EPOCSTATLINK)UDEB
EPOCBLDUREL = $(EPOCBLD)UREL
EPOCTRGUREL = $(EPOCTRG)UREL
EPOCLIBUREL = $(EPOCLIB)UDEB
EPOCLINKUREL = $(EPOCLINK)UDEB
EPOCSTATLINKUREL = $(EPOCSTATLINK)UREL
TRGDIR = Z\SYSTEM\APPS\PICODRIVES60
DATADIR = Z\SYSTEM\DATA
LIBRARY :
@echo WARNING: Not attempting to create "$(EPOCLIB)UDEB\PICODRIVE.LIB".
@echo When exports are frozen in "\PICODRIVE\BWINS\PICODRIVEU.DEF", regenerate Makefile.
# REAL TARGET - IMPORT LIBRARY
"$(EPOCLIB)UDEB\PICODRIVE.LIB" : "\PICODRIVE\BWINS\PICODRIVEU.DEF" MAKEWORKLIBRARY
lib.exe /nologo /machine:i386 /nodefaultlib /name:"PICODRIVE.DLL" /def:"\PICODRIVE\BWINS\PICODRIVEU.DEF" /out:"$(EPOCLIB)UDEB\PICODRIVE.LIB"
del "$(EPOCLIB)UDEB\PICODRIVE.exp"
MAKEWORKLIBRARY : "\s60v1\EPOC32\RELEASE\WINS\UDEB"
"\s60v1\EPOC32\RELEASE\WINS\UDEB" :
@perl -S emkdir.pl "\s60v1\EPOC32\RELEASE\WINS\UDEB"
# BUILD - UDEB
LIBS= \
"$(EPOCSTATLINKUDEB)\PICO.LIB" \
"$(EPOCSTATLINKUDEB)\A68K.OBJ" \
"$(EPOCSTATLINKUDEB)\MZ80_ASM.OBJ" \
"$(EPOCLINKUDEB)\CONE.LIB" \
"$(EPOCLINKUDEB)\EIKCORE.LIB" \
"$(EPOCLINKUDEB)\MEDIACLIENTAUDIOSTREAM.LIB" \
"$(EPOCLINKUDEB)\EUSER.LIB" \
"$(EPOCLINKUDEB)\ZLIB.LIB" \
"$(EPOCLINKUDEB)\EFSRV.LIB" \
"$(EPOCLINKUDEB)\ESTLIB.LIB" \
"$(EPOCLINKUDEB)\FBSCLI.LIB" \
"$(EPOCLINKUDEB)\ESTOR.LIB" \
"$(EPOCLINKUDEB)\EIKCOCTL.LIB" \
"$(EPOCLINKUDEB)\WS32.LIB" \
"$(EPOCLINKUDEB)\AVKON.LIB" \
"$(EPOCLINKUDEB)\BAFL.LIB" \
"$(EPOCLINKUDEB)\BITGDI.LIB" \
"$(EPOCLINKUDEB)\EIKDLG.LIB"
LINK_OBJS= \
"$(EPOCBLDUDEB)\PICODRIVE.UID.obj" \
"$(EPOCBLDUDEB)\PICODRIVEEXE.obj" \
"$(EPOCBLDUDEB)\UNZIP.obj"
STAGE1_LINK_FLAGS="$(EPOCSTATLINKUDEB)\EDLL.LIB" \
$(LIBS) /nologo /entry:"_E32Dll" /subsystem:windows /dll /debug \
/incremental:no /machine:IX86 /nodefaultlib /include:"?_E32Dll@@YGHPAXI0@Z" /out:"$(EPOCBLDUDEB)\PICODRIVE.DLL" /WARN:3
PRELINKUDEB : $(LINK_OBJS) "$(EPOCSTATLINKUDEB)\EDLL.LIB" $(LIBS)
link.exe @<<
$(STAGE1_LINK_FLAGS) $(LINK_OBJS)
<<
del "$(EPOCBLDUDEB)\PICODRIVE.DLL"
del "$(EPOCBLDUDEB)\PICODRIVE.exp"
dumpbin /exports /out:"$(EPOCBLDUDEB)\PICODRIVE.inf" "$(EPOCBLDUDEB)\PICODRIVE.lib"
del "$(EPOCBLDUDEB)\PICODRIVE.lib"
perl -S makedef.pl -Inffile "$(EPOCBLDUDEB)\PICODRIVE.inf" "$(EPOCBLD)PICODRIVE.def"
del "$(EPOCBLDUDEB)\PICODRIVE.inf"
lib.exe /nologo /machine:i386 /nodefaultlib /name:"PICODRIVE.DLL" /def:"$(EPOCBLD)PICODRIVE.def" /out:"$(EPOCBLDUDEB)\PICODRIVE.lib"
del "$(EPOCBLDUDEB)\PICODRIVE.lib"
@echo First-stage link successful
STOPLINKUDEB : DELEXPOBJUDEB
@echo Stopped the build by removing the export object,
@echo if present, because the pre-link stage failed
POSTBUILDUDEB : DELEXPOBJUDEB LIBRARY
DELEXPOBJUDEB :
if exist "$(EPOCBLDUDEB)\PICODRIVE.exp" del "$(EPOCBLDUDEB)\PICODRIVE.exp"
# BUILD - UREL
LIBS= \
"$(EPOCSTATLINKUREL)\PICO.LIB" \
"$(EPOCSTATLINKUREL)\A68K.OBJ" \
"$(EPOCSTATLINKUREL)\MZ80_ASM.OBJ" \
"$(EPOCLINKUREL)\CONE.LIB" \
"$(EPOCLINKUREL)\EIKCORE.LIB" \
"$(EPOCLINKUREL)\MEDIACLIENTAUDIOSTREAM.LIB" \
"$(EPOCLINKUREL)\EUSER.LIB" \
"$(EPOCLINKUREL)\ZLIB.LIB" \
"$(EPOCLINKUREL)\EFSRV.LIB" \
"$(EPOCLINKUREL)\ESTLIB.LIB" \
"$(EPOCLINKUREL)\FBSCLI.LIB" \
"$(EPOCLINKUREL)\ESTOR.LIB" \
"$(EPOCLINKUREL)\EIKCOCTL.LIB" \
"$(EPOCLINKUREL)\WS32.LIB" \
"$(EPOCLINKUREL)\AVKON.LIB" \
"$(EPOCLINKUREL)\BAFL.LIB" \
"$(EPOCLINKUREL)\BITGDI.LIB" \
"$(EPOCLINKUREL)\EIKDLG.LIB"
LINK_OBJS= \
"$(EPOCBLDUREL)\PICODRIVE.UID.obj" \
"$(EPOCBLDUREL)\PICODRIVEEXE.obj" \
"$(EPOCBLDUREL)\UNZIP.obj"
STAGE1_LINK_FLAGS="$(EPOCSTATLINKUREL)\EDLL.LIB" \
$(LIBS) /nologo /entry:"_E32Dll" /subsystem:windows /dll \
/incremental:no /machine:IX86 /nodefaultlib /include:"?_E32Dll@@YGHPAXI0@Z" /out:"$(EPOCBLDUREL)\PICODRIVE.DLL" /WARN:3
PRELINKUREL : $(LINK_OBJS) "$(EPOCSTATLINKUREL)\EDLL.LIB" $(LIBS)
link.exe @<<
$(STAGE1_LINK_FLAGS) $(LINK_OBJS)
<<
del "$(EPOCBLDUREL)\PICODRIVE.DLL"
del "$(EPOCBLDUREL)\PICODRIVE.exp"
dumpbin /exports /out:"$(EPOCBLDUREL)\PICODRIVE.inf" "$(EPOCBLDUREL)\PICODRIVE.lib"
del "$(EPOCBLDUREL)\PICODRIVE.lib"
perl -S makedef.pl -Inffile "$(EPOCBLDUREL)\PICODRIVE.inf" "$(EPOCBLD)PICODRIVE.def"
del "$(EPOCBLDUREL)\PICODRIVE.inf"
lib.exe /nologo /machine:i386 /nodefaultlib /name:"PICODRIVE.DLL" /def:"$(EPOCBLD)PICODRIVE.def" /out:"$(EPOCBLDUREL)\PICODRIVE.lib"
del "$(EPOCBLDUREL)\PICODRIVE.lib"
@echo First-stage link successful
STOPLINKUREL : DELEXPOBJUREL
@echo Stopped the build by removing the export object,
@echo if present, because the pre-link stage failed
POSTBUILDUREL : DELEXPOBJUREL LIBRARY
DELEXPOBJUREL :
if exist "$(EPOCBLDUREL)\PICODRIVE.exp" del "$(EPOCBLDUREL)\PICODRIVE.exp"
RECREATEWORKSPACE :
cd \PICODRIVE\S60
perl -S makmake.pl -D \PICODRIVE\S60\PICODRIVES60.MMP VC6

View file

@ -0,0 +1,5 @@
// Makmake-generated uid source file
#include <E32STD.H>
#pragma data_seg(".E32_UID")
__WINS_UID(0x1000007a,0x00000000,0x00000000)
#pragma data_seg()

136
platform/s60/PicoDrive.rss Normal file
View file

@ -0,0 +1,136 @@
// PicoDriveS60.RSS
//
//
NAME PICO
#include <eikon.rh>
#include <eikon.rsg>
#include <avkon.rsg>
#include <avkon.rh>
RESOURCE RSS_SIGNATURE { }
RESOURCE TBUF16 { buf=""; }
RESOURCE EIK_APP_INFO
{
menubar = r_pico_menubar;
}
RESOURCE MENU_BAR r_pico_menubar // *** Menu bar
{
titles =
{
};
}
RESOURCE ARRAY r_picodrive_keys
{
items=
{
LBUF{txt="Up";},
LBUF{txt="Down";},
LBUF{txt="Left";},
LBUF{txt="Right";},
LBUF{txt="A";},
LBUF{txt="B";},
LBUF{txt="C";},
LBUF{txt="X";},
LBUF{txt="Y";},
LBUF{txt="Z";},
LBUF{txt="Mode";},
LBUF{txt="Start";},
LBUF{txt="Up&Left";},
LBUF{txt="Up&Right";},
LBUF{txt="Down&Right";},
LBUF{txt="Down&Left";},
LBUF{txt="Soft reset";},
LBUF{txt="Pan left";},
LBUF{txt="Pan right";}
};
}
RESOURCE DIALOG r_pico_file_select_dialog
{
flags = EGeneralQueryFlags;
buttons = R_AVKON_SOFTKEYS_DONE_CANCEL;
items =
{
DLG_LINE
{
type = EAknCtListQueryControl;
id = EListQueryControl;
control = AVKON_LIST_QUERY_CONTROL
{
heading = "Files";
listtype = EAknCtSinglePopupMenuListBox;
listbox = LISTBOX
{
flags = EAknDialogSelectionList;
height = 3;
width = 1;
};
};
}
};
}
RESOURCE DIALOG r_pico_add_cheat
{
title="Add cheatcode";
flags=EEikDialogFlagNoDrag |
EEikDialogFlagCbaButtons |
EEikDialogFlagModeless|EEikDialogFlagWait;
buttons = R_AVKON_SOFTKEYS_OK_CANCEL;
items=
{
DLG_LINE
{
type=EEikCtLabel;
id=0x2002;
itemflags = EEikDlgItemNonFocusing;
control= LABEL
{
txt = "Enter cheatcode";
};
},
DLG_LINE
{
itemflags = EEikDlgItemNonFocusing;
id=0x2001;
type=EEikCtLabel;
control= LABEL {
horiz_align=EEikLabelAlignHLeft;
txt = "\nGG: XXXX-XXXX\nPatch: XXXXXX:YYYY";
};
},
DLG_LINE
{
type=EEikCtEdwin;
id=0x2000;
itemflags = EEikDlgItemOfferAllHotKeys|EEikDlgItemSeparatorAfter;
control= EDWIN {
maxlength=12;
};
}
};
}
RESOURCE ARRAY r_picodrive_regions
{
items=
{
LBUF{txt="Region: Auto";},
LBUF{txt="Region: Jap NTSC";},
LBUF{txt="Region: Jap PAL";},
LBUF{txt="Region: US NTSC";},
LBUF{txt="Region: EUR PAL";}
};
}

View file

@ -0,0 +1,31 @@
//
// MAKEFILE.MMP for component PicoDrive S60
//
target PicoDriveS60.app
targetpath system\apps\PicoDriveS60
targettype app
UID 0x100039ce 0x101F9B49
MACRO SERIES60
SOURCEPATH ..\s60
userinclude ..\s60
systeminclude \epoc32\include \epoc32\include\libc ..\s60
// app source
source PicoDriveAppS60.cpp
// libraries
library cone.lib eikcore.lib
library euser.lib apparc.lib
library efsrv.lib apgrfx.lib
library avkon.lib
//resource file
sourcepath ..\S60
resource PicoDriveS60.rss
// Color Bitmap - UK only
AIF picodriveS60.aif ..\S60 picodriveS60aif.rss c12 PicoL.bmp PicoLm.bmp

File diff suppressed because it is too large Load diff

281
platform/s60/PicoDriveExe.h Normal file
View file

@ -0,0 +1,281 @@
#ifndef PicoDriveH
#define PicoDriveH
#include <e32base.h>
#include <eikappui.h>
#include <coecntrl.h>
#include <aknapp.h>
#include <akndoc.h>
#include <MdaAudioOutputStream.h>
#include <Mda\Common\Audio.h>
#include <aknappUI.h>
struct Target
{
unsigned char *screen;
TPoint point; // Screen to client point
TRect view,update;
TInt scanline_length;
TInt screen_offset;
TBool stretch_line;
};
enum TPicoMainMenu
{
ELoadRom,
ELoadState,
ESaveState,
ESetControls,
ESetScreen,
ESelectSound,
ESelectCheat,
EResetHw,
EAboutPico,
EExitPico,
ELastMenuItem
};
enum TPicoSoundMenu
{
EEnableZ80,
EEnableYM2612,
EEnableSN76496,
ESoundVolume,
ESoundRate,
ELastSoundItem
};
enum TPicoCheatMenu
{
EAddCheat,
EClearCheats,
ELastCheatItem
};
enum TPicoControllerMenu
{
EControllerType,
EConfigControls
};
enum TPicoMenus
{
EPicoMainMenu,
ESelectScrMenu,
EAboutPicoMenu,
ESelectSoundMenu,
ESelectControlsMenu,
ESelectCheatMenu
};
enum TPicoKeys
{
EPicoUpKey,
EPicoDownKey,
EPicoLeftKey,
EPicoRightKey,
EPicoAKey,
EPicoBKey,
EPicoCKey,
EPicoXKey,
EPicoYKey,
EPicoZKey,
EPicoModeKey,
EPicoStartKey,
EPicoULKey,
EPicoURKey,
EPicoDRKey,
EPicoDLKey,
EPicoResetKey,
EPicoPanLKey,
EPicoPanRKey,
EPicoNoKeys
};
class CPicoAddCheatDlg:public CEikDialog
{
public:
CPicoAddCheatDlg(TDes8& aCheatCode):iCheatCode(aCheatCode){};
~CPicoAddCheatDlg(){ iEikonEnv->EikAppUi()->RemoveFromStack(this);}
TBool OkToExitL(TInt /*aButtonId*/)
{
static_cast<CEikEdwin*>(ControlOrNull(0x2000))->GetText(iUniCheatCode);
iCheatCode.Copy(iUniCheatCode);
return ETrue;
}
void PreLayoutDynInitL()
{
iEikonEnv->EikAppUi()->AddToStackL(this);
}
private:
TDes8& iCheatCode;
TBuf<16> iUniCheatCode;
};
#ifdef S60V3
class CPicoDriveDoc:public CAknDocument
{
public:
CPicoDriveDoc(CEikApplication& aApp);
~CPicoDriveDoc();
CEikAppUi* CreateAppUiL();
};
class CPicoDriveApp:public CAknApplication
{
public:
CPicoDriveApp();
~CPicoDriveApp();
TUid AppDllUid()const;
CApaDocument* CreateDocumentL();
/**
* From @c CApaApplication. Opens the .ini file associated with the
* application. By default, ini files are not supported by SERIES60
* applications. If you want to use an ini file, either override this
* function to base call @c CEikApplication::OpenIniFileLC, or call it
* directly.
* @param aFs File server session to use. Not used.
* @return Pointer to the dictionary store object representing the
* application's .ini file.
*/
CDictionaryStore* OpenIniFileLC(RFs& aFs) const;
};
#endif
class CQPicoDriveView:public CCoeControl,public MDirectScreenAccess
{
public:
CQPicoDriveView() {};
~CQPicoDriveView();
void Draw(const TRect& aRect) const;
void ConstructL();
void PutBitmap(CFbsBitmap* aBitmap,TPoint aPoint,TRect aRect);
void Restart(RDirectScreenAccess::TTerminationReasons aReason);
void AbortNow(RDirectScreenAccess::TTerminationReasons aReason);
void DrawText(const TDesC& aText,TPoint aPoint,TBool aHighLight=EFalse,TRgb aTextColour = KRgbWhite);
TInt DrawTextInRect(const TDesC& aText,TRect aRect,TInt aStartPos);
void Clear();
CDirectScreenAccess* iDsa;
TBool iDrawingOn;
TBool iForeground;
};
class CPicoDriveUi:public CAknAppUi,public MMdaAudioOutputStreamCallback
{
public:
CPicoDriveUi();
~CPicoDriveUi();
void ConstructL();
void StartAsynchUpdate();
protected:
static TInt AsyncUpdateL(TAny* aAppUi);
void StartEmulatorL();
virtual TKeyResponse HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
void HandleForegroundEventL(TBool aForeground);
// Menu drawers
void PutMainMenu();
void PutScreenSelect();
void PutControllerSelect();
void PutConfigKeys();
void PutSoundSelect();
void PutCheatSelect();
void PutAbout(TBool iOnlyRedraw = EFalse);
// Asynch screen update callback
void UpdateScreen();
TInt SelectFile(TFileName& aFileName);
// Emulation functions
int EmulateInit();
void EmulateExit();
int EmulateFrame();
int InputFrame();
int TargetInit();
void CalulateLineStarts();
static TInt IdleCallBackStop(TAny* aAppUi);
static TInt StartEmulatorL(TAny* aAppUi);
// Settings storage
void SaveSettingsL();
void InternalizeL(const CDictionaryStore& aStore);
void ExternalizeL( CDictionaryStore& aStore);
// Save state handling
int saveLoadGame(int load, int sram);
/**
* Calculates the palette table 0-4096
*/
void CalculatePaletteTable();
CAsyncCallBack iIdleCallBack;
// Variables
TUint16 iPad1;
TUint16 iPad2;
TFileName iRomName;
char RomName[260];
TInt iScanCodes[EPicoNoKeys];
TInt iCurrentScan;
CDesCArrayFlat* iKeyNames;
CDesCArrayFlat* iRegNames;
TBool iEmuRunning;
CQPicoDriveView* iView;
TInt iResourceFileId;
CAsyncCallBack iStartUp;
CFbsBitmap* iBackBuffer;
TFileName iAppPath;
TPoint iPutPoint;
TRect iPutRect;
TInt iSelection;
TInt iSndSelection;
TInt iCtrlSelection;
TInt iCheatSelection;
TInt iNoCheats;
TBool iCheatEnter;
CEikDialog* iCheatDlg;
TInt iListOffset;
TInt iScrMode;
TInt iLastScrMode;
TBool iRomLoaded;
TBool iInterpolate;
TBool iStretch;
TBool iEnableSixButtons;
TPicoMenus iPicoMenu;
CAsyncCallBack iAsyncUpdate;
// sound support
CMdaAudioOutputStream* iSndStream;
TMdaAudioDataSettings iAudioSettings;
TBuf8<442*2*6> iMonoSound;
TInt iCurrentSeg;
TBool iEnableSound;
TBool iSndRateChanged;
TInt iSoundVolume; // 0-10 in 10% percent
void MaoscOpenComplete(TInt aError);
void MaoscBufferCopied(TInt aError, const TDesC8& aBuffer);
void MaoscPlayComplete(TInt aError);
// Update the sound output rate
TBool UpdatePSndRate();
// Rom pointers
unsigned char *RomData;
unsigned int RomSize;
TInt64 LastSecond;
int FramesDone;
int FramesPerSecond;
TDisplayMode iDisplayMode;
TInt iLastAboutPos;
TBool iFirstStart;
TInt iFrameSkip;
TInt iFontHeight;
int (*myPicoScan)(unsigned int scan,unsigned short *pal);
TBuf<1024> iTempString;
// make save filename
char saveFname[KMaxFileName];
};
#endif

View file

@ -0,0 +1,37 @@
target PicoDrive.exe
TARGETTYPE exedll
TARGETPATH system\apps\PicoDriveS60
SOURCEPATH ..\S60
source picodriveexe.cpp
sourcepath ..
source unzip.c
#ifndef WINS
sourcepath ..\gcc
source libgcc2.c
#endif
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc
USERINCLUDE ..\pico ..\pico\sound ..\s60 ..
// libraries
library cone.lib EIKCORE.lib MEDIACLIENTAUDIOSTREAM.LIB
library euser.lib zlib.lib
library efsrv.lib estlib.lib fbscli.lib estor.lib eikcoctl.lib
library ws32.lib AVKON.LIB bafl.lib bitgdi.lib eikdlg.lib
staticlibrary pico.lib
#if defined(WINS)
staticlibrary a68k.obj
staticlibrary mz80_asm.obj
#else
staticlibrary cyclone.o
staticlibrary DRZ80.o
staticlibrary draw.o
//staticlibrary blit.o
staticlibrary ym2612_helper.o
staticlibrary memory.o
staticlibrary draw2.o
#endif
EPOCHEAPSIZE 1024000 8192000
//EPOCSTACKSIZE 65535

View file

@ -0,0 +1,150 @@
// PicoDriveS60.RSS
//
//
NAME Pico
#include <eikon.rh>
#include <eikon.rsg>
#include <avkon.rsg>
#include <avkon.rh>
RESOURCE RSS_SIGNATURE { }
RESOURCE TBUF16 { buf=""; }
RESOURCE EIK_APP_INFO
{
menubar = r_miniapp_menubar;
cba=R_AVKON_SOFTKEYS_OPTIONS_BACK;
}
RESOURCE MENU_BAR r_miniapp_menubar // *** Menu bar
{
titles =
{
MENU_TITLE { menu_pane = r_miniapp_menu; txt = "PicoDrive"; }
};
}
RESOURCE MENU_PANE r_miniapp_menu // *** Submenu 1
{
items =
{
MENU_ITEM { command = EEikCmdExit; txt = "Close";}
};
}
RESOURCE ARRAY r_picodrive_keys
{
items=
{
LBUF{txt="Up";},
LBUF{txt="Down";},
LBUF{txt="Left";},
LBUF{txt="Right";},
LBUF{txt="A";},
LBUF{txt="B";},
LBUF{txt="C";},
LBUF{txt="X";},
LBUF{txt="Y";},
LBUF{txt="Z";},
LBUF{txt="Mode";},
LBUF{txt="Start";},
LBUF{txt="Up&Left";},
LBUF{txt="Up&Right";},
LBUF{txt="Down&Right";},
LBUF{txt="Down&Left";},
LBUF{txt="Soft reset";},
LBUF{txt="Pan left";},
LBUF{txt="Pan right";}
};
}
RESOURCE DIALOG r_pico_file_select_dialog
{
flags = EGeneralQueryFlags;
buttons = R_AVKON_SOFTKEYS_DONE_CANCEL;
items =
{
DLG_LINE
{
type = EAknCtListQueryControl;
id = EListQueryControl;
control = AVKON_LIST_QUERY_CONTROL
{
heading = "Files";
listtype = EAknCtSinglePopupMenuListBox;
listbox = LISTBOX
{
flags = EAknDialogSelectionList;
height = 3;
width = 1;
};
};
}
};
}
RESOURCE DIALOG r_pico_add_cheat
{
title="Add cheatcode";
flags=EEikDialogFlagNoDrag |
EEikDialogFlagCbaButtons |
EEikDialogFlagModeless|EEikDialogFlagWait;
buttons = R_AVKON_SOFTKEYS_OK_CANCEL;
items=
{
DLG_LINE
{
type=EEikCtLabel;
id=0x2002;
itemflags = EEikDlgItemNonFocusing;
control= LABEL
{
txt = "Enter cheatcode";
};
},
DLG_LINE
{
itemflags = EEikDlgItemNonFocusing;
id=0x2001;
type=EEikCtLabel;
control= LABEL {
horiz_align=EEikLabelAlignHLeft;
txt = "\nGG: XXXX-XXXX\nPatch: XXXXXX:YYYY";
};
},
DLG_LINE
{
type=EEikCtEdwin;
id=0x2000;
itemflags = EEikDlgItemOfferAllHotKeys|EEikDlgItemSeparatorAfter;
control= EDWIN {
maxlength=12;
};
}
};
}
RESOURCE ARRAY r_picodrive_regions
{
items=
{
LBUF{txt="Region: Auto";},
LBUF{txt="Region: Jap NTSC";},
LBUF{txt="Region: Jap PAL";},
LBUF{txt="Region: US NTSC";},
LBUF{txt="Region: EUR PAL";}
};
}

View file

@ -0,0 +1,20 @@
#include <aiftool.rh>
RESOURCE AIF_DATA
{
app_uid= 0x101F9B49;
//
hidden=KAppNotHidden;
embeddability=KAppNotEmbeddable;
caption_list=
{
CAPTION { code=ELangEnglish; caption="PicoDrive"; },
CAPTION { code=ELangAmerican; caption="PicoDrive"; }
};
//
num_icons=1;
}

View file

@ -0,0 +1,77 @@
target PicoDrive.exe
TARGETTYPE exe
TARGETPATH sys\bin
SOURCEPATH ..\S60
UID 0x100039ce 0xA00007BE
source picodriveexe.cpp
sourcepath ..
source unzip.c
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc
systeminclude \epoc32\include\mmf\plugin
USERINCLUDE ..\pico ..\pico\sound ..\s60 ..
// libraries
library cone.lib EIKCORE.lib MEDIACLIENTAUDIOSTREAM.LIB
library euser.lib apparc.lib
library efsrv.lib estlib.lib fbscli.lib estor.lib eikcoctl.lib
library ws32.lib AVKON.LIB bafl.lib bitgdi.lib gdi.lib eikdlg.lib
staticlibrary pico.lib
#if defined(WINS)
staticlibrary a68k.obj
staticlibrary mz80_asm.obj
staticlibrary zlib.lib
#else
staticlibrary cyclone.o
staticlibrary DRZ80.o
staticlibrary draw.o
//staticlibrary blit.o
staticlibrary ym2612_helper.o
staticlibrary zlib.lib
staticlibrary memory.o
staticlibrary draw2.o
#endif
sourcepath ..\S60
DOCUMENT interpolatevideo.inl
DOCUMENT normalvideo.inl
DOCUMENT S60V3Video.inl
START RESOURCE PicoDrive_reg.rss
TARGETPATH \private\10003a3f\apps
END
START RESOURCE PicoDrive_loc.rss
TARGETPATH \Resource\Apps
LANG SC
END
SOURCEPATH ..\s60
START RESOURCE PicoDrive.rss
HEADER
TARGETPATH \Resource\Apps
LANG SC
END
START BITMAP PicoDrive.mbm
TARGETPATH \Resource\Apps
SOURCEPATH ..\s60
// Source Color-depth Source-bitmap-list
// c denotes whether the bitmap is a colour bitmap and the digits represent the
// colour-depth of the bitmap and the bitmap mask respectively
SOURCE c24 PicoS.bmp
SOURCE 8 PicoSMI.bmp
SOURCE c24 PicoL.bmp
SOURCE 8 PicoLMI.bmp
END
MACRO S60V3
EPOCHEAPSIZE 1024000 8192000
CAPABILITY NONE

View file

@ -0,0 +1,22 @@
#include <AppInfo.rh>
// This file localise the applications icons and caption
RESOURCE LOCALISABLE_APP_INFO
{
caption_and_icon =
{
CAPTION_AND_ICON_INFO
{
// The caption text is defined in the rls file
caption = "PicoDrive";
// Icons are used to represent applications in the
// application launcher and application title bar.
// The number_of_icons value identifies how many icons
// that exist in the icon_file.
number_of_icons = 2;
// Using the application icons.
icon_file = "\\Resource\\Apps\\PicoDrive.mbm";
}
};
}

View file

@ -0,0 +1,18 @@
// All registration files need to #include appinfo.rh.
#include <AppInfo.rh>
// All registration files must define UID2, which is always
// KUidAppRegistrationResourceFile, and UID3, which is the application's UID.
UID2 KUidAppRegistrationResourceFile
UID3 0xA00007BE // application UID
// Registration file need to containo an APP_REGISTRATION_INFO resource that
// minimally needs to provide the name of the application binary (using the
// app_file statement).
RESOURCE APP_REGISTRATION_INFO
{
app_file = "PicoDrive"; // filename of application binary (minus extension)
// Specify the location of the localisable icon/caption definition file
localisable_resource_file = "\\Resource\\Apps\\PicoDrive_loc";
}

BIN
platform/s60/PicoL.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
platform/s60/PicoLM.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

BIN
platform/s60/PicoLMI.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

BIN
platform/s60/PicoS.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

BIN
platform/s60/PicoSM.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

BIN
platform/s60/PicoSMI.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

View file

@ -0,0 +1,178 @@
#include "PicoDriveAppS60.h"
#include <picodrives60.rsg>
#include <apgcli.h>
#include <eikdll.h>
EXPORT_C CApaApplication* NewApplication()
{
return (new CPicoDrive);
}
CPicoDrive::CPicoDrive()
{
}
CPicoDrive::~CPicoDrive()
{
}
CApaDocument* CPicoDrive::CreateDocumentL()
{
return new (ELeave) CPicoDriveDoc(*this);
}
TUid CPicoDrive::AppDllUid() const
{
return TUid::Uid(0x101F9B49);
}
CPicoDriveDoc::CPicoDriveDoc(CEikApplication& aApp):CAknDocument(aApp)
{
}
CPicoDriveDoc::~CPicoDriveDoc()
{
}
CEikAppUi* CPicoDriveDoc::CreateAppUiL()
{
return new (ELeave) CPicoDriveUi;
}
void CPicoDriveUi::HandleForegroundEventL(TBool aForeground)
{
if(aForeground)
{
BringUpEmulatorL();
}
}
CPicoDriveUi::CPicoDriveUi()
{
}
CPicoDriveUi::~CPicoDriveUi()
{
RemoveFromViewStack(*iView,iView);
DeregisterViewAndRemoveStack(*iView);
delete iView;
if(iWatcher)
{
iThreadWatch.LogonCancel(iWatcher->iStatus);
iWatcher->Cancel();
}
delete iWatcher;
iThreadWatch.Close();
}
void CPicoDriveUi::ConstructL()
{
BaseConstructL();
iView = new(ELeave)CPicoView;
iView->SetMopParent(this);
iView->ConstructL();
RegisterViewAndAddStackL(*iView);
AddToViewStackL(*iView,iView);
SetDefaultViewL(*iView);
TBuf<128> startFile;
startFile = iEikonEnv->EikAppUi()->Application()->AppFullName();
TParse parser;
parser.Set(startFile,NULL,NULL);
startFile = parser.DriveAndPath();
#ifndef __WINS__
startFile.Append( _L("PicoDrive.EXE"));
#else
startFile.Append( _L("PicoDrive.DLL"));
#endif
CApaCommandLine* cmdLine=CApaCommandLine::NewLC(startFile);
RApaLsSession lsSession;
lsSession.Connect();
CleanupClosePushL(lsSession);
lsSession.StartApp(*cmdLine,iThreadId);
CleanupStack::PopAndDestroy();//close lsSession
CleanupStack::PopAndDestroy(cmdLine);
User::After(500000);// Let the application start
TApaTaskList taskList(iEikonEnv->WsSession());
TApaTask myTask=taskList.FindApp(TUid::Uid(0x101F9B49));
myTask.SendToBackground();
TApaTask exeTask=taskList.FindByPos(0);
iExeWgId=exeTask.WgId();
if(iThreadWatch.Open(iThreadId)==KErrNone)
{
iWatcher = new (ELeave)CPicoWatcher;
iWatcher->iAppUi=this;
iThreadWatch.Logon(iWatcher->iStatus);
}
}
CPicoWatcher::CPicoWatcher():CActive(EPriorityStandard)
{
CActiveScheduler::Add(this);
iStatus=KRequestPending;
SetActive();
}
CPicoWatcher::~CPicoWatcher()
{
}
void CPicoWatcher::DoCancel()
{
}
void CPicoWatcher::RunL()
{
iAppUi->HandleCommandL(EEikCmdExit);
}
void CPicoDriveUi::BringUpEmulatorL()
{
RThread thread;
if(thread.Open(iThreadId)==KErrNone)
{
thread.Close();
TApaTask apaTask(iEikonEnv->WsSession());
apaTask.SetWgId(iExeWgId);
apaTask.BringToForeground();
}
else
{
iExeWgId=-1;
}
}
void CPicoDriveUi::HandleCommandL(TInt aCommand)
{
switch(aCommand)
{
case EEikCmdExit:
{
RThread thread;
if(thread.Open(iThreadId)==KErrNone)
{
thread.Terminate(0);
thread.Close();
}
Exit();
}
break;
}
}
GLDEF_C TInt E32Dll(TDllReason)
{
return KErrNone;
}

View file

@ -0,0 +1,78 @@
#ifndef picodriveapps60h
#define picodriveapps60h
#include <aknapp.h>
#include <eikapp.h>
#include <e32base.h>
#include <coecntrl.h>
#include <eikenv.h>
#include <coeview.h>
#include <eikappui.h>
class CPicoView:public MCoeView,public CCoeControl
{
public:
CPicoView() {};
~CPicoView(){};
void ConstructL(){CreateWindowL();SetRect(iEikonEnv->EikAppUi()->ClientRect());ActivateL();SetBlank();};
void ViewDeactivated(){MakeVisible(EFalse);};
void ViewActivatedL(const TVwsViewId& /*aPrevViewId*/,TUid /*aCustomMessageId*/,const TDesC8& /*aCustomMessage*/)
{
MakeVisible(ETrue);
}
TVwsViewId ViewId() const
{
TVwsViewId viewId(TUid::Uid(0x101F9B49),TUid::Uid(0x101010));
return viewId;
}
};
class CPicoDrive:public CEikApplication
{
public:
CPicoDrive();
~CPicoDrive();
CApaDocument* CreateDocumentL();
TUid AppDllUid() const;
};
#include <AKNdoc.h>
class CPicoDriveDoc:public CAknDocument
{
public:
~CPicoDriveDoc();
CEikAppUi* CreateAppUiL();
void ConstructL();
CPicoDriveDoc(CEikApplication& aApplicaiton);
};
#include <aknappui.h>
class CPicoDriveUi;
class CPicoWatcher:public CActive
{
public:
CPicoWatcher();
~CPicoWatcher();
void DoCancel();
void RunL();
CPicoDriveUi* iAppUi;
};
class CPicoDriveUi:public CAknAppUi
{
public:
CPicoDriveUi();
~CPicoDriveUi();
void ConstructL();
void HandleCommandL(TInt aCommand);
void HandleForegroundEventL(TBool aForeground);
void BringUpEmulatorL();
private:
CPicoView* iView;
TThreadId iThreadId;
TInt iExeWgId;
RThread iThreadWatch;
CPicoWatcher* iWatcher;
};
#endif

View file

@ -0,0 +1,15 @@
@ECHO OFF
REM Bldmake-generated batch file - ABLD.BAT
REM ** DO NOT EDIT **
perl -S ABLD.PL "\picodrive\s60\s60v3\\" %1 %2 %3 %4 %5 %6 %7 %8 %9
if errorlevel==1 goto CheckPerl
goto End
:CheckPerl
perl -v >NUL
if errorlevel==1 echo Is Perl, version 5.003_07 or later, installed?
goto End
:End

View file

@ -0,0 +1,12 @@
PRJ_PLATFORMS
GCCE winscw
PRJ_MMPFILES
..\pico.mmp BUILD_AS_ARM
..\picodriveS60V3.mmp BUILD_AS_ARM

371
platform/s60/S60v3video.inl Normal file
View file

@ -0,0 +1,371 @@
static int EmulateScanFull16(unsigned int scan,unsigned short *data)
{
unsigned short *ps=NULL,*end=NULL;
unsigned short *pd=NULL;
unsigned short *pdSrc1 = NULL;
unsigned short *pdSrc2 = NULL;
int screenScan;
int index = 0;
int xpitch=0;
TInt retValue = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
screenScan = gLineTable[scan];
if ((int)screenScan< 0) return 0; // Out of range
if ((int)screenScan>=Targ.view.iBr.iY) return 0; // Out of range
pd=(unsigned short*)(Targ.screen+screenScan*2+Targ.screen_offset);
pdSrc1 = pd;
xpitch=-(Targ.scanline_length>>1);
if((Pico.video.reg[12]&1))
{
ps=data; end=ps+320;
do
{
if(gColumnStepTable[index]>1)
{
*pd = gColorMapTab[*ps];
pd+=xpitch;
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
index++;
ps++;
}
else if(gColumnStepTable[index]>0)
{
*pd = gColorMapTab[*ps];
index++;
ps++;
}
else
{
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
ps+=2;
index+=2;
}
pd+=xpitch;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 10 pixels into 7
do
{
if(gNarrowColumnStepTable[index]>1)
{
*pd = gColorMapTab[*ps];
pd+=xpitch;
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
index++;
}
else if(gNarrowColumnStepTable[index]>0)
{
*pd = gColorMapTab[*ps];
ps++;
index++;
}
else
{
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
ps+=2;
index+=2;
}
pd+=xpitch;
}
while (ps<end);
}
if(scan>0 && screenScan != gLineTable[scan-1]+1)
{
pdSrc2 = pdSrc1-2;
pd = pdSrc1-1;
for(TInt loop=0;loop<Targ.view.iBr.iY;loop++)
{
*pd=((*pdSrc1+*pdSrc2)>>1);
pd+=xpitch;
pdSrc1+=xpitch;
pdSrc2+=xpitch;
}
}
return retValue;
}
static int EmulateScanFullRight16(unsigned int scan,unsigned short *data)
{
unsigned short *ps=NULL,*end=NULL;
unsigned short *pd=NULL;
unsigned short *pdSrc1 = NULL;
unsigned short *pdSrc2 = NULL;
int screenScan;
int xpitch=0;
int retValue = 0;
int index = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
screenScan = gLineTable[scan];
if ((int)screenScan< 0) return 0; // Out of range
if ((int)screenScan>=Targ.view.iBr.iY) return 0; // Out of range
pd=(unsigned short*)(Targ.screen+Targ.scanline_length-screenScan*2);
pdSrc1 = pd;
xpitch=+(Targ.scanline_length>>1);
if((Pico.video.reg[12]&1))
{
ps=data; end=ps+320;
do
{
if(gColumnStepTable[index]>1)
{
*pd = gColorMapTab[*ps];
pd+=xpitch;
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
index++;
ps++;
}
else if(gColumnStepTable[index]>0)
{
*pd = gColorMapTab[*ps];
index++;
ps++;
}
else
{
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
ps+=2;
index+=2;
}
pd+=xpitch;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 10 pixels into 7
do
{
if(gNarrowColumnStepTable[index]>1)
{
*pd = gColorMapTab[*ps];
pd+=xpitch;
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
index++;
}
else if(gNarrowColumnStepTable[index]>0)
{
*pd = gColorMapTab[*ps];
ps++;
index++;
}
else
{
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
ps+=2;
index+=2;
}
pd+=xpitch;
}
while (ps<end);
}
if(scan>0 && screenScan != gLineTable[scan-1]+1)
{
pdSrc2 = pdSrc1+2;
pd = pdSrc1+1;
for(TInt loop=0;loop<Targ.view.iBr.iY;loop++)
{
*pd=((*pdSrc1+*pdSrc2)>>1);
pd+=xpitch;
pdSrc1+=xpitch;
pdSrc2+=xpitch;
}
}
return retValue;
}
static int EmulateScan16(unsigned int scan,unsigned short *data)
{
// int len=0;
unsigned short *ps=NULL,*end=NULL;
unsigned short *pd=NULL;
int xpitch=0;
int retValue = 0;
int index = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
scan = gLineTable[scan];
if ((int)scan< 0) return 0; // Out of range
if ((int)scan>=Targ.view.iBr.iY) return 0; // Out of range
pd=(unsigned short*)(Targ.screen+scan*Targ.scanline_length);
xpitch=2;
if((Pico.video.reg[12]&1))
{
ps=data; end=ps+320;
do
{
if(gColumnStepTable[index]>0)
{
*pd = gColorMapTab[*ps];
ps++;
index++;
}
else
{
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
ps+=2;
index+=2;
}
pd++;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 10 pixels into 7
do
{
if(gNarrowColumnStepTable[index]>0)
{
*pd = gColorMapTab[*ps];
ps++;
index++;
}
else
{
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
ps+=2;
index+=2;
}
pd++;
}
while (ps<end);
}
return retValue;
}
static int EmulateStretchScan16(unsigned int scan,unsigned short *data)
{
unsigned short *ps=NULL,*end=NULL;
unsigned short *pd=NULL;
unsigned short *pdSrc1 = NULL;
unsigned short *pdSrc2 = NULL;
int retValue = 0;
int index = 0;
int screenScan;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
screenScan = gLineTable[scan];
if ((int)screenScan<0)
return 0; // Out of range
if ((int)screenScan>=Targ.view.iBr.iY)
return 0; // Out of range
pd=(unsigned short*)(Targ.screen+screenScan*Targ.scanline_length);
pdSrc1 = pd;
if((Pico.video.reg[12]&1))
{
ps=data; end=ps+320;
do
{
if(gColumnStepTable[index]>1)
{
*pd = gColorMapTab[*ps];
pd++;
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
index++;
ps++;
}
else if(gColumnStepTable[index]>0)
{
*pd = gColorMapTab[*ps];
index++;
ps++;
}
else
{
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
ps+=2;
index+=2;
}
pd++;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 10 pixels into 7
do
{
if(gNarrowColumnStepTable[index]>1)
{
*pd = gColorMapTab[*ps];
pd++;
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
index++;
}
else if(gNarrowColumnStepTable[index]>0)
{
*pd = gColorMapTab[*ps];
ps++;
index++;
}
else
{
*pd = ((gColorMapTab[*ps]+gColorMapTab[*(ps+1)])>>1);
ps+=2;
index+=2;
}
pd++;
}
while (ps<end);
}
if(scan>0 && screenScan != gLineTable[scan-1]+1)
{
pdSrc2 = pdSrc1-Targ.scanline_length;
pd = pdSrc1-(Targ.scanline_length>>1);
for(TInt loop=0;loop<Targ.view.iBr.iX;loop++)
{
*pd=((*pdSrc1+*pdSrc2)>>1);
pd++;
pdSrc1++;
pdSrc2++;
}
}
return retValue;
}

12
platform/s60/bld.inf Normal file
View file

@ -0,0 +1,12 @@
PRJ_PLATFORMS
WINS ARMI arm4 thumb winscw
PRJ_MMPFILES
.\pico.mmp
.\picodriveS60.mmp
.\PicoDriveAppS60.mmp

1
platform/s60/c.bat Normal file
View file

@ -0,0 +1 @@
createsis sign -key key-gen1.key -cert cert-gen1.cer -pass pico picodrives603rd.sis PicoS603rd.sis

20
platform/s60/cert-gen.cer Normal file
View file

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDRzCCAwWgAwIBAgIBADALBgcqhkjOOAQDBQAwgYgxEjAQBgNVBAoTCVBpY29E
cml2ZTFyMHAGA1UEAxNpUGljb0RyaXZlUzYwIDNyZCBFZGl0aW9uIGI2YjM0MGEw
NDUwZWZiOGVhMWU5Nzg0ZjhlMTc3NDkzYWUxZTk3M2I2YzFlZTQ4YzdjZTc5NTRm
YTE1NzMzMjNkNzZjNWJjOThmM2QxYWIzMB4XDTA2MDczMDE0MjQzNFoXDTA3MDcz
MDE0MjQzNFowgYgxEjAQBgNVBAoTCVBpY29Ecml2ZTFyMHAGA1UEAxNpUGljb0Ry
aXZlUzYwIDNyZCBFZGl0aW9uIGI2YjM0MGEwNDUwZWZiOGVhMWU5Nzg0ZjhlMTc3
NDkzYWUxZTk3M2I2YzFlZTQ4YzdjZTc5NTRmYTE1NzMzMjNkNzZjNWJjOThmM2Qx
YWIzMIIBtjCCASsGByqGSM44BAEwggEeAoGBAKFNfGnxxT6j7q2lPQt1MnJckjyY
hYC6obfgf6gE/3XV0zNFU5TZlQkZph78m4Zp4GtK5oW/spVyCLfnwgs4UnH0E3tf
MOG1wXDhaHLjgAENiD4iQbumqTN5ri0wXcqnJC5rigk//TR3mvZ7JvjDeaMXK+Xu
gE/1uF8JoxAQHC/zAhUAl8PPPiuqVpZ6bWAwDeyBmHsKOOUCgYA6cPQiswwNVZWZ
mF5DALTAm6/zrPUkmBbe8Vk2jW37lVpIoLCJofNskNpshe4ZTTHtGOgzhjaCOsgL
juf2O0QqhZG8Wwhzo2fNosbZWxonSmmg1JIKn/32oK6FjaK3VAWno+lgGK0GhTC6
Or+HqvvLdtaBeXHqrZWBXfvbYU8XAAOBhAACgYBVTFzZLgkclbXWAsszLExHwCYm
p3Jw10VfNBJxiYq5JxP+jifLLwt9nyt65h4N/y3AyYxL/f11mU7XUGsTU7x4U3NF
9WStFmpBOlJ1MrH09v2L1yi/D8gA7wfRgerErIadurc3ZcfqHyiafaoABzGczttq
vE1o/BRWm+GmciQjVjALBgcqhkjOOAQDBQADLwAwLAIUMc/hS91kPFwtmUO7j4Dp
3deMtZQCFGigHND6/mfaWOyfip4mQe2s4l4T
-----END CERTIFICATE-----

View file

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDSTCCAwagAwIBAgIBADALBgcqhkjOOAQDBQAwgYgxEjAQBgNVBAoTCVBpY29E
cml2ZTFyMHAGA1UEAxNpUGljb0RyaXZlUzYwIDNyZCBFZGl0aW9uIDY3MzZkOWY0
NjZjMDNmY2Y3MmE2ZDhkYTgxYWFlZjEyYWFlOTc3NDExZmEyZDM0ZDY2MDE5Zjk1
NmRiMzA2NmUyNTkyZjE0NTNlMjBhNDc2MB4XDTA2MDgwMjIyMjI0MFoXDTA3MDgw
MjIyMjI0MFowgYgxEjAQBgNVBAoTCVBpY29Ecml2ZTFyMHAGA1UEAxNpUGljb0Ry
aXZlUzYwIDNyZCBFZGl0aW9uIDY3MzZkOWY0NjZjMDNmY2Y3MmE2ZDhkYTgxYWFl
ZjEyYWFlOTc3NDExZmEyZDM0ZDY2MDE5Zjk1NmRiMzA2NmUyNTkyZjE0NTNlMjBh
NDc2MIIBtzCCASwGByqGSM44BAEwggEfAoGBALRUuJYcdrh5PdDdpsN2t4mBhNy2
Vy+GEF2LR8KzHXB27KdAYvqhQmpCJ6gMyC3zvg6Gw1s0lyO/f+HI563qqUYFgxbx
ka4F2lWxeQOnw/bB2NhG/WGqVPHsARyg8+RI1cfVwHo67Fj91aftE0gTUzw/ZiCT
QYrLxvuaatiyrKP9AhUAlk4NyEkcgRkZeyiae/QaIq9VScECgYEArw/5SQAoluMg
8y0VqTZp23e8zsBN46VwYOq4kBY4b1Evl6UoX20hcWtanqvozlkLKEVP/BbCHut7
YUgy/zPtAc4hv/biUd1uEIsCf/4NvVBP5NBHal0xzcJQQDMiA0nha3igOQ4v2ItT
Oqsts0HDzxK3OxC3XuirRiOlLTSywKADgYQAAoGACbtcf0HKOT2ZD5n+KUJDOZS2
ipJsSQUjVdJqgcZo+M6+Hg9KpSIMTexr3CW3JtvwNZx4hh5EbtyuYiYnjmTX611L
258Ytr1pw93F7LztO/H0GOCU977Y7s/UZtoF/XJiGKKuYGLEiBIzBWUEchvDgpIB
J0D1lZa5JLfrt6i68pkwCwYHKoZIzjgEAwUAAzAAMC0CFBseBBEe6eFXOP0Oo1T1
sdN2bzfyAhUAilFr5j3mPd3p0Gs+hZe+33NzSdg=
-----END CERTIFICATE-----

View file

@ -0,0 +1 @@
createsis sign -key key-gen1.key -cert cert-gen1.cer -pass pico picodrives603rd.sis PicoS603rd.sis

112
platform/s60/install.txt Normal file
View file

@ -0,0 +1,112 @@
Welcome to the S60 version
of Picodrive!
Credits
-------
This work is mainly based on
Picodrive by Dave,
(www.finalburn.com)
with added sound support and other improvements by Notaz
(http://notaz.atspace.com).
ARM asm Z80 core is provided by DrZ80 by Reezy
(http://reesy.gp32x.de/)
and YM2612 and SN76489 support are provided by the M.A.M.E project
(http://www.mame.net/).
See credits within Picodrive for more information.
Instructions
------------
Picodrive S60 is a Megadrive/ Genesis emulator which enables you to play old games on your S60 phone.
When its started you are presented with a main menu.
Use arrows to navigate up and down in the menu and use left softkey or the middle button to select an option
* Load ROM
Displays a simple built in filebrowser. Displays the last folder you browsed,and default this is top level, with a drive listine (E: is your memory card)
Use the left soft key (right softkey will cancel) and then navigate until you are in the folder with your rom files.
Use the left softkey to select a file, and emulation will comence as soon as the rom has been loaded.
Supported data types are either SMD,BIN or a ZIP with a single SMD or BIN file inside.
* Load state
Only working when a rom has been loaded, used to load a saved game state for the currently loaded rom. Emulation will resume automatically when the state has been loaded.
* Save state
Only working when a rom has been loaded. Saves the current state of a rom.
* Configure controls
Lets you configure the controls to use for game play.
Only one control at port 1 is supported. It might be either a 3 button or 6 button joypad.
Select using the confirm/left softkey and return to the main menu using the 'C' key.
Default is
3 button pad.
Up - Joystick up
Down - Joystick down
Left - Joystick left
Right - Joystick right
A - Left soft key
B - Middle/confirm key
C - Right soft key
X - Not configured
Y - Not configured
Z - Not configured
Start - '0' key
Up&Left - Not configured
Up&Right - Not configured
Down&Right - Not configured
Down&Left - Not configured
'C' key is used to get back to the main menu when running the emulation and should not be used for anything else.
3 button pad/6 button pad - Selects to toggle between the two pad types
Configure keys - Select this to redefine the key bindings
Press the key you want to assign to the requested action.
You can assign the same key to the same action, and is good if you dont need the 8 way controls.
* Configure screen
Lets you configure the screen mode and frameskip.
Use left softkey or confirm key to select mode. After adjust interpolate or frameskip, select a screen mode to exit the menu
Portrait is a scaled mode, to 176x168 (default)
Landscape modes are a portrait mode which scales down to 208x168
Portrait stretched is a scaled modenot in aspect, and scales to 176x208
Interpolate on means that a scanline is interpolated to a smoother look, but this also requires more cpu.
(default on)
Frameskip lets you decide if you want to set your own constant frameskip or let the action decide
(default is auto)
* Configure sound
Lets you configure sound settings.
Use confirm or left soft key to change a value and use the 'c' key to exit to the main menu
Z80 - Used in many games to drive the sound Will cost a penalty in shown FPS, but can increase compability if enabled even if sound is turned off.
(default is on)
YM2612 - FM OPL sound Enable for FM sound
(default is on)
SN76496 - TI Sound chip - Enable for sound
(default is on)
Volume - Select to change volume
(Default is 60%)
Sample rate - Select to toggle between 8Khz,11Khz,16Khz and 22Khz. If you select a rate which is not compatible with your phone it will be reset back to 8Khz.
(default is 8KHZ)
* Reset
Will reset the current rom if loaded, and resume execution from the start
* Credits
Displays a full credits list for the Picodrive project
* Exit
Exit Picodrive
Last line will display the name of the rom currently loaded
Please enjoy and have fun.

View file

@ -0,0 +1,213 @@
static int EmulateScanFull16_176Interpolate(unsigned int scan,unsigned short *data)
{
unsigned short *ps=NULL,*end=NULL;
unsigned char *pd=NULL;
int xpitch=0;
TInt retValue = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
scan = gLineTable[scan];
if ((int)scan< 0) return 0; // Out of range
if ((int)scan>=176) return 0; // Out of range
pd=Targ.screen+gLineOffsets[scan];//Targ.screen+scan*2+Targ.screen_offset+8;
xpitch=-Targ.scanline_length;
if((Pico.video.reg[12]&1))
{
ps=data; end=ps+320;
// Reduce 14 pixels into 9
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[1]]+gColorMapTab[ps[2]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[3]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[4]]+gColorMapTab[ps[5]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[6]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[7]]+gColorMapTab[ps[8]])>>1);pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[9]]+gColorMapTab[ps[10]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[11]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[12]]+gColorMapTab[ps[13]])>>1);pd+=xpitch;
ps+=14;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 5 pixels into 4
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[1]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[2]]+gColorMapTab[ps[3]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[4]];pd+=xpitch;
ps+=5;
}
while (ps<end);
}
return retValue;
}
static int EmulateScanFullRight16_176Interpolate(unsigned int scan,unsigned short *data)
{
unsigned short *ps=NULL,*end=NULL;
unsigned char *pd=NULL;
int xpitch=0;
int retValue = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
scan = gLineTable[scan];
if ((int)scan< 0) return 0; // Out of range
if ((int)scan>=176) return 0; // Out of range
pd=Targ.screen+gLineOffsets[scan];//Targ.screen+Targ.scanline_length-scan*2-8;
xpitch=+Targ.scanline_length;
if((Pico.video.reg[12]&1))
{
ps=data; end=ps+320;
// Reduce 14 pixels into 9
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[1]]+gColorMapTab[ps[2]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[3]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[4]]+gColorMapTab[ps[5]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[6]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[7]]+gColorMapTab[ps[8]])>>1);pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[9]]+gColorMapTab[ps[10]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[11]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[12]]+gColorMapTab[ps[13]])>>1);pd+=xpitch;
ps+=14;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 5 pixels into 4
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[1]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[2]]+gColorMapTab[ps[3]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[4]];pd+=xpitch;
ps+=5;
}
while (ps<end);
}
return retValue;
}
static int EmulateScan16_176Interpolate(unsigned int scan,unsigned short *data)
{
unsigned short *ps=NULL,*end=NULL;
unsigned char *pd=NULL;
int xpitch=0;
int retValue = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
scan = gLineTable[scan];
if ((int)scan< 0) return 0; // Out of range
if ((int)scan>=176) return 0; // Out of range
pd=Targ.screen+gLineOffsets[scan];//Targ.screen+scan*Targ.scanline_length;
xpitch=2;
if((Pico.video.reg[12]&1))
{
ps=data; end=ps+320;
// Reduce 9 pixels into 5
do
{
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[0]]+gColorMapTab[ps[1]])>>1);pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[2]]+gColorMapTab[ps[3]])>>1);pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[4]]+gColorMapTab[ps[5]])>>1);pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[6]]+gColorMapTab[ps[7]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[8]];pd+=xpitch;
ps+=9;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 10 pixels into 7
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[1]]+gColorMapTab[ps[2]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[3]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[4]]+gColorMapTab[ps[5]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[6]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[7]]+gColorMapTab[ps[8]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[9]];pd+=xpitch;
ps+=10;
}
while (ps<end);
}
return retValue;
}
static int EmulateStretchScan16_176Interpolate(unsigned int scan,unsigned short *data)
{
unsigned short *ps=NULL,*end=NULL;
unsigned char *pd=NULL;
int xpitch=0;
int retValue = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
scan = gLineTable[scan];
if ((int)scan<0)
return 0; // Out of range
if ((int)scan>=208)
return 0; // Out of range
pd=Targ.screen+gLineOffsets[scan];//Targ.screen+scan*Targ.scanline_length;
xpitch=2;
if((Pico.video.reg[12]&1))
{
ps=data; end=ps+320;
// Reduce 9 pixels into 5
do
{
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[0]]+gColorMapTab[ps[1]])>>1);pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[2]]+gColorMapTab[ps[3]])>>1);pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[4]]+gColorMapTab[ps[5]])>>1);pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[6]]+gColorMapTab[ps[7]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[8]];pd+=xpitch;
ps+=9;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 10 pixels into 7
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[1]]+gColorMapTab[ps[2]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[3]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[4]]+gColorMapTab[ps[5]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[6]];pd+=xpitch;
*(unsigned short *)pd=(unsigned short)((gColorMapTab[ps[7]]+gColorMapTab[ps[8]])>>1);pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[9]];pd+=xpitch;
ps+=10;
}
while (ps<end);
}
return retValue;
}

15
platform/s60/key-gen.key Normal file
View file

@ -0,0 +1,15 @@
-----BEGIN DSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,DC864EF6667B49B5
oJZfn5zYx3zcNkaWTGEtmTbRB/wBifvWi65aZiexLtWCTmHM/ivllpU2mwtLAoNF
u4yGun8VJlY0rUwGJeRgi3CiOAztv7ZdsBpAPW3diIqFmjKjC7z/zyGlPis1o9mN
EilGXwSp5Vri78k2wUf5z9MKIIw73ghdbTYstyfveDqhz1pwdDIz5KGmGXzwzilR
zt2yKqGvih8jhoulm4QeBzvMC+8H5esgr5AY00pH1nb0hCapJ//9ZEF96pDmsxrj
GczA1A4x4XcoapxSbr8I9fK6krTQb1Hk5VlGJ9edpqvXEb3v70t9Dmn4nOEYUcIR
bQR05wQ4VM5UUgR+j4H19rqNvA3PyBVzGxgdqyf0I6mX/b0beUXx66lHWXhxX6Ou
mxrfoJ2VLwpxLjK50tSb0LKjwlBvCfuYgWVyqbQotQGD25+XhlvRsK/pn6VOZhdp
VrLK/VfTMV/OH1jtUvTrQkAbXOOVv7ykXqhpf/BvAxzvuThaN6aPzdnmJkVnCGKt
cilqlUnHus10OshHmSSG72dZAen6Blk4d4pRj70tWc1MrjQSLQmr7e9eXsb66Wlx
5PACJbz6cuf+/HOOE/II1g==
-----END DSA PRIVATE KEY-----

15
platform/s60/key-gen1.key Normal file
View file

@ -0,0 +1,15 @@
-----BEGIN DSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,1A2FBCDEC9FFBC99
6sognJox0C7uNUeZRhjUZIK2tErcdKBVUI24Q+wOCtOisbUxywjWDqra7xqMjgWe
swt2oAf28+MvEqivI13Ftpe05iqoM8TbVvEz+0s4fe4GWHs9j4OaVjsxIYcIz4IK
VjcmheoOxkvFyFavwGa/dUPvrGUj++dXz5igOE6+WQhKlio18bbnpjv/iEJyPjFl
+LJnU757jrRRxUXO3bQAhP5ddE4PFrethDyNQpchJgvlf/8glUTIrafTLGXbohuD
838pUktXc67mcPQd59CMVe/Uia3q9R0HfIzdzcGlcd9FM3n8iklFqTmqfB2gBuZY
V39ESxRSJCRozO7QR6yjlxjYTDMe2YAaIcSzdrx35kU1Jxjbm7BpbKZLmCnfsesn
+Nj0A5HWruoMR5qulScbXtZ+CMZz7fLsdoG7Y6Y7xtyK4pXx33WlPtkkDf2nA8gS
cYo3/yfx9uECudVLgvGctNmnuR8X+lFUuo/5lEo3u3P62zTaEfFHHzHdyo5y97qV
JGr6Lt1VIz8lh/iVb5TPXkkJaR0jpaqqZsJiLBho1ULvdAp2duVk5skAnH7EhD/Z
KAwoHH70fFXV4n5TegiJ4g==
-----END DSA PRIVATE KEY-----

View file

@ -0,0 +1,265 @@
static int EmulateScanFull16_176(unsigned int scan,unsigned short *data)
{
unsigned short *ps=NULL,*end=NULL;
unsigned char *pd=NULL;
int xpitch=0;
TInt retValue = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
scan = gLineTable[scan];
if ((int)scan< 0) return 0; // Out of range
if ((int)scan>=176) return 0; // Out of range
pd=Targ.screen+gLineOffsets[scan];//Targ.screen+scan*2+Targ.screen_offset+8;
xpitch=-Targ.scanline_length;
if(Pico.video.reg[12]&1)
{
ps=data; end=ps+320;
// Reduce 14 pixels into 9
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[1]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[3]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[4]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[6]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[7]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[9]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[11]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[12]];pd+=xpitch;
ps+=14;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 5 pixels into 4
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[1]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[2]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[4]];pd+=xpitch;
ps+=5;
}
while (ps<end);
}
return retValue;
}
static int EmulateScanFullRight16_176(unsigned int scan,unsigned short *data)
{
unsigned short *ps=NULL,*end=NULL;
unsigned char *pd=NULL;
int xpitch=0;
int retValue = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
scan = gLineTable[scan];
if ((int)scan< 0) return 0; // Out of range
if ((int)scan>=176) return 0; // Out of range
pd=Targ.screen+gLineOffsets[scan];//Targ.screen+Targ.scanline_length-scan*2-8;
xpitch=+Targ.scanline_length;
if(Pico.video.reg[12]&1)
{
ps=data; end=ps+320;
// Reduce 14 pixels into 9
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[1]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[3]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[4]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[6]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[7]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[9]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[11]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[12]];pd+=xpitch;
ps+=14;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 5 pixels into 4
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[1]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[2]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[4]];pd+=xpitch;
ps+=5;
}
while (ps<end);
}
return retValue;
}
static int EmulateScan16_176(unsigned int scan,unsigned short *data)
{
// int len=0;
unsigned short *ps=NULL,*end=NULL;
unsigned char *pd=NULL;
int xpitch=0;
int retValue = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
scan = gLineTable[scan];
if ((int)scan< 0) return 0; // Out of range
if ((int)scan>=176) return 0; // Out of range
pd=Targ.screen+gLineOffsets[scan];//Targ.screen+scan*Targ.scanline_length;
xpitch=2;
if(Pico.video.reg[12]&1)
{
ps=data; end=ps+320;
// Reduce 9 pixels into 5
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[2]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[4]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[6]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[8]];pd+=xpitch;
ps+=9;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 10 pixels into 7
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[1]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[3]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[4]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[6]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[7]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[9]];pd+=xpitch;
ps+=10;
}
while (ps<end);
}
return retValue;
}
static int EmulateStretchScan16_176(unsigned int scan,unsigned short *data)
{
unsigned short *ps=NULL,*end=NULL;
unsigned char *pd=NULL;
int xpitch=0;
int retValue = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
scan = gLineTable[scan];
if ((int)scan<0)
return 0; // Out of range
if ((int)scan>=208)
return 0; // Out of range
pd=Targ.screen+gLineOffsets[scan];//Targ.screen+scan*Targ.scanline_length;
xpitch=2;
if(Pico.video.reg[12]&1)
{
ps=data; end=ps+320;
// Reduce 9 pixels into 5
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[2]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[4]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[6]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[8]];pd+=xpitch;
ps+=9;
}
while (ps<end);
}
else
{
ps=data+32; end=ps+256;
// Reduce 10 pixels into 7
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[1]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[3]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[4]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[6]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[7]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[9]];pd+=xpitch;
ps+=10;
}
while (ps<end);
}
return retValue;
}
static int EmulateStretchScan16_320(unsigned int scan,unsigned short *data)
{
unsigned short *ps=NULL,*end=NULL;
unsigned char *pd=NULL;
int xpitch=0;
int retValue = 0;
if(scan<224)
retValue = 1-(gLineTable[scan+1]-gLineTable[scan]);
scan = gLineTable[scan];
if ((int)scan<0)
return 0; // Out of range
if ((int)scan>=208)
return 0; // Out of range
pd=Targ.screen+gLineOffsets[scan];//Targ.screen+scan*Targ.scanline_length;
xpitch=2;
ps=data+gFullOffset; end=ps+176;
/* if(!(Pico.video.reg[12]&1))
{
ps=data+gFullOffset; end=ps+176;
}
else
{
ps=data+32+gFullOffset; end=ps+176;
}*/
// Draw 8 pixels in a row
do
{
*(unsigned short *)pd=gColorMapTab[ps[0]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[1]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[2]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[3]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[4]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[5]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[6]];pd+=xpitch;
*(unsigned short *)pd=gColorMapTab[ps[7]];pd+=xpitch;
ps+=8;
}
while (ps<end);
return retValue;
}

181
platform/s60/pico.dsp Normal file
View file

@ -0,0 +1,181 @@
# Microsoft Developer Studio Project File - Name="PICO" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=PICO - Win32 Uni Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "PICO.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "PICO.mak" CFG="PICO - Win32 Uni Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "PICO - Win32 Uni Debug" (based on "Win32 (x86) Static Library")
!MESSAGE "PICO - Win32 Uni Release" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "PICO - Win32 Uni Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\Win32_U0"
# PROP BASE Intermediate_Dir ".\Win32_U0"
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "\s60v1\EPOC32\RELEASE\WINS\UDEB"
# PROP Intermediate_Dir "\s60v1\EPOC32\BUILD\PICODRIVE\S60\PICO\WINS\UDEB"
# ADD CPP /nologo /Zp4 /MDd /W4 /Zi /Od /X /I "\PICODRIVE\PICO" /I "\PICODRIVE\CYCLONE" /I "\s60v1\EPOC32\INCLUDE" /I "\s60v1\EPOC32\INCLUDE\LIBC" /D "__SYMBIAN32__" /D "__VC32__" /D "__WINS__" /D "__AVKON_ELAF__" /D "_USE_MZ80" /D "EMU_A68K" /D "_DEBUG" /D "_UNICODE" /FR /Fd"\s60v1\EPOC32\RELEASE\WINS\UDEB\PICO.PDB" /GF /c
# ADD BASE RSC /l 0x809
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /machine:IX86
# ADD LIB32 /nologo /subsystem:windows /machine:IX86 /nodefaultlib /out:"\s60v1\EPOC32\RELEASE\WINS\UDEB\PICO.LIB"
!ELSEIF "$(CFG)" == "PICO - Win32 Uni Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\Win32_Un"
# PROP BASE Intermediate_Dir ".\Win32_Un"
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "\s60v1\EPOC32\RELEASE\WINS\UREL"
# PROP Intermediate_Dir "\s60v1\EPOC32\BUILD\PICODRIVE\S60\PICO\WINS\UREL"
# ADD CPP /nologo /Zp4 /MD /W4 /O1 /Op /X /I "\PICODRIVE\PICO" /I "\PICODRIVE\CYCLONE" /I "\s60v1\EPOC32\INCLUDE" /I "\s60v1\EPOC32\INCLUDE\LIBC" /D "__SYMBIAN32__" /D "__VC32__" /D "__WINS__" /D "__AVKON_ELAF__" /D "_USE_MZ80" /D "EMU_A68K" /D "NDEBUG" /D "_UNICODE" /GF /c
# ADD BASE RSC /l 0x809
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /machine:IX86
# ADD LIB32 /nologo /subsystem:windows /machine:IX86 /nodefaultlib /out:"\s60v1\EPOC32\RELEASE\WINS\UREL\PICO.LIB"
!ENDIF
# Begin Target
# Name "PICO - Win32 Uni Debug"
# Name "PICO - Win32 Uni Release"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
# Begin Source File
SOURCE=\PICODRIVE\PICO\Area.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Cart.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Draw.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Draw2.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Ggenie.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Memory.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Misc.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Pico.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Sek.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Utils.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Videoport.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\SOUND\Sn76496.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\SOUND\Sound.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\SOUND\Ym2612.c
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\S60\Pico.mmp
# PROP Exclude_From_Build 1
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=\PICODRIVE\PICO\Ggenie.h
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\SOUND\Sn76496.h
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\SOUND\Ym2612.h
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Pico.h
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\SOUND\Mz80.h
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\SOUND\Driver.h
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\SOUND\Sound.h
# End Source File
# Begin Source File
SOURCE=\PICODRIVE\PICO\Picoint.h
# End Source File
# End Group
# End Target
# End Project

24
platform/s60/pico.mmp Normal file
View file

@ -0,0 +1,24 @@
// *** Definitions
TARGET pico.lib
TARGETTYPE lib
SOURCEPATH ..\pico
source Area.c Cart.c Draw.c Memory.c Misc.c Pico.c Sek.c Utils.c VideoPort.c Draw2.c ggenie.c
// source Draw2.c
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc
USERINCLUDE ..\pico ..\cyclone
sourcepath ..\pico\sound
source sn76496.c sound.c ym2612.c
#ifdef WINS
MACRO _USE_MZ80
MACRO EMU_A68K
#else
MACRO EMU_C68K
MACRO _USE_DRZ80
MACRO _ASM_DRAW_C
MACRO _ASM_MEMORY_C
MACRO _USE_YM2612_ASM_HELPER
#endif

View file

@ -0,0 +1,6 @@
BLD: UDEB
REBUILD : CLEANUDEB UDEB
include pico.mak

View file

@ -0,0 +1,6 @@
BLD: UREL
REBUILD : CLEANUREL UREL
include pico.mak

View file

@ -0,0 +1,27 @@
;
; Basic install file for picodriveS60
;
; Languages
; none - English only by default
; Installation header
; Only one component name as we only support English
; UID is the app's UID
#{"PicoDriveS60 1st Edition "},( 0x101F9B49 ),0,60,0
(0x101F6F88), 0, 0, 0, {"Series60ProductID"}
; Application file
"\epoc32\release\armi\urel\picodriveS60.app"-"!:\system\apps\picodriveS60\picodriveS60.app"
"\epoc32\release\armi\urel\picodrive.exe"-"!:\system\apps\picodriveS60\picodrive.exe"
"\epoc32\release\armi\urel\picodriveS60.rsc"-"!:\system\apps\picodriveS60\picodriveS60.rsc"
"\epoc32\release\armi\urel\picodriveS60.aif"-"!:\system\apps\picodriveS60\picodriveS60.aif"
""-"c:\system\apps\picodriveS60\picodriveS60.ini",FN
".\install.txt"-"!:\system\apps\PicodriveS60\install.txt",FILETEXT
; Required files
; None
; Component .sis files
; None

View file

@ -0,0 +1,26 @@
;
; Basic install file for picodriveS60
;
; Languages
; none - English only by default
; Installation header
; Only one component name as we only support English
; UID is the app's UID
#{"PicoDriveS60 2nd Edition "},( 0x101F9B49 ),0,60,0
(0x101F6F88), 0, 0, 0, {"Series60ProductID"}
; Application file
"\epoc32\release\armi\urel\picodriveS60.app"-"!:\system\apps\picodriveS60\picodriveS60.app"
"\epoc32\release\armi\urel\picodrive.exe"-"!:\system\apps\picodriveS60\picodrive.exe"
"\epoc32\data\z\system\apps\picodrives60\picodriveS60.rsc"-"!:\system\apps\picodriveS60\picodriveS60.rsc"
"\epoc32\data\z\system\apps\picodrives60\picodriveS60.aif"-"!:\system\apps\picodriveS60\picodriveS60.aif"
""-"c:\system\apps\picodriveS60\picodriveS60.ini",FN
".\install.txt"-"!:\system\apps\PicodriveS60\install.txt",FILETEXT
; Required files
; None
; Component .sis files
; None

View file

@ -0,0 +1,35 @@
;
; Basic install file for picodriveS60
;
; Languages
;Language - standard language definitions
&EN
; List of localised vendor names - one per language. At least one must be provided (English [EN]).
; List must correspond to list of languages specified elsewhere in the .pkg
%{"PicoDrive"}
; The non-localised, globally unique vendor name (mandatory)
:"PicoDrive"
; Installation header
; Only one component name as we only support English
; UID is the app's UID
#{"PicoDriveS60 3rd Edition "},( 0xA00007BE ),0,50,0
;Supports Series 60 v 3.0
[0x101F7961], 0, 0, 0, {"Series60ProductID"}
; Application file
"\epoc32\release\gcce\urel\picodrive.exe"-"!:\sys\bin\picodrive.exe"
"\epoc32\data\z\resource\apps\picodrive.rsc"-"!:\resource\apps\picodrive.rsc"
"\epoc32\data\z\resource\apps\picodrive.mbm"-"!:\resource\apps\picodrive.mbm"
"\epoc32\data\z\resource\apps\picodrive_loc.rsc"-"!:\resource\apps\picodrive_loc.rsc"
"\epoc32\data\z\private\10003a3f\apps\picodrive_reg.rsc"-"!:\private\10003a3f\import\apps\picodrive_reg.rsc"
""-"c:\private\A00007BE\picodriveS60.ini",FN
".\install.txt"-"!:\resource\apps\picodrive_install.txt",FILETEXT
; Required files
; None
; Component .sis files
; None

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,854 @@
PATH=\S60V3\epoc32\tools\;C:\Program\CSL Arm Toolchain\arm-none-symbianelf\bin;C:\Program\CSL Arm Toolchain\bin;\uiq3\epoc32\tools\;\S60V3\epoc32\tools\;\S60V3\epoc32\gcc\bin\;C:\winnt\system32;C:\winnt;C:\winnt\System32\Wbem;C:\Program Files\ATI Technologies\ATI Control Panel;C:\Program Files\Common Files\Adaptec Shared\System;C:\Perl\bin;\uiq3\epoc32\tools;c:\MSVC6\VC98\Bin;e:\UIQ3\epoc32\tools\nokia_compiler\Symbian_Tools\Command_Line_Tools;C:\Program Files\CSL Arm Toolchain\arm-none-symbianelf\bin;C:\Program Files\CSL Arm Toolchain\bin
Path=$(PATH)
COMPILER_PATH="\S60V3\epoc32\tools\nokia_compiler\Symbian_Tools\Command_Line_Tools\"
# CWD \picodrive\s60\
# MMPFile \picodrive\s60\picodrives60v3.MMP
# Target PicoDrive.exe
# TargetType EXE
# BasicTargetType EXE
# MakefileType GNU
ERASE = @erase 2>>nul
# EPOC DEFINITIONS
EPOCBLD = \S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW
EPOCTRG = \S60V3\EPOC32\RELEASE\WINSCW
EPOCLIB = \S60V3\EPOC32\RELEASE\WINSCW
EPOCLINK = \S60V3\EPOC32\RELEASE\WINSCW
EPOCSTATLINK = \S60V3\EPOC32\RELEASE\WINSCW
EPOCASSPLINK = \S60V3\EPOC32\RELEASE\WINSCW
EPOCDATA = \S60V3\EPOC32\DATA
EPOCINC = \S60V3\EPOC32\INCLUDE
TRGDIR = Z\sys\bin
DATADIR = Z\System\Data
EPOCBLDUDEB = $(EPOCBLD)\UDEB
EPOCTRGUDEB = $(EPOCTRG)\UDEB
EPOCLIBUDEB = $(EPOCLIB)\UDEB
EPOCLINKUDEB = $(EPOCLINK)\UDEB
EPOCSTATLINKUDEB = $(EPOCSTATLINK)\UDEB
EPOCASSPLINKUDEB = $(EPOCASSPLINK)\UDEB
EPOCBLDUREL = $(EPOCBLD)\UREL
EPOCTRGUREL = $(EPOCTRG)\UREL
EPOCLIBUREL = $(EPOCLIB)\UDEB
EPOCLINKUREL = $(EPOCLINK)\UDEB
EPOCSTATLINKUREL = $(EPOCSTATLINK)\UREL
EPOCASSPLINKUREL = $(EPOCASSPLINK)\UDEB
# EPOC PSEUDOTARGETS
UDEB : MAKEWORKUDEB RESOURCEUDEB
UREL : MAKEWORKUREL RESOURCEUREL
ALL : UDEB UREL
CLEAN CLEANALL : CLEANBUILD CLEANRELEASE CLEANLIBRARY
WHAT WHATALL : WHATUDEB WHATUREL
RESOURCE RESOURCEALL : RESOURCEUDEB RESOURCEUREL
CLEANBUILD CLEANBUILDALL : CLEANBUILDUDEB CLEANBUILDUREL
CLEANRELEASE CLEANRELEASEALL : CLEANRELEASEUDEB CLEANRELEASEUREL
MAKEWORK MAKEWORKALL : MAKEWORKUDEB MAKEWORKUREL
LISTING LISTINGALL : LISTINGUDEB LISTINGUREL
MAKEWORK : MAKEWORKLIBRARY
RESOURCEUDEB RESOURCEUREL : GENERIC_RESOURCE
MWCIncludes:=$(MWCSym2Includes)
export MWCIncludes
MWLibraries:=+\S60V3\epoc32\tools\nokia_compiler\Symbian_Support\Runtime\Runtime_x86\Runtime_Win32\Libs;\S60V3\epoc32\tools\nokia_compiler\Symbian_Support\Win32-x86 Support\Libraries\Win32 SDK
export MWLibraries
MWLibraryFiles:=gdi32.lib;user32.lib;kernel32.lib;
export MWLibraryFiles
# EPOC DEFINITIONS
INCDIR = -cwd source -i- \
-i "\picodrive\pico" \
-i "\picodrive\pico\sound" \
-i "\picodrive\s60" \
-i "\picodrive" \
-i "\S60V3\EPOC32\include" \
-i "\S60V3\EPOC32\include\libc" \
-i "\S60V3\EPOC32\include\mmf\plugin" \
-i "\S60V3\epoc32\include\variant"\
-i "\S60V3\epoc32\include\variant\ " -include "Symbian_OS_v9.1.hrh"
CWFLAGS = -wchar_t off -align 4 -warnings on -w nohidevirtual,nounusedexpr -enum int -str pool -exc ms -nostdinc
CWDEFS = -d "__SYMBIAN32__" -d "__CW32__" -d "__WINS__" -d "__WINSCW__" -d "__EXE__" -d "S60V3" -d "__SUPPORT_CPP_EXCEPTIONS__" $(USERDEFS)
CWUDEB = perl -S err_formatter.pl $(COMPILER_PATH)mwccsym2.exe -msgstyle parseable -sym codeview -inline off $(CWFLAGS) -d _DEBUG -d _UNICODE $(CWDEFS) $(INCDIR)
CWUREL = perl -S err_formatter.pl $(COMPILER_PATH)mwccsym2.exe -msgstyle parseable -O4,s $(CWFLAGS) -d NDEBUG -d _UNICODE $(CWDEFS) $(INCDIR)
UDEB : \
$(EPOCTRGUDEB)\PicoDrive.exe
UREL : \
$(EPOCTRGUREL)\PicoDrive.exe
RESOURCEUDEB : MAKEWORKUDEB \
$(EPOCTRGUDEB)\Z\Resource\Apps\PicoDrive.mbm \
$(EPOCTRGUDEB)\Z\private\10003a3f\apps\PicoDrive_reg.RSC \
$(EPOCTRGUDEB)\Z\Resource\Apps\PicoDrive_loc.RSC \
$(EPOCTRGUDEB)\Z\Resource\Apps\PicoDrive.RSC
RESOURCEUREL : MAKEWORKUREL \
$(EPOCTRGUREL)\Z\Resource\Apps\PicoDrive.mbm \
$(EPOCTRGUREL)\Z\private\10003a3f\apps\PicoDrive_reg.RSC \
$(EPOCTRGUREL)\Z\Resource\Apps\PicoDrive_loc.RSC \
$(EPOCTRGUREL)\Z\Resource\Apps\PicoDrive.RSC
# REAL TARGET - LIBRARY
LIBRARY : MAKEWORKLIBRARY
FREEZE :
CLEANLIBRARY :
GENERIC_RESOURCE : GENERIC_MAKEWORK
# REAL TARGET - BUILD VARIANT UDEB
WHATUDEB : WHATGENERIC
CLEANUDEB : CLEANBUILDUDEB CLEANRELEASEUDEB
CLEANBUILDUDEB :
@perl -S ermdir.pl "$(EPOCBLDUDEB)"
CLEANRELEASEUDEB : CLEANGENERIC
UDEB_RELEASEABLES1= \
$(EPOCTRGUDEB)\PicoDrive.exe \
$(EPOCTRGUDEB)\Z\Resource\Apps\PicoDrive.RSC \
$(EPOCTRGUDEB)\Z\Resource\Apps\PicoDrive.mbm \
$(EPOCTRGUDEB)\Z\Resource\Apps\PicoDrive_loc.RSC \
$(EPOCTRGUDEB)\Z\private\10003a3f\apps\PicoDrive_reg.RSC
WHATUDEB:
@echo $(UDEB_RELEASEABLES1)
CLEANRELEASEUDEB:
-$(ERASE) $(UDEB_RELEASEABLES1)
LISTINGUDEB : MAKEWORKUDEB \
LISTINGUDEBpicodriveexe \
LISTINGUDEBunzip \
LISTINGUDEBPicoDrive_UID_
LIBSUDEB= \
$(EPOCSTATLINKUDEB)\pico.lib \
$(EPOCSTATLINKUDEB)\a68k.obj \
$(EPOCSTATLINKUDEB)\mz80_asm.obj \
$(EPOCSTATLINKUDEB)\zlib.lib \
$(EPOCLINKUDEB)\cone.lib \
$(EPOCLINKUDEB)\EIKCORE.lib \
$(EPOCLINKUDEB)\MEDIACLIENTAUDIOSTREAM.LIB \
$(EPOCLINKUDEB)\euser.lib \
$(EPOCLINKUDEB)\apparc.lib \
$(EPOCLINKUDEB)\efsrv.lib \
$(EPOCLINKUDEB)\estlib.lib \
$(EPOCLINKUDEB)\fbscli.lib \
$(EPOCLINKUDEB)\estor.lib \
$(EPOCLINKUDEB)\eikcoctl.lib \
$(EPOCLINKUDEB)\ws32.lib \
$(EPOCLINKUDEB)\AVKON.LIB \
$(EPOCLINKUDEB)\bafl.lib \
$(EPOCLINKUDEB)\bitgdi.lib \
$(EPOCLINKUDEB)\gdi.lib \
$(EPOCLINKUDEB)\eikdlg.lib
LINK_OBJSUDEB= \
$(EPOCBLDUDEB)\picodriveexe.o \
$(EPOCBLDUDEB)\unzip.o \
$(EPOCBLDUDEB)\PicoDrive_UID_.o
COMMON_LINK_FLAGSUDEB= -stdlib "$(EPOCSTATLINKUDEB)\EEXE.LIB" -m\
"?_E32Bootstrap@@YGXXZ" -subsystem windows -heapreserve=8000 -heapcommit=256\
-sym codeview -lMSL_All_MSE_Symbian_D.lib
LINK_FLAGSUDEB= $(COMMON_LINK_FLAGSUDEB) $(LIBSUDEB) \
-o "$(EPOCTRGUDEB)\PicoDrive.exe" -noimplib
$(EPOCTRGUDEB)\PicoDrive.exe : $(LINK_OBJSUDEB) $(EPOCSTATLINKUDEB)\EEXE.LIB $(LIBSUDEB)
$(COMPILER_PATH)mwldsym2.exe -msgstyle gcc $(LINK_FLAGSUDEB) -l $(EPOCBLDUDEB) -search $(notdir $(LINK_OBJSUDEB))
# REAL TARGET - BUILD VARIANT UREL
WHATUREL : WHATGENERIC
CLEANUREL : CLEANBUILDUREL CLEANRELEASEUREL
CLEANBUILDUREL :
@perl -S ermdir.pl "$(EPOCBLDUREL)"
CLEANRELEASEUREL : CLEANGENERIC
UREL_RELEASEABLES1= \
$(EPOCTRGUREL)\PicoDrive.exe \
$(EPOCTRGUREL)\PicoDrive.exe.map \
$(EPOCTRGUREL)\Z\Resource\Apps\PicoDrive.RSC \
$(EPOCTRGUREL)\Z\Resource\Apps\PicoDrive.mbm \
$(EPOCTRGUREL)\Z\Resource\Apps\PicoDrive_loc.RSC \
$(EPOCTRGUREL)\Z\private\10003a3f\apps\PicoDrive_reg.RSC
WHATUREL:
@echo $(UREL_RELEASEABLES1)
CLEANRELEASEUREL:
-$(ERASE) $(UREL_RELEASEABLES1)
LISTINGUREL : MAKEWORKUREL \
LISTINGURELpicodriveexe \
LISTINGURELunzip \
LISTINGURELPicoDrive_UID_
LIBSUREL= \
$(EPOCSTATLINKUREL)\pico.lib \
$(EPOCSTATLINKUREL)\a68k.obj \
$(EPOCSTATLINKUREL)\mz80_asm.obj \
$(EPOCSTATLINKUREL)\zlib.lib \
$(EPOCLINKUREL)\cone.lib \
$(EPOCLINKUREL)\EIKCORE.lib \
$(EPOCLINKUREL)\MEDIACLIENTAUDIOSTREAM.LIB \
$(EPOCLINKUREL)\euser.lib \
$(EPOCLINKUREL)\apparc.lib \
$(EPOCLINKUREL)\efsrv.lib \
$(EPOCLINKUREL)\estlib.lib \
$(EPOCLINKUREL)\fbscli.lib \
$(EPOCLINKUREL)\estor.lib \
$(EPOCLINKUREL)\eikcoctl.lib \
$(EPOCLINKUREL)\ws32.lib \
$(EPOCLINKUREL)\AVKON.LIB \
$(EPOCLINKUREL)\bafl.lib \
$(EPOCLINKUREL)\bitgdi.lib \
$(EPOCLINKUREL)\gdi.lib \
$(EPOCLINKUREL)\eikdlg.lib
LINK_OBJSUREL= \
$(EPOCBLDUREL)\picodriveexe.o \
$(EPOCBLDUREL)\unzip.o \
$(EPOCBLDUREL)\PicoDrive_UID_.o
COMMON_LINK_FLAGSUREL= -stdlib "$(EPOCSTATLINKUREL)\EEXE.LIB" -m\
"?_E32Bootstrap@@YGXXZ" -subsystem windows -heapreserve=8000 -heapcommit=256\
-lMSL_All_MSE_Symbian.lib
LINK_FLAGSUREL= $(COMMON_LINK_FLAGSUREL) $(LIBSUREL) \
-o "$(EPOCTRGUREL)\PicoDrive.exe" -map "$(EPOCTRGUREL)\PicoDrive.exe.map" -noimplib
$(EPOCTRGUREL)\PicoDrive.exe : $(LINK_OBJSUREL) $(EPOCSTATLINKUREL)\EEXE.LIB $(LIBSUREL)
$(COMPILER_PATH)mwldsym2.exe -msgstyle gcc $(LINK_FLAGSUREL) -l $(EPOCBLDUREL) -search $(notdir $(LINK_OBJSUREL))
# SOURCES
# BitMap PicoDrive.mbm
GENERIC_RESOURCE : $(EPOCDATA)\Z\Resource\Apps\PicoDrive.mbm
$(EPOCDATA)\Z\Resource\Apps\PicoDrive.mbm : \
\picodrive\s60\picos.bmp \
\picodrive\s60\picosmi.bmp \
\picodrive\s60\picol.bmp \
\picodrive\s60\picolmi.bmp
perl -S epocmbm.pl -h"\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW\PicoDrive.mbg" -o"$(EPOCDATA)\Z\Resource\Apps\PicoDrive.mbm" -l"\Z\Resource\Apps\:\picodrive\s60"\
-b"\
/c24\picodrive\s60\picos.bmp\
/8\picodrive\s60\picosmi.bmp\
/c24\picodrive\s60\picol.bmp\
/8\picodrive\s60\picolmi.bmp" \
-l"\Z\Resource\Apps\:\picodrive\s60"
$(EPOCTRGUDEB)\Z\Resource\Apps\PicoDrive.mbm : $(EPOCDATA)\Z\Resource\Apps\PicoDrive.mbm
perl -S ecopyfile.pl $? $@
$(EPOCTRGUREL)\Z\Resource\Apps\PicoDrive.mbm : $(EPOCDATA)\Z\Resource\Apps\PicoDrive.mbm
perl -S ecopyfile.pl $? $@
# Resource Z\private\10003a3f\apps\PicoDrive_reg.RSC
DEPEND= \
\S60V3\EPOC32\include\AppInfo.rh \
\S60V3\epoc32\include\variant\Symbian_OS_v9.1.hrh
GENERIC_RESOURCE : $(EPOCDATA)\Z\private\10003a3f\apps\PicoDrive_reg.RSC
$(EPOCDATA)\Z\private\10003a3f\apps\PicoDrive_reg.RSC : \picodrive\S60\PicoDrive_reg.rss $(DEPEND)
perl -S epocrc.pl -m045,046,047 -I "\picodrive\S60" -I "\picodrive\pico" -I "\picodrive\pico\sound" -I "\picodrive\s60" -I "\picodrive" -I- -I "\S60V3\EPOC32\include" -I "\S60V3\EPOC32\include\libc" -I "\S60V3\EPOC32\include\mmf\plugin" -I "\S60V3\epoc32\include\variant" -DLANGUAGE_SC -u "\picodrive\S60\PicoDrive_reg.rss" -o$@ -t"\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW" -l"Z\private\10003a3f\apps:\picodrive\s60"
$(EPOCTRGUDEB)\Z\private\10003a3f\apps\PicoDrive_reg.RSC : $(EPOCDATA)\Z\private\10003a3f\apps\PicoDrive_reg.RSC
perl -S ecopyfile.pl $? $@
$(EPOCTRGUREL)\Z\private\10003a3f\apps\PicoDrive_reg.RSC : $(EPOCDATA)\Z\private\10003a3f\apps\PicoDrive_reg.RSC
perl -S ecopyfile.pl $? $@
# Resource Z\Resource\Apps\PicoDrive_loc.RSC
DEPEND= \
\S60V3\EPOC32\include\AppInfo.rh \
\S60V3\epoc32\include\variant\Symbian_OS_v9.1.hrh
GENERIC_RESOURCE : $(EPOCDATA)\Z\Resource\Apps\PicoDrive_loc.RSC
$(EPOCDATA)\Z\Resource\Apps\PicoDrive_loc.RSC : \picodrive\S60\PicoDrive_loc.rss $(DEPEND)
perl -S epocrc.pl -m045,046,047 -I "\picodrive\S60" -I "\picodrive\pico" -I "\picodrive\pico\sound" -I "\picodrive\s60" -I "\picodrive" -I- -I "\S60V3\EPOC32\include" -I "\S60V3\EPOC32\include\libc" -I "\S60V3\EPOC32\include\mmf\plugin" -I "\S60V3\epoc32\include\variant" -DLANGUAGE_SC -u "\picodrive\S60\PicoDrive_loc.rss" -o$@ -t"\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW" -l"Z\Resource\Apps:\picodrive\s60"
$(EPOCTRGUDEB)\Z\Resource\Apps\PicoDrive_loc.RSC : $(EPOCDATA)\Z\Resource\Apps\PicoDrive_loc.RSC
perl -S ecopyfile.pl $? $@
$(EPOCTRGUREL)\Z\Resource\Apps\PicoDrive_loc.RSC : $(EPOCDATA)\Z\Resource\Apps\PicoDrive_loc.RSC
perl -S ecopyfile.pl $? $@
# Resource Z\Resource\Apps\PicoDrive.RSC
DEPEND= \
\S60V3\EPOC32\include\BADEF.RH \
\S60V3\EPOC32\include\BAERRRSVR.RH \
\S60V3\EPOC32\include\aknfontcategory.hrh \
\S60V3\EPOC32\include\aknfontidoffsets.hrh \
\S60V3\EPOC32\include\avkon.hrh \
\S60V3\EPOC32\include\avkon.rh \
\S60V3\EPOC32\include\avkon.rsg \
\S60V3\EPOC32\include\eikcdlg.rsg \
\S60V3\EPOC32\include\eikcoctl.rsg \
\S60V3\EPOC32\include\eikcolor.hrh \
\S60V3\EPOC32\include\eikcore.rsg \
\S60V3\EPOC32\include\eikctl.rsg \
\S60V3\EPOC32\include\eikon.hrh \
\S60V3\EPOC32\include\eikon.rh \
\S60V3\EPOC32\include\eikon.rsg \
\S60V3\EPOC32\include\gulftflg.hrh \
\S60V3\EPOC32\include\lafpublc.hrh \
\S60V3\EPOC32\include\uikon.hrh \
\S60V3\EPOC32\include\uikon.rh \
\S60V3\epoc32\include\variant\Symbian_OS_v9.1.hrh
GENERIC_RESOURCE : $(EPOCDATA)\Z\Resource\Apps\PicoDrive.RSC
$(EPOCDATA)\Z\Resource\Apps\PicoDrive.RSC : \picodrive\s60\PicoDrive.rss $(DEPEND)
perl -S epocrc.pl -m045,046,047 -I "\picodrive\s60" -I "\picodrive\pico" -I "\picodrive\pico\sound" -I "\picodrive\s60" -I "\picodrive" -I- -I "\S60V3\EPOC32\include" -I "\S60V3\EPOC32\include\libc" -I "\S60V3\EPOC32\include\mmf\plugin" -I "\S60V3\epoc32\include\variant" -DLANGUAGE_SC -u "\picodrive\s60\PicoDrive.rss" -o$@ -h"\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW\PicoDrive.rsg" -t"\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW" -l"Z\Resource\Apps:\picodrive\s60"
perl -S ecopyfile.pl "\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW\PicoDrive.rsg" "\S60V3\EPOC32\INCLUDE\PicoDrive.RSG"
$(EPOCTRGUDEB)\Z\Resource\Apps\PicoDrive.RSC : $(EPOCDATA)\Z\Resource\Apps\PicoDrive.RSC
perl -S ecopyfile.pl $? $@
$(EPOCTRGUREL)\Z\Resource\Apps\PicoDrive.RSC : $(EPOCDATA)\Z\Resource\Apps\PicoDrive.RSC
perl -S ecopyfile.pl $? $@
# Source picodriveexe.cpp
$(EPOCBLDUDEB)\picodriveexe.o \
$(EPOCBLDUREL)\picodriveexe.o \
: \
\S60V3\EPOC32\include\AknControl.h \
\S60V3\EPOC32\include\AknMfneCommandObserver.h \
\S60V3\EPOC32\include\AknPictographDrawerInterface.h \
\S60V3\EPOC32\include\AknTouchPaneObserver.h \
\S60V3\EPOC32\include\AknsConstants.h \
\S60V3\EPOC32\include\AknsConstants.hrh \
\S60V3\EPOC32\include\AknsItemID.h \
\S60V3\EPOC32\include\AknsItemID.inl \
\S60V3\EPOC32\include\E32Base.h \
\S60V3\EPOC32\include\Ecom\EComErrorCodes.h \
\S60V3\EPOC32\include\Ecom\EComResolverParams.h \
\S60V3\EPOC32\include\Ecom\EComResolverParams.inl \
\S60V3\EPOC32\include\Ecom\Ecom.h \
\S60V3\EPOC32\include\Ecom\ImplementationInformation.h \
\S60V3\EPOC32\include\Ecom\ImplementationInformation.inl \
\S60V3\EPOC32\include\Eikspane.h \
\S60V3\EPOC32\include\F32File.h \
\S60V3\EPOC32\include\LineBreak.h \
\S60V3\EPOC32\include\MdaAudioOutputStream.h \
\S60V3\EPOC32\include\Mda\Common\Audio.h \
\S60V3\EPOC32\include\Mda\Common\Audio.hrh \
\S60V3\EPOC32\include\Mda\Common\AudioStream.hrh \
\S60V3\EPOC32\include\Mda\Common\Base.h \
\S60V3\EPOC32\include\Mda\Common\Base.h \
\S60V3\EPOC32\include\Mda\Common\Base.hrh \
\S60V3\EPOC32\include\Mda\Common\Base.inl \
\S60V3\EPOC32\include\Mda\Common\Controller.h \
\S60V3\EPOC32\include\Mda\Common\Port.h \
\S60V3\EPOC32\include\Mda\Common\Port.hrh \
\S60V3\EPOC32\include\Mda\Common\Resource.h \
\S60V3\EPOC32\include\Mda\Common\Resource.hrh \
\S60V3\EPOC32\include\MetaContainer.h \
\S60V3\EPOC32\include\MetaContainer.inl \
\S60V3\EPOC32\include\MetaData.h \
\S60V3\EPOC32\include\Metadata.inl \
\S60V3\EPOC32\include\Mmf\Common\MmfBase.h \
\S60V3\EPOC32\include\Mmf\Common\MmfUtilities.h \
\S60V3\EPOC32\include\Mmfclntutility.h \
\S60V3\EPOC32\include\aknDialog.h \
\S60V3\EPOC32\include\aknPanic.h \
\S60V3\EPOC32\include\aknapp.h \
\S60V3\EPOC32\include\aknappUI.h \
\S60V3\EPOC32\include\aknappui.h \
\S60V3\EPOC32\include\akncontrol.h \
\S60V3\EPOC32\include\akndef.h \
\S60V3\EPOC32\include\akndef.hrh \
\S60V3\EPOC32\include\akndoc.h \
\S60V3\EPOC32\include\aknenv.h \
\S60V3\EPOC32\include\aknfontcategory.hrh \
\S60V3\EPOC32\include\aknfontidoffsets.hrh \
\S60V3\EPOC32\include\aknform.h \
\S60V3\EPOC32\include\aknintermediate.h \
\S60V3\EPOC32\include\aknipfed.h \
\S60V3\EPOC32\include\aknlayout.lag \
\S60V3\EPOC32\include\aknlayout2id.h \
\S60V3\EPOC32\include\aknlistquerycontrol.h \
\S60V3\EPOC32\include\aknlistquerydialog.h \
\S60V3\EPOC32\include\aknmultilinequerycontrol.h \
\S60V3\EPOC32\include\aknnumed.h \
\S60V3\EPOC32\include\aknnumedwin.h \
\S60V3\EPOC32\include\aknnumseced.h \
\S60V3\EPOC32\include\aknpopup.h \
\S60V3\EPOC32\include\aknpopupfader.h \
\S60V3\EPOC32\include\aknpopupheadingpane.h \
\S60V3\EPOC32\include\aknpopuplayout.h \
\S60V3\EPOC32\include\aknquerycontrol.h \
\S60V3\EPOC32\include\aknquerydata.h \
\S60V3\EPOC32\include\aknquerydialog.h \
\S60V3\EPOC32\include\aknscbut.h \
\S60V3\EPOC32\include\aknscrlb.h \
\S60V3\EPOC32\include\aknutils.h \
\S60V3\EPOC32\include\apacmdln.h \
\S60V3\EPOC32\include\apadef.h \
\S60V3\EPOC32\include\apaflrec.h \
\S60V3\EPOC32\include\apaid.h \
\S60V3\EPOC32\include\apgtask.h \
\S60V3\EPOC32\include\apmstd.h \
\S60V3\EPOC32\include\apparc.h \
\S60V3\EPOC32\include\avkon.hrh \
\S60V3\EPOC32\include\avkon.rsg \
\S60V3\EPOC32\include\babitflags.h \
\S60V3\EPOC32\include\badesca.h \
\S60V3\EPOC32\include\baerrhan.h \
\S60V3\EPOC32\include\bamdesca.h \
\S60V3\EPOC32\include\barsc.h \
\S60V3\EPOC32\include\basched.h \
\S60V3\EPOC32\include\bidi.h \
\S60V3\EPOC32\include\biditext.h \
\S60V3\EPOC32\include\bitbase.h \
\S60V3\EPOC32\include\bitdev.h \
\S60V3\EPOC32\include\bitdev.inl \
\S60V3\EPOC32\include\bitmap.h \
\S60V3\EPOC32\include\bitstd.h \
\S60V3\EPOC32\include\caf\agent.h \
\S60V3\EPOC32\include\caf\attribute.h \
\S60V3\EPOC32\include\caf\attributeset.h \
\S60V3\EPOC32\include\caf\caf.h \
\S60V3\EPOC32\include\caf\caferr.h \
\S60V3\EPOC32\include\caf\cafmimeheader.h \
\S60V3\EPOC32\include\caf\cafpanic.h \
\S60V3\EPOC32\include\caf\caftypes.h \
\S60V3\EPOC32\include\caf\caftypes.h \
\S60V3\EPOC32\include\caf\content.h \
\S60V3\EPOC32\include\caf\data.h \
\S60V3\EPOC32\include\caf\dirstreamable.h \
\S60V3\EPOC32\include\caf\embeddedobject.h \
\S60V3\EPOC32\include\caf\importfile.h \
\S60V3\EPOC32\include\caf\manager.h \
\S60V3\EPOC32\include\caf\metadata.h \
\S60V3\EPOC32\include\caf\metadataarray.h \
\S60V3\EPOC32\include\caf\rightsinfo.h \
\S60V3\EPOC32\include\caf\rightsmanager.h \
\S60V3\EPOC32\include\caf\streamableptrarray.h \
\S60V3\EPOC32\include\caf\streamableptrarray.inl \
\S60V3\EPOC32\include\caf\stringattributeset.h \
\S60V3\EPOC32\include\caf\supplier.h \
\S60V3\EPOC32\include\caf\supplieroutputfile.h \
\S60V3\EPOC32\include\caf\virtualpath.h \
\S60V3\EPOC32\include\caf\virtualpathptr.h \
\S60V3\EPOC32\include\coeaui.h \
\S60V3\EPOC32\include\coeccntx.h \
\S60V3\EPOC32\include\coecntrl.h \
\S60V3\EPOC32\include\coecobs.h \
\S60V3\EPOC32\include\coecontrolarray.h \
\S60V3\EPOC32\include\coedef.h \
\S60V3\EPOC32\include\coehelp.h \
\S60V3\EPOC32\include\coeinput.h \
\S60V3\EPOC32\include\coemain.h \
\S60V3\EPOC32\include\coemop.h \
\S60V3\EPOC32\include\coetextdrawer.h \
\S60V3\EPOC32\include\coeview.h \
\S60V3\EPOC32\include\d32locd.h \
\S60V3\EPOC32\include\d32locd.inl \
\S60V3\EPOC32\include\e32base.h \
\S60V3\EPOC32\include\e32base.inl \
\S60V3\EPOC32\include\e32capability.h \
\S60V3\EPOC32\include\e32cmn.h \
\S60V3\EPOC32\include\e32cmn.inl \
\S60V3\EPOC32\include\e32const.h \
\S60V3\EPOC32\include\e32debug.h \
\S60V3\EPOC32\include\e32def.h \
\S60V3\EPOC32\include\e32des16.h \
\S60V3\EPOC32\include\e32des8.h \
\S60V3\EPOC32\include\e32err.h \
\S60V3\EPOC32\include\e32event.h \
\S60V3\EPOC32\include\e32hal.h \
\S60V3\EPOC32\include\e32keys.h \
\S60V3\EPOC32\include\e32ktran.h \
\S60V3\EPOC32\include\e32ldr.h \
\S60V3\EPOC32\include\e32lmsg.h \
\S60V3\EPOC32\include\e32notif.h \
\S60V3\EPOC32\include\e32std.h \
\S60V3\EPOC32\include\e32std.inl \
\S60V3\EPOC32\include\e32svr.h \
\S60V3\EPOC32\include\ecom\ECom.h \
\S60V3\EPOC32\include\ecom\ecom.h \
\S60V3\EPOC32\include\eikalign.h \
\S60V3\EPOC32\include\eikamnt.h \
\S60V3\EPOC32\include\eikapp.h \
\S60V3\EPOC32\include\eikappui.h \
\S60V3\EPOC32\include\eikaufty.h \
\S60V3\EPOC32\include\eikbctrl.h \
\S60V3\EPOC32\include\eikbtgpc.h \
\S60V3\EPOC32\include\eikbtgrp.h \
\S60V3\EPOC32\include\eikbutb.h \
\S60V3\EPOC32\include\eikcal.h \
\S60V3\EPOC32\include\eikcba.h \
\S60V3\EPOC32\include\eikccpu.h \
\S60V3\EPOC32\include\eikcmbut.h \
\S60V3\EPOC32\include\eikcmobs.h \
\S60V3\EPOC32\include\eikcolor.hrh \
\S60V3\EPOC32\include\eikctgrp.h \
\S60V3\EPOC32\include\eikcycledef.h \
\S60V3\EPOC32\include\eikdef.h \
\S60V3\EPOC32\include\eikdgfty.h \
\S60V3\EPOC32\include\eikdialg.h \
\S60V3\EPOC32\include\eikdoc.h \
\S60V3\EPOC32\include\eikdpobs.h \
\S60V3\EPOC32\include\eikedwin.h \
\S60V3\EPOC32\include\eikedwob.h \
\S60V3\EPOC32\include\eikenv.h \
\S60V3\EPOC32\include\eikfctry.h \
\S60V3\EPOC32\include\eikfpne.h \
\S60V3\EPOC32\include\eikimage.h \
\S60V3\EPOC32\include\eiklay.h \
\S60V3\EPOC32\include\eiklbed.h \
\S60V3\EPOC32\include\eiklbm.h \
\S60V3\EPOC32\include\eiklbo.h \
\S60V3\EPOC32\include\eiklbv.h \
\S60V3\EPOC32\include\eiklbx.h \
\S60V3\EPOC32\include\eiklibry.h \
\S60V3\EPOC32\include\eikmenub.h \
\S60V3\EPOC32\include\eikmenup.h \
\S60V3\EPOC32\include\eikmfne.h \
\S60V3\EPOC32\include\eikmobs.h \
\S60V3\EPOC32\include\eikon.hrh \
\S60V3\EPOC32\include\eiksbfrm.h \
\S60V3\EPOC32\include\eiksbobs.h \
\S60V3\EPOC32\include\eikscbut.h \
\S60V3\EPOC32\include\eikscrlb.h \
\S60V3\EPOC32\include\eikseced.h \
\S60V3\EPOC32\include\eikspmod.h \
\S60V3\EPOC32\include\eiksrv.h \
\S60V3\EPOC32\include\eiksrv.pan \
\S60V3\EPOC32\include\eiksrvc.h \
\S60V3\EPOC32\include\eiksrvs.h \
\S60V3\EPOC32\include\eikstart.h \
\S60V3\EPOC32\include\eiktxlbm.h \
\S60V3\EPOC32\include\eiktxlbx.h \
\S60V3\EPOC32\include\eikunder.h \
\S60V3\EPOC32\include\eikvcurs.h \
\S60V3\EPOC32\include\es_sock.h \
\S60V3\EPOC32\include\es_sock.inl \
\S60V3\EPOC32\include\f32file.h \
\S60V3\EPOC32\include\f32file.inl \
\S60V3\EPOC32\include\fbs.h \
\S60V3\EPOC32\include\fepbase.h \
\S60V3\EPOC32\include\fldbase.h \
\S60V3\EPOC32\include\fldbltin.h \
\S60V3\EPOC32\include\fldinfo.h \
\S60V3\EPOC32\include\fldset.h \
\S60V3\EPOC32\include\fntstore.h \
\S60V3\EPOC32\include\frmframe.h \
\S60V3\EPOC32\include\frmlaydt.h \
\S60V3\EPOC32\include\frmparam.h \
\S60V3\EPOC32\include\frmtlay.h \
\S60V3\EPOC32\include\frmtview.h \
\S60V3\EPOC32\include\frmvis.h \
\S60V3\EPOC32\include\gdi.h \
\S60V3\EPOC32\include\gdi.inl \
\S60V3\EPOC32\include\graphicsaccelerator.h \
\S60V3\EPOC32\include\gulalign.h \
\S60V3\EPOC32\include\gulbordr.h \
\S60V3\EPOC32\include\gulcolor.h \
\S60V3\EPOC32\include\guldef.h \
\S60V3\EPOC32\include\gulftflg.hrh \
\S60V3\EPOC32\include\gulicon.h \
\S60V3\EPOC32\include\gulutil.h \
\S60V3\EPOC32\include\in_sock.h \
\S60V3\EPOC32\include\lafmain.h \
\S60V3\EPOC32\include\lafpublc.h \
\S60V3\EPOC32\include\lafpublc.hrh \
\S60V3\EPOC32\include\libc\_ansi.h \
\S60V3\EPOC32\include\libc\ctype.h \
\S60V3\EPOC32\include\libc\machine\types.h \
\S60V3\EPOC32\include\libc\stdarg_e.h \
\S60V3\EPOC32\include\libc\stddef.h \
\S60V3\EPOC32\include\libc\stdio.h \
\S60V3\EPOC32\include\libc\stdlib.h \
\S60V3\EPOC32\include\libc\string.h \
\S60V3\EPOC32\include\libc\sys\reent.h \
\S60V3\EPOC32\include\libc\sys\stdio_t.h \
\S60V3\EPOC32\include\libc\sys\time.h \
\S60V3\EPOC32\include\libc\time.h \
\S60V3\EPOC32\include\mda\client\utility.h \
\S60V3\EPOC32\include\mda\common\base.h \
\S60V3\EPOC32\include\medobsrv.h \
\S60V3\EPOC32\include\mm\mmcaf.h \
\S60V3\EPOC32\include\mmf\common\MmfFourCC.h \
\S60V3\EPOC32\include\mmf\common\MmfIpc.inl \
\S60V3\EPOC32\include\mmf\common\MmfUtilities.h \
\S60V3\EPOC32\include\mmf\common\MmfUtilities.inl \
\S60V3\EPOC32\include\mmf\common\Mmfbase.h \
\S60V3\EPOC32\include\mmf\common\mmcaf.h \
\S60V3\EPOC32\include\mmf\common\mmfaudio.h \
\S60V3\EPOC32\include\mmf\common\mmfbase.h \
\S60V3\EPOC32\include\mmf\common\mmfcontroller.h \
\S60V3\EPOC32\include\mmf\common\mmfcontrollerframework.h \
\S60V3\EPOC32\include\mmf\common\mmfcontrollerframeworkbase.h \
\S60V3\EPOC32\include\mmf\common\mmfcontrollerpluginresolver.h \
\S60V3\EPOC32\include\mmf\common\mmfipc.h \
\S60V3\EPOC32\include\mmf\common\mmfstandardcustomcommands.h \
\S60V3\EPOC32\include\mmf\common\mmfutilities.h \
\S60V3\EPOC32\include\mmf\common\mmfvideo.h \
\S60V3\EPOC32\include\mmf\plugin\mmfPluginInterfaceUIDs.hrh \
\S60V3\EPOC32\include\mmf\server\mmfbuffer.h \
\S60V3\EPOC32\include\mmf\server\mmfbuffer.hrh \
\S60V3\EPOC32\include\mmf\server\mmfdatabuffer.h \
\S60V3\EPOC32\include\mmf\server\mmfdatasink.h \
\S60V3\EPOC32\include\mmf\server\mmfdatasource.h \
\S60V3\EPOC32\include\mmf\server\mmfdatasourcesink.hrh \
\S60V3\EPOC32\include\nifvar.h \
\S60V3\EPOC32\include\openfont.h \
\S60V3\EPOC32\include\partitions.h \
\S60V3\EPOC32\include\picodrive.rsg \
\S60V3\EPOC32\include\s32buf.h \
\S60V3\EPOC32\include\s32buf.inl \
\S60V3\EPOC32\include\s32file.h \
\S60V3\EPOC32\include\s32file.inl \
\S60V3\EPOC32\include\s32mem.h \
\S60V3\EPOC32\include\s32mem.inl \
\S60V3\EPOC32\include\s32page.h \
\S60V3\EPOC32\include\s32page.inl \
\S60V3\EPOC32\include\s32share.h \
\S60V3\EPOC32\include\s32share.inl \
\S60V3\EPOC32\include\s32std.h \
\S60V3\EPOC32\include\s32std.inl \
\S60V3\EPOC32\include\s32stor.h \
\S60V3\EPOC32\include\s32stor.inl \
\S60V3\EPOC32\include\s32strm.h \
\S60V3\EPOC32\include\s32strm.inl \
\S60V3\EPOC32\include\savenotf.h \
\S60V3\EPOC32\include\tagma.h \
\S60V3\EPOC32\include\txtetext.h \
\S60V3\EPOC32\include\txtetext.inl \
\S60V3\EPOC32\include\txtfmlyr.h \
\S60V3\EPOC32\include\txtfmlyr.inl \
\S60V3\EPOC32\include\txtfmstm.h \
\S60V3\EPOC32\include\txtfrmat.h \
\S60V3\EPOC32\include\txtfrmat.inl \
\S60V3\EPOC32\include\txtstyle.h \
\S60V3\EPOC32\include\txtstyle.inl \
\S60V3\EPOC32\include\uikon.hrh \
\S60V3\EPOC32\include\vwsappst.h \
\S60V3\EPOC32\include\vwsdef.h \
\S60V3\EPOC32\include\w32std.h \
\S60V3\epoc32\include\variant\Symbian_OS_v9.1.hrh \
\picodrive\pico\GGenie.h \
\picodrive\pico\Pico.h \
\picodrive\pico\PicoInt.h \
\picodrive\pico\pico.h \
\picodrive\s60\PicoDriveexe.h \
\picodrive\s60\S60V3Video.inl \
\picodrive\unzip.h
$(EPOCBLDUDEB)\picodriveexe.o : \picodrive\S60\picodriveexe.cpp
echo picodriveexe.cpp
$(CWUDEB) -o "$@" -c "\picodrive\S60\picodriveexe.cpp"
LISTINGUDEBpicodriveexe : $(EPOCBLDUDEB)\picodriveexe.lis
perl -S ecopyfile.pl $? \picodrive\S60\picodriveexe.WINSCW.lst
$(EPOCBLDUREL)\picodriveexe.o : \picodrive\S60\picodriveexe.cpp
echo picodriveexe.cpp
$(CWUREL) -o "$@" -c "\picodrive\S60\picodriveexe.cpp"
LISTINGURELpicodriveexe : $(EPOCBLDUREL)\picodriveexe.lis
perl -S ecopyfile.pl $? \picodrive\S60\picodriveexe.WINSCW.lst
# Source unzip.c
$(EPOCBLDUDEB)\unzip.o \
$(EPOCBLDUREL)\unzip.o \
: \
\S60V3\EPOC32\include\libc\_ansi.h \
\S60V3\EPOC32\include\libc\assert.h \
\S60V3\EPOC32\include\libc\ctype.h \
\S60V3\EPOC32\include\libc\machine\types.h \
\S60V3\EPOC32\include\libc\stdarg_e.h \
\S60V3\EPOC32\include\libc\stddef.h \
\S60V3\EPOC32\include\libc\stdio.h \
\S60V3\EPOC32\include\libc\stdlib.h \
\S60V3\EPOC32\include\libc\string.h \
\S60V3\EPOC32\include\libc\sys\reent.h \
\S60V3\EPOC32\include\libc\sys\stdio_t.h \
\S60V3\EPOC32\include\libc\time.h \
\S60V3\EPOC32\include\zconf.h \
\S60V3\epoc32\include\variant\Symbian_OS_v9.1.hrh \
\picodrive\unzip.h \
\picodrive\zlib\zlib.h
$(EPOCBLDUDEB)\unzip.o : \picodrive\unzip.c
echo unzip.c
$(CWUDEB) -o "$@" -c "\picodrive\unzip.c"
LISTINGUDEBunzip : $(EPOCBLDUDEB)\unzip.lis
perl -S ecopyfile.pl $? \picodrive\unzip.WINSCW.lst
$(EPOCBLDUREL)\unzip.o : \picodrive\unzip.c
echo unzip.c
$(CWUREL) -o "$@" -c "\picodrive\unzip.c"
LISTINGURELunzip : $(EPOCBLDUREL)\unzip.lis
perl -S ecopyfile.pl $? \picodrive\unzip.WINSCW.lst
# Source PicoDrive.UID.CPP
$(EPOCBLDUDEB)\PicoDrive_UID_.o \
$(EPOCBLDUREL)\PicoDrive_UID_.o \
: \
\S60V3\EPOC32\include\e32capability.h \
\S60V3\EPOC32\include\e32cmn.h \
\S60V3\EPOC32\include\e32cmn.inl \
\S60V3\EPOC32\include\e32const.h \
\S60V3\EPOC32\include\e32def.h \
\S60V3\EPOC32\include\e32des16.h \
\S60V3\EPOC32\include\e32des8.h \
\S60V3\EPOC32\include\e32err.h \
\S60V3\epoc32\include\variant\Symbian_OS_v9.1.hrh
$(EPOCBLDUDEB)\PicoDrive_UID_.o : \picodrive\s60\PicoDrive.UID.CPP
echo PicoDrive.UID.CPP
$(CWUDEB) -o "$@" -c "\picodrive\s60\PicoDrive.UID.CPP"
LISTINGUDEBPicoDrive_UID_ : $(EPOCBLDUDEB)\PicoDrive_UID_.lis
perl -S ecopyfile.pl $? \picodrive\s60\PicoDrive_UID_.WINSCW.lst
$(EPOCBLDUREL)\PicoDrive_UID_.o : \picodrive\s60\PicoDrive.UID.CPP
echo PicoDrive.UID.CPP
$(CWUREL) -o "$@" -c "\picodrive\s60\PicoDrive.UID.CPP"
LISTINGURELPicoDrive_UID_ : $(EPOCBLDUREL)\PicoDrive_UID_.lis
perl -S ecopyfile.pl $? \picodrive\s60\PicoDrive_UID_.WINSCW.lst
ROMFILE:
# Implicit rule for generating .lis files
.SUFFIXES : .lis .o
.o.lis:
$(COMPILER_PATH)mwldsym2.exe -msgstyle gcc -S -show source,unmangled,comments $< -o $@
GENERIC_RELEASEABLES1= \
$(EPOCDATA)\Z\Resource\Apps\PicoDrive.RSC \
$(EPOCDATA)\Z\Resource\Apps\PicoDrive.mbm \
$(EPOCDATA)\Z\Resource\Apps\PicoDrive_loc.RSC \
$(EPOCDATA)\Z\private\10003a3f\apps\PicoDrive_reg.RSC \
$(EPOCINC)\PicoDrive.RSG \
\S60V3\EPOC32\LOCALISATION\GROUP\PICODRIVE.INFO \
\S60V3\EPOC32\LOCALISATION\GROUP\PICODRIVE_LOC.INFO \
\S60V3\EPOC32\LOCALISATION\GROUP\PICODRIVE_REG.INFO \
\S60V3\EPOC32\LOCALISATION\PICODRIVE_LOC\RSC\PICODRIVE_LOC.RPP \
\S60V3\EPOC32\LOCALISATION\PICODRIVE_REG\RSC\PICODRIVE_REG.RPP \
\S60V3\EPOC32\LOCALISATION\\MBM\PICOL.BMP \
\S60V3\EPOC32\LOCALISATION\\MBM\PICOLMI.BMP \
\S60V3\EPOC32\LOCALISATION\\MBM\PICOS.BMP \
\S60V3\EPOC32\LOCALISATION\\MBM\PICOSMI.BMP \
\S60V3\EPOC32\LOCALISATION\\RSC\PICODRIVE.RPP
WHATGENERIC:
@echo $(GENERIC_RELEASEABLES1)
CLEANGENERIC:
-$(ERASE) $(GENERIC_RELEASEABLES1)
# Rules to create all necessary directories
GENERIC_MAKEWORK : \
\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW \
\S60V3\EPOC32\DATA\Z\Resource\Apps \
\S60V3\EPOC32\DATA\Z\private\10003a3f\apps \
\S60V3\EPOC32\INCLUDE
MAKEWORKLIBRARY : \
\S60V3\EPOC32\RELEASE\WINSCW\UDEB
MAKEWORKUDEB : \
\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW\UDEB \
\S60V3\EPOC32\RELEASE\WINSCW\UDEB \
\S60V3\EPOC32\RELEASE\WINSCW\UDEB\Z\Resource\Apps \
\S60V3\EPOC32\RELEASE\WINSCW\UDEB\Z\private\10003a3f\apps
MAKEWORKUREL : \
\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW\UREL \
\S60V3\EPOC32\RELEASE\WINSCW\UREL \
\S60V3\EPOC32\RELEASE\WINSCW\UREL\Z\Resource\Apps \
\S60V3\EPOC32\RELEASE\WINSCW\UREL\Z\private\10003a3f\apps
\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW \
\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW\UDEB \
\S60V3\EPOC32\BUILD\picodrive\s60\picodrives60v3\WINSCW\UREL \
\S60V3\EPOC32\DATA\Z\Resource\Apps \
\S60V3\EPOC32\DATA\Z\private\10003a3f\apps \
\S60V3\EPOC32\INCLUDE \
\S60V3\EPOC32\RELEASE\WINSCW\UDEB \
\S60V3\EPOC32\RELEASE\WINSCW\UDEB\Z\Resource\Apps \
\S60V3\EPOC32\RELEASE\WINSCW\UDEB\Z\private\10003a3f\apps \
\S60V3\EPOC32\RELEASE\WINSCW\UREL \
\S60V3\EPOC32\RELEASE\WINSCW\UREL\Z\Resource\Apps \
\S60V3\EPOC32\RELEASE\WINSCW\UREL\Z\private\10003a3f\apps \
:
perl -S emkdir.pl $@

Some files were not shown because too many files have changed in this diff Show more