full ym2612 save/load for 940
[picodrive.git] / platform / gp2x / code940 / 940.c
CommitLineData
6cadc2da 1// The top-level functions for the ARM940\r
2// (c) Copyright 2006-2007, Grazvydas "notaz" Ignotas\r
3\r
cc68a136 4#include "940shared.h"\r
5\r
42c7b147 6static _940_data_t *shared_data = (_940_data_t *) 0x00100000;\r
7static _940_ctl_t *shared_ctl = (_940_ctl_t *) 0x00200000;\r
e362c573 8static unsigned char *mp3_data = (unsigned char *) 0x00400000;\r
cc68a136 9YM2612 *ym2612_940;\r
cc68a136 10\r
11// from init.s\r
abe0ea43 12int wait_get_job(int oldjob);\r
cc68a136 13void spend_cycles(int c);\r
abe0ea43 14void dcache_clean(void);\r
15void dcache_clean_flush(void);\r
16void drain_wb(void);\r
51a902ae 17// this should help to resolve race confition where shared var\r
18// is changed by other core just before we update it\r
19void set_if_not_changed(int *val, int oldval, int newval);\r
cc68a136 20\r
e4fb433c 21void _memcpy(void *dst, const void *src, int count);\r
22\r
cc68a136 23// asm volatile ("mov r0, #0" ::: "r0");\r
24// asm volatile ("mcr p15, 0, r0, c7, c6, 0" ::: "r0"); /* flush dcache */\r
25// asm volatile ("mcr p15, 0, r0, c7, c10, 4" ::: "r0"); /* drain write buffer */\r
26\r
51a902ae 27\r
28static void mp3_decode(void)\r
29{\r
30 int mp3_offs = shared_ctl->mp3_offs;\r
31 unsigned char *readPtr = mp3_data + mp3_offs;\r
32 int bytesLeft = shared_ctl->mp3_len - mp3_offs;\r
33 int offset; // frame offset from readPtr\r
34 int err;\r
35\r
36 if (bytesLeft <= 0) return; // EOF, nothing to do\r
37\r
38 offset = MP3FindSyncWord(readPtr, bytesLeft);\r
39 if (offset < 0) {\r
40 set_if_not_changed(&shared_ctl->mp3_offs, mp3_offs, shared_ctl->mp3_len);\r
41 return; // EOF\r
42 }\r
43 readPtr += offset;\r
44 bytesLeft -= offset;\r
45\r
46 err = MP3Decode(shared_data->mp3dec, &readPtr, &bytesLeft,\r
47 shared_data->mp3_buffer[shared_ctl->mp3_buffsel], 0);\r
48 if (err) {\r
49 if (err == ERR_MP3_INDATA_UNDERFLOW) {\r
51a902ae 50 set_if_not_changed(&shared_ctl->mp3_offs, mp3_offs, shared_ctl->mp3_len);\r
51 return;\r
52 } else if (err <= -6 && err >= -12) {\r
53 // ERR_MP3_INVALID_FRAMEHEADER, ERR_MP3_INVALID_*\r
54 // just try to skip the offending frame..\r
55 readPtr++;\r
56 }\r
57 shared_ctl->mp3_errors++;\r
58 shared_ctl->mp3_lasterr = err;\r
59 }\r
60 set_if_not_changed(&shared_ctl->mp3_offs, mp3_offs, readPtr - mp3_data);\r
61}\r
62\r
e4fb433c 63static void ym_flush_writes(void)\r
64{\r
65 UINT16 *wbuff;\r
66 int i;\r
67\r
68 if (shared_ctl->writebuffsel == 1) {\r
69 wbuff = shared_ctl->writebuff1;\r
70 } else {\r
71 wbuff = shared_ctl->writebuff0;\r
72 }\r
73\r
74 /* playback all writes */\r
75 for (i = 2048; i > 0; i--) {\r
76 UINT16 d = *wbuff++;\r
77 if (d == 0xffff) break;\r
78 if (d == 0xfffe) continue;\r
79 YM2612Write_(d >> 8, d);\r
80 }\r
81}\r
82\r
2433f409 83static void ym_update(int *ym_buffer)\r
84{\r
85 int i, dw;\r
86 int two_upds = 0;\r
87 UINT16 *wbuff;\r
88\r
89 if (shared_ctl->writebuffsel == 1) {\r
90 wbuff = shared_ctl->writebuff1;\r
91 } else {\r
92 wbuff = shared_ctl->writebuff0;\r
93 }\r
94\r
95 /* playback all writes */\r
96 for (i = 2048/2; i > 0; i--) {\r
97 UINT16 d;\r
98 dw = *(int *)wbuff;\r
99 d = dw;\r
100 wbuff++;\r
101 if (d == 0xffff) break;\r
102 if (d == 0xfffe) { two_upds=1; break; }\r
103 YM2612Write_(d >> 8, d);\r
104 d = (dw>>16);\r
105 wbuff++;\r
106 if (d == 0xffff) break;\r
107 if (d == 0xfffe) { two_upds=1; break; }\r
108 YM2612Write_(d >> 8, d);\r
109 }\r
110\r
e4fb433c 111 if (two_upds)\r
112 {\r
2433f409 113 int len1 = shared_ctl->length / 2;\r
114 shared_ctl->ym_active_chs =\r
115 YM2612UpdateOne_(ym_buffer, len1, shared_ctl->stereo, 1);\r
116\r
117 for (i *= 2; i > 0; i--) {\r
118 UINT16 d = *wbuff++;\r
119 if (d == 0xffff) break;\r
120 YM2612Write_(d >> 8, d);\r
121 }\r
122\r
123 ym_buffer += shared_ctl->stereo ? len1*2 : len1;\r
124 len1 = shared_ctl->length - len1;\r
125\r
126 shared_ctl->ym_active_chs =\r
127 YM2612UpdateOne_(ym_buffer, len1, shared_ctl->stereo, 1);\r
128 } else {\r
129 shared_ctl->ym_active_chs =\r
130 YM2612UpdateOne_(ym_buffer, shared_ctl->length, shared_ctl->stereo, 1);\r
131 }\r
132}\r
133\r
51a902ae 134\r
abe0ea43 135void Main940(void)\r
cc68a136 136{\r
abe0ea43 137 int *ym_buffer = shared_data->ym_buffer;\r
138 int job = 0;\r
cc68a136 139 ym2612_940 = &shared_data->ym2612;\r
cc68a136 140\r
cc68a136 141\r
abe0ea43 142 for (;;)\r
cc68a136 143 {\r
abe0ea43 144 job = wait_get_job(job);\r
145\r
146 shared_ctl->lastjob = job;\r
cc68a136 147\r
abe0ea43 148 switch (job)\r
cc68a136 149 {\r
abe0ea43 150 case JOB940_INITALL:\r
151 /* ym2612 */\r
152 shared_ctl->writebuff0[0] = shared_ctl->writebuff1[0] = 0xffff;\r
153 YM2612Init_(shared_ctl->baseclock, shared_ctl->rate);\r
154 /* Helix mp3 decoder */\r
155 shared_data->mp3dec = MP3InitDecoder();\r
156 break;\r
157\r
158 case JOB940_INVALIDATE_DCACHE:\r
159 drain_wb();\r
160 dcache_clean_flush();\r
161 break;\r
162\r
163 case JOB940_YM2612RESETCHIP:\r
164 YM2612ResetChip_();\r
165 break;\r
166\r
167 case JOB940_PICOSTATELOAD:\r
168 YM2612PicoStateLoad_();\r
169 break;\r
170\r
e4fb433c 171 case JOB940_PICOSTATESAVE2:\r
172 YM2612PicoStateSave2(0, 0);\r
173 _memcpy(shared_ctl->writebuff0, ym2612_940->REGS, 0x200);\r
174 break;\r
175\r
176 case JOB940_PICOSTATELOAD2_PREP:\r
177 ym_flush_writes();\r
178 break;\r
179\r
180 case JOB940_PICOSTATELOAD2:\r
181 _memcpy(ym2612_940->REGS, shared_ctl->writebuff0, 0x200);\r
182 YM2612PicoStateLoad2(0, 0);\r
183 break;\r
184\r
2433f409 185 case JOB940_YM2612UPDATEONE:\r
186 ym_update(ym_buffer);\r
abe0ea43 187 break;\r
cc68a136 188\r
abe0ea43 189 case JOB940_MP3DECODE:\r
190 mp3_decode();\r
191 break;\r
192 }\r
42c7b147 193\r
194 shared_ctl->loopc++;\r
abe0ea43 195 dcache_clean();\r
cc68a136 196 }\r
197}\r
b837b69b 198\r