X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=platform%2Fgp2x%2Fcode940%2F940.c;h=90087a3e2fae583e21f485f8ffc5b450abec3713;hb=16b0afd0294a8acde173e2973f9a35eafe0bd185;hp=b242603ba52dae21bf1e4d1ff6a05d786a04d0fc;hpb=abe0ea43b561e2def84cf921b1d6d8c82819ea69;p=picodrive.git diff --git a/platform/gp2x/code940/940.c b/platform/gp2x/code940/940.c index b242603..90087a3 100644 --- a/platform/gp2x/code940/940.c +++ b/platform/gp2x/code940/940.c @@ -1,8 +1,11 @@ +// The top-level functions for the ARM940 +// (c) Copyright 2006-2007, Grazvydas "notaz" Ignotas + #include "940shared.h" static _940_data_t *shared_data = (_940_data_t *) 0x00100000; static _940_ctl_t *shared_ctl = (_940_ctl_t *) 0x00200000; -static unsigned char *mp3_data = (unsigned char *) 0x01000000; +static unsigned char *mp3_data = (unsigned char *) 0x00400000; YM2612 *ym2612_940; // from init.s @@ -15,22 +18,51 @@ void drain_wb(void); // is changed by other core just before we update it void set_if_not_changed(int *val, int oldval, int newval); +void _memcpy(void *dst, const void *src, int count); + // asm volatile ("mov r0, #0" ::: "r0"); // asm volatile ("mcr p15, 0, r0, c7, c6, 0" ::: "r0"); /* flush dcache */ // asm volatile ("mcr p15, 0, r0, c7, c10, 4" ::: "r0"); /* drain write buffer */ +static int find_sync_word(unsigned char *buf, int nBytes) +{ + unsigned char *p, *pe; + + /* find byte-aligned syncword - need 12 (MPEG 1,2) or 11 (MPEG 2.5) matching bits */ + for (p = buf, pe = buf + nBytes - 4; p < pe; p++) + { + int pn; + if (p[0] != 0xff) continue; + pn = p[1]; + if ((pn & 0xf8) != 0xf8 || // currently must be MPEG1 + (pn & 6) == 0) { // invalid layer + p++; continue; + } + pn = p[2]; + if ((pn & 0xf0) < 0x20 || (pn & 0xf0) == 0xf0 || // bitrates + (pn & 0x0c) != 0) { // not 44kHz + continue; + } + + return p - buf; + } + + return -1; +} + static void mp3_decode(void) { int mp3_offs = shared_ctl->mp3_offs; unsigned char *readPtr = mp3_data + mp3_offs; int bytesLeft = shared_ctl->mp3_len - mp3_offs; int offset; // frame offset from readPtr - int err; + int retries = 0, err; if (bytesLeft <= 0) return; // EOF, nothing to do - offset = MP3FindSyncWord(readPtr, bytesLeft); +retry: + offset = find_sync_word(readPtr, bytesLeft); if (offset < 0) { set_if_not_changed(&shared_ctl->mp3_offs, mp3_offs, shared_ctl->mp3_len); return; // EOF @@ -48,6 +80,8 @@ static void mp3_decode(void) // ERR_MP3_INVALID_FRAMEHEADER, ERR_MP3_INVALID_* // just try to skip the offending frame.. readPtr++; + bytesLeft--; + if (retries++ < 2) goto retry; } shared_ctl->mp3_errors++; shared_ctl->mp3_lasterr = err; @@ -55,6 +89,77 @@ static void mp3_decode(void) set_if_not_changed(&shared_ctl->mp3_offs, mp3_offs, readPtr - mp3_data); } +static void ym_flush_writes(void) +{ + UINT16 *wbuff; + int i; + + if (shared_ctl->writebuffsel == 1) { + wbuff = shared_ctl->writebuff1; + } else { + wbuff = shared_ctl->writebuff0; + } + + /* playback all writes */ + for (i = 2048; i > 0; i--) { + UINT16 d = *wbuff++; + if (d == 0xffff) break; + if (d == 0xfffe) continue; + YM2612Write_(d >> 8, d); + } +} + +static void ym_update(int *ym_buffer) +{ + int i, dw; + int two_upds = 0; + UINT16 *wbuff; + + if (shared_ctl->writebuffsel == 1) { + wbuff = shared_ctl->writebuff1; + } else { + wbuff = shared_ctl->writebuff0; + } + + /* playback all writes */ + for (i = 2048/2; i > 0; i--) { + UINT16 d; + dw = *(int *)wbuff; + d = dw; + wbuff++; + if (d == 0xffff) break; + if (d == 0xfffe) { two_upds=1; break; } + YM2612Write_(d >> 8, d); + d = (dw>>16); + wbuff++; + if (d == 0xffff) break; + if (d == 0xfffe) { two_upds=1; break; } + YM2612Write_(d >> 8, d); + } + + if (two_upds) + { + int len1 = shared_ctl->length / 2; + shared_ctl->ym_active_chs = + YM2612UpdateOne_(ym_buffer, len1, shared_ctl->stereo, 1); + + for (i *= 2; i > 0; i--) { + UINT16 d = *wbuff++; + if (d == 0xffff) break; + YM2612Write_(d >> 8, d); + } + + ym_buffer += shared_ctl->stereo ? len1*2 : len1; + len1 = shared_ctl->length - len1; + + shared_ctl->ym_active_chs = + YM2612UpdateOne_(ym_buffer, len1, shared_ctl->stereo, 1); + } else { + shared_ctl->ym_active_chs = + YM2612UpdateOne_(ym_buffer, shared_ctl->length, shared_ctl->stereo, 1); + } +} + void Main940(void) { @@ -92,33 +197,32 @@ void Main940(void) YM2612PicoStateLoad_(); break; - case JOB940_YM2612UPDATEONE: { - int i, dw, *wbuff; - if (shared_ctl->writebuffsel == 1) { - wbuff = (int *) shared_ctl->writebuff1; - } else { - wbuff = (int *) shared_ctl->writebuff0; - } - - /* playback all writes */ - for (i = 2048/2; i > 0; i--) { - UINT16 d; - dw = *wbuff++; - d = dw; - if (d == 0xffff) break; - YM2612Write_(d >> 8, d); - d = (dw>>16); - if (d == 0xffff) break; - YM2612Write_(d >> 8, d); - } - - YM2612UpdateOne_(ym_buffer, shared_ctl->length, shared_ctl->stereo, 1); + case JOB940_PICOSTATESAVE2: + YM2612PicoStateSave2(0, 0); + _memcpy(shared_ctl->writebuff0, ym2612_940->REGS, 0x200); + break; + + case JOB940_PICOSTATELOAD2_PREP: + ym_flush_writes(); + break; + + case JOB940_PICOSTATELOAD2: + _memcpy(ym2612_940->REGS, shared_ctl->writebuff0, 0x200); + YM2612PicoStateLoad2(0, 0); + break; + + case JOB940_YM2612UPDATEONE: + ym_update(ym_buffer); break; - } case JOB940_MP3DECODE: mp3_decode(); break; + + case JOB940_MP3RESET: + if (shared_data->mp3dec) MP3FreeDecoder(shared_data->mp3dec); + shared_data->mp3dec = MP3InitDecoder(); + break; } shared_ctl->loopc++;