\r
int sound_render(int offset, int length)\r
{\r
+ int buf32_updated = 0;\r
int *buf32 = PsndBuffer+offset;\r
int stereo = (PicoOpt & 8) >> 3;\r
// emulating CD && PCM option enabled && PCM chip on && have enabled channels\r
\r
// Add in the stereo FM buffer\r
if (PicoOpt & 1)\r
- YM2612UpdateOne(buf32, length, stereo, 1);\r
+ buf32_updated = YM2612UpdateOne(buf32, length, stereo, 1);\r
+\r
+//printf("active_chs: %02x\n", buf32_updated);\r
\r
// CD: PCM sound\r
- if (do_pcm)\r
+ if (do_pcm) {\r
pcm_update(buf32, length, stereo);\r
+ //buf32_updated = 1;\r
+ }\r
\r
// CD: CDDA audio\r
if ((PicoMCD & 1) && (PicoOpt & 0x800))\r
UINT32 eg_timer;\r
UINT32 eg_timer_add;\r
UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]\r
- UINT32 algo; /* 50 */\r
+ UINT32 algo; /* 50: algo[3], was_update */\r
INT32 op1_out;\r
} chan_rend_context;\r
\r
} else {\r
buffer[scounter] += smp;\r
}\r
+ ct->algo = 8; // algo is only used in asm, here only bit3 is used\r
}\r
\r
/* update phase counters AFTER output calculations */\r
#endif\r
\r
\r
-static void chan_render(int *buffer, int length, FM_CH *CH, UINT32 flags) // flags: stereo, lastchan, disabled, ?, pan_r, pan_l\r
+static int chan_render(int *buffer, int length, FM_CH *CH, UINT32 flags) // flags: stereo, lastchan, disabled, ?, pan_r, pan_l\r
{\r
chan_rend_context ct;\r
\r
CH->SLOT[SLOT3].phase = ct.phase3;\r
CH->SLOT[SLOT4].phase = ct.phase4;\r
CH->mem_value = ct.mem;\r
+\r
+ return (ct.algo & 8) >> 3; // had output\r
}\r
\r
/* update phase increment and envelope generator */\r
int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)\r
{\r
int pan;\r
+ int active_chs = 0;\r
\r
// if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash\r
if (is_buf_empty) memset32(buffer, 0, length<<stereo);\r
if (stereo) stereo = 1;\r
\r
/* mix to 32bit dest */\r
- chan_render(buffer, length, &ym2612.CH[0], stereo|((pan&0x003)<<4)); // flags: stereo, lastchan, disabled, ?, pan_r, pan_l\r
- chan_render(buffer, length, &ym2612.CH[1], stereo|((pan&0x00c)<<2));\r
- chan_render(buffer, length, &ym2612.CH[2], stereo|((pan&0x030) ));\r
- chan_render(buffer, length, &ym2612.CH[3], stereo|((pan&0x0c0)>>2));\r
- chan_render(buffer, length, &ym2612.CH[4], stereo|((pan&0x300)>>4));\r
- chan_render(buffer, length, &ym2612.CH[5], stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)|2);\r
-\r
- return 1; // buffer updated\r
+ // flags: stereo, lastchan, disabled, ?, pan_r, pan_l\r
+ active_chs |= chan_render(buffer, length, &ym2612.CH[0], stereo|((pan&0x003)<<4)) << 0;\r
+ active_chs |= chan_render(buffer, length, &ym2612.CH[1], stereo|((pan&0x00c)<<2)) << 1;\r
+ active_chs |= chan_render(buffer, length, &ym2612.CH[2], stereo|((pan&0x030) )) << 2;\r
+ active_chs |= chan_render(buffer, length, &ym2612.CH[3], stereo|((pan&0x0c0)>>2)) << 3;\r
+ active_chs |= chan_render(buffer, length, &ym2612.CH[4], stereo|((pan&0x300)>>4)) << 4;\r
+ active_chs |= chan_render(buffer, length, &ym2612.CH[5], stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)|2) << 5;\r
+\r
+ return active_chs; // 1 if buffer updated\r
}\r
\r
\r
#define YM2612PicoStateLoad YM2612PicoStateLoad_\r
#else\r
/* GP2X specific */\r
-#include "../../platform/gp2x/940ctl_ym2612.h"\r
+#include "../../platform/gp2x/940ctl.h"\r
extern int PicoOpt;\r
#define YM2612Init(baseclock,rate) { \\r
if (PicoOpt&0x200) YM2612Init_940(baseclock, rate); \\r
if (PicoOpt&0x200) YM2612ResetChip_940(); \\r
else YM2612ResetChip_(); \\r
}\r
-#define YM2612UpdateOne(buffer,length,stereo,is_buf_empty) { \\r
- if (PicoOpt&0x200) YM2612UpdateOne_940(buffer, length, stereo, is_buf_empty); \\r
- else YM2612UpdateOne_(buffer, length, stereo, is_buf_empty); \\r
-}\r
+#define YM2612UpdateOne(buffer,length,stereo,is_buf_empty) \\r
+ (PicoOpt&0x200) ? YM2612UpdateOne_940(buffer, length, stereo, is_buf_empty) : \\r
+ YM2612UpdateOne_(buffer, length, stereo, is_buf_empty);\r
#define YM2612Write(a,v) \\r
(PicoOpt&0x200) ? YM2612Write_940(a, v) : YM2612Write_(a, v)\r
#define YM2612Read() \\r
@ it does not seem to give much performance increase (if any at all), so don't use it if it causes trouble.
@ - notaz, 2006
+@ vim:filetype=armasm
+
.equiv SLOT1, 0
.equiv SLOT2, 2
.equiv SLOT3, 1
@ lr=context, r12=pack (stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
-@ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|algo, r5=tl_tab/slot,
+@ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|unused[4],was_update,algo[3], r5=tl_tab/slot,
@ r6-r7=vol_out[4], r8=eg_timer, r9=eg_timer_add[31:16], r10=op1_out, r11=buffer
.global chan_render_loop @ chan_rend_context *ct, int *buffer, int length
@ -- WRITE SAMPLE --
tst r0, r0
beq ctl_sample_skip
+ orr r4, r4, #8 @ have_output
tst r12, #1
beq ctl_sample_mono
crl_loop_end:
str r8, [lr, #0x44] @ eg_timer
str r12, [lr, #0x4c] @ pack (for lfo_ampm)
+ str r4, [lr, #0x50] @ was_update
str r10, [lr, #0x54] @ op1_out
ldmfd sp!, {r4-r11,pc}
}\r
\r
\r
+void sharedmem_deinit(void)\r
+{\r
+ munmap(shared_mem, 0x210000);\r
+ munmap(mp3_mem, MP3_SIZE_MAX);\r
+ shared_mem = mp3_mem = NULL;\r
+ shared_data = NULL;\r
+ shared_ctl = NULL;\r
+}\r
+\r
+\r
extern char **g_argv;\r
\r
/* none of the functions in this file should be called before this one */\r
int YM2612UpdateOne_940(int *buffer, int length, int stereo, int is_buf_empty)\r
{\r
int *ym_buf = shared_data->ym_buffer;\r
+ int ym_active_chs;\r
\r
//printf("YM2612UpdateOne_940()\n");\r
\r
if (CHECK_BUSY(JOB940_YM2612UPDATEONE)) wait_busy_940(JOB940_YM2612UPDATEONE);\r
\r
- // mix in ym buffer\r
- if (is_buf_empty) memcpy32(buffer, ym_buf, length<<stereo);\r
- // else TODO\r
+ ym_active_chs = shared_ctl->ym_active_chs;\r
\r
-// for (len = length << stereo; len > 0; len--)\r
-// {\r
-// *dest_buf++ += *ym_buf++;\r
-// }\r
+ // mix in ym buffer. is_buf_empty means nobody mixed there anything yet and it may contain trash\r
+ if (is_buf_empty && ym_active_chs) memcpy32(buffer, ym_buf, length<<stereo);\r
+ else memset32(buffer, 0, length<<stereo);\r
\r
if (shared_ctl->writebuffsel == 1) {\r
shared_ctl->writebuff0[writebuff_ptr] = 0xffff;\r
\r
add_job_940(JOB940_YM2612UPDATEONE);\r
\r
- return 1;\r
+ return ym_active_chs;\r
}\r
\r
\r
void sharedmem_init(void);\r
+void sharedmem_deinit(void);\r
\r
void YM2612Init_940(int baseclock, int rate);\r
void YM2612ResetChip_940(void);\r
# frontend\r
OBJS += main.o menu.o gp2x.o usbjoy.o emu.o squidgehack.o asmutils.o cpuctrl.o\r
# 940 core control\r
-OBJS += 940ctl_ym2612.o\r
+OBJS += 940ctl.o\r
# Pico\r
OBJS += ../../Pico/Area.o ../../Pico/Cart.o ../../Pico/Utils.o ../../Pico/Memory.o ../../Pico/Misc.o \\r
../../Pico/Pico.o ../../Pico/Sek.o ../../Pico/VideoPort.o ../../Pico/Draw2.o ../../Pico/Draw.o\r
YM2612Write_(d >> 8, d);\r
}\r
\r
- YM2612UpdateOne_(ym_buffer, shared_ctl->length, shared_ctl->stereo, 1);\r
+ shared_ctl->ym_active_chs =\r
+ YM2612UpdateOne_(ym_buffer, shared_ctl->length, shared_ctl->stereo, 1);\r
break;\r
}\r
\r
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 ym_active_chs;\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
#define FRAMEBUFF_ADDR3 0x4000000-640*480*4\r
\r
static const int gp2x_screenaddrs[] = { FRAMEBUFF_ADDR0, FRAMEBUFF_ADDR1, FRAMEBUFF_ADDR2, FRAMEBUFF_ADDR3 };\r
+static unsigned short gp2x_screenaddr_old[4];\r
\r
\r
/* video stuff */\r
gp2x_screen = gp2x_screens[0];\r
screensel = 0;\r
\r
+ gp2x_screenaddr_old[0] = gp2x_memregs[0x290E>>1];\r
+ gp2x_screenaddr_old[1] = gp2x_memregs[0x2910>>1];\r
+ gp2x_screenaddr_old[2] = gp2x_memregs[0x2912>>1];\r
+ gp2x_screenaddr_old[3] = gp2x_memregs[0x2914>>1];\r
+\r
// snd\r
mixerdev = open("/dev/mixer", O_RDWR);\r
if (mixerdev == -1)\r
Pause940(1);\r
\r
gp2x_video_changemode(15);\r
+ gp2x_memregs[0x290E>>1] = gp2x_screenaddr_old[0];\r
+ gp2x_memregs[0x2910>>1] = gp2x_screenaddr_old[1];\r
+ gp2x_memregs[0x2912>>1] = gp2x_screenaddr_old[2];\r
+ gp2x_memregs[0x2914>>1] = gp2x_screenaddr_old[3];\r
+\r
munmap(gp2x_screens[0], 640*480*4);\r
munmap((void *)gp2x_memregs, 0x10000);\r
close(memdev);\r
#include "gp2x.h"\r
#include "menu.h"\r
#include "emu.h"\r
+#include "940ctl.h"\r
#include "version.h"\r
\r
#include "squidgehack.h"\r
set_RAM_Timings(6, 4, 1, 1, 1, 2, 2);\r
printf("done.\n"); fflush(stdout);\r
}\r
+ sharedmem_init();\r
emu_Init();\r
\r
engineState = PGS_Menu;\r
endloop:\r
\r
emu_Deinit();\r
+ sharedmem_deinit();\r
cpuctrl_deinit();\r
gp2x_deinit();\r
if(mmuhack_status)\r