wwdsp.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /* important variables */
  2. short mem[0x1000];
  3. #define v_0341 mem[0x0341] /* op#2 saves a copy of 344 here */
  4. #define v_0343 mem[0x0343] /* message type? */
  5. #define v_0344 mem[0x0344] /* low byte of first word of message */
  6. #define v_0345 mem[0x0345] /* copy of second word of message */
  7. #define a_0346 mem[0x0346] /* buffer for message contents, size unknown */
  8. #define v_034e mem[0x034e] /* init to 0, later set to most recent value written in a_04fc */
  9. #define v_0350 mem[0x0350] /* init to 0x0280 (write location of messages) */
  10. #define v_0351 mem[0x0351] /* init to 0x0280 (read location?) */
  11. #define v_0352 mem[0x0352] /* init to 0 (number of messages pending?) */
  12. #define v_0355 mem[0x0355] /* used by op#2, init to 0 */
  13. #define a_0356 (mem+0x0356) /* message contents */
  14. #define a_0388 (mem+0x388) /* where op 2 keeps its message */
  15. #define a_038e (mem+0x38e) /* op#2 saves a copy of 345 here */
  16. #define a_03a8 (mem+0x3a8) /* where op#2 dmas in its data, at least 0x80 */
  17. #define v_03fa mem[0x03fa] /* temp for ax0.h during exception */
  18. #define v_03fb mem[0x03fb] /* temp for ar0 during exception */
  19. #define v_03fc mem[0x03fc] /* temp for r08 during exception */
  20. #define v_03fd mem[0x03fd] /* temp for ac0.h during exception */
  21. #define v_03fe mem[0x03fe] /* temp for ac0.m during exception */
  22. #define v_03ff mem[0x03ff] /* temp for ac0.l during exception */
  23. #define a_04e8 (mem+0x04e8) /* 4 element array */
  24. #define a_04ec (mem+0x04ec) /* 4 element array (empty) */
  25. #define a_04f0 (mem+0x04f0) /* 4 element array */
  26. #define a_04f4 (mem+0x04f4) /* 4 element array (empty) */
  27. #define a_04fc (mem+0x04fc) /* 16 element array, written by messages */
  28. #define a_09a0 (mem+0x09a0) /* 0x50 element array, used by op#2, cleared */
  29. #define a_0a00 (mem+0x0a00) /* 0x50 element array, used by op#2, cleared */
  30. #define a_0b00 (mem+0x0b00) /* array from 0x0b00-0x0bff, involves accelerator? */
  31. #define a_0ca0 (mem+0x0ca0) /* 0x50 element array, used by op#2, cleared */
  32. #define a_0d00 (mem+0x0d00) /* 0x50 element array, used by op#2, cleared */
  33. #define a_0d60 (mem+0x0d60) /* 0x50 element array, used by op#2, cleared */
  34. #define a_0f40 (mem+0x0f40) /* 0x50 element array, used by op#2, cleared */
  35. /* reset exception vector 0x0000 */
  36. void main() {
  37. /* JMP 0x0012 */
  38. /* various inits */
  39. SBCLR(5); /* disable interrupts? */
  40. fcn_0057(); /* init hardware stuff */
  41. for(ac1.m=0x1000,ac0.m=0;ac1.m>0;ac1.m--) mem[ac0.m++]=0; /* clear all vars */
  42. fcn_0688(); /* init some vars */
  43. fcn_04c0(); /* set something up related to the accelerator at a_0b00 */
  44. fcn_0e14(); /* set up a table */
  45. fcn_066a(0); /* send a message */
  46. fcn_0674(0x1111); /* send a message */
  47. v_034e=0;
  48. SBSET(5); /* enable interrupts? */
  49. /* jump to 0x06c5 */
  50. mainloop:
  51. while (v_0352) ; /* while no messages pending */
  52. SBCLR(5); /* do not distrub */
  53. v_0352--; /* important that this be atomic */
  54. SBSET(5);
  55. t=v_0351;
  56. size=mem[t++];
  57. if (!(size&0x8000)) { /* size > 0x7fff invalid */
  58. if (size==0) { /* die on message of length 0? */
  59. /* jump to 0x06f5 */
  60. /* jump to 0x05f0 */
  61. /* TODO: analysis of HALT */
  62. HALT();
  63. }
  64. for (i=size,j=0;i>0;i--) {
  65. a_0356[j++]=mem[t++];
  66. a_0356[j++]=mem[t++];
  67. }
  68. v_0351=t;
  69. /* jump to 0x002f */
  70. /* actual command handling */
  71. v_0345=a_0356[1];
  72. v_0344=a_0356[0]&0x00ff;
  73. v_0343=(a_0346[0]>>7)&0x7e;
  74. /* jump table at 0x75 used here */
  75. switch (v_0343>>1) {
  76. // 0x43
  77. case 0:
  78. case 10:
  79. case 11:
  80. case 12:
  81. case 14:
  82. case 15:
  83. /* invalid command? */
  84. config=0x00ff;
  85. fcn_066a(0x04); /* send off a message */
  86. fcn_0674(a_0356[0]); /* send first word of command as a message */
  87. goto mainloop;
  88. break;
  89. case 1:
  90. /* jmp 0x0095 */
  91. break;
  92. case 2:
  93. /* jmp 0x0243 */
  94. sub_0243();
  95. break;
  96. case 3:
  97. /* jmp 0x0073 */
  98. break;
  99. case 4:
  100. /* jmp 0x580 */
  101. break;
  102. case 5:
  103. /* jmp 0x592 */
  104. break;
  105. case 6:
  106. /* jmp 0x469 */
  107. break;
  108. case 7:
  109. /* jmp 0x41d */
  110. break;
  111. case 8: /* mix */
  112. /* jmp 0x0485 */
  113. fcn_0067(fcn_0067(0x0346)); /* read message twice? */
  114. /* take in the two buffers to mix */
  115. fcn_0525(mem[0x344],mem[0x346],mem[0x347],0x400); /* size, addrH, addrL, dsp addr */
  116. fcn_0525(mem[0x344],mem[0x348],mem[0x349],0x800);
  117. S16(); /* saturate all adds, multiplies to 16 bits? */
  118. i=mem[0x0344];
  119. src1=0x400;
  120. src2=0x800;
  121. scale=mem[0x345];
  122. prod=scale*mem[src2++];
  123. val2=mem[src2++];
  124. do {
  125. val1=mem[src1];
  126. val1+=prod;
  127. prod=scale*val2;
  128. mem[src1]=val1;
  129. val2=mem[src2];
  130. src1++;
  131. src2++;
  132. } while (--i);
  133. S40();
  134. /* dma out mixed buf */
  135. fcn_0523(mem[0x344],mem[0x346],mem[0x347],0x400);
  136. break;
  137. case 9:
  138. /* jmp 0x44d */
  139. break;
  140. case 13:
  141. /* jmp 0x00b2 */
  142. break;
  143. }
  144. }
  145. v_0351=t;
  146. goto mainloop;
  147. }
  148. /* message in MBOX exception vector? 0x000e */
  149. void exception() {
  150. /* JMP 0x05b8 */
  151. SBCLR(5);
  152. S40();
  153. /* save ax0.h,ac0.h,ac0.m, and ac0.l */
  154. if ((tH=register_fffe)&0x8000) { /* CPU mailbox H */
  155. if (!(tsize=register_ffff)) { /* CPU mailbox L */
  156. /* empty message? */
  157. while (!((tH=register_fffe)&0x8000)) ;
  158. tH&=0xf;
  159. v_034e=(tH+1)<<4;
  160. a_04fc[tH]=register_ffff;
  161. } else { /* nonempty message? */
  162. /* jump to 0x0692 */
  163. /* save ar0, r08 */
  164. t=v_0350;
  165. mem[t++]=tsize;
  166. do {
  167. while (!((tH=register_fffe)&0x8000)) ;
  168. mem[t++]=tH;
  169. mem[t++]=register_ffff;
  170. } while (--tsize);
  171. v_0350=t;
  172. v_0352++;
  173. /* restore ar0, r08 */
  174. /* jump to 0x05e6 */
  175. }
  176. } else { /* interrupt without message? */
  177. /* jump to 0x06b9 */
  178. /* save ar0, r08 */
  179. mem[v_0350]=0; /* empty message */
  180. /* jump to 0x06ab */
  181. v_0350++;
  182. v_0352++;
  183. /* restore ar0, r08 */
  184. /* jump to 0x05e6 */
  185. }
  186. /* 0x05e6 */
  187. /* restore ax0.h,ac0.h,ac0.m, and ac0.l */
  188. SBSET(5);
  189. /* RTI */
  190. }
  191. /* set up some registers */
  192. void fcn_0057() {
  193. SBCLR(2);
  194. SBCLR(3);
  195. SBCLR(4);
  196. SBCLR(6);
  197. S40(); /* 40-bit mode */
  198. CLR15();
  199. M0(); /* don't multiply result by 2 */
  200. r08=-1;
  201. r09=-1;
  202. r0a=-1;
  203. r0b=-1;
  204. config=0xff;
  205. }
  206. void fcn_0688() {
  207. v_0350=0x0280;
  208. v_0351=0x0280;
  209. v_0352=0;
  210. }
  211. void fcn_04c0() {
  212. config=0xff;
  213. for(i=0xff,ar0=0xb00;i>0;i--) mem[ar0++]=0;
  214. mem[ar0++]=0; /* get the last one */
  215. fcn_0573(0x0b00,0x0100,0);
  216. }
  217. /* a=an address in ac1.m, l=a length in ar0, v=a value? in ac0.m */
  218. void fcn_0573(short a, short l, short v) {
  219. fcn_0561(a,l,0x0001);
  220. }
  221. /* a=an address in ac1.m, l=a length in ar0, v=a value? in ac0.m, f is a flag? in ac0.h */
  222. /* return is in ax0.h */
  223. short fcn_0561(short a, short l, short v, short f) {
  224. register_ffd1=0x0a; /* unknown reg, accel? */
  225. register_ffd6=-1; /* accel end addr H */
  226. register_ffd7=-1; /* accel end addr L */
  227. register_ffd8=v>>1; /*
  228. register_ffd9=?; /* has a value from way back? */
  229. return f;
  230. }
  231. /* initializes some tables that look useful... */
  232. void fcn_0e14() {
  233. a_04e8[0]=0x8240;
  234. a_04e8[1]=0x7fff;
  235. a_04e8[2]=0x7dbf;
  236. a_04e8[3]=0x843f;
  237. a_04f0[0]=0xb23b;
  238. a_04f0[1]=0x7fff;
  239. a_04f0[2]=0x4dc4;
  240. a_04f0[3]=0xd808;
  241. a_04ec[0]=a_04ec[1]=a_04ec[2]=a_04ec[3]=0;
  242. a_04f4[0]=a_04f4[1]=a_04f4[2]=a_04f4[3]=0;
  243. }
  244. /* send a message via DSP MBOX */
  245. void fcn_066a(short m) {
  246. fcn_0682(); /* wait for empty mbox */
  247. register_fffc=0xdcd1;
  248. register_fffd=m;
  249. register_fffb=1; /* IRQ */
  250. fcn_0682();
  251. }
  252. /* wait for dsp mbox empty */
  253. void fcn_0682() {
  254. while (register_fffc&0x8000);
  255. }
  256. void fcn_0674(short m) {
  257. fcn_0682();
  258. register_fffc=0xf355;
  259. register_fffd=m;
  260. fcn_0682();
  261. }
  262. /* a=address in ar0 */
  263. /* fetch a message body (up to zero)? */
  264. short fcn_0067(short a) {
  265. i=0x0357;
  266. j=a;
  267. do {
  268. mem[j++]=mem[i++];
  269. mem[j++]=mem[i];
  270. } while (mem[i++]);
  271. return a;
  272. }
  273. /* dma in, I assume */
  274. /* size=words to transfer in ar0, addrL=low word of RAM address in ac0.l, addrH=high word of RAM address in ac0.m, dspaddr=dsp address in ac1.m */
  275. void fcn_0525(short size, short addrH, short addrL, short dspaddr) {
  276. register_ffcd=dspaddr; /* dsp address */
  277. register_ffc9=0; /* direction: ram->dsp */
  278. register_ffce=addrH; /* memory address H */
  279. register_ffcf=addrL; /* memory address L */
  280. register_ffcb=size<<1; /* bytes to transfer (size must be in words) */
  281. fcn_0536(); /* dma wait */
  282. }
  283. /* dma wait? */
  284. void fcn_0536() {
  285. while (!(register_ffc9&4));
  286. }
  287. /* dma out, I assume */
  288. /* size=words to transfer in ar0, addrL=low word of RAM address is ac0.l, addrH=high word of RAM address in ac0.m, dspaddr=dsp address in ac1.m */
  289. /* shares code with fcn_0525 */
  290. void fcn_0523(short size, short addrH, short addrL, shot dspaddr) {
  291. register_ffcd=dspaddr;
  292. /* jump back into 0525 */
  293. register_ffc9=1; /* direction dsp->ram */
  294. register_ffce=addrH;
  295. register_ffcf=addrL;
  296. register_ffcb=size<<1;
  297. fcn_0536();
  298. }
  299. /* huge subroutine, op #2 */
  300. void sub_0243() {
  301. fcn_0067(0x0388); /* called in an indirect manner... */
  302. v_0341=v_0344; /* low byte first word of message */
  303. v_038e=v_0345;
  304. v_0355=0;
  305. fcn_022a(); /* get stuffs */
  306. fcn_05a4(); /* write to accel */
  307. for (i=v_0341;i>0i--) {
  308. fcn_0102();
  309. }
  310. }
  311. void fcn_022a() {
  312. /* something else must set 386, 387 */
  313. fcn_0525(0x0040,v_0386,v_0387,0x03a8);
  314. }
  315. void fcn_05a4() {
  316. register_ffd4=-1;
  317. register_ffd5=-1;
  318. register_ffd6=-1;
  319. register_ffd7=-1;
  320. }
  321. void fcn_0102() {
  322. for (i=0;i<0x50;i++) a_0d00[i]=0;
  323. for (i=0;i<0x50;i++) a_0d60[i]=0;
  324. fcn_0e3f();
  325. for (i=0;i<0x50;i++) a_0ca0[i]=0;
  326. for (i=0;i<0x50;i++) a_0f40[i]=0;
  327. for (i=0;i<0x50;i++) a_0fa0[i]=0;
  328. for (i=0;i<0x50;i++) a_0a00[i]=0;
  329. for (i=0;i<0x50;i++) a_09a0[i]=0;
  330. }
  331. void fcn_0e3f() {
  332. fcn_00fa(0x0f40,0x0b00,0x50,0x6784);
  333. fcn_0ba4(0x04e8,0x0b00,0x04ec);
  334. }
  335. /* addr1=address in ar0, addr2=address in ar3, size=size of table at addr1 in ac1.m, val=in ax0.l */
  336. void fcn_00fa(short addr1, short addr2, short size, short val) {
  337. M2(); /* all multiplications 2x */
  338. tmp=mem[addr1++];
  339. prod=val*tmp*2;
  340. tmp=mem[addr1++];
  341. ac0.m=prod;
  342. prod=val*tmp*2;
  343. tmp=mem[addr1++];
  344. do {
  345. ac0.m=prod;
  346. prod=val*tmp*2;
  347. mem[addr2]=ac0.m;
  348. tmp=mem[addr1];
  349. addr1++;
  350. addr2++;
  351. } while (--size);
  352. M0();
  353. }
  354. /* addr1=address in ar0 (source 4 element table?), addr2=address in ar1 (accelerator?), addr3=address in ar2 (destination 4 element table?) */
  355. void fcn_00ba4(short addr1, short addr2, short addr3) {
  356. }