int PicoCartUnload(void)\r
{\r
if (Pico.rom != NULL) {\r
+ SekFinishIdleDet();\r
free(Pico.rom);\r
Pico.rom=NULL;\r
}\r
{\r
unsigned char sram_reg=Pico.m.sram_reg; // must be preserved\r
\r
+ Pico.m.frame_count = 0;\r
+\r
// clear all memory of the emulated machine\r
memset(&Pico.ram,0,(unsigned int)&Pico.rom-(unsigned int)&Pico.ram);\r
\r
PicoResetMCD();\r
return 0;\r
}\r
+ else {\r
+ // reinit, so that checksum checks pass\r
+ SekFinishIdleDet();\r
+ if (!(PicoOpt & POPT_DIS_IDLE_DET))\r
+ SekInitIdleDet();\r
+ }\r
\r
// reset sram state; enable sram access by default if it doesn't overlap with ROM\r
Pico.m.sram_reg=sram_reg&0x14;\r
// same for Outrunners (92-121, when active is set to 24)\r
// 96 is VR hack\r
static const int dma_timings[] = {\r
-96, 167, 166, 83, // vblank: 32cell: dma2vram dma2[vs|c]ram vram_fill vram_copy\r
-102, 205, 204, 102, // vblank: 40cell:\r
-16, 16, 15, 8, // active: 32cell:\r
-24, 18, 17, 9 // ...\r
+ 96, 167, 166, 83, // vblank: 32cell: dma2vram dma2[vs|c]ram vram_fill vram_copy\r
+ 102, 205, 204, 102, // vblank: 40cell:\r
+ 16, 16, 15, 8, // active: 32cell:\r
+ 24, 18, 17, 9 // ...\r
};\r
\r
static const int dma_bsycles[] = {\r
-(488<<8)/96, (488<<8)/167, (488<<8)/166, (488<<8)/83,\r
-(488<<8)/102, (488<<8)/205, (488<<8)/204, (488<<8)/102,\r
-(488<<8)/16, (488<<8)/16, (488<<8)/15, (488<<8)/8,\r
-(488<<8)/24, (488<<8)/18, (488<<8)/17, (488<<8)/9\r
+ (488<<8)/96, (488<<8)/167, (488<<8)/166, (488<<8)/83,\r
+ (488<<8)/102, (488<<8)/205, (488<<8)/204, (488<<8)/102,\r
+ (488<<8)/16, (488<<8)/16, (488<<8)/15, (488<<8)/8,\r
+ (488<<8)/24, (488<<8)/18, (488<<8)/17, (488<<8)/9\r
};\r
\r
PICO_INTERNAL int CheckDMA(void)\r
{\r
int cyc_do;\r
SekCycleAim+=cyc;\r
- if((cyc_do=SekCycleAim-SekCycleCnt) <= 0) return;\r
+ if ((cyc_do=SekCycleAim-SekCycleCnt) <= 0) return;\r
#if defined(EMU_CORE_DEBUG)\r
// this means we do run-compare\r
SekCycleCnt+=CM_compareRun(cyc_do, 0);\r
return 0;\r
}\r
\r
+int idle_hit_counter = 0;\r
+\r
int PicoFrame(void)\r
{\r
int acc;\r
\r
+ if ((Pico.m.frame_count&0x3f) == 0) {\r
+ elprintf(EL_STATUS, "ihits: %i", idle_hit_counter);\r
+ idle_hit_counter = 0;\r
+ }\r
+\r
Pico.m.frame_count++;\r
\r
if (PicoAHW & PAHW_MCD) {\r
#define POPT_DIS_VDP_FIFO (1<<16) // 0x 0000\r
#define POPT_EN_SVP_DRC (1<<17)\r
#define POPT_DIS_SPRITE_LIM (1<<18)\r
+#define POPT_DIS_IDLE_DET (1<<19)\r
extern int PicoOpt; // bitfield\r
#define PAHW_MCD (1<<0)\r
#define PAHW_32X (1<<1)\r
unsigned char eeprom_cycle; // EEPROM SRAM cycle number\r
unsigned char eeprom_slave; // EEPROM slave word for X24C02 and better SRAMs\r
unsigned char prot_bytes[2]; // simple protection faking\r
- unsigned short dma_xfers;\r
+ unsigned short dma_xfers; // 18\r
unsigned char pad[2];\r
- unsigned int frame_count; // mainly for movies\r
+ unsigned int frame_count; // 1c for movies and idle det\r
};\r
\r
// some assembly stuff depend on these, do not touch!\r
PICO_INTERNAL int SekReset(void);\r
PICO_INTERNAL void SekState(int *data);\r
PICO_INTERNAL void SekSetRealTAS(int use_real);\r
+void SekInitIdleDet(void);\r
+void SekFinishIdleDet(void);\r
\r
// cd/Sek.c\r
PICO_INTERNAL int SekInitS68k(void);\r
#define EL_CDPOLL 0x00002000 /* MCD: log poll detection */\r
#define EL_SVP 0x00004000 /* SVP stuff */\r
#define EL_PICOHW 0x00008000 /* Pico stuff */\r
+#define EL_IDLE 0x00010000 /* idle loop det. */\r
\r
#define EL_STATUS 0x40000000 /* status messages */\r
#define EL_ANOMALY 0x80000000 /* some unexpected conditions (during emulation) */\r
#endif\r
}\r
\r
+/* idle loop detection, not to be used in CD mode */\r
+#ifdef EMU_C68K\r
+#include "cpu/Cyclone/tools/idle.h"\r
+#endif\r
+\r
+static int *idledet_addrs = NULL;\r
+static int idledet_count = 0, idledet_bads = 0;\r
+int idledet_start_frame = 0;\r
+\r
+static int jump_verify[0x10000];\r
+extern int CycloneJumpTab[];\r
+static unsigned char *rom_verify = NULL;\r
+\r
+void SekInitIdleDet(void)\r
+{\r
+ void *tmp = realloc(idledet_addrs, 0x200*4);\r
+ if (tmp == NULL) {\r
+ free(idledet_addrs);\r
+ idledet_addrs = NULL;\r
+ }\r
+ else\r
+ idledet_addrs = tmp;\r
+ idledet_count = idledet_bads = 0;\r
+ idledet_start_frame = Pico.m.frame_count + 360;\r
+\r
+ memcpy(jump_verify, CycloneJumpTab, 0x10000*4);\r
+ rom_verify = realloc(rom_verify, Pico.romsize);\r
+ memcpy(rom_verify, Pico.rom, Pico.romsize);\r
+#ifdef EMU_C68K\r
+ CycloneInitIdle();\r
+#endif\r
+}\r
+\r
+int SekIsIdleCode(unsigned short *dst, int bytes)\r
+{\r
+ printf("SekIsIdleCode %04x %i\n", *dst, bytes);\r
+ switch (bytes)\r
+ {\r
+ case 4:\r
+ if ( (*dst & 0xfff8) == 0x4a10 || // tst.b ($aX) // where should be no need to wait\r
+ (*dst & 0xfff8) == 0x4a28 || // tst.b ($xxxx,a0) // for byte change anywhere\r
+ (*dst & 0xff3f) == 0x4a38 || // tst.x ($xxxx.w), tas ($xxxx.w)\r
+ (*dst & 0xc1ff) == 0x0038 || // move.x ($xxxx.w), dX\r
+ (*dst & 0xf13f) == 0xb038) // cmp.x ($xxxx.w), dX\r
+ return 1;\r
+ break;\r
+ case 6:\r
+ if ( ((dst[1] & 0xe0) == 0xe0 && ( // RAM\r
+ *dst == 0x4a39 || // tst.b ($xxxxxxxx)\r
+ *dst == 0x4a79 || // tst.w ($xxxxxxxx)\r
+ *dst == 0x4ab9)) || // tst.l ($xxxxxxxx)\r
+ *dst == 0x0838) // btst $X, ($xxxx.w) [6 byte op]\r
+ return 1;\r
+ break;\r
+ case 8:\r
+ if ( (dst[2] & 0xe0) == 0xe0 && ( // RAM\r
+ *dst == 0x0839 || // btst $X, ($xxxxxxxx.w) [8 byte op]\r
+ (*dst & 0xffbf) == 0x0c39)) // cmpi.{b,w} $X, ($xxxxxxxx)\r
+ return 1;\r
+ break;\r
+ case 12:\r
+ if ((*dst & 0xf1f8) == 0x3010 && // move.w (aX), dX\r
+ (dst[1]&0xf100) == 0x0000 && // arithmetic\r
+ (dst[3]&0xf100) == 0x0000) // arithmetic\r
+ return 1;\r
+ break;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop)\r
+{\r
+#ifdef EMU_C68K\r
+ pc -= PicoCpuCM68k.membase;\r
+#endif\r
+ pc &= ~0xff000000;\r
+ elprintf(EL_IDLE, "idle: patch %06x %04x %04x #%i", pc, oldop, newop, idledet_count);\r
+ if (pc > Pico.romsize) {\r
+ if (++idledet_bads > 128) return 2; // remove detector\r
+ return 1; // don't patch\r
+ }\r
+\r
+ if (idledet_count >= 0x200 && (idledet_count & 0x1ff) == 0) {\r
+ void *tmp = realloc(idledet_addrs, (idledet_count+0x200)*4);\r
+ if (tmp == NULL) return 1;\r
+ idledet_addrs = tmp;\r
+ }\r
+\r
+ idledet_addrs[idledet_count++] = pc;\r
+ return 0;\r
+}\r
+\r
+void SekFinishIdleDet(void)\r
+{\r
+ int done_something = idledet_count > 0;\r
+#ifdef EMU_C68K\r
+ CycloneFinishIdle();\r
+#endif\r
+ while (idledet_count > 0)\r
+ {\r
+ unsigned short *op = (unsigned short *)&Pico.rom[idledet_addrs[--idledet_count]];\r
+ if ((*op & 0xfd00) == 0x7100)\r
+ *op &= 0xff, *op |= 0x6600;\r
+ else if ((*op & 0xfd00) == 0x7500)\r
+ *op &= 0xff, *op |= 0x6700;\r
+ else if ((*op & 0xfd00) == 0x7d00)\r
+ *op &= 0xff, *op |= 0x6000;\r
+ else\r
+ elprintf(EL_STATUS|EL_IDLE, "idle: don't know how to restore %04x", *op);\r
+ }\r
+\r
+ if (done_something)\r
+ {\r
+ int i;\r
+ for (i = 0; i < 0x10000; i++)\r
+ if (jump_verify[i] != CycloneJumpTab[i])\r
+ printf("jumptab corruption @ %04x!\n", i), exit(1);\r
+ for (i = 0; i < Pico.romsize; i++)\r
+ if (rom_verify[i] != Pico.rom[i])\r
+ printf("ROM corruption @ %06x!\n", i), exit(1);\r
+ }\r
+}\r
+\r
+\r
#if defined(EMU_M68K) && M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER\r
static unsigned char op_flags[0x400000/2] = { 0, };\r
static int atexit_set = 0;\r
--- /dev/null
+
+void CycloneInitIdle(void);
+void CycloneFinishIdle(void);
--- /dev/null
+@ vim:filetype=armasm
+
+@ ranges/opcodes (idle, normal):
+@ 71xx, 73xx - bne.s (8bit offset)
+@ 75xx, 77xx - beq.s (8bit offset)
+@ 7dxx, 7fxx - bra.s (8bit offset)
+
+.data
+.align 2
+
+have_patches:
+ .word 0
+
+.equ patch_desc_table_size, 10
+
+patch_desc_table:
+ .word (0x71fa<<16) | 0x66fa, idle_detector_bcc8, idle_bne, Op6601 @ bne.s
+ .word (0x71f8<<16) | 0x66f8, idle_detector_bcc8, idle_bne, Op6601 @ bne.s
+ .word (0x71f6<<16) | 0x66f6, idle_detector_bcc8, idle_bne, Op6601 @ bne.s
+ .word (0x71f2<<16) | 0x66f2, idle_detector_bcc8, idle_bne, Op6601 @ bne.s
+ .word (0x75fa<<16) | 0x67fa, idle_detector_bcc8, idle_beq, Op6701 @ beq.s
+ .word (0x75f8<<16) | 0x67f8, idle_detector_bcc8, idle_beq, Op6701 @ beq.s
+ .word (0x75f6<<16) | 0x67f6, idle_detector_bcc8, idle_beq, Op6701 @ bne.s
+ .word (0x75f2<<16) | 0x67f2, idle_detector_bcc8, idle_beq, Op6701 @ bne.s
+ .word (0x7dfe<<16) | 0x60fe, idle_detector_dead, idle_bra, Op6001 @ bra.s
+ .word (0x7dfc<<16) | 0x60fc, idle_detector_dead, idle_bra, Op6001 @ bra.s
+
+
+.text
+.align 2
+
+
+.global CycloneInitIdle
+
+CycloneInitIdle:
+ ldr r3, =CycloneJumpTab
+ ldr r2, =patch_desc_table
+ mov r12,#patch_desc_table_size
+
+cii_loop:
+ ldrh r0, [r2]
+ ldr r1, [r2, #4] @ detector
+ str r1, [r3, r0, lsl #2]
+ ldrh r0, [r2, #2]
+ ldr r1, [r2, #8] @ idle
+ add r0, r3, r0, lsl #2
+ str r1, [r0]
+ ldr r1, [r2, #12] @ normal
+ str r1, [r0, #0x800]
+ add r2, r2, #16
+ subs r12,r12,#1
+ bgt cii_loop
+
+ ldr r0, =have_patches
+ mov r1, #1
+ str r1, [r0]
+ bx lr
+
+
+.global CycloneFinishIdle
+
+CycloneFinishIdle:
+ ldr r0, =have_patches
+ ldr r0, [r0]
+ tst r0, r0
+ bxeq lr
+
+ ldr r3, =CycloneJumpTab
+ ldr r2, =patch_desc_table
+ mov r12,#patch_desc_table_size
+
+cfi_loop:
+ ldrh r0, [r2]
+ ldr r1, [r2, #12] @ normal
+ str r1, [r3, r0, lsl #2]
+ ldrh r0, [r2, #2]
+ ldr r1, =Op____
+ add r0, r3, r0, lsl #2
+ str r1, [r0]
+ str r1, [r0, #0x800]
+ add r2, r2, #16
+ subs r12,r12,#1
+ bgt cfi_loop
+
+ ldr r0, =have_patches
+ mov r1, #0
+ str r1, [r0]
+ bx lr
+
+
+
+.macro inc_counter cond
+ ldr r0, =idle_hit_counter
+ ldr r1, [r0]
+ add r1, r1, #1
+ str\cond r1, [r0]
+.endm
+
+idle_bra:
+ mov r5, #4
+ inc_counter
+ b Op6001
+
+idle_bne:
+ msr cpsr_flg, r10 ;@ ARM flags = 68000 flags
+ movne r5, #4
+ inc_counter ne
+ b Op6601
+
+idle_beq:
+ msr cpsr_flg, r10 ;@ ARM flags = 68000 flags
+ moveq r5, #4
+ inc_counter eq
+ b Op6701
+
+
+@ @@@ @
+
+idle_detector_bcc8:
+ ldr r0, =(Pico+0x22208) @ Pico.m
+ ldr r1, =idledet_start_frame
+ ldr r0, [r0, #0x1c] @ ..frame_count
+ ldr r1, [r1]
+ cmp r0, r1
+ blt exit_detector @ not yet
+
+ mov r0, r8, asl #24 @ Shift 8-bit signed offset up...
+ add r0, r4, r0, asr #24 @ jump dest
+ bic r0, r0, #1
+
+ mov r1, #0
+ sub r1, r1, r8, lsl #24
+ mov r1, r1, lsr #24
+ sub r1, r1, #2
+
+ bl SekIsIdleCode
+ tst r0, r0
+ and r2, r8, #0x00ff
+ orr r2, r2, #0x7100
+ orreq r2, r2, #0x0200
+ tst r8, #0x0100 @ 67xx (beq)?
+ orrne r2, r2, #0x0400
+
+ @ r2 = patch_opcode
+ sub r0, r4, #2
+ ldrh r1, [r0]
+ mov r11,r2
+ bl SekRegisterIdlePatch
+ cmp r0, #1 @ 0 - ok to patch, 1 - no patch, 2 - remove detector
+ strlth r11,[r4, #-2]
+ ble exit_detector
+
+ @ remove detector from Cyclone
+ tst r8, #0x0100 @ 67xx (beq)?
+ ldreq r1, =Op6601
+ ldrne r1, =Op6701
+
+ ldr r3, =CycloneJumpTab
+ str r1, [r3, r8, lsl #2]
+ bx r1
+
+exit_detector:
+ tst r8, #0x0100 @ 67xx (beq)?
+ beq Op6601
+ b Op6701
+
+
+idle_detector_dead:
+ @ patch without further questions
+ and r2, r8, #0x00ff
+ orr r2, r2, #0x7d00
+ sub r0, r4, #2
+ ldrh r1, [r0]
+ mov r11,r2
+ bl SekRegisterIdlePatch
+ strh r11,[r4, #-2]
+ b Op6001
+
+.pool
+
* Tasco Deluxe for his reverse engineering work on SVP and some mappers.\r
* Bart Trzynadlowski for his SSFII and 68000 docs.\r
* Haze for his research (http://haze.mameworld.info).\r
+* Lordus, Exophase and Rokas for various ideas.\r
+* Nemesis for his YM2612 research.\r
* Mark and Jean-loup for zlib library.\r
* ketchupgun for the skin.\r
#ifdef GP2X\r
* A_SN for his gamma code.\r
* craigix for supplying the GP2X hardware and making this port possible.\r
* Alex for the icon.\r
-* Exophase, Rokas and Lordus for various ideas.\r
* All the people from gp32x boards for their support.\r
#endif\r
#ifdef GIZ\r
return 0;\r
}\r
\r
- Pico.m.frame_count = 0;\r
-\r
// insert CD if it was detected\r
if (cd_state != CIT_NOT_CD) {\r
ret = Insert_CD(romFileName, cd_state);\r
MA_OPT2_NO_FRAME_LIMIT, /* psp */
MA_OPT2_SVP_DYNAREC,
MA_OPT2_NO_SPRITE_LIM,
+ MA_OPT2_NO_IDLE_LOOPS,
MA_OPT2_DONE,
MA_OPT3_SCALE, /* psp (all OPT3) */
MA_OPT3_HSCALE32,
repeats = 0;\r
wait = 20;\r
}\r
- if (wait > 6 && (ret&(BTN_UP|BTN_LEFT|BTN_DOWN|BTN_RIGHT)))\r
+ if (wait > 6 && (ret&(BTN_UP|BTN_LEFT|BTN_DOWN|BTN_RIGHT|BTN_L|BTN_R)))\r
wait = 6;\r
inp_prev = ret;\r
\r
\r
static void draw_menu_credits(void)\r
{\r
- int tl_x = 15, tl_y = 64, y;\r
+ int tl_x = 15, tl_y = 56, y;\r
menu_draw_begin(1);\r
\r
text_out16(tl_x, 20, "PicoDrive v" VERSION " (c) notaz, 2006-2008");\r
text_out16(tl_x, (y+=10), " base code of PicoDrive");\r
text_out16(tl_x, (y+=10), "Reesy & FluBBa: DrZ80 core");\r
text_out16(tl_x, (y+=10), "MAME devs: YM2612 and SN76496 cores");\r
- text_out16(tl_x, (y+=10), "Charles MacDonald: Genesis hw docs");\r
- text_out16(tl_x, (y+=10), "Stephane Dallongeville:");\r
- text_out16(tl_x, (y+=10), " opensource Gens");\r
- text_out16(tl_x, (y+=10), "Haze: Genesis hw info");\r
text_out16(tl_x, (y+=10), "Reesy: kgsdk wrapper, sound code");\r
text_out16(tl_x, (y+=10), "jens.l: gizmondo hardware");\r
text_out16(tl_x, (y+=10), "ketchupgun: skin design");\r
\r
+ text_out16(tl_x, (y+=20), "special thanks (for code, docs, ideas)");\r
+ text_out16(tl_x, (y+=10), " Charles MacDonald, Haze,");\r
+ text_out16(tl_x, (y+=10), " Stephane Dallongeville,");\r
+ text_out16(tl_x, (y+=10), " Lordus, Exophase, Rokas,");\r
+ text_out16(tl_x, (y+=10), " Nemesis, Tasco Deluxe");\r
+\r
menu_draw_end();\r
}\r
\r
endif\r
ifeq "$(use_cyclone)" "1"\r
DEFINC += -DEMU_C68K\r
-OBJS += ../../cpu/Cyclone/proj/Cyclone.o\r
+OBJS += ../../cpu/Cyclone/proj/Cyclone.o ../../cpu/Cyclone/tools/idle.o\r
endif\r
# drz80/mz80\r
ifeq "$(mz80)" "1"\r
#include <zlib/zlib.h>\r
\r
#ifndef _DIRENT_HAVE_D_TYPE\r
-#error "need d_type for file browser\r
+#error "need d_type for file browser"\r
#endif\r
\r
extern int mmuhack_status;\r
repeats = 0;\r
wait = 20;\r
}\r
- if (wait > 6 && (ret&(GP2X_UP|GP2X_LEFT|GP2X_DOWN|GP2X_RIGHT)))\r
+ if (wait > 6 && (ret&(GP2X_UP|GP2X_LEFT|GP2X_DOWN|GP2X_RIGHT|GP2X_L|GP2X_R)))\r
wait = 6;\r
inp_prev = ret;\r
inp_prevjoy = 0;\r
{ "craigix's RAM timings", MB_ONOFF, MA_OPT2_RAMTIMINGS, ¤tConfig.EmuOpt, 0x0100, 0, 0, 1, 1 },\r
{ NULL, MB_ONOFF, MA_OPT2_SQUIDGEHACK, ¤tConfig.EmuOpt, 0x0010, 0, 0, 1, 1 },\r
{ "SVP dynarec", MB_ONOFF, MA_OPT2_SVP_DYNAREC, &PicoOpt, 0x20000, 0, 0, 1, 1 },\r
+ { "Disable idle loop patching",MB_ONOFF, MA_OPT2_NO_IDLE_LOOPS, &PicoOpt, 0x80000, 0, 0, 1, 1 },\r
{ "done", MB_NONE, MA_OPT2_DONE, NULL, 0, 0, 0, 1, 0 },\r
};\r
\r
\r
static void draw_menu_credits(void)\r
{\r
- int tl_x = 15, tl_y = 64, y;\r
+ int tl_x = 15, tl_y = 56, y;\r
gp2x_pd_clone_buffer2();\r
\r
text_out16(tl_x, 20, "PicoDrive v" VERSION " (c) notaz, 2006-2008");\r
text_out16(tl_x, (y+=10), " base code of PicoDrive");\r
text_out16(tl_x, (y+=10), "Reesy & FluBBa: DrZ80 core");\r
text_out16(tl_x, (y+=10), "MAME devs: YM2612 and SN76496 cores");\r
- text_out16(tl_x, (y+=10), "Charles MacDonald: Genesis hw docs");\r
- text_out16(tl_x, (y+=10), "Stephane Dallongeville:");\r
- text_out16(tl_x, (y+=10), " opensource Gens");\r
- text_out16(tl_x, (y+=10), "Haze: Genesis hw info");\r
text_out16(tl_x, (y+=10), "rlyeh and others: minimal SDK");\r
text_out16(tl_x, (y+=10), "Squidge: squidgehack");\r
text_out16(tl_x, (y+=10), "Dzz: ARM940 sample");\r
- text_out16(tl_x, (y+=10), "GnoStiC / Puck2099: USB joystick");\r
+ text_out16(tl_x, (y+=10), "GnoStiC / Puck2099: USB joy code");\r
text_out16(tl_x, (y+=10), "craigix: GP2X hardware");\r
text_out16(tl_x, (y+=10), "ketchupgun: skin design");\r
\r
+ text_out16(tl_x, (y+=20), "special thanks (for code, docs, ideas)");\r
+ text_out16(tl_x, (y+=10), " Charles MacDonald, Haze,");\r
+ text_out16(tl_x, (y+=10), " Stephane Dallongeville,");\r
+ text_out16(tl_x, (y+=10), " Lordus, Exophase, Rokas,");\r
+ text_out16(tl_x, (y+=10), " Nemesis, Tasco Deluxe");\r
+\r
menu_flip();\r
}\r
\r
#define CAN_HANDLE_240_LINES 1\r
\r
// logging emu events\r
-#define EL_LOGMASK EL_STATUS // (EL_STATUS|EL_ANOMALY|EL_UIO|EL_SRAMIO|EL_INTS|EL_CDPOLL) // xffff\r
+#define EL_LOGMASK (EL_STATUS|EL_IDLE) // (EL_STATUS|EL_ANOMALY|EL_UIO|EL_SRAMIO|EL_INTS|EL_CDPOLL) // xffff\r
\r
//#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__)\r
#define dprintf(x...)\r
-#define VERSION "1.45"\r
+#define VERSION "1.50"\r
\r
if (!is_key_config)
ret |= (ret & 0xf0000000) >> 24; // use analog as d-pad
- if (wait > 6 && (ret&(BTN_UP|BTN_LEFT|BTN_DOWN|BTN_RIGHT)))
+ if (wait > 6 && (ret&(BTN_UP|BTN_LEFT|BTN_DOWN|BTN_RIGHT|BTN_L|BTN_R)))
wait = 6;
// we don't need diagonals in menus
text_out16(tl_x, (y+=10), "Chui: Fame/C");
text_out16(tl_x, (y+=10), "NJ: CZ80");
text_out16(tl_x, (y+=10), "MAME devs: YM2612 and SN76496 cores");
- text_out16(tl_x, (y+=10), "Stephane Dallongeville:");
- text_out16(tl_x, (y+=10), " Gens code, base of Fame/C, CZ80");
- text_out16(tl_x, (y+=10), "Charles MacDonald: Genesis hw docs");
- text_out16(tl_x, (y+=10), "Haze: Genesis hw info");
text_out16(tl_x, (y+=10), "ps2dev.org people: PSP SDK/code");
text_out16(tl_x, (y+=10), "ketchupgun: skin design");
+ text_out16(tl_x, (y+=20), "special thanks (for code, docs, ideas):");
+ text_out16(tl_x, (y+=10), " Charles MacDonald, Haze,");
+ text_out16(tl_x, (y+=10), " Stephane Dallongeville,");
+ text_out16(tl_x, (y+=10), " Lordus, Exophase, Rokas,");
+ text_out16(tl_x, (y+=10), " Nemesis, Tasco Deluxe");
+
menu_draw_end();
}
-#define VERSION "1.40b"\r
+#define VERSION "1.50"\r
\r