From ea8c405fa721a8658b1f7c51cf6238ba2bba8a17 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 22 Sep 2007 22:53:18 +0000 Subject: [PATCH] giz port, restructuring git-svn-id: file:///home/notaz/opt/svn/PicoDrive@257 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/Draw.c | 32 +- Pico/Draw.s | 85 +++- Pico/Draw2.s | 37 +- Pico/{misc.s => Misc.s} | 0 Pico/Pico.h | 4 + Pico/cd/{misc.s => Misc.s} | 0 platform/common/emu.c | 775 ++++++++++++++++++++++++++++++ platform/common/emu.h | 48 ++ platform/common/menu.c | 16 +- platform/common/menu.h | 1 + platform/gizmondo/Makefile | 26 +- platform/gizmondo/asm_utils.h | 3 + platform/gizmondo/asm_utils.s | 112 +++++ platform/gizmondo/emu.c | 518 +++++++++++++++++++- platform/gizmondo/emu.h | 34 +- platform/gizmondo/giz.c | 13 +- platform/gizmondo/main.c | 3 +- platform/gizmondo/menu.c | 35 +- platform/gizmondo/menu.h | 2 - platform/gizmondo/port_config.h | 3 + platform/gizmondo/port_config.s | 13 +- platform/gp2x/940ctl.c | 1 + platform/gp2x/Makefile | 6 +- platform/gp2x/emu.c | 821 +++----------------------------- platform/gp2x/emu.h | 35 +- platform/gp2x/main.c | 1 + platform/gp2x/menu.c | 32 +- platform/gp2x/menu.h | 2 - platform/gp2x/port_config.h | 3 + platform/gp2x/port_config.s | 13 +- 30 files changed, 1705 insertions(+), 969 deletions(-) rename Pico/{misc.s => Misc.s} (100%) rename Pico/cd/{misc.s => Misc.s} (100%) create mode 100644 platform/common/emu.c create mode 100644 platform/common/emu.h create mode 100644 platform/gizmondo/asm_utils.h create mode 100644 platform/gizmondo/asm_utils.s diff --git a/Pico/Draw.c b/Pico/Draw.c index 9d7e9bc..ff2a48c 100644 --- a/Pico/Draw.c +++ b/Pico/Draw.c @@ -8,14 +8,18 @@ #include "PicoInt.h" -#ifndef __GNUC__ -#pragma warning (disable:4706) // Disable assignment within conditional -#endif int (*PicoScan)(unsigned int num, void *data)=NULL; -unsigned short DefOutBuff[320*2]; +#if OVERRIDE_HIGHCOL +static unsigned char DefHighCol[8+320+8]; +unsigned char *HighCol=DefHighCol; +#else unsigned char HighCol[8+320+8]; +#endif +unsigned short DefOutBuff[320*2]; +void *DrawLineDest=DefOutBuff; // pointer to dest buffer where to draw this line to + static int HighCacheA[41+1]; // caches for high layers static int HighCacheB[41+1]; static int HighCacheS[80+1]; // and sprites @@ -25,7 +29,6 @@ char HighSprZ[320+8+8]; // Z-buffer for accurate sprites and shadow/hilight mode // lsb->msb: moved sprites, not all window tiles use same priority, accurate sprites (copied from PicoOpt), interlace // dirty sprites, sonic mode, have layer with all hi prio tiles (mk3), layer sh/hi already processed int rendstatus; -void *DrawLineDest=DefOutBuff; // pointer to dest buffer where to draw this line to int Scanline=0; // Scanline static int SpriteBlocks; @@ -1253,7 +1256,7 @@ static void FinalizeLine8bit(int sh) } } -void (*FinalizeLine)(int sh) = FinalizeLineBGR444; +static void (*FinalizeLine)(int sh) = FinalizeLineBGR444; // -------------------------------------------- @@ -1354,8 +1357,8 @@ PICO_INTERNAL int PicoLine(int scan) if (Pico.video.reg[1]&0x40) DrawDisplay(sh); - FinalizeLine(sh); - //if (SpriteBlocks & (1<<(scan>>3))) for (sh=0; sh < 30; sh++) DrawLineDest[sh] = 0xf; + if (FinalizeLine != NULL) + FinalizeLine(sh); Skip=PicoScan(Scanline,DrawLineDest); @@ -1365,9 +1368,12 @@ PICO_INTERNAL int PicoLine(int scan) void PicoDrawSetColorFormat(int which) { - if (which == 2) - FinalizeLine = FinalizeLine8bit; - else if (which == 1) - FinalizeLine = FinalizeLineRGB555; - else FinalizeLine = FinalizeLineBGR444; + switch (which) + { + case 2: FinalizeLine = FinalizeLine8bit; break; + case 1: FinalizeLine = FinalizeLineRGB555; break; + case 0: FinalizeLine = FinalizeLineBGR444; break; + default:FinalizeLine = NULL; break; + } } + diff --git a/Pico/Draw.s b/Pico/Draw.s index e31ba0b..d26d176 100644 --- a/Pico/Draw.s +++ b/Pico/Draw.s @@ -6,6 +6,7 @@ @ (c) Copyright 2007, Grazvydas "notaz" Ignotas @ All Rights Reserved +.include "port_config.s" .extern Pico .extern PicoOpt @@ -317,11 +318,18 @@ DrawLayer: add r8, r8, r9, lsr #8 @ tilex+=cellskip add r7, r7, r9, lsr #5 @ dx+=cellskip<<3; sub r10,r10,r9, lsl #16 @ cells-=cellskip - mvn r9, #0 @ r9=prevcode=-1 @ cache some stuff to avoid mem access +.if OVERRIDE_HIGHCOL + ldr r11,=HighCol + mov r0, #0xf + ldr r11,[r11] +.else ldr r11,=HighCol mov r0, #0xf +.endif + + mvn r9, #0 @ r9=prevcode=-1 add r1, r11, r7 @ r1=pdest @@ -463,13 +471,19 @@ DrawLayer: add r8, r8, r9, lsr #8 @ tilex+=cellskip add r7, r7, r9, lsr #5 @ dx+=cellskip<<3; add r10,r10,r9, lsl #16 @ cell+=cellskip - mvn r9, #0 @ r9=prevcode=-1 @ cache some stuff to avoid mem access +.if OVERRIDE_HIGHCOL ldr r11,=HighCol mov r0, #0xf - add r1, r11, r7 @ r1=pdest + ldr r11,[r11] +.else + ldr r11,=HighCol + mov r0, #0xf +.endif + mvn r9, #0 @ r9=prevcode=-1 + add r1, r11, r7 @ r1=pdest @ r4 & r7 are scratch in this loop .dsloop_vs_subr1: @@ -639,10 +653,18 @@ DrawLayer: BackFill: stmfd sp!, {r4-r9,lr} +.if OVERRIDE_HIGHCOL + ldr lr, =HighCol + mov r0, r0, lsl #26 + ldr lr, [lr] + mov r0, r0, lsr #26 + add lr, lr, #8 +.else ldr lr, =(HighCol+8) - mov r0, r0, lsl #26 mov r0, r0, lsr #26 +.endif + orr r0, r0, r1, lsl #6 orr r0, r0, r0, lsl #8 orr r0, r0, r0, lsl #16 @@ -680,9 +702,15 @@ DrawTilesFromCache: stmfd sp!, {r4-r8,r11,lr} @ cache some stuff to avoid mem access +.if OVERRIDE_HIGHCOL ldr r11,=HighCol - ldr lr, =(Pico+0x10000) @ lr=Pico.vram mov r12,#0xf + ldr r11,[r11] +.else + ldr r11,=HighCol + mov r12,#0xf +.endif + ldr lr, =(Pico+0x10000) @ lr=Pico.vram mvn r5, #0 @ r5=prevcode=-1 ands r8, r1, #1 @@ -874,11 +902,17 @@ DrawSpritesFromCache: stmfd sp!, {r4-r11,lr} @ cache some stuff to avoid mem access +.if OVERRIDE_HIGHCOL ldr r11,=HighCol + mov r12,#0xf + ldr r11,[r11] +.else + ldr r11,=HighCol + mov r12,#0xf +.endif ldr lr, =(Pico+0x10000) @ lr=Pico.vram mov r6, r1, lsl #31 orr r6, r6, #1<<30 - mov r12,#0xf mov r10, r0 @@ -1042,9 +1076,15 @@ DrawSprite: bne .dspr_cache @ if(code&0x8000) // high priority - cache it @ cache some stuff to avoid mem access +.if OVERRIDE_HIGHCOL + ldr r11,=HighCol + mov r12,#0xf + ldr r11,[r11] +.else ldr r11,=HighCol - ldr lr, =(Pico+0x10000) @ lr=Pico.vram mov r12,#0xf +.endif + ldr lr, =(Pico+0x10000) @ lr=Pico.vram mov r5, r5, lsl #4 @ delta<<=4; // Delta of address and r4, r9, #0x6000 @@ -1202,12 +1242,19 @@ DrawWindow: orr r6, r6, r3, lsl #8 @ shadow mode sub r8, r1, r0 - mov r8, r8, lsl #1 @ cells - - mvn r9, #0 @ r9=prevcode=-1 @ cache some stuff to avoid mem access +.if OVERRIDE_HIGHCOL + ldr r11,=HighCol + mov r8, r8, lsl #1 @ cells + ldr r11,[r11] + mvn r9, #0 @ r9=prevcode=-1 + add r11,r11,#8 +.else ldr r11,=(HighCol+8) + mov r8, r8, lsl #1 @ cells + mvn r9, #0 @ r9=prevcode=-1 +.endif add r1, r11, r0, lsl #4 @ r1=pdest mov r0, #0xf b .dwloop_enter @@ -1408,9 +1455,17 @@ FinalizeLineBGR444: .fl_noshBGR444: +.if OVERRIDE_HIGHCOL + ldr r1, =HighCol + mov lr, #0xff + ldr r1, [r1] + mov lr, lr, lsl #1 + add r1, r1, #8 +.else ldr r1, =(HighCol+8) mov lr, #0xff mov lr, lr, lsl #1 +.endif .fl_loopBGR444: @@ -1480,6 +1535,8 @@ FinalizeLineBGR444: orr \reg, \reg, r3 @ add blue back .endm +.global vidConvCpyRGB565 + vidConvCpyRGB565: @ void *to, void *from, int pixels stmfd sp!, {r4-r9,lr} @@ -1562,9 +1619,17 @@ FinalizeLineRGB555: sub r3, r3, #0x40*2 .fl_noshRGB555: +.if OVERRIDE_HIGHCOL + ldr r1, =HighCol + ldr r0, =DrawLineDest + ldr r1, [r1] + ldr r0, [r0] + add r1, r1, #8 +.else ldr r0, =DrawLineDest ldr r1, =(HighCol+8) ldr r0, [r0] +.endif ldrb r12, [r8, #12] mov lr, #0xff diff --git a/Pico/Draw2.s b/Pico/Draw2.s index 9c3f027..f001089 100644 --- a/Pico/Draw2.s +++ b/Pico/Draw2.s @@ -23,11 +23,11 @@ BackFillFull: stmfd sp!, {r4-r9,lr} ldr lr, =PicoDraw2FB @ lr=PicoDraw2FB + mov r0, r0, lsl #26 ldr lr, [lr] + mov r0, r0, lsr #26 add lr, lr, #328*8 - mov r0, r0, lsl #26 - mov r0, r0, lsr #26 orr r0, r0, r0, lsl #8 orr r0, r0, r0, lsl #16 @@ -344,25 +344,25 @@ DrawLayerFull: mov r6, r1 @ hcache + ldr r11, =(Pico+0x22228) @ Pico.video + ldr r10, =(Pico+0x10000) @ r10=Pico.vram + ldrb r5, [r11, #13] @ pvid->reg[13] + ldrb r7, [r11, #11] + sub lr, r3, r2 and lr, lr, #0x00ff0000 @ lr=cells - ldr r10, =(Pico+0x10000) @ r10=Pico.vram - - ldr r11, =(Pico+0x22228) @ Pico.video - ldrb r5, [r11, #13] @ pvid->reg[13] mov r5, r5, lsl #10 @ htab=pvid->reg[13]<<9; (halfwords) add r5, r5, r0, lsl #1 @ htab+=plane bic r5, r5, #0x00ff0000 @ just in case - ldrb r7, [r11, #11] tst r7, #3 @ full screen scroll? (if ==0) + ldrb r7, [r11, #16] @ ??hh??ww ldreqh r5, [r10, r5] biceq r5, r5, #0x0000fc00 @ r5=hscroll (0-0x3ff) movne r5, r5, lsr #1 orrne r5, r5, #0x8000 @ this marks that we have htab pointer, not hscroll here - ldrb r7, [r11, #16] @ ??hh??ww and r8, r7, #3 orr r5, r5, r7, lsl #1+24 @@ -386,7 +386,7 @@ DrawLayerFull: mov r8, r8, lsl #24+5 orr r8, r8, #0x1f000000 - @ Find name table: + @ Find name table: tst r0, r0 ldreqb r4, [r11, #2] moveq r4, r4, lsr #3 @@ -395,13 +395,13 @@ DrawLayerFull: orr lr, lr, r4, lsl #13 @ lr|=nametab_bits{3}<<13 ldr r11, =PicoDraw2FB @ r11=PicoDraw2FB - ldr r11, [r11] sub r4, r9, #(START_ROW<<24) + ldr r11, [r11] mov r4, r4, asr #24 mov r7, #328*8 mla r11, r4, r7, r11 @ scrpos+=8*328*(planestart-START_ROW); - @ Get vertical scroll value: + @ Get vertical scroll value: add r7, r10, #0x012000 add r7, r7, #0x000180 @ r7=Pico.vsram (Pico+0x22180) ldr r7, [r7] @@ -454,10 +454,10 @@ DrawLayerFull: ldrh r7, [r10, r7] .rtr_hscroll_done: + and r8, r8, #0xff000000 rsb r4, r7, #0 @ r4=tilex=(-ts->hscroll)>>3 mov r4, r4, asr #3 and r4, r4, #0xff - and r8, r8, #0xff000000 orr r8, r8, r4 @ r8=(xmask<<24)|tilex sub r7, r7, #1 @@ -573,8 +573,8 @@ DrawTilesFromCacheF: mvn r6, #0 @ r6=prevy=-1 ldr r4, =PicoDraw2FB @ r4=PicoDraw2FB - ldr r4, [r4] ldr r1, [r0], #4 @ read y offset + ldr r4, [r4] mov r7, #328 mla r1, r7, r1, r4 sub r12, r1, #(328*8*START_ROW) @ r12=scrpos @@ -591,7 +591,7 @@ DrawTilesFromCacheF: movs r1, r7, lsr #16 @ r1=dx; ldmeqfd sp!, {r4-r10,pc} @ dx is never zero, this must be a terminator, return - @ trow changed? + @ row changed? cmp r6, r7, lsr #27 movne r6, r7, lsr #27 movne r4, #328*8 @@ -697,12 +697,12 @@ DrawWindowFull: mov r9, #0xff000000 @ r9=prevcode=-1 ldr r11, =PicoDraw2FB @ r11=scrpos + and r4, r0, #0xff ldr r11, [r11] + sub r4, r4, #START_ROW add r11, r11, #328*8 add r11, r11, #8 - and r4, r0, #0xff - sub r4, r4, #START_ROW mov r7, #328*8 mla r11, r7, r4, r11 @ scrpos+=8*328*(start-START_ROW); mov r0, #0xf @@ -881,9 +881,9 @@ DrawSpriteFull: mov r12, r3, lsl #23 mov r12, r12, lsr #23 - sub r12, r12, #0x78 @ r12=sy ldr lr, [r0, #4] @ lr=code + sub r12, r12, #0x78 @ r12=sy mov r8, lr, lsl #7 mov r8, r8, lsr #23 sub r8, r8, #0x78 @ r8=sx @@ -894,9 +894,8 @@ DrawSpriteFull: and r3, lr, #0x6000 mov r3, r3, lsr #9 @ r3=pal=((code>>9)&0x30); - ldr r10, =(Pico+0x10000) @ r10=Pico.vram - ldr r11, =PicoDraw2FB @ r11=scrpos + ldr r10, =(Pico+0x10000) @ r10=Pico.vram ldr r11, [r11] sub r1, r12, #(START_ROW*8) mov r0, #328 diff --git a/Pico/misc.s b/Pico/Misc.s similarity index 100% rename from Pico/misc.s rename to Pico/Misc.s diff --git a/Pico/Pico.h b/Pico/Pico.h index 296c113..b337f8d 100644 --- a/Pico/Pico.h +++ b/Pico/Pico.h @@ -106,6 +106,9 @@ extern void (*PicoCartLoadProgressCB)(int percent); // Draw.c void PicoDrawSetColorFormat(int which); // 0=BGR444, 1=RGB555, 2=8bit(HighPal pal) extern void *DrawLineDest; +#if OVERRIDE_HIGHCOL +extern unsigned char *HighCol; +#endif extern int (*PicoScan)(unsigned int num, void *data); // internals extern unsigned short HighPal[0x100]; @@ -113,6 +116,7 @@ extern int rendstatus; // utility #ifdef _ASM_DRAW_C void *blockcpy(void *dst, const void *src, size_t n); +void vidConvCpyRGB565(void *to, void *from, int pixels); #else #define blockcpy memcpy #endif diff --git a/Pico/cd/misc.s b/Pico/cd/Misc.s similarity index 100% rename from Pico/cd/misc.s rename to Pico/cd/Misc.s diff --git a/platform/common/emu.c b/platform/common/emu.c new file mode 100644 index 0000000..99fca49 --- /dev/null +++ b/platform/common/emu.c @@ -0,0 +1,775 @@ +// (c) Copyright 2006-2007 notaz, All rights reserved. +// Free for non-commercial use. + +// For commercial use, separate licencing terms must be obtained. + +#include +#include +#include // tolower +#ifndef NO_SYNC +#include +#endif + +#include "emu.h" +#include "menu.h" +#include "fonts.h" +#include "lprintf.h" + +#include +#include +#include + +#if defined(__GP2X__) + #include "../gp2x/gp2x.h" + #define SCREEN_WIDTH 320 + #define SCREEN_BUFFER gp2x_screen +#elif defined(__GIZ__) + #include "../gizmondo/giz.h" + #define SCREEN_WIDTH 321 + #define SCREEN_BUFFER giz_screen // ? +#endif + +char *PicoConfigFile = "picoconfig.bin"; +currentConfig_t currentConfig; +unsigned char *rom_data = NULL; +char noticeMsg[64]; +int state_slot = 0; +int config_slot = 0, config_slot_current = 0; + +unsigned char *movie_data = NULL; +static int movie_size = 0; + +// provided by platform code: +extern char romFileName[]; +extern void emu_noticeMsgUpdated(void); +extern void emu_getMainDir(char *dst, int len); +extern void emu_setDefaultConfig(void); +extern void menu_romload_prepare(const char *rom_name); +extern void menu_romload_end(void); + + +// utilities +static void strlwr_(char* string) +{ + while ( (*string++ = (char)tolower(*string)) ); +} + +static int try_rfn_cut(void) +{ + FILE *tmp; + char *p; + + p = romFileName + strlen(romFileName) - 1; + for (; p > romFileName; p--) + if (*p == '.') break; + *p = 0; + + if((tmp = fopen(romFileName, "rb"))) { + fclose(tmp); + return 1; + } + return 0; +} + +static void get_ext(char *file, char *ext) +{ + char *p; + + p = file + strlen(file) - 4; + if (p < file) p = file; + strncpy(ext, p, 4); + ext[4] = 0; + strlwr_(ext); +} + +char *biosfiles_us[] = { "us_scd2_9306", "SegaCDBIOS9303", "us_scd1_9210" }; +char *biosfiles_eu[] = { "eu_mcd2_9306", "eu_mcd2_9303", "eu_mcd1_9210" }; +char *biosfiles_jp[] = { "jp_mcd1_9112", "jp_mcd1_9111" }; + +int emu_findBios(int region, char **bios_file) +{ + static char bios_path[1024]; + int i, count; + char **files; + FILE *f = NULL; + + if (region == 4) { // US + files = biosfiles_us; + count = sizeof(biosfiles_us) / sizeof(char *); + } else if (region == 8) { // EU + files = biosfiles_eu; + count = sizeof(biosfiles_eu) / sizeof(char *); + } else if (region == 1 || region == 2) { + files = biosfiles_jp; + count = sizeof(biosfiles_jp) / sizeof(char *); + } else { + return 0; + } + + for (i = 0; i < count; i++) + { + emu_getMainDir(bios_path, sizeof(bios_path)); + strcat(bios_path, files[i]); + strcat(bios_path, ".bin"); + f = fopen(bios_path, "rb"); + if (f) break; + + bios_path[strlen(bios_path) - 4] = 0; + strcat(bios_path, ".zip"); + f = fopen(bios_path, "rb"); + if (f) break; + } + + if (f) { + lprintf("using bios: %s\n", bios_path); + fclose(f); + if (bios_file) *bios_file = bios_path; + return 1; + } else { + sprintf(menuErrorMsg, "no %s BIOS files found, read docs", + region != 4 ? (region == 8 ? "EU" : "JAP") : "USA"); + lprintf("%s\n", menuErrorMsg); + return 0; + } +} + +/* checks if romFileName points to valid MegaCD image + * if so, checks for suitable BIOS */ +int emu_cdCheck(int *pregion) +{ + unsigned char buf[32]; + pm_file *cd_f; + int type = 0, region = 4; // 1: Japan, 4: US, 8: Europe + + cd_f = pm_open(romFileName); + if (!cd_f) return 0; // let the upper level handle this + + if (pm_read(buf, 32, cd_f) != 32) { + pm_close(cd_f); + return 0; + } + + if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x00, 14)) type = 1; // Sega CD (ISO) + if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x10, 14)) type = 2; // Sega CD (BIN) + if (type == 0) { + pm_close(cd_f); + return 0; + } + + /* it seems we have a CD image here. Try to detect region now.. */ + pm_seek(cd_f, (type == 1) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET); + pm_read(buf, 1, cd_f); + pm_close(cd_f); + + if (buf[0] == 0x64) region = 8; // EU + if (buf[0] == 0xa1) region = 1; // JAP + + lprintf("detected %s Sega/Mega CD image with %s region\n", + type == 2 ? "BIN" : "ISO", region != 4 ? (region == 8 ? "EU" : "JAP") : "USA"); + + if (pregion != NULL) *pregion = region; + + return type; +} + +int emu_ReloadRom(void) +{ + unsigned int rom_size = 0; + char *used_rom_name = romFileName; + char ext[5]; + pm_file *rom; + int ret, cd_state, cd_region, cfg_loaded = 0; + + lprintf("emu_ReloadRom(%s)\n", romFileName); + + get_ext(romFileName, ext); + + // detect wrong extensions + if(!strcmp(ext, ".srm") || !strcmp(ext, "s.gz") || !strcmp(ext, ".mds")) { // s.gz ~ .mds.gz + sprintf(menuErrorMsg, "Not a ROM selected."); + return 0; + } + + PicoPatchUnload(); + + // check for movie file + if(movie_data) { + free(movie_data); + movie_data = 0; + } + if(!strcmp(ext, ".gmv")) { + // check for both gmv and rom + int dummy; + FILE *movie_file = fopen(romFileName, "rb"); + if(!movie_file) { + sprintf(menuErrorMsg, "Failed to open movie."); + return 0; + } + fseek(movie_file, 0, SEEK_END); + movie_size = ftell(movie_file); + fseek(movie_file, 0, SEEK_SET); + if(movie_size < 64+3) { + sprintf(menuErrorMsg, "Invalid GMV file."); + fclose(movie_file); + return 0; + } + movie_data = malloc(movie_size); + if(movie_data == NULL) { + sprintf(menuErrorMsg, "low memory."); + fclose(movie_file); + return 0; + } + fread(movie_data, 1, movie_size, movie_file); + fclose(movie_file); + if (strncmp((char *)movie_data, "Gens Movie TEST", 15) != 0) { + sprintf(menuErrorMsg, "Invalid GMV file."); + return 0; + } + dummy = try_rfn_cut() || try_rfn_cut(); + if (!dummy) { + sprintf(menuErrorMsg, "Could't find a ROM for movie."); + return 0; + } + get_ext(romFileName, ext); + } + else if (!strcmp(ext, ".pat")) { + int dummy; + PicoPatchLoad(romFileName); + dummy = try_rfn_cut() || try_rfn_cut(); + if (!dummy) { + sprintf(menuErrorMsg, "Could't find a ROM to patch."); + return 0; + } + get_ext(romFileName, ext); + } + + if ((PicoMCD & 1) && Pico_mcd != NULL) + Stop_CD(); + + // check for MegaCD image + cd_state = emu_cdCheck(&cd_region); + if (cd_state > 0) + { + // valid CD image, check for BIOS.. + + // we need to have config loaded at this point + ret = emu_ReadConfig(1, 1); + if (!ret) emu_ReadConfig(0, 1); + cfg_loaded = 1; + + if (PicoRegionOverride) { + cd_region = PicoRegionOverride; + lprintf("overrided region to %s\n", cd_region != 4 ? (cd_region == 8 ? "EU" : "JAP") : "USA"); + } + if (!emu_findBios(cd_region, &used_rom_name)) { + // bios_help() ? + return 0; + } + + PicoMCD |= 1; + get_ext(used_rom_name, ext); + } + else + { + if (PicoMCD & 1) Stop_CD(); + PicoMCD &= ~1; + } + + rom = pm_open(used_rom_name); + if(!rom) { + sprintf(menuErrorMsg, "Failed to open rom."); + return 0; + } + + menu_romload_prepare(used_rom_name); + + if(rom_data) { + free(rom_data); + rom_data = 0; + rom_size = 0; + } + + if( (ret = PicoCartLoad(rom, &rom_data, &rom_size)) ) { + sprintf(menuErrorMsg, "PicoCartLoad() failed."); + lprintf("%s\n", menuErrorMsg); + pm_close(rom); + menu_romload_end(); + return 0; + } + pm_close(rom); + menu_romload_end(); + + // detect wrong files (Pico crashes on very small files), also see if ROM EP is good + if(rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 || + ((*(unsigned char *)(rom_data+4)<<16)|(*(unsigned short *)(rom_data+6))) >= (int)rom_size) { + if (rom_data) free(rom_data); + rom_data = 0; + sprintf(menuErrorMsg, "Not a ROM selected."); + return 0; + } + + // load config for this ROM (do this before insert to get correct region) + if (!cfg_loaded) { + ret = emu_ReadConfig(1, 1); + if (!ret) emu_ReadConfig(0, 1); + } + + lprintf("PicoCartInsert(%p, %d);\n", rom_data, rom_size); + if(PicoCartInsert(rom_data, rom_size)) { + sprintf(menuErrorMsg, "Failed to load ROM."); + return 0; + } + + Pico.m.frame_count = 0; + + // insert CD if it was detected + if (cd_state > 0) { + ret = Insert_CD(romFileName, cd_state == 2); + if (ret != 0) { + sprintf(menuErrorMsg, "Insert_CD() failed, invalid CD image?"); + lprintf("%s\n", menuErrorMsg); + return 0; + } + } + + // emu_ReadConfig() might have messed currentConfig.lastRomFile + strncpy(currentConfig.lastRomFile, romFileName, sizeof(currentConfig.lastRomFile)-1); + currentConfig.lastRomFile[sizeof(currentConfig.lastRomFile)-1] = 0; + + if (PicoPatches) { + PicoPatchPrepare(); + PicoPatchApply(); + } + + // additional movie stuff + if (movie_data) { + if(movie_data[0x14] == '6') + PicoOpt |= 0x20; // 6 button pad + else PicoOpt &= ~0x20; + PicoOpt |= 0x10040; // accurate timing, no VDP fifo timing + if(movie_data[0xF] >= 'A') { + if(movie_data[0x16] & 0x80) { + PicoRegionOverride = 8; + } else { + PicoRegionOverride = 4; + } + PicoReset(0); + // TODO: bits 6 & 5 + } + movie_data[0x18+30] = 0; + sprintf(noticeMsg, "MOVIE: %s", (char *) &movie_data[0x18]); + } + else + { + PicoOpt &= ~0x10000; + if(Pico.m.pal) { + strcpy(noticeMsg, "PAL SYSTEM / 50 FPS"); + } else { + strcpy(noticeMsg, "NTSC SYSTEM / 60 FPS"); + } + } + emu_noticeMsgUpdated(); + + // load SRAM for this ROM + if(currentConfig.EmuOpt & 1) + emu_SaveLoadGame(1, 1); + + return 1; +} + + +static void romfname_ext(char *dst, const char *prefix, const char *ext) +{ + char *p; + int prefix_len = 0; + + // make save filename + for (p = romFileName+strlen(romFileName)-1; p >= romFileName && *p != '/'; p--); p++; + *dst = 0; + if (prefix) { + strcpy(dst, prefix); + prefix_len = strlen(prefix); + } + strncpy(dst + prefix_len, p, 511-prefix_len); + dst[511-8] = 0; + if (dst[strlen(dst)-4] == '.') dst[strlen(dst)-4] = 0; + if (ext) strcat(dst, ext); +} + + +int emu_ReadConfig(int game, int no_defaults) +{ + FILE *f; + char cfg[512], extbuf[16]; + int bread = 0; + + if (!game) + { + if (!no_defaults) + { + emu_setDefaultConfig(); + } + strncpy(cfg, PicoConfigFile, 511); + if (config_slot != 0) + { + char *p = strrchr(cfg, '.'); + if (p == NULL) p = cfg + strlen(cfg); + sprintf(extbuf, ".%i.pbcfg", config_slot); + strncpy(p, extbuf, 511 - (p - cfg)); + } + cfg[511] = 0; + } else { + if (config_slot != 0) + sprintf(extbuf, ".%i.pbcfg", config_slot); + else strcpy(extbuf, ".pbcfg"); + romfname_ext(cfg, "cfg/", extbuf); + f = fopen(cfg, "rb"); + if (!f) romfname_ext(cfg, NULL, ".pbcfg"); + else fclose(f); + } + + lprintf("emu_ReadConfig: %s ", cfg); + f = fopen(cfg, "rb"); + if (f) { + bread = fread(¤tConfig, 1, sizeof(currentConfig), f); + fclose(f); + } + lprintf(bread > 0 ? "(ok)\n" : "(failed)\n"); + + PicoOpt = currentConfig.PicoOpt; + PsndRate = currentConfig.PsndRate; + PicoRegionOverride = currentConfig.PicoRegion; + PicoAutoRgnOrder = currentConfig.PicoAutoRgnOrder; + PicoCDBuffers = currentConfig.PicoCDBuffers; + //scaling_update(); + // some sanity checks + if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200; + if (currentConfig.gamma < 10 || currentConfig.gamma > 300) currentConfig.gamma = 100; + if (currentConfig.volume < 0 || currentConfig.volume > 99) currentConfig.volume = 50; + // if volume keys are unbound, bind them to volume control + if (!currentConfig.KeyBinds[23] && !currentConfig.KeyBinds[22]) { + currentConfig.KeyBinds[23] = 1<<29; // vol up + currentConfig.KeyBinds[22] = 1<<30; // vol down + } + + if (bread > 0) config_slot_current = config_slot; + return (bread > 0); // == sizeof(currentConfig)); +} + + +int emu_WriteConfig(int game) +{ + FILE *f; + char cfg[512], extbuf[16]; + int bwrite = 0; + + if (!game) + { + strncpy(cfg, PicoConfigFile, 511); + if (config_slot != 0) + { + char *p = strrchr(cfg, '.'); + if (p == NULL) p = cfg + strlen(cfg); + sprintf(extbuf, ".%i.pbcfg", config_slot); + strncpy(p, extbuf, 511 - (p - cfg)); + } + cfg[511] = 0; + } else { + if (config_slot != 0) + sprintf(extbuf, ".%i.pbcfg", config_slot); + else strcpy(extbuf, ".pbcfg"); + romfname_ext(cfg, "cfg/", extbuf); + } + + lprintf("emu_WriteConfig: %s ", cfg); + f = fopen(cfg, "wb"); + if (f) { + currentConfig.PicoOpt = PicoOpt; + currentConfig.PsndRate = PsndRate; + currentConfig.PicoRegion = PicoRegionOverride; + currentConfig.PicoAutoRgnOrder = PicoAutoRgnOrder; + currentConfig.PicoCDBuffers = PicoCDBuffers; + bwrite = fwrite(¤tConfig, 1, sizeof(currentConfig), f); + fflush(f); + fclose(f); +#ifndef NO_SYNC + sync(); +#endif + } + lprintf((bwrite == sizeof(currentConfig)) ? "(ok)\n" : "(failed)\n"); + + if (bwrite == sizeof(currentConfig)) config_slot_current = config_slot; + return (bwrite == sizeof(currentConfig)); +} + + +void emu_textOut8(int x, int y, const char *text) +{ + int i,l,len=strlen(text); + unsigned char *screen = (unsigned char *)SCREEN_BUFFER + x + y*SCREEN_WIDTH; + + /* always using built-in font */ + for (i = 0; i < len; i++) + { + for (l=0;l<8;l++) + { + unsigned char fd = fontdata8x8[((text[i])*8)+l]; + if (fd&0x80) screen[l*SCREEN_WIDTH+0]=0xf0; + if (fd&0x40) screen[l*SCREEN_WIDTH+1]=0xf0; + if (fd&0x20) screen[l*SCREEN_WIDTH+2]=0xf0; + if (fd&0x10) screen[l*SCREEN_WIDTH+3]=0xf0; + if (fd&0x08) screen[l*SCREEN_WIDTH+4]=0xf0; + if (fd&0x04) screen[l*SCREEN_WIDTH+5]=0xf0; + if (fd&0x02) screen[l*SCREEN_WIDTH+6]=0xf0; + if (fd&0x01) screen[l*SCREEN_WIDTH+7]=0xf0; + } + screen += 8; + } +} + +void emu_textOut16(int x, int y, const char *text) +{ + int i,l,len=strlen(text); + unsigned short *screen = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH; + + for (i = 0; i < len; i++) + { + for (l=0;l<8;l++) + { + unsigned char fd = fontdata8x8[((text[i])*8)+l]; + if(fd&0x80) screen[l*SCREEN_WIDTH+0]=0xffff; + if(fd&0x40) screen[l*SCREEN_WIDTH+1]=0xffff; + if(fd&0x20) screen[l*SCREEN_WIDTH+2]=0xffff; + if(fd&0x10) screen[l*SCREEN_WIDTH+3]=0xffff; + if(fd&0x08) screen[l*SCREEN_WIDTH+4]=0xffff; + if(fd&0x04) screen[l*SCREEN_WIDTH+5]=0xffff; + if(fd&0x02) screen[l*SCREEN_WIDTH+6]=0xffff; + if(fd&0x01) screen[l*SCREEN_WIDTH+7]=0xffff; + } + screen += 8; + } +} + + +void emu_updateMovie(void) +{ + int offs = Pico.m.frame_count*3 + 0x40; + if (offs+3 > movie_size) { + free(movie_data); + movie_data = 0; + strcpy(noticeMsg, "END OF MOVIE."); + lprintf("END OF MOVIE.\n"); + emu_noticeMsgUpdated(); + } else { + // MXYZ SACB RLDU + PicoPad[0] = ~movie_data[offs] & 0x8f; // ! SCBA RLDU + if(!(movie_data[offs] & 0x10)) PicoPad[0] |= 0x40; // A + if(!(movie_data[offs] & 0x20)) PicoPad[0] |= 0x10; // B + if(!(movie_data[offs] & 0x40)) PicoPad[0] |= 0x20; // A + PicoPad[1] = ~movie_data[offs+1] & 0x8f; // ! SCBA RLDU + if(!(movie_data[offs+1] & 0x10)) PicoPad[1] |= 0x40; // A + if(!(movie_data[offs+1] & 0x20)) PicoPad[1] |= 0x10; // B + if(!(movie_data[offs+1] & 0x40)) PicoPad[1] |= 0x20; // A + PicoPad[0] |= (~movie_data[offs+2] & 0x0A) << 8; // ! MZYX + if(!(movie_data[offs+2] & 0x01)) PicoPad[0] |= 0x0400; // X + if(!(movie_data[offs+2] & 0x04)) PicoPad[0] |= 0x0100; // Z + PicoPad[1] |= (~movie_data[offs+2] & 0xA0) << 4; // ! MZYX + if(!(movie_data[offs+2] & 0x10)) PicoPad[1] |= 0x0400; // X + if(!(movie_data[offs+2] & 0x40)) PicoPad[1] |= 0x0100; // Z + } +} + + +static size_t gzRead2(void *p, size_t _size, size_t _n, void *file) +{ + return gzread(file, p, _n); +} + + +static size_t gzWrite2(void *p, size_t _size, size_t _n, void *file) +{ + return gzwrite(file, p, _n); +} + +static int try_ropen_file(const char *fname) +{ + FILE *f; + + f = fopen(fname, "rb"); + if (f) { + fclose(f); + return 1; + } + return 0; +} + +char *emu_GetSaveFName(int load, int is_sram, int slot) +{ + static char saveFname[512]; + char ext[16]; + + if (is_sram) + { + romfname_ext(saveFname, (PicoMCD&1) ? "brm/" : "srm/", (PicoMCD&1) ? ".brm" : ".srm"); + if (load) { + if (try_ropen_file(saveFname)) return saveFname; + // try in current dir.. + romfname_ext(saveFname, NULL, (PicoMCD&1) ? ".brm" : ".srm"); + if (try_ropen_file(saveFname)) return saveFname; + return NULL; // give up + } + } + else + { + ext[0] = 0; + if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot); + strcat(ext, (currentConfig.EmuOpt & 8) ? ".mds.gz" : ".mds"); + + romfname_ext(saveFname, "mds/", ext); + if (load) { + if (try_ropen_file(saveFname)) return saveFname; + romfname_ext(saveFname, NULL, ext); + if (try_ropen_file(saveFname)) return saveFname; + if (currentConfig.EmuOpt & 8) { + ext[0] = 0; + if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot); + strcat(ext, ".mds"); + + romfname_ext(saveFname, "mds/", ext); + if (try_ropen_file(saveFname)) return saveFname; + romfname_ext(saveFname, NULL, ext); + if (try_ropen_file(saveFname)) return saveFname; + } + return NULL; + } + } + + return saveFname; +} + +int emu_checkSaveFile(int slot) +{ + return emu_GetSaveFName(1, 0, slot) ? 1 : 0; +} + +void emu_setSaveStateCbs(int gz) +{ + if (gz) { + areaRead = gzRead2; + areaWrite = gzWrite2; + areaEof = (areaeof *) gzeof; + areaSeek = (areaseek *) gzseek; + areaClose = (areaclose *) gzclose; + } else { + areaRead = (arearw *) fread; + areaWrite = (arearw *) fwrite; + areaEof = (areaeof *) feof; + areaSeek = (areaseek *) fseek; + areaClose = (areaclose *) fclose; + } +} + +int emu_SaveLoadGame(int load, int sram) +{ + int ret = 0; + char *saveFname; + + // make save filename + saveFname = emu_GetSaveFName(load, sram, state_slot); + if (saveFname == NULL) { + if (!sram) { + strcpy(noticeMsg, load ? "LOAD FAILED (missing file)" : "SAVE FAILED "); + emu_noticeMsgUpdated(); + } + return -1; + } + + lprintf("saveLoad (%i, %i): %s\n", load, sram, saveFname); + + if(sram) { + FILE *sramFile; + int sram_size; + unsigned char *sram_data; + int truncate = 1; + if (PicoMCD&1) { + if (PicoOpt&0x8000) { // MCD RAM cart? + sram_size = 0x12000; + sram_data = SRam.data; + if (sram_data) + memcpy32((int *)sram_data, (int *)Pico_mcd->bram, 0x2000/4); + } else { + sram_size = 0x2000; + sram_data = Pico_mcd->bram; + truncate = 0; // the .brm may contain RAM cart data after normal brm + } + } else { + sram_size = SRam.end-SRam.start+1; + if(Pico.m.sram_reg & 4) sram_size=0x2000; + sram_data = SRam.data; + } + if (!sram_data) return 0; // SRam forcefully disabled for this game + + if (load) { + sramFile = fopen(saveFname, "rb"); + if(!sramFile) return -1; + fread(sram_data, 1, sram_size, sramFile); + fclose(sramFile); + if ((PicoMCD&1) && (PicoOpt&0x8000)) + memcpy32((int *)Pico_mcd->bram, (int *)sram_data, 0x2000/4); + } else { + // sram save needs some special processing + // see if we have anything to save + for (; sram_size > 0; sram_size--) + if (sram_data[sram_size-1]) break; + + if (sram_size) { + sramFile = fopen(saveFname, truncate ? "wb" : "r+b"); + if (!sramFile) sramFile = fopen(saveFname, "wb"); // retry + if (!sramFile) return -1; + ret = fwrite(sram_data, 1, sram_size, sramFile); + ret = (ret != sram_size) ? -1 : 0; + fclose(sramFile); +#ifndef NO_SYNC + sync(); +#endif + } + } + return ret; + } + else + { + void *PmovFile = NULL; + if (strcmp(saveFname + strlen(saveFname) - 3, ".gz") == 0) { + if( (PmovFile = gzopen(saveFname, load ? "rb" : "wb")) ) { + emu_setSaveStateCbs(1); + if(!load) gzsetparams(PmovFile, 9, Z_DEFAULT_STRATEGY); + } + } + else + { + if( (PmovFile = fopen(saveFname, load ? "rb" : "wb")) ) { + emu_setSaveStateCbs(0); + } + } + if(PmovFile) { + ret = PmovState(load ? 6 : 5, PmovFile); + areaClose(PmovFile); + PmovFile = 0; + if (load) Pico.m.dirtyPal=1; +#ifndef NO_SYNC + else sync(); +#endif + } + else ret = -1; + if (!ret) + strcpy(noticeMsg, load ? "GAME LOADED " : "GAME SAVED "); + else + { + strcpy(noticeMsg, load ? "LOAD FAILED " : "SAVE FAILED "); + ret = -1; + } + + emu_noticeMsgUpdated(); + return ret; + } +} diff --git a/platform/common/emu.h b/platform/common/emu.h new file mode 100644 index 0000000..67533cb --- /dev/null +++ b/platform/common/emu.h @@ -0,0 +1,48 @@ +// (c) Copyright 2006-2007 notaz, All rights reserved. +// Free for non-commercial use. + +// For commercial use, separate licencing terms must be obtained. + +typedef struct { + char lastRomFile[512]; + int EmuOpt; // LSb->MSb: use_sram, show_fps, enable_sound, gzip_saves, + // squidgehack, no_save_cfg_on_exit, , 16_bit_mode + // craigix_ram, confirm_save, show_cd_leds, confirm_load + // A_SNs_gamma, perfect_vsync + 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]; + int PicoAutoRgnOrder; + int PicoCDBuffers; + int scaling; // 0=center, 1=hscale, 2=hvscale, 3=hsoftscale +} currentConfig_t; + + +extern currentConfig_t currentConfig; +extern char *PicoConfigFile; +extern unsigned char *rom_data; +extern char noticeMsg[64]; +extern int state_slot; +extern int config_slot, config_slot_current; +extern unsigned char *movie_data; + + +int emu_ReloadRom(void); +int emu_SaveLoadGame(int load, int sram); +int emu_ReadConfig(int game, int no_defaults); +int emu_WriteConfig(int game); +char *emu_GetSaveFName(int load, int is_sram, int slot); +int emu_checkSaveFile(int slot); +void emu_setSaveStateCbs(int gz); +void emu_updateMovie(void); +int emu_cdCheck(int *pregion); +int emu_findBios(int region, char **bios_file); +void emu_textOut8 (int x, int y, const char *text); +void emu_textOut16(int x, int y, const char *text); + diff --git a/platform/common/menu.c b/platform/common/menu.c index ed02ff8..d2957c2 100644 --- a/platform/common/menu.c +++ b/platform/common/menu.c @@ -14,16 +14,18 @@ #include "lprintf.h" #if defined(__GP2X__) -#include "../gp2x/gp2x.h" -#define SCREEN_WIDTH 320 -#define SCREEN_BUFFER gp2x_screen + #include "../gp2x/gp2x.h" + #define SCREEN_WIDTH 320 + #define SCREEN_BUFFER gp2x_screen #elif defined(__GIZ__) -#include "../gizmondo/giz.h" -#define SCREEN_WIDTH 321 -#define SCREEN_BUFFER menu_screen -extern unsigned char menu_screen[321*240*2]; + //#include "../gizmondo/giz.h" + #define SCREEN_WIDTH 321 + #define SCREEN_BUFFER menu_screen + extern unsigned char *menu_screen; #endif +char menuErrorMsg[64] = { 0, }; + static unsigned char menu_font_data[10240]; static int menu_text_color = 0xffff; // default to white static int menu_sel_color = -1; // disabled diff --git a/platform/common/menu.h b/platform/common/menu.h index 1e096ff..b21818d 100644 --- a/platform/common/menu.h +++ b/platform/common/menu.h @@ -7,6 +7,7 @@ void smalltext_out16(int x, int y, const char *texto, int color); void smalltext_out16_lim(int x, int y, const char *texto, int color, int max); void menu_draw_selection(int x, int y, int w); +extern char menuErrorMsg[64]; typedef enum diff --git a/platform/gizmondo/Makefile b/platform/gizmondo/Makefile index 1824fe1..ff7906a 100644 --- a/platform/gizmondo/Makefile +++ b/platform/gizmondo/Makefile @@ -14,8 +14,13 @@ amalgamate = 0 -DEFINC = -I../.. -I. -D__GIZ__ -D_UNZIP_SUPPORT -COPT_COMMON = -static -Wall -O2 -ftracer -fstrength-reduce -fomit-frame-pointer -fstrict-aliasing -ffast-math +DEFINC = -I../.. -I. -D__GIZ__ -D_UNZIP_SUPPORT -DNO_SYNC +COPT_COMMON = -static -Wall -Winline +ifeq ($(DEBUG),) +COPT_COMMON += -O2 -ftracer -fstrength-reduce -fomit-frame-pointer -fstrict-aliasing -ffast-math +else +COPT_COMMON += -ggdb +endif ifeq "$(profile)" "1" COPT_COMMON += -fprofile-generate endif @@ -30,10 +35,10 @@ AS = $(CROSS)as LD = $(CROSS)ld # frontend -OBJS += main.o menu.o giz.o emu.o +OBJS += main.o emu.o menu.o giz.o asm_utils.o # common -OBJS += ../common/menu.o ../common/fonts.o ../common/arm_utils.o ../common/readpng.o +OBJS += ../common/emu.o ../common/menu.o ../common/fonts.o ../common/arm_utils.o ../common/readpng.o # Pico ifeq "$(amalgamate)" "1" @@ -129,7 +134,7 @@ endif ../../Pico/sound/mix_asm.o : ../../Pico/sound/mix.s @echo $< @$(AS) $(ASFLAGS) $< -o $@ -../../Pico/misc_asm.o : ../../Pico/misc.s +../../Pico/misc_asm.o : ../../Pico/Misc.s @echo $< @$(AS) $(ASFLAGS) $< -o $@ ../../Pico/cd/pico_asm.o : ../../Pico/cd/Pico.s @@ -138,7 +143,7 @@ endif ../../Pico/cd/memory_asm.o : ../../Pico/cd/Memory.s @echo $< @$(AS) $(ASFLAGS) $< -o $@ -../../Pico/cd/misc_asm.o : ../../Pico/cd/misc.s +../../Pico/cd/misc_asm.o : ../../Pico/cd/Misc.s @echo $< @$(AS) $(ASFLAGS) $< -o $@ @@ -160,6 +165,15 @@ clean_prof: find ../.. -name '*.gcno' -delete find ../.. -name '*.gcda' -delete +up: PicoDrive.exe + synce-pcp -d 3 PicoDrive.exe ":/SD Card/emus/PicoDrive/PicoDrive.exe" + +run: up + synce-prun "/SD Card/emus/PicoDrive/PicoDrive.exe" + +run_only: + synce-prun "/SD Card/emus/PicoDrive/PicoDrive.exe" + # ----------- release ----------- ifneq ($(findstring rel,$(MAKECMDGOALS)),) ifeq ($(VER),) diff --git a/platform/gizmondo/asm_utils.h b/platform/gizmondo/asm_utils.h new file mode 100644 index 0000000..271dbc1 --- /dev/null +++ b/platform/gizmondo/asm_utils.h @@ -0,0 +1,3 @@ + +void vidCpy8to16_40(void *dest, void *src, short *pal, int lines); + diff --git a/platform/gizmondo/asm_utils.s b/platform/gizmondo/asm_utils.s new file mode 100644 index 0000000..4676e1e --- /dev/null +++ b/platform/gizmondo/asm_utils.s @@ -0,0 +1,112 @@ +@ vim:filetype=armasm + + +.global vidCpy8to16_40 @ void *dest, void *src, short *pal, int lines + +vidCpy8to16_40: + stmfd sp!, {r4-r9,lr} + + mov r3, r3, lsr #1 + orr r3, r3, r3, lsl #8 + add r1, r1, #8 + orr r3, r3, #(320/8-1)<<24 + + @ even lines +vcloop_40_aligned: + ldr r12, [r1], #4 + ldr r7, [r1], #4 + + and r4, lr, r12, lsl #1 + ldrh r4, [r2, r4] + and r5, lr, r12, lsr #7 + ldrh r5, [r2, r5] + and r6, lr, r12, lsr #15 + ldrh r6, [r2, r6] + orr r4, r4, r5, lsl #16 + + and r5, lr, r12, lsr #23 + ldrh r5, [r2, r5] + and r8, lr, r7, lsl #1 + ldrh r8, [r2, r8] + orr r5, r6, r5, lsl #16 + + and r6, lr, r7, lsr #7 + ldrh r6, [r2, r6] + and r12,lr, r7, lsr #15 + ldrh r12,[r2, r12] + and r9, lr, r7, lsr #23 + ldrh r9, [r2, r9] + orr r8, r8, r6, lsl #16 + + subs r3, r3, #1<<24 + orr r12,r12, r9, lsl #16 + + stmia r0!, {r4,r5,r8,r12} + bpl vcloop_40_aligned + + add r1, r1, #336 @ skip a line and 1 col + add r0, r0, #320*2+2*2 + add r3, r3, #(320/8)<<24 + sub r3, r3, #1 + tst r3, #0xff + bne vcloop_40_aligned + + and r4, r3, #0xff00 + orr r3, r3, r4, lsr #8 + mov r4, r4, lsr #7 + sub r4, r4, #1 + mov r5, #320*2 + add r5, r5, #2 + mul r4, r5, r4 + sub r0, r0, r4 + mov r5, #328 + mul r4, r5, r4 + sub r1, r1, r4 + +vcloop_40_unaligned: + ldr r12, [r1], #4 + ldr r7, [r1], #4 + + and r4, lr, r12, lsl #1 + ldrh r4, [r2, r4] + and r5, lr, r12, lsr #7 + ldrh r5, [r2, r5] + strh r4, [r0]! + and r6, lr, r12, lsr #15 + ldrh r6, [r2, r6] + + and r4, lr, r12, lsr #23 + ldrh r4, [r2, r4] + orr r5, r5, r6, lsl #16 + + and r8, lr, r7, lsl #1 + ldrh r8, [r2, r8] + + and r6, lr, r7, lsr #7 + ldrh r6, [r2, r6] + orr r8, r4, r8, lsl #16 + + and r12,lr, r7, lsr #15 + ldrh r12,[r2, r12] + + and r4, lr, r7, lsr #23 + ldrh r4, [r2, r6] + orr r12,r6, r12,lsl #16 + subs r3, r3, #1 + + stmia r0!, {r5,r8,r12} + strh r4, [r0]! + bne vcloop_40_unaligned + + add r1, r1, #336 @ skip a line and 1 col + add r0, r0, #320*2+2*2 + add r3, r3, #(320/8)<<24 + sub r3, r3, #1 + tst r3, #0xff + bne vcloop_40_unaligned + + ldmfd sp!, {r4-r9,lr} + bx lr + + + diff --git a/platform/gizmondo/emu.c b/platform/gizmondo/emu.c index 3f9a6cb..a3cf057 100644 --- a/platform/gizmondo/emu.c +++ b/platform/gizmondo/emu.c @@ -1,33 +1,503 @@ #include +#include +#include "kgsdk/Framework2D.h" +#include "kgsdk/FrameworkAudio.h" +#include "../common/emu.h" +#include "../common/lprintf.h" +#include "../common/arm_utils.h" #include "emu.h" +#include "menu.h" +#include "giz.h" +#include "asm_utils.h" +#include + +#ifdef BENCHMARK +#define OSD_FPS_X 220 +#else +#define OSD_FPS_X 260 +#endif + +// main 300K gfx-related buffer. Used by menu and renderers. +unsigned char gfx_buffer[321*240*2*2]; char romFileName[MAX_PATH]; int engineState; -currentConfig_t currentConfig; -unsigned char *rom_data = NULL; -unsigned char *PicoDraw2FB = NULL; // temporary buffer for alt renderer -int state_slot = 0; +unsigned char *PicoDraw2FB = gfx_buffer; // temporary buffer for alt renderer ( (8+320)*(8+240+8) ) int reset_timing = 0; -int config_slot = 0, config_slot_current = 0; - - - - -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 no_defaults){} -int emu_WriteConfig(int game){} -char *emu_GetSaveFName(int load, int is_sram, int slot){} -int emu_check_save_file(int slot){} -void emu_set_save_cbs(int gz){} -void emu_forced_frame(void){} -int emu_cd_check(int *pregion){} -int find_bios(int region, char **bios_file){} -void scaling_update(void){} + +static DWORD noticeMsgTime = 0; +static int osd_fps_x; + + +static void blit(const char *fps, const char *notice); +static void clearArea(int full); + +void emu_noticeMsgUpdated(void) +{ + noticeMsgTime = GetTickCount(); +} + +void emu_getMainDir(char *dst, int len) +{ + if (len > 0) *dst = 0; +} + +static void emu_msg_cb(const char *msg) +{ + if (giz_screen == NULL) + giz_screen = Framework2D_LockBuffer(); + + memset32((int *)((char *)giz_screen + 321*232*2), 0, 321*8*2/4); + emu_textOut16(4, 232, msg); + noticeMsgTime = GetTickCount() - 2000; + + /* assumption: emu_msg_cb gets called only when something slow is about to happen */ + reset_timing = 1; +} + +static void emu_state_cb(const char *str) +{ + clearArea(0); + blit("", str); +} + +static void emu_msg_tray_open(void) +{ + strcpy(noticeMsg, "CD tray opened"); + noticeMsgTime = GetTickCount(); +} + + +void emu_Init(void) +{ + // make dirs for saves, cfgs, etc. + CreateDirectory(L"mds", NULL); + CreateDirectory(L"srm", NULL); + CreateDirectory(L"brm", NULL); + CreateDirectory(L"cfg", NULL); + + PicoInit(); + PicoMessage = emu_msg_cb; + PicoMCDopenTray = emu_msg_tray_open; + PicoMCDcloseTray = menu_loop_tray; +} + +void emu_Deinit(void) +{ + // save SRAM + if((currentConfig.EmuOpt & 1) && SRam.changed) { + emu_SaveLoadGame(0, 1); + SRam.changed = 0; + } + + if (!(currentConfig.EmuOpt & 0x20)) { + FILE *f = fopen(PicoConfigFile, "r+b"); + if (!f) emu_WriteConfig(0); + else { + // if we already have config, reload it, except last ROM + fseek(f, sizeof(currentConfig.lastRomFile), SEEK_SET); + fread(¤tConfig.EmuOpt, 1, sizeof(currentConfig) - sizeof(currentConfig.lastRomFile), f); + fseek(f, 0, SEEK_SET); + fwrite(¤tConfig, 1, sizeof(currentConfig), f); + fflush(f); + fclose(f); + } + } + + PicoExit(); +} + +void emu_setDefaultConfig(void) +{ + memset(¤tConfig, 0, sizeof(currentConfig)); + currentConfig.lastRomFile[0] = 0; + currentConfig.EmuOpt = 0x1f | 0x600; // | confirm_save, cd_leds + currentConfig.PicoOpt = 0x0f | 0xc00; // | cd_pcm, cd_cdda + currentConfig.PsndRate = 22050; + currentConfig.PicoRegion = 0; // auto + currentConfig.PicoAutoRgnOrder = 0x184; // US, EU, JP + currentConfig.Frameskip = -1; // auto + currentConfig.volume = 50; + currentConfig.KeyBinds[ 2] = 1<<0; // SACB RLDU + currentConfig.KeyBinds[ 3] = 1<<1; + currentConfig.KeyBinds[ 0] = 1<<2; + currentConfig.KeyBinds[ 1] = 1<<3; + currentConfig.KeyBinds[ 5] = 1<<4; + currentConfig.KeyBinds[ 6] = 1<<5; + currentConfig.KeyBinds[ 7] = 1<<6; + currentConfig.KeyBinds[ 8] = 1<<7; + currentConfig.KeyBinds[ 4] = 1<<26; // switch rend + currentConfig.KeyBinds[ 8] = 1<<27; // save state + currentConfig.KeyBinds[ 9] = 1<<28; // load state + currentConfig.KeyBinds[12] = 1<<29; // vol up + currentConfig.KeyBinds[11] = 1<<30; // vol down + currentConfig.PicoCDBuffers = 64; + currentConfig.scaling = 0; +} + + +static int EmuScan16(unsigned int num, void *sdata) +{ + if (!(Pico.video.reg[1]&8)) num += 8; + DrawLineDest = (unsigned short *) giz_screen + 321*(num+1); + + return 0; +} + +static int EmuScan8(unsigned int num, void *sdata) +{ + // draw like the fast renderer + if (!(Pico.video.reg[1]&8)) num += 8; + HighCol = gfx_buffer + 328*8 + 328*(num+1); + + return 0; +} + +static void osd_text(int x, int y, const char *text) +{ + int len = strlen(text) * 8; + int *p, i, h; + len = (len+1) >> 1; + for (h = 0; h < 8; h++) { + p = (int *) ((unsigned short *) giz_screen+x+321*(y+h)); + p = (int *) ((int)p & ~3); // align + for (i = len; i; i--, p++) *p = 0; + } + emu_textOut16(x, y, text); +} + + +short localPal[0x100]; +static void (*vidCpy8to16)(void *dest, void *src, short *pal, int lines) = NULL; + +static void blit(const char *fps, const char *notice) +{ + int emu_opt = currentConfig.EmuOpt; + + if (PicoOpt&0x10) { + // 8bit fast renderer + if (Pico.m.dirtyPal) { + Pico.m.dirtyPal = 0; + vidConvCpyRGB565(localPal, Pico.cram, 0x40); + } + vidCpy8to16((unsigned short *)giz_screen+321*8, PicoDraw2FB+328*8, localPal, 224); + } else if (!(emu_opt&0x80)) { + // 8bit accurate renderer + if (Pico.m.dirtyPal) { + Pico.m.dirtyPal = 0; + vidConvCpyRGB565(localPal, Pico.cram, 0x40); + if(Pico.video.reg[0xC]&8) { // shadow/hilight mode + //vidConvCpyRGB32sh(localPal+0x40, Pico.cram, 0x40); + //vidConvCpyRGB32hi(localPal+0x80, Pico.cram, 0x40); // TODO + blockcpy(localPal+0xc0, localPal+0x40, 0x40*4); + localPal[0xc0] = 0x0600; + localPal[0xd0] = 0xc000; + localPal[0xe0] = 0x0000; // reserved pixels for OSD + localPal[0xf0] = 0xffff; + } + /* no support + else if (rendstatus & 0x20) { // mid-frame palette changes + vidConvCpyRGB565(localPal+0x40, HighPal, 0x40); + vidConvCpyRGB565(localPal+0x80, HighPal+0x40, 0x40); + } */ + } + // TODO... + vidCpy8to16((unsigned short *)giz_screen+321*8, PicoDraw2FB+328*8, localPal, 224); + } + + if (notice || (emu_opt & 2)) { + int h = 232; + if (notice) osd_text(4, h, notice); + if (emu_opt & 2) osd_text(osd_fps_x, h, fps); + } +// if ((emu_opt & 0x400) && (PicoMCD & 1)) +// cd_leds(); + + //gp2x_video_wait_vsync(); + + if (!(PicoOpt&0x10)) { + if (Pico.video.reg[1] & 8) { + if (currentConfig.EmuOpt&0x80) + DrawLineDest = (unsigned short *) giz_screen; + else + HighCol = gfx_buffer; + } else { + if (currentConfig.EmuOpt&0x80) + DrawLineDest = (unsigned short *) giz_screen + 320*8; + else + HighCol = gfx_buffer + 328*8; + } + } +} + +// clears whole screen or just the notice area (in all buffers) +static void clearArea(int full) +{ + if (giz_screen == NULL) + giz_screen = Framework2D_LockBuffer(); + if (full) memset32(giz_screen, 0, 320*240*2/4); + else memset32((int *)((char *)giz_screen + 320*232*2), 0, 320*8*2/4); +} + +static void vidResetMode(void) +{ + void *screen; + if (PicoOpt&0x10) { + } else if (currentConfig.EmuOpt&0x80) { + PicoDrawSetColorFormat(1); + PicoScan = EmuScan16; + } else { + PicoDrawSetColorFormat(0); + PicoScan = EmuScan8; + } + if ((PicoOpt&0x10)||!(currentConfig.EmuOpt&0x80)) { + // setup pal for 8-bit modes + localPal[0xc0] = 0x0600; + localPal[0xd0] = 0xc000; + localPal[0xe0] = 0x0000; // reserved pixels for OSD + localPal[0xf0] = 0xffff; + } + Pico.m.dirtyPal = 1; + screen = Framework2D_LockBuffer(); + memset32(screen, 0, 320*240*2/4); + Framework2D_UnlockBuffer(); + giz_screen = NULL; +} + + +static void SkipFrame(int do_audio) +{ + PicoSkipFrame=do_audio ? 1 : 2; + PicoFrame(); + PicoSkipFrame=0; +} + +void emu_forcedFrame(void) +{ + // TODO +} + +static void updateKeys(void) +{ +} + +static void simpleWait(DWORD until) +{ +} + +void emu_Loop(void) +{ + //static int PsndRate_old = 0, PicoOpt_old = 0, PsndLen_real = 0, pal_old = 0; + char fpsbuff[24]; // fps count c string + DWORD tval, tval_prev = 0, tval_thissec = 0; // timing + int frames_done = 0, frames_shown = 0, oldmodes = 0; + int target_fps, target_frametime, lim_time, tval_diff, i; + char *notice = NULL; + + lprintf("entered emu_Loop()\n"); + + fpsbuff[0] = 0; + + // make sure we are in correct mode + vidResetMode(); + if (currentConfig.scaling) PicoOpt|=0x4000; + else PicoOpt&=~0x4000; + Pico.m.dirtyPal = 1; + oldmodes = ((Pico.video.reg[12]&1)<<2) ^ 0xc; + //find_combos(); // TODO + + // pal/ntsc might have changed, reset related stuff + target_fps = Pico.m.pal ? 50 : 60; + target_frametime = (1000<<8)/target_fps; + reset_timing = 1; + + // prepare sound stuff +/* if (currentConfig.EmuOpt & 4) { + int snd_excess_add; + if (PsndRate != PsndRate_old || (PicoOpt&0x0b) != (PicoOpt_old&0x0b) || Pico.m.pal != pal_old) { + sound_rerate(Pico.m.frame_count ? 1 : 0); + } + snd_excess_add = ((PsndRate - PsndLen*target_fps)<<16) / target_fps; + lprintf("starting audio: %i len: %i (ex: %04x) stereo: %i, pal: %i\n", + PsndRate, PsndLen, snd_excess_add, (PicoOpt&8)>>3, Pico.m.pal); + gp2x_start_sound(PsndRate, 16, (PicoOpt&8)>>3); + gp2x_sound_volume(currentConfig.volume, currentConfig.volume); + PicoWriteSound = updateSound; + memset(sndBuffer, 0, sizeof(sndBuffer)); + PsndOut = sndBuffer; + PsndRate_old = PsndRate; + PsndLen_real = PsndLen; + PicoOpt_old = PicoOpt; + pal_old = Pico.m.pal; + } else*/ { + PsndOut = 0; + } + + // prepare CD buffer + if (PicoMCD & 1) PicoCDBufferInit(); + + // loop? + while (engineState == PGS_Running) + { + int modes; + + tval = GetTickCount(); + if (reset_timing || tval < tval_prev) { + reset_timing = 0; + tval_thissec = tval; + frames_shown = frames_done = 0; + } + + // show notice message? + if (noticeMsgTime) { + static int noticeMsgSum; + if (tval - noticeMsgTime > 2000) { // > 2.0 sec + noticeMsgTime = 0; + clearArea(0); + notice = 0; + } else { + int sum = noticeMsg[0]+noticeMsg[1]+noticeMsg[2]; + if (sum != noticeMsgSum) { clearArea(0); noticeMsgSum = sum; } + notice = noticeMsg; + } + } + + // check for mode changes + modes = ((Pico.video.reg[12]&1)<<2)|(Pico.video.reg[1]&8); + if (modes != oldmodes) { + osd_fps_x = OSD_FPS_X; + //if (modes & 4) + vidCpy8to16 = vidCpy8to16_40; + //else + // vidCpy8to16 = vidCpy8to16_32col; + oldmodes = modes; + clearArea(1); + } + + // second passed? + if (tval - tval_thissec >= 1000) + { +#ifdef BENCHMARK + static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4]; + if(++bench == 10) { + bench = 0; + bench_fps_s = bench_fps; + bf[bfp++ & 3] = bench_fps; + bench_fps = 0; + } + bench_fps += frames_shown; + sprintf(fpsbuff, "%02i/%02i/%02i", frames_shown, bench_fps_s, (bf[0]+bf[1]+bf[2]+bf[3])>>2); +#else + if(currentConfig.EmuOpt & 2) + sprintf(fpsbuff, "%02i/%02i", frames_shown, frames_done); +#endif + tval_thissec = tval; + + if (PsndOut == 0 && currentConfig.Frameskip >= 0) { + frames_done = frames_shown = 0; + } else { + // it is quite common for this implementation to leave 1 fame unfinished + // when second changes, but we don't want buffer to starve. + if (PsndOut && frames_done < target_fps && frames_done > target_fps-5) { + updateKeys(); + SkipFrame(1); frames_done++; + } + + frames_done -= target_fps; if (frames_done < 0) frames_done = 0; + frames_shown -= target_fps; if (frames_shown < 0) frames_shown = 0; + if (frames_shown > frames_done) frames_shown = frames_done; + } + } +#ifdef PFRAMES + sprintf(fpsbuff, "%i", Pico.m.frame_count); +#endif + + tval_prev = tval; + lim_time = (frames_done+1) * target_frametime; + if (currentConfig.Frameskip >= 0) // frameskip enabled + { + for (i = 0; i < currentConfig.Frameskip; i++) { + updateKeys(); + SkipFrame(1); frames_done++; + if (PsndOut) { // do framelimitting if sound is enabled + int tval_diff; + tval = GetTickCount(); + tval_diff = (int)(tval - tval_thissec) << 8; + if (tval_diff < lim_time) // we are too fast + simpleWait(tval + ((lim_time - tval_diff)>>8)); + } + lim_time += target_frametime; + } + } + else // auto frameskip + { + int tval_diff; + tval = GetTickCount(); + tval_diff = (int)(tval - tval_thissec) << 8; + if (tval_diff > lim_time) + { + // no time left for this frame - skip + if (tval_diff - lim_time >= (300<<8)) { + /* something caused a slowdown for us (disk access? cache flush?) + * try to recover by resetting timing... */ + reset_timing = 1; + continue; + } + updateKeys(); + SkipFrame(tval_diff < lim_time+target_frametime*2); frames_done++; + continue; + } + } + + updateKeys(); + + if (giz_screen == NULL) + giz_screen = Framework2D_LockBuffer(); + + PicoFrame(); + blit(fpsbuff, notice); + + if (giz_screen != NULL) { + Framework2D_UnlockBuffer(); + giz_screen = NULL; + } + + // check time + tval = GetTickCount(); + tval_diff = (int)(tval - tval_thissec) << 8; + + if (currentConfig.Frameskip < 0 && tval_diff - lim_time >= (300<<8)) // slowdown detection + reset_timing = 1; + else if (PsndOut != NULL || currentConfig.Frameskip < 0) + { + // sleep if we are still too fast + if (tval_diff < lim_time) + { + // we are too fast + simpleWait(tval + ((lim_time - tval_diff) >> 8)); + } + } + + frames_done++; frames_shown++; + } + + + if (PicoMCD & 1) PicoCDBufferFree(); + + // save SRAM + if ((currentConfig.EmuOpt & 1) && SRam.changed) { + emu_state_cb("Writing SRAM/BRAM.."); + emu_SaveLoadGame(0, 1); + SRam.changed = 0; + } +} + + +void emu_ResetGame(void) +{ + PicoReset(0); + reset_timing = 1; +} diff --git a/platform/gizmondo/emu.h b/platform/gizmondo/emu.h index defa5e6..86ab426 100644 --- a/platform/gizmondo/emu.h +++ b/platform/gizmondo/emu.h @@ -16,44 +16,14 @@ enum TPicoGameState { PGS_RestartRun, }; -typedef struct { - char lastRomFile[512]; - int EmuOpt; // LSb->MSb: use_sram, show_fps, enable_sound, gzip_saves, - // , no_save_cfg_on_exit, , 16_bit_mode - // , confirm_save, show_cd_leds, confirm_load - // , - int PicoOpt; // used for config saving only, see Pico.h - int PsndRate; // ditto - int PicoRegion; // ditto - int Frameskip; - int CPUclock; // unused, placeholder for config compatibility - int KeyBinds[32]; - int volume; - int gamma; // unused - int JoyBinds[4][32]; // unused - int PicoAutoRgnOrder; - int PicoCDBuffers; - int scaling; // unused -} currentConfig_t; - +extern unsigned char gfx_buffer[321*240*2*2]; 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 no_defaults); -int emu_WriteConfig(int game); -char *emu_GetSaveFName(int load, int is_sram, int slot); -int emu_check_save_file(int slot); -void emu_set_save_cbs(int gz); -void emu_forced_frame(void); -int emu_cd_check(int *pregion); -int find_bios(int region, char **bios_file); -void scaling_update(void); +void emu_forcedFrame(void); diff --git a/platform/gizmondo/giz.c b/platform/gizmondo/giz.c index 16bad7a..25f5d58 100644 --- a/platform/gizmondo/giz.c +++ b/platform/gizmondo/giz.c @@ -43,8 +43,6 @@ void giz_init(HINSTANCE hInstance, HINSTANCE hPrevInstance) { int ret; - giz_screen = NULL; - lprintf("PicoDrive v" VERSION " (c) notaz, 2006,2007\n"); lprintf("%s %s\n\n", __DATE__, __TIME__); @@ -60,6 +58,17 @@ void giz_init(HINSTANCE hInstance, HINSTANCE hPrevInstance) lprintf_al("Framework2D_Init() failed\n"); exit(1); } + + // test screen + giz_screen = Framework2D_LockBuffer(); + if (giz_screen == NULL) + { + lprintf_al("Framework2D_LockBuffer() failed\n"); + exit(1); + } + lprintf("Framework2D_LockBuffer returned %p\n", giz_screen); + Framework2D_UnlockBuffer(); + giz_screen = NULL; } void giz_deinit(void) diff --git a/platform/gizmondo/main.c b/platform/gizmondo/main.c index 21216b7..8038a94 100644 --- a/platform/gizmondo/main.c +++ b/platform/gizmondo/main.c @@ -7,8 +7,9 @@ #include "giz.h" #include "menu.h" -#include "../common/menu.h" #include "emu.h" +#include "../common/menu.h" +#include "../common/emu.h" #include "version.h" diff --git a/platform/gizmondo/menu.c b/platform/gizmondo/menu.c index 74bb6e1..5e4aa8f 100644 --- a/platform/gizmondo/menu.c +++ b/platform/gizmondo/menu.c @@ -19,6 +19,7 @@ #include "menu.h" #include "../common/arm_utils.h" #include "../common/menu.h" +#include "../common/emu.h" #include "../common/readpng.h" #include "version.h" #include "kgsdk/Framework.h" @@ -28,22 +29,17 @@ #include #include -extern char romFileName[MAX_PATH]; -extern char *rom_data; -extern int state_slot; -extern int config_slot, config_slot_current; #define gizKeyUnkn "???" static const char * const gizKeyNames[] = { "LEFT", "RIGHT", "UP", "DOWN", "STOP", "PLAY", "FORWARD", "REWIND", "LEFT_SHOULDER", "RIGHT_SHOULDER", "HOME", "VOLUME", "BRIGHTNESS", "ALARM", "POWER", gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, - gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, + gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn, gizKeyUnkn }; -static unsigned char bg_buffer[321*240*2]; -unsigned char menu_screen[321*240*2]; /* draw here and blit later, to avoid flicker */ -char menuErrorMsg[40] = {0, }; +static unsigned char *bg_buffer = gfx_buffer + 321*240*2; +unsigned char *menu_screen = gfx_buffer; /* draw here and blit later, to avoid flicker */ static void menu_darken_bg(void *dst, const void *src, int pixels, int darker); static void menu_prepare_bg(int use_game_bg); @@ -502,7 +498,7 @@ static void state_check_slots(void) for (slot = 0; slot < 10; slot++) { - if (emu_check_save_file(slot)) + if (emu_checkSaveFile(slot)) { state_slot_flags |= 1 << slot; } @@ -530,10 +526,10 @@ static void draw_savestate_bg(int slot) if (strcmp(fname + strlen(fname) - 3, ".gz") == 0) { file = gzopen(fname, "rb"); - emu_set_save_cbs(1); + emu_setSaveStateCbs(1); } else { file = fopen(fname, "rb"); - emu_set_save_cbs(0); + emu_setSaveStateCbs(0); } if (file) { @@ -551,7 +547,7 @@ static void draw_savestate_bg(int slot) areaClose(file); } - emu_forced_frame(); + emu_forcedFrame(); menu_prepare_bg(1); memcpy(Pico.vram, tmp_vram, sizeof(Pico.vram)); @@ -888,17 +884,17 @@ static void cd_menu_loop_options(void) menu_id selected_id; char *bios, *p; - if (find_bios(4, &bios)) { // US + if (emu_findBios(4, &bios)) { // US for (p = bios+strlen(bios)-1; p > bios && *p != '/'; p--); p++; strncpy(bios_names.us, p, sizeof(bios_names.us)); bios_names.us[sizeof(bios_names.us)-1] = 0; } else strcpy(bios_names.us, "NOT FOUND"); - if (find_bios(8, &bios)) { // EU + if (emu_findBios(8, &bios)) { // EU for (p = bios+strlen(bios)-1; p > bios && *p != '/'; p--); p++; strncpy(bios_names.eu, p, sizeof(bios_names.eu)); bios_names.eu[sizeof(bios_names.eu)-1] = 0; } else strcpy(bios_names.eu, "NOT FOUND"); - if (find_bios(1, &bios)) { // JP + if (emu_findBios(1, &bios)) { // JP for (p = bios+strlen(bios)-1; p > bios && *p != '/'; p--); p++; strncpy(bios_names.jp, p, sizeof(bios_names.jp)); bios_names.jp[sizeof(bios_names.jp)-1] = 0; } else strcpy(bios_names.jp, "NOT FOUND"); @@ -930,21 +926,21 @@ static void cd_menu_loop_options(void) } switch (selected_id) { // BIOS testers case MA_CDOPT_TESTBIOS_USA: - if (find_bios(4, &bios)) { // test US + if (emu_findBios(4, &bios)) { // test US strcpy(romFileName, bios); engineState = PGS_ReloadRom; return; } break; case MA_CDOPT_TESTBIOS_EUR: - if (find_bios(8, &bios)) { // test EU + if (emu_findBios(8, &bios)) { // test EU strcpy(romFileName, bios); engineState = PGS_ReloadRom; return; } break; case MA_CDOPT_TESTBIOS_JAP: - if (find_bios(1, &bios)) { // test JP + if (emu_findBios(1, &bios)) { // test JP strcpy(romFileName, bios); engineState = PGS_ReloadRom; return; @@ -1188,7 +1184,6 @@ static void menu_options_save(void) // unbind XYZ MODE, just in case unbind_action(0xf00); } - scaling_update(); } static int menu_loop_options(void) @@ -1617,7 +1612,7 @@ int menu_loop_tray(void) selfname = romsel_loop(curr_path); if (selfname) { int ret = -1, cd_type; - cd_type = emu_cd_check(NULL); + cd_type = emu_cdCheck(NULL); if (cd_type > 0) ret = Insert_CD(romFileName, cd_type == 2); if (ret != 0) { diff --git a/platform/gizmondo/menu.h b/platform/gizmondo/menu.h index ae1bccd..7784da9 100644 --- a/platform/gizmondo/menu.h +++ b/platform/gizmondo/menu.h @@ -3,8 +3,6 @@ // For commercial use, separate licencing terms must be obtained. -extern char menuErrorMsg[40]; - void menu_init(void); void text_out16(int x, int y, const char *texto, ...); void menu_loop(void); diff --git a/platform/gizmondo/port_config.h b/platform/gizmondo/port_config.h index a6a15af..3bf29f7 100644 --- a/platform/gizmondo/port_config.h +++ b/platform/gizmondo/port_config.h @@ -5,6 +5,9 @@ #define CPU_CALL +// draw.c +#define OVERRIDE_HIGHCOL 1 + // draw2.c #define START_ROW 0 // which row of tiles to start rendering at? #define END_ROW 28 // ..end diff --git a/platform/gizmondo/port_config.s b/platform/gizmondo/port_config.s index 89c44d9..99cd249 100644 --- a/platform/gizmondo/port_config.s +++ b/platform/gizmondo/port_config.s @@ -1,10 +1,13 @@ @ vim:filetype=armasm -@ .equiv START_ROW, 1 -@ .equiv END_ROW, 27 +@ .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 +.equiv START_ROW, 0 +.equiv END_ROW, 28 + +.equiv OVERRIDE_HIGHCOL, 1 @ this should be set to one only for GP2X port -.equiv EXTERNAL_YM2612, 0 +.equiv EXTERNAL_YM2612, 0 + diff --git a/platform/gp2x/940ctl.c b/platform/gp2x/940ctl.c index 9498858..0cbdb1c 100644 --- a/platform/gp2x/940ctl.c +++ b/platform/gp2x/940ctl.c @@ -17,6 +17,7 @@ #include "mp3.h" #include "../common/arm_utils.h" #include "../common/menu.h" +#include "../common/emu.h" #include "../../Pico/PicoInt.h" #include "../../Pico/sound/ym2612.h" #include "../../Pico/sound/mix.h" diff --git a/platform/gp2x/Makefile b/platform/gp2x/Makefile index 1458a34..65565f1 100644 --- a/platform/gp2x/Makefile +++ b/platform/gp2x/Makefile @@ -58,7 +58,7 @@ OBJS += main.o menu.o gp2x.o usbjoy.o emu.o squidgehack.o cpuctrl.o OBJS += 940ctl.o # common -OBJS += ../common/menu.o ../common/fonts.o ../common/arm_utils.o ../common/readpng.o +OBJS += ../common/emu.o ../common/menu.o ../common/fonts.o ../common/arm_utils.o ../common/readpng.o # Pico ifeq "$(amalgamate)" "1" @@ -183,7 +183,7 @@ testrefr.gpe : test.o gp2x.o ../../Pico/sound/mix_asm.o : ../../Pico/sound/mix.s @echo $< @$(AS) $(ASOPT) $< -o $@ -../../Pico/misc_asm.o : ../../Pico/misc.s +../../Pico/misc_asm.o : ../../Pico/Misc.s @echo $< @$(AS) $(ASOPT) $< -o $@ ../../Pico/cd/pico_asm.o : ../../Pico/cd/Pico.s @@ -192,7 +192,7 @@ testrefr.gpe : test.o gp2x.o ../../Pico/cd/memory_asm.o : ../../Pico/cd/Memory.s @echo $< @$(AS) $(ASOPT) $< -o $@ -../../Pico/cd/misc_asm.o : ../../Pico/cd/misc.s +../../Pico/cd/misc_asm.o : ../../Pico/cd/Misc.s @echo $< @$(AS) $(ASOPT) $< -o $@ diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 9615013..63b2d04 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -20,6 +20,7 @@ #include "menu.h" #include "../common/arm_utils.h" #include "../common/fonts.h" +#include "../common/emu.h" #include "cpuctrl.h" #include @@ -37,366 +38,42 @@ int engineState; int select_exits = 0; -char *PicoConfigFile = "picoconfig.bin"; -currentConfig_t currentConfig; char romFileName[PATH_MAX]; -unsigned char *rom_data = NULL; extern int crashed_940; static short sndBuffer[2*44100/50]; -static char noticeMsg[64]; // notice msg to draw static struct timeval noticeMsgTime = { 0, 0 }; // when started showing static int osd_fps_x; static int combo_keys = 0, combo_acts = 0; // keys and actions which need button combos static int gp2x_old_gamma = 100; -static unsigned char *movie_data = NULL; -static int movie_size = 0; +char noticeMsg[64]; // notice msg to draw unsigned char *PicoDraw2FB = NULL; // temporary buffer for alt renderer -int state_slot = 0; int reset_timing = 0; -int config_slot = 0, config_slot_current = 0; +static void emu_msg_cb(const char *msg); +static void emu_msg_tray_open(void); -// utilities -static void strlwr(char* string) -{ - while ( (*string++ = (char)tolower(*string)) ); -} -static int try_rfn_cut(void) +void emu_noticeMsgUpdated(void) { - FILE *tmp; - char *p; - - p = romFileName + strlen(romFileName) - 1; - for (; p > romFileName; p--) - if (*p == '.') break; - *p = 0; - - if((tmp = fopen(romFileName, "rb"))) { - fclose(tmp); - return 1; - } - return 0; + gettimeofday(¬iceMsgTime, 0); } -static void get_ext(char *file, char *ext) +void emu_getMainDir(char *dst, int len) { - char *p; + extern char **g_argv; + int j; - p = file + strlen(file) - 4; - if (p < file) p = file; - strncpy(ext, p, 4); - ext[4] = 0; - strlwr(ext); + strncpy(dst, g_argv[0], len); + len -= 32; // reserve + if (len < 0) len = 0; + dst[len] = 0; + for (j = strlen(dst); j > 0; j--) + if (dst[j] == '/') { dst[j+1] = 0; break; } } -char *biosfiles_us[] = { "us_scd2_9306", "SegaCDBIOS9303", "us_scd1_9210" }; -char *biosfiles_eu[] = { "eu_mcd2_9306", "eu_mcd2_9303", "eu_mcd1_9210" }; -char *biosfiles_jp[] = { "jp_mcd1_9112", "jp_mcd1_9111" }; - -extern char **g_argv; - -int find_bios(int region, char **bios_file) -{ - static char bios_path[1024]; - int i, j, count; - char **files; - FILE *f = NULL; - - if (region == 4) { // US - files = biosfiles_us; - count = sizeof(biosfiles_us) / sizeof(char *); - } else if (region == 8) { // EU - files = biosfiles_eu; - count = sizeof(biosfiles_eu) / sizeof(char *); - } else if (region == 1 || region == 2) { - files = biosfiles_jp; - count = sizeof(biosfiles_jp) / sizeof(char *); - } else { - return 0; - } - - for (i = 0; i < count; i++) - { - strncpy(bios_path, g_argv[0], 1023); - bios_path[1024-32] = 0; - for (j = strlen(bios_path); j > 0; j--) - if (bios_path[j] == '/') { bios_path[j+1] = 0; break; } - strcat(bios_path, files[i]); - strcat(bios_path, ".bin"); - f = fopen(bios_path, "rb"); - if (f) break; - - bios_path[strlen(bios_path) - 4] = 0; - strcat(bios_path, ".zip"); - f = fopen(bios_path, "rb"); - if (f) break; - } - - if (f) { - printf("using bios: %s\n", bios_path); - fclose(f); - if (bios_file) *bios_file = bios_path; - return 1; - } else { - sprintf(menuErrorMsg, "no %s BIOS files found, read docs", - region != 4 ? (region == 8 ? "EU" : "JAP") : "USA"); - printf("%s\n", menuErrorMsg); - return 0; - } -} - -/* checks if romFileName points to valid MegaCD image - * if so, checks for suitable BIOS */ -int emu_cd_check(int *pregion) -{ - unsigned char buf[32]; - pm_file *cd_f; - int type = 0, region = 4; // 1: Japan, 4: US, 8: Europe - - cd_f = pm_open(romFileName); - if (!cd_f) return 0; // let the upper level handle this - - if (pm_read(buf, 32, cd_f) != 32) { - pm_close(cd_f); - return 0; - } - - if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x00, 14)) type = 1; // Sega CD (ISO) - if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x10, 14)) type = 2; // Sega CD (BIN) - if (type == 0) { - pm_close(cd_f); - return 0; - } - - /* it seems we have a CD image here. Try to detect region now.. */ - pm_seek(cd_f, (type == 1) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET); - pm_read(buf, 1, cd_f); - pm_close(cd_f); - - if (buf[0] == 0x64) region = 8; // EU - if (buf[0] == 0xa1) region = 1; // JAP - - printf("detected %s Sega/Mega CD image with %s region\n", - type == 2 ? "BIN" : "ISO", region != 4 ? (region == 8 ? "EU" : "JAP") : "USA"); - - if (pregion != NULL) *pregion = region; - - return type; -} - -int emu_ReloadRom(void) -{ - unsigned int rom_size = 0; - char *used_rom_name = romFileName; - char ext[5]; - pm_file *rom; - int ret, cd_state, cd_region, cfg_loaded = 0; - - printf("emu_ReloadRom(%s)\n", romFileName); - - get_ext(romFileName, ext); - - // detect wrong extensions - if(!strcmp(ext, ".srm") || !strcmp(ext, "s.gz") || !strcmp(ext, ".mds")) { // s.gz ~ .mds.gz - sprintf(menuErrorMsg, "Not a ROM selected."); - return 0; - } - - PicoPatchUnload(); - - // check for movie file - if(movie_data) { - free(movie_data); - movie_data = 0; - } - if(!strcmp(ext, ".gmv")) { - // check for both gmv and rom - int dummy; - FILE *movie_file = fopen(romFileName, "rb"); - if(!movie_file) { - sprintf(menuErrorMsg, "Failed to open movie."); - return 0; - } - fseek(movie_file, 0, SEEK_END); - movie_size = ftell(movie_file); - fseek(movie_file, 0, SEEK_SET); - if(movie_size < 64+3) { - sprintf(menuErrorMsg, "Invalid GMV file."); - fclose(movie_file); - return 0; - } - movie_data = malloc(movie_size); - if(movie_data == NULL) { - sprintf(menuErrorMsg, "low memory."); - fclose(movie_file); - return 0; - } - fread(movie_data, 1, movie_size, movie_file); - fclose(movie_file); - if (strncmp((char *)movie_data, "Gens Movie TEST", 15) != 0) { - sprintf(menuErrorMsg, "Invalid GMV file."); - return 0; - } - dummy = try_rfn_cut() || try_rfn_cut(); - if (!dummy) { - sprintf(menuErrorMsg, "Could't find a ROM for movie."); - return 0; - } - get_ext(romFileName, ext); - } - else if (!strcmp(ext, ".pat")) { - int dummy; - PicoPatchLoad(romFileName); - dummy = try_rfn_cut() || try_rfn_cut(); - if (!dummy) { - sprintf(menuErrorMsg, "Could't find a ROM to patch."); - return 0; - } - get_ext(romFileName, ext); - } - - if ((PicoMCD & 1) && Pico_mcd != NULL) - Stop_CD(); - - // check for MegaCD image - cd_state = emu_cd_check(&cd_region); - if (cd_state > 0) - { - // valid CD image, check for BIOS.. - - // we need to have config loaded at this point - ret = emu_ReadConfig(1, 1); - if (!ret) emu_ReadConfig(0, 1); - cfg_loaded = 1; - - if (PicoRegionOverride) { - cd_region = PicoRegionOverride; - printf("overrided region to %s\n", cd_region != 4 ? (cd_region == 8 ? "EU" : "JAP") : "USA"); - } - if (!find_bios(cd_region, &used_rom_name)) { - // bios_help() ? - return 0; - } - - PicoMCD |= 1; - get_ext(used_rom_name, ext); - } - else - { - if (PicoMCD & 1) Stop_CD(); - PicoMCD &= ~1; - } - - rom = pm_open(used_rom_name); - if(!rom) { - sprintf(menuErrorMsg, "Failed to open rom."); - return 0; - } - - menu_romload_prepare(used_rom_name); - - if(rom_data) { - free(rom_data); - rom_data = 0; - rom_size = 0; - } - - if( (ret = PicoCartLoad(rom, &rom_data, &rom_size)) ) { - sprintf(menuErrorMsg, "PicoCartLoad() failed."); - printf("%s\n", menuErrorMsg); - pm_close(rom); - menu_romload_end(); - return 0; - } - pm_close(rom); - menu_romload_end(); - - // detect wrong files (Pico crashes on very small files), also see if ROM EP is good - if(rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 || - ((*(unsigned char *)(rom_data+4)<<16)|(*(unsigned short *)(rom_data+6))) >= (int)rom_size) { - if (rom_data) free(rom_data); - rom_data = 0; - sprintf(menuErrorMsg, "Not a ROM selected."); - return 0; - } - - // load config for this ROM (do this before insert to get correct region) - if (!cfg_loaded) { - ret = emu_ReadConfig(1, 1); - if (!ret) emu_ReadConfig(0, 1); - } - - printf("PicoCartInsert(%p, %d);\n", rom_data, rom_size); - if(PicoCartInsert(rom_data, rom_size)) { - sprintf(menuErrorMsg, "Failed to load ROM."); - return 0; - } - - Pico.m.frame_count = 0; - - // insert CD if it was detected - if (cd_state > 0) { - ret = Insert_CD(romFileName, cd_state == 2); - if (ret != 0) { - sprintf(menuErrorMsg, "Insert_CD() failed, invalid CD image?"); - printf("%s\n", menuErrorMsg); - return 0; - } - } - - // emu_ReadConfig() might have messed currentConfig.lastRomFile - strncpy(currentConfig.lastRomFile, romFileName, sizeof(currentConfig.lastRomFile)-1); - currentConfig.lastRomFile[sizeof(currentConfig.lastRomFile)-1] = 0; - - if (PicoPatches) { - PicoPatchPrepare(); - PicoPatchApply(); - } - - // additional movie stuff - if (movie_data) { - if(movie_data[0x14] == '6') - PicoOpt |= 0x20; // 6 button pad - else PicoOpt &= ~0x20; - PicoOpt |= 0x10040; // accurate timing, no VDP fifo timing - if(movie_data[0xF] >= 'A') { - if(movie_data[0x16] & 0x80) { - PicoRegionOverride = 8; - } else { - PicoRegionOverride = 4; - } - PicoReset(0); - // TODO: bits 6 & 5 - } - movie_data[0x18+30] = 0; - sprintf(noticeMsg, "MOVIE: %s", (char *) &movie_data[0x18]); - } - else - { - PicoOpt &= ~0x10000; - if(Pico.m.pal) { - strcpy(noticeMsg, "PAL SYSTEM / 50 FPS"); - } else { - strcpy(noticeMsg, "NTSC SYSTEM / 60 FPS"); - } - } - gettimeofday(¬iceMsgTime, 0); - - // load SRAM for this ROM - if(currentConfig.EmuOpt & 1) - emu_SaveLoadGame(1, 1); - - return 1; -} - - -static void emu_msg_cb(const char *msg); -static void emu_msg_tray_open(void); - void emu_Init(void) { // make temp buffer for alt renderer @@ -419,25 +96,6 @@ void emu_Init(void) } -static void romfname_ext(char *dst, const char *prefix, const char *ext) -{ - char *p; - int prefix_len = 0; - - // make save filename - for (p = romFileName+strlen(romFileName)-1; p >= romFileName && *p != '/'; p--); p++; - *dst = 0; - if (prefix) { - strcpy(dst, prefix); - prefix_len = strlen(prefix); - } - strncpy(dst + prefix_len, p, 511-prefix_len); - dst[511-8] = 0; - if (dst[strlen(dst)-4] == '.') dst[strlen(dst)-4] = 0; - if (ext) strcat(dst, ext); -} - - static void find_combos(void) { int act, u; @@ -468,7 +126,7 @@ static void find_combos(void) } -void scaling_update(void) +static void scaling_update(void) { PicoOpt &= ~0x4100; switch (currentConfig.scaling) { @@ -480,138 +138,6 @@ void scaling_update(void) } -int emu_ReadConfig(int game, int no_defaults) -{ - FILE *f; - char cfg[512], extbuf[16]; - int bread = 0; - - if (!game) - { - if (!no_defaults) - { - // set default config - memset(¤tConfig, 0, sizeof(currentConfig)); - currentConfig.lastRomFile[0] = 0; - currentConfig.EmuOpt = 0x1f | 0x600; // | confirm_save, cd_leds - currentConfig.PicoOpt = 0x0f | 0xe00; // | use_940, cd_pcm, cd_cdda - currentConfig.PsndRate = 22050; // 44100; - currentConfig.PicoRegion = 0; // auto - currentConfig.PicoAutoRgnOrder = 0x184; // US, EU, JP - currentConfig.Frameskip = -1; // auto - currentConfig.CPUclock = 200; - currentConfig.volume = 50; - currentConfig.KeyBinds[ 0] = 1<<0; // SACB RLDU - currentConfig.KeyBinds[ 4] = 1<<1; - currentConfig.KeyBinds[ 2] = 1<<2; - currentConfig.KeyBinds[ 6] = 1<<3; - currentConfig.KeyBinds[14] = 1<<4; - currentConfig.KeyBinds[13] = 1<<5; - currentConfig.KeyBinds[12] = 1<<6; - currentConfig.KeyBinds[ 8] = 1<<7; - currentConfig.KeyBinds[15] = 1<<26; // switch rend - currentConfig.KeyBinds[10] = 1<<27; // save state - currentConfig.KeyBinds[11] = 1<<28; // load state - currentConfig.KeyBinds[23] = 1<<29; // vol up - currentConfig.KeyBinds[22] = 1<<30; // vol down - currentConfig.gamma = 100; - currentConfig.PicoCDBuffers = 64; - currentConfig.scaling = 0; - } - strncpy(cfg, PicoConfigFile, 511); - if (config_slot != 0) - { - char *p = strrchr(cfg, '.'); - if (p == NULL) p = cfg + strlen(cfg); - sprintf(extbuf, ".%i.pbcfg", config_slot); - strncpy(p, extbuf, 511 - (p - cfg)); - } - cfg[511] = 0; - } else { - if (config_slot != 0) - sprintf(extbuf, ".%i.pbcfg", config_slot); - else strcpy(extbuf, ".pbcfg"); - romfname_ext(cfg, "cfg/", extbuf); - f = fopen(cfg, "rb"); - if (!f) romfname_ext(cfg, NULL, ".pbcfg"); - else fclose(f); - } - - printf("emu_ReadConfig: %s ", cfg); - f = fopen(cfg, "rb"); - if (f) { - bread = fread(¤tConfig, 1, sizeof(currentConfig), f); - fclose(f); - } - printf(bread > 0 ? "(ok)\n" : "(failed)\n"); - - PicoOpt = currentConfig.PicoOpt; - PsndRate = currentConfig.PsndRate; - PicoRegionOverride = currentConfig.PicoRegion; - PicoAutoRgnOrder = currentConfig.PicoAutoRgnOrder; - PicoCDBuffers = currentConfig.PicoCDBuffers; - scaling_update(); - // some sanity checks - if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200; - if (currentConfig.gamma < 10 || currentConfig.gamma > 300) currentConfig.gamma = 100; - if (currentConfig.volume < 0 || currentConfig.volume > 99) currentConfig.volume = 50; - // if volume keys are unbound, bind them to volume control - if (!currentConfig.KeyBinds[23] && !currentConfig.KeyBinds[22]) { - currentConfig.KeyBinds[23] = 1<<29; // vol up - currentConfig.KeyBinds[22] = 1<<30; // vol down - } - - if (bread > 0) config_slot_current = config_slot; - return (bread > 0); // == sizeof(currentConfig)); -} - - -int emu_WriteConfig(int game) -{ - FILE *f; - char cfg[512], extbuf[16]; - int bwrite = 0; - - if (!game) - { - strncpy(cfg, PicoConfigFile, 511); - if (config_slot != 0) - { - char *p = strrchr(cfg, '.'); - if (p == NULL) p = cfg + strlen(cfg); - sprintf(extbuf, ".%i.pbcfg", config_slot); - strncpy(p, extbuf, 511 - (p - cfg)); - } - cfg[511] = 0; - } else { - if (config_slot != 0) - sprintf(extbuf, ".%i.pbcfg", config_slot); - else strcpy(extbuf, ".pbcfg"); - romfname_ext(cfg, "cfg/", extbuf); - } - - printf("emu_WriteConfig: %s ", cfg); - f = fopen(cfg, "wb"); - if (f) { - currentConfig.PicoOpt = PicoOpt; - currentConfig.PsndRate = PsndRate; - currentConfig.PicoRegion = PicoRegionOverride; - currentConfig.PicoAutoRgnOrder = PicoAutoRgnOrder; - currentConfig.PicoCDBuffers = PicoCDBuffers; - bwrite = fwrite(¤tConfig, 1, sizeof(currentConfig), f); - fflush(f); - fclose(f); -#ifndef NO_SYNC - sync(); -#endif - } - printf((bwrite == sizeof(currentConfig)) ? "(ok)\n" : "(failed)\n"); - - if (bwrite == sizeof(currentConfig)) config_slot_current = config_slot; - return (bwrite == sizeof(currentConfig)); -} - - void emu_Deinit(void) { // save SRAM @@ -646,54 +172,36 @@ void emu_Deinit(void) set_gamma(100, 0); } -static void text_out8_builtin(int x, int y, const char *text) -{ - int i,l,len=strlen(text); - unsigned char *screen = (unsigned char *)gp2x_screen + x + y*320; - - /* always using built-in font */ - for (i = 0; i < len; i++) - { - for (l=0;l<8;l++) - { - unsigned char fd = fontdata8x8[((text[i])*8)+l]; - if (fd&0x80) screen[l*320+0]=0xf0; - if (fd&0x40) screen[l*320+1]=0xf0; - if (fd&0x20) screen[l*320+2]=0xf0; - if (fd&0x10) screen[l*320+3]=0xf0; - if (fd&0x08) screen[l*320+4]=0xf0; - if (fd&0x04) screen[l*320+5]=0xf0; - if (fd&0x02) screen[l*320+6]=0xf0; - if (fd&0x01) screen[l*320+7]=0xf0; - } - screen += 8; - } -} - -static void text_out16_builtin(int x, int y, const char *text) -{ - int i,l,len=strlen(text); - unsigned short *screen = (unsigned short *)gp2x_screen + x + y*320; - - for (i = 0; i < len; i++) - { - for (l=0;l<8;l++) - { - unsigned char fd = fontdata8x8[((text[i])*8)+l]; - if(fd&0x80) screen[l*320+0]=0xffff; - if(fd&0x40) screen[l*320+1]=0xffff; - if(fd&0x20) screen[l*320+2]=0xffff; - if(fd&0x10) screen[l*320+3]=0xffff; - if(fd&0x08) screen[l*320+4]=0xffff; - if(fd&0x04) screen[l*320+5]=0xffff; - if(fd&0x02) screen[l*320+6]=0xffff; - if(fd&0x01) screen[l*320+7]=0xffff; - } - screen += 8; - } +void emu_setDefaultConfig(void) +{ + memset(¤tConfig, 0, sizeof(currentConfig)); + currentConfig.lastRomFile[0] = 0; + currentConfig.EmuOpt = 0x1f | 0x600; // | confirm_save, cd_leds + currentConfig.PicoOpt = 0x0f | 0xe00; // | use_940, cd_pcm, cd_cdda + currentConfig.PsndRate = 22050; // 44100; + currentConfig.PicoRegion = 0; // auto + currentConfig.PicoAutoRgnOrder = 0x184; // US, EU, JP + currentConfig.Frameskip = -1; // auto + currentConfig.CPUclock = 200; + currentConfig.volume = 50; + currentConfig.KeyBinds[ 0] = 1<<0; // SACB RLDU + currentConfig.KeyBinds[ 4] = 1<<1; + currentConfig.KeyBinds[ 2] = 1<<2; + currentConfig.KeyBinds[ 6] = 1<<3; + currentConfig.KeyBinds[14] = 1<<4; + currentConfig.KeyBinds[13] = 1<<5; + currentConfig.KeyBinds[12] = 1<<6; + currentConfig.KeyBinds[ 8] = 1<<7; + currentConfig.KeyBinds[15] = 1<<26; // switch rend + currentConfig.KeyBinds[10] = 1<<27; // save state + currentConfig.KeyBinds[11] = 1<<28; // load state + currentConfig.KeyBinds[23] = 1<<29; // vol up + currentConfig.KeyBinds[22] = 1<<30; // vol down + currentConfig.gamma = 100; + currentConfig.PicoCDBuffers = 64; + currentConfig.scaling = 0; } - void osd_text(int x, int y, const char *text) { int len = strlen(text)*8; @@ -706,7 +214,7 @@ void osd_text(int x, int y, const char *text) p = (int *) ((unsigned char *) gp2x_screen+x+320*(y+h)); for (i = len; i; i--, p++) *p = 0xe0e0e0e0; } - text_out8_builtin(x, y, text); + emu_textOut8(x, y, text); } else { int *p, i, h; x &= ~1; // align x @@ -715,7 +223,7 @@ void osd_text(int x, int y, const char *text) p = (int *) ((unsigned short *) gp2x_screen+x+320*(y+h)); for (i = len; i; i--, p++) *p = (*p>>2)&0x39e7; } - text_out16_builtin(x, y, text); + emu_textOut16(x, y, text); } } @@ -917,7 +425,7 @@ static void RunEvents(unsigned int which) { if(which & 0x1800) { // save or load (but not both) int do_it = 1; - if ( emu_check_save_file(state_slot) && + if ( emu_checkSaveFile(state_slot) && (( (which & 0x1000) && (currentConfig.EmuOpt & 0x800)) || // load (!(which & 0x1000) && (currentConfig.EmuOpt & 0x200))) ) { // save unsigned long keys; @@ -962,7 +470,7 @@ static void RunEvents(unsigned int which) state_slot += 1; if(state_slot > 9) state_slot = 0; } - sprintf(noticeMsg, "SAVE SLOT %i [%s]", state_slot, emu_check_save_file(state_slot) ? "USED" : "FREE"); + sprintf(noticeMsg, "SAVE SLOT %i [%s]", state_slot, emu_checkSaveFile(state_slot) ? "USED" : "FREE"); gettimeofday(¬iceMsgTime, 0); } if(which & 0x0080) { @@ -971,35 +479,6 @@ static void RunEvents(unsigned int which) } -static void updateMovie(void) -{ - int offs = Pico.m.frame_count*3 + 0x40; - if (offs+3 > movie_size) { - free(movie_data); - movie_data = 0; - strcpy(noticeMsg, "END OF MOVIE."); - printf("END OF MOVIE.\n"); - gettimeofday(¬iceMsgTime, 0); - } else { - // MXYZ SACB RLDU - PicoPad[0] = ~movie_data[offs] & 0x8f; // ! SCBA RLDU - if(!(movie_data[offs] & 0x10)) PicoPad[0] |= 0x40; // A - if(!(movie_data[offs] & 0x20)) PicoPad[0] |= 0x10; // B - if(!(movie_data[offs] & 0x40)) PicoPad[0] |= 0x20; // A - PicoPad[1] = ~movie_data[offs+1] & 0x8f; // ! SCBA RLDU - if(!(movie_data[offs+1] & 0x10)) PicoPad[1] |= 0x40; // A - if(!(movie_data[offs+1] & 0x20)) PicoPad[1] |= 0x10; // B - if(!(movie_data[offs+1] & 0x40)) PicoPad[1] |= 0x20; // A - PicoPad[0] |= (~movie_data[offs+2] & 0x0A) << 8; // ! MZYX - if(!(movie_data[offs+2] & 0x01)) PicoPad[0] |= 0x0400; // X - if(!(movie_data[offs+2] & 0x04)) PicoPad[0] |= 0x0100; // Z - PicoPad[1] |= (~movie_data[offs+2] & 0xA0) << 4; // ! MZYX - if(!(movie_data[offs+2] & 0x10)) PicoPad[1] |= 0x0400; // X - if(!(movie_data[offs+2] & 0x40)) PicoPad[1] |= 0x0100; // Z - } -} - - static void updateKeys(void) { unsigned long keys, allActions[2] = { 0, 0 }, events; @@ -1077,7 +556,7 @@ static void updateKeys(void) events &= ~prevEvents; if (events) RunEvents(events); - if (movie_data) updateMovie(); + if (movie_data) emu_updateMovie(); prevEvents = (allActions[0] | allActions[1]) >> 16; } @@ -1101,7 +580,7 @@ static void SkipFrame(int do_audio) } -void emu_forced_frame(void) +void emu_forcedFrame(void) { int po_old = PicoOpt; int eo_old = currentConfig.EmuOpt; @@ -1184,6 +663,7 @@ void emu_Loop(void) // make sure we are in correct mode vidResetMode(); + scaling_update(); Pico.m.dirtyPal = 1; oldmodes = ((Pico.video.reg[12]&1)<<2) ^ 0xc; find_combos(); @@ -1339,7 +819,7 @@ void emu_Loop(void) } } else if(tval.tv_usec > lim_time) { // auto frameskip // no time left for this frame - skip - if (tval.tv_usec - lim_time >= 0x300000) { + if (tval.tv_usec - lim_time >= 300000) { /* something caused a slowdown for us (disk access? cache flush?) * try to recover by resetting timing... */ reset_timing = 1; @@ -1415,7 +895,7 @@ if (Pico.m.frame_count == 31563) { gettimeofday(&tval, 0); if (thissec != tval.tv_sec) tval.tv_usec+=1000000; - if (currentConfig.Frameskip < 0 && tval.tv_usec - lim_time >= 0x300000) // slowdown detection + if (currentConfig.Frameskip < 0 && tval.tv_usec - lim_time >= 300000) // slowdown detection reset_timing = 1; else if (PsndOut != NULL || currentConfig.Frameskip < 0) { @@ -1451,7 +931,7 @@ if (Pico.m.frame_count == 31563) { // if in 8bit mode, generate 16bit image for menu background if ((PicoOpt&0x10) || !(currentConfig.EmuOpt&0x80)) - emu_forced_frame(); + emu_forcedFrame(); } @@ -1462,196 +942,3 @@ void emu_ResetGame(void) } -size_t gzRead2(void *p, size_t _size, size_t _n, void *file) -{ - return gzread(file, p, _n); -} - - -size_t gzWrite2(void *p, size_t _size, size_t _n, void *file) -{ - return gzwrite(file, p, _n); -} - -static int try_ropen_file(const char *fname) -{ - FILE *f; - - f = fopen(fname, "rb"); - if (f) { - fclose(f); - return 1; - } - return 0; -} - -char *emu_GetSaveFName(int load, int is_sram, int slot) -{ - static char saveFname[512]; - char ext[16]; - - if (is_sram) - { - romfname_ext(saveFname, (PicoMCD&1) ? "brm/" : "srm/", (PicoMCD&1) ? ".brm" : ".srm"); - if (load) { - if (try_ropen_file(saveFname)) return saveFname; - // try in current dir.. - romfname_ext(saveFname, NULL, (PicoMCD&1) ? ".brm" : ".srm"); - if (try_ropen_file(saveFname)) return saveFname; - return NULL; // give up - } - } - else - { - ext[0] = 0; - if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot); - strcat(ext, (currentConfig.EmuOpt & 8) ? ".mds.gz" : ".mds"); - - romfname_ext(saveFname, "mds/", ext); - if (load) { - if (try_ropen_file(saveFname)) return saveFname; - romfname_ext(saveFname, NULL, ext); - if (try_ropen_file(saveFname)) return saveFname; - if (currentConfig.EmuOpt & 8) { - ext[0] = 0; - if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot); - strcat(ext, ".mds"); - - romfname_ext(saveFname, "mds/", ext); - if (try_ropen_file(saveFname)) return saveFname; - romfname_ext(saveFname, NULL, ext); - if (try_ropen_file(saveFname)) return saveFname; - } - return NULL; - } - } - - return saveFname; -} - -int emu_check_save_file(int slot) -{ - return emu_GetSaveFName(1, 0, slot) ? 1 : 0; -} - -void emu_set_save_cbs(int gz) -{ - if (gz) { - areaRead = gzRead2; - areaWrite = gzWrite2; - areaEof = (areaeof *) gzeof; - areaSeek = (areaseek *) gzseek; - areaClose = (areaclose *) gzclose; - } else { - areaRead = (arearw *) fread; - areaWrite = (arearw *) fwrite; - areaEof = (areaeof *) feof; - areaSeek = (areaseek *) fseek; - areaClose = (areaclose *) fclose; - } -} - -int emu_SaveLoadGame(int load, int sram) -{ - int ret = 0; - char *saveFname; - - // make save filename - saveFname = emu_GetSaveFName(load, sram, state_slot); - if (saveFname == NULL) { - if (!sram) { - strcpy(noticeMsg, load ? "LOAD FAILED (missing file)" : "SAVE FAILED "); - gettimeofday(¬iceMsgTime, 0); - } - return -1; - } - - printf("saveLoad (%i, %i): %s\n", load, sram, saveFname); - - if(sram) { - FILE *sramFile; - int sram_size; - unsigned char *sram_data; - int truncate = 1; - if (PicoMCD&1) { - if (PicoOpt&0x8000) { // MCD RAM cart? - sram_size = 0x12000; - sram_data = SRam.data; - if (sram_data) - memcpy32((int *)sram_data, (int *)Pico_mcd->bram, 0x2000/4); - } else { - sram_size = 0x2000; - sram_data = Pico_mcd->bram; - truncate = 0; // the .brm may contain RAM cart data after normal brm - } - } else { - sram_size = SRam.end-SRam.start+1; - if(Pico.m.sram_reg & 4) sram_size=0x2000; - sram_data = SRam.data; - } - if (!sram_data) return 0; // SRam forcefully disabled for this game - - if (load) { - sramFile = fopen(saveFname, "rb"); - if(!sramFile) return -1; - fread(sram_data, 1, sram_size, sramFile); - fclose(sramFile); - if ((PicoMCD&1) && (PicoOpt&0x8000)) - memcpy32((int *)Pico_mcd->bram, (int *)sram_data, 0x2000/4); - } else { - // sram save needs some special processing - // see if we have anything to save - for (; sram_size > 0; sram_size--) - if (sram_data[sram_size-1]) break; - - if (sram_size) { - sramFile = fopen(saveFname, truncate ? "wb" : "r+b"); - if (!sramFile) sramFile = fopen(saveFname, "wb"); // retry - if (!sramFile) return -1; - ret = fwrite(sram_data, 1, sram_size, sramFile); - ret = (ret != sram_size) ? -1 : 0; - fclose(sramFile); -#ifndef NO_SYNC - sync(); -#endif - } - } - return ret; - } - else - { - void *PmovFile = NULL; - if (strcmp(saveFname + strlen(saveFname) - 3, ".gz") == 0) { - if( (PmovFile = gzopen(saveFname, load ? "rb" : "wb")) ) { - emu_set_save_cbs(1); - if(!load) gzsetparams(PmovFile, 9, Z_DEFAULT_STRATEGY); - } - } - else - { - if( (PmovFile = fopen(saveFname, load ? "rb" : "wb")) ) { - emu_set_save_cbs(0); - } - } - if(PmovFile) { - ret = PmovState(load ? 6 : 5, PmovFile); - areaClose(PmovFile); - PmovFile = 0; - if (load) Pico.m.dirtyPal=1; -#ifndef NO_SYNC - else sync(); -#endif - } - else ret = -1; - if (!ret) - strcpy(noticeMsg, load ? "GAME LOADED " : "GAME SAVED "); - else - { - strcpy(noticeMsg, load ? "LOAD FAILED " : "SAVE FAILED "); - ret = -1; - } - - gettimeofday(¬iceMsgTime, 0); - return ret; - } -} diff --git a/platform/gp2x/emu.h b/platform/gp2x/emu.h index 6ae089d..8eddd1f 100644 --- a/platform/gp2x/emu.h +++ b/platform/gp2x/emu.h @@ -16,44 +16,15 @@ enum TPicoGameState { PGS_RestartRun, }; -typedef struct { - char lastRomFile[512]; - int EmuOpt; // LSb->MSb: use_sram, show_fps, enable_sound, gzip_saves, - // squidgehack, no_save_cfg_on_exit, , 16_bit_mode - // craigix_ram, confirm_save, show_cd_leds, confirm_load - // A_SNs_gamma, perfect_vsync - 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]; - int PicoAutoRgnOrder; - int PicoCDBuffers; - int scaling; // 0=center, 1=hscale, 2=hvscale, 3=hsoftscale -} 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 no_defaults); -int emu_WriteConfig(int game); -char *emu_GetSaveFName(int load, int is_sram, int slot); -int emu_check_save_file(int slot); -void emu_set_save_cbs(int gz); -void emu_forced_frame(void); -int emu_cd_check(int *pregion); -int find_bios(int region, char **bios_file); -void scaling_update(void); +void emu_forcedFrame(void); + +void osd_text(int x, int y, const char *text); diff --git a/platform/gp2x/main.c b/platform/gp2x/main.c index 13eb5a8..95e0e9f 100644 --- a/platform/gp2x/main.c +++ b/platform/gp2x/main.c @@ -12,6 +12,7 @@ #include "gp2x.h" #include "menu.h" #include "../common/menu.h" +#include "../common/emu.h" #include "emu.h" #include "940ctl.h" #include "version.h" diff --git a/platform/gp2x/menu.c b/platform/gp2x/menu.c index 63ba6a0..a60e4d8 100644 --- a/platform/gp2x/menu.c +++ b/platform/gp2x/menu.c @@ -14,8 +14,9 @@ #include "emu.h" #include "menu.h" #include "usbjoy.h" -#include "../common/arm_utils.h" +#include "../common/emu.h" #include "../common/menu.h" +#include "../common/arm_utils.h" #include "../common/readpng.h" #include "version.h" @@ -27,11 +28,7 @@ #error "need d_type for file browser #endif -extern char romFileName[PATH_MAX]; -extern char *rom_data; extern int mmuhack_status; -extern int state_slot; -extern int config_slot, config_slot_current; static const char *gp2xKeyNames[] = { "UP", "???", "LEFT", "???", "DOWN", "???", "RIGHT", "???", @@ -40,8 +37,6 @@ static const char *gp2xKeyNames[] = { "???", "???", "???", "PUSH", "???", "???", "???", "???" }; -char menuErrorMsg[40] = {0, }; - static void menu_darken_bg(void *dst, int pixels, int darker); static void menu_prepare_bg(int use_game_bg); @@ -452,7 +447,7 @@ static void state_check_slots(void) for (slot = 0; slot < 10; slot++) { - if (emu_check_save_file(slot)) + if (emu_checkSaveFile(slot)) { state_slot_flags |= 1 << slot; } @@ -480,10 +475,10 @@ static void draw_savestate_bg(int slot) if (strcmp(fname + strlen(fname) - 3, ".gz") == 0) { file = gzopen(fname, "rb"); - emu_set_save_cbs(1); + emu_setSaveStateCbs(1); } else { file = fopen(fname, "rb"); - emu_set_save_cbs(0); + emu_setSaveStateCbs(0); } if (file) { @@ -501,7 +496,7 @@ static void draw_savestate_bg(int slot) areaClose(file); } - emu_forced_frame(); + emu_forcedFrame(); menu_prepare_bg(1); memcpy(Pico.vram, tmp_vram, sizeof(Pico.vram)); @@ -928,17 +923,17 @@ static void cd_menu_loop_options(void) menu_id selected_id; char *bios, *p; - if (find_bios(4, &bios)) { // US + if (emu_findBios(4, &bios)) { // US for (p = bios+strlen(bios)-1; p > bios && *p != '/'; p--); p++; strncpy(bios_names.us, p, sizeof(bios_names.us)); bios_names.us[sizeof(bios_names.us)-1] = 0; } else strcpy(bios_names.us, "NOT FOUND"); - if (find_bios(8, &bios)) { // EU + if (emu_findBios(8, &bios)) { // EU for (p = bios+strlen(bios)-1; p > bios && *p != '/'; p--); p++; strncpy(bios_names.eu, p, sizeof(bios_names.eu)); bios_names.eu[sizeof(bios_names.eu)-1] = 0; } else strcpy(bios_names.eu, "NOT FOUND"); - if (find_bios(1, &bios)) { // JP + if (emu_findBios(1, &bios)) { // JP for (p = bios+strlen(bios)-1; p > bios && *p != '/'; p--); p++; strncpy(bios_names.jp, p, sizeof(bios_names.jp)); bios_names.jp[sizeof(bios_names.jp)-1] = 0; } else strcpy(bios_names.jp, "NOT FOUND"); @@ -972,21 +967,21 @@ static void cd_menu_loop_options(void) if (inp & GP2X_START) { // BIOS testers switch (selected_id) { case MA_CDOPT_TESTBIOS_USA: - if (find_bios(4, &bios)) { // test US + if (emu_findBios(4, &bios)) { // test US strcpy(romFileName, bios); engineState = PGS_ReloadRom; return; } break; case MA_CDOPT_TESTBIOS_EUR: - if (find_bios(8, &bios)) { // test EU + if (emu_findBios(8, &bios)) { // test EU strcpy(romFileName, bios); engineState = PGS_ReloadRom; return; } break; case MA_CDOPT_TESTBIOS_JAP: - if (find_bios(1, &bios)) { // test JP + if (emu_findBios(1, &bios)) { // test JP strcpy(romFileName, bios); engineState = PGS_ReloadRom; return; @@ -1259,7 +1254,6 @@ static void menu_options_save(void) // unbind XYZ MODE, just in case unbind_action(0xf00, -1, -1); } - scaling_update(); } static int menu_loop_options(void) @@ -1697,7 +1691,7 @@ int menu_loop_tray(void) selfname = romsel_loop(curr_path); if (selfname) { int ret = -1, cd_type; - cd_type = emu_cd_check(NULL); + cd_type = emu_cdCheck(NULL); if (cd_type > 0) ret = Insert_CD(romFileName, cd_type == 2); if (ret != 0) { diff --git a/platform/gp2x/menu.h b/platform/gp2x/menu.h index bd216a4..7561d34 100644 --- a/platform/gp2x/menu.h +++ b/platform/gp2x/menu.h @@ -3,8 +3,6 @@ // For commercial use, separate licencing terms must be obtained. -extern char menuErrorMsg[40]; - void menu_loop(void); int menu_loop_tray(void); void menu_romload_prepare(const char *rom_name); diff --git a/platform/gp2x/port_config.h b/platform/gp2x/port_config.h index fd28f79..dcd5032 100644 --- a/platform/gp2x/port_config.h +++ b/platform/gp2x/port_config.h @@ -5,6 +5,9 @@ #define CPU_CALL +// draw.c +#define OVERRIDE_HIGHCOL 0 + // draw2.c #define START_ROW 0 // which row of tiles to start rendering at? #define END_ROW 28 // ..end diff --git a/platform/gp2x/port_config.s b/platform/gp2x/port_config.s index 9fac2a3..87c3e52 100644 --- a/platform/gp2x/port_config.s +++ b/platform/gp2x/port_config.s @@ -1,10 +1,13 @@ @ vim:filetype=armasm -@ .equiv START_ROW, 1 -@ .equiv END_ROW, 27 +@ .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 +.equiv START_ROW, 0 +.equiv END_ROW, 28 + +.equiv OVERRIDE_HIGHCOL, 0 @ this should be set to one only for GP2X port -.equiv EXTERNAL_YM2612, 1 +.equiv EXTERNAL_YM2612, 1 + -- 2.39.2