code940 now plays mp3s
authornotaz <notasas@gmail.com>
Sat, 20 Jan 2007 23:11:02 +0000 (23:11 +0000)
committernotaz <notasas@gmail.com>
Sat, 20 Jan 2007 23:11:02 +0000 (23:11 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@22 be3aeb3a-fb24-0410-a615-afba39da0efa

26 files changed:
platform/gp2x/940ctl_ym2612.c
platform/gp2x/Makefile
platform/gp2x/code940/940.c [moved from platform/gp2x/940.c with 52% similarity]
platform/gp2x/code940/940init.s [moved from platform/gp2x/940init.s with 84% similarity]
platform/gp2x/code940/940shared.h [moved from platform/gp2x/940shared.h with 52% similarity]
platform/gp2x/code940/Makefile [new file with mode: 0644]
platform/gp2x/code940/memcpy.s [new file with mode: 0644]
platform/gp2x/code940/mp3test.c [new file with mode: 0644]
platform/gp2x/code940/uClibc/README [moved from platform/gp2x/uClibc/README with 100% similarity]
platform/gp2x/code940/uClibc/e_log.c [moved from platform/gp2x/uClibc/e_log.c with 100% similarity]
platform/gp2x/code940/uClibc/e_pow.c [moved from platform/gp2x/uClibc/e_pow.c with 100% similarity]
platform/gp2x/code940/uClibc/e_rem_pio2.c [moved from platform/gp2x/uClibc/e_rem_pio2.c with 100% similarity]
platform/gp2x/code940/uClibc/e_sqrt.c [moved from platform/gp2x/uClibc/e_sqrt.c with 100% similarity]
platform/gp2x/code940/uClibc/k_cos.c [moved from platform/gp2x/uClibc/k_cos.c with 100% similarity]
platform/gp2x/code940/uClibc/k_rem_pio2.c [moved from platform/gp2x/uClibc/k_rem_pio2.c with 100% similarity]
platform/gp2x/code940/uClibc/k_sin.c [moved from platform/gp2x/uClibc/k_sin.c with 100% similarity]
platform/gp2x/code940/uClibc/math.h [moved from platform/gp2x/uClibc/math.h with 100% similarity]
platform/gp2x/code940/uClibc/math_private.h [moved from platform/gp2x/uClibc/math_private.h with 100% similarity]
platform/gp2x/code940/uClibc/memset.s [moved from platform/gp2x/uClibc/memset.s with 100% similarity]
platform/gp2x/code940/uClibc/s_copysign.c [moved from platform/gp2x/uClibc/s_copysign.c with 100% similarity]
platform/gp2x/code940/uClibc/s_fabs.c [moved from platform/gp2x/uClibc/s_fabs.c with 100% similarity]
platform/gp2x/code940/uClibc/s_floor.c [moved from platform/gp2x/uClibc/s_floor.c with 100% similarity]
platform/gp2x/code940/uClibc/s_scalbn.c [moved from platform/gp2x/uClibc/s_scalbn.c with 100% similarity]
platform/gp2x/code940/uClibc/s_sin.c [moved from platform/gp2x/uClibc/s_sin.c with 100% similarity]
platform/gp2x/code940/uClibc/wrappers.c [moved from platform/gp2x/uClibc/wrappers.c with 100% similarity]
platform/gp2x/gp2x.c

index 4dc320d..35bf4a7 100644 (file)
@@ -7,7 +7,7 @@
 #include <fcntl.h>\r
 #include <errno.h>\r
 \r
-#include "940shared.h"\r
+#include "code940/940shared.h"\r
 #include "gp2x.h"\r
 #include "emu.h"\r
 #include "menu.h"\r
@@ -235,11 +235,11 @@ static void wait_busy_940(void)
        printf("wait iterations: %i\n", i);\r
 #else\r
        for (i = 0; shared_ctl->busy && i < 0x10000; i++)\r
-               spend_cycles(4*1024);\r
+               spend_cycles(8*1024); // tested to be best for mp3 dec\r
        if (i < 0x10000) return;\r
 \r
        /* 940 crashed */\r
-       printf("940 crashed (cnt: %i, wc: %i, ve: ", shared_ctl->loopc, shared_ctl->waitc);\r
+       printf("940 crashed (cnt: %i, ve: ", shared_ctl->loopc);\r
        for (i = 0; i < 8; i++)\r
                printf("%i ", shared_ctl->vstarts[i]);\r
        printf(")\n");\r
@@ -373,7 +373,7 @@ void YM2612Init_940(int baseclock, int rate)
        /* now cause 940 to init it's ym2612 stuff */\r
        shared_ctl->baseclock = baseclock;\r
        shared_ctl->rate = rate;\r
-       shared_ctl->jobs[0] = JOB940_YM2612INIT;\r
+       shared_ctl->jobs[0] = JOB940_INITALL;\r
        shared_ctl->jobs[1] = 0;\r
        shared_ctl->busy = 1;\r
 \r
index 602e4f6..11e6749 100644 (file)
@@ -1,8 +1,6 @@
 \r
 # you may or may not need to change this\r
 #devkit_path = x:/stuff/dev/devkitgp2x/\r
-devkit_path = /usr/local/devkitPro/devkitGP2X/\r
-lgcc_path = $(devkit_path)lib/gcc/arm-linux/4.0.3/\r
 CROSS = arm-linux-\r
 #CROSS = $(devkit_path)bin/arm-linux-\r
 \r
@@ -17,7 +15,7 @@ asm_ym2612 = 1
 #use_musashi = 1\r
 #up = 1\r
 \r
-DEFINC = -I../.. -I. -D__GP2X__ -D_UNZIP_SUPPORT # -DBENCHMARK\r
+DEFINC = -I../.. -I. -DARM -D__GP2X__ -D_UNZIP_SUPPORT # -DBENCHMARK\r
 COPT_COMMON = -static -s -O3 -ftracer -fstrength-reduce -Wall -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math\r
 ifeq "$(profile)" "1"\r
 COPT_COMMON += -fprofile-generate\r
@@ -80,7 +78,7 @@ DEFINC += -D_USE_DRZ80
 OBJS += ../../cpu/DrZ80/drz80.o\r
 endif\r
 \r
-all: PicoDrive.gpe code940.bin\r
+all: PicoDrive.gpe\r
 \r
 PicoDrive.gpe : $(OBJS)\r
        @echo $@\r
@@ -92,15 +90,11 @@ ifeq "$(up)" "1"
        @cmd //C copy $@ \\\\10.0.1.2\\gp2x\\mnt\\sd\\games\\PicoDrive\\\r
 endif\r
 \r
-up: # up940\r
+up:\r
        @cp -v PicoDrive.gpe /mnt/gp2x/mnt/sd/games/PicoDrive/\r
 \r
 #      @cmd //C copy PicoDrive.gpe \\\\10.0.1.2\\gp2x\\mnt\\sd\\games\\PicoDrive\\\r
 \r
-up940:\r
-       @cp -v code940.bin /mnt/gp2x/mnt/sd/games/PicoDrive/\r
-\r
-#      @cmd //C copy code940.bin \\\\10.0.1.2\\gp2x\\mnt\\sd\\games\\PicoDrive\\\r
 \r
 testrefr.gpe : test.o gp2x.o asmutils.o\r
        @echo $@\r
@@ -133,45 +127,13 @@ testrefr.gpe : test.o gp2x.o asmutils.o
        @make -C ../../cpu/Cyclone/proj -f Makefile.linux\r
 \r
 \r
-# stuff for 940 core\r
-\r
-# init, emu_control, emu\r
-OBJS940 += 940init.o 940.o 940ym2612.o\r
-# the asm code seems to be faster when run on 920, but not on 940 for some reason\r
-# OBJS940 += ../../Pico/sound/ym2612_asm.o\r
-\r
-# uClibc library code\r
-OBJS940 += uClibc/memset.o uClibc/s_floor.o uClibc/e_pow.o uClibc/e_sqrt.o uClibc/s_fabs.o\r
-OBJS940 += uClibc/s_scalbn.o uClibc/s_copysign.o uClibc/k_sin.o uClibc/k_cos.o uClibc/s_sin.o\r
-OBJS940 += uClibc/e_rem_pio2.o uClibc/k_rem_pio2.o uClibc/e_log.o uClibc/wrappers.o\r
-\r
-code940.bin : code940.gpe\r
-       @echo $@\r
-       @$(OBJCOPY) -O binary $< $@\r
-\r
-code940.gpe : $(OBJS940)\r
-       @echo $@\r
-       @$(LD) -static -e code940 -Ttext 0x0 $^ -L$(lgcc_path) -lgcc -o $@\r
-\r
-940ym2612.o : ../../Pico/sound/ym2612.c\r
-       @echo $@\r
-       @$(GCC) $(COPT_COMMON) -mtune=arm940t $(DEFINC) -DEXTERNAL_YM2612 -c $< -o $@\r
-\r
-\r
 # cleanup\r
-clean: clean_pd clean_940\r
-tidy: tidy_pd tidy_940\r
-\r
-clean_pd: tidy_pd\r
+clean: tidy\r
        @$(RM) PicoDrive.gpe\r
-tidy_pd:\r
+tidy:\r
        @$(RM) $(OBJS)\r
 #      @make -C ../../cpu/Cyclone/proj -f Makefile.linux clean\r
 \r
-clean_940: tidy_940\r
-       @$(RM) code940.bin\r
-tidy_940:\r
-       @$(RM) code940.gpe $(OBJS940)\r
 \r
 clean_prof:\r
        find ../.. -name '*.gcno' -delete\r
@@ -190,10 +152,3 @@ usbjoy.o : usbjoy.c
        @echo $<\r
        @$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@\r
 \r
-uClibc/e_pow.o : uClibc/e_pow.c\r
-       @echo $<\r
-       @$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@\r
-\r
-uClibc/e_sqrt.o : uClibc/e_sqrt.c\r
-       @echo $<\r
-       @$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@\r
similarity index 52%
rename from platform/gp2x/940.c
rename to platform/gp2x/code940/940.c
index e94bf21..e0c4002 100644 (file)
@@ -1,7 +1,8 @@
 #include "940shared.h"\r
 \r
-static _940_data_t *shared_data = (_940_data_t *) 0x100000;\r
-static _940_ctl_t  *shared_ctl  = (_940_ctl_t *)  0x200000;\r
+static _940_data_t *shared_data = (_940_data_t *)   0x00100000;\r
+static _940_ctl_t  *shared_ctl  = (_940_ctl_t *)    0x00200000;\r
+static unsigned char *mp3_data  = (unsigned char *) 0x01000000;\r
 YM2612 *ym2612_940;\r
 int *mix_buffer;\r
 \r
@@ -22,17 +23,17 @@ void Main940(int startvector)
 \r
        // debug\r
        shared_ctl->vstarts[startvector]++;\r
-       asm volatile ("mcr p15, 0, r0, c7, c10, 4" ::: "r0");\r
+       // asm volatile ("mcr p15, 0, r0, c7, c10, 4" ::: "r0");\r
 \r
 \r
-       for (;; shared_ctl->loopc++)\r
+       for (;;)\r
        {\r
-               int job_num;\r
+               int job_num = 0;\r
 /*\r
                while (!shared_ctl->busy)\r
                {\r
                        //shared_ctl->waitc++;\r
-                       spend_cycles(256);\r
+                       spend_cycles(8*1024);\r
                }\r
 */\r
                if (!shared_ctl->busy)\r
@@ -44,9 +45,12 @@ void Main940(int startvector)
                {\r
                        switch (shared_ctl->jobs[job_num])\r
                        {\r
-                               case JOB940_YM2612INIT:\r
+                               case JOB940_INITALL:\r
+                                       /* ym2612 */\r
                                        shared_ctl->writebuff0[0] = shared_ctl->writebuff1[0] = 0xffff;\r
                                        YM2612Init_(shared_ctl->baseclock, shared_ctl->rate);\r
+                                       /* Helix mp3 decoder */\r
+                                       shared_data->mp3dec = MP3InitDecoder();\r
                                        break;\r
 \r
                                case JOB940_YM2612RESETCHIP:\r
@@ -80,14 +84,51 @@ void Main940(int startvector)
                                        YM2612UpdateOne_(0, shared_ctl->length, shared_ctl->stereo);\r
                                        break;\r
                                }\r
+\r
+                               case JOB940_MP3DECODE: {\r
+                                       int mp3_offs = shared_ctl->mp3_offs;\r
+                                       unsigned char *readPtr = mp3_data + mp3_offs;\r
+                                       int bytesLeft = shared_ctl->mp3_len - mp3_offs;\r
+                                       int offset; // frame offset from readPtr\r
+                                       int err;\r
+\r
+                                       if (bytesLeft <= 0) break; // EOF, nothing to do\r
+\r
+                                       offset = MP3FindSyncWord(readPtr, bytesLeft);\r
+                                       if (offset < 0) {\r
+                                               shared_ctl->mp3_offs = shared_ctl->mp3_len;\r
+                                               break; // EOF\r
+                                       }\r
+                                       readPtr += offset;\r
+                                       bytesLeft -= offset;\r
+\r
+                                       err = MP3Decode(shared_data->mp3dec, &readPtr, &bytesLeft,\r
+                                               shared_data->mp3_buffer[shared_ctl->mp3_buffsel], 0);\r
+                                       if (err) {\r
+                                               if (err == ERR_MP3_INDATA_UNDERFLOW) {\r
+                                                       shared_ctl->mp3_offs = shared_ctl->mp3_len; // EOF\r
+                                                       break;\r
+                                               } else if (err <= -6 && err >= -12) {\r
+                                                       // ERR_MP3_INVALID_FRAMEHEADER, ERR_MP3_INVALID_*\r
+                                                       // just try to skip the offending frame..\r
+                                                       readPtr++;\r
+                                               }\r
+                                               shared_ctl->mp3_errors++;\r
+                                               shared_ctl->mp3_lasterr = err;\r
+                                       }\r
+                                       shared_ctl->mp3_offs = readPtr - mp3_data;\r
+                                       break;\r
+                               }\r
                        }\r
                }\r
 \r
-               shared_ctl->busy = 0;\r
-//             cache_clean_flush();\r
                cache_clean();\r
 //             asm volatile ("mov r0, #0" ::: "r0");\r
 //             asm volatile ("mcr p15, 0, r0, c7, c10, 4" ::: "r0"); /* drain write buffer, should be done on nonbuffered write */\r
+//             cache_clean_flush();\r
+\r
+               shared_ctl->loopc++;\r
+               shared_ctl->busy = 0;\r
        }\r
 }\r
 \r
similarity index 84%
rename from platform/gp2x/940init.s
rename to platform/gp2x/code940/940init.s
index 771511f..dcf4368 100644 (file)
@@ -73,25 +73,34 @@ code940:                          @ interrupt table:
     mcr p15, 0, r0, c6, c3, 0\r
     mcr p15, 0, r0, c6, c3, 1\r
 \r
-    @ set region 1 to be cacheable (so the first 2M will be cacheable)\r
-    mov r0, #2\r
+    @ set up region 4: 16M 0x01000000-0x02000000 (mp3 area)\r
+    mov r0, #(0x17<<1)|1\r
+    orr r0, r0, #0x01000000\r
+    mcr p15, 0, r0, c6, c4, 0\r
+    mcr p15, 0, r0, c6, c4, 1\r
+\r
+    @ set regions 1 and 4 to be cacheable (so the first 2M and mp3 area will be cacheable)\r
+    mov r0, #(1<<1)|(1<<4)\r
     mcr p15, 0, r0, c2, c0, 0\r
     mcr p15, 0, r0, c2, c0, 1\r
 \r
     @ set region 1 to be bufferable too (only data)\r
+    mov r0, #(1<<1)\r
     mcr p15, 0, r0, c3, c0, 0\r
 \r
     @ set protection, allow accsess only to regions 1 and 2\r
-    mov r0, #(3<<6)|(3<<4)|(3<<2)|(0)  @ data: [full, full, full, no access] for regions [3 2 1 0]\r
+    mov r0, #(3<<8)|(3<<6)|(3<<4)|(3<<2)|(0)  @ data: [full, full, full, full, no access] for regions [4 3 2 1 0]\r
     mcr p15, 0, r0, c5, c0, 0\r
-    mov r0, #(0<<6)|(0<<4)|(3<<2)|(0)  @ instructions: [no access, no, full, no]\r
+    mov r0, #(0<<8)|(0<<6)|(0<<4)|(3<<2)|(0)  @ instructions: [no access, no, no, full, no]\r
     mcr p15, 0, r0, c5, c0, 1\r
 \r
     mrc p15, 0, r0, c1, c0, 0   @ fetch current control reg\r
     orr r0, r0, #1              @ 0x00000001: enable protection unit\r
     orr r0, r0, #4              @ 0x00000004: enable D cache\r
     orr r0, r0, #0x1000         @ 0x00001000: enable I cache\r
-    orr r0, r0, #0xC0000000     @ 0xC0000000: async+fastbus\r
+    bic r0, r0, #0xC0000000\r
+    orr r0, r0, #0x40000000     @ 0x40000000: synchronous, faster?\r
+@    orr r0, r0, #0xC0000000     @ 0xC0000000: async\r
     mcr p15, 0, r0, c1, c0, 0   @ set control reg\r
 \r
     @ flush (invalidate) the cache (just in case)\r
@@ -173,4 +182,4 @@ wait_irq:
 \r
 .pool\r
 \r
-@ vim:filetype=ignored:\r
+@ vim:filetype=armasm:\r
similarity index 52%
rename from platform/gp2x/940shared.h
rename to platform/gp2x/code940/940shared.h
index bad0f3c..cc5d0c4 100644 (file)
@@ -1,10 +1,12 @@
-#include "../../Pico/sound/ym2612.h"\r
+#include "../../../Pico/sound/ym2612.h"\r
+#include "../helix/pub/mp3dec.h"\r
 \r
 enum _940_job_t {\r
-       JOB940_YM2612INIT = 1,\r
+       JOB940_INITALL = 1,\r
        JOB940_YM2612RESETCHIP,\r
        JOB940_YM2612UPDATEONE,\r
        JOB940_PICOSTATELOAD,\r
+       JOB940_MP3DECODE,\r
        JOB940_NUMJOBS\r
 };\r
 \r
@@ -12,9 +14,10 @@ enum _940_job_t {
 \r
 typedef struct\r
 {\r
-       YM2612  ym2612;                                 /* current state of the emulated YM2612 */\r
-       int             mix_buffer[44100/50*2];         /* this is where the YM2612 samples will be mixed to */\r
-       short           mp3_buffer[2][1152*2];          /* buffer for mp3 decoder's output */\r
+       YM2612  ym2612;                                 /* current state of the emulated YM2612 */\r
+       HMP3Decoder mp3dec;                     /* mp3 decoder's handle */\r
+       int     mix_buffer[44100/50*2];         /* this is where the YM2612 samples will be mixed to */\r
+       short   mp3_buffer[2][1152*2];          /* buffers for mp3 decoder's output */\r
 } _940_data_t;\r
 \r
 \r
@@ -29,7 +32,11 @@ typedef struct
        int             writebuffsel;                   /* which write buffer to use (from 940 side) */\r
        UINT16  writebuff0[2048];                       /* list of writes to ym2612, 1024 for savestates, 1024 extra */\r
        UINT16  writebuff1[2048];\r
+       int             mp3_len;                        /* data len of loaded mp3 */\r
+       int             mp3_offs;                       /* current playback offset (just after last decoded frame) */\r
+       int             mp3_buffsel;                    /* which output buffer to decode to */\r
        int             vstarts[8];                             /* debug: number of starts from each of 8 vectors */\r
        int             loopc;                                  /* debug: main loop counter */\r
-       int             waitc;                                  /* debug: wait loop counter */\r
+       int             mp3_errors;                     /* debug: mp3 decoder's error counter */\r
+       int             mp3_lasterr;                    /* debug: mp3 decoder's last error */\r
 } _940_ctl_t;\r
diff --git a/platform/gp2x/code940/Makefile b/platform/gp2x/code940/Makefile
new file mode 100644 (file)
index 0000000..8fe170a
--- /dev/null
@@ -0,0 +1,87 @@
+\r
+# you may or may not need to change this\r
+#devkit_path = x:/stuff/dev/devkitgp2x/\r
+devkit_path = /usr/local/devkitPro/devkitGP2X/\r
+lgcc_path = $(devkit_path)lib/gcc/arm-linux/4.0.3/\r
+CROSS = arm-linux-\r
+#CROSS = $(devkit_path)bin/arm-linux-\r
+\r
+# settings\r
+#up = 1\r
+\r
+DEFINC = -I../.. -I. -D__GP2X__ -DARM # -DBENCHMARK\r
+COPT_COMMON = -static -s -O3 -ftracer -fstrength-reduce -Wall -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math\r
+COPT = $(COPT_COMMON) -mtune=arm920t\r
+GCC = $(CROSS)gcc\r
+STRIP = $(CROSS)strip\r
+AS = $(CROSS)as\r
+LD = $(CROSS)ld\r
+OBJCOPY = $(CROSS)objcopy\r
+\r
+all: code940.bin\r
+\r
+up940:\r
+       @cp -v code940.bin /mnt/gp2x/mnt/sd/games/PicoDrive/\r
+\r
+#      @cmd //C copy code940.bin \\\\10.0.1.2\\gp2x\\mnt\\sd\\games\\PicoDrive\\\r
+\r
+.c.o:\r
+       @echo $<\r
+       $(GCC) $(COPT) $(DEFINC) -c $< -o $@\r
+.s.o:\r
+       @echo $<\r
+       $(GCC) $(COPT) $(DEFINC) -c $< -o $@\r
+\r
+\r
+# stuff for 940 core\r
+\r
+# init, emu_control, emu\r
+OBJS940 += 940init.o 940.o 940ym2612.o memcpy.o\r
+# the asm code seems to be faster when run on 920, but not on 940 for some reason\r
+# OBJS940 += ../../Pico/sound/ym2612_asm.o\r
+\r
+# uClibc library code\r
+OBJS940 += uClibc/memset.o uClibc/s_floor.o uClibc/e_pow.o uClibc/e_sqrt.o uClibc/s_fabs.o\r
+OBJS940 += uClibc/s_scalbn.o uClibc/s_copysign.o uClibc/k_sin.o uClibc/k_cos.o uClibc/s_sin.o\r
+OBJS940 += uClibc/e_rem_pio2.o uClibc/k_rem_pio2.o uClibc/e_log.o uClibc/wrappers.o\r
+\r
+code940.bin : code940.gpe\r
+       @echo $@\r
+       @$(OBJCOPY) -O binary $< $@\r
+\r
+code940.gpe : $(OBJS940) ../helix/helix_mp3.a\r
+       @echo $@\r
+       @$(LD) -static -e code940 -Ttext 0x0 $^ -L$(lgcc_path) -lgcc -o $@\r
+\r
+940ym2612.o : ../../../Pico/sound/ym2612.c\r
+       @echo $@\r
+       @$(GCC) $(COPT_COMMON) -mtune=arm940t $(DEFINC) -DEXTERNAL_YM2612 -c $< -o $@\r
+\r
+../helix/helix_mp3.a:\r
+       @make -C ../helix/\r
+\r
+\r
+# cleanup\r
+clean: tidy\r
+       @$(RM) code940.bin\r
+tidy:\r
+       @$(RM) code940.gpe $(OBJS940)\r
+\r
+\r
+OBJSMP3T = mp3test.o ../gp2x.o ../asmutils.o ../usbjoy.o\r
+\r
+mp3test.gpe : $(OBJSMP3T) ../helix/helix_mp3.a\r
+       $(GCC) -static -o $@ $^\r
+       $(STRIP) $@\r
+       @cp -v $@ /mnt/gp2x/mnt/sd\r
+\r
+cleanmp3test:\r
+       $(RM) $(OBJSMP3T) mp3test.gpe\r
+\r
+# uClibc/e_pow.o : uClibc/e_pow.c\r
+#      @echo $<\r
+#      @$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@\r
+\r
+# uClibc/e_sqrt.o : uClibc/e_sqrt.c\r
+#      @echo $<\r
+#      @$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@\r
diff --git a/platform/gp2x/code940/memcpy.s b/platform/gp2x/code940/memcpy.s
new file mode 100644 (file)
index 0000000..bb4cdaa
--- /dev/null
@@ -0,0 +1,500 @@
+/* $NetBSD: memcpy.S,v 1.3 1997/11/22 03:27:12 mark Exp $ */
+
+/*-
+* Copyright (c) 1997 The NetBSD Foundation, Inc.
+* All rights reserved.
+*
+* This code is derived from software contributed to The NetBSD Foundation
+* by Neil A. Carson and Mark Brinicombe
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+* 3. All advertising materials mentioning features or use of this software
+*    must display the following acknowledgement:
+* This product includes software developed by the NetBSD
+* Foundation, Inc. and its contributors.
+* 4. Neither the name of The NetBSD Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+* ``AS IS\'\' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* This was modified by Jay Monkman <jmonkman@smoothsmoothie.com> to
+*   save and restore r12. This is necessary for RTEMS.
+*/
+/* #include <machine/asm.h>*/
+
+#define ENTRY(_LABEL) \
+ .global _LABEL; _LABEL:
+
+.globl memcpy
+memcpy:
+
+@ ENTRY(gp2x_memcpy)
+stmfd sp!, {r0, r12, lr}
+@ bl _gp2x_memcpy
+bl _memcpy
+ldmfd sp!, {r0, r12, pc}
+
+
+
+.globl memmove
+memmove:
+
+@ ENTRY(gp2x_memmove)
+stmfd sp!, {r0, r12, lr}
+@ bl _gp2x_memcpy
+bl _memcpy
+ldmfd sp!, {r0, r12, pc}
+
+
+
+/*
+* This is one fun bit of code ...
+* Some easy listening music is suggested while trying to understand this
+* code e.g. Iron Maiden
+*
+* For anyone attempting to understand it :
+*
+* The core code is implemented here with simple stubs for memcpy()
+* memmove() and bcopy().
+*
+* All local labels are prefixed with Lmemcpy_
+* Following the prefix a label starting f is used in the forward copy code
+* while a label using b is used in the backwards copy code
+* The source and destination addresses determine whether a forward or
+* backward copy is performed.
+* Separate bits of code are used to deal with the following situations
+* for both the forward and backwards copy.
+* unaligned source address
+* unaligned destination address
+* Separate copy routines are used to produce an optimised result for each
+* of these cases.
+* The copy code will use LDM/STM instructions to copy up to 32 bytes at
+* a time where possible.
+*
+* Note: r12 (aka ip) can be trashed during the function along with
+* r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out.
+* Additional registers are preserved prior to use i.e. r4, r5 & lr
+*
+* Apologies for the state of the comments;-)
+*/
+
+
+
+_memcpy:
+
+@ ENTRY(_gp2x_memcpy)
+/* Determine copy direction */
+cmp r1, r0
+bcc Lmemcpy_backwards
+
+moveq r0, #0   /* Quick abort for len=0 */
+moveq pc, lr
+
+stmdb sp!, {r0, lr}  /* memcpy() returns dest addr */
+subs r2, r2, #4
+blt Lmemcpy_fl4  /* less than 4 bytes */
+ands r12, r0, #3
+bne Lmemcpy_fdestul  /* oh unaligned destination addr */
+ands r12, r1, #3
+bne Lmemcpy_fsrcul  /* oh unaligned source addr */
+
+Lmemcpy_ft8:
+/* We have aligned source and destination */
+subs r2, r2, #8
+blt Lmemcpy_fl12  /* less than 12 bytes (4 from above) */
+subs r2, r2, #0x14        
+blt Lmemcpy_fl32  /* less than 32 bytes (12 from above) */
+stmdb sp!, {r4, r7, r8, r9, r10}  /* borrow r4 */
+
+/* blat 64 bytes at a time */
+/* XXX for really big copies perhaps we should use more registers */
+Lmemcpy_floop32:
+ldmia r1!, {r3, r4, r7, r8, r9, r10, r12, lr}
+stmia r0!, {r3, r4, r7, r8, r9, r10, r12, lr}
+ldmia r1!, {r3, r4, r7, r8, r9, r10, r12, lr}
+stmia r0!, {r3, r4, r7, r8, r9, r10, r12, lr}
+subs r2, r2, #0x40        
+bge Lmemcpy_floop32
+
+cmn r2, #0x10
+ldmgeia r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
+stmgeia r0!, {r3, r4, r12, lr}
+subge r2, r2, #0x10        
+ldmia sp!, {r4, r7, r8, r9, r10}  /* return r4 */
+
+Lmemcpy_fl32:
+adds r2, r2, #0x14        
+
+/* blat 12 bytes at a time */
+Lmemcpy_floop12:
+ldmgeia r1!, {r3, r12, lr}
+stmgeia r0!, {r3, r12, lr}
+subges r2, r2, #0x0c        
+bge Lmemcpy_floop12
+
+Lmemcpy_fl12:
+adds r2, r2, #8
+blt Lmemcpy_fl4
+
+subs r2, r2, #4
+ldrlt r3, [r1], #4
+strlt r3, [r0], #4
+ldmgeia r1!, {r3, r12}
+stmgeia r0!, {r3, r12}
+subge r2, r2, #4
+
+Lmemcpy_fl4:
+/* less than 4 bytes to go */
+adds r2, r2, #4
+ldmeqia sp!, {r0, pc}  /* done */
+
+/* copy the crud byte at a time */
+cmp r2, #2
+ldrb r3, [r1], #1
+strb r3, [r0], #1
+ldrgeb r3, [r1], #1
+strgeb r3, [r0], #1
+ldrgtb r3, [r1], #1
+strgtb r3, [r0], #1
+ldmia sp!, {r0, pc}
+
+/* erg - unaligned destination */
+Lmemcpy_fdestul:
+rsb r12, r12, #4
+cmp r12, #2
+
+/* align destination with byte copies */
+ldrb r3, [r1], #1
+strb r3, [r0], #1
+ldrgeb r3, [r1], #1
+strgeb r3, [r0], #1
+ldrgtb r3, [r1], #1
+strgtb r3, [r0], #1
+subs r2, r2, r12
+blt Lmemcpy_fl4  /* less the 4 bytes */
+
+ands r12, r1, #3
+beq Lmemcpy_ft8  /* we have an aligned source */
+
+/* erg - unaligned source */
+/* This is where it gets nasty ... */
+Lmemcpy_fsrcul:
+bic r1, r1, #3
+ldr lr, [r1], #4
+cmp r12, #2
+bgt Lmemcpy_fsrcul3
+beq Lmemcpy_fsrcul2
+cmp r2, #0x0c            
+blt Lmemcpy_fsrcul1loop4
+sub r2, r2, #0x0c        
+stmdb sp!, {r4, r5}
+
+Lmemcpy_fsrcul1loop16:
+mov r3, lr, lsr #8
+ldmia r1!, {r4, r5, r12, lr}
+orr r3, r3, r4, lsl #24
+mov r4, r4, lsr #8
+orr r4, r4, r5, lsl #24
+mov r5, r5, lsr #8
+orr r5, r5, r12, lsl #24
+mov r12, r12, lsr #8
+orr r12, r12, lr, lsl #24
+stmia r0!, {r3-r5, r12}
+subs r2, r2, #0x10        
+bge Lmemcpy_fsrcul1loop16
+ldmia sp!, {r4, r5}
+adds r2, r2, #0x0c        
+blt Lmemcpy_fsrcul1l4
+
+Lmemcpy_fsrcul1loop4:
+mov r12, lr, lsr #8
+ldr lr, [r1], #4
+orr r12, r12, lr, lsl #24
+str r12, [r0], #4
+subs r2, r2, #4
+bge Lmemcpy_fsrcul1loop4
+
+Lmemcpy_fsrcul1l4:
+sub r1, r1, #3
+b Lmemcpy_fl4
+
+Lmemcpy_fsrcul2:
+cmp r2, #0x0c            
+blt Lmemcpy_fsrcul2loop4
+sub r2, r2, #0x0c        
+stmdb sp!, {r4, r5}
+
+Lmemcpy_fsrcul2loop16:
+mov r3, lr, lsr #16
+ldmia r1!, {r4, r5, r12, lr}
+orr r3, r3, r4, lsl #16
+mov r4, r4, lsr #16
+orr r4, r4, r5, lsl #16
+mov r5, r5, lsr #16
+orr r5, r5, r12, lsl #16
+mov r12, r12, lsr #16
+orr r12, r12, lr, lsl #16
+stmia r0!, {r3-r5, r12}
+subs r2, r2, #0x10        
+bge Lmemcpy_fsrcul2loop16
+ldmia sp!, {r4, r5}
+adds r2, r2, #0x0c        
+blt Lmemcpy_fsrcul2l4
+
+Lmemcpy_fsrcul2loop4:
+mov r12, lr, lsr #16
+ldr lr, [r1], #4
+orr r12, r12, lr, lsl #16
+str r12, [r0], #4
+subs r2, r2, #4
+bge Lmemcpy_fsrcul2loop4
+
+Lmemcpy_fsrcul2l4:
+sub r1, r1, #2
+b Lmemcpy_fl4
+
+Lmemcpy_fsrcul3:
+cmp r2, #0x0c            
+blt Lmemcpy_fsrcul3loop4
+sub r2, r2, #0x0c        
+stmdb sp!, {r4, r5}
+
+Lmemcpy_fsrcul3loop16:
+mov r3, lr, lsr #24
+ldmia r1!, {r4, r5, r12, lr}
+orr r3, r3, r4, lsl #8
+mov r4, r4, lsr #24
+orr r4, r4, r5, lsl #8
+mov r5, r5, lsr #24
+orr r5, r5, r12, lsl #8
+mov r12, r12, lsr #24
+orr r12, r12, lr, lsl #8
+stmia r0!, {r3-r5, r12}
+subs r2, r2, #0x10        
+bge Lmemcpy_fsrcul3loop16
+ldmia sp!, {r4, r5}
+adds r2, r2, #0x0c        
+blt Lmemcpy_fsrcul3l4
+
+Lmemcpy_fsrcul3loop4:
+mov r12, lr, lsr #24
+ldr lr, [r1], #4
+orr r12, r12, lr, lsl #8
+str r12, [r0], #4
+subs r2, r2, #4
+bge Lmemcpy_fsrcul3loop4
+
+Lmemcpy_fsrcul3l4:
+sub r1, r1, #1
+b Lmemcpy_fl4
+
+Lmemcpy_backwards:
+add r1, r1, r2
+add r0, r0, r2
+subs r2, r2, #4
+blt Lmemcpy_bl4  /* less than 4 bytes */
+ands r12, r0, #3
+bne Lmemcpy_bdestul  /* oh unaligned destination addr */
+ands r12, r1, #3
+bne Lmemcpy_bsrcul  /* oh unaligned source addr */
+
+Lmemcpy_bt8:
+/* We have aligned source and destination */
+subs r2, r2, #8
+blt Lmemcpy_bl12  /* less than 12 bytes (4 from above) */
+stmdb sp!, {r4, r7, r8, r9, r10, lr}
+subs r2, r2, #0x14  /* less than 32 bytes (12 from above) */
+blt Lmemcpy_bl32
+
+/* blat 64 bytes at a time */
+/* XXX for really big copies perhaps we should use more registers */
+Lmemcpy_bloop32:
+ldmdb r1!, {r3, r4, r7, r8, r9, r10, r12, lr}
+stmdb r0!, {r3, r4, r7, r8, r9, r10, r12, lr}
+ldmdb r1!, {r3, r4, r7, r8, r9, r10, r12, lr}
+stmdb r0!, {r3, r4, r7, r8, r9, r10, r12, lr}
+subs r2, r2, #0x40        
+bge Lmemcpy_bloop32
+
+Lmemcpy_bl32:
+cmn r2, #0x10            
+ldmgedb r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
+stmgedb r0!, {r3, r4, r12, lr}
+subge r2, r2, #0x10        
+adds r2, r2, #0x14        
+ldmgedb r1!, {r3, r12, lr} /* blat a remaining 12 bytes */
+stmgedb r0!, {r3, r12, lr}
+subge r2, r2, #0x0c        
+ldmia sp!, {r4, r7, r8, r9, r10, lr}
+
+Lmemcpy_bl12:
+adds r2, r2, #8
+blt Lmemcpy_bl4
+subs r2, r2, #4
+ldrlt r3, [r1, #-4]!
+strlt r3, [r0, #-4]!
+ldmgedb r1!, {r3, r12}
+stmgedb r0!, {r3, r12}
+subge r2, r2, #4
+
+Lmemcpy_bl4:
+/* less than 4 bytes to go */
+adds r2, r2, #4
+moveq pc, lr   /* done */
+
+/* copy the crud byte at a time */
+cmp r2, #2
+ldrb r3, [r1, #-1]!
+strb r3, [r0, #-1]!
+ldrgeb r3, [r1, #-1]!
+strgeb r3, [r0, #-1]!
+ldrgtb r3, [r1, #-1]!
+strgtb r3, [r0, #-1]!
+mov pc, lr
+
+/* erg - unaligned destination */
+Lmemcpy_bdestul:
+cmp r12, #2
+
+/* align destination with byte copies */
+ldrb r3, [r1, #-1]!
+strb r3, [r0, #-1]!
+ldrgeb r3, [r1, #-1]!
+strgeb r3, [r0, #-1]!
+ldrgtb r3, [r1, #-1]!
+strgtb r3, [r0, #-1]!
+subs r2, r2, r12
+blt Lmemcpy_bl4  /* less than 4 bytes to go */
+ands r12, r1, #3
+beq Lmemcpy_bt8  /* we have an aligned source */
+
+/* erg - unaligned source */
+/* This is where it gets nasty ... */
+Lmemcpy_bsrcul:
+bic r1, r1, #3
+ldr r3, [r1, #0]
+cmp r12, #2
+blt Lmemcpy_bsrcul1
+beq Lmemcpy_bsrcul2
+cmp r2, #0x0c            
+blt Lmemcpy_bsrcul3loop4
+sub r2, r2, #0x0c        
+stmdb sp!, {r4, r5, lr}
+
+Lmemcpy_bsrcul3loop16:
+mov lr, r3, lsl #8
+ldmdb r1!, {r3-r5, r12}
+orr lr, lr, r12, lsr #24
+mov r12, r12, lsl #8
+orr r12, r12, r5, lsr #24
+mov r5, r5, lsl #8
+orr r5, r5, r4, lsr #24
+mov r4, r4, lsl #8
+orr r4, r4, r3, lsr #24
+stmdb r0!, {r4, r5, r12, lr}
+subs r2, r2, #0x10        
+bge Lmemcpy_bsrcul3loop16
+ldmia sp!, {r4, r5, lr}
+adds r2, r2, #0x0c        
+blt Lmemcpy_bsrcul3l4
+
+Lmemcpy_bsrcul3loop4:
+mov r12, r3, lsl #8
+ldr r3, [r1, #-4]!
+orr r12, r12, r3, lsr #24
+str r12, [r0, #-4]!
+subs r2, r2, #4
+bge Lmemcpy_bsrcul3loop4
+
+Lmemcpy_bsrcul3l4:
+add r1, r1, #3
+b Lmemcpy_bl4
+
+Lmemcpy_bsrcul2:
+cmp r2, #0x0c            
+blt Lmemcpy_bsrcul2loop4
+sub r2, r2, #0x0c        
+stmdb sp!, {r4, r5, lr}
+
+Lmemcpy_bsrcul2loop16:
+mov lr, r3, lsl #16
+ldmdb r1!, {r3-r5, r12}
+orr lr, lr, r12, lsr #16
+mov r12, r12, lsl #16
+orr r12, r12, r5, lsr #16
+mov r5, r5, lsl #16
+orr r5, r5, r4, lsr #16
+mov r4, r4, lsl #16
+orr r4, r4, r3, lsr #16
+stmdb r0!, {r4, r5, r12, lr}
+subs r2, r2, #0x10        
+bge Lmemcpy_bsrcul2loop16
+ldmia sp!, {r4, r5, lr}
+adds r2, r2, #0x0c        
+blt Lmemcpy_bsrcul2l4
+
+Lmemcpy_bsrcul2loop4:
+mov r12, r3, lsl #16
+ldr r3, [r1, #-4]!
+orr r12, r12, r3, lsr #16
+str r12, [r0, #-4]!
+subs r2, r2, #4
+bge Lmemcpy_bsrcul2loop4
+
+Lmemcpy_bsrcul2l4:
+add r1, r1, #2
+b Lmemcpy_bl4
+
+Lmemcpy_bsrcul1:
+cmp r2, #0x0c            
+blt Lmemcpy_bsrcul1loop4
+sub r2, r2, #0x0c        
+stmdb sp!, {r4, r5, lr}
+
+Lmemcpy_bsrcul1loop32:
+mov lr, r3, lsl #24
+ldmdb r1!, {r3-r5, r12}
+orr lr, lr, r12, lsr #8
+mov r12, r12, lsl #24
+orr r12, r12, r5, lsr #8
+mov r5, r5, lsl #24
+orr r5, r5, r4, lsr #8
+mov r4, r4, lsl #24
+orr r4, r4, r3, lsr #8
+stmdb r0!, {r4, r5, r12, lr}
+subs r2, r2, #0x10        
+bge Lmemcpy_bsrcul1loop32
+ldmia sp!, {r4, r5, lr}
+adds r2, r2, #0x0c        
+blt Lmemcpy_bsrcul1l4
+
+Lmemcpy_bsrcul1loop4:
+mov r12, r3, lsl #24
+ldr r3, [r1, #-4]!
+orr r12, r12, r3, lsr #8
+str r12, [r0, #-4]!
+subs r2, r2, #4
+bge Lmemcpy_bsrcul1loop4
+
+Lmemcpy_bsrcul1l4:
+add r1, r1, #1
+b Lmemcpy_bl4
diff --git a/platform/gp2x/code940/mp3test.c b/platform/gp2x/code940/mp3test.c
new file mode 100644 (file)
index 0000000..9072d85
--- /dev/null
@@ -0,0 +1,383 @@
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include <sys/mman.h>\r
+#include <sys/ioctl.h>\r
+#include <sys/time.h>\r
+#include <fcntl.h>\r
+#include <errno.h>\r
+\r
+#include "940shared.h"\r
+#include "../gp2x.h"\r
+//#include "emu.h"\r
+//#include "menu.h"\r
+#include "../asmutils.h"\r
+#include "../helix/pub/mp3dec.h"\r
+\r
+/* we will need some gp2x internals here */\r
+extern volatile unsigned short *gp2x_memregs; /* from minimal library rlyeh */\r
+extern volatile unsigned long  *gp2x_memregl;\r
+\r
+static unsigned char *shared_mem = 0;\r
+static _940_data_t *shared_data = 0;\r
+static _940_ctl_t *shared_ctl = 0;\r
+static unsigned char *mp3_mem = 0;\r
+\r
+#define MP3_SIZE_MAX (0x1000000 - 4*640*480)\r
+\r
+int crashed_940 = 0;\r
+\r
+\r
+/***********************************************************/\r
+\r
+#define MAXOUT         (+32767)\r
+#define MINOUT         (-32768)\r
+\r
+/* limitter */\r
+#define Limit(val, max,min) { \\r
+       if ( val > max )      val = max; \\r
+       else if ( val < min ) val = min; \\r
+}\r
+\r
+\r
+void wait_busy_940(void)\r
+{\r
+       int i;\r
+#if 0\r
+       printf("940 busy, entering wait loop.. (cnt: %i, wc: %i, ve: ", shared_ctl->loopc, shared_ctl->waitc);\r
+       for (i = 0; i < 8; i++)\r
+               printf("%i ", shared_ctl->vstarts[i]);\r
+       printf(")\n");\r
+\r
+       for (i = 0; shared_ctl->busy; i++)\r
+       {\r
+               spend_cycles(1024); /* needs tuning */\r
+       }\r
+       printf("wait iterations: %i\n", i);\r
+#else\r
+       for (i = 0; shared_ctl->busy && i < 0x10000; i++)\r
+               spend_cycles(8*1024);\r
+       if (i < 0x10000) return;\r
+\r
+       /* 940 crashed */\r
+       printf("940 crashed (cnt: %i, ve: ", shared_ctl->loopc);\r
+       for (i = 0; i < 8; i++)\r
+               printf("%i ", shared_ctl->vstarts[i]);\r
+       printf(")\n");\r
+       crashed_940 = 1;\r
+#endif\r
+}\r
+\r
+\r
+void add_job_940(int job0, int job1)\r
+{\r
+       shared_ctl->jobs[0] = job0;\r
+       shared_ctl->jobs[1] = job1;\r
+       shared_ctl->busy = 1;\r
+       gp2x_memregs[0x3B3E>>1] = 0xffff; // cause an IRQ for 940\r
+}\r
+\r
+\r
+static int read_to_upper(void *dest, void *tmpbuf, int tmpsize, FILE *f)\r
+{\r
+       int nRead, nLen = 0;\r
+\r
+       while(1)\r
+       {\r
+               nRead = fread(tmpbuf, 1, tmpsize, f);\r
+               if(nRead <= 0)\r
+                       break;\r
+               memcpy((unsigned char *)dest + nLen, tmpbuf, nRead);\r
+               nLen += nRead;\r
+       }\r
+\r
+       return nLen;\r
+}\r
+\r
+static void simpleWait(int thissec, int lim_time)\r
+{\r
+       struct timeval tval;\r
+\r
+       spend_cycles(1024);\r
+       gettimeofday(&tval, 0);\r
+       if(thissec != tval.tv_sec) tval.tv_usec+=1000000;\r
+\r
+       while(tval.tv_usec < lim_time)\r
+       {\r
+               spend_cycles(1024);\r
+               gettimeofday(&tval, 0);\r
+               if(thissec != tval.tv_sec) tval.tv_usec+=1000000;\r
+       }\r
+}\r
+\r
+\r
+char **g_argv;\r
+\r
+/* none of the functions in this file should be called before this one */\r
+void YM2612Init_940(int baseclock, int rate)\r
+{\r
+       printf("YM2612Init_940()\n");\r
+       printf("Mem usage: shared_data: %i, shared_ctl: %i\n", sizeof(*shared_data), sizeof(*shared_ctl));\r
+\r
+       Reset940(1, 2);\r
+       Pause940(1);\r
+\r
+       gp2x_memregs[0x3B46>>1] = 0xffff; // clear pending DUALCPU interrupts for 940\r
+       gp2x_memregs[0x3B42>>1] = 0xffff; // enable DUALCPU interrupts for 940\r
+\r
+       gp2x_memregl[0x4508>>2] = ~(1<<26); // unmask DUALCPU ints in the undocumented 940's interrupt controller\r
+\r
+       if (shared_mem == NULL)\r
+       {\r
+               shared_mem = (unsigned char *) mmap(0, 0x210000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0x2000000);\r
+               if(shared_mem == MAP_FAILED)\r
+               {\r
+                       printf("mmap(shared_data) failed with %i\n", errno);\r
+                       exit(1);\r
+               }\r
+               shared_data = (_940_data_t *) (shared_mem+0x100000);\r
+               /* this area must not get buffered on either side */\r
+               shared_ctl =  (_940_ctl_t *)  (shared_mem+0x200000);\r
+               mp3_mem = (unsigned char *) mmap(0, MP3_SIZE_MAX, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0x3000000);\r
+               if (mp3_mem == MAP_FAILED)\r
+               {\r
+                       printf("mmap(mp3_mem) failed with %i\n", errno);\r
+                       exit(1);\r
+               }\r
+               crashed_940 = 1;\r
+       }\r
+\r
+       if (crashed_940)\r
+       {\r
+               unsigned char ucData[1024];\r
+               int i;\r
+               char binpath[1024];\r
+               FILE *fp;\r
+\r
+               strncpy(binpath, g_argv[0], 1023);\r
+               binpath[1023] = 0;\r
+               for (i = strlen(binpath); i > 0; i--)\r
+                       if (binpath[i] == '/') { binpath[i] = 0; break; }\r
+               strcat(binpath, "/code940.bin");\r
+\r
+               fp = fopen(binpath, "rb");\r
+               if(!fp)\r
+               {\r
+                       printf("failed to open %s\n", binpath);\r
+                       exit(1);\r
+               }\r
+\r
+               read_to_upper(shared_mem, ucData, sizeof(ucData), fp);\r
+               fclose(fp);\r
+               crashed_940 = 0;\r
+       }\r
+\r
+       memset(shared_data, 0, sizeof(*shared_data));\r
+       memset(shared_ctl,  0, sizeof(*shared_ctl));\r
+\r
+       /* now cause 940 to init it's ym2612 stuff */\r
+       shared_ctl->baseclock = baseclock;\r
+       shared_ctl->rate = rate;\r
+       shared_ctl->jobs[0] = JOB940_INITALL;\r
+       shared_ctl->jobs[1] = 0;\r
+       shared_ctl->busy = 1;\r
+\r
+       /* start the 940 */\r
+       Reset940(0, 2);\r
+       Pause940(0);\r
+}\r
+\r
+\r
+unsigned char *mp3_data = 0;\r
+\r
+void local_decode(void)\r
+{\r
+       int mp3_offs = shared_ctl->mp3_offs;\r
+       unsigned char *readPtr = mp3_data + mp3_offs;\r
+       int bytesLeft = shared_ctl->mp3_len - mp3_offs;\r
+       int offset; // frame offset from readPtr\r
+       int err = 0;\r
+\r
+       if (bytesLeft <= 0) return; // EOF, nothing to do\r
+\r
+       offset = MP3FindSyncWord(readPtr, bytesLeft);\r
+       if (offset < 0) {\r
+               shared_ctl->mp3_offs = shared_ctl->mp3_len;\r
+               return; // EOF\r
+       }\r
+       readPtr += offset;\r
+       bytesLeft -= offset;\r
+\r
+       err = MP3Decode(shared_data->mp3dec, &readPtr, &bytesLeft,\r
+                       shared_data->mp3_buffer[shared_ctl->mp3_buffsel], 0);\r
+       if (err) {\r
+               if (err == ERR_MP3_INDATA_UNDERFLOW) {\r
+                       shared_ctl->mp3_offs = shared_ctl->mp3_len; // EOF\r
+                       return;\r
+               } else if (err <= -6 && err >= -12) {\r
+                       // ERR_MP3_INVALID_FRAMEHEADER, ERR_MP3_INVALID_*\r
+                       // just try to skip the offending frame..\r
+                       readPtr++;\r
+               }\r
+               shared_ctl->mp3_errors++;\r
+               shared_ctl->mp3_lasterr = err;\r
+       }\r
+       shared_ctl->mp3_offs = readPtr - mp3_data;\r
+}\r
+\r
+\r
+void gp2x_sound_sync(void);\r
+\r
+#define USE_LOCAL 0\r
+#define BENCHMARK 0\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+       FILE *f;\r
+       int size;\r
+       struct timeval tval; // timing\r
+       int thissec = 0, fps = 0;\r
+       int target_frametime, frame_samples, samples_ready, mp3_buffer_offs, play_bufsel;\r
+       unsigned char play_buffer[44100/50*2*2];\r
+\r
+       if (argc != 2) {\r
+               printf("usage: %s <mp3file>\n", argv[0]);\r
+               return 1;\r
+       }\r
+\r
+       g_argv = argv;\r
+\r
+       gp2x_init();\r
+       YM2612Init_940(123, 44100);\r
+\r
+       // load a mp3\r
+       f = fopen(argv[1], "rb");\r
+       if (!f) {\r
+               printf("can't open %s\n", argv[1]);\r
+               return 1;\r
+       }\r
+\r
+       fseek(f, 0, SEEK_END);\r
+       size = (int) ftell(f);\r
+       if (size > MP3_SIZE_MAX) {\r
+               printf("size %i > %i\n", size, MP3_SIZE_MAX);\r
+               size = MP3_SIZE_MAX;\r
+       }\r
+\r
+       fseek(f, 0, SEEK_SET);\r
+       if (fread(mp3_mem, 1, size, f) != size) {\r
+               printf("read failed, errno=%i\n", errno);\r
+               fclose(f);\r
+               exit(1);\r
+       }\r
+       fclose(f);\r
+       shared_ctl->mp3_len = size;\r
+\r
+#if USE_LOCAL\r
+       shared_data->mp3dec = MP3InitDecoder();\r
+       mp3_data = malloc(size);\r
+       printf("init: dec: %p ptr: %p\n", shared_data->mp3dec, mp3_data);\r
+       if (!mp3_data) {\r
+               printf("low mem\n");\r
+               exit(1);\r
+       }\r
+       memcpy(mp3_data, mp3_mem, size);\r
+#else\r
+       //printf("YM2612UpdateOne_940()\n");\r
+       if (shared_ctl->busy) wait_busy_940();\r
+#endif\r
+\r
+       gp2x_start_sound(44100, 16, 1);\r
+\r
+       #define DESIRED_FPS 50\r
+       target_frametime = 1000000/DESIRED_FPS;\r
+       frame_samples = 44100/DESIRED_FPS;\r
+       samples_ready = mp3_buffer_offs = 0;\r
+       play_bufsel = 1;\r
+\r
+       for (;; fps++)\r
+       {\r
+               int lim_time;\r
+\r
+               gettimeofday(&tval, 0);\r
+               if (tval.tv_sec != thissec)\r
+               {\r
+                       printf("fps: %i\n", fps);\r
+                       thissec = tval.tv_sec;\r
+                       fps = 0;\r
+#if BENCHMARK\r
+                       shared_ctl->mp3_offs = 0;\r
+#endif\r
+               }\r
+\r
+#if 0\r
+               // decode\r
+#if USE_LOCAL\r
+               shared_ctl->mp3_buffsel ^= 1;\r
+               local_decode();\r
+#else\r
+               wait_busy_940();\r
+               shared_ctl->mp3_buffsel ^= 1;\r
+               add_job_940(JOB940_MP3DECODE, 0);\r
+#endif\r
+\r
+               if (shared_ctl->mp3_lasterr) {\r
+                       printf("mp3_lasterr #%i: %i size: %i offs: %i\n", shared_ctl->mp3_errors, shared_ctl->mp3_lasterr,\r
+                               shared_ctl->mp3_len, shared_ctl->mp3_offs);\r
+                       printf("loopc: %i bytes: %08x\n",\r
+                               shared_ctl->loopc, *(int *)(mp3_mem+shared_ctl->mp3_offs));\r
+                       shared_ctl->mp3_lasterr = 0;\r
+               }\r
+\r
+#if !BENCHMARK\r
+               // play\r
+               gp2x_sound_sync();\r
+               gp2x_sound_write(shared_data->mp3_buffer[shared_ctl->mp3_buffsel^1], 1152*2*2);\r
+#endif\r
+#else\r
+               lim_time = (fps+1) * target_frametime;\r
+\r
+               wait_busy_940();\r
+\r
+               // decode, play\r
+               if (samples_ready >= frame_samples) {\r
+                       if (1152 - mp3_buffer_offs >= frame_samples) {\r
+                               memcpy(play_buffer, shared_data->mp3_buffer[play_bufsel] + mp3_buffer_offs*2,\r
+                                       frame_samples*2*2);\r
+                               mp3_buffer_offs += frame_samples;\r
+                       } else {\r
+                               // collect from both buffers..\r
+                               int left = 1152 - mp3_buffer_offs;\r
+                               memcpy(play_buffer, shared_data->mp3_buffer[play_bufsel] + mp3_buffer_offs*2,\r
+                                       left*2*2);\r
+                               play_bufsel ^= 1;\r
+                               mp3_buffer_offs = frame_samples - left;\r
+                               memcpy(play_buffer + left*2*2, shared_data->mp3_buffer[play_bufsel],\r
+                                       mp3_buffer_offs*2*2);\r
+                       }\r
+                       gp2x_sound_write(play_buffer, frame_samples*2*2);\r
+                       samples_ready -= frame_samples;\r
+               }\r
+\r
+               // make sure we will have enough samples next frame\r
+               if (samples_ready < frame_samples) {\r
+//                     wait_busy_940();\r
+                       shared_ctl->mp3_buffsel ^= 1;\r
+                       add_job_940(JOB940_MP3DECODE, 0);\r
+                       samples_ready += 1152;\r
+               }\r
+\r
+               gettimeofday(&tval, 0);\r
+               if(thissec != tval.tv_sec) tval.tv_usec+=1000000;\r
+               if(tval.tv_usec < lim_time)\r
+               {\r
+                       // we are too fast\r
+                       simpleWait(thissec, lim_time);\r
+               }\r
+#endif\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
index d1a844f..18c5e48 100644 (file)
@@ -204,6 +204,10 @@ void gp2x_sound_write(void *buff, int len)
        write(sounddev, buff, len);\r
 }\r
 \r
+void gp2x_sound_sync(void)\r
+{\r
+       ioctl(sounddev, SOUND_PCM_SYNC, 0);\r
+}\r
 \r
 void gp2x_sound_volume(int l, int r)\r
 {\r