}\r
else if (stream->type == PMT_ZIP)\r
{\r
+ if (PicoMessage != NULL && offset > 6*1024*1024) {\r
+ long pos = gztell((gzFile) stream->param);\r
+ if (offset < pos || offset - pos > 6*1024*1024)\r
+ PicoMessage("Decompressing data...");\r
+ }\r
return gzseek((gzFile) stream->param, offset, whence);\r
}\r
else\r
stmfd sp!,{r0,lr}\r
bic r0, r0, #1\r
mov r1, #8\r
- bl UnusualRead16\r
+ bl OtherRead16End\r
ldmfd sp!,{r1,lr}\r
tst r1, #1\r
moveq r0, r0, lsr #8\r
\r
m_read16_above_rom:\r
mov r1, #16\r
- ldr r2, =UnusualRead16\r
+ ldr r2, =OtherRead16End\r
bic r0, r0, #1\r
bx r2\r
\r
bic r0, r0, #1\r
stmfd sp!,{r0,lr}\r
mov r1, #32\r
- bl UnusualRead16\r
+ bl OtherRead16End\r
mov r1, r0\r
ldmfd sp!,{r0}\r
stmfd sp!,{r1}\r
add r0, r0, #2\r
mov r1, #32\r
- bl UnusualRead16\r
+ bl OtherRead16End\r
ldmfd sp!,{r1,lr}\r
orr r0, r0, r1, lsl #16\r
bx lr\r
// |=0x80 for Shadow of the Beast & Super Offroad; rotate fakes next fetched instruction for Time Killers
if (a==0xa11100) { // z80 busreq
d=Pico.m.z80Run&1;
-#if 0
if (!d) {
- // do we need this?
+ // needed by buggy Terminator (Sega CD)
extern int z80stopCycle;
int stop_before = SekCyclesDone() - z80stopCycle;
- if (stop_before > 0 && stop_before <= 16) // Gens uses 16 here
+ dprintf("stop before: %i", stop_before);
+ if (stop_before > 0 && stop_before <= 32) // Gens uses 16 here
d = 1; // bus not yet available
}
-#endif
d=(d<<8)|0x8000|Pico.m.rotate++;
dprintf("get_zrun: %04x [%i|%i] @%06x", d, Pico.m.scanline, SekCyclesDone(), SekPc);
goto end;
return 0;\r
}\r
\r
-static int DefaultCram(int cram)\r
-{\r
- int high=0x0841;\r
- // Convert 0000bbbb ggggrrrr\r
- // to rrrr1ggg g10bbbb1\r
- high|=(cram&0x00f)<<12; // Red\r
- high|=(cram&0x0f0)<< 3; // Green\r
- high|=(cram&0xf00)>> 7; // Blue\r
- return high;\r
-}\r
-\r
-// Function to convert Megadrive Cram into a native colour:\r
-int (*PicoCram)(int cram)=DefaultCram;\r
+// callback to output message from emu\r
+void (*PicoMessage)(const char *msg)=NULL;\r
\r
#if defined(__DEBUG_PRINT) || defined(WIN32)\r
// tmp debug: dump some stuff\r
int PicoReset(int hard);\r
int PicoFrame(void);\r
extern int PicoPad[2]; // Joypads, format is MXYZ SACB RLDU\r
-extern int (*PicoCram)(int cram); // Callback to convert colour ram 0000bbb0 ggg0rrr0\r
extern void (*PicoWriteSound)(int len); // called once per frame at the best time to send sound buffer (PsndOut) to hardware\r
+extern void (*PicoMessage)(const char *msg); // callback to output text message from emu\r
\r
int PicoFrameMCD(void);\r
\r
\r
//#define __debug_io\r
//#define __debug_io2\r
+\r
//#define rdprintf dprintf\r
#define rdprintf(...)\r
//#define wrdprintf dprintf\r
case 2:\r
Pico_mcd->s68k_regs[2] = d; // really use s68k side register\r
return;\r
- case 3:\r
+ case 3: {\r
+ u32 dold = Pico_mcd->s68k_regs[3]&0x1f;\r
dprintf("m68k_regs w3: %02x @%06x", (u8)d, SekPc);\r
d &= 0xc2;\r
- if ((Pico_mcd->s68k_regs[3]>>6) != ((d>>6)&3))\r
+ if ((dold>>6) != ((d>>6)&3))\r
dprintf("m68k: prg bank: %i -> %i", (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3));\r
//if ((Pico_mcd->s68k_regs[3]&4) != (d&4)) dprintf("m68k: ram mode %i mbit", (d&4) ? 1 : 2);\r
//if ((Pico_mcd->s68k_regs[3]&2) != (d&2)) dprintf("m68k: %s", (d&4) ? ((d&2) ? "word swap req" : "noop?") :\r
// ((d&2) ? "word ram to s68k" : "word ram to m68k"));\r
- d |= Pico_mcd->s68k_regs[3]&0x1d;\r
- if (!(d & 4) && (d & 2)) d &= ~1; // return word RAM to s68k in 2M mode\r
- Pico_mcd->s68k_regs[3] = d; // really use s68k side register\r
+ if (dold & 4) {\r
+ d ^= 2; // writing 0 to DMNA actually sets it, 1 does nothing\r
+ } else {\r
+ //dold &= ~2; // ??\r
+ if (d & 2) dold &= ~1; // return word RAM to s68k in 2M mode\r
+ }\r
+ Pico_mcd->s68k_regs[3] = d | dold; // really use s68k side register\r
+\r
+/*\r
+ d |= Pico_mcd->s68k_regs[3]&0x1d;\r
+ if (!(d & 4) && (d & 2)) d &= ~1; // return word RAM to s68k in 2M mode\r
+ Pico_mcd->s68k_regs[3] = d; // really use s68k side register\r
+*/\r
return;\r
+ }\r
case 6:\r
Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer\r
return;\r
ldr r9, [r9]
sub r0, r9, r8
- add r3, r3, r3, asr #1
- add r3, r3, r3, asr #3 @ cycn_s68k = (cycn + cycn/2 + cycn/8)
+ mov r2, r3
+ add r3, r3, r2, asr #1
+ add r3, r3, r2, asr #3 @ cycn_s68k = (cycn + cycn/2 + cycn/8)
subs r5, r0, r3, asr #16
ble schedule_m68k @ s68k has not enough cycles
;@ r7 = Pointer to Cpu Context
;@ r8 = Current Opcode
ldrb r9,[r7,#0x46] ;@ r9 = Flags (NZCV)
- ldr r0,[r7,#0x44]
- mov r9,r9,lsl #28 ;@ r9 = Flags 0xf0000000, cpsr format
+ ldr r1,[r7,#0x44] ;@ get SR high and IRQ level
+ orr r9,r9,r9,lsl #28 ;@ r9 = Flags 0xf0000000, cpsr format
;@ r10 = Source value / Memory Base
;@ CheckInterrupt:
- movs r0,r0,lsr #24 ;@ Get IRQ level
+ movs r0,r1,lsr #24 ;@ Get IRQ level
beq NoIntsLocal
cmp r0,#6 ;@ irq>6 ?
- ldrleb r1,[r7,#0x44] ;@ Get SR high: T_S__III
andle r1,r1,#7 ;@ Get interrupt mask
cmple r0,r1 ;@ irq<=6: Is irq<=mask ?
- blgt CycloneDoInterrupt
-;@ Check if interrupt used up all the cycles:
- subs r5,r5,#0
- ldrlt r1,[r7,#0x54]
- bxlt r1 ;@ jump to alternative CycloneEnd
+ ldrgt lr,[r7,#0x54] @ Interrupt will definitely use more cycles than our step,
+ bgt CycloneDoInterrupt @ so make this function return directly to CycloneEnd_*
NoIntsLocal:
-;@ Check if our processor is in stopped state and jump to opcode handler if not
+ ;@ Check if our processor is in stopped state and jump to opcode handler if not
ldr r0,[r7,#0x58]
ldrh r8,[r4],#2 ;@ Fetch first opcode
tst r0,r0 ;@ stopped?
+ andeq r9,r9,#0xf0000000
ldreq pc,[r6,r8,asl #2] ;@ Jump to opcode handler
@ stopped
+ sub r4,r4,#2
ldr r1,[r7,#0x54]
mov r5,#0
bx r1
/* this is a try to fight slow SD access of GP2X */
void PicoCDBufferRead(void *dest, int lba)
{
- int is_bin, offs, read_len;
+ int is_bin, offs, read_len, moved = 0;
reads++;
is_bin = Pico_mcd->TOC.Tracks[0].ftype == TYPE_BIN;
if (lba < prev_lba && prev_lba - lba < PicoCDBuffers)
{
- dprintf("CD buffer move");
read_len = prev_lba - lba;
+ dprintf("CD buffer move=%i, read_len=%i", PicoCDBuffers - read_len, read_len);
memmove(cd_buffer + read_len*2048, cd_buffer, (PicoCDBuffers - read_len)*2048);
+ moved = 1;
}
else
{
read_len = PicoCDBuffers;
}
+ if (PicoMessage != NULL && read_len >= 512)
+ {
+ PicoMessage("Buffering data...");
+ }
+
if (is_bin)
{
int i;
}
memcpy32(dest, (int *) cd_buffer, 2048/4);
prev_lba = lba;
+
+ if (moved)
+ {
+ /* file pointer must point to the same data in file, as would-be data after our buffer */
+ int where_seek;
+ lba += PicoCDBuffers;
+ where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
+ pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
+ }
}
void CheckInterrupt(int op)\r
{\r
ot(";@ CheckInterrupt:\n");\r
- ot(" ldr r0,[r7,#0x44]\n"); // same as ldrb r0,[r7,#0x47]\r
- ot(" movs r0,r0,lsr #24 ;@ Get IRQ level (loading word is faster)\n");\r
+ ot(" ldr r1,[r7,#0x44] ;@ Get SR high T_S__III and irq level\n");\r
+ ot(" movs r0,r1,lsr #24 ;@ Get IRQ level\n"); // same as ldrb r0,[r7,#0x47]\r
ot(" beq NoInts%x\n",op);\r
ot(" cmp r0,#6 ;@ irq>6 ?\n");\r
- ot(" ldrleb r1,[r7,#0x44] ;@ Get SR high: T_S__III\n");\r
ot(" andle r1,r1,#7 ;@ Get interrupt mask\n");\r
ot(" cmple r0,r1 ;@ irq<=6: Is irq<=mask ?\n");\r
ot(" blgt CycloneDoInterrupt\n");\r
ot(" ldr r5,[r7,#0x5c] ;@ r5 = Cycles\n");\r
ot(" ldr r4,[r7,#0x40] ;@ r4 = Current PC + Memory Base\n");\r
ot(" ;@ r8 = Current Opcode\n");\r
- ot(" ldr r0,[r7,#0x44]\n");\r
+ ot(" ldr r1,[r7,#0x44] ;@ Get SR high T_S__III and irq level\n");\r
ot(" mov r9,r9,lsl #28 ;@ r9 = Flags 0xf0000000, cpsr format\n");\r
ot(" ;@ r10 = Source value / Memory Base\n");\r
ot("\n");\r
ot(";@ CheckInterrupt:\n");\r
- ot(" movs r0,r0,lsr #24 ;@ Get IRQ level\n"); // same as ldrb r0,[r7,#0x47]\r
+ ot(" movs r0,r1,lsr #24 ;@ Get IRQ level\n"); // same as ldrb r0,[r7,#0x47]\r
ot(" beq NoInts0\n");\r
ot(" cmp r0,#6 ;@ irq>6 ?\n");\r
- ot(" ldrleb r1,[r7,#0x44] ;@ Get SR high: T_S__III\n");\r
ot(" andle r1,r1,#7 ;@ Get interrupt mask\n");\r
ot(" cmple r0,r1 ;@ irq<=6: Is irq<=mask ?\n");\r
ot(" blgt CycloneDoInterrupt\n");\r
if (loaded_mp3 != f)\r
{\r
// printf("loading mp3... "); fflush(stdout);\r
+ if (PicoMessage != NULL)\r
+ {\r
+ fseek(f, 0, SEEK_END);\r
+ if (ftell(f) > 2*1024*1024)\r
+ PicoMessage("Loading MP3...");\r
+ }\r
fseek(f, 0, SEEK_SET);\r
fread(mp3_mem, 1, MP3_SIZE_MAX, f);\r
// if (feof(f)) printf("done.\n");\r
dprint = 1\r
#mz80 = 1\r
#debug_cyclone = 1\r
-asm_memory = 0 # TODO\r
+asm_memory = 1\r
asm_render = 1\r
asm_ym2612 = 1\r
asm_misc = 1\r
}\r
\r
\r
+static void emu_msg_cb(const char *msg);\r
+\r
void emu_Init(void)\r
{\r
// make temp buffer for alt renderer\r
mkdir("cfg", 0777);\r
\r
PicoInit();\r
+ PicoMessage = emu_msg_cb;\r
\r
// logf = fopen("log.txt", "w");\r
}\r
}\r
\r
\r
+static void emu_msg_cb(const char *msg)\r
+{\r
+ if ((PicoOpt&0x10)||!(currentConfig.EmuOpt&0x80)) {\r
+ // 8-bit renderers\r
+ gp2x_memset_all_buffers(320*232, 0xe0, 320*8);\r
+ osd_text(4, 232, msg);\r
+ gp2x_memcpy_all_buffers((char *)gp2x_screen+320*232, 320*232, 320*8);\r
+ } else {\r
+ // 16bit accurate renderer\r
+ gp2x_memset_all_buffers(320*232*2, 0, 320*8*2);\r
+ osd_text(4, 232, msg);\r
+ gp2x_memcpy_all_buffers((char *)gp2x_screen+320*232*2, 320*232*2, 320*8*2);\r
+ }\r
+ gettimeofday(¬iceMsgTime, 0);\r
+ noticeMsgTime.tv_sec -= 2;\r
+}\r
+\r
static void emu_state_cb(const char *str)\r
{\r
clearArea(0);\r
gp2x_text_out8(tl_x, (y+=10), "CD LEDs %s", (currentConfig.EmuOpt &0x0400)?"ON":"OFF"); // 3\r
gp2x_text_out8(tl_x, (y+=10), "CDDA audio (using mp3s) %s", (currentConfig.PicoOpt&0x0800)?"ON":"OFF"); // 4\r
gp2x_text_out8(tl_x, (y+=10), "PCM audio %s", (currentConfig.PicoOpt&0x0400)?"ON":"OFF"); // 5\r
- gp2x_text_out8(tl_x, (y+=10), "Better sync (slow) %s", (currentConfig.PicoOpt&0x2000)?"ON":"OFF"); // 6\r
+ gp2x_text_out8(tl_x, (y+=10), "Better sync (slower) %s", (currentConfig.PicoOpt&0x2000)?"ON":"OFF"); // 6\r
gp2x_text_out8(tl_x, (y+=10), "ReadAhead buffer %s", ra_buff); // 7\r
gp2x_text_out8(tl_x, (y+=10), "Done");\r
\r