Previous 15994 Revisions Next

r7622 Monday 22nd March, 2010 at 18:01:38 UTC by Fabio Priuli
[SNES] updated DSP1, DSP2, DSP3, DSP4, OBC1, SRTC and ST010 addon chips to store their variables in a struct
[src/mame/machine]snes.c snesdsp1.c snesdsp2.c snesdsp3.c snesdsp4.c snesdsp4.h snesobc1.c snesrtc.c snesst10.c

src/mame/machine/snesdsp2.c
r7621r7622
1313
1414***************************************************************************/
1515
16static int DSP2_waiting_for_command = 0;
17static int DSP2_command = 0;
18static int DSP2_in_count = 0,  DSP2_in_index = 0;
19static int DSP2_out_count = 0, DSP2_out_index = 0;
16struct _snes_dsp2_state
17{
18   int waiting_for_command;
19   int command;
20   int in_count, in_index;
21   int out_count, out_index;
2022
21static UINT8 DSP2_parameters[512] = {0};
22static UINT8 DSP2_output[512] = {0};
23   UINT8 parameters[512];
24   UINT8 output[512];
2325
24static UINT8 DSP2_op05transparent = 0;
25static int DSP2_op05haslen = 0;
26static int DSP2_op05len = 0;
27static int DSP2_op06haslen = 0;
28static int DSP2_op06len = 0;
29static UINT16 DSP2_op09word1 = 0;
30static UINT16 DSP2_op09word2 = 0;
31static int DSP2_op0dhaslen = 0;
32static int DSP2_op0doutlen = 0;
33static int DSP2_op0dinlen = 0;
26   UINT8 op05transparent;
27   int op05haslen;
28   int op05len;
29   int op06haslen;
30   int op06len;
31   UINT16 op09word1;
32   UINT16 op09word2;
33   int op0dhaslen;
34   int op0doutlen;
35   int op0dinlen;
36};
3437
38static struct _snes_dsp2_state  dsp2_state;
3539
40
41static void dsp2_register_save(running_machine *machine);
42
3643//convert bitmap to bitplane tile
37static void DSP2_op01( void )
44static void dsp2_op01( void )
3845{
3946//op01 size is always 32 bytes input and output
4047//the hardware does strange things if you vary the size
4148
4249   unsigned char c0, c1, c2, c3;
43   unsigned char *p1  = DSP2_parameters;
44   unsigned char *p2a = DSP2_output;
45   unsigned char *p2b = DSP2_output + 16; //halfway
50   unsigned char *p1  = dsp2_state.parameters;
51   unsigned char *p2a = dsp2_state.output;
52   unsigned char *p2b = dsp2_state.output + 16; //halfway
4653   int j;
4754
4855//process 8 blocks of 4 bytes each
r7621r7622
9299}
93100
94101//set transparent color
95static void DSP2_op03( void )
102static void dsp2_op03( void )
96103{
97   DSP2_op05transparent = DSP2_parameters[0];
104   dsp2_state.op05transparent = dsp2_state.parameters[0];
98105}
99106
100107//replace bitmap using transparent color
101static void DSP2_op05( void )
108static void dsp2_op05( void )
102109{
103110   UINT8 color;
104111// Overlay bitmap with transparency.
r7621r7622
127134// proven necessary.
128135
129136   unsigned char c1, c2;
130   unsigned char *p1 = DSP2_parameters;
131   unsigned char *p2 = DSP2_parameters + DSP2_op05len;
132   unsigned char *p3 = DSP2_output;
137   unsigned char *p1 = dsp2_state.parameters;
138   unsigned char *p2 = dsp2_state.parameters + dsp2_state.op05len;
139   unsigned char *p3 = dsp2_state.output;
133140   int n;
134141
135   color = DSP2_op05transparent & 0x0f;
142   color = dsp2_state.op05transparent & 0x0f;
136143
137   for (n = 0; n < DSP2_op05len; n++)
144   for (n = 0; n < dsp2_state.op05len; n++)
138145   {
139146      c1 = *p1++;
140147      c2 = *p2++;
141      *p3++ = ( ((c2 >> 4)   == color ) ? c1 & 0xf0 : c2 & 0xf0 ) |
142            ( ((c2 & 0x0f) == color ) ? c1 & 0x0f : c2 & 0x0f );
148      *p3++ = (((c2 >> 4) == color) ? c1 & 0xf0 : c2 & 0xf0) |
149            (((c2 & 0x0f) == color) ? c1 & 0x0f : c2 & 0x0f);
143150   }
144151}
145152
146153//reverse bitmap
147static void DSP2_op06( void )
154static void dsp2_op06( void )
148155{
149156// Input:
150157//    size
151158//    bitmap
152159   int i, j;
153   for (i = 0, j = DSP2_op06len - 1; i < DSP2_op06len; i++, j--)
160   for (i = 0, j = dsp2_state.op06len - 1; i < dsp2_state.op06len; i++, j--)
154161   {
155      DSP2_output[j] = (DSP2_parameters[i] << 4) | (DSP2_parameters[i] >> 4);
162      dsp2_state.output[j] = (dsp2_state.parameters[i] << 4) | (dsp2_state.parameters[i] >> 4);
156163   }
157164}
158165
159166//multiply
160static void DSP2_op09( void )
167static void dsp2_op09( void )
161168{
162169   UINT32 r = 0;
163   DSP2_out_count = 4;
170   dsp2_state.out_count = 4;
164171
165   DSP2_op09word1 = DSP2_parameters[0] | (DSP2_parameters[1] << 8);
166   DSP2_op09word2 = DSP2_parameters[2] | (DSP2_parameters[3] << 8);
172   dsp2_state.op09word1 = dsp2_state.parameters[0] | (dsp2_state.parameters[1] << 8);
173   dsp2_state.op09word2 = dsp2_state.parameters[2] | (dsp2_state.parameters[3] << 8);
167174
168   r = DSP2_op09word1 * DSP2_op09word2;
169   DSP2_output[0] = r;
170   DSP2_output[1] = r >> 8;
171   DSP2_output[2] = r >> 16;
172   DSP2_output[3] = r >> 24;
175   r = dsp2_state.op09word1 * dsp2_state.op09word2;
176   dsp2_state.output[0] = r;
177   dsp2_state.output[1] = r >> 8;
178   dsp2_state.output[2] = r >> 16;
179   dsp2_state.output[3] = r >> 24;
173180}
174181
175182//scale bitmap
176static void DSP2_op0d( void )
183static void dsp2_op0d( void )
177184{
178185// Bit accurate hardware algorithm - uses fixed point math
179186// This should match the DSP2 Op0D output exactly
r7621r7622
193200   UINT32 pixloc;     // match size of multiplier
194201   int    i, j;
195202   UINT8  pixelarray[512];
196   if (DSP2_op0dinlen <= DSP2_op0doutlen)
203   if (dsp2_state.op0dinlen <= dsp2_state.op0doutlen)
197204   {
198205      multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1
199206   }
200207   else
201208   {
202      multiplier = (DSP2_op0dinlen << 17) / ((DSP2_op0doutlen << 1) + 1);
209      multiplier = (dsp2_state.op0dinlen << 17) / ((dsp2_state.op0doutlen << 1) + 1);
203210   }
204211
205212   pixloc = 0;
206   for (i = 0; i < DSP2_op0doutlen * 2; i++)
213   for (i = 0; i < dsp2_state.op0doutlen * 2; i++)
207214   {
208215      j = pixloc >> 16;
209216
210217      if (j & 1)
211         pixelarray[i] = (DSP2_parameters[j >> 1] & 0x0f);
218         pixelarray[i] = (dsp2_state.parameters[j >> 1] & 0x0f);
212219      else
213         pixelarray[i] = (DSP2_parameters[j >> 1] & 0xf0) >> 4;
220         pixelarray[i] = (dsp2_state.parameters[j >> 1] & 0xf0) >> 4;
214221
215222      pixloc += multiplier;
216223   }
217224
218   for (i = 0; i < DSP2_op0doutlen; i++)
225   for (i = 0; i < dsp2_state.op0doutlen; i++)
219226   {
220      DSP2_output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1];
227      dsp2_state.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1];
221228   }
222229}
223230
224231
225static void DSP2_reset( void )
232static void dsp2_init( running_machine *machine )
226233{
227   DSP2_waiting_for_command = 1;
228   DSP2_in_count  = 0;
229   DSP2_in_index  = 0;
230   DSP2_out_count = 0;
231   DSP2_out_index = 0;
234   dsp2_state.waiting_for_command = 1;
235   dsp2_state.in_count  = 0;
236   dsp2_state.in_index  = 0;
237   dsp2_state.out_count = 0;
238   dsp2_state.out_index = 0;
232239
233   DSP2_op05transparent = 0;
234   DSP2_op05haslen      = 0;
235   DSP2_op05len         = 0;
236   DSP2_op06haslen      = 0;
237   DSP2_op06len         = 0;
238   DSP2_op09word1       = 0;
239   DSP2_op09word2       = 0;
240   DSP2_op0dhaslen      = 0;
241   DSP2_op0doutlen      = 0;
242   DSP2_op0dinlen       = 0;
240   memset(dsp2_state.parameters, 0 , ARRAY_LENGTH(dsp2_state.parameters));
241   memset(dsp2_state.output, 0 , ARRAY_LENGTH(dsp2_state.output));
242
243   dsp2_state.op05transparent = 0;
244   dsp2_state.op05haslen      = 0;
245   dsp2_state.op05len         = 0;
246   dsp2_state.op06haslen      = 0;
247   dsp2_state.op06len         = 0;
248   dsp2_state.op09word1       = 0;
249   dsp2_state.op09word2       = 0;
250   dsp2_state.op0dhaslen      = 0;
251   dsp2_state.op0doutlen      = 0;
252   dsp2_state.op0dinlen       = 0;
253
254   dsp2_register_save(machine);
243255}
244256
245static UINT8 DSP2_read( void )
257static UINT8 dsp2_read( void )
246258{
247259   UINT8 r = 0xff;
248   if (DSP2_out_count)
260   if (dsp2_state.out_count)
249261   {
250      r = DSP2_output[DSP2_out_index++];
251      DSP2_out_index &= 511;
252      if (DSP2_out_count == DSP2_out_index)
253         DSP2_out_count = 0;
262      r = dsp2_state.output[dsp2_state.out_index++];
263      dsp2_state.out_index &= 511;
264      if (dsp2_state.out_count == dsp2_state.out_index)
265         dsp2_state.out_count = 0;
254266   }
255267   return r;
256268}
257269
258static void DSP2_write(UINT8 data)
270static void dsp2_write(UINT8 data)
259271{
260   if(DSP2_waiting_for_command)
272   if (dsp2_state.waiting_for_command)
261273   {
262      DSP2_command  = data;
263      DSP2_in_index = 0;
264      DSP2_waiting_for_command = 0;
274      dsp2_state.command  = data;
275      dsp2_state.in_index = 0;
276      dsp2_state.waiting_for_command = 0;
265277
266278      switch (data)
267279      {
268         case 0x01: DSP2_in_count = 32; break;
269         case 0x03: DSP2_in_count =  1; break;
270         case 0x05: DSP2_in_count =  1; break;
271         case 0x06: DSP2_in_count =  1; break;
280         case 0x01: dsp2_state.in_count = 32; break;
281         case 0x03: dsp2_state.in_count =  1; break;
282         case 0x05: dsp2_state.in_count =  1; break;
283         case 0x06: dsp2_state.in_count =  1; break;
272284         case 0x07: break;
273285         case 0x08: break;
274         case 0x09: DSP2_in_count =  4; break;
275         case 0x0d: DSP2_in_count =  2; break;
276         case 0x0f: DSP2_in_count =  0; break;
286         case 0x09: dsp2_state.in_count =  4; break;
287         case 0x0d: dsp2_state.in_count =  2; break;
288         case 0x0f: dsp2_state.in_count =  0; break;
277289      }
278290   }
279291   else
280292   {
281      DSP2_parameters[DSP2_in_index++] = data;
282      DSP2_in_index &= 511;
293      dsp2_state.parameters[dsp2_state.in_index++] = data;
294      dsp2_state.in_index &= 511;
283295   }
284296
285   if (DSP2_in_count == DSP2_in_index)
297   if (dsp2_state.in_count == dsp2_state.in_index)
286298   {
287      DSP2_waiting_for_command = 1;
288      DSP2_out_index = 0;
289      switch (DSP2_command)
299      dsp2_state.waiting_for_command = 1;
300      dsp2_state.out_index = 0;
301      switch (dsp2_state.command)
290302      {
291         case 0x01:
292            DSP2_out_count = 32;
293            DSP2_op01();
294            break;
303      case 0x01:
304         dsp2_state.out_count = 32;
305         dsp2_op01();
306         break;
295307
296         case 0x03:
297            DSP2_op03();
298            break;
308      case 0x03:
309         dsp2_op03();
310         break;
299311
300         case 0x05:
301            if (DSP2_op05haslen)
302            {
303               DSP2_op05haslen = 0;
304               DSP2_out_count  = DSP2_op05len;
305               DSP2_op05();
306            }
307            else
308            {
309               DSP2_op05len    = DSP2_parameters[0];
310               DSP2_in_index   = 0;
311               DSP2_in_count   = DSP2_op05len * 2;
312               DSP2_op05haslen = 1;
313               if (data)
314                  DSP2_waiting_for_command = 0;
315            }
316            break;
312      case 0x05:
313         if (dsp2_state.op05haslen)
314         {
315            dsp2_state.op05haslen = 0;
316            dsp2_state.out_count  = dsp2_state.op05len;
317            dsp2_op05();
318         }
319         else
320         {
321            dsp2_state.op05len    = dsp2_state.parameters[0];
322            dsp2_state.in_index   = 0;
323            dsp2_state.in_count   = dsp2_state.op05len * 2;
324            dsp2_state.op05haslen = 1;
325            if (data)
326               dsp2_state.waiting_for_command = 0;
327         }
328         break;
317329
318         case 0x06:
319            if (DSP2_op06haslen)
320            {
321               DSP2_op06haslen = 0;
322               DSP2_out_count  = DSP2_op06len;
323               DSP2_op06();
324            }
325            else
326            {
327               DSP2_op06len    = DSP2_parameters[0];
328               DSP2_in_index   = 0;
329               DSP2_in_count   = DSP2_op06len;
330               DSP2_op06haslen = 1;
331               if (data)
332                  DSP2_waiting_for_command = 0;
333            }
334            break;
330      case 0x06:
331         if (dsp2_state.op06haslen)
332         {
333            dsp2_state.op06haslen = 0;
334            dsp2_state.out_count  = dsp2_state.op06len;
335            dsp2_op06();
336         }
337         else
338         {
339            dsp2_state.op06len    = dsp2_state.parameters[0];
340            dsp2_state.in_index   = 0;
341            dsp2_state.in_count   = dsp2_state.op06len;
342            dsp2_state.op06haslen = 1;
343            if (data)
344               dsp2_state.waiting_for_command = 0;
345         }
346         break;
335347
336         case 0x07: break;
337         case 0x08: break;
348      case 0x07: break;
349      case 0x08: break;
338350
339         case 0x09:
340            DSP2_op09();
341            break;
351      case 0x09:
352         dsp2_op09();
353         break;
342354
343         case 0x0d:
344            if (DSP2_op0dhaslen)
345            {
346               DSP2_op0dhaslen = 0;
347               DSP2_out_count  = DSP2_op0doutlen;
348               DSP2_op0d();
349            }
350            else
351            {
352               DSP2_op0dinlen  = DSP2_parameters[0];
353               DSP2_op0doutlen = DSP2_parameters[1];
354               DSP2_in_index   = 0;
355               DSP2_in_count   = (DSP2_op0dinlen + 1) >> 1;
356               DSP2_op0dhaslen = 1;
357               if(data)
358                  DSP2_waiting_for_command = 0;
359            }
360            break;
355      case 0x0d:
356         if (dsp2_state.op0dhaslen)
357         {
358            dsp2_state.op0dhaslen = 0;
359            dsp2_state.out_count  = dsp2_state.op0doutlen;
360            dsp2_op0d();
361         }
362         else
363         {
364            dsp2_state.op0dinlen  = dsp2_state.parameters[0];
365            dsp2_state.op0doutlen = dsp2_state.parameters[1];
366            dsp2_state.in_index   = 0;
367            dsp2_state.in_count   = (dsp2_state.op0dinlen + 1) >> 1;
368            dsp2_state.op0dhaslen = 1;
369            if (data)
370               dsp2_state.waiting_for_command = 0;
371         }
372         break;
361373
362         case 0x0f:
363            break;
374      case 0x0f:
375         break;
364376      }
365377   }
366378}
379
380static void dsp2_register_save( running_machine *machine )
381{
382   state_save_register_global(machine, dsp2_state.waiting_for_command);
383   state_save_register_global(machine, dsp2_state.command);
384   state_save_register_global(machine, dsp2_state.in_count);
385   state_save_register_global(machine, dsp2_state.in_index);
386   state_save_register_global(machine, dsp2_state.out_count);
387   state_save_register_global(machine, dsp2_state.out_index);
388
389   state_save_register_global_array(machine, dsp2_state.parameters);
390   state_save_register_global_array(machine, dsp2_state.output);
391
392   state_save_register_global(machine, dsp2_state.op05transparent);
393   state_save_register_global(machine, dsp2_state.op05haslen);
394   state_save_register_global(machine, dsp2_state.op05len);
395   state_save_register_global(machine, dsp2_state.op06haslen);
396   state_save_register_global(machine, dsp2_state.op06len);
397   state_save_register_global(machine, dsp2_state.op09word1);
398   state_save_register_global(machine, dsp2_state.op09word2);
399   state_save_register_global(machine, dsp2_state.op0dhaslen);
400   state_save_register_global(machine, dsp2_state.op0doutlen);
401   state_save_register_global(machine, dsp2_state.op0dinlen);
402}
src/mame/machine/snesobc1.c
r7621r7622
1212
1313***************************************************************************/
1414
15#include "includes/snes.h"
15struct _snes_obc1_state
16{
17   int address;
18   int offset;
19   int shift;
20};
1621
17static int obc1_address;
18static int obc1_offset;
19static int obc1_shift;
22static struct _snes_obc1_state  obc1_state;
2023
24
2125static READ8_HANDLER( obc1_read )
2226{
2327   UINT16 address = offset & 0x1fff;
r7621r7622
2630   switch (address)
2731   {
2832      case 0x1ff0:
29         value = snes_ram[obc1_offset + (obc1_address << 2) + 0];
33         value = snes_ram[obc1_state.offset + (obc1_state.address << 2) + 0];
3034         break;
3135
3236      case 0x1ff1:
33         value = snes_ram[obc1_offset + (obc1_address << 2) + 1];
37         value = snes_ram[obc1_state.offset + (obc1_state.address << 2) + 1];
3438         break;
3539
3640      case 0x1ff2:
37         value = snes_ram[obc1_offset + (obc1_address << 2) + 2];
41         value = snes_ram[obc1_state.offset + (obc1_state.address << 2) + 2];
3842         break;
3943
4044      case 0x1ff3:
41         value = snes_ram[obc1_offset + (obc1_address << 2) + 3];
45         value = snes_ram[obc1_state.offset + (obc1_state.address << 2) + 3];
4246         break;
4347
4448      case 0x1ff4:
45         value = snes_ram[obc1_offset + (obc1_address >> 2) + 0x200];
49         value = snes_ram[obc1_state.offset + (obc1_state.address >> 2) + 0x200];
4650         break;
4751
4852      default:
r7621r7622
6266   switch(address)
6367   {
6468      case 0x1ff0:
65         snes_ram[obc1_offset + (obc1_address << 2) + 0] = data;
69         snes_ram[obc1_state.offset + (obc1_state.address << 2) + 0] = data;
6670         break;
6771
6872      case 0x1ff1:
69         snes_ram[obc1_offset + (obc1_address << 2) + 1] = data;
73         snes_ram[obc1_state.offset + (obc1_state.address << 2) + 1] = data;
7074         break;
7175
7276      case 0x1ff2:
73         snes_ram[obc1_offset + (obc1_address << 2) + 2] = data;
77         snes_ram[obc1_state.offset + (obc1_state.address << 2) + 2] = data;
7478         break;
7579
7680      case 0x1ff3:
77         snes_ram[obc1_offset + (obc1_address << 2) + 3] = data;
81         snes_ram[obc1_state.offset + (obc1_state.address << 2) + 3] = data;
7882         break;
7983
8084      case 0x1ff4:
81         temp = snes_ram[obc1_offset + (obc1_address >> 2) + 0x200];
82         temp = (temp & ~(3 << obc1_shift)) | ((data & 0x03) << obc1_shift);
83         snes_ram[obc1_offset + (obc1_address >> 2) + 0x200] = temp;
85         temp = snes_ram[obc1_state.offset + (obc1_state.address >> 2) + 0x200];
86         temp = (temp & ~(3 << obc1_state.shift)) | ((data & 0x03) << obc1_state.shift);
87         snes_ram[obc1_state.offset + (obc1_state.address >> 2) + 0x200] = temp;
8488         break;
8589
8690      case 0x1ff5:
87         obc1_offset = (data & 0x01) ? 0x1800 : 0x1c00;
91         obc1_state.offset = (data & 0x01) ? 0x1800 : 0x1c00;
8892         snes_ram[address & 0x1fff] = data;
8993         break;
9094
9195      case 0x1ff6:
92         obc1_address = data & 0x7f;
93         obc1_shift = (data & 0x03) << 1;
96         obc1_state.address = data & 0x7f;
97         obc1_state.shift = (data & 0x03) << 1;
9498         snes_ram[address & 0x1fff] = data;
9599         break;
96100
r7621r7622
100104   }
101105}
102106
103static void obc1_init( void )
107static void obc1_init( running_machine *machine )
104108{
105   obc1_offset  = (snes_ram[0x1ff5] & 0x01) ? 0x1800 : 0x1c00;
106   obc1_address = (snes_ram[0x1ff6] & 0x7f);
107   obc1_shift   = (snes_ram[0x1ff6] & 0x03) << 1;
109   obc1_state.offset  = (snes_ram[0x1ff5] & 0x01) ? 0x1800 : 0x1c00;
110   obc1_state.address = (snes_ram[0x1ff6] & 0x7f);
111   obc1_state.shift   = (snes_ram[0x1ff6] & 0x03) << 1;
112
113   state_save_register_global(machine, obc1_state.offset);
114   state_save_register_global(machine, obc1_state.address);
115   state_save_register_global(machine, obc1_state.shift);
108116}
src/mame/machine/snesdsp3.c
r7621r7622
1212
1313************************************************************************/
1414
15static UINT16 DSP3_DataROM[1024];
15static void dsp3_Command(void);
1616
17static void(*SetDSP3)(void);
18static void DSP3_Command(void);
17struct _snes_dsp3_state
18{
19   UINT16  DR;
20   UINT16  SR;
21   UINT16  MemoryIndex;
1922
20static UINT16 DSP3_DR;
21static UINT16 DSP3_SR;
22static UINT16 DSP3_MemoryIndex;
23   INT16   AddLo;
24   INT16   AddHi;
25   INT16   WinLo;
26   INT16   WinHi;
27   UINT16  Codewords;
28   UINT16  Outwords;
29   UINT16  Symbol;
30   UINT16  BitCount;
31   UINT16  Index;
32   UINT16  Codes[512];
33   UINT16  BitsLeft;
34   UINT16  ReqBits;
35   UINT16  ReqData;
36   UINT16  BitCommand;
37   UINT8   BaseLength;
38   UINT16  BaseCodes;
39   UINT16  BaseCode;
40   UINT8   CodeLengths[8];
41   UINT16  CodeOffsets[8];
42   UINT16  LZCode;
43   UINT8   LZLength;
2344
24static void DSP3_Reset(void)
45   UINT16  X;
46   UINT16  Y;
47
48   UINT8   Bitmap[8];
49   UINT8   Bitplane[8];
50   UINT16  BMIndex;
51   UINT16  BPIndex;
52   UINT16  Count;
53
54   INT16 op3e_x;
55   INT16 op3e_y;
56
57   INT16 op1e_terrain[0x2000];
58   INT16 op1e_cost[0x2000];
59   INT16 op1e_weight[0x2000];
60
61   INT16 op1e_cell;
62   INT16 op1e_turn;
63   INT16 op1e_search;
64
65   INT16 op1e_x;
66   INT16 op1e_y;
67
68   INT16 op1e_min_radius;
69   INT16 op1e_max_radius;
70
71   INT16 op1e_max_search_radius;
72   INT16 op1e_max_path_radius;
73
74   INT16 op1e_lcv_radius;
75   INT16 op1e_lcv_steps;
76   INT16 op1e_lcv_turns;
77
78   void(*SetDSP3)(void);
79
80   UINT16 DataROM[1024];
81};
82
83static struct _snes_dsp3_state  dsp3_state;
84
85
86static void dsp3_Reset(void)
2587{
26   DSP3_DR = 0x0080;
27   DSP3_SR = 0x0084;
28   SetDSP3 = &DSP3_Command;
88   dsp3_state.DR = 0x0080;
89   dsp3_state.SR = 0x0084;
90   dsp3_state.SetDSP3 = &dsp3_Command;
2991}
3092
3193#ifdef UNUSED_FUNCTION
32void DSP3_MemorySize(void)
94void dsp3_MemorySize(void)
3395{
34   DSP3_DR = 0x0300;
35   SetDSP3 = &DSP3_Reset;
96   dsp3_state.DR = 0x0300;
97   dsp3_state.SetDSP3 = &dsp3_Reset;
3698}
3799#endif
38100
39static void DSP3_TestMemory(void)
101static void dsp3_TestMemory(void)
40102{
41   DSP3_DR = 0x0000;
42   SetDSP3 = &DSP3_Reset;
103   dsp3_state.DR = 0x0000;
104   dsp3_state.SetDSP3 = &dsp3_Reset;
43105}
44106
45static void DSP3_DumpDataROM(void)
107static void dsp3_DumpDataROM(void)
46108{
47   DSP3_DR = DSP3_DataROM[DSP3_MemoryIndex++];
48   if (DSP3_MemoryIndex == 1024)
49      SetDSP3 = &DSP3_Reset;
109   dsp3_state.DR = dsp3_state.DataROM[dsp3_state.MemoryIndex++];
110   if (dsp3_state.MemoryIndex == 1024)
111      dsp3_state.SetDSP3 = &dsp3_Reset;
50112}
51113
52static void DSP3_MemoryDump(void)
114static void dsp3_MemoryDump(void)
53115{
54   DSP3_MemoryIndex = 0;
55   SetDSP3 = &DSP3_DumpDataROM;
56   DSP3_DumpDataROM();
116   dsp3_state.MemoryIndex = 0;
117   dsp3_state.SetDSP3 = &dsp3_DumpDataROM;
118   dsp3_DumpDataROM();
57119}
58120
59static INT16 DSP3_WinLo;
60static INT16 DSP3_WinHi;
61
62static void DSP3_OP06(void)
121static void dsp3_OP06(void)
63122{
64   DSP3_WinLo = (UINT8)(DSP3_DR);
65   DSP3_WinHi = (UINT8)(DSP3_DR >> 8);
66   DSP3_Reset();
123   dsp3_state.WinLo = (UINT8)(dsp3_state.DR);
124   dsp3_state.WinHi = (UINT8)(dsp3_state.DR >> 8);
125   dsp3_Reset();
67126}
68127
69static void DSP3_OP03(void)
128static void dsp3_OP03(void)
70129{
71   INT16 Lo = (UINT8)(DSP3_DR);
72   INT16 Hi = (UINT8)(DSP3_DR >> 8);
73   INT16 Ofs = (DSP3_WinLo * Hi << 1) + (Lo << 1);
74   DSP3_DR = Ofs >> 1;
75   SetDSP3 = &DSP3_Reset;
130   INT16 Lo = (UINT8)(dsp3_state.DR);
131   INT16 Hi = (UINT8)(dsp3_state.DR >> 8);
132   INT16 Ofs = (dsp3_state.WinLo * Hi << 1) + (Lo << 1);
133   dsp3_state.DR = Ofs >> 1;
134   dsp3_state.SetDSP3 = &dsp3_Reset;
76135}
77136
78static INT16 DSP3_AddLo;
79static INT16 DSP3_AddHi;
80
81static void DSP3_OP07_B(void)
137static void dsp3_OP07_B(void)
82138{
83   INT16 Ofs = (DSP3_WinLo * DSP3_AddHi << 1) + (DSP3_AddLo << 1);
84   DSP3_DR = Ofs >> 1;
85   SetDSP3 = &DSP3_Reset;
139   INT16 Ofs = (dsp3_state.WinLo * dsp3_state.AddHi << 1) + (dsp3_state.AddLo << 1);
140   dsp3_state.DR = Ofs >> 1;
141   dsp3_state.SetDSP3 = &dsp3_Reset;
86142}
87143
88static void DSP3_OP07_A(void)
144static void dsp3_OP07_A(void)
89145{
90   INT16 Lo = (UINT8)(DSP3_DR);
91   INT16 Hi = (UINT8)(DSP3_DR >> 8);
146   INT16 Lo = (UINT8)(dsp3_state.DR);
147   INT16 Hi = (UINT8)(dsp3_state.DR >> 8);
92148
93   if (Lo & 1)   Hi += (DSP3_AddLo & 1);
149   if (Lo & 1)
150      Hi += (dsp3_state.AddLo & 1);
94151
95   DSP3_AddLo += Lo;
96   DSP3_AddHi += Hi;
152   dsp3_state.AddLo += Lo;
153   dsp3_state.AddHi += Hi;
97154
98   if (DSP3_AddLo < 0)
99      DSP3_AddLo += DSP3_WinLo;
100   else
101      if (DSP3_AddLo >= DSP3_WinLo)
102         DSP3_AddLo -= DSP3_WinLo;
155   if (dsp3_state.AddLo < 0)
156      dsp3_state.AddLo += dsp3_state.WinLo;
157   else if (dsp3_state.AddLo >= dsp3_state.WinLo)
158      dsp3_state.AddLo -= dsp3_state.WinLo;
103159
104   if (DSP3_AddHi < 0)
105      DSP3_AddHi += DSP3_WinHi;
106   else
107      if (DSP3_AddHi >= DSP3_WinHi)
108         DSP3_AddHi -= DSP3_WinHi;
160   if (dsp3_state.AddHi < 0)
161      dsp3_state.AddHi += dsp3_state.WinHi;
162   else if (dsp3_state.AddHi >= dsp3_state.WinHi)
163      dsp3_state.AddHi -= dsp3_state.WinHi;
109164
110   DSP3_DR = DSP3_AddLo | (DSP3_AddHi << 8) | ((DSP3_AddHi >> 8) & 0xff);
111   SetDSP3 = &DSP3_OP07_B;
165   dsp3_state.DR = dsp3_state.AddLo | (dsp3_state.AddHi << 8) | ((dsp3_state.AddHi >> 8) & 0xff);
166   dsp3_state.SetDSP3 = &dsp3_OP07_B;
112167}
113168
114static void DSP3_OP07(void)
169static void dsp3_OP07(void)
115170{
116   UINT32 dataOfs = ((DSP3_DR << 1) + 0x03b2) & 0x03ff;
171   UINT32 dataOfs = ((dsp3_state.DR << 1) + 0x03b2) & 0x03ff;
117172
118   DSP3_AddHi = DSP3_DataROM[dataOfs];
119   DSP3_AddLo = DSP3_DataROM[dataOfs + 1];
173   dsp3_state.AddHi = dsp3_state.DataROM[dataOfs];
174   dsp3_state.AddLo = dsp3_state.DataROM[dataOfs + 1];
120175
121   SetDSP3 = &DSP3_OP07_A;
122   DSP3_SR = 0x0080;
176   dsp3_state.SetDSP3 = &dsp3_OP07_A;
177   dsp3_state.SR = 0x0080;
123178}
124179
125static UINT16 DSP3_Codewords;
126static UINT16 DSP3_Outwords;
127static UINT16 DSP3_Symbol;
128static UINT16 DSP3_BitCount;
129static UINT16 DSP3_Index;
130static UINT16 DSP3_Codes[512];
131static UINT16 DSP3_BitsLeft;
132static UINT16 DSP3_ReqBits;
133static UINT16 DSP3_ReqData;
134static UINT16 DSP3_BitCommand;
135static UINT8  DSP3_BaseLength;
136static UINT16 DSP3_BaseCodes;
137static UINT16 DSP3_BaseCode;
138static UINT8  DSP3_CodeLengths[8];
139static UINT16 DSP3_CodeOffsets[8];
140static UINT16 DSP3_LZCode;
141static UINT8  DSP3_LZLength;
142
143static UINT16 DSP3_X;
144static UINT16 DSP3_Y;
145
146static void DSP3_Coordinate(void)
180static void dsp3_Coordinate(void)
147181{
148   DSP3_Index++;
182   dsp3_state.Index++;
149183
150   switch (DSP3_Index)
184   switch (dsp3_state.Index)
151185   {
152186   case 3:
153      {
154         if (DSP3_DR == 0xffff)
155            DSP3_Reset();
156         break;
157      }
187      if (dsp3_state.DR == 0xffff)
188         dsp3_Reset();
189      break;
158190   case 4:
159      {
160         DSP3_X = DSP3_DR;
161         break;
162      }
191      dsp3_state.X = dsp3_state.DR;
192      break;
163193   case 5:
164      {
165         DSP3_Y = DSP3_DR;
166         DSP3_DR = 1;
167         break;
168      }
194      dsp3_state.Y = dsp3_state.DR;
195      dsp3_state.DR = 1;
196      break;
169197   case 6:
170      {
171         DSP3_DR = DSP3_X;
172         break;
173      }
198      dsp3_state.DR = dsp3_state.X;
199      break;
174200   case 7:
175      {
176         DSP3_DR = DSP3_Y;
177         DSP3_Index = 0;
178         break;
179      }
201      dsp3_state.DR = dsp3_state.Y;
202      dsp3_state.Index = 0;
203      break;
180204   }
181205}
182206
183static UINT8  DSP3_Bitmap[8];
184static UINT8  DSP3_Bitplane[8];
185static UINT16 DSP3_BMIndex;
186static UINT16 DSP3_BPIndex;
187static UINT16 DSP3_Count;
188
189static void DSP3_Convert_A(void)
207static void dsp3_Convert_A(void)
190208{
191   if (DSP3_BMIndex < 8)
209   if (dsp3_state.BMIndex < 8)
192210   {
193      DSP3_Bitmap[DSP3_BMIndex++] = (UINT8) (DSP3_DR);
194      DSP3_Bitmap[DSP3_BMIndex++] = (UINT8) (DSP3_DR >> 8);
211      dsp3_state.Bitmap[dsp3_state.BMIndex++] = (UINT8) (dsp3_state.DR);
212      dsp3_state.Bitmap[dsp3_state.BMIndex++] = (UINT8) (dsp3_state.DR >> 8);
195213
196      if (DSP3_BMIndex == 8)
214      if (dsp3_state.BMIndex == 8)
197215      {
198      short i, j;
199         for (i=0; i < 8; i++)
200            for (j=0; j < 8; j++)
216         short i, j;
217         for (i = 0; i < 8; i++)
218            for (j = 0; j < 8; j++)
201219            {
202               DSP3_Bitplane[j] <<= 1;
203               DSP3_Bitplane[j] |= (DSP3_Bitmap[i] >> j) & 1;
220               dsp3_state.Bitplane[j] <<= 1;
221               dsp3_state.Bitplane[j] |= (dsp3_state.Bitmap[i] >> j) & 1;
204222            }
205223
206         DSP3_BPIndex = 0;
207         DSP3_Count--;
224         dsp3_state.BPIndex = 0;
225         dsp3_state.Count--;
208226      }
209227   }
210228
211   if (DSP3_BMIndex == 8)
229   if (dsp3_state.BMIndex == 8)
212230   {
213      if (DSP3_BPIndex == 8)
231      if (dsp3_state.BPIndex == 8)
214232      {
215         if (!DSP3_Count) DSP3_Reset();
216         DSP3_BMIndex = 0;
233         if (!dsp3_state.Count)
234            dsp3_Reset();
235         dsp3_state.BMIndex = 0;
217236      }
218237      else
219238      {
220         DSP3_DR = DSP3_Bitplane[DSP3_BPIndex++];
221         DSP3_DR |= DSP3_Bitplane[DSP3_BPIndex++] << 8;
239         dsp3_state.DR =  dsp3_state.Bitplane[dsp3_state.BPIndex++];
240         dsp3_state.DR |= dsp3_state.Bitplane[dsp3_state.BPIndex++] << 8;
222241      }
223242   }
224243}
225244
226static void DSP3_Convert(void)
245static void dsp3_Convert(void)
227246{
228   DSP3_Count = DSP3_DR;
229   DSP3_BMIndex = 0;
230   SetDSP3 = &DSP3_Convert_A;
247   dsp3_state.Count = dsp3_state.DR;
248   dsp3_state.BMIndex = 0;
249   dsp3_state.SetDSP3 = &dsp3_Convert_A;
231250}
232251
233static UINT8 DSP3_GetBits(UINT8 Count)
252static UINT8 dsp3_GetBits(UINT8 Count)
234253{
235   if (!DSP3_BitsLeft)
254   if (!dsp3_state.BitsLeft)
236255   {
237      DSP3_BitsLeft = Count;
238      DSP3_ReqBits = 0;
256      dsp3_state.BitsLeft = Count;
257      dsp3_state.ReqBits = 0;
239258   }
240259
241260   do {
242      if (!DSP3_BitCount)
261      if (!dsp3_state.BitCount)
243262      {
244         DSP3_SR = 0xC0;
263         dsp3_state.SR = 0xC0;
245264         return 0;
246265      }
247266
248      DSP3_ReqBits <<= 1;
249      if (DSP3_ReqData & 0x8000) DSP3_ReqBits++;
250      DSP3_ReqData <<= 1;
267      dsp3_state.ReqBits <<= 1;
268      if (dsp3_state.ReqData & 0x8000)
269         dsp3_state.ReqBits++;
270      dsp3_state.ReqData <<= 1;
251271
252      DSP3_BitCount--;
253      DSP3_BitsLeft--;
272      dsp3_state.BitCount--;
273      dsp3_state.BitsLeft--;
254274
255   } while (DSP3_BitsLeft);
275   } while (dsp3_state.BitsLeft);
256276
257277   return 1;
258278}
259279
260static void DSP3_Decode_Data(void)
280static void dsp3_Decode_Data(void)
261281{
262   if (!DSP3_BitCount)
282   if (!dsp3_state.BitCount)
263283   {
264      if (DSP3_SR & 0x40)
284      if (dsp3_state.SR & 0x40)
265285      {
266         DSP3_ReqData = DSP3_DR;
267         DSP3_BitCount += 16;
286         dsp3_state.ReqData = dsp3_state.DR;
287         dsp3_state.BitCount += 16;
268288      }
269289      else
270290      {
271         DSP3_SR = 0xC0;
291         dsp3_state.SR = 0xC0;
272292         return;
273293      }
274294   }
275295
276   if (DSP3_LZCode == 1)
296   if (dsp3_state.LZCode == 1)
277297   {
278      if (!DSP3_GetBits(1))
298      if (!dsp3_GetBits(1))
279299         return;
280300
281      if (DSP3_ReqBits)
282         DSP3_LZLength = 12;
301      if (dsp3_state.ReqBits)
302         dsp3_state.LZLength = 12;
283303      else
284         DSP3_LZLength = 8;
304         dsp3_state.LZLength = 8;
285305
286      DSP3_LZCode++;
306      dsp3_state.LZCode++;
287307   }
288308
289   if (DSP3_LZCode == 2)
309   if (dsp3_state.LZCode == 2)
290310   {
291      if (!DSP3_GetBits(DSP3_LZLength))
311      if (!dsp3_GetBits(dsp3_state.LZLength))
292312         return;
293313
294      DSP3_LZCode = 0;
295      DSP3_Outwords--;
296      if (!DSP3_Outwords) SetDSP3 = &DSP3_Reset;
314      dsp3_state.LZCode = 0;
315      dsp3_state.Outwords--;
316      if (!dsp3_state.Outwords) dsp3_state.SetDSP3 = &dsp3_Reset;
297317
298      DSP3_SR = 0x80;
299      DSP3_DR = DSP3_ReqBits;
318      dsp3_state.SR = 0x80;
319      dsp3_state.DR = dsp3_state.ReqBits;
300320      return;
301321   }
302322
303   if (DSP3_BaseCode == 0xffff)
323   if (dsp3_state.BaseCode == 0xffff)
304324   {
305      if (!DSP3_GetBits(DSP3_BaseLength))
325      if (!dsp3_GetBits(dsp3_state.BaseLength))
306326         return;
307327
308      DSP3_BaseCode = DSP3_ReqBits;
328      dsp3_state.BaseCode = dsp3_state.ReqBits;
309329   }
310330
311   if (!DSP3_GetBits(DSP3_CodeLengths[DSP3_BaseCode]))
331   if (!dsp3_GetBits(dsp3_state.CodeLengths[dsp3_state.BaseCode]))
312332      return;
313333
314   DSP3_Symbol = DSP3_Codes[DSP3_CodeOffsets[DSP3_BaseCode] + DSP3_ReqBits];
315   DSP3_BaseCode = 0xffff;
334   dsp3_state.Symbol = dsp3_state.Codes[dsp3_state.CodeOffsets[dsp3_state.BaseCode] + dsp3_state.ReqBits];
335   dsp3_state.BaseCode = 0xffff;
316336
317   if (DSP3_Symbol & 0xff00)
337   if (dsp3_state.Symbol & 0xff00)
318338   {
319      DSP3_Symbol += 0x7f02;
320      DSP3_LZCode++;
339      dsp3_state.Symbol += 0x7f02;
340      dsp3_state.LZCode++;
321341   }
322342   else
323343   {
324      DSP3_Outwords--;
325      if (!DSP3_Outwords)
326         SetDSP3 = &DSP3_Reset;
344      dsp3_state.Outwords--;
345      if (!dsp3_state.Outwords)
346         dsp3_state.SetDSP3 = &dsp3_Reset;
327347   }
328348
329   DSP3_SR = 0x80;
330   DSP3_DR = DSP3_Symbol;
349   dsp3_state.SR = 0x80;
350   dsp3_state.DR = dsp3_state.Symbol;
331351}
332352
333static void DSP3_Decode_Tree(void)
353static void dsp3_Decode_Tree(void)
334354{
335   if (!DSP3_BitCount)
355   if (!dsp3_state.BitCount)
336356   {
337      DSP3_ReqData = DSP3_DR;
338      DSP3_BitCount += 16;
357      dsp3_state.ReqData = dsp3_state.DR;
358      dsp3_state.BitCount += 16;
339359   }
340360
341   if (!DSP3_BaseCodes)
361   if (!dsp3_state.BaseCodes)
342362   {
343      DSP3_GetBits(1);
344      if (DSP3_ReqBits)
363      dsp3_GetBits(1);
364      if (dsp3_state.ReqBits)
345365      {
346         DSP3_BaseLength = 3;
347         DSP3_BaseCodes = 8;
366         dsp3_state.BaseLength = 3;
367         dsp3_state.BaseCodes = 8;
348368      }
349369      else
350370      {
351         DSP3_BaseLength = 2;
352         DSP3_BaseCodes = 4;
371         dsp3_state.BaseLength = 2;
372         dsp3_state.BaseCodes = 4;
353373      }
354374   }
355375
356   while (DSP3_BaseCodes)
376   while (dsp3_state.BaseCodes)
357377   {
358      if (!DSP3_GetBits(3))
378      if (!dsp3_GetBits(3))
359379         return;
360380
361      DSP3_ReqBits++;
381      dsp3_state.ReqBits++;
362382
363      DSP3_CodeLengths[DSP3_Index] = (UINT8) DSP3_ReqBits;
364      DSP3_CodeOffsets[DSP3_Index] = DSP3_Symbol;
365      DSP3_Index++;
383      dsp3_state.CodeLengths[dsp3_state.Index] = (UINT8) dsp3_state.ReqBits;
384      dsp3_state.CodeOffsets[dsp3_state.Index] = dsp3_state.Symbol;
385      dsp3_state.Index++;
366386
367      DSP3_Symbol += 1 << DSP3_ReqBits;
368      DSP3_BaseCodes--;
387      dsp3_state.Symbol += 1 << dsp3_state.ReqBits;
388      dsp3_state.BaseCodes--;
369389   }
370390
371   DSP3_BaseCode = 0xffff;
372   DSP3_LZCode = 0;
391   dsp3_state.BaseCode = 0xffff;
392   dsp3_state.LZCode = 0;
373393
374   SetDSP3 = &DSP3_Decode_Data;
375   if (DSP3_BitCount) DSP3_Decode_Data();
394   dsp3_state.SetDSP3 = &dsp3_Decode_Data;
395   if (dsp3_state.BitCount)
396      dsp3_Decode_Data();
376397}
377398
378static void DSP3_Decode_Symbols(void)
399static void dsp3_Decode_Symbols(void)
379400{
380   DSP3_ReqData = DSP3_DR;
381   DSP3_BitCount += 16;
401   dsp3_state.ReqData = dsp3_state.DR;
402   dsp3_state.BitCount += 16;
382403
383404   do {
384405
385      if (DSP3_BitCommand == 0xffff)
406      if (dsp3_state.BitCommand == 0xffff)
386407      {
387         if (!DSP3_GetBits(2)) return;
388         DSP3_BitCommand = DSP3_ReqBits;
408         if (!dsp3_GetBits(2)) return;
409         dsp3_state.BitCommand = dsp3_state.ReqBits;
389410      }
390411
391      switch (DSP3_BitCommand)
412      switch (dsp3_state.BitCommand)
392413      {
393414      case 0:
394415         {
395            if (!DSP3_GetBits(9)) return;
396            DSP3_Symbol = DSP3_ReqBits;
416            if (!dsp3_GetBits(9)) return;
417            dsp3_state.Symbol = dsp3_state.ReqBits;
397418            break;
398419         }
399420      case 1:
400421         {
401            DSP3_Symbol++;
422            dsp3_state.Symbol++;
402423            break;
403424         }
404425      case 2:
405426         {
406            if (!DSP3_GetBits(1)) return;
407            DSP3_Symbol += 2 + DSP3_ReqBits;
427            if (!dsp3_GetBits(1)) return;
428            dsp3_state.Symbol += 2 + dsp3_state.ReqBits;
408429            break;
409430         }
410431      case 3:
411432         {
412            if (!DSP3_GetBits(4)) return;
413            DSP3_Symbol += 4 + DSP3_ReqBits;
433            if (!dsp3_GetBits(4)) return;
434            dsp3_state.Symbol += 4 + dsp3_state.ReqBits;
414435            break;
415436         }
416437      }
417438
418      DSP3_BitCommand = 0xffff;
439      dsp3_state.BitCommand = 0xffff;
419440
420      DSP3_Codes[DSP3_Index++] = DSP3_Symbol;
421      DSP3_Codewords--;
441      dsp3_state.Codes[dsp3_state.Index++] = dsp3_state.Symbol;
442      dsp3_state.Codewords--;
422443
423   } while (DSP3_Codewords);
444   } while (dsp3_state.Codewords);
424445
425   DSP3_Index = 0;
426   DSP3_Symbol = 0;
427   DSP3_BaseCodes = 0;
446   dsp3_state.Index = 0;
447   dsp3_state.Symbol = 0;
448   dsp3_state.BaseCodes = 0;
428449
429   SetDSP3 = &DSP3_Decode_Tree;
430   if (DSP3_BitCount) DSP3_Decode_Tree();
450   dsp3_state.SetDSP3 = &dsp3_Decode_Tree;
451   if (dsp3_state.BitCount) dsp3_Decode_Tree();
431452}
432453
433static void DSP3_Decode_A(void)
454static void dsp3_Decode_A(void)
434455{
435   DSP3_Outwords = DSP3_DR;
436   SetDSP3 = &DSP3_Decode_Symbols;
437   DSP3_BitCount = 0;
438   DSP3_BitsLeft = 0;
439   DSP3_Symbol = 0;
440   DSP3_Index = 0;
441   DSP3_BitCommand = 0xffff;
442   DSP3_SR = 0xC0;
456   dsp3_state.Outwords = dsp3_state.DR;
457   dsp3_state.SetDSP3 = &dsp3_Decode_Symbols;
458   dsp3_state.BitCount = 0;
459   dsp3_state.BitsLeft = 0;
460   dsp3_state.Symbol = 0;
461   dsp3_state.Index = 0;
462   dsp3_state.BitCommand = 0xffff;
463   dsp3_state.SR = 0xC0;
443464}
444465
445static void DSP3_Decode(void)
466static void dsp3_Decode(void)
446467{
447   DSP3_Codewords = DSP3_DR;
448   SetDSP3 = &DSP3_Decode_A;
468   dsp3_state.Codewords = dsp3_state.DR;
469   dsp3_state.SetDSP3 = &dsp3_Decode_A;
449470}
450471
451472
452473// Opcodes 1E/3E bit-perfect to 'dsp3-intro' log
453474// src: adapted from SD Gundam X/G-Next
454475
455static INT16 op3e_x;
456static INT16 op3e_y;
457
458static INT16 op1e_terrain[0x2000];
459static INT16 op1e_cost[0x2000];
460static INT16 op1e_weight[0x2000];
461
462static INT16 op1e_cell;
463static INT16 op1e_turn;
464static INT16 op1e_search;
465
466static INT16 op1e_x;
467static INT16 op1e_y;
468
469static INT16 op1e_min_radius;
470static INT16 op1e_max_radius;
471
472static INT16 op1e_max_search_radius;
473static INT16 op1e_max_path_radius;
474
475static INT16 op1e_lcv_radius;
476static INT16 op1e_lcv_steps;
477static INT16 op1e_lcv_turns;
478
479static void DSP3_OP3E(void)
476static void dsp3_OP3E(void)
480477{
481   op3e_x = (UINT8)(DSP3_DR & 0x00ff);
482   op3e_y = (UINT8)((DSP3_DR & 0xff00)>>8);
478   dsp3_state.op3e_x = (UINT8)(dsp3_state.DR & 0x00ff);
479   dsp3_state.op3e_y = (UINT8)((dsp3_state.DR & 0xff00) >> 8);
483480
484   DSP3_OP03();
481   dsp3_OP03();
485482
486   op1e_terrain[ DSP3_DR ] = 0x00;
487   op1e_cost[ DSP3_DR ] = 0xff;
488   op1e_weight[ DSP3_DR ] = 0;
483   dsp3_state.op1e_terrain[dsp3_state.DR] = 0x00;
484   dsp3_state.op1e_cost[dsp3_state.DR] = 0xff;
485   dsp3_state.op1e_weight[dsp3_state.DR] = 0;
489486
490   op1e_max_search_radius = 0;
491   op1e_max_path_radius = 0;
487   dsp3_state.op1e_max_search_radius = 0;
488   dsp3_state.op1e_max_path_radius = 0;
492489}
493490
494static void DSP3_OP1E_A(void);
495static void DSP3_OP1E_A1(void);
496static void DSP3_OP1E_A2(void);
497static void DSP3_OP1E_A3(void);
491static void dsp3_OP1E_A(void);
492static void dsp3_OP1E_A1(void);
493static void dsp3_OP1E_A2(void);
494static void dsp3_OP1E_A3(void);
498495
499static void DSP3_OP1E_B(void);
500static void DSP3_OP1E_B1(void);
501static void DSP3_OP1E_B2(void);
496static void dsp3_OP1E_B(void);
497static void dsp3_OP1E_B1(void);
498static void dsp3_OP1E_B2(void);
502499
503static void DSP3_OP1E_C(void);
504static void DSP3_OP1E_C1(void);
505static void DSP3_OP1E_C2(void);
500static void dsp3_OP1E_C(void);
501static void dsp3_OP1E_C1(void);
502static void dsp3_OP1E_C2(void);
506503
507static void DSP3_OP1E_D( INT16, INT16 *, INT16 * );
508static void DSP3_OP1E_D1( INT16 move, INT16 *lo, INT16 *hi );
504static void dsp3_OP1E_D(INT16, INT16 *, INT16 *);
505static void dsp3_OP1E_D1(INT16 move, INT16 *lo, INT16 *hi);
509506
510static void DSP3_OP1E(void)
507static void dsp3_OP1E(void)
511508{
512509   int lcv;
513510
514   op1e_min_radius = (UINT8)(DSP3_DR & 0x00ff);
515   op1e_max_radius = (UINT8)((DSP3_DR & 0xff00)>>8);
511   dsp3_state.op1e_min_radius = (UINT8)(dsp3_state.DR & 0x00ff);
512   dsp3_state.op1e_max_radius = (UINT8)((dsp3_state.DR & 0xff00)>>8);
516513
517   if( op1e_min_radius == 0 )
518      op1e_min_radius++;
514   if (dsp3_state.op1e_min_radius == 0)
515      dsp3_state.op1e_min_radius++;
519516
520   if( op1e_max_search_radius >= op1e_min_radius )
521      op1e_min_radius = op1e_max_search_radius+1;
517   if (dsp3_state.op1e_max_search_radius >= dsp3_state.op1e_min_radius)
518      dsp3_state.op1e_min_radius = dsp3_state.op1e_max_search_radius + 1;
522519
523   if( op1e_max_radius > op1e_max_search_radius )
524      op1e_max_search_radius = op1e_max_radius;
520   if (dsp3_state.op1e_max_radius > dsp3_state.op1e_max_search_radius)
521      dsp3_state.op1e_max_search_radius = dsp3_state.op1e_max_radius;
525522
526   op1e_lcv_radius = op1e_min_radius;
527   op1e_lcv_steps = op1e_min_radius;
523   dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius;
524   dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius;
528525
529   op1e_lcv_turns = 6;
530   op1e_turn = 0;
526   dsp3_state.op1e_lcv_turns = 6;
527   dsp3_state.op1e_turn = 0;
531528
532   op1e_x = op3e_x;
533   op1e_y = op3e_y;
529   dsp3_state.op1e_x = dsp3_state.op3e_x;
530   dsp3_state.op1e_y = dsp3_state.op3e_y;
534531
535   for( lcv = 0; lcv < op1e_min_radius; lcv++ )
536      DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
532   for (lcv = 0; lcv < dsp3_state.op1e_min_radius; lcv++)
533      dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y);
537534
538   DSP3_OP1E_A();
535   dsp3_OP1E_A();
539536}
540537
541static void DSP3_OP1E_A(void)
538static void dsp3_OP1E_A(void)
542539{
543540   int lcv;
544541
545   if( op1e_lcv_steps == 0 ) {
546      op1e_lcv_radius++;
542   if (dsp3_state.op1e_lcv_steps == 0)
543   {
544      dsp3_state.op1e_lcv_radius++;
547545
548      op1e_lcv_steps = op1e_lcv_radius;
546      dsp3_state.op1e_lcv_steps = dsp3_state.op1e_lcv_radius;
549547
550      op1e_x = op3e_x;
551      op1e_y = op3e_y;
548      dsp3_state.op1e_x = dsp3_state.op3e_x;
549      dsp3_state.op1e_y = dsp3_state.op3e_y;
552550
553      for( lcv = 0; lcv < op1e_lcv_radius; lcv++ )
554         DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
551      for (lcv = 0; lcv < dsp3_state.op1e_lcv_radius; lcv++)
552         dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y);
555553   }
556554
557   if( op1e_lcv_radius > op1e_max_radius ) {
558      op1e_turn++;
559      op1e_lcv_turns--;
555   if (dsp3_state.op1e_lcv_radius > dsp3_state.op1e_max_radius)
556   {
557      dsp3_state.op1e_turn++;
558      dsp3_state.op1e_lcv_turns--;
560559
561      op1e_lcv_radius = op1e_min_radius;
562      op1e_lcv_steps = op1e_min_radius;
560      dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius;
561      dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius;
563562
564      op1e_x = op3e_x;
565      op1e_y = op3e_y;
563      dsp3_state.op1e_x = dsp3_state.op3e_x;
564      dsp3_state.op1e_y = dsp3_state.op3e_y;
566565
567      for( lcv = 0; lcv < op1e_min_radius; lcv++ )
568         DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
566      for (lcv = 0; lcv < dsp3_state.op1e_min_radius; lcv++)
567         dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y);
569568   }
570569
571   if( op1e_lcv_turns == 0 ) {
572      DSP3_DR = 0xffff;
573      DSP3_SR = 0x0080;
574      SetDSP3 = &DSP3_OP1E_B;
570   if (dsp3_state.op1e_lcv_turns == 0)
571   {
572      dsp3_state.DR = 0xffff;
573      dsp3_state.SR = 0x0080;
574      dsp3_state.SetDSP3 = &dsp3_OP1E_B;
575575      return;
576576   }
577577
578   DSP3_DR = (UINT8)(op1e_x) | ((UINT8)(op1e_y)<<8);
579   DSP3_OP03();
578   dsp3_state.DR = (UINT8)(dsp3_state.op1e_x) | ((UINT8)(dsp3_state.op1e_y) << 8);
579   dsp3_OP03();
580580
581   op1e_cell = DSP3_DR;
581   dsp3_state.op1e_cell = dsp3_state.DR;
582582
583   DSP3_SR = 0x0080;
584   SetDSP3 = &DSP3_OP1E_A1;
583   dsp3_state.SR = 0x0080;
584   dsp3_state.SetDSP3 = &dsp3_OP1E_A1;
585585}
586586
587static void DSP3_OP1E_A1(void)
587static void dsp3_OP1E_A1(void)
588588{
589   DSP3_SR = 0x0084;
590   SetDSP3 = &DSP3_OP1E_A2;
589   dsp3_state.SR = 0x0084;
590   dsp3_state.SetDSP3 = &dsp3_OP1E_A2;
591591}
592592
593static void DSP3_OP1E_A2(void)
593static void dsp3_OP1E_A2(void)
594594{
595   op1e_terrain[ op1e_cell ] = (UINT8)(DSP3_DR & 0x00ff);
595   dsp3_state.op1e_terrain[dsp3_state.op1e_cell] = (UINT8)(dsp3_state.DR & 0x00ff);
596596
597   DSP3_SR = 0x0084;
598   SetDSP3 = &DSP3_OP1E_A3;
597   dsp3_state.SR = 0x0084;
598   dsp3_state.SetDSP3 = &dsp3_OP1E_A3;
599599}
600600
601static void DSP3_OP1E_A3(void)
601static void dsp3_OP1E_A3(void)
602602{
603   op1e_cost[ op1e_cell ] = (UINT8)(DSP3_DR & 0x00ff);
603   dsp3_state.op1e_cost[dsp3_state.op1e_cell] = (UINT8)(dsp3_state.DR & 0x00ff);
604604
605   if( op1e_lcv_radius == 1 ) {
606      if( op1e_terrain[ op1e_cell ] & 1 ) {
607         op1e_weight[ op1e_cell ] = 0xff;
608      } else {
609         op1e_weight[ op1e_cell ] = op1e_cost[ op1e_cell ];
605   if (dsp3_state.op1e_lcv_radius == 1)
606   {
607      if (dsp3_state.op1e_terrain[dsp3_state.op1e_cell] & 1)
608      {
609         dsp3_state.op1e_weight[dsp3_state.op1e_cell] = 0xff;
610610      }
611      else
612      {
613         dsp3_state.op1e_weight[dsp3_state.op1e_cell] = dsp3_state.op1e_cost[dsp3_state.op1e_cell];
614      }
611615   }
612   else {
613      op1e_weight[ op1e_cell ] = 0xff;
616   else
617   {
618      dsp3_state.op1e_weight[dsp3_state.op1e_cell] = 0xff;
614619   }
615620
616   DSP3_OP1E_D( (INT16)(op1e_turn+2), &op1e_x, &op1e_y );
617   op1e_lcv_steps--;
621   dsp3_OP1E_D((INT16)(dsp3_state.op1e_turn + 2), &dsp3_state.op1e_x, &dsp3_state.op1e_y);
622   dsp3_state.op1e_lcv_steps--;
618623
619   DSP3_SR = 0x0080;
620   DSP3_OP1E_A();
624   dsp3_state.SR = 0x0080;
625   dsp3_OP1E_A();
621626}
622627
623628
624static void DSP3_OP1E_B(void)
629static void dsp3_OP1E_B(void)
625630{
626   op1e_x = op3e_x;
627   op1e_y = op3e_y;
628   op1e_lcv_radius = 1;
631   dsp3_state.op1e_x = dsp3_state.op3e_x;
632   dsp3_state.op1e_y = dsp3_state.op3e_y;
633   dsp3_state.op1e_lcv_radius = 1;
629634
630   op1e_search = 0;
635   dsp3_state.op1e_search = 0;
631636
632   DSP3_OP1E_B1();
637   dsp3_OP1E_B1();
633638
634   SetDSP3 = &DSP3_OP1E_C;
639   dsp3_state.SetDSP3 = &dsp3_OP1E_C;
635640}
636641
637642
638static void DSP3_OP1E_B1(void)
643static void dsp3_OP1E_B1(void)
639644{
640   while( op1e_lcv_radius < op1e_max_radius ) {
641      op1e_y--;
645   while (dsp3_state.op1e_lcv_radius < dsp3_state.op1e_max_radius)
646   {
647      dsp3_state.op1e_y--;
642648
643      op1e_lcv_turns = 6;
644      op1e_turn = 5;
649      dsp3_state.op1e_lcv_turns = 6;
650      dsp3_state.op1e_turn = 5;
645651
646      while( op1e_lcv_turns ) {
647         op1e_lcv_steps = op1e_lcv_radius;
652      while (dsp3_state.op1e_lcv_turns)
653      {
654         dsp3_state.op1e_lcv_steps = dsp3_state.op1e_lcv_radius;
648655
649         while( op1e_lcv_steps ) {
650            DSP3_OP1E_D1( op1e_turn, &op1e_x, &op1e_y );
656         while (dsp3_state.op1e_lcv_steps)
657         {
658            dsp3_OP1E_D1(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y);
651659
652            if( 0 <= op1e_y && op1e_y < DSP3_WinHi &&
653                  0 <= op1e_x && op1e_x < DSP3_WinLo ) {
654               DSP3_DR = (UINT8)(op1e_x) | ((UINT8)(op1e_y)<<8);
655               DSP3_OP03();
660            if (0 <= dsp3_state.op1e_y && dsp3_state.op1e_y < dsp3_state.WinHi &&
661                  0 <= dsp3_state.op1e_x && dsp3_state.op1e_x < dsp3_state.WinLo )
662            {
663               dsp3_state.DR = (UINT8)(dsp3_state.op1e_x) | ((UINT8)(dsp3_state.op1e_y) << 8);
664               dsp3_OP03();
656665
657               op1e_cell = DSP3_DR;
658               if( op1e_cost[ op1e_cell ] < 0x80 &&
659                     op1e_terrain[ op1e_cell ] < 0x40 ) {
660                  DSP3_OP1E_B2();
666               dsp3_state.op1e_cell = dsp3_state.DR;
667               if (dsp3_state.op1e_cost[dsp3_state.op1e_cell ] < 0x80 && dsp3_state.op1e_terrain[dsp3_state.op1e_cell] < 0x40)
668               {
669                  dsp3_OP1E_B2();
661670               } // end cell perimeter
662671            }
663672
664            op1e_lcv_steps--;
673            dsp3_state.op1e_lcv_steps--;
665674         } // end search line
666675
667         op1e_turn--;
668         if( op1e_turn == 0 ) op1e_turn = 6;
676         dsp3_state.op1e_turn--;
677         if (dsp3_state.op1e_turn == 0)
678            dsp3_state.op1e_turn = 6;
669679
670         op1e_lcv_turns--;
680         dsp3_state.op1e_lcv_turns--;
671681      } // end circle search
672682
673      op1e_lcv_radius++;
683      dsp3_state.op1e_lcv_radius++;
674684   } // end radius search
675685}
676686
677687
678static void DSP3_OP1E_B2(void)
688static void dsp3_OP1E_B2(void)
679689{
680690   INT16 cell;
681691   INT16 path;
r7621r7622
685695   path = 0xff;
686696   lcv_turns = 6;
687697
688   while( lcv_turns ) {
689      x = op1e_x;
690      y = op1e_y;
698   while (lcv_turns)
699   {
700      x = dsp3_state.op1e_x;
701      y = dsp3_state.op1e_y;
691702
692      DSP3_OP1E_D1( lcv_turns, &x, &y );
703      dsp3_OP1E_D1(lcv_turns, &x, &y);
693704
694      DSP3_DR = (UINT8)(x) | ((UINT8)(y)<<8);
695      DSP3_OP03();
705      dsp3_state.DR = (UINT8)(x) | ((UINT8)(y)<<8);
706      dsp3_OP03();
696707
697      cell = DSP3_DR;
708      cell = dsp3_state.DR;
698709
699      if( 0 <= y && y < DSP3_WinHi &&
700            0 <= x && x < DSP3_WinLo  ) {
701
702         if( op1e_terrain[ cell ] < 0x80 || op1e_weight[ cell ] == 0 ) {
703            if( op1e_weight[ cell ] < path ) {
704               path = op1e_weight[ cell ];
705            }
710      if (0 <= y && y < dsp3_state.WinHi && 0 <= x && x < dsp3_state.WinLo)
711      {
712         if (dsp3_state.op1e_terrain[cell] < 0x80 || dsp3_state.op1e_weight[cell] == 0)
713         {
714            if (dsp3_state.op1e_weight[cell] < path)
715               path = dsp3_state.op1e_weight[cell];
706716         }
707717      } // end step travel
708718
709719      lcv_turns--;
710720   } // end while turns
711721
712   if( path != 0xff ) {
713      op1e_weight[ op1e_cell ] = path + op1e_cost[ op1e_cell ];
714   }
722   if (path != 0xff)
723      dsp3_state.op1e_weight[dsp3_state.op1e_cell] = path + dsp3_state.op1e_cost[dsp3_state.op1e_cell];
715724}
716725
717726
718static void DSP3_OP1E_C(void)
727static void dsp3_OP1E_C(void)
719728{
720729   int lcv;
721730
722   op1e_min_radius = (UINT8)(DSP3_DR & 0x00ff);
723   op1e_max_radius = (UINT8)((DSP3_DR & 0xff00)>>8);
731   dsp3_state.op1e_min_radius = (UINT8)(dsp3_state.DR & 0x00ff);
732   dsp3_state.op1e_max_radius = (UINT8)((dsp3_state.DR & 0xff00) >> 8);
724733
725   if( op1e_min_radius == 0 )
726      op1e_min_radius++;
734   if (dsp3_state.op1e_min_radius == 0)
735      dsp3_state.op1e_min_radius++;
727736
728   if( op1e_max_path_radius >= op1e_min_radius )
729      op1e_min_radius = op1e_max_path_radius+1;
737   if (dsp3_state.op1e_max_path_radius >= dsp3_state.op1e_min_radius)
738      dsp3_state.op1e_min_radius = dsp3_state.op1e_max_path_radius + 1;
730739
731   if( op1e_max_radius > op1e_max_path_radius )
732      op1e_max_path_radius = op1e_max_radius;
740   if (dsp3_state.op1e_max_radius > dsp3_state.op1e_max_path_radius)
741      dsp3_state.op1e_max_path_radius = dsp3_state.op1e_max_radius;
733742
734   op1e_lcv_radius = op1e_min_radius;
735   op1e_lcv_steps = op1e_min_radius;
743   dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius;
744   dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius;
736745
737   op1e_lcv_turns = 6;
738   op1e_turn = 0;
746   dsp3_state.op1e_lcv_turns = 6;
747   dsp3_state.op1e_turn = 0;
739748
740   op1e_x = op3e_x;
741   op1e_y = op3e_y;
749   dsp3_state.op1e_x = dsp3_state.op3e_x;
750   dsp3_state.op1e_y = dsp3_state.op3e_y;
742751
743   for( lcv = 0; lcv < op1e_min_radius; lcv++ )
744      DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
752   for (lcv = 0; lcv < dsp3_state.op1e_min_radius; lcv++)
753      dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y);
745754
746   DSP3_OP1E_C1();
755   dsp3_OP1E_C1();
747756}
748757
749758
750static void DSP3_OP1E_C1(void)
759static void dsp3_OP1E_C1(void)
751760{
752761   int lcv;
753762
754   if( op1e_lcv_steps == 0 ) {
755      op1e_lcv_radius++;
763   if (dsp3_state.op1e_lcv_steps == 0)
764   {
765      dsp3_state.op1e_lcv_radius++;
756766
757      op1e_lcv_steps = op1e_lcv_radius;
767      dsp3_state.op1e_lcv_steps = dsp3_state.op1e_lcv_radius;
758768
759      op1e_x = op3e_x;
760      op1e_y = op3e_y;
769      dsp3_state.op1e_x = dsp3_state.op3e_x;
770      dsp3_state.op1e_y = dsp3_state.op3e_y;
761771
762      for( lcv = 0; lcv < op1e_lcv_radius; lcv++ )
763         DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
772      for (lcv = 0; lcv < dsp3_state.op1e_lcv_radius; lcv++)
773         dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y);
764774   }
765775
766   if( op1e_lcv_radius > op1e_max_radius ) {
767      op1e_turn++;
768      op1e_lcv_turns--;
776   if (dsp3_state.op1e_lcv_radius > dsp3_state.op1e_max_radius)
777   {
778      dsp3_state.op1e_turn++;
779      dsp3_state.op1e_lcv_turns--;
769780
770      op1e_lcv_radius = op1e_min_radius;
771      op1e_lcv_steps = op1e_min_radius;
781      dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius;
782      dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius;
772783
773      op1e_x = op3e_x;
774      op1e_y = op3e_y;
784      dsp3_state.op1e_x = dsp3_state.op3e_x;
785      dsp3_state.op1e_y = dsp3_state.op3e_y;
775786
776      for( lcv = 0; lcv < op1e_min_radius; lcv++ )
777         DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y );
787      for (lcv = 0; lcv < dsp3_state.op1e_min_radius; lcv++)
788         dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y);
778789   }
779790
780   if( op1e_lcv_turns == 0 ) {
781      DSP3_DR = 0xffff;
782      DSP3_SR = 0x0080;
783      SetDSP3 = &DSP3_Reset;
791   if (dsp3_state.op1e_lcv_turns == 0)
792   {
793      dsp3_state.DR = 0xffff;
794      dsp3_state.SR = 0x0080;
795      dsp3_state.SetDSP3 = &dsp3_Reset;
784796      return;
785797   }
786798
787   DSP3_DR = (UINT8)(op1e_x) | ((UINT8)(op1e_y)<<8);
788   DSP3_OP03();
799   dsp3_state.DR = (UINT8)(dsp3_state.op1e_x) | ((UINT8)(dsp3_state.op1e_y) << 8);
800   dsp3_OP03();
789801
790   op1e_cell = DSP3_DR;
802   dsp3_state.op1e_cell = dsp3_state.DR;
791803
792   DSP3_SR = 0x0080;
793   SetDSP3 = &DSP3_OP1E_C2;
804   dsp3_state.SR = 0x0080;
805   dsp3_state.SetDSP3 = &dsp3_OP1E_C2;
794806}
795807
796808
797static void DSP3_OP1E_C2(void)
809static void dsp3_OP1E_C2(void)
798810{
799   DSP3_DR = op1e_weight[ op1e_cell ];
811   dsp3_state.DR = dsp3_state.op1e_weight[dsp3_state.op1e_cell];
800812
801   DSP3_OP1E_D( (INT16)(op1e_turn+2), &op1e_x, &op1e_y );
802   op1e_lcv_steps--;
813   dsp3_OP1E_D((INT16)(dsp3_state.op1e_turn + 2), &dsp3_state.op1e_x, &dsp3_state.op1e_y);
814   dsp3_state.op1e_lcv_steps--;
803815
804   DSP3_SR = 0x0084;
805   SetDSP3 = &DSP3_OP1E_C1;
816   dsp3_state.SR = 0x0084;
817   dsp3_state.SetDSP3 = &dsp3_OP1E_C1;
806818}
807819
808820
809static void DSP3_OP1E_D( INT16 move, INT16 *lo, INT16 *hi )
821static void dsp3_OP1E_D( INT16 move, INT16 *lo, INT16 *hi )
810822{
811823   UINT32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff;
812824   INT16 Lo;
813825   INT16 Hi;
814826
815   DSP3_AddHi = DSP3_DataROM[dataOfs];
816   DSP3_AddLo = DSP3_DataROM[dataOfs + 1];
827   dsp3_state.AddHi = dsp3_state.DataROM[dataOfs];
828   dsp3_state.AddLo = dsp3_state.DataROM[dataOfs + 1];
817829
818830   Lo = (UINT8)(*lo);
819831   Hi = (UINT8)(*hi);
820832
821   if (Lo & 1)   Hi += (DSP3_AddLo & 1);
833   if (Lo & 1)   Hi += (dsp3_state.AddLo & 1);
822834
823   DSP3_AddLo += Lo;
824   DSP3_AddHi += Hi;
835   dsp3_state.AddLo += Lo;
836   dsp3_state.AddHi += Hi;
825837
826   if (DSP3_AddLo < 0)
827      DSP3_AddLo += DSP3_WinLo;
828   else
829      if (DSP3_AddLo >= DSP3_WinLo)
830         DSP3_AddLo -= DSP3_WinLo;
838   if (dsp3_state.AddLo < 0)
839      dsp3_state.AddLo += dsp3_state.WinLo;
840   else if (dsp3_state.AddLo >= dsp3_state.WinLo)
841      dsp3_state.AddLo -= dsp3_state.WinLo;
831842
832   if (DSP3_AddHi < 0)
833      DSP3_AddHi += DSP3_WinHi;
834   else
835      if (DSP3_AddHi >= DSP3_WinHi)
836         DSP3_AddHi -= DSP3_WinHi;
843   if (dsp3_state.AddHi < 0)
844      dsp3_state.AddHi += dsp3_state.WinHi;
845   else if (dsp3_state.AddHi >= dsp3_state.WinHi)
846      dsp3_state.AddHi -= dsp3_state.WinHi;
837847
838   *lo = DSP3_AddLo;
839   *hi = DSP3_AddHi;
848   *lo = dsp3_state.AddLo;
849   *hi = dsp3_state.AddHi;
840850}
841851
842852
843static void DSP3_OP1E_D1( INT16 move, INT16 *lo, INT16 *hi )
853static void dsp3_OP1E_D1( INT16 move, INT16 *lo, INT16 *hi )
844854{
845855   //UINT32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff;
846856   INT16 Lo;
r7621r7622
854864      0x00, 0x00, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x00
855865   };
856866
857   if( (*lo) & 1 )
858      DSP3_AddHi = HiAdd[ move + 8 ];
867   if ((*lo) & 1)
868      dsp3_state.AddHi = HiAdd[move + 8];
859869   else
860      DSP3_AddHi = HiAdd[ move + 0 ];
861   DSP3_AddLo = LoAdd[ move ];
870      dsp3_state.AddHi = HiAdd[move + 0];
871   dsp3_state.AddLo = LoAdd[move];
862872
863873   Lo = (UINT8)(*lo);
864874   Hi = (UINT8)(*hi);
865875
866   if (Lo & 1)   Hi += (DSP3_AddLo & 1);
876   if (Lo & 1)
877      Hi += (dsp3_state.AddLo & 1);
867878
868   DSP3_AddLo += Lo;
869   DSP3_AddHi += Hi;
879   dsp3_state.AddLo += Lo;
880   dsp3_state.AddHi += Hi;
870881
871   *lo = DSP3_AddLo;
872   *hi = DSP3_AddHi;
882   *lo = dsp3_state.AddLo;
883   *hi = dsp3_state.AddHi;
873884}
874885
875886
876static void DSP3_OP10(void)
887static void dsp3_OP10(void)
877888{
878   if( DSP3_DR == 0xffff ) {
879      DSP3_Reset();
880   } else {
889   if (dsp3_state.DR == 0xffff )
890      dsp3_Reset();
891   else
892   {
881893      // absorb 2 bytes
882      DSP3_DR = DSP3_DR;
894      dsp3_state.DR = dsp3_state.DR;
883895   }
884896}
885897
886898#ifdef UNUSED_FUNCTION
887static void DSP3_OP0C_A(void)
899static void dsp3_OP0C_A(void)
888900{
889901   // absorb 2 bytes
890902
891   DSP3_DR = 0;
892   SetDSP3 = &DSP3_Reset;
903   dsp3_state.DR = 0;
904   dsp3_state.SetDSP3 = &dsp3_Reset;
893905}
894906#endif
895907
896static void DSP3_OP0C(void)
908static void dsp3_OP0C(void)
897909{
898910   // absorb 2 bytes
899911
900   DSP3_DR = 0;
901   //SetDSP3 = &DSP3_OP0C_A;
902   SetDSP3 = &DSP3_Reset;
912   dsp3_state.DR = 0;
913   //dsp3_state.SetDSP3 = &dsp3_OP0C_A;
914   dsp3_state.SetDSP3 = &dsp3_Reset;
903915}
904916
905917
906static void DSP3_OP1C_C(void)
918static void dsp3_OP1C_C(void)
907919{
908920   // return 2 bytes
909   DSP3_DR = 0;
910   SetDSP3 = &DSP3_Reset;
921   dsp3_state.DR = 0;
922   dsp3_state.SetDSP3 = &dsp3_Reset;
911923}
912924
913925
914static void DSP3_OP1C_B(void)
926static void dsp3_OP1C_B(void)
915927{
916928   // absorb 2 bytes
917929
918930   // return 2 bytes
919   DSP3_DR = 0;
920   SetDSP3 = &DSP3_OP1C_C;
931   dsp3_state.DR = 0;
932   dsp3_state.SetDSP3 = &dsp3_OP1C_C;
921933}
922934
923935
924static void DSP3_OP1C_A(void)
936static void dsp3_OP1C_A(void)
925937{
926938   // absorb 2 bytes
927939
928   SetDSP3 = &DSP3_OP1C_B;
940   dsp3_state.SetDSP3 = &dsp3_OP1C_B;
929941}
930942
931943
932static void DSP3_OP1C(void)
944static void dsp3_OP1C(void)
933945{
934946   // absorb 2 bytes
935947
936   SetDSP3 = &DSP3_OP1C_A;
948   dsp3_state.SetDSP3 = &dsp3_OP1C_A;
937949}
938950
939951
940static void DSP3_Command(void)
952static void dsp3_Command(void)
941953{
942   if (DSP3_DR < 0x40)
954   if (dsp3_state.DR < 0x40)
943955   {
944      switch (DSP3_DR)
956      switch (dsp3_state.DR)
945957      {
946    case 0x02: SetDSP3 = &DSP3_Coordinate; break;
947    case 0x03: SetDSP3 = &DSP3_OP03; break;
948    case 0x06: SetDSP3 = &DSP3_OP06; break;
949    case 0x07: SetDSP3 = &DSP3_OP07; return;
950    case 0x0c: SetDSP3 = &DSP3_OP0C; break;
951    case 0x0f: SetDSP3 = &DSP3_TestMemory; break;
952    case 0x10: SetDSP3 = &DSP3_OP10; break;
953    case 0x18: SetDSP3 = &DSP3_Convert; break;
954    case 0x1c: SetDSP3 = &DSP3_OP1C; break;
955    case 0x1e: SetDSP3 = &DSP3_OP1E; break;
956    case 0x1f: SetDSP3 = &DSP3_MemoryDump; break;
957    case 0x38: SetDSP3 = &DSP3_Decode; break;
958    case 0x3e: SetDSP3 = &DSP3_OP3E; break;
959    default:
960     return;
958      case 0x02: dsp3_state.SetDSP3 = &dsp3_Coordinate; break;
959      case 0x03: dsp3_state.SetDSP3 = &dsp3_OP03; break;
960      case 0x06: dsp3_state.SetDSP3 = &dsp3_OP06; break;
961      case 0x07: dsp3_state.SetDSP3 = &dsp3_OP07; return;
962      case 0x0c: dsp3_state.SetDSP3 = &dsp3_OP0C; break;
963      case 0x0f: dsp3_state.SetDSP3 = &dsp3_TestMemory; break;
964      case 0x10: dsp3_state.SetDSP3 = &dsp3_OP10; break;
965      case 0x18: dsp3_state.SetDSP3 = &dsp3_Convert; break;
966      case 0x1c: dsp3_state.SetDSP3 = &dsp3_OP1C; break;
967      case 0x1e: dsp3_state.SetDSP3 = &dsp3_OP1E; break;
968      case 0x1f: dsp3_state.SetDSP3 = &dsp3_MemoryDump; break;
969      case 0x38: dsp3_state.SetDSP3 = &dsp3_Decode; break;
970      case 0x3e: dsp3_state.SetDSP3 = &dsp3_OP3E; break;
971      default: return;
961972      }
962      DSP3_SR = 0x0080;
963      DSP3_Index = 0;
973
974      dsp3_state.SR = 0x0080;
975      dsp3_state.Index = 0;
964976   }
965977}
966978
967979
968static void DSP3_write( UINT16 dsp3_address, UINT8 dsp3_byte )
980static void dsp3_write( UINT16 dsp3_address, UINT8 dsp3_byte )
969981{
970  if (dsp3_address < 0xC000)
971  {
972      if (DSP3_SR & 0x04)
982   if (dsp3_address < 0xC000)
983   {
984      if (dsp3_state.SR & 0x04)
973985      {
974         DSP3_DR = (DSP3_DR & 0xff00) + dsp3_byte;
975         (*SetDSP3)();
986         dsp3_state.DR = (dsp3_state.DR & 0xff00) + dsp3_byte;
987         (*dsp3_state.SetDSP3)();
976988      }
977989      else
978990      {
979         DSP3_SR ^= 0x10;
991         dsp3_state.SR ^= 0x10;
980992
981         if (DSP3_SR & 0x10)
982            DSP3_DR = (DSP3_DR & 0xff00) + dsp3_byte;
993         if (dsp3_state.SR & 0x10)
994            dsp3_state.DR = (dsp3_state.DR & 0xff00) + dsp3_byte;
983995         else
984996         {
985            DSP3_DR = (DSP3_DR & 0x00ff) + (dsp3_byte << 8);
986            (*SetDSP3)();
997            dsp3_state.DR = (dsp3_state.DR & 0x00ff) + (dsp3_byte << 8);
998            (*dsp3_state.SetDSP3)();
987999         }
9881000      }
989  }
1001   }
9901002}
9911003
992static UINT8 DSP3_read( UINT16 dsp3_address )
1004static UINT8 dsp3_read( UINT16 dsp3_address )
9931005{
994  UINT8 value;
995  if (dsp3_address < 0xC000)
996  {
997      if (DSP3_SR & 0x04)
1006   UINT8 value;
1007   if (dsp3_address < 0xC000)
1008   {
1009      if (dsp3_state.SR & 0x04)
9981010      {
999         value = (UINT8) DSP3_DR;
1000         (*SetDSP3)();
1011         value = (UINT8) dsp3_state.DR;
1012         (*dsp3_state.SetDSP3)();
10011013      }
10021014      else
10031015      {
1004         DSP3_SR ^= 0x10;
1016         dsp3_state.SR ^= 0x10;
10051017
1006         if (DSP3_SR & 0x10)
1007            value = (UINT8) (DSP3_DR);
1018         if (dsp3_state.SR & 0x10)
1019            value = (UINT8) (dsp3_state.DR);
10081020         else
10091021         {
1010            value = (UINT8) (DSP3_DR >> 8);
1011            (*SetDSP3)();
1022            value = (UINT8) (dsp3_state.DR >> 8);
1023            (*dsp3_state.SetDSP3)();
10121024         }
10131025      }
10141026
1015  }
1016  else
1017  {
1018    value = (UINT8) DSP3_SR;
1019  }
1027   }
1028   else
1029   {
1030      value = (UINT8) dsp3_state.SR;
1031   }
10201032
1021  return value;
1033   return value;
10221034}
10231035
1024static void InitDSP3( running_machine *machine )
1036static void dsp3_register_save( running_machine *machine )
10251037{
1038   state_save_register_global(machine, dsp3_state.DR);
1039   state_save_register_global(machine, dsp3_state.SR);
1040   state_save_register_global(machine, dsp3_state.MemoryIndex);
1041
1042   state_save_register_global(machine, dsp3_state.AddLo);
1043   state_save_register_global(machine, dsp3_state.AddHi);
1044   state_save_register_global(machine, dsp3_state.WinLo);
1045   state_save_register_global(machine, dsp3_state.WinHi);
1046   state_save_register_global(machine, dsp3_state.Codewords);
1047   state_save_register_global(machine, dsp3_state.Outwords);
1048   state_save_register_global(machine, dsp3_state.Symbol);
1049   state_save_register_global(machine, dsp3_state.BitCount);
1050   state_save_register_global(machine, dsp3_state.Index);
1051   state_save_register_global_array(machine, dsp3_state.Codes);
1052   state_save_register_global(machine, dsp3_state.BitsLeft);
1053   state_save_register_global(machine, dsp3_state.ReqBits);
1054   state_save_register_global(machine, dsp3_state.ReqData);
1055   state_save_register_global(machine, dsp3_state.BitCommand);
1056   state_save_register_global(machine, dsp3_state.BaseLength);
1057   state_save_register_global(machine, dsp3_state.BaseCodes);
1058   state_save_register_global(machine, dsp3_state.BaseCode);
1059   state_save_register_global_array(machine, dsp3_state.CodeLengths);
1060   state_save_register_global_array(machine, dsp3_state.CodeOffsets);
1061   state_save_register_global(machine, dsp3_state.LZCode);
1062   state_save_register_global(machine, dsp3_state.LZLength);
1063
1064   state_save_register_global(machine, dsp3_state.X);
1065   state_save_register_global(machine, dsp3_state.Y);
1066
1067   state_save_register_global_array(machine, dsp3_state.Bitmap);
1068   state_save_register_global_array(machine, dsp3_state.Bitplane);
1069   state_save_register_global(machine, dsp3_state.BMIndex);
1070   state_save_register_global(machine, dsp3_state.BPIndex);
1071   state_save_register_global(machine, dsp3_state.Count);
1072
1073   state_save_register_global(machine, dsp3_state.op3e_x);
1074   state_save_register_global(machine, dsp3_state.op3e_y);
1075
1076   state_save_register_global_array(machine, dsp3_state.op1e_terrain);
1077   state_save_register_global_array(machine, dsp3_state.op1e_cost);
1078   state_save_register_global_array(machine, dsp3_state.op1e_weight);
1079
1080   state_save_register_global(machine, dsp3_state.op1e_cell);
1081   state_save_register_global(machine, dsp3_state.op1e_turn);
1082   state_save_register_global(machine, dsp3_state.op1e_search);
1083
1084   state_save_register_global(machine, dsp3_state.op1e_x);
1085   state_save_register_global(machine, dsp3_state.op1e_y);
1086
1087   state_save_register_global(machine, dsp3_state.op1e_min_radius);
1088   state_save_register_global(machine, dsp3_state.op1e_max_radius);
1089
1090   state_save_register_global(machine, dsp3_state.op1e_max_search_radius);
1091   state_save_register_global(machine, dsp3_state.op1e_max_path_radius);
1092
1093   state_save_register_global(machine, dsp3_state.op1e_lcv_radius);
1094   state_save_register_global(machine, dsp3_state.op1e_lcv_steps);
1095   state_save_register_global(machine, dsp3_state.op1e_lcv_turns);
1096
1097}
1098
1099static void dsp3_init( running_machine *machine )
1100{
10261101   UINT32 i;
10271102   UINT8 *dspin = memory_region(machine, "addons");
10281103
1029   DSP3_Reset();
10301104
10311105   // expand the DSP-3 data ROM
1032   for (i = 0; i < 2048; i+=2)
1106   for (i = 0; i < 2048; i += 2)
10331107   {
1034      DSP3_DataROM[i/2] = dspin[0x800 + i] << 8 | dspin[0x800 + i + 1];
1108      dsp3_state.DataROM[i / 2] = dspin[0x800 + i] << 8 | dspin[0x800 + i + 1];
10351109   }
1110
1111   dsp3_register_save(machine);
10361112}
src/mame/machine/snesrtc.c
r7621r7622
11/***************************************************************************
22
3  snessdd1.c
3  snesrtc.c
44
55  File to handle emulation of the SNES "S-RTC" add-on chip.
66
r7621r7622
2222   RTCM_Write
2323};
2424
25typedef struct
25struct _snes_rtc_state
2626{
27   UINT8 rtc_ram[13];
28   INT32 rtc_mode;
29   INT8 rtc_index;
30} _snes_rtc_t;
27   UINT8  ram[13];
28   INT32  mode;
29   INT8   index;
30};
3131
32static _snes_rtc_t snes_rtc;
32static _snes_rtc_state rtc_state;
3333
3434static const UINT8 srtc_months[12] =
3535{
r7621r7622
3939   31, 30, 31
4040};
4141
42static void srtc_update_time(running_machine *machine)
42static void srtc_update_time( running_machine *machine )
4343{
4444   mame_system_time curtime, *systime = &curtime;
4545   mame_get_current_datetime(machine, &curtime);
46   snes_rtc.rtc_ram[0] = systime->local_time.second % 10;
47   snes_rtc.rtc_ram[1] = systime->local_time.second / 10;
48   snes_rtc.rtc_ram[2] = systime->local_time.minute % 10;
49   snes_rtc.rtc_ram[3] = systime->local_time.minute / 10;
50   snes_rtc.rtc_ram[4] = systime->local_time.hour % 10;
51   snes_rtc.rtc_ram[5] = systime->local_time.hour / 10;
52   snes_rtc.rtc_ram[6] = systime->local_time.mday % 10;
53   snes_rtc.rtc_ram[7] = systime->local_time.mday / 10;
54   snes_rtc.rtc_ram[8] = systime->local_time.month;
55   snes_rtc.rtc_ram[9] = (systime->local_time.year - 1900) % 10;
56   snes_rtc.rtc_ram[10] = ((systime->local_time.year - 1900) / 10) % 10;
57   snes_rtc.rtc_ram[11] = (systime->local_time.year - 1900) / 100;
58   snes_rtc.rtc_ram[12] = systime->local_time.weekday % 7;
46   rtc_state.ram[0] = systime->local_time.second % 10;
47   rtc_state.ram[1] = systime->local_time.second / 10;
48   rtc_state.ram[2] = systime->local_time.minute % 10;
49   rtc_state.ram[3] = systime->local_time.minute / 10;
50   rtc_state.ram[4] = systime->local_time.hour % 10;
51   rtc_state.ram[5] = systime->local_time.hour / 10;
52   rtc_state.ram[6] = systime->local_time.mday % 10;
53   rtc_state.ram[7] = systime->local_time.mday / 10;
54   rtc_state.ram[8] = systime->local_time.month;
55   rtc_state.ram[9] = (systime->local_time.year - 1900) % 10;
56   rtc_state.ram[10] = ((systime->local_time.year - 1900) / 10) % 10;
57   rtc_state.ram[11] = (systime->local_time.year - 1900) / 100;
58   rtc_state.ram[12] = systime->local_time.weekday % 7;
5959}
6060
6161// Returns day-of-week for specified date
6262// e.g. 0 = Sunday, 1 = Monday, ... 6 = Saturday
6363// Usage: weekday(2008, 1, 1) returns the weekday of January 1st, 2008
64static UINT8 srtc_weekday(UINT32 year, UINT32 month, UINT32 day)
64static UINT8 srtc_weekday( UINT32 year, UINT32 month, UINT32 day )
6565{
6666   UINT32 y = 1900, m = 1;   // Epoch is 1900-01-01
6767   UINT32 sum = 0;         // Number of days passed since epoch
r7621r7622
7070   month = MAX(1, MIN(12, month));
7171   day = MAX(1, MIN(31, day));
7272
73   while(y < year)
73   while (y < year)
7474   {
7575      UINT8 leapyear = 0;
76      if((y % 4) == 0)
76      if ((y % 4) == 0)
7777      {
7878         leapyear = 1;
79         if((y % 100) == 0 && (y % 400) != 0)
79         if ((y % 100) == 0 && (y % 400) != 0)
8080         {
8181            leapyear = 0;
8282         }
r7621r7622
8585      y++;
8686   }
8787
88   while(m < month)
88   while (m < month)
8989   {
9090      UINT32 days = srtc_months[m - 1];
91      if(days == 28)
91      if (days == 28)
9292      {
9393         UINT8 leapyear = 0;
94         if((y % 4) == 0)
94         if ((y % 4) == 0)
9595         {
9696            leapyear = 1;
97            if((y % 100) == 0 && (y % 400) != 0)
97            if ((y % 100) == 0 && (y % 400) != 0)
9898            {
9999               leapyear = 0;
100100            }
r7621r7622
109109   return (sum + 1) % 7; // 1900-01-01 was a Monday
110110}
111111
112static UINT8 srtc_mmio_read(running_machine *machine, UINT16 addr)
112static UINT8 srtc_read( running_machine *machine, UINT16 addr )
113113{
114114   addr &= 0xffff;
115115
116   if(addr == 0x2800)
116   if (addr == 0x2800)
117117   {
118      if(snes_rtc.rtc_mode != RTCM_Read)
118      if (rtc_state.mode != RTCM_Read)
119119      {
120120         return 0x00;
121121      }
122122
123      if(snes_rtc.rtc_index < 0)
123      if (rtc_state.index < 0)
124124      {
125125         srtc_update_time(machine);
126         snes_rtc.rtc_index++;
126         rtc_state.index++;
127127         return 0x0f;
128128      }
129      else if(snes_rtc.rtc_index > 12)
129      else if (rtc_state.index > 12)
130130      {
131         snes_rtc.rtc_index = -1;
131         rtc_state.index = -1;
132132         return 0x0f;
133133      }
134134      else
135135      {
136         return snes_rtc.rtc_ram[snes_rtc.rtc_index++];
136         return rtc_state.ram[rtc_state.index++];
137137      }
138138   }
139139
140140   return 0xff;
141141}
142142
143static void srtc_mmio_write(running_machine *machine, UINT16 addr, UINT8 data)
143static void srtc_write( running_machine *machine, UINT16 addr, UINT8 data )
144144{
145145   addr &= 0xffff;
146146
147   if(addr == 0x2801)
147   if (addr == 0x2801)
148148   {
149149      data &= 0x0f;   // Only the low four bits are used
150150
151      if(data == 0x0d)
151      if (data == 0x0d)
152152      {
153         snes_rtc.rtc_mode = RTCM_Read;
154         snes_rtc.rtc_index = -1;
153         rtc_state.mode = RTCM_Read;
154         rtc_state.index = -1;
155155         return;
156156      }
157157
158      if(data == 0x0e)
158      if (data == 0x0e)
159159      {
160         snes_rtc.rtc_mode = RTCM_Command;
160         rtc_state.mode = RTCM_Command;
161161         return;
162162      }
163163
164      if(data == 0x0f)
164      if (data == 0x0f)
165165      {
166166         return;   // Unknown behaviour
167167      }
168168
169      if(snes_rtc.rtc_mode == RTCM_Write)
169      if (rtc_state.mode == RTCM_Write)
170170      {
171         if(snes_rtc.rtc_index >= 0 && snes_rtc.rtc_index < 12)
171         if (rtc_state.index >= 0 && rtc_state.index < 12)
172172         {
173            snes_rtc.rtc_ram[snes_rtc.rtc_index++] = data;
173            rtc_state.ram[rtc_state.index++] = data;
174174
175            if(snes_rtc.rtc_index == 12)
175            if (rtc_state.index == 12)
176176            {
177177               // Day of week is automatically calculated and written
178               UINT32 day   = snes_rtc.rtc_ram[6] + snes_rtc.rtc_ram[7] * 10;
179               UINT32 month = snes_rtc.rtc_ram[8];
180               UINT32 year  = snes_rtc.rtc_ram[9] + snes_rtc.rtc_ram[10] * 10 + snes_rtc.rtc_ram[11] * 100;
178               UINT32 day   = rtc_state.ram[6] + rtc_state.ram[7] * 10;
179               UINT32 month = rtc_state.ram[8];
180               UINT32 year  = rtc_state.ram[9] + rtc_state.ram[10] * 10 + rtc_state.ram[11] * 100;
181181               year += 1000;
182182
183               snes_rtc.rtc_ram[snes_rtc.rtc_index++] = srtc_weekday(year, month, day);
183               rtc_state.ram[rtc_state.index++] = srtc_weekday(year, month, day);
184184            }
185185         }
186186      }
187      else if(snes_rtc.rtc_mode == RTCM_Command)
187      else if (rtc_state.mode == RTCM_Command)
188188      {
189         if(data == 0)
189         if (data == 0)
190190         {
191            snes_rtc.rtc_mode = RTCM_Write;
192            snes_rtc.rtc_index = 0;
191            rtc_state.mode = RTCM_Write;
192            rtc_state.index = 0;
193193         }
194         else if(data == 4)
194         else if (data == 4)
195195         {
196196            UINT8 i;
197            snes_rtc.rtc_mode = RTCM_Ready;
198            snes_rtc.rtc_index = -1;
197            rtc_state.mode = RTCM_Ready;
198            rtc_state.index = -1;
199199            for(i = 0; i < 13; i++)
200200            {
201               snes_rtc.rtc_ram[i] = 0;
201               rtc_state.ram[i] = 0;
202202            }
203203         }
204204         else
205205         {
206206            // Unknown behaviour
207            snes_rtc.rtc_mode = RTCM_Ready;
207            rtc_state.mode = RTCM_Ready;
208208         }
209209      }
210210   }
211211}
212212
213static void srtc_reset(running_machine *machine)
213static void srtc_init( running_machine *machine )
214214{
215   snes_rtc.rtc_mode = RTCM_Read;
216   snes_rtc.rtc_index = -1;
215   rtc_state.mode = RTCM_Read;
216   rtc_state.index = -1;
217217   srtc_update_time(machine);
218
219   state_save_register_global_array(machine, rtc_state.ram);
220   state_save_register_global(machine, rtc_state.mode);
221   state_save_register_global(machine, rtc_state.index);
218222}
219
src/mame/machine/snesdsp4.c
r7621r7622
2727
2828#include "snesdsp4.h"
2929
30static struct DSP4_t DSP4;
31static struct DSP4_vars_t DSP4_vars;
30static struct dsp4_t dsp4;
31static struct dsp4_vars_t dsp4_vars;
3232
3333INLINE UINT16 READ_WORD(UINT8 *addr)
3434{
r7621r7622
5353
5454static INT16 DSP4_READ_WORD( void )
5555{
56  INT16 out;
56   INT16 out;
5757
58  out = READ_WORD(DSP4.parameters + DSP4.in_index);
59  DSP4.in_index += 2;
58   out = READ_WORD(dsp4.parameters + dsp4.in_index);
59   dsp4.in_index += 2;
6060
61  return out;
61   return out;
6262}
6363
6464static INT32 DSP4_READ_DWORD( void )
6565{
66  INT32 out;
66   INT32 out;
6767
68  out = READ_DWORD(DSP4.parameters + DSP4.in_index);
69  DSP4.in_index += 4;
68   out = READ_DWORD(dsp4.parameters + dsp4.in_index);
69   dsp4.in_index += 4;
7070
71  return out;
71   return out;
7272}
7373
7474
r7621r7622
7777// output protocol
7878
7979#define DSP4_CLEAR_OUT() \
80{ DSP4.out_count = 0; DSP4.out_index = 0; }
80{ dsp4.out_count = 0; dsp4.out_index = 0; }
8181
8282#define DSP4_WRITE_BYTE( d ) \
83{ WRITE_WORD( DSP4.output + DSP4.out_count, ( d ) ); DSP4.out_count++; }
83{ WRITE_WORD( dsp4.output + dsp4.out_count, ( d ) ); dsp4.out_count++; }
8484
8585#define DSP4_WRITE_WORD( d ) \
86{ WRITE_WORD( DSP4.output + DSP4.out_count, ( d ) ); DSP4.out_count += 2; }
86{ WRITE_WORD( dsp4.output + dsp4.out_count, ( d ) ); dsp4.out_count += 2; }
8787
8888#ifndef MSB_FIRST
8989#define DSP4_WRITE_16_WORD( d ) \
90{ memcpy(DSP4.output + DSP4.out_count, ( d ), 32); DSP4.out_count += 32; }
90{ memcpy(dsp4.output + dsp4.out_count, ( d ), 32); dsp4.out_count += 32; }
9191#else
92#define DSP4_WRITE_16_WORD( d )                         \
93{ INT16 *p = ( d ), *end = ( d )+16;                    \
94  for (; p != end; p++)                                 \
95  {                                                     \
96    WRITE_WORD( DSP4.output + DSP4.out_count, *p );     \
97  }                                                     \
98  DSP4.out_count += 32;                                 \
92#define DSP4_WRITE_16_WORD( d )                             \
93{                                                           \
94   INT16 *p = ( d ), *end = ( d )+16;                    \
95   for (; p != end; p++)                                 \
96   {                                                     \
97      WRITE_WORD( dsp4.output + dsp4.out_count, *p ); \
98   }                                                     \
99   dsp4.out_count += 32;                                 \
99100}
100101#endif
101102
102103#ifdef PRINT_OP
103104#define DSP4_WRITE_DEBUG( x, d ) \
104  WRITE_WORD( nop + x, d );
105   WRITE_WORD( nop + x, d );
105106#endif
106107
107108#ifdef DEBUG_DSP
108109#define DSP4_WRITE_DEBUG( x, d ) \
109  WRITE_WORD( nop + x, d );
110   WRITE_WORD( nop + x, d );
110111#endif
111112
112113//////////////////////////////////////////////////////////////
r7621r7622
114115// used to wait for dsp i/o
115116
116117#define DSP4_WAIT( x ) \
117  DSP4.in_index = 0; DSP4_vars.DSP4_Logic = x; return;
118   dsp4.in_index = 0; dsp4_vars.Logic = x; return;
118119
119120//////////////////////////////////////////////////////////////
120121
r7621r7622
142143                                    0x0333, 0x031f, 0x030c, 0x02fa, 0x02e8, 0x02d8, 0x02c8, 0x02b9, 0x02aa, 0x029c,
143144                                    0x028f, 0x0282, 0x0276, 0x026a, 0x025e, 0x0253, 0x0249, 0x023e, 0x0234, 0x022b,
144145                                    0x0222, 0x0219, 0x0210, 0x0208,  };
145static INT16 DSP4_Inverse(INT16 value)
146static INT16 dsp4_Inverse(INT16 value)
146147{
147  // saturate bounds
148  if (value < 0)
149  {
150    value = 0;
151  }
152  if (value > 63)
153  {
154    value = 63;
155  }
148   // saturate bounds
149   if (value < 0)
150   {
151      value = 0;
152   }
153   if (value > 63)
154   {
155      value = 63;
156   }
156157
157  return div_lut[value];
158   return div_lut[value];
158159}
159160
160161//////////////////////////////////////////////////////////////
161162
162163// Prototype
163static void DSP4_OP0B(UINT8 *draw, INT16 sp_x, INT16 sp_y, INT16 sp_attr, UINT8 size, UINT8 stop);
164static void dsp4_OP0B(UINT8 *draw, INT16 sp_x, INT16 sp_y, INT16 sp_attr, UINT8 size, UINT8 stop);
164165
165166//////////////////////////////////////////////////////////////
166167
167168// OP00
168static void DSP4_Multiply(INT16 Multiplicand, INT16 Multiplier, INT32 *Product)
169static void dsp4_Multiply(INT16 Multiplicand, INT16 Multiplier, INT32 *Product)
169170{
170  *Product = (Multiplicand * Multiplier << 1) >> 1;
171   *Product = (Multiplicand * Multiplier << 1) >> 1;
171172}
172173
173174//////////////////////////////////////////////////////////////
174175
175176
176static void DSP4_OP01( void )
177static void dsp4_OP01( void )
177178{
178  DSP4.waiting4command = 0;
179   dsp4.waiting4command = 0;
179180
180  // op flow control
181  switch (DSP4_vars.DSP4_Logic)
182  {
183    case 1:
184      goto resume1; break;
185    case 2:
186      goto resume2; break;
187    case 3:
188      goto resume3; break;
189  }
181   // op flow control
182   switch (dsp4_vars.Logic)
183   {
184      case 1:
185         goto resume1; break;
186      case 2:
187         goto resume2; break;
188      case 3:
189         goto resume3; break;
190   }
190191
191  ////////////////////////////////////////////////////
192  // process initial inputs
192   ////////////////////////////////////////////////////
193   // process initial inputs
193194
194  // sort inputs
195  DSP4_vars.world_y = DSP4_READ_DWORD();
196  DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
197  DSP4_vars.poly_top[0][0] = DSP4_READ_WORD();
198  DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD();
199  DSP4_vars.viewport_bottom = DSP4_READ_WORD();
200  DSP4_vars.world_x = DSP4_READ_DWORD();
201  DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD();
202  DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
203  DSP4_vars.world_yofs = DSP4_READ_WORD();
204  DSP4_vars.world_dy = DSP4_READ_DWORD();
205  DSP4_vars.world_dx = DSP4_READ_DWORD();
206  DSP4_vars.distance = DSP4_READ_WORD();
207  DSP4_READ_WORD(); // 0x0000
208  DSP4_vars.world_xenv = DSP4_READ_DWORD();
209  DSP4_vars.world_ddy = DSP4_READ_WORD();
210  DSP4_vars.world_ddx = DSP4_READ_WORD();
211  DSP4_vars.view_yofsenv = DSP4_READ_WORD();
195   // sort inputs
196   dsp4_vars.world_y = DSP4_READ_DWORD();
197   dsp4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
198   dsp4_vars.poly_top[0][0] = DSP4_READ_WORD();
199   dsp4_vars.poly_cx[1][0] = DSP4_READ_WORD();
200   dsp4_vars.viewport_bottom = DSP4_READ_WORD();
201   dsp4_vars.world_x = DSP4_READ_DWORD();
202   dsp4_vars.poly_cx[0][0] = DSP4_READ_WORD();
203   dsp4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
204   dsp4_vars.world_yofs = DSP4_READ_WORD();
205   dsp4_vars.world_dy = DSP4_READ_DWORD();
206   dsp4_vars.world_dx = DSP4_READ_DWORD();
207   dsp4_vars.distance = DSP4_READ_WORD();
208   DSP4_READ_WORD(); // 0x0000
209   dsp4_vars.world_xenv = DSP4_READ_DWORD();
210   dsp4_vars.world_ddy = DSP4_READ_WORD();
211   dsp4_vars.world_ddx = DSP4_READ_WORD();
212   dsp4_vars.view_yofsenv = DSP4_READ_WORD();
212213
213  // initial (x,y,offset) at starting DSP4_vars.raster line
214  DSP4_vars.view_x1 = (INT16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16);
215  DSP4_vars.view_y1 = (INT16)(DSP4_vars.world_y >> 16);
216  DSP4_vars.view_xofs1 = (INT16)(DSP4_vars.world_x >> 16);
217  DSP4_vars.view_yofs1 = DSP4_vars.world_yofs;
218  DSP4_vars.view_turnoff_x = 0;
219  DSP4_vars.view_turnoff_dx = 0;
214   // initial (x,y,offset) at starting dsp4_vars.raster line
215   dsp4_vars.view_x1 = (INT16)((dsp4_vars.world_x + dsp4_vars.world_xenv) >> 16);
216   dsp4_vars.view_y1 = (INT16)(dsp4_vars.world_y >> 16);
217   dsp4_vars.view_xofs1 = (INT16)(dsp4_vars.world_x >> 16);
218   dsp4_vars.view_yofs1 = dsp4_vars.world_yofs;
219   dsp4_vars.view_turnoff_x = 0;
220   dsp4_vars.view_turnoff_dx = 0;
220221
221  // first DSP4_vars.raster line
222  DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0];
222   // first dsp4_vars.raster line
223   dsp4_vars.poly_raster[0][0] = dsp4_vars.poly_bottom[0][0];
223224
224  do
225  {
226    ////////////////////////////////////////////////////
227    // process one iteration of projection
225   do
226   {
227      ////////////////////////////////////////////////////
228      // process one iteration of projection
228229
229    // perspective projection of world (x,y,scroll) points
230    // based on the current projection lines
231    DSP4_vars.view_x2 = (INT16)(( ( ( DSP4_vars.world_x + DSP4_vars.world_xenv ) >> 16 ) * DSP4_vars.distance >> 15 ) + ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 ));
232    DSP4_vars.view_y2 = (INT16)((DSP4_vars.world_y >> 16) * DSP4_vars.distance >> 15);
233    DSP4_vars.view_xofs2 = DSP4_vars.view_x2;
234    DSP4_vars.view_yofs2 = (DSP4_vars.world_yofs * DSP4_vars.distance >> 15) + DSP4_vars.poly_bottom[0][0] - DSP4_vars.view_y2;
230      // perspective projection of world (x,y,scroll) points
231      // based on the current projection lines
232      dsp4_vars.view_x2 = (INT16)(( ( ( dsp4_vars.world_x + dsp4_vars.world_xenv ) >> 16 ) * dsp4_vars.distance >> 15 ) + ( dsp4_vars.view_turnoff_x * dsp4_vars.distance >> 15 ));
233      dsp4_vars.view_y2 = (INT16)((dsp4_vars.world_y >> 16) * dsp4_vars.distance >> 15);
234      dsp4_vars.view_xofs2 = dsp4_vars.view_x2;
235      dsp4_vars.view_yofs2 = (dsp4_vars.world_yofs * dsp4_vars.distance >> 15) + dsp4_vars.poly_bottom[0][0] - dsp4_vars.view_y2;
235236
236237
237    // 1. World x-location before transformation
238    // 2. Viewer x-position at the next
239    // 3. World y-location before perspective projection
240    // 4. Viewer y-position below the horizon
241    // 5. Number of DSP4_vars.raster lines drawn in this iteration
238      // 1. World x-location before transformation
239      // 2. Viewer x-position at the next
240      // 3. World y-location before perspective projection
241      // 4. Viewer y-position below the horizon
242      // 5. Number of dsp4_vars.raster lines drawn in this iteration
242243
243    DSP4_CLEAR_OUT();
244    DSP4_WRITE_WORD((UINT16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16));
245    DSP4_WRITE_WORD(DSP4_vars.view_x2);
246    DSP4_WRITE_WORD((UINT16)(DSP4_vars.world_y >> 16));
247    DSP4_WRITE_WORD(DSP4_vars.view_y2);
244      DSP4_CLEAR_OUT();
245      DSP4_WRITE_WORD((UINT16)((dsp4_vars.world_x + dsp4_vars.world_xenv) >> 16));
246      DSP4_WRITE_WORD(dsp4_vars.view_x2);
247      DSP4_WRITE_WORD((UINT16)(dsp4_vars.world_y >> 16));
248      DSP4_WRITE_WORD(dsp4_vars.view_y2);
248249
249    //////////////////////////////////////////////////////
250      //////////////////////////////////////////////////////
250251
251    // SR = 0x00
252      // SR = 0x00
252253
253    // determine # of DSP4_vars.raster lines used
254    DSP4_vars.segments = DSP4_vars.poly_raster[0][0] - DSP4_vars.view_y2;
254      // determine # of dsp4_vars.raster lines used
255      dsp4_vars.segments = dsp4_vars.poly_raster[0][0] - dsp4_vars.view_y2;
255256
256    // prevent overdraw
257    if (DSP4_vars.view_y2 >= DSP4_vars.poly_raster[0][0])
258      DSP4_vars.segments = 0;
259    else
260      DSP4_vars.poly_raster[0][0] = DSP4_vars.view_y2;
257      // prevent overdraw
258      if (dsp4_vars.view_y2 >= dsp4_vars.poly_raster[0][0])
259         dsp4_vars.segments = 0;
260      else
261         dsp4_vars.poly_raster[0][0] = dsp4_vars.view_y2;
261262
262    // don't draw outside the window
263    if (DSP4_vars.view_y2 < DSP4_vars.poly_top[0][0])
264    {
265      DSP4_vars.segments = 0;
263      // don't draw outside the window
264      if (dsp4_vars.view_y2 < dsp4_vars.poly_top[0][0])
265      {
266         dsp4_vars.segments = 0;
266267
267      // flush remaining DSP4_vars.raster lines
268      if (DSP4_vars.view_y1 >= DSP4_vars.poly_top[0][0])
269        DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.poly_top[0][0];
270    }
268         // flush remaining dsp4_vars.raster lines
269         if (dsp4_vars.view_y1 >= dsp4_vars.poly_top[0][0])
270            dsp4_vars.segments = dsp4_vars.view_y1 - dsp4_vars.poly_top[0][0];
271      }
271272
272    // SR = 0x80
273      // SR = 0x80
273274
274    DSP4_WRITE_WORD(DSP4_vars.segments);
275      DSP4_WRITE_WORD(dsp4_vars.segments);
275276
276    //////////////////////////////////////////////////////
277      //////////////////////////////////////////////////////
277278
278    // scan next command if no SR check needed
279    if (DSP4_vars.segments)
280    {
281      INT32 px_dx, py_dy;
282      INT32 x_scroll, y_scroll;
279      // scan next command if no SR check needed
280      if (dsp4_vars.segments)
281      {
282         INT32 px_dx, py_dy;
283         INT32 x_scroll, y_scroll;
283284
284      // SR = 0x00
285         // SR = 0x00
285286
286      // linear interpolation (lerp) between projected points
287      px_dx = (DSP4_vars.view_xofs2 - DSP4_vars.view_xofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;
288      py_dy = (DSP4_vars.view_yofs2 - DSP4_vars.view_yofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;
287         // linear interpolation (lerp) between projected points
288         px_dx = (dsp4_vars.view_xofs2 - dsp4_vars.view_xofs1) * dsp4_Inverse(dsp4_vars.segments) << 1;
289         py_dy = (dsp4_vars.view_yofs2 - dsp4_vars.view_yofs1) * dsp4_Inverse(dsp4_vars.segments) << 1;
289290
290      // starting step values
291      x_scroll = SEX16(DSP4_vars.poly_cx[0][0] + DSP4_vars.view_xofs1);
292      y_scroll = SEX16(-DSP4_vars.viewport_bottom + DSP4_vars.view_yofs1 + DSP4_vars.view_yofsenv + DSP4_vars.poly_cx[1][0] - DSP4_vars.world_yofs);
291         // starting step values
292         x_scroll = SEX16(dsp4_vars.poly_cx[0][0] + dsp4_vars.view_xofs1);
293         y_scroll = SEX16(-dsp4_vars.viewport_bottom + dsp4_vars.view_yofs1 + dsp4_vars.view_yofsenv + dsp4_vars.poly_cx[1][0] - dsp4_vars.world_yofs);
293294
294      // SR = 0x80
295         // SR = 0x80
295296
296      // rasterize line
297      for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++)
298      {
299        // 1. HDMA memory pointer (bg1)
300        // 2. vertical scroll offset ($210E)
301        // 3. horizontal scroll offset ($210D)
297         // rasterize line
298         for (dsp4_vars.lcv = 0; dsp4_vars.lcv < dsp4_vars.segments; dsp4_vars.lcv++)
299         {
300            // 1. HDMA memory pointer (bg1)
301            // 2. vertical scroll offset ($210E)
302            // 3. horizontal scroll offset ($210D)
302303
303        DSP4_WRITE_WORD(DSP4_vars.poly_ptr[0][0]);
304        DSP4_WRITE_WORD((UINT16)((y_scroll + 0x8000) >> 16));
305        DSP4_WRITE_WORD((UINT16)((x_scroll + 0x8000) >> 16));
304            DSP4_WRITE_WORD(dsp4_vars.poly_ptr[0][0]);
305            DSP4_WRITE_WORD((UINT16)((y_scroll + 0x8000) >> 16));
306            DSP4_WRITE_WORD((UINT16)((x_scroll + 0x8000) >> 16));
306307
307308
308        // update memory address
309        DSP4_vars.poly_ptr[0][0] -= 4;
309            // update memory address
310            dsp4_vars.poly_ptr[0][0] -= 4;
310311
311        // update screen values
312        x_scroll += px_dx;
313        y_scroll += py_dy;
314      }
315    }
312            // update screen values
313            x_scroll += px_dx;
314            y_scroll += py_dy;
315         }
316      }
316317
317    ////////////////////////////////////////////////////
318    // Post-update
318      ////////////////////////////////////////////////////
319      // Post-update
319320
320    // update new viewer (x,y,scroll) to last DSP4_vars.raster line drawn
321    DSP4_vars.view_x1 = DSP4_vars.view_x2;
322    DSP4_vars.view_y1 = DSP4_vars.view_y2;
323    DSP4_vars.view_xofs1 = DSP4_vars.view_xofs2;
324    DSP4_vars.view_yofs1 = DSP4_vars.view_yofs2;
321      // update new viewer (x,y,scroll) to last dsp4_vars.raster line drawn
322      dsp4_vars.view_x1 = dsp4_vars.view_x2;
323      dsp4_vars.view_y1 = dsp4_vars.view_y2;
324      dsp4_vars.view_xofs1 = dsp4_vars.view_xofs2;
325      dsp4_vars.view_yofs1 = dsp4_vars.view_yofs2;
325326
326    // add deltas for projection lines
327    DSP4_vars.world_dx += SEX78(DSP4_vars.world_ddx);
328    DSP4_vars.world_dy += SEX78(DSP4_vars.world_ddy);
327      // add deltas for projection lines
328      dsp4_vars.world_dx += SEX78(dsp4_vars.world_ddx);
329      dsp4_vars.world_dy += SEX78(dsp4_vars.world_ddy);
329330
330    // update projection lines
331    DSP4_vars.world_x += (DSP4_vars.world_dx + DSP4_vars.world_xenv);
332    DSP4_vars.world_y += DSP4_vars.world_dy;
331      // update projection lines
332      dsp4_vars.world_x += (dsp4_vars.world_dx + dsp4_vars.world_xenv);
333      dsp4_vars.world_y += dsp4_vars.world_dy;
333334
334    // update road turnoff position
335    DSP4_vars.view_turnoff_x += DSP4_vars.view_turnoff_dx;
335      // update road turnoff position
336      dsp4_vars.view_turnoff_x += dsp4_vars.view_turnoff_dx;
336337
337    ////////////////////////////////////////////////////
338    // command check
338      ////////////////////////////////////////////////////
339      // command check
339340
340    // scan next command
341    DSP4.in_count = 2;
342    DSP4_WAIT(1) resume1 :
341      // scan next command
342      dsp4.in_count = 2;
343      DSP4_WAIT(1) resume1 :
343344
344    // check for termination
345    DSP4_vars.distance = DSP4_READ_WORD();
346    if (DSP4_vars.distance == -0x8000)
347      break;
345      // check for termination
346      dsp4_vars.distance = DSP4_READ_WORD();
347      if (dsp4_vars.distance == -0x8000)
348         break;
348349
349    // road turnoff
350    if( (UINT16) DSP4_vars.distance == 0x8001 )
351    {
352      DSP4.in_count = 6;
353      DSP4_WAIT(2) resume2:
350      // road turnoff
351      if( (UINT16) dsp4_vars.distance == 0x8001 )
352      {
353         dsp4.in_count = 6;
354         DSP4_WAIT(2) resume2:
354355
355      DSP4_vars.distance = DSP4_READ_WORD();
356      DSP4_vars.view_turnoff_x = DSP4_READ_WORD();
357      DSP4_vars.view_turnoff_dx = DSP4_READ_WORD();
356         dsp4_vars.distance = DSP4_READ_WORD();
357         dsp4_vars.view_turnoff_x = DSP4_READ_WORD();
358         dsp4_vars.view_turnoff_dx = DSP4_READ_WORD();
358359
359      // factor in new changes
360      DSP4_vars.view_x1 += ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 );
361      DSP4_vars.view_xofs1 += ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 );
360         // factor in new changes
361         dsp4_vars.view_x1 += ( dsp4_vars.view_turnoff_x * dsp4_vars.distance >> 15 );
362         dsp4_vars.view_xofs1 += ( dsp4_vars.view_turnoff_x * dsp4_vars.distance >> 15 );
362363
363      // update stepping values
364      DSP4_vars.view_turnoff_x += DSP4_vars.view_turnoff_dx;
364         // update stepping values
365         dsp4_vars.view_turnoff_x += dsp4_vars.view_turnoff_dx;
365366
366      DSP4.in_count = 2;
367      DSP4_WAIT(1)
368    }
367         dsp4.in_count = 2;
368         DSP4_WAIT(1)
369      }
369370
370    // already have 2 bytes read
371    DSP4.in_count = 6;
372    DSP4_WAIT(3) resume3 :
371      // already have 2 bytes read
372      dsp4.in_count = 6;
373      DSP4_WAIT(3) resume3 :
373374
374    // inspect inputs
375    DSP4_vars.world_ddy = DSP4_READ_WORD();
376    DSP4_vars.world_ddx = DSP4_READ_WORD();
377    DSP4_vars.view_yofsenv = DSP4_READ_WORD();
375      // inspect inputs
376      dsp4_vars.world_ddy = DSP4_READ_WORD();
377      dsp4_vars.world_ddx = DSP4_READ_WORD();
378      dsp4_vars.view_yofsenv = DSP4_READ_WORD();
378379
379    // no envelope here
380    DSP4_vars.world_xenv = 0;
381  }
382  while (1);
380      // no envelope here
381      dsp4_vars.world_xenv = 0;
382   }
383   while (1);
383384
384  // terminate op
385  DSP4.waiting4command = 1;
385   // terminate op
386   dsp4.waiting4command = 1;
386387}
387388
388389//////////////////////////////////////////////////////////////
389390
390391
391static void DSP4_OP03( void )
392static void dsp4_OP03( void )
392393{
393  DSP4_vars.OAM_RowMax = 33;
394  memset(DSP4_vars.OAM_Row, 0, 64);
394   dsp4_vars.OAM_RowMax = 33;
395   memset(dsp4_vars.OAM_Row, 0, 64);
395396}
396397
397398
398399//////////////////////////////////////////////////////////////
399400
400401
401static void DSP4_OP05( void )
402static void dsp4_OP05( void )
402403{
403  DSP4_vars.OAM_index = 0;
404  DSP4_vars.OAM_bits = 0;
405  memset(DSP4_vars.OAM_attr, 0, 32);
406  DSP4_vars.sprite_count = 0;
404   dsp4_vars.OAM_index = 0;
405   dsp4_vars.OAM_bits = 0;
406   memset(dsp4_vars.OAM_attr, 0, 32);
407   dsp4_vars.sprite_count = 0;
407408}
408409
409410
410411//////////////////////////////////////////////////////////////
411412
412static void DSP4_OP06( void )
413static void dsp4_OP06( void )
413414{
414  DSP4_CLEAR_OUT();
415  DSP4_WRITE_16_WORD(DSP4_vars.OAM_attr);
415   DSP4_CLEAR_OUT();
416   DSP4_WRITE_16_WORD(dsp4_vars.OAM_attr);
416417}
417418
418419//////////////////////////////////////////////////////////////
419420
420421
421static void DSP4_OP07( void )
422static void dsp4_OP07( void )
422423{
423  DSP4.waiting4command = 0;
424   dsp4.waiting4command = 0;
424425
425  // op flow control
426  switch (DSP4_vars.DSP4_Logic)
427  {
428    case 1:
429      goto resume1; break;
430    case 2:
431      goto resume2; break;
432  }
426   // op flow control
427   switch (dsp4_vars.Logic)
428   {
429      case 1:
430         goto resume1; break;
431      case 2:
432         goto resume2; break;
433   }
433434
434  ////////////////////////////////////////////////////
435  // sort inputs
435   ////////////////////////////////////////////////////
436   // sort inputs
436437
437  DSP4_vars.world_y = DSP4_READ_DWORD();
438  DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
439  DSP4_vars.poly_top[0][0] = DSP4_READ_WORD();
440  DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD();
441  DSP4_vars.viewport_bottom = DSP4_READ_WORD();
442  DSP4_vars.world_x = DSP4_READ_DWORD();
443  DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD();
444  DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
445  DSP4_vars.world_yofs = DSP4_READ_WORD();
446  DSP4_vars.distance = DSP4_READ_WORD();
447  DSP4_vars.view_y2 = DSP4_READ_WORD();
448  DSP4_vars.view_dy = DSP4_READ_WORD() * DSP4_vars.distance >> 15;
449  DSP4_vars.view_x2 = DSP4_READ_WORD();
450  DSP4_vars.view_dx = DSP4_READ_WORD() * DSP4_vars.distance >> 15;
451  DSP4_vars.view_yofsenv = DSP4_READ_WORD();
438   dsp4_vars.world_y = DSP4_READ_DWORD();
439   dsp4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
440   dsp4_vars.poly_top[0][0] = DSP4_READ_WORD();
441   dsp4_vars.poly_cx[1][0] = DSP4_READ_WORD();
442   dsp4_vars.viewport_bottom = DSP4_READ_WORD();
443   dsp4_vars.world_x = DSP4_READ_DWORD();
444   dsp4_vars.poly_cx[0][0] = DSP4_READ_WORD();
445   dsp4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
446   dsp4_vars.world_yofs = DSP4_READ_WORD();
447   dsp4_vars.distance = DSP4_READ_WORD();
448   dsp4_vars.view_y2 = DSP4_READ_WORD();
449   dsp4_vars.view_dy = DSP4_READ_WORD() * dsp4_vars.distance >> 15;
450   dsp4_vars.view_x2 = DSP4_READ_WORD();
451   dsp4_vars.view_dx = DSP4_READ_WORD() * dsp4_vars.distance >> 15;
452   dsp4_vars.view_yofsenv = DSP4_READ_WORD();
452453
453  // initial (x,y,offset) at starting DSP4_vars.raster line
454  DSP4_vars.view_x1 = (INT16)(DSP4_vars.world_x >> 16);
455  DSP4_vars.view_y1 = (INT16)(DSP4_vars.world_y >> 16);
456  DSP4_vars.view_xofs1 = DSP4_vars.view_x1;
457  DSP4_vars.view_yofs1 = DSP4_vars.world_yofs;
454   // initial (x,y,offset) at starting dsp4_vars.raster line
455   dsp4_vars.view_x1 = (INT16)(dsp4_vars.world_x >> 16);
456   dsp4_vars.view_y1 = (INT16)(dsp4_vars.world_y >> 16);
457   dsp4_vars.view_xofs1 = dsp4_vars.view_x1;
458   dsp4_vars.view_yofs1 = dsp4_vars.world_yofs;
458459
459  // first DSP4_vars.raster line
460  DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0];
460   // first dsp4_vars.raster line
461   dsp4_vars.poly_raster[0][0] = dsp4_vars.poly_bottom[0][0];
461462
462463
463  do
464  {
465    ////////////////////////////////////////////////////
466    // process one iteration of projection
464   do
465   {
466      ////////////////////////////////////////////////////
467      // process one iteration of projection
467468
468    // add shaping
469    DSP4_vars.view_x2 += DSP4_vars.view_dx;
470    DSP4_vars.view_y2 += DSP4_vars.view_dy;
469      // add shaping
470      dsp4_vars.view_x2 += dsp4_vars.view_dx;
471      dsp4_vars.view_y2 += dsp4_vars.view_dy;
471472
472    // vertical scroll calculation
473    DSP4_vars.view_xofs2 = DSP4_vars.view_x2;
474    DSP4_vars.view_yofs2 = (DSP4_vars.world_yofs * DSP4_vars.distance >> 15) + DSP4_vars.poly_bottom[0][0] - DSP4_vars.view_y2;
473      // vertical scroll calculation
474      dsp4_vars.view_xofs2 = dsp4_vars.view_x2;
475      dsp4_vars.view_yofs2 = (dsp4_vars.world_yofs * dsp4_vars.distance >> 15) + dsp4_vars.poly_bottom[0][0] - dsp4_vars.view_y2;
475476
476    // 1. Viewer x-position at the next
477    // 2. Viewer y-position below the horizon
478    // 3. Number of DSP4_vars.raster lines drawn in this iteration
477      // 1. Viewer x-position at the next
478      // 2. Viewer y-position below the horizon
479      // 3. Number of dsp4_vars.raster lines drawn in this iteration
479480
480    DSP4_CLEAR_OUT();
481    DSP4_WRITE_WORD(DSP4_vars.view_x2);
482    DSP4_WRITE_WORD(DSP4_vars.view_y2);
481      DSP4_CLEAR_OUT();
482      DSP4_WRITE_WORD(dsp4_vars.view_x2);
483      DSP4_WRITE_WORD(dsp4_vars.view_y2);
483484
484    //////////////////////////////////////////////////////
485      //////////////////////////////////////////////////////
485486
486    // SR = 0x00
487      // SR = 0x00
487488
488    // determine # of DSP4_vars.raster lines used
489    DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.view_y2;
489      // determine # of dsp4_vars.raster lines used
490      dsp4_vars.segments = dsp4_vars.view_y1 - dsp4_vars.view_y2;
490491
491    // prevent overdraw
492    if (DSP4_vars.view_y2 >= DSP4_vars.poly_raster[0][0])
493      DSP4_vars.segments = 0;
494    else
495      DSP4_vars.poly_raster[0][0] = DSP4_vars.view_y2;
492      // prevent overdraw
493      if (dsp4_vars.view_y2 >= dsp4_vars.poly_raster[0][0])
494         dsp4_vars.segments = 0;
495      else
496         dsp4_vars.poly_raster[0][0] = dsp4_vars.view_y2;
496497
497    // don't draw outside the window
498    if (DSP4_vars.view_y2 < DSP4_vars.poly_top[0][0])
499    {
500      DSP4_vars.segments = 0;
498      // don't draw outside the window
499      if (dsp4_vars.view_y2 < dsp4_vars.poly_top[0][0])
500      {
501         dsp4_vars.segments = 0;
501502
502      // flush remaining DSP4_vars.raster lines
503      if (DSP4_vars.view_y1 >= DSP4_vars.poly_top[0][0])
504        DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.poly_top[0][0];
505    }
503         // flush remaining dsp4_vars.raster lines
504         if (dsp4_vars.view_y1 >= dsp4_vars.poly_top[0][0])
505            dsp4_vars.segments = dsp4_vars.view_y1 - dsp4_vars.poly_top[0][0];
506      }
506507
507    // SR = 0x80
508      // SR = 0x80
508509
509    DSP4_WRITE_WORD(DSP4_vars.segments);
510      DSP4_WRITE_WORD(dsp4_vars.segments);
510511
511    //////////////////////////////////////////////////////
512      //////////////////////////////////////////////////////
512513
513    // scan next command if no SR check needed
514    if (DSP4_vars.segments)
515    {
516      INT32 px_dx, py_dy;
517      INT32 x_scroll, y_scroll;
514      // scan next command if no SR check needed
515      if (dsp4_vars.segments)
516      {
517         INT32 px_dx, py_dy;
518         INT32 x_scroll, y_scroll;
518519
519      // SR = 0x00
520         // SR = 0x00
520521
521      // linear interpolation (lerp) between projected points
522      px_dx = (DSP4_vars.view_xofs2 - DSP4_vars.view_xofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;
523      py_dy = (DSP4_vars.view_yofs2 - DSP4_vars.view_yofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;
522         // linear interpolation (lerp) between projected points
523         px_dx = (dsp4_vars.view_xofs2 - dsp4_vars.view_xofs1) * dsp4_Inverse(dsp4_vars.segments) << 1;
524         py_dy = (dsp4_vars.view_yofs2 - dsp4_vars.view_yofs1) * dsp4_Inverse(dsp4_vars.segments) << 1;
524525
525      // starting step values
526      x_scroll = SEX16(DSP4_vars.poly_cx[0][0] + DSP4_vars.view_xofs1);
527      y_scroll = SEX16(-DSP4_vars.viewport_bottom + DSP4_vars.view_yofs1 + DSP4_vars.view_yofsenv + DSP4_vars.poly_cx[1][0] - DSP4_vars.world_yofs);
526         // starting step values
527         x_scroll = SEX16(dsp4_vars.poly_cx[0][0] + dsp4_vars.view_xofs1);
528         y_scroll = SEX16(-dsp4_vars.viewport_bottom + dsp4_vars.view_yofs1 + dsp4_vars.view_yofsenv + dsp4_vars.poly_cx[1][0] - dsp4_vars.world_yofs);
528529
529      // SR = 0x80
530         // SR = 0x80
530531
531      // rasterize line
532      for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++)
533      {
534        // 1. HDMA memory pointer (bg2)
535        // 2. vertical scroll offset ($2110)
536        // 3. horizontal scroll offset ($210F)
532         // rasterize line
533         for (dsp4_vars.lcv = 0; dsp4_vars.lcv < dsp4_vars.segments; dsp4_vars.lcv++)
534         {
535            // 1. HDMA memory pointer (bg2)
536            // 2. vertical scroll offset ($2110)
537            // 3. horizontal scroll offset ($210F)
537538
538        DSP4_WRITE_WORD(DSP4_vars.poly_ptr[0][0]);
539        DSP4_WRITE_WORD((UINT16)((y_scroll + 0x8000) >> 16));
540        DSP4_WRITE_WORD((UINT16)((x_scroll + 0x8000) >> 16));
539            DSP4_WRITE_WORD(dsp4_vars.poly_ptr[0][0]);
540            DSP4_WRITE_WORD((UINT16)((y_scroll + 0x8000) >> 16));
541            DSP4_WRITE_WORD((UINT16)((x_scroll + 0x8000) >> 16));
541542
542        // update memory address
543        DSP4_vars.poly_ptr[0][0] -= 4;
543            // update memory address
544            dsp4_vars.poly_ptr[0][0] -= 4;
544545
545        // update screen values
546        x_scroll += px_dx;
547        y_scroll += py_dy;
548      }
549    }
546            // update screen values
547            x_scroll += px_dx;
548            y_scroll += py_dy;
549         }
550      }
550551
551    /////////////////////////////////////////////////////
552    // Post-update
552      /////////////////////////////////////////////////////
553      // Post-update
553554
554    // update new viewer (x,y,scroll) to last DSP4_vars.raster line drawn
555    DSP4_vars.view_x1 = DSP4_vars.view_x2;
556    DSP4_vars.view_y1 = DSP4_vars.view_y2;
557    DSP4_vars.view_xofs1 = DSP4_vars.view_xofs2;
558    DSP4_vars.view_yofs1 = DSP4_vars.view_yofs2;
555      // update new viewer (x,y,scroll) to last dsp4_vars.raster line drawn
556      dsp4_vars.view_x1 = dsp4_vars.view_x2;
557      dsp4_vars.view_y1 = dsp4_vars.view_y2;
558      dsp4_vars.view_xofs1 = dsp4_vars.view_xofs2;
559      dsp4_vars.view_yofs1 = dsp4_vars.view_yofs2;
559560
560    ////////////////////////////////////////////////////
561    // command check
561      ////////////////////////////////////////////////////
562      // command check
562563
563    // scan next command
564    DSP4.in_count = 2;
565    DSP4_WAIT(1) resume1 :
564      // scan next command
565      dsp4.in_count = 2;
566      DSP4_WAIT(1) resume1 :
566567
567    // check for opcode termination
568    DSP4_vars.distance = DSP4_READ_WORD();
569    if (DSP4_vars.distance == -0x8000)
570      break;
568      // check for opcode termination
569      dsp4_vars.distance = DSP4_READ_WORD();
570      if (dsp4_vars.distance == -0x8000)
571         break;
571572
572    // already have 2 bytes in queue
573    DSP4.in_count = 10;
574    DSP4_WAIT(2) resume2 :
573      // already have 2 bytes in queue
574      dsp4.in_count = 10;
575      DSP4_WAIT(2) resume2 :
575576
576    // inspect inputs
577    DSP4_vars.view_y2 = DSP4_READ_WORD();
578    DSP4_vars.view_dy = DSP4_READ_WORD() * DSP4_vars.distance >> 15;
579    DSP4_vars.view_x2 = DSP4_READ_WORD();
580    DSP4_vars.view_dx = DSP4_READ_WORD() * DSP4_vars.distance >> 15;
581    DSP4_vars.view_yofsenv = DSP4_READ_WORD();
582  }
583  while (1);
577      // inspect inputs
578      dsp4_vars.view_y2 = DSP4_READ_WORD();
579      dsp4_vars.view_dy = DSP4_READ_WORD() * dsp4_vars.distance >> 15;
580      dsp4_vars.view_x2 = DSP4_READ_WORD();
581      dsp4_vars.view_dx = DSP4_READ_WORD() * dsp4_vars.distance >> 15;
582      dsp4_vars.view_yofsenv = DSP4_READ_WORD();
583   }
584   while (1);
584585
585  DSP4.waiting4command = 1;
586   dsp4.waiting4command = 1;
586587}
587588
588589//////////////////////////////////////////////////////////////
589590
590static void DSP4_OP08( void )
591static void dsp4_OP08( void )
591592{
592  INT16 wleft, wright;
593  INT16 view_x[2], view_y[2];
594  INT16 envelope[2][2];
593   INT16 wleft, wright;
594   INT16 view_x[2], view_y[2];
595   INT16 envelope[2][2];
595596
596  DSP4.waiting4command = 0;
597   dsp4.waiting4command = 0;
597598
598  // op flow control
599  switch (DSP4_vars.DSP4_Logic)
600  {
601    case 1:
602      goto resume1; break;
603    case 2:
604      goto resume2; break;
605  }
599   // op flow control
600   switch (dsp4_vars.Logic)
601   {
602      case 1:
603         goto resume1; break;
604      case 2:
605         goto resume2; break;
606   }
606607
607  ////////////////////////////////////////////////////
608  // process initial inputs for two polygons
608   ////////////////////////////////////////////////////
609   // process initial inputs for two polygons
609610
610  // clip values
611  DSP4_vars.poly_clipRt[0][0] = DSP4_READ_WORD();
612  DSP4_vars.poly_clipRt[0][1] = DSP4_READ_WORD();
613  DSP4_vars.poly_clipRt[1][0] = DSP4_READ_WORD();
614  DSP4_vars.poly_clipRt[1][1] = DSP4_READ_WORD();
611   // clip values
612   dsp4_vars.poly_clipRt[0][0] = DSP4_READ_WORD();
613   dsp4_vars.poly_clipRt[0][1] = DSP4_READ_WORD();
614   dsp4_vars.poly_clipRt[1][0] = DSP4_READ_WORD();
615   dsp4_vars.poly_clipRt[1][1] = DSP4_READ_WORD();
615616
616  DSP4_vars.poly_clipLf[0][0] = DSP4_READ_WORD();
617  DSP4_vars.poly_clipLf[0][1] = DSP4_READ_WORD();
618  DSP4_vars.poly_clipLf[1][0] = DSP4_READ_WORD();
619  DSP4_vars.poly_clipLf[1][1] = DSP4_READ_WORD();
617   dsp4_vars.poly_clipLf[0][0] = DSP4_READ_WORD();
618   dsp4_vars.poly_clipLf[0][1] = DSP4_READ_WORD();
619   dsp4_vars.poly_clipLf[1][0] = DSP4_READ_WORD();
620   dsp4_vars.poly_clipLf[1][1] = DSP4_READ_WORD();
620621
621  // unknown (constant) (ex. 1P/2P = $00A6, $00A6, $00A6, $00A6)
622  DSP4_READ_WORD();
623  DSP4_READ_WORD();
624  DSP4_READ_WORD();
625  DSP4_READ_WORD();
622   // unknown (constant) (ex. 1P/2P = $00A6, $00A6, $00A6, $00A6)
623   DSP4_READ_WORD();
624   DSP4_READ_WORD();
625   DSP4_READ_WORD();
626   DSP4_READ_WORD();
626627
627  // unknown (constant) (ex. 1P/2P = $00A5, $00A5, $00A7, $00A7)
628  DSP4_READ_WORD();
629  DSP4_READ_WORD();
630  DSP4_READ_WORD();
631  DSP4_READ_WORD();
628   // unknown (constant) (ex. 1P/2P = $00A5, $00A5, $00A7, $00A7)
629   DSP4_READ_WORD();
630   DSP4_READ_WORD();
631   DSP4_READ_WORD();
632   DSP4_READ_WORD();
632633
633  // polygon centering (left,right)
634  DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD();
635  DSP4_vars.poly_cx[0][1] = DSP4_READ_WORD();
636  DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD();
637  DSP4_vars.poly_cx[1][1] = DSP4_READ_WORD();
634   // polygon centering (left,right)
635   dsp4_vars.poly_cx[0][0] = DSP4_READ_WORD();
636   dsp4_vars.poly_cx[0][1] = DSP4_READ_WORD();
637   dsp4_vars.poly_cx[1][0] = DSP4_READ_WORD();
638   dsp4_vars.poly_cx[1][1] = DSP4_READ_WORD();
638639
639  // HDMA pointer locations
640  DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
641  DSP4_vars.poly_ptr[0][1] = DSP4_READ_WORD();
642  DSP4_vars.poly_ptr[1][0] = DSP4_READ_WORD();
643  DSP4_vars.poly_ptr[1][1] = DSP4_READ_WORD();
640   // HDMA pointer locations
641   dsp4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
642   dsp4_vars.poly_ptr[0][1] = DSP4_READ_WORD();
643   dsp4_vars.poly_ptr[1][0] = DSP4_READ_WORD();
644   dsp4_vars.poly_ptr[1][1] = DSP4_READ_WORD();
644645
645  // starting DSP4_vars.raster line below the horizon
646  DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
647  DSP4_vars.poly_bottom[0][1] = DSP4_READ_WORD();
648  DSP4_vars.poly_bottom[1][0] = DSP4_READ_WORD();
649  DSP4_vars.poly_bottom[1][1] = DSP4_READ_WORD();
646   // starting dsp4_vars.raster line below the horizon
647   dsp4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
648   dsp4_vars.poly_bottom[0][1] = DSP4_READ_WORD();
649   dsp4_vars.poly_bottom[1][0] = DSP4_READ_WORD();
650   dsp4_vars.poly_bottom[1][1] = DSP4_READ_WORD();
650651
651  // top boundary line to clip
652  DSP4_vars.poly_top[0][0] = DSP4_READ_WORD();
653  DSP4_vars.poly_top[0][1] = DSP4_READ_WORD();
654  DSP4_vars.poly_top[1][0] = DSP4_READ_WORD();
655  DSP4_vars.poly_top[1][1] = DSP4_READ_WORD();
652   // top boundary line to clip
653   dsp4_vars.poly_top[0][0] = DSP4_READ_WORD();
654   dsp4_vars.poly_top[0][1] = DSP4_READ_WORD();
655   dsp4_vars.poly_top[1][0] = DSP4_READ_WORD();
656   dsp4_vars.poly_top[1][1] = DSP4_READ_WORD();
656657
657  // unknown
658  // (ex. 1P = $2FC8, $0034, $FF5C, $0035)
659  //
660  // (ex. 2P = $3178, $0034, $FFCC, $0035)
661  // (ex. 2P = $2FC8, $0034, $FFCC, $0035)
658   // unknown
659   // (ex. 1P = $2FC8, $0034, $FF5C, $0035)
660   //
661   // (ex. 2P = $3178, $0034, $FFCC, $0035)
662   // (ex. 2P = $2FC8, $0034, $FFCC, $0035)
662663
663  DSP4_READ_WORD();
664  DSP4_READ_WORD();
665  DSP4_READ_WORD();
666  DSP4_READ_WORD();
664   DSP4_READ_WORD();
665   DSP4_READ_WORD();
666   DSP4_READ_WORD();
667   DSP4_READ_WORD();
667668
668  // look at guidelines for both polygon shapes
669  DSP4_vars.distance = DSP4_READ_WORD();
670  view_x[0] = DSP4_READ_WORD();
671  view_y[0] = DSP4_READ_WORD();
672  view_x[1] = DSP4_READ_WORD();
673  view_y[1] = DSP4_READ_WORD();
669   // look at guidelines for both polygon shapes
670   dsp4_vars.distance = DSP4_READ_WORD();
671   view_x[0] = DSP4_READ_WORD();
672   view_y[0] = DSP4_READ_WORD();
673   view_x[1] = DSP4_READ_WORD();
674   view_y[1] = DSP4_READ_WORD();
674675
675  // envelope shaping guidelines (one frame only)
676  envelope[0][0] = DSP4_READ_WORD();
677  envelope[0][1] = DSP4_READ_WORD();
678  envelope[1][0] = DSP4_READ_WORD();
679  envelope[1][1] = DSP4_READ_WORD();
676   // envelope shaping guidelines (one frame only)
677   envelope[0][0] = DSP4_READ_WORD();
678   envelope[0][1] = DSP4_READ_WORD();
679   envelope[1][0] = DSP4_READ_WORD();
680   envelope[1][1] = DSP4_READ_WORD();
680681
681  // starting base values to project from
682  DSP4_vars.poly_start[0] = view_x[0];
683  DSP4_vars.poly_start[1] = view_x[1];
682   // starting base values to project from
683   dsp4_vars.poly_start[0] = view_x[0];
684   dsp4_vars.poly_start[1] = view_x[1];
684685
685  // starting DSP4_vars.raster lines to begin drawing
686  DSP4_vars.poly_raster[0][0] = view_y[0];
687  DSP4_vars.poly_raster[0][1] = view_y[0];
688  DSP4_vars.poly_raster[1][0] = view_y[1];
689  DSP4_vars.poly_raster[1][1] = view_y[1];
686   // starting dsp4_vars.raster lines to begin drawing
687   dsp4_vars.poly_raster[0][0] = view_y[0];
688   dsp4_vars.poly_raster[0][1] = view_y[0];
689   dsp4_vars.poly_raster[1][0] = view_y[1];
690   dsp4_vars.poly_raster[1][1] = view_y[1];
690691
691  // starting distances
692  DSP4_vars.poly_plane[0] = DSP4_vars.distance;
693  DSP4_vars.poly_plane[1] = DSP4_vars.distance;
692   // starting distances
693   dsp4_vars.poly_plane[0] = dsp4_vars.distance;
694   dsp4_vars.poly_plane[1] = dsp4_vars.distance;
694695
695  // SR = 0x00
696   // SR = 0x00
696697
697  // re-center coordinates
698  wleft = DSP4_vars.poly_cx[0][0] - view_x[0] + envelope[0][0];
699  wright = DSP4_vars.poly_cx[0][1] - view_x[0] + envelope[0][1];
698   // re-center coordinates
699   wleft = dsp4_vars.poly_cx[0][0] - view_x[0] + envelope[0][0];
700   wright = dsp4_vars.poly_cx[0][1] - view_x[0] + envelope[0][1];
700701
701  // saturate offscreen data for polygon #1
702  if (wleft < DSP4_vars.poly_clipLf[0][0])
703  {
704    wleft = DSP4_vars.poly_clipLf[0][0];
705  }
706  if (wleft > DSP4_vars.poly_clipRt[0][0])
707  {
708    wleft = DSP4_vars.poly_clipRt[0][0];
709  }
710  if (wright < DSP4_vars.poly_clipLf[0][1])
711  {
712    wright = DSP4_vars.poly_clipLf[0][1];
713  }
714  if (wright > DSP4_vars.poly_clipRt[0][1])
715  {
716    wright = DSP4_vars.poly_clipRt[0][1];
717  }
702   // saturate offscreen data for polygon #1
703   if (wleft < dsp4_vars.poly_clipLf[0][0])
704   {
705      wleft = dsp4_vars.poly_clipLf[0][0];
706   }
707   if (wleft > dsp4_vars.poly_clipRt[0][0])
708   {
709      wleft = dsp4_vars.poly_clipRt[0][0];
710   }
711   if (wright < dsp4_vars.poly_clipLf[0][1])
712   {
713      wright = dsp4_vars.poly_clipLf[0][1];
714   }
715   if (wright > dsp4_vars.poly_clipRt[0][1])
716   {
717      wright = dsp4_vars.poly_clipRt[0][1];
718   }
718719
719  // SR = 0x80
720   // SR = 0x80
720721
721  // initial output for polygon #1
722  DSP4_CLEAR_OUT();
723  DSP4_WRITE_BYTE(wleft & 0xff);
724  DSP4_WRITE_BYTE(wright & 0xff);
722   // initial output for polygon #1
723   DSP4_CLEAR_OUT();
724   DSP4_WRITE_BYTE(wleft & 0xff);
725   DSP4_WRITE_BYTE(wright & 0xff);
725726
726727
727  do
728  {
729    INT16 polygon;
730    ////////////////////////////////////////////////////
731    // command check
728   do
729   {
730      INT16 polygon;
731      ////////////////////////////////////////////////////
732      // command check
732733
733    // scan next command
734    DSP4.in_count = 2;
735    DSP4_WAIT(1) resume1 :
734      // scan next command
735      dsp4.in_count = 2;
736      DSP4_WAIT(1) resume1 :
736737
737    // terminate op
738    DSP4_vars.distance = DSP4_READ_WORD();
739    if (DSP4_vars.distance == -0x8000)
740      break;
738      // terminate op
739      dsp4_vars.distance = DSP4_READ_WORD();
740      if (dsp4_vars.distance == -0x8000)
741         break;
741742
742    // already have 2 bytes in queue
743    DSP4.in_count = 16;
743      // already have 2 bytes in queue
744      dsp4.in_count = 16;
744745
745    DSP4_WAIT(2) resume2 :
746      DSP4_WAIT(2) resume2 :
746747
747    // look at guidelines for both polygon shapes
748    view_x[0] = DSP4_READ_WORD();
749    view_y[0] = DSP4_READ_WORD();
750    view_x[1] = DSP4_READ_WORD();
751    view_y[1] = DSP4_READ_WORD();
748      // look at guidelines for both polygon shapes
749      view_x[0] = DSP4_READ_WORD();
750      view_y[0] = DSP4_READ_WORD();
751      view_x[1] = DSP4_READ_WORD();
752      view_y[1] = DSP4_READ_WORD();
752753
753    // envelope shaping guidelines (one frame only)
754    envelope[0][0] = DSP4_READ_WORD();
755    envelope[0][1] = DSP4_READ_WORD();
756    envelope[1][0] = DSP4_READ_WORD();
757    envelope[1][1] = DSP4_READ_WORD();
754      // envelope shaping guidelines (one frame only)
755      envelope[0][0] = DSP4_READ_WORD();
756      envelope[0][1] = DSP4_READ_WORD();
757      envelope[1][0] = DSP4_READ_WORD();
758      envelope[1][1] = DSP4_READ_WORD();
758759
759    ////////////////////////////////////////////////////
760    // projection begins
760      ////////////////////////////////////////////////////
761      // projection begins
761762
762    // init
763    DSP4_CLEAR_OUT();
763      // init
764      DSP4_CLEAR_OUT();
764765
765766
766    //////////////////////////////////////////////
767    // solid polygon renderer - 2 shapes
767      //////////////////////////////////////////////
768      // solid polygon renderer - 2 shapes
768769
769    for (polygon = 0; polygon < 2; polygon++)
770    {
771      INT32 left_inc, right_inc;
772      INT16 x1_final, x2_final;
773      INT16 env[2][2];
774      INT16 poly;
770      for (polygon = 0; polygon < 2; polygon++)
771      {
772         INT32 left_inc, right_inc;
773         INT16 x1_final, x2_final;
774         INT16 env[2][2];
775         INT16 poly;
775776
776      // SR = 0x00
777         // SR = 0x00
777778
778      // # DSP4_vars.raster lines to draw
779      DSP4_vars.segments = DSP4_vars.poly_raster[polygon][0] - view_y[polygon];
779         // # dsp4_vars.raster lines to draw
780         dsp4_vars.segments = dsp4_vars.poly_raster[polygon][0] - view_y[polygon];
780781
781      // prevent overdraw
782      if (DSP4_vars.segments > 0)
783      {
784        // bump drawing cursor
785        DSP4_vars.poly_raster[polygon][0] = view_y[polygon];
786        DSP4_vars.poly_raster[polygon][1] = view_y[polygon];
787      }
788      else
789        DSP4_vars.segments = 0;
782         // prevent overdraw
783         if (dsp4_vars.segments > 0)
784         {
785            // bump drawing cursor
786            dsp4_vars.poly_raster[polygon][0] = view_y[polygon];
787            dsp4_vars.poly_raster[polygon][1] = view_y[polygon];
788         }
789         else
790            dsp4_vars.segments = 0;
790791
791      // don't draw outside the window
792      if (view_y[polygon] < DSP4_vars.poly_top[polygon][0])
793      {
794        DSP4_vars.segments = 0;
792         // don't draw outside the window
793         if (view_y[polygon] < dsp4_vars.poly_top[polygon][0])
794         {
795            dsp4_vars.segments = 0;
795796
796        // flush remaining DSP4_vars.raster lines
797        if (view_y[polygon] >= DSP4_vars.poly_top[polygon][0])
798          DSP4_vars.segments = view_y[polygon] - DSP4_vars.poly_top[polygon][0];
799      }
797            // flush remaining dsp4_vars.raster lines
798            if (view_y[polygon] >= dsp4_vars.poly_top[polygon][0])
799               dsp4_vars.segments = view_y[polygon] - dsp4_vars.poly_top[polygon][0];
800         }
800801
801      // SR = 0x80
802         // SR = 0x80
802803
803      // tell user how many DSP4_vars.raster structures to read in
804      DSP4_WRITE_WORD(DSP4_vars.segments);
804         // tell user how many dsp4_vars.raster structures to read in
805         DSP4_WRITE_WORD(dsp4_vars.segments);
805806
806      // normal parameters
807      poly = polygon;
807         // normal parameters
808         poly = polygon;
808809
809      /////////////////////////////////////////////////////
810         /////////////////////////////////////////////////////
810811
811      // scan next command if no SR check needed
812      if (DSP4_vars.segments)
813      {
814        INT32 win_left, win_right;
812         // scan next command if no SR check needed
813         if (dsp4_vars.segments)
814         {
815            INT32 win_left, win_right;
815816
816        // road turnoff selection
817        if( (UINT16) envelope[ polygon ][ 0 ] == (UINT16) 0xc001 )
818          poly = 1;
819        else if( envelope[ polygon ][ 1 ] == 0x3fff )
820          poly = 1;
817            // road turnoff selection
818            if( (UINT16) envelope[ polygon ][ 0 ] == (UINT16) 0xc001 )
819               poly = 1;
820            else if( envelope[ polygon ][ 1 ] == 0x3fff )
821               poly = 1;
821822
822        ///////////////////////////////////////////////
823        // left side of polygon
823            ///////////////////////////////////////////////
824            // left side of polygon
824825
825        // perspective correction on additional shaping parameters
826        env[0][0] = envelope[polygon][0] * DSP4_vars.poly_plane[poly] >> 15;
827        env[0][1] = envelope[polygon][0] * DSP4_vars.distance >> 15;
826            // perspective correction on additional shaping parameters
827            env[0][0] = envelope[polygon][0] * dsp4_vars.poly_plane[poly] >> 15;
828            env[0][1] = envelope[polygon][0] * dsp4_vars.distance >> 15;
828829
829        // project new shapes (left side)
830        x1_final = view_x[poly] + env[0][0];
831        x2_final = DSP4_vars.poly_start[poly] + env[0][1];
830            // project new shapes (left side)
831            x1_final = view_x[poly] + env[0][0];
832            x2_final = dsp4_vars.poly_start[poly] + env[0][1];
832833
833        // interpolate between projected points with shaping
834        left_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4_vars.segments) << 1;
835        if (DSP4_vars.segments == 1)
836          left_inc = -left_inc;
834            // interpolate between projected points with shaping
835            left_inc = (x2_final - x1_final) * dsp4_Inverse(dsp4_vars.segments) << 1;
836            if (dsp4_vars.segments == 1)
837               left_inc = -left_inc;
837838
838        ///////////////////////////////////////////////
839        // right side of polygon
839            ///////////////////////////////////////////////
840            // right side of polygon
840841
841        // perspective correction on additional shaping parameters
842        env[1][0] = envelope[polygon][1] * DSP4_vars.poly_plane[poly] >> 15;;
843        env[1][1] = envelope[polygon][1] * DSP4_vars.distance >> 15;
842            // perspective correction on additional shaping parameters
843            env[1][0] = envelope[polygon][1] * dsp4_vars.poly_plane[poly] >> 15;;
844            env[1][1] = envelope[polygon][1] * dsp4_vars.distance >> 15;
844845
845        // project new shapes (right side)
846        x1_final = view_x[poly] + env[1][0];
847        x2_final = DSP4_vars.poly_start[poly] + env[1][1];
846            // project new shapes (right side)
847            x1_final = view_x[poly] + env[1][0];
848            x2_final = dsp4_vars.poly_start[poly] + env[1][1];
848849
849850
850        // interpolate between projected points with shaping
851        right_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4_vars.segments) << 1;
852        if (DSP4_vars.segments == 1)
853          right_inc = -right_inc;
851            // interpolate between projected points with shaping
852            right_inc = (x2_final - x1_final) * dsp4_Inverse(dsp4_vars.segments) << 1;
853            if (dsp4_vars.segments == 1)
854               right_inc = -right_inc;
854855
855        ///////////////////////////////////////////////
856        // update each point on the line
856            ///////////////////////////////////////////////
857            // update each point on the line
857858
858        win_left = SEX16(DSP4_vars.poly_cx[polygon][0] - DSP4_vars.poly_start[poly] + env[0][0]);
859        win_right = SEX16(DSP4_vars.poly_cx[polygon][1] - DSP4_vars.poly_start[poly] + env[1][0]);
859            win_left = SEX16(dsp4_vars.poly_cx[polygon][0] - dsp4_vars.poly_start[poly] + env[0][0]);
860            win_right = SEX16(dsp4_vars.poly_cx[polygon][1] - dsp4_vars.poly_start[poly] + env[1][0]);
860861
861        // update DSP4_vars.distance drawn into world
862        DSP4_vars.poly_plane[polygon] = DSP4_vars.distance;
862            // update dsp4_vars.distance drawn into world
863            dsp4_vars.poly_plane[polygon] = dsp4_vars.distance;
863864
864        // rasterize line
865        for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++)
866        {
867          INT16 x_left, x_right;
865            // rasterize line
866            for (dsp4_vars.lcv = 0; dsp4_vars.lcv < dsp4_vars.segments; dsp4_vars.lcv++)
867            {
868               INT16 x_left, x_right;
868869
869          // project new coordinates
870          win_left += left_inc;
871          win_right += right_inc;
870               // project new coordinates
871               win_left += left_inc;
872               win_right += right_inc;
872873
873          // grab integer portion, drop fraction (no rounding)
874          x_left = (INT16)(win_left >> 16);
875          x_right = (INT16)(win_right >> 16);
874               // grab integer portion, drop fraction (no rounding)
875               x_left = (INT16)(win_left >> 16);
876               x_right = (INT16)(win_right >> 16);
876877
877          // saturate offscreen data
878          if (x_left < DSP4_vars.poly_clipLf[polygon][0])
879            x_left = DSP4_vars.poly_clipLf[polygon][0];
880          if (x_left > DSP4_vars.poly_clipRt[polygon][0])
881            x_left = DSP4_vars.poly_clipRt[polygon][0];
882          if (x_right < DSP4_vars.poly_clipLf[polygon][1])
883            x_right = DSP4_vars.poly_clipLf[polygon][1];
884          if (x_right > DSP4_vars.poly_clipRt[polygon][1])
885            x_right = DSP4_vars.poly_clipRt[polygon][1];
878               // saturate offscreen data
879               if (x_left < dsp4_vars.poly_clipLf[polygon][0])
880                  x_left = dsp4_vars.poly_clipLf[polygon][0];
881               if (x_left > dsp4_vars.poly_clipRt[polygon][0])
882                  x_left = dsp4_vars.poly_clipRt[polygon][0];
883               if (x_right < dsp4_vars.poly_clipLf[polygon][1])
884                  x_right = dsp4_vars.poly_clipLf[polygon][1];
885               if (x_right > dsp4_vars.poly_clipRt[polygon][1])
886                  x_right = dsp4_vars.poly_clipRt[polygon][1];
886887
887          // 1. HDMA memory pointer
888          // 2. Left window position ($2126/$2128)
889          // 3. Right window position ($2127/$2129)
888               // 1. HDMA memory pointer
889               // 2. Left window position ($2126/$2128)
890               // 3. Right window position ($2127/$2129)
890891
891          DSP4_WRITE_WORD(DSP4_vars.poly_ptr[polygon][0]);
892          DSP4_WRITE_BYTE(x_left & 0xff);
893          DSP4_WRITE_BYTE(x_right & 0xff);
892               DSP4_WRITE_WORD(dsp4_vars.poly_ptr[polygon][0]);
893               DSP4_WRITE_BYTE(x_left & 0xff);
894               DSP4_WRITE_BYTE(x_right & 0xff);
894895
895896
896          // update memory pointers
897          DSP4_vars.poly_ptr[polygon][0] -= 4;
898          DSP4_vars.poly_ptr[polygon][1] -= 4;
899        } // end rasterize line
900      }
897               // update memory pointers
898               dsp4_vars.poly_ptr[polygon][0] -= 4;
899               dsp4_vars.poly_ptr[polygon][1] -= 4;
900            } // end rasterize line
901         }
901902
902      ////////////////////////////////////////////////
903      // Post-update
903         ////////////////////////////////////////////////
904         // Post-update
904905
905      // new projection spot to continue rasterizing from
906      DSP4_vars.poly_start[polygon] = view_x[poly];
907    } // end polygon rasterizer
908  }
909  while (1);
906         // new projection spot to continue rasterizing from
907         dsp4_vars.poly_start[polygon] = view_x[poly];
908      } // end polygon rasterizer
909   }
910   while (1);
910911
911  // unknown output
912  DSP4_CLEAR_OUT();
913  DSP4_WRITE_WORD(0);
912   // unknown output
913   DSP4_CLEAR_OUT();
914   DSP4_WRITE_WORD(0);
914915
915916
916  DSP4.waiting4command = 1;
917   dsp4.waiting4command = 1;
917918}
918919
919920//////////////////////////////////////////////////////////////
920921
921static void DSP4_OP09( void )
922static void dsp4_OP09( void )
922923{
923  DSP4.waiting4command = 0;
924   dsp4.waiting4command = 0;
924925
925  // op flow control
926  switch (DSP4_vars.DSP4_Logic)
927  {
928    case 1:
929      goto resume1; break;
930    case 2:
931      goto resume2; break;
932    case 3:
933      goto resume3; break;
934    case 4:
935      goto resume4; break;
936    case 5:
937      goto resume5; break;
938    case 6:
939      goto resume6; break;
940  }
926   // op flow control
927   switch (dsp4_vars.Logic)
928   {
929      case 1:
930         goto resume1; break;
931      case 2:
932         goto resume2; break;
933      case 3:
934         goto resume3; break;
935      case 4:
936         goto resume4; break;
937      case 5:
938         goto resume5; break;
939      case 6:
940         goto resume6; break;
941   }
941942
942  ////////////////////////////////////////////////////
943  // process initial inputs
943   ////////////////////////////////////////////////////
944   // process initial inputs
944945
945  // grab screen information
946  DSP4_vars.viewport_cx = DSP4_READ_WORD();
947  DSP4_vars.viewport_cy = DSP4_READ_WORD();
948  DSP4_READ_WORD(); // 0x0000
949  DSP4_vars.viewport_left = DSP4_READ_WORD();
950  DSP4_vars.viewport_right = DSP4_READ_WORD();
951  DSP4_vars.viewport_top = DSP4_READ_WORD();
952  DSP4_vars.viewport_bottom = DSP4_READ_WORD();
946   // grab screen information
947   dsp4_vars.viewport_cx = DSP4_READ_WORD();
948   dsp4_vars.viewport_cy = DSP4_READ_WORD();
949   DSP4_READ_WORD(); // 0x0000
950   dsp4_vars.viewport_left = DSP4_READ_WORD();
951   dsp4_vars.viewport_right = DSP4_READ_WORD();
952   dsp4_vars.viewport_top = DSP4_READ_WORD();
953   dsp4_vars.viewport_bottom = DSP4_READ_WORD();
953954
954  // starting DSP4_vars.raster line below the horizon
955  DSP4_vars.poly_bottom[0][0] = DSP4_vars.viewport_bottom - DSP4_vars.viewport_cy;
956  DSP4_vars.poly_raster[0][0] = 0x100;
955   // starting dsp4_vars.raster line below the horizon
956   dsp4_vars.poly_bottom[0][0] = dsp4_vars.viewport_bottom - dsp4_vars.viewport_cy;
957   dsp4_vars.poly_raster[0][0] = 0x100;
957958
958  do
959  {
960    ////////////////////////////////////////////////////
961    // check for new sprites
959   do
960   {
961      ////////////////////////////////////////////////////
962      // check for new sprites
962963
963    DSP4.in_count = 4;
964    DSP4_WAIT(1) resume1 :
964      dsp4.in_count = 4;
965      DSP4_WAIT(1) resume1 :
965966
966    ////////////////////////////////////////////////
967    // DSP4_vars.raster overdraw check
967      ////////////////////////////////////////////////
968      // dsp4_vars.raster overdraw check
968969
969    DSP4_vars.raster = DSP4_READ_WORD();
970      dsp4_vars.raster = DSP4_READ_WORD();
970971
971    // continue updating the DSP4_vars.raster line where overdraw begins
972    if (DSP4_vars.raster < DSP4_vars.poly_raster[0][0])
973    {
974      DSP4_vars.sprite_clipy = DSP4_vars.viewport_bottom - (DSP4_vars.poly_bottom[0][0] - DSP4_vars.raster);
975      DSP4_vars.poly_raster[0][0] = DSP4_vars.raster;
976    }
972      // continue updating the dsp4_vars.raster line where overdraw begins
973      if (dsp4_vars.raster < dsp4_vars.poly_raster[0][0])
974      {
975         dsp4_vars.sprite_clipy = dsp4_vars.viewport_bottom - (dsp4_vars.poly_bottom[0][0] - dsp4_vars.raster);
976         dsp4_vars.poly_raster[0][0] = dsp4_vars.raster;
977      }
977978
978    /////////////////////////////////////////////////
979    // identify sprite
979      /////////////////////////////////////////////////
980      // identify sprite
980981
981    // op termination
982    DSP4_vars.distance = DSP4_READ_WORD();
983    if (DSP4_vars.distance == -0x8000)
984      goto terminate;
982      // op termination
983      dsp4_vars.distance = DSP4_READ_WORD();
984      if (dsp4_vars.distance == -0x8000)
985         goto terminate;
985986
986987
987    // no sprite
988    if (DSP4_vars.distance == 0x0000)
989    {
990      continue;
991    }
988      // no sprite
989      if (dsp4_vars.distance == 0x0000)
990      {
991         continue;
992      }
992993
993    ////////////////////////////////////////////////////
994    // process projection information
994      ////////////////////////////////////////////////////
995      // process projection information
995996
996    // vehicle sprite
997    if ((UINT16) DSP4_vars.distance == 0x9000)
998    {
999      INT16 car_left, car_right, car_back;
1000      INT16 impact_left, impact_back;
1001      INT16 world_spx, world_spy;
1002      INT16 view_spx, view_spy;
1003      UINT16 energy;
997      // vehicle sprite
998      if ((UINT16) dsp4_vars.distance == 0x9000)
999      {
1000         INT16 car_left, car_right, car_back;
1001         INT16 impact_left, impact_back;
1002         INT16 world_spx, world_spy;
1003         INT16 view_spx, view_spy;
1004         UINT16 energy;
10041005
1005      // we already have 4 bytes we want
1006      DSP4.in_count = 14;
1007      DSP4_WAIT(2) resume2 :
1006         // we already have 4 bytes we want
1007         dsp4.in_count = 14;
1008         DSP4_WAIT(2) resume2 :
10081009
1009      // filter inputs
1010      energy = DSP4_READ_WORD();
1011      impact_back = DSP4_READ_WORD();
1012      car_back = DSP4_READ_WORD();
1013      impact_left = DSP4_READ_WORD();
1014      car_left = DSP4_READ_WORD();
1015      DSP4_vars.distance = DSP4_READ_WORD();
1016      car_right = DSP4_READ_WORD();
1010         // filter inputs
1011         energy = DSP4_READ_WORD();
1012         impact_back = DSP4_READ_WORD();
1013         car_back = DSP4_READ_WORD();
1014         impact_left = DSP4_READ_WORD();
1015         car_left = DSP4_READ_WORD();
1016         dsp4_vars.distance = DSP4_READ_WORD();
1017         car_right = DSP4_READ_WORD();
10171018
1018      // calculate car's world (x,y) values
1019      world_spx = car_right - car_left;
1020      world_spy = car_back;
1019         // calculate car's world (x,y) values
1020         world_spx = car_right - car_left;
1021         world_spy = car_back;
10211022
1022      // add in collision vector [needs bit-twiddling]
1023      world_spx -= energy * (impact_left - car_left) >> 16;
1024      world_spy -= energy * (car_back - impact_back) >> 16;
1023         // add in collision vector [needs bit-twiddling]
1024         world_spx -= energy * (impact_left - car_left) >> 16;
1025         world_spy -= energy * (car_back - impact_back) >> 16;
10251026
1026      // perspective correction for world (x,y)
1027      view_spx = world_spx * DSP4_vars.distance >> 15;
1028      view_spy = world_spy * DSP4_vars.distance >> 15;
1027         // perspective correction for world (x,y)
1028         view_spx = world_spx * dsp4_vars.distance >> 15;
1029         view_spy = world_spy * dsp4_vars.distance >> 15;
10291030
1030      // convert to screen values
1031      DSP4_vars.sprite_x = DSP4_vars.viewport_cx + view_spx;
1032      DSP4_vars.sprite_y = DSP4_vars.viewport_bottom - (DSP4_vars.poly_bottom[0][0] - view_spy);
1031         // convert to screen values
1032         dsp4_vars.sprite_x = dsp4_vars.viewport_cx + view_spx;
1033         dsp4_vars.sprite_y = dsp4_vars.viewport_bottom - (dsp4_vars.poly_bottom[0][0] - view_spy);
10331034
1034      // make the car's (x)-coordinate available
1035      DSP4_CLEAR_OUT();
1036      DSP4_WRITE_WORD(world_spx);
1035         // make the car's (x)-coordinate available
1036         DSP4_CLEAR_OUT();
1037         DSP4_WRITE_WORD(world_spx);
10371038
1038      // grab a few remaining vehicle values
1039      DSP4.in_count = 4;
1040      DSP4_WAIT(3) resume3 :
1039         // grab a few remaining vehicle values
1040         dsp4.in_count = 4;
1041         DSP4_WAIT(3) resume3 :
10411042
1042      // add vertical lift factor
1043      DSP4_vars.sprite_y += DSP4_READ_WORD();
1044    }
1045    // terrain sprite
1046    else
1047    {
1048      INT16 world_spx, world_spy;
1049      INT16 view_spx, view_spy;
1043         // add vertical lift factor
1044         dsp4_vars.sprite_y += DSP4_READ_WORD();
1045      }
1046      // terrain sprite
1047      else
1048      {
1049         INT16 world_spx, world_spy;
1050         INT16 view_spx, view_spy;
10501051
1051      // we already have 4 bytes we want
1052      DSP4.in_count = 10;
1053      DSP4_WAIT(4) resume4 :
1052         // we already have 4 bytes we want
1053         dsp4.in_count = 10;
1054         DSP4_WAIT(4) resume4 :
10541055
1055      // sort loop inputs
1056      DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD();
1057      DSP4_vars.poly_raster[0][1] = DSP4_READ_WORD();
1058      world_spx = DSP4_READ_WORD();
1059      world_spy = DSP4_READ_WORD();
1056         // sort loop inputs
1057         dsp4_vars.poly_cx[0][0] = DSP4_READ_WORD();
1058         dsp4_vars.poly_raster[0][1] = DSP4_READ_WORD();
1059         world_spx = DSP4_READ_WORD();
1060         world_spy = DSP4_READ_WORD();
10601061
1061      // compute base DSP4_vars.raster line from the bottom
1062      DSP4_vars.segments = DSP4_vars.poly_bottom[0][0] - DSP4_vars.raster;
1062         // compute base dsp4_vars.raster line from the bottom
1063         dsp4_vars.segments = dsp4_vars.poly_bottom[0][0] - dsp4_vars.raster;
10631064
1064      // perspective correction for world (x,y)
1065      view_spx = world_spx * DSP4_vars.distance >> 15;
1066      view_spy = world_spy * DSP4_vars.distance >> 15;
1065         // perspective correction for world (x,y)
1066         view_spx = world_spx * dsp4_vars.distance >> 15;
1067         view_spy = world_spy * dsp4_vars.distance >> 15;
10671068
1068      // convert to screen values
1069      DSP4_vars.sprite_x = DSP4_vars.viewport_cx + view_spx - DSP4_vars.poly_cx[0][0];
1070      DSP4_vars.sprite_y = DSP4_vars.viewport_bottom - DSP4_vars.segments + view_spy;
1071    }
1069         // convert to screen values
1070         dsp4_vars.sprite_x = dsp4_vars.viewport_cx + view_spx - dsp4_vars.poly_cx[0][0];
1071         dsp4_vars.sprite_y = dsp4_vars.viewport_bottom - dsp4_vars.segments + view_spy;
1072      }
10721073
1073    // default sprite size: 16x16
1074    DSP4_vars.sprite_size = 1;
1075    DSP4_vars.sprite_attr = DSP4_READ_WORD();
1074      // default sprite size: 16x16
1075      dsp4_vars.sprite_size = 1;
1076      dsp4_vars.sprite_attr = DSP4_READ_WORD();
10761077
1077    ////////////////////////////////////////////////////
1078    // convert tile data to SNES OAM format
1078      ////////////////////////////////////////////////////
1079      // convert tile data to SNES OAM format
10791080
1080    do
1081    {
1082      UINT16 header;
1081      do
1082      {
1083         UINT16 header;
10831084
1084      INT16 sp_x, sp_y, sp_attr, sp_dattr;
1085      INT16 sp_dx, sp_dy;
1086      INT16 pixels;
1085         INT16 sp_x, sp_y, sp_attr, sp_dattr;
1086         INT16 sp_dx, sp_dy;
1087         INT16 pixels;
10871088
1088      UINT8 draw;
1089         UINT8 draw;
10891090
1090      DSP4.in_count = 2;
1091      DSP4_WAIT(5) resume5 :
1091         dsp4.in_count = 2;
1092         DSP4_WAIT(5) resume5 :
10921093
1093      draw = 1;
1094         draw = 1;
10941095
1095      // opcode termination
1096      DSP4_vars.raster = DSP4_READ_WORD();
1097      if (DSP4_vars.raster == -0x8000)
1098        goto terminate;
1096         // opcode termination
1097         dsp4_vars.raster = DSP4_READ_WORD();
1098         if (dsp4_vars.raster == -0x8000)
1099            goto terminate;
10991100
1100      // stop code
1101      if (DSP4_vars.raster == 0x0000 && !DSP4_vars.sprite_size)
1102        break;
1101         // stop code
1102         if (dsp4_vars.raster == 0x0000 && !dsp4_vars.sprite_size)
1103            break;
11031104
1104      // toggle sprite size
1105      if (DSP4_vars.raster == 0x0000)
1106      {
1107        DSP4_vars.sprite_size = !DSP4_vars.sprite_size;
1108        continue;
1109      }
1105         // toggle sprite size
1106         if (dsp4_vars.raster == 0x0000)
1107         {
1108            dsp4_vars.sprite_size = !dsp4_vars.sprite_size;
1109            continue;
1110         }
11101111
1111      // check for valid sprite header
1112      header = DSP4_vars.raster;
1113      header >>= 8;
1114      if (header != 0x20 &&
1115          header != 0x2e && //This is for attractor sprite
1116          header != 0x40 &&
1117          header != 0x60 &&
1118          header != 0xa0 &&
1119          header != 0xc0 &&
1120          header != 0xe0)
1121        break;
1112         // check for valid sprite header
1113         header = dsp4_vars.raster;
1114         header >>= 8;
1115         if (header != 0x20 &&
1116               header != 0x2e && //This is for attractor sprite
1117               header != 0x40 &&
1118               header != 0x60 &&
1119               header != 0xa0 &&
1120               header != 0xc0 &&
1121               header != 0xe0)
1122            break;
11221123
1123      // read in rest of sprite data
1124      DSP4.in_count = 4;
1125      DSP4_WAIT(6) resume6 :
1124         // read in rest of sprite data
1125         dsp4.in_count = 4;
1126         DSP4_WAIT(6) resume6 :
11261127
1127      draw = 1;
1128         draw = 1;
11281129
1129      /////////////////////////////////////
1130      // process tile data
1130         /////////////////////////////////////
1131         // process tile data
11311132
1132      // sprite deltas
1133      sp_dattr = DSP4_vars.raster;
1134      sp_dy = DSP4_READ_WORD();
1135      sp_dx = DSP4_READ_WORD();
1133         // sprite deltas
1134         sp_dattr = dsp4_vars.raster;
1135         sp_dy = DSP4_READ_WORD();
1136         sp_dx = DSP4_READ_WORD();
11361137
1137      // update coordinates to screen space
1138      sp_x = DSP4_vars.sprite_x + sp_dx;
1139      sp_y = DSP4_vars.sprite_y + sp_dy;
1138         // update coordinates to screen space
1139         sp_x = dsp4_vars.sprite_x + sp_dx;
1140         sp_y = dsp4_vars.sprite_y + sp_dy;
11401141
1141      // update sprite nametable/attribute information
1142      sp_attr = DSP4_vars.sprite_attr + sp_dattr;
1142         // update sprite nametable/attribute information
1143         sp_attr = dsp4_vars.sprite_attr + sp_dattr;
11431144
1144      // allow partially visibile tiles
1145      pixels = DSP4_vars.sprite_size ? 15 : 7;
1145         // allow partially visibile tiles
1146         pixels = dsp4_vars.sprite_size ? 15 : 7;
11461147
1147      DSP4_CLEAR_OUT();
1148         DSP4_CLEAR_OUT();
11481149
1149      // transparent tile to clip off parts of a sprite (overdraw)
1150      if (DSP4_vars.sprite_clipy - pixels <= sp_y &&
1151          sp_y <= DSP4_vars.sprite_clipy &&
1152          sp_x >= DSP4_vars.viewport_left - pixels &&
1153          sp_x <= DSP4_vars.viewport_right &&
1154          DSP4_vars.sprite_clipy >= DSP4_vars.viewport_top - pixels &&
1155          DSP4_vars.sprite_clipy <= DSP4_vars.viewport_bottom)
1156      {
1157        DSP4_OP0B(&draw, sp_x, DSP4_vars.sprite_clipy, 0x00EE, DSP4_vars.sprite_size, 0);
1158      }
1150         // transparent tile to clip off parts of a sprite (overdraw)
1151         if (dsp4_vars.sprite_clipy - pixels <= sp_y &&
1152               sp_y <= dsp4_vars.sprite_clipy &&
1153               sp_x >= dsp4_vars.viewport_left - pixels &&
1154               sp_x <= dsp4_vars.viewport_right &&
1155               dsp4_vars.sprite_clipy >= dsp4_vars.viewport_top - pixels &&
1156               dsp4_vars.sprite_clipy <= dsp4_vars.viewport_bottom)
1157         {
1158            dsp4_OP0B(&draw, sp_x, dsp4_vars.sprite_clipy, 0x00EE, dsp4_vars.sprite_size, 0);
1159         }
11591160
11601161
1161      // normal sprite tile
1162      if (sp_x >= DSP4_vars.viewport_left - pixels &&
1163          sp_x <= DSP4_vars.viewport_right &&
1164          sp_y >= DSP4_vars.viewport_top - pixels &&
1165          sp_y <= DSP4_vars.viewport_bottom &&
1166          sp_y <= DSP4_vars.sprite_clipy)
1167      {
1168        DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, DSP4_vars.sprite_size, 0);
1169      }
1162         // normal sprite tile
1163         if (sp_x >= dsp4_vars.viewport_left - pixels &&
1164               sp_x <= dsp4_vars.viewport_right &&
1165               sp_y >= dsp4_vars.viewport_top - pixels &&
1166               sp_y <= dsp4_vars.viewport_bottom &&
1167               sp_y <= dsp4_vars.sprite_clipy)
1168         {
1169            dsp4_OP0B(&draw, sp_x, sp_y, sp_attr, dsp4_vars.sprite_size, 0);
1170         }
11701171
11711172
1172      // no following OAM data
1173      DSP4_OP0B(&draw, 0, 0x0100, 0, 0, 1);
1174    }
1175    while (1);
1176  }
1177  while (1);
1173         // no following OAM data
1174         dsp4_OP0B(&draw, 0, 0x0100, 0, 0, 1);
1175      }
1176      while (1);
1177   }
1178   while (1);
11781179
1179  terminate : DSP4.waiting4command = 1;
1180   terminate : dsp4.waiting4command = 1;
11801181}
11811182
11821183//////////////////////////////////////////////////////////////
r7621r7622
11841185static const UINT16 OP0A_Values[16] = { 0x0000, 0x0030, 0x0060, 0x0090, 0x00c0, 0x00f0, 0x0120, 0x0150, 0xfe80,
11851186                                 0xfeb0, 0xfee0, 0xff10, 0xff40, 0xff70, 0xffa0, 0xffd0 };
11861187
1187static void DSP4_OP0A(INT16 n2, INT16 *o1, INT16 *o2, INT16 *o3, INT16 *o4)
1188static void dsp4_OP0A(INT16 n2, INT16 *o1, INT16 *o2, INT16 *o3, INT16 *o4)
11881189{
1189  *o4 = OP0A_Values[(n2 & 0x000f)];
1190  *o3 = OP0A_Values[(n2 & 0x00f0) >> 4];
1191  *o2 = OP0A_Values[(n2 & 0x0f00) >> 8];
1192  *o1 = OP0A_Values[(n2 & 0xf000) >> 12];
1190   *o4 = OP0A_Values[(n2 & 0x000f)];
1191   *o3 = OP0A_Values[(n2 & 0x00f0) >> 4];
1192   *o2 = OP0A_Values[(n2 & 0x0f00) >> 8];
1193   *o1 = OP0A_Values[(n2 & 0xf000) >> 12];
11931194}
11941195
11951196//////////////////////////////////////////////////////////////
11961197
1197static void DSP4_OP0B(UINT8 *draw, INT16 sp_x, INT16 sp_y, INT16 sp_attr, UINT8 size, UINT8 stop)
1198static void dsp4_OP0B(UINT8 *draw, INT16 sp_x, INT16 sp_y, INT16 sp_attr, UINT8 size, UINT8 stop)
11981199{
1199  INT16 Row1, Row2;
1200   INT16 Row1, Row2;
12001201
1201  // SR = 0x00
1202   // SR = 0x00
12021203
1203  // align to nearest 8-pixel row
1204  Row1 = (sp_y >> 3) & 0x1f;
1205  Row2 = (Row1 + 1) & 0x1f;
1204   // align to nearest 8-pixel row
1205   Row1 = (sp_y >> 3) & 0x1f;
1206   Row2 = (Row1 + 1) & 0x1f;
12061207
1207  // check boundaries
1208  if (!((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb)))
1209  {
1210    *draw = 0;
1211  }
1212  if (size)
1213  {
1214    if (DSP4_vars.OAM_Row[Row1] + 1 >= DSP4_vars.OAM_RowMax)
1215      *draw = 0;
1216    if (DSP4_vars.OAM_Row[Row2] + 1 >= DSP4_vars.OAM_RowMax)
1217      *draw = 0;
1218  }
1219  else
1220  {
1221    if (DSP4_vars.OAM_Row[Row1] >= DSP4_vars.OAM_RowMax)
1222    {
1223      *draw = 0;
1224    }
1225  }
1208   // check boundaries
1209   if (!((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb)))
1210   {
1211      *draw = 0;
1212   }
1213   if (size)
1214   {
1215      if (dsp4_vars.OAM_Row[Row1] + 1 >= dsp4_vars.OAM_RowMax)
1216         *draw = 0;
1217      if (dsp4_vars.OAM_Row[Row2] + 1 >= dsp4_vars.OAM_RowMax)
1218         *draw = 0;
1219   }
1220   else
1221   {
1222      if (dsp4_vars.OAM_Row[Row1] >= dsp4_vars.OAM_RowMax)
1223      {
1224         *draw = 0;
1225      }
1226   }
12261227
1227  // emulator fail-safe (unknown if this really exists)
1228  if (DSP4_vars.sprite_count >= 128)
1229  {
1230    *draw = 0;
1231  }
1228   // emulator fail-safe (unknown if this really exists)
1229   if (dsp4_vars.sprite_count >= 128)
1230   {
1231      *draw = 0;
1232   }
12321233
1233  // SR = 0x80
1234   // SR = 0x80
12341235
1235  if (*draw)
1236  {
1237    // Row tiles
1238    if (size)
1239    {
1240      DSP4_vars.OAM_Row[Row1] += 2;
1241      DSP4_vars.OAM_Row[Row2] += 2;
1242    }
1243    else
1244    {
1245      DSP4_vars.OAM_Row[Row1]++;
1246    }
1236   if (*draw)
1237   {
1238      // Row tiles
1239      if (size)
1240      {
1241         dsp4_vars.OAM_Row[Row1] += 2;
1242         dsp4_vars.OAM_Row[Row2] += 2;
1243      }
1244      else
1245      {
1246         dsp4_vars.OAM_Row[Row1]++;
1247      }
12471248
1248    // yield OAM output
1249    DSP4_WRITE_WORD(1);
1249      // yield OAM output
1250      DSP4_WRITE_WORD(1);
12501251
1251    // pack OAM data: x,y,name,attr
1252    DSP4_WRITE_BYTE(sp_x & 0xff);
1253    DSP4_WRITE_BYTE(sp_y & 0xff);
1254    DSP4_WRITE_WORD(sp_attr);
1252      // pack OAM data: x,y,name,attr
1253      DSP4_WRITE_BYTE(sp_x & 0xff);
1254      DSP4_WRITE_BYTE(sp_y & 0xff);
1255      DSP4_WRITE_WORD(sp_attr);
12551256
1256    DSP4_vars.sprite_count++;
1257      dsp4_vars.sprite_count++;
12571258
1258    // OAM: size,msb data
1259    // save post-oam table data for future retrieval
1260    DSP4_vars.OAM_attr[DSP4_vars.OAM_index] |= ((sp_x <0 || sp_x> 255) << DSP4_vars.OAM_bits);
1261    DSP4_vars.OAM_bits++;
1259      // OAM: size,msb data
1260      // save post-oam table data for future retrieval
1261      dsp4_vars.OAM_attr[dsp4_vars.OAM_index] |= ((sp_x <0 || sp_x> 255) << dsp4_vars.OAM_bits);
1262      dsp4_vars.OAM_bits++;
12621263
1263    DSP4_vars.OAM_attr[DSP4_vars.OAM_index] |= (size << DSP4_vars.OAM_bits);
1264    DSP4_vars.OAM_bits++;
1264      dsp4_vars.OAM_attr[dsp4_vars.OAM_index] |= (size << dsp4_vars.OAM_bits);
1265      dsp4_vars.OAM_bits++;
12651266
1266    // move to next byte in buffer
1267    if (DSP4_vars.OAM_bits == 16)
1268    {
1269      DSP4_vars.OAM_bits = 0;
1270      DSP4_vars.OAM_index++;
1271    }
1272  }
1273  else if (stop)
1274  {
1275    // yield no OAM output
1276    DSP4_WRITE_WORD(0);
1277  }
1267      // move to next byte in buffer
1268      if (dsp4_vars.OAM_bits == 16)
1269      {
1270         dsp4_vars.OAM_bits = 0;
1271         dsp4_vars.OAM_index++;
1272      }
1273   }
1274   else if (stop)
1275   {
1276      // yield no OAM output
1277      DSP4_WRITE_WORD(0);
1278   }
12781279}
12791280
12801281//////////////////////////////////////////////////////////////
12811282
1282static void DSP4_OP0D( void )
1283static void dsp4_OP0D( void )
12831284{
1284  DSP4.waiting4command = 0;
1285   dsp4.waiting4command = 0;
12851286
1286  // op flow control
1287  switch (DSP4_vars.DSP4_Logic)
1288  {
1289    case 1:
1290      goto resume1; break;
1291    case 2:
1292      goto resume2; break;
1293  }
1287   // op flow control
1288   switch (dsp4_vars.Logic)
1289   {
1290      case 1:
1291         goto resume1; break;
1292      case 2:
1293         goto resume2; break;
1294   }
12941295
1295  ////////////////////////////////////////////////////
1296  // process initial inputs
1296   ////////////////////////////////////////////////////
1297   // process initial inputs
12971298
1298  // sort inputs
1299  DSP4_vars.world_y = DSP4_READ_DWORD();
1300  DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
1301  DSP4_vars.poly_top[0][0] = DSP4_READ_WORD();
1302  DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD();
1303  DSP4_vars.viewport_bottom = DSP4_READ_WORD();
1304  DSP4_vars.world_x = DSP4_READ_DWORD();
1305  DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD();
1306  DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
1307  DSP4_vars.world_yofs = DSP4_READ_WORD();
1308  DSP4_vars.world_dy = DSP4_READ_DWORD();
1309  DSP4_vars.world_dx = DSP4_READ_DWORD();
1310  DSP4_vars.distance = DSP4_READ_WORD();
1311  DSP4_READ_WORD(); // 0x0000
1312  DSP4_vars.world_xenv = SEX78(DSP4_READ_WORD());
1313  DSP4_vars.world_ddy = DSP4_READ_WORD();
1314  DSP4_vars.world_ddx = DSP4_READ_WORD();
1315  DSP4_vars.view_yofsenv = DSP4_READ_WORD();
1299   // sort inputs
1300   dsp4_vars.world_y = DSP4_READ_DWORD();
1301   dsp4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
1302   dsp4_vars.poly_top[0][0] = DSP4_READ_WORD();
1303   dsp4_vars.poly_cx[1][0] = DSP4_READ_WORD();
1304   dsp4_vars.viewport_bottom = DSP4_READ_WORD();
1305   dsp4_vars.world_x = DSP4_READ_DWORD();
1306   dsp4_vars.poly_cx[0][0] = DSP4_READ_WORD();
1307   dsp4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
1308   dsp4_vars.world_yofs = DSP4_READ_WORD();
1309   dsp4_vars.world_dy = DSP4_READ_DWORD();
1310   dsp4_vars.world_dx = DSP4_READ_DWORD();
1311   dsp4_vars.distance = DSP4_READ_WORD();
1312   DSP4_READ_WORD(); // 0x0000
1313   dsp4_vars.world_xenv = SEX78(DSP4_READ_WORD());
1314   dsp4_vars.world_ddy = DSP4_READ_WORD();
1315   dsp4_vars.world_ddx = DSP4_READ_WORD();
1316   dsp4_vars.view_yofsenv = DSP4_READ_WORD();
13161317
1317  // initial (x,y,offset) at starting DSP4_vars.raster line
1318  DSP4_vars.view_x1 = (INT16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16);
1319  DSP4_vars.view_y1 = (INT16)(DSP4_vars.world_y >> 16);
1320  DSP4_vars.view_xofs1 = (INT16)(DSP4_vars.world_x >> 16);
1321  DSP4_vars.view_yofs1 = DSP4_vars.world_yofs;
1318   // initial (x,y,offset) at starting dsp4_vars.raster line
1319   dsp4_vars.view_x1 = (INT16)((dsp4_vars.world_x + dsp4_vars.world_xenv) >> 16);
1320   dsp4_vars.view_y1 = (INT16)(dsp4_vars.world_y >> 16);
1321   dsp4_vars.view_xofs1 = (INT16)(dsp4_vars.world_x >> 16);
1322   dsp4_vars.view_yofs1 = dsp4_vars.world_yofs;
13221323
1323  // first DSP4_vars.raster line
1324  DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0];
1324   // first dsp4_vars.raster line
1325   dsp4_vars.poly_raster[0][0] = dsp4_vars.poly_bottom[0][0];
13251326
13261327
1327  do
1328  {
1329    ////////////////////////////////////////////////////
1330    // process one iteration of projection
1328   do
1329   {
1330      ////////////////////////////////////////////////////
1331      // process one iteration of projection
13311332
1332    // perspective projection of world (x,y,scroll) points
1333    // based on the current projection lines
1334    DSP4_vars.view_x2 = (INT16)(( ( ( DSP4_vars.world_x + DSP4_vars.world_xenv ) >> 16 ) * DSP4_vars.distance >> 15 ) + ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 ));
1335    DSP4_vars.view_y2 = (INT16)((DSP4_vars.world_y >> 16) * DSP4_vars.distance >> 15);
1336    DSP4_vars.view_xofs2 = DSP4_vars.view_x2;
1337    DSP4_vars.view_yofs2 = (DSP4_vars.world_yofs * DSP4_vars.distance >> 15) + DSP4_vars.poly_bottom[0][0] - DSP4_vars.view_y2;
1333      // perspective projection of world (x,y,scroll) points
1334      // based on the current projection lines
1335      dsp4_vars.view_x2 = (INT16)(( ( ( dsp4_vars.world_x + dsp4_vars.world_xenv ) >> 16 ) * dsp4_vars.distance >> 15 ) + ( dsp4_vars.view_turnoff_x * dsp4_vars.distance >> 15 ));
1336      dsp4_vars.view_y2 = (INT16)((dsp4_vars.world_y >> 16) * dsp4_vars.distance >> 15);
1337      dsp4_vars.view_xofs2 = dsp4_vars.view_x2;
1338      dsp4_vars.view_yofs2 = (dsp4_vars.world_yofs * dsp4_vars.distance >> 15) + dsp4_vars.poly_bottom[0][0] - dsp4_vars.view_y2;
13381339
1339    // 1. World x-location before transformation
1340    // 2. Viewer x-position at the current
1341    // 3. World y-location before perspective projection
1342    // 4. Viewer y-position below the horizon
1343    // 5. Number of DSP4_vars.raster lines drawn in this iteration
1340      // 1. World x-location before transformation
1341      // 2. Viewer x-position at the current
1342      // 3. World y-location before perspective projection
1343      // 4. Viewer y-position below the horizon
1344      // 5. Number of dsp4_vars.raster lines drawn in this iteration
13441345
1345    DSP4_CLEAR_OUT();
1346    DSP4_WRITE_WORD((UINT16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16));
1347    DSP4_WRITE_WORD(DSP4_vars.view_x2);
1348    DSP4_WRITE_WORD((UINT16)(DSP4_vars.world_y >> 16));
1349    DSP4_WRITE_WORD(DSP4_vars.view_y2);
1346      DSP4_CLEAR_OUT();
1347      DSP4_WRITE_WORD((UINT16)((dsp4_vars.world_x + dsp4_vars.world_xenv) >> 16));
1348      DSP4_WRITE_WORD(dsp4_vars.view_x2);
1349      DSP4_WRITE_WORD((UINT16)(dsp4_vars.world_y >> 16));
1350      DSP4_WRITE_WORD(dsp4_vars.view_y2);
13501351
1351    //////////////////////////////////////////////////////////
1352      //////////////////////////////////////////////////////////
13521353
1353    // SR = 0x00
1354      // SR = 0x00
13541355
1355    // determine # of DSP4_vars.raster lines used
1356    DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.view_y2;
1356      // determine # of dsp4_vars.raster lines used
1357      dsp4_vars.segments = dsp4_vars.view_y1 - dsp4_vars.view_y2;
13571358
1358    // prevent overdraw
1359    if (DSP4_vars.view_y2 >= DSP4_vars.poly_raster[0][0])
1360      DSP4_vars.segments = 0;
1361    else
1362      DSP4_vars.poly_raster[0][0] = DSP4_vars.view_y2;
1359      // prevent overdraw
1360      if (dsp4_vars.view_y2 >= dsp4_vars.poly_raster[0][0])
1361         dsp4_vars.segments = 0;
1362      else
1363         dsp4_vars.poly_raster[0][0] = dsp4_vars.view_y2;
13631364
1364    // don't draw outside the window
1365    if (DSP4_vars.view_y2 < DSP4_vars.poly_top[0][0])
1366    {
1367      DSP4_vars.segments = 0;
1365      // don't draw outside the window
1366      if (dsp4_vars.view_y2 < dsp4_vars.poly_top[0][0])
1367      {
1368         dsp4_vars.segments = 0;
13681369
1369      // flush remaining DSP4_vars.raster lines
1370      if (DSP4_vars.view_y1 >= DSP4_vars.poly_top[0][0])
1371        DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.poly_top[0][0];
1372    }
1370         // flush remaining dsp4_vars.raster lines
1371         if (dsp4_vars.view_y1 >= dsp4_vars.poly_top[0][0])
1372            dsp4_vars.segments = dsp4_vars.view_y1 - dsp4_vars.poly_top[0][0];
1373      }
13731374
1374    // SR = 0x80
1375      // SR = 0x80
13751376
1376    DSP4_WRITE_WORD(DSP4_vars.segments);
1377      DSP4_WRITE_WORD(dsp4_vars.segments);
13771378
1378    //////////////////////////////////////////////////////////
1379      //////////////////////////////////////////////////////////
13791380
1380    // scan next command if no SR check needed
1381    if (DSP4_vars.segments)
1382    {
1383      INT32 px_dx, py_dy;
1384      INT32 x_scroll, y_scroll;
1381      // scan next command if no SR check needed
1382      if (dsp4_vars.segments)
1383      {
1384         INT32 px_dx, py_dy;
1385         INT32 x_scroll, y_scroll;
13851386
1386      // SR = 0x00
1387         // SR = 0x00
13871388
1388      // linear interpolation (lerp) between projected points
1389      px_dx = (DSP4_vars.view_xofs2 - DSP4_vars.view_xofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;
1390      py_dy = (DSP4_vars.view_yofs2 - DSP4_vars.view_yofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;
1389         // linear interpolation (lerp) between projected points
1390         px_dx = (dsp4_vars.view_xofs2 - dsp4_vars.view_xofs1) * dsp4_Inverse(dsp4_vars.segments) << 1;
1391         py_dy = (dsp4_vars.view_yofs2 - dsp4_vars.view_yofs1) * dsp4_Inverse(dsp4_vars.segments) << 1;
13911392
1392      // starting step values
1393      x_scroll = SEX16(DSP4_vars.poly_cx[0][0] + DSP4_vars.view_xofs1);
1394      y_scroll = SEX16(-DSP4_vars.viewport_bottom + DSP4_vars.view_yofs1 + DSP4_vars.view_yofsenv + DSP4_vars.poly_cx[1][0] - DSP4_vars.world_yofs);
1393         // starting step values
1394         x_scroll = SEX16(dsp4_vars.poly_cx[0][0] + dsp4_vars.view_xofs1);
1395         y_scroll = SEX16(-dsp4_vars.viewport_bottom + dsp4_vars.view_yofs1 + dsp4_vars.view_yofsenv + dsp4_vars.poly_cx[1][0] - dsp4_vars.world_yofs);
13951396
1396      // SR = 0x80
1397         // SR = 0x80
13971398
1398      // rasterize line
1399      for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++)
1400      {
1401        // 1. HDMA memory pointer (bg1)
1402        // 2. vertical scroll offset ($210E)
1403        // 3. horizontal scroll offset ($210D)
1399         // rasterize line
1400         for (dsp4_vars.lcv = 0; dsp4_vars.lcv < dsp4_vars.segments; dsp4_vars.lcv++)
1401         {
1402            // 1. HDMA memory pointer (bg1)
1403            // 2. vertical scroll offset ($210E)
1404            // 3. horizontal scroll offset ($210D)
14041405
1405        DSP4_WRITE_WORD(DSP4_vars.poly_ptr[0][0]);
1406        DSP4_WRITE_WORD((UINT16)((y_scroll + 0x8000) >> 16));
1407        DSP4_WRITE_WORD((UINT16)((x_scroll + 0x8000) >> 16));
1406            DSP4_WRITE_WORD(dsp4_vars.poly_ptr[0][0]);
1407            DSP4_WRITE_WORD((UINT16)((y_scroll + 0x8000) >> 16));
1408            DSP4_WRITE_WORD((UINT16)((x_scroll + 0x8000) >> 16));
14081409
14091410
1410        // update memory address
1411        DSP4_vars.poly_ptr[0][0] -= 4;
1411            // update memory address
1412            dsp4_vars.poly_ptr[0][0] -= 4;
14121413
1413        // update screen values
1414        x_scroll += px_dx;
1415        y_scroll += py_dy;
1416      }
1417    }
1414            // update screen values
1415            x_scroll += px_dx;
1416            y_scroll += py_dy;
1417         }
1418      }
14181419
1419    /////////////////////////////////////////////////////
1420    // Post-update
1420      /////////////////////////////////////////////////////
1421      // Post-update
14211422
1422    // update new viewer (x,y,scroll) to last DSP4_vars.raster line drawn
1423    DSP4_vars.view_x1 = DSP4_vars.view_x2;
1424    DSP4_vars.view_y1 = DSP4_vars.view_y2;
1425    DSP4_vars.view_xofs1 = DSP4_vars.view_xofs2;
1426    DSP4_vars.view_yofs1 = DSP4_vars.view_yofs2;
1423      // update new viewer (x,y,scroll) to last dsp4_vars.raster line drawn
1424      dsp4_vars.view_x1 = dsp4_vars.view_x2;
1425      dsp4_vars.view_y1 = dsp4_vars.view_y2;
1426      dsp4_vars.view_xofs1 = dsp4_vars.view_xofs2;
1427      dsp4_vars.view_yofs1 = dsp4_vars.view_yofs2;
14271428
1428    // add deltas for projection lines
1429    DSP4_vars.world_dx += SEX78(DSP4_vars.world_ddx);
1430    DSP4_vars.world_dy += SEX78(DSP4_vars.world_ddy);
1429      // add deltas for projection lines
1430      dsp4_vars.world_dx += SEX78(dsp4_vars.world_ddx);
1431      dsp4_vars.world_dy += SEX78(dsp4_vars.world_ddy);
14311432
1432    // update projection lines
1433    DSP4_vars.world_x += (DSP4_vars.world_dx + DSP4_vars.world_xenv);
1434    DSP4_vars.world_y += DSP4_vars.world_dy;
1433      // update projection lines
1434      dsp4_vars.world_x += (dsp4_vars.world_dx + dsp4_vars.world_xenv);
1435      dsp4_vars.world_y += dsp4_vars.world_dy;
14351436
1436    ////////////////////////////////////////////////////
1437    // command check
1437      ////////////////////////////////////////////////////
1438      // command check
14381439
1439    // scan next command
1440    DSP4.in_count = 2;
1441    DSP4_WAIT(1) resume1 :
1440      // scan next command
1441      dsp4.in_count = 2;
1442      DSP4_WAIT(1) resume1 :
14421443
1443    // inspect input
1444    DSP4_vars.distance = DSP4_READ_WORD();
1444      // inspect input
1445      dsp4_vars.distance = DSP4_READ_WORD();
14451446
1446    // terminate op
1447    if (DSP4_vars.distance == -0x8000)
1448      break;
1447      // terminate op
1448      if (dsp4_vars.distance == -0x8000)
1449         break;
14491450
1450    // already have 2 bytes in queue
1451    DSP4.in_count = 6;
1452    DSP4_WAIT(2) resume2:
1451      // already have 2 bytes in queue
1452      dsp4.in_count = 6;
1453      DSP4_WAIT(2) resume2:
14531454
1454    // inspect inputs
1455    DSP4_vars.world_ddy = DSP4_READ_WORD();
1456    DSP4_vars.world_ddx = DSP4_READ_WORD();
1457    DSP4_vars.view_yofsenv = DSP4_READ_WORD();
1455      // inspect inputs
1456      dsp4_vars.world_ddy = DSP4_READ_WORD();
1457      dsp4_vars.world_ddx = DSP4_READ_WORD();
1458      dsp4_vars.view_yofsenv = DSP4_READ_WORD();
14581459
1459    // no envelope here
1460    DSP4_vars.world_xenv = 0;
1461  }
1462  while (1);
1460      // no envelope here
1461      dsp4_vars.world_xenv = 0;
1462   }
1463   while (1);
14631464
1464  DSP4.waiting4command = 1;
1465   dsp4.waiting4command = 1;
14651466}
14661467
14671468//////////////////////////////////////////////////////////////
14681469
14691470
1470static void DSP4_OP0E( void )
1471static void dsp4_OP0E( void )
14711472{
1472  DSP4_vars.OAM_RowMax = 16;
1473  memset(DSP4_vars.OAM_Row, 0, 64);
1473   dsp4_vars.OAM_RowMax = 16;
1474   memset(dsp4_vars.OAM_Row, 0, 64);
14741475}
14751476
14761477
14771478//////////////////////////////////////////////////////////////
14781479
1479static void DSP4_OP0F( void )
1480static void dsp4_OP0F( void )
14801481{
1481  DSP4.waiting4command = 0;
1482   dsp4.waiting4command = 0;
14821483
1483  // op flow control
1484  switch (DSP4_vars.DSP4_Logic)
1485  {
1486    case 1:
1487      goto resume1; break;
1488    case 2:
1489      goto resume2; break;
1490    case 3:
1491      goto resume3; break;
1492    case 4:
1493      goto resume4; break;
1494  }
1484   // op flow control
1485   switch (dsp4_vars.Logic)
1486   {
1487      case 1:
1488         goto resume1; break;
1489      case 2:
1490         goto resume2; break;
1491      case 3:
1492         goto resume3; break;
1493      case 4:
1494         goto resume4; break;
1495   }
14951496
1496  ////////////////////////////////////////////////////
1497  // process initial inputs
1497   ////////////////////////////////////////////////////
1498   // process initial inputs
14981499
1499  // sort inputs
1500  DSP4_READ_WORD(); // 0x0000
1501  DSP4_vars.world_y = DSP4_READ_DWORD();
1502  DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
1503  DSP4_vars.poly_top[0][0] = DSP4_READ_WORD();
1504  DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD();
1505  DSP4_vars.viewport_bottom = DSP4_READ_WORD();
1506  DSP4_vars.world_x = DSP4_READ_DWORD();
1507  DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD();
1508  DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
1509  DSP4_vars.world_yofs = DSP4_READ_WORD();
1510  DSP4_vars.world_dy = DSP4_READ_DWORD();
1511  DSP4_vars.world_dx = DSP4_READ_DWORD();
1512  DSP4_vars.distance = DSP4_READ_WORD();
1513  DSP4_READ_WORD(); // 0x0000
1514  DSP4_vars.world_xenv = DSP4_READ_DWORD();
1515  DSP4_vars.world_ddy = DSP4_READ_WORD();
1516  DSP4_vars.world_ddx = DSP4_READ_WORD();
1517  DSP4_vars.view_yofsenv = DSP4_READ_WORD();
1500   // sort inputs
1501   DSP4_READ_WORD(); // 0x0000
1502   dsp4_vars.world_y = DSP4_READ_DWORD();
1503   dsp4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
1504   dsp4_vars.poly_top[0][0] = DSP4_READ_WORD();
1505   dsp4_vars.poly_cx[1][0] = DSP4_READ_WORD();
1506   dsp4_vars.viewport_bottom = DSP4_READ_WORD();
1507   dsp4_vars.world_x = DSP4_READ_DWORD();
1508   dsp4_vars.poly_cx[0][0] = DSP4_READ_WORD();
1509   dsp4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
1510   dsp4_vars.world_yofs = DSP4_READ_WORD();
1511   dsp4_vars.world_dy = DSP4_READ_DWORD();
1512   dsp4_vars.world_dx = DSP4_READ_DWORD();
1513   dsp4_vars.distance = DSP4_READ_WORD();
1514   DSP4_READ_WORD(); // 0x0000
1515   dsp4_vars.world_xenv = DSP4_READ_DWORD();
1516   dsp4_vars.world_ddy = DSP4_READ_WORD();
1517   dsp4_vars.world_ddx = DSP4_READ_WORD();
1518   dsp4_vars.view_yofsenv = DSP4_READ_WORD();
15181519
1519  // initial (x,y,offset) at starting DSP4_vars.raster line
1520  DSP4_vars.view_x1 = (INT16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16);
1521  DSP4_vars.view_y1 = (INT16)(DSP4_vars.world_y >> 16);
1522  DSP4_vars.view_xofs1 = (INT16)(DSP4_vars.world_x >> 16);
1523  DSP4_vars.view_yofs1 = DSP4_vars.world_yofs;
1524  DSP4_vars.view_turnoff_x = 0;
1525  DSP4_vars.view_turnoff_dx = 0;
1520   // initial (x,y,offset) at starting dsp4_vars.raster line
1521   dsp4_vars.view_x1 = (INT16)((dsp4_vars.world_x + dsp4_vars.world_xenv) >> 16);
1522   dsp4_vars.view_y1 = (INT16)(dsp4_vars.world_y >> 16);
1523   dsp4_vars.view_xofs1 = (INT16)(dsp4_vars.world_x >> 16);
1524   dsp4_vars.view_yofs1 = dsp4_vars.world_yofs;
1525   dsp4_vars.view_turnoff_x = 0;
1526   dsp4_vars.view_turnoff_dx = 0;
15261527
1527  // first DSP4_vars.raster line
1528  DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0];
1528   // first dsp4_vars.raster line
1529   dsp4_vars.poly_raster[0][0] = dsp4_vars.poly_bottom[0][0];
15291530
15301531
1531  do
1532  {
1533    ////////////////////////////////////////////////////
1534    // process one iteration of projection
1532   do
1533   {
1534      ////////////////////////////////////////////////////
1535      // process one iteration of projection
15351536
1536    // perspective projection of world (x,y,scroll) points
1537    // based on the current projection lines
1538    DSP4_vars.view_x2 = (INT16)(((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16) * DSP4_vars.distance >> 15);
1539    DSP4_vars.view_y2 = (INT16)((DSP4_vars.world_y >> 16) * DSP4_vars.distance >> 15);
1540    DSP4_vars.view_xofs2 = DSP4_vars.view_x2;
1541    DSP4_vars.view_yofs2 = (DSP4_vars.world_yofs * DSP4_vars.distance >> 15) + DSP4_vars.poly_bottom[0][0] - DSP4_vars.view_y2;
1537      // perspective projection of world (x,y,scroll) points
1538      // based on the current projection lines
1539      dsp4_vars.view_x2 = (INT16)(((dsp4_vars.world_x + dsp4_vars.world_xenv) >> 16) * dsp4_vars.distance >> 15);
1540      dsp4_vars.view_y2 = (INT16)((dsp4_vars.world_y >> 16) * dsp4_vars.distance >> 15);
1541      dsp4_vars.view_xofs2 = dsp4_vars.view_x2;
1542      dsp4_vars.view_yofs2 = (dsp4_vars.world_yofs * dsp4_vars.distance >> 15) + dsp4_vars.poly_bottom[0][0] - dsp4_vars.view_y2;
15421543
1543    // 1. World x-location before transformation
1544    // 2. Viewer x-position at the next
1545    // 3. World y-location before perspective projection
1546    // 4. Viewer y-position below the horizon
1547    // 5. Number of DSP4_vars.raster lines drawn in this iteration
1544      // 1. World x-location before transformation
1545      // 2. Viewer x-position at the next
1546      // 3. World y-location before perspective projection
1547      // 4. Viewer y-position below the horizon
1548      // 5. Number of dsp4_vars.raster lines drawn in this iteration
15481549
1549    DSP4_CLEAR_OUT();
1550    DSP4_WRITE_WORD((UINT16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16));
1551    DSP4_WRITE_WORD(DSP4_vars.view_x2);
1552    DSP4_WRITE_WORD((UINT16)(DSP4_vars.world_y >> 16));
1553    DSP4_WRITE_WORD(DSP4_vars.view_y2);
1550      DSP4_CLEAR_OUT();
1551      DSP4_WRITE_WORD((UINT16)((dsp4_vars.world_x + dsp4_vars.world_xenv) >> 16));
1552      DSP4_WRITE_WORD(dsp4_vars.view_x2);
1553      DSP4_WRITE_WORD((UINT16)(dsp4_vars.world_y >> 16));
1554      DSP4_WRITE_WORD(dsp4_vars.view_y2);
15541555
1555    //////////////////////////////////////////////////////
1556      //////////////////////////////////////////////////////
15561557
1557    // SR = 0x00
1558      // SR = 0x00
15581559
1559    // determine # of DSP4_vars.raster lines used
1560    DSP4_vars.segments = DSP4_vars.poly_raster[0][0] - DSP4_vars.view_y2;
1560      // determine # of dsp4_vars.raster lines used
1561      dsp4_vars.segments = dsp4_vars.poly_raster[0][0] - dsp4_vars.view_y2;
15611562
1562    // prevent overdraw
1563    if (DSP4_vars.view_y2 >= DSP4_vars.poly_raster[0][0])
1564      DSP4_vars.segments = 0;
1565    else
1566      DSP4_vars.poly_raster[0][0] = DSP4_vars.view_y2;
1563      // prevent overdraw
1564      if (dsp4_vars.view_y2 >= dsp4_vars.poly_raster[0][0])
1565         dsp4_vars.segments = 0;
1566      else
1567         dsp4_vars.poly_raster[0][0] = dsp4_vars.view_y2;
15671568
1568    // don't draw outside the window
1569    if (DSP4_vars.view_y2 < DSP4_vars.poly_top[0][0])
1570    {
1571      DSP4_vars.segments = 0;
1569      // don't draw outside the window
1570      if (dsp4_vars.view_y2 < dsp4_vars.poly_top[0][0])
1571      {
1572         dsp4_vars.segments = 0;
15721573
1573      // flush remaining DSP4_vars.raster lines
1574      if (DSP4_vars.view_y1 >= DSP4_vars.poly_top[0][0])
1575        DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.poly_top[0][0];
1576    }
1574         // flush remaining dsp4_vars.raster lines
1575         if (dsp4_vars.view_y1 >= dsp4_vars.poly_top[0][0])
1576            dsp4_vars.segments = dsp4_vars.view_y1 - dsp4_vars.poly_top[0][0];
1577      }
15771578
1578    // SR = 0x80
1579      // SR = 0x80
15791580
1580    DSP4_WRITE_WORD(DSP4_vars.segments);
1581      DSP4_WRITE_WORD(dsp4_vars.segments);
15811582
1582    //////////////////////////////////////////////////////
1583      //////////////////////////////////////////////////////
15831584
1584    // scan next command if no SR check needed
1585    if (DSP4_vars.segments)
1586    {
1587      INT32 px_dx, py_dy;
1588      INT32 x_scroll, y_scroll;
1585      // scan next command if no SR check needed
1586      if (dsp4_vars.segments)
1587      {
1588         INT32 px_dx, py_dy;
1589         INT32 x_scroll, y_scroll;
15891590
1590      for (DSP4_vars.lcv = 0; DSP4_vars.lcv < 4; DSP4_vars.lcv++)
1591      {
1592        // grab inputs
1593        DSP4.in_count = 4;
1594        DSP4_WAIT(1);
1595        resume1 :
1596        for (;;)
1597        {
1598          INT16 distance;
1599          INT16 color, red, green, blue;
1591         for (dsp4_vars.lcv = 0; dsp4_vars.lcv < 4; dsp4_vars.lcv++)
1592         {
1593            // grab inputs
1594            dsp4.in_count = 4;
1595            DSP4_WAIT(1);
1596            resume1 :
1597            for (;;)
1598            {
1599               INT16 distance;
1600               INT16 color, red, green, blue;
16001601
1601          distance = DSP4_READ_WORD();
1602          color = DSP4_READ_WORD();
1602               distance = DSP4_READ_WORD();
1603               color = DSP4_READ_WORD();
16031604
1604          // U1+B5+G5+R5
1605          red = color & 0x1f;
1606          green = (color >> 5) & 0x1f;
1607          blue = (color >> 10) & 0x1f;
1605               // U1+B5+G5+R5
1606               red = color & 0x1f;
1607               green = (color >> 5) & 0x1f;
1608               blue = (color >> 10) & 0x1f;
16081609
1609          // dynamic lighting
1610          red = (red * distance >> 15) & 0x1f;
1611          green = (green * distance >> 15) & 0x1f;
1612          blue = (blue * distance >> 15) & 0x1f;
1613          color = red | (green << 5) | (blue << 10);
1610               // dynamic lighting
1611               red = (red * distance >> 15) & 0x1f;
1612               green = (green * distance >> 15) & 0x1f;
1613               blue = (blue * distance >> 15) & 0x1f;
1614               color = red | (green << 5) | (blue << 10);
16141615
1615          DSP4_CLEAR_OUT();
1616          DSP4_WRITE_WORD(color);
1617          break;
1618        }
1619      }
1616               DSP4_CLEAR_OUT();
1617               DSP4_WRITE_WORD(color);
1618               break;
1619            }
1620         }
16201621
1621      //////////////////////////////////////////////////////
1622         //////////////////////////////////////////////////////
16221623
1623      // SR = 0x00
1624         // SR = 0x00
16241625
1625      // linear interpolation (lerp) between projected points
1626      px_dx = (DSP4_vars.view_xofs2 - DSP4_vars.view_xofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;
1627      py_dy = (DSP4_vars.view_yofs2 - DSP4_vars.view_yofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;
1626         // linear interpolation (lerp) between projected points
1627         px_dx = (dsp4_vars.view_xofs2 - dsp4_vars.view_xofs1) * dsp4_Inverse(dsp4_vars.segments) << 1;
1628         py_dy = (dsp4_vars.view_yofs2 - dsp4_vars.view_yofs1) * dsp4_Inverse(dsp4_vars.segments) << 1;
16281629
16291630
1630      // starting step values
1631      x_scroll = SEX16(DSP4_vars.poly_cx[0][0] + DSP4_vars.view_xofs1);
1632      y_scroll = SEX16(-DSP4_vars.viewport_bottom + DSP4_vars.view_yofs1 + DSP4_vars.view_yofsenv + DSP4_vars.poly_cx[1][0] - DSP4_vars.world_yofs);
1631         // starting step values
1632         x_scroll = SEX16(dsp4_vars.poly_cx[0][0] + dsp4_vars.view_xofs1);
1633         y_scroll = SEX16(-dsp4_vars.viewport_bottom + dsp4_vars.view_yofs1 + dsp4_vars.view_yofsenv + dsp4_vars.poly_cx[1][0] - dsp4_vars.world_yofs);
16331634
1634      // SR = 0x80
1635         // SR = 0x80
16351636
1636      // rasterize line
1637      for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++)
1638      {
1639        // 1. HDMA memory pointer
1640        // 2. vertical scroll offset ($210E)
1641        // 3. horizontal scroll offset ($210D)
1637         // rasterize line
1638         for (dsp4_vars.lcv = 0; dsp4_vars.lcv < dsp4_vars.segments; dsp4_vars.lcv++)
1639         {
1640            // 1. HDMA memory pointer
1641            // 2. vertical scroll offset ($210E)
1642            // 3. horizontal scroll offset ($210D)
16421643
1643        DSP4_WRITE_WORD(DSP4_vars.poly_ptr[0][0]);
1644        DSP4_WRITE_WORD((UINT16)((y_scroll + 0x8000) >> 16));
1645        DSP4_WRITE_WORD((UINT16)((x_scroll + 0x8000) >> 16));
1644            DSP4_WRITE_WORD(dsp4_vars.poly_ptr[0][0]);
1645            DSP4_WRITE_WORD((UINT16)((y_scroll + 0x8000) >> 16));
1646            DSP4_WRITE_WORD((UINT16)((x_scroll + 0x8000) >> 16));
16461647
1647        // update memory address
1648        DSP4_vars.poly_ptr[0][0] -= 4;
1648            // update memory address
1649            dsp4_vars.poly_ptr[0][0] -= 4;
16491650
1650        // update screen values
1651        x_scroll += px_dx;
1652        y_scroll += py_dy;
1653      }
1654    }
1651            // update screen values
1652            x_scroll += px_dx;
1653            y_scroll += py_dy;
1654         }
1655      }
16551656
1656    ////////////////////////////////////////////////////
1657    // Post-update
1657      ////////////////////////////////////////////////////
1658      // Post-update
16581659
1659    // update new viewer (x,y,scroll) to last DSP4_vars.raster line drawn
1660    DSP4_vars.view_x1 = DSP4_vars.view_x2;
1661    DSP4_vars.view_y1 = DSP4_vars.view_y2;
1662    DSP4_vars.view_xofs1 = DSP4_vars.view_xofs2;
1663    DSP4_vars.view_yofs1 = DSP4_vars.view_yofs2;
1660      // update new viewer (x,y,scroll) to last dsp4_vars.raster line drawn
1661      dsp4_vars.view_x1 = dsp4_vars.view_x2;
1662      dsp4_vars.view_y1 = dsp4_vars.view_y2;
1663      dsp4_vars.view_xofs1 = dsp4_vars.view_xofs2;
1664      dsp4_vars.view_yofs1 = dsp4_vars.view_yofs2;
16641665
1665    // add deltas for projection lines
1666    DSP4_vars.world_dx += SEX78(DSP4_vars.world_ddx);
1667    DSP4_vars.world_dy += SEX78(DSP4_vars.world_ddy);
1666      // add deltas for projection lines
1667      dsp4_vars.world_dx += SEX78(dsp4_vars.world_ddx);
1668      dsp4_vars.world_dy += SEX78(dsp4_vars.world_ddy);
16681669
1669    // update projection lines
1670    DSP4_vars.world_x += (DSP4_vars.world_dx + DSP4_vars.world_xenv);
1671    DSP4_vars.world_y += DSP4_vars.world_dy;
1670      // update projection lines
1671      dsp4_vars.world_x += (dsp4_vars.world_dx + dsp4_vars.world_xenv);
1672      dsp4_vars.world_y += dsp4_vars.world_dy;
16721673
1673    // update road turnoff position
1674    DSP4_vars.view_turnoff_x += DSP4_vars.view_turnoff_dx;
1674      // update road turnoff position
1675      dsp4_vars.view_turnoff_x += dsp4_vars.view_turnoff_dx;
16751676
1676    ////////////////////////////////////////////////////
1677    // command check
1677      ////////////////////////////////////////////////////
1678      // command check
16781679
1679    // scan next command
1680    DSP4.in_count = 2;
1681    DSP4_WAIT(2) resume2:
1680      // scan next command
1681      dsp4.in_count = 2;
1682      DSP4_WAIT(2) resume2:
16821683
1683    // check for termination
1684    DSP4_vars.distance = DSP4_READ_WORD();
1685    if (DSP4_vars.distance == -0x8000)
1686      break;
1684      // check for termination
1685      dsp4_vars.distance = DSP4_READ_WORD();
1686      if (dsp4_vars.distance == -0x8000)
1687         break;
16871688
1688    // road splice
1689    if( (UINT16) DSP4_vars.distance == 0x8001 )
1690    {
1691      DSP4.in_count = 6;
1692      DSP4_WAIT(3) resume3:
1689      // road splice
1690      if( (UINT16) dsp4_vars.distance == 0x8001 )
1691      {
1692         dsp4.in_count = 6;
1693         DSP4_WAIT(3) resume3:
16931694
1694      DSP4_vars.distance = DSP4_READ_WORD();
1695      DSP4_vars.view_turnoff_x = DSP4_READ_WORD();
1696      DSP4_vars.view_turnoff_dx = DSP4_READ_WORD();
1695         dsp4_vars.distance = DSP4_READ_WORD();
1696         dsp4_vars.view_turnoff_x = DSP4_READ_WORD();
1697         dsp4_vars.view_turnoff_dx = DSP4_READ_WORD();
16971698
1698      // factor in new changes
1699      DSP4_vars.view_x1 += ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 );
1700      DSP4_vars.view_xofs1 += ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 );
1699         // factor in new changes
1700         dsp4_vars.view_x1 += ( dsp4_vars.view_turnoff_x * dsp4_vars.distance >> 15 );
1701         dsp4_vars.view_xofs1 += ( dsp4_vars.view_turnoff_x * dsp4_vars.distance >> 15 );
17011702
1702      // update stepping values
1703      DSP4_vars.view_turnoff_x += DSP4_vars.view_turnoff_dx;
1703         // update stepping values
1704         dsp4_vars.view_turnoff_x += dsp4_vars.view_turnoff_dx;
17041705
1705      DSP4.in_count = 2;
1706      DSP4_WAIT(2)
1707    }
1706         dsp4.in_count = 2;
1707         DSP4_WAIT(2)
1708      }
17081709
1709    // already have 2 bytes in queue
1710    DSP4.in_count = 6;
1711    DSP4_WAIT(4) resume4 :
1710      // already have 2 bytes in queue
1711      dsp4.in_count = 6;
1712      DSP4_WAIT(4) resume4 :
17121713
1713    // inspect inputs
1714    DSP4_vars.world_ddy = DSP4_READ_WORD();
1715    DSP4_vars.world_ddx = DSP4_READ_WORD();
1716    DSP4_vars.view_yofsenv = DSP4_READ_WORD();
1714      // inspect inputs
1715      dsp4_vars.world_ddy = DSP4_READ_WORD();
1716      dsp4_vars.world_ddx = DSP4_READ_WORD();
1717      dsp4_vars.view_yofsenv = DSP4_READ_WORD();
17171718
1718    // no envelope here
1719    DSP4_vars.world_xenv = 0;
1720  }
1721  while (1);
1719      // no envelope here
1720      dsp4_vars.world_xenv = 0;
1721   }
1722   while (1);
17221723
1723  // terminate op
1724  DSP4.waiting4command = 1;
1724   // terminate op
1725   dsp4.waiting4command = 1;
17251726}
17261727
17271728//////////////////////////////////////////////////////////////
17281729
17291730
1730static void DSP4_OP10( void )
1731static void dsp4_OP10( void )
17311732{
1732  DSP4.waiting4command = 0;
1733   dsp4.waiting4command = 0;
17331734
1734  // op flow control
1735  switch (DSP4_vars.DSP4_Logic)
1736  {
1737    case 1:
1738      goto resume1; break;
1739    case 2:
1740      goto resume2; break;
1741    case 3:
1742      goto resume3; break;
1743  }
1735   // op flow control
1736   switch (dsp4_vars.Logic)
1737   {
1738      case 1:
1739         goto resume1; break;
1740      case 2:
1741         goto resume2; break;
1742      case 3:
1743         goto resume3; break;
1744   }
17441745
1745  ////////////////////////////////////////////////////
1746  // sort inputs
1746   ////////////////////////////////////////////////////
1747   // sort inputs
17471748
1748  DSP4_READ_WORD(); // 0x0000
1749  DSP4_vars.world_y = DSP4_READ_DWORD();
1750  DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
1751  DSP4_vars.poly_top[0][0] = DSP4_READ_WORD();
1752  DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD();
1753  DSP4_vars.viewport_bottom = DSP4_READ_WORD();
1754  DSP4_vars.world_x = DSP4_READ_DWORD();
1755  DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD();
1756  DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
1757  DSP4_vars.world_yofs = DSP4_READ_WORD();
1758  DSP4_vars.distance = DSP4_READ_WORD();
1759  DSP4_vars.view_y2 = DSP4_READ_WORD();
1760  DSP4_vars.view_dy = DSP4_READ_WORD() * DSP4_vars.distance >> 15;
1761  DSP4_vars.view_x2 = DSP4_READ_WORD();
1762  DSP4_vars.view_dx = DSP4_READ_WORD() * DSP4_vars.distance >> 15;
1763  DSP4_vars.view_yofsenv = DSP4_READ_WORD();
1749   DSP4_READ_WORD(); // 0x0000
1750   dsp4_vars.world_y = DSP4_READ_DWORD();
1751   dsp4_vars.poly_bottom[0][0] = DSP4_READ_WORD();
1752   dsp4_vars.poly_top[0][0] = DSP4_READ_WORD();
1753   dsp4_vars.poly_cx[1][0] = DSP4_READ_WORD();
1754   dsp4_vars.viewport_bottom = DSP4_READ_WORD();
1755   dsp4_vars.world_x = DSP4_READ_DWORD();
1756   dsp4_vars.poly_cx[0][0] = DSP4_READ_WORD();
1757   dsp4_vars.poly_ptr[0][0] = DSP4_READ_WORD();
1758   dsp4_vars.world_yofs = DSP4_READ_WORD();
1759   dsp4_vars.distance = DSP4_READ_WORD();
1760   dsp4_vars.view_y2 = DSP4_READ_WORD();
1761   dsp4_vars.view_dy = DSP4_READ_WORD() * dsp4_vars.distance >> 15;
1762   dsp4_vars.view_x2 = DSP4_READ_WORD();
1763   dsp4_vars.view_dx = DSP4_READ_WORD() * dsp4_vars.distance >> 15;
1764   dsp4_vars.view_yofsenv = DSP4_READ_WORD();
17641765
1765  // initial (x,y,offset) at starting DSP4_vars.raster line
1766  DSP4_vars.view_x1 = (INT16)(DSP4_vars.world_x >> 16);
1767  DSP4_vars.view_y1 = (INT16)(DSP4_vars.world_y >> 16);
1768  DSP4_vars.view_xofs1 = DSP4_vars.view_x1;
1769  DSP4_vars.view_yofs1 = DSP4_vars.world_yofs;
1766   // initial (x,y,offset) at starting dsp4_vars.raster line
1767   dsp4_vars.view_x1 = (INT16)(dsp4_vars.world_x >> 16);
1768   dsp4_vars.view_y1 = (INT16)(dsp4_vars.world_y >> 16);
1769   dsp4_vars.view_xofs1 = dsp4_vars.view_x1;
1770   dsp4_vars.view_yofs1 = dsp4_vars.world_yofs;
17701771
1771  // first DSP4_vars.raster line
1772  DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0];
1772   // first dsp4_vars.raster line
1773   dsp4_vars.poly_raster[0][0] = dsp4_vars.poly_bottom[0][0];
17731774
1774  do
1775  {
1776    ////////////////////////////////////////////////////
1777    // process one iteration of projection
1775   do
1776   {
1777      ////////////////////////////////////////////////////
1778      // process one iteration of projection
17781779
1779    // add shaping
1780    DSP4_vars.view_x2 += DSP4_vars.view_dx;
1781    DSP4_vars.view_y2 += DSP4_vars.view_dy;
1780      // add shaping
1781      dsp4_vars.view_x2 += dsp4_vars.view_dx;
1782      dsp4_vars.view_y2 += dsp4_vars.view_dy;
17821783
1783    // vertical scroll calculation
1784    DSP4_vars.view_xofs2 = DSP4_vars.view_x2;
1785    DSP4_vars.view_yofs2 = (DSP4_vars.world_yofs * DSP4_vars.distance >> 15) + DSP4_vars.poly_bottom[0][0] - DSP4_vars.view_y2;
1784      // vertical scroll calculation
1785      dsp4_vars.view_xofs2 = dsp4_vars.view_x2;
1786      dsp4_vars.view_yofs2 = (dsp4_vars.world_yofs * dsp4_vars.distance >> 15) + dsp4_vars.poly_bottom[0][0] - dsp4_vars.view_y2;
17861787
1787    // 1. Viewer x-position at the next
1788    // 2. Viewer y-position below the horizon
1789    // 3. Number of DSP4_vars.raster lines drawn in this iteration
1788      // 1. Viewer x-position at the next
1789      // 2. Viewer y-position below the horizon
1790      // 3. Number of dsp4_vars.raster lines drawn in this iteration
17901791
1791    DSP4_CLEAR_OUT();
1792    DSP4_WRITE_WORD(DSP4_vars.view_x2);
1793    DSP4_WRITE_WORD(DSP4_vars.view_y2);
1792      DSP4_CLEAR_OUT();
1793      DSP4_WRITE_WORD(dsp4_vars.view_x2);
1794      DSP4_WRITE_WORD(dsp4_vars.view_y2);
17941795
1795    //////////////////////////////////////////////////////
1796      //////////////////////////////////////////////////////
17961797
1797    // SR = 0x00
1798      // SR = 0x00
17981799
1799    // determine # of DSP4_vars.raster lines used
1800    DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.view_y2;
1800      // determine # of dsp4_vars.raster lines used
1801      dsp4_vars.segments = dsp4_vars.view_y1 - dsp4_vars.view_y2;
18011802
1802    // prevent overdraw
1803    if (DSP4_vars.view_y2 >= DSP4_vars.poly_raster[0][0])
1804      DSP4_vars.segments = 0;
1805    else
1806      DSP4_vars.poly_raster[0][0] = DSP4_vars.view_y2;
1803      // prevent overdraw
1804      if (dsp4_vars.view_y2 >= dsp4_vars.poly_raster[0][0])
1805         dsp4_vars.segments = 0;
1806      else
1807         dsp4_vars.poly_raster[0][0] = dsp4_vars.view_y2;
18071808
1808    // don't draw outside the window
1809    if (DSP4_vars.view_y2 < DSP4_vars.poly_top[0][0])
1810    {
1811      DSP4_vars.segments = 0;
1809      // don't draw outside the window
1810      if (dsp4_vars.view_y2 < dsp4_vars.poly_top[0][0])
1811      {
1812         dsp4_vars.segments = 0;
18121813
1813      // flush remaining DSP4_vars.raster lines
1814      if (DSP4_vars.view_y1 >= DSP4_vars.poly_top[0][0])
1815        DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.poly_top[0][0];
1816    }
1814         // flush remaining dsp4_vars.raster lines
1815         if (dsp4_vars.view_y1 >= dsp4_vars.poly_top[0][0])
1816            dsp4_vars.segments = dsp4_vars.view_y1 - dsp4_vars.poly_top[0][0];
1817      }
18171818
1818    // SR = 0x80
1819      // SR = 0x80
18191820
1820    DSP4_WRITE_WORD(DSP4_vars.segments);
1821      DSP4_WRITE_WORD(dsp4_vars.segments);
18211822
1822    //////////////////////////////////////////////////////
1823      //////////////////////////////////////////////////////
18231824
1824    // scan next command if no SR check needed
1825    if (DSP4_vars.segments)
1826    {
1827      for (DSP4_vars.lcv = 0; DSP4_vars.lcv < 4; DSP4_vars.lcv++)
1828      {
1829        // grab inputs
1830        DSP4.in_count = 4;
1831        DSP4_WAIT(1);
1832        resume1 :
1833        for (;;)
1834        {
1835          INT16 distance;
1836          INT16 color, red, green, blue;
1825      // scan next command if no SR check needed
1826      if (dsp4_vars.segments)
1827      {
1828         for (dsp4_vars.lcv = 0; dsp4_vars.lcv < 4; dsp4_vars.lcv++)
1829         {
1830            // grab inputs
1831            dsp4.in_count = 4;
1832            DSP4_WAIT(1);
1833            resume1 :
1834            for (;;)
1835            {
1836               INT16 distance;
1837               INT16 color, red, green, blue;
18371838
1838          distance = DSP4_READ_WORD();
1839          color = DSP4_READ_WORD();
1839               distance = DSP4_READ_WORD();
1840               color = DSP4_READ_WORD();
18401841
1841          // U1+B5+G5+R5
1842          red = color & 0x1f;
1843          green = (color >> 5) & 0x1f;
1844          blue = (color >> 10) & 0x1f;
1842               // U1+B5+G5+R5
1843               red = color & 0x1f;
1844               green = (color >> 5) & 0x1f;
1845               blue = (color >> 10) & 0x1f;
18451846
1846          // dynamic lighting
1847          red = (red * distance >> 15) & 0x1f;
1848          green = (green * distance >> 15) & 0x1f;
1849          blue = (blue * distance >> 15) & 0x1f;
1850          color = red | (green << 5) | (blue << 10);
1847               // dynamic lighting
1848               red = (red * distance >> 15) & 0x1f;
1849               green = (green * distance >> 15) & 0x1f;
1850               blue = (blue * distance >> 15) & 0x1f;
1851               color = red | (green << 5) | (blue << 10);
18511852
1852          DSP4_CLEAR_OUT();
1853          DSP4_WRITE_WORD(color);
1854          break;
1855        }
1856      }
1857    }
1853               DSP4_CLEAR_OUT();
1854               DSP4_WRITE_WORD(color);
1855               break;
1856            }
1857         }
1858      }
18581859
1859    //////////////////////////////////////////////////////
1860      //////////////////////////////////////////////////////
18601861
1861    // scan next command if no SR check needed
1862    if (DSP4_vars.segments)
1863    {
1864      INT32 px_dx, py_dy;
1865      INT32 x_scroll, y_scroll;
1862      // scan next command if no SR check needed
1863      if (dsp4_vars.segments)
1864      {
1865         INT32 px_dx, py_dy;
1866         INT32 x_scroll, y_scroll;
18661867
1867      // SR = 0x00
1868         // SR = 0x00
18681869
1869      // linear interpolation (lerp) between projected points
1870      px_dx = (DSP4_vars.view_xofs2 - DSP4_vars.view_xofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;
1871      py_dy = (DSP4_vars.view_yofs2 - DSP4_vars.view_yofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;
1870         // linear interpolation (lerp) between projected points
1871         px_dx = (dsp4_vars.view_xofs2 - dsp4_vars.view_xofs1) * dsp4_Inverse(dsp4_vars.segments) << 1;
1872         py_dy = (dsp4_vars.view_yofs2 - dsp4_vars.view_yofs1) * dsp4_Inverse(dsp4_vars.segments) << 1;
18721873
1873      // starting step values
1874      x_scroll = SEX16(DSP4_vars.poly_cx[0][0] + DSP4_vars.view_xofs1);
1875      y_scroll = SEX16(-DSP4_vars.viewport_bottom + DSP4_vars.view_yofs1 + DSP4_vars.view_yofsenv + DSP4_vars.poly_cx[1][0] - DSP4_vars.world_yofs);
1874         // starting step values
1875         x_scroll = SEX16(dsp4_vars.poly_cx[0][0] + dsp4_vars.view_xofs1);
1876         y_scroll = SEX16(-dsp4_vars.viewport_bottom + dsp4_vars.view_yofs1 + dsp4_vars.view_yofsenv + dsp4_vars.poly_cx[1][0] - dsp4_vars.world_yofs);
18761877
1877      // SR = 0x80
1878         // SR = 0x80
18781879
1879      // rasterize line
1880      for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++)
1881      {
1882        // 1. HDMA memory pointer (bg2)
1883        // 2. vertical scroll offset ($2110)
1884        // 3. horizontal scroll offset ($210F)
1880         // rasterize line
1881         for (dsp4_vars.lcv = 0; dsp4_vars.lcv < dsp4_vars.segments; dsp4_vars.lcv++)
1882         {
1883            // 1. HDMA memory pointer (bg2)
1884            // 2. vertical scroll offset ($2110)
1885            // 3. horizontal scroll offset ($210F)
18851886
1886        DSP4_WRITE_WORD(DSP4_vars.poly_ptr[0][0]);
1887        DSP4_WRITE_WORD((UINT16)((y_scroll + 0x8000) >> 16));
1888        DSP4_WRITE_WORD((UINT16)((x_scroll + 0x8000) >> 16));
1887            DSP4_WRITE_WORD(dsp4_vars.poly_ptr[0][0]);
1888            DSP4_WRITE_WORD((UINT16)((y_scroll + 0x8000) >> 16));
1889            DSP4_WRITE_WORD((UINT16)((x_scroll + 0x8000) >> 16));
18891890
1890        // update memory address
1891        DSP4_vars.poly_ptr[0][0] -= 4;
1891            // update memory address
1892            dsp4_vars.poly_ptr[0][0] -= 4;
18921893
1893        // update screen values
1894        x_scroll += px_dx;
1895        y_scroll += py_dy;
1896      }
1897    }
1894            // update screen values
1895            x_scroll += px_dx;
1896            y_scroll += py_dy;
1897         }
1898      }
18981899
1899    /////////////////////////////////////////////////////
1900    // Post-update
1900      /////////////////////////////////////////////////////
1901      // Post-update
19011902
1902    // update new viewer (x,y,scroll) to last DSP4_vars.raster line drawn
1903    DSP4_vars.view_x1 = DSP4_vars.view_x2;
1904    DSP4_vars.view_y1 = DSP4_vars.view_y2;
1905    DSP4_vars.view_xofs1 = DSP4_vars.view_xofs2;
1906    DSP4_vars.view_yofs1 = DSP4_vars.view_yofs2;
1903      // update new viewer (x,y,scroll) to last dsp4_vars.raster line drawn
1904      dsp4_vars.view_x1 = dsp4_vars.view_x2;
1905      dsp4_vars.view_y1 = dsp4_vars.view_y2;
1906      dsp4_vars.view_xofs1 = dsp4_vars.view_xofs2;
1907      dsp4_vars.view_yofs1 = dsp4_vars.view_yofs2;
19071908
1908    ////////////////////////////////////////////////////
1909    // command check
1909      ////////////////////////////////////////////////////
1910      // command check
19101911
1911    // scan next command
1912    DSP4.in_count = 2;
1913    DSP4_WAIT(2) resume2 :
1912      // scan next command
1913      dsp4.in_count = 2;
1914      DSP4_WAIT(2) resume2 :
19141915
1915    // check for opcode termination
1916    DSP4_vars.distance = DSP4_READ_WORD();
1917    if (DSP4_vars.distance == -0x8000)
1918      break;
1916      // check for opcode termination
1917      dsp4_vars.distance = DSP4_READ_WORD();
1918      if (dsp4_vars.distance == -0x8000)
1919         break;
19191920
1920    // already have 2 bytes in queue
1921    DSP4.in_count = 10;
1922    DSP4_WAIT(3) resume3 :
1921      // already have 2 bytes in queue
1922      dsp4.in_count = 10;
1923      DSP4_WAIT(3) resume3 :
19231924
19241925
1925    // inspect inputs
1926    DSP4_vars.view_y2 = DSP4_READ_WORD();
1927    DSP4_vars.view_dy = DSP4_READ_WORD() * DSP4_vars.distance >> 15;
1928    DSP4_vars.view_x2 = DSP4_READ_WORD();
1929    DSP4_vars.view_dx = DSP4_READ_WORD() * DSP4_vars.distance >> 15;
1930  }
1931  while (1);
1926      // inspect inputs
1927      dsp4_vars.view_y2 = DSP4_READ_WORD();
1928      dsp4_vars.view_dy = DSP4_READ_WORD() * dsp4_vars.distance >> 15;
1929      dsp4_vars.view_x2 = DSP4_READ_WORD();
1930      dsp4_vars.view_dx = DSP4_READ_WORD() * dsp4_vars.distance >> 15;
1931   }
1932   while (1);
19321933
1933  DSP4.waiting4command = 1;
1934   dsp4.waiting4command = 1;
19341935}
19351936
19361937//////////////////////////////////////////////////////////////
19371938
1938static void DSP4_OP11(INT16 A, INT16 B, INT16 C, INT16 D, INT16 *M)
1939static void dsp4_OP11(INT16 A, INT16 B, INT16 C, INT16 D, INT16 *M)
19391940{
1940  // 0x155 = 341 = Horizontal Width of the Screen
1941  *M = ((A * 0x0155 >> 2) & 0xf000) |
1942       ((B * 0x0155 >> 6) & 0x0f00) |
1943       ((C * 0x0155 >> 10) & 0x00f0) |
1944       ((D * 0x0155 >> 14) & 0x000f);
1941   // 0x155 = 341 = Horizontal Width of the Screen
1942   *M = ((A * 0x0155 >> 2) & 0xf000) |
1943          ((B * 0x0155 >> 6) & 0x0f00) |
1944          ((C * 0x0155 >> 10) & 0x00f0) |
1945          ((D * 0x0155 >> 14) & 0x000f);
19451946}
19461947
19471948
r7621r7622
19521953//Processing Code
19531954/////////////////////////////////////////////////////////////
19541955
1955static void InitDSP4( void )
1956static void dsp4_register_save( running_machine *machine )
19561957{
1957  memset(&DSP4, 0, sizeof(DSP4));
1958  DSP4.waiting4command = 1;
1958   state_save_register_global(machine, dsp4.waiting4command);
1959   state_save_register_global(machine, dsp4.half_command);
1960   state_save_register_global(machine, dsp4.command);
1961   state_save_register_global(machine, dsp4.in_count);
1962   state_save_register_global(machine, dsp4.in_index);
1963   state_save_register_global(machine, dsp4.out_count);
1964   state_save_register_global(machine, dsp4.out_index);
1965   state_save_register_global_array(machine, dsp4.parameters);
1966   state_save_register_global_array(machine, dsp4.output);
1967
1968   state_save_register_global(machine, dsp4_vars.Logic);
1969   state_save_register_global(machine, dsp4_vars.lcv);
1970   state_save_register_global(machine, dsp4_vars.distance);
1971   state_save_register_global(machine, dsp4_vars.raster);
1972   state_save_register_global(machine, dsp4_vars.segments);
1973
1974   state_save_register_global(machine, dsp4_vars.world_x);
1975   state_save_register_global(machine, dsp4_vars.world_y);
1976   state_save_register_global(machine, dsp4_vars.world_dx);
1977   state_save_register_global(machine, dsp4_vars.world_dy);
1978   state_save_register_global(machine, dsp4_vars.world_ddx);
1979   state_save_register_global(machine, dsp4_vars.world_ddy);
1980   state_save_register_global(machine, dsp4_vars.world_xenv);
1981   state_save_register_global(machine, dsp4_vars.world_yofs);
1982
1983   state_save_register_global(machine, dsp4_vars.view_x1);
1984   state_save_register_global(machine, dsp4_vars.view_y1);
1985   state_save_register_global(machine, dsp4_vars.view_x2);
1986   state_save_register_global(machine, dsp4_vars.view_y2);
1987   state_save_register_global(machine, dsp4_vars.view_dx);
1988   state_save_register_global(machine, dsp4_vars.view_dy);
1989   state_save_register_global(machine, dsp4_vars.view_xofs1);
1990   state_save_register_global(machine, dsp4_vars.view_yofs1);
1991   state_save_register_global(machine, dsp4_vars.view_xofs2);
1992   state_save_register_global(machine, dsp4_vars.view_yofs2);
1993   state_save_register_global(machine, dsp4_vars.view_yofsenv);
1994   state_save_register_global(machine, dsp4_vars.view_turnoff_x);
1995   state_save_register_global(machine, dsp4_vars.view_turnoff_dx);
1996
1997
1998   state_save_register_global(machine, dsp4_vars.viewport_cx);
1999   state_save_register_global(machine, dsp4_vars.viewport_cy);
2000   state_save_register_global(machine, dsp4_vars.viewport_left);
2001   state_save_register_global(machine, dsp4_vars.viewport_right);
2002   state_save_register_global(machine, dsp4_vars.viewport_top);
2003   state_save_register_global(machine, dsp4_vars.viewport_bottom);
2004
2005
2006   state_save_register_global(machine, dsp4_vars.sprite_x);
2007   state_save_register_global(machine, dsp4_vars.sprite_y);
2008   state_save_register_global(machine, dsp4_vars.sprite_attr);
2009   state_save_register_global(machine, dsp4_vars.sprite_size);
2010   state_save_register_global(machine, dsp4_vars.sprite_clipy);
2011   state_save_register_global(machine, dsp4_vars.sprite_count);
2012
2013   state_save_register_global_array(machine, dsp4_vars.poly_clipLf[0]);
2014   state_save_register_global_array(machine, dsp4_vars.poly_clipLf[1]);
2015   state_save_register_global_array(machine, dsp4_vars.poly_clipRt[0]);
2016   state_save_register_global_array(machine, dsp4_vars.poly_clipRt[1]);
2017   state_save_register_global_array(machine, dsp4_vars.poly_ptr[0]);
2018   state_save_register_global_array(machine, dsp4_vars.poly_ptr[1]);
2019   state_save_register_global_array(machine, dsp4_vars.poly_raster[0]);
2020   state_save_register_global_array(machine, dsp4_vars.poly_raster[1]);
2021   state_save_register_global_array(machine, dsp4_vars.poly_top[0]);
2022   state_save_register_global_array(machine, dsp4_vars.poly_top[1]);
2023   state_save_register_global_array(machine, dsp4_vars.poly_bottom[0]);
2024   state_save_register_global_array(machine, dsp4_vars.poly_bottom[1]);
2025   state_save_register_global_array(machine, dsp4_vars.poly_cx[0]);
2026   state_save_register_global_array(machine, dsp4_vars.poly_cx[1]);
2027   state_save_register_global_array(machine, dsp4_vars.poly_start);
2028   state_save_register_global_array(machine, dsp4_vars.poly_plane);
2029
2030   state_save_register_global_array(machine, dsp4_vars.OAM_attr);
2031   state_save_register_global(machine, dsp4_vars.OAM_index);
2032   state_save_register_global(machine, dsp4_vars.OAM_bits);
2033
2034   state_save_register_global(machine, dsp4_vars.OAM_RowMax);
2035   state_save_register_global_array(machine, dsp4_vars.OAM_Row);
19592036}
19602037
1961static void DSP4_write( UINT8 dsp4_byte )
2038static void dsp4_init( running_machine *machine )
19622039{
1963  // clear pending read
1964  if (DSP4.out_index < DSP4.out_count)
1965  {
1966    DSP4.out_index++;
1967    return;
1968  }
2040   memset(&dsp4, 0, sizeof(dsp4));
2041   dsp4.waiting4command = 1;
19692042
1970  if (DSP4.waiting4command)
1971  {
1972    if (DSP4.half_command)
1973    {
1974      DSP4.command |= (dsp4_byte << 8);
1975      DSP4.in_index = 0;
1976      DSP4.waiting4command = 0;
1977      DSP4.half_command = 0;
1978      DSP4.out_count = 0;
1979      DSP4.out_index = 0;
2043   dsp4_register_save(machine);
2044}
19802045
1981      DSP4_vars.DSP4_Logic = 0;
2046static void dsp4_write( UINT8 dsp4_byte )
2047{
2048   // clear pending read
2049   if (dsp4.out_index < dsp4.out_count)
2050   {
2051      dsp4.out_index++;
2052      return;
2053   }
19822054
2055   if (dsp4.waiting4command)
2056   {
2057      if (dsp4.half_command)
2058      {
2059         dsp4.command |= (dsp4_byte << 8);
2060         dsp4.in_index = 0;
2061         dsp4.waiting4command = 0;
2062         dsp4.half_command = 0;
2063         dsp4.out_count = 0;
2064         dsp4.out_index = 0;
19832065
1984      switch (DSP4.command)
1985      {
1986        case 0x0000:
1987          DSP4.in_count = 4; break;
1988        case 0x0001:
1989          DSP4.in_count = 44; break;
1990        case 0x0003:
1991          DSP4.in_count = 0; break;
1992        case 0x0005:
1993          DSP4.in_count = 0; break;
1994        case 0x0006:
1995          DSP4.in_count = 0; break;
1996        case 0x0007:
1997          DSP4.in_count = 34; break;
1998        case 0x0008:
1999          DSP4.in_count = 90; break;
2000        case 0x0009:
2001          DSP4.in_count = 14; break;
2002        case 0x000a:
2003          DSP4.in_count = 6; break;
2004        case 0x000b:
2005          DSP4.in_count = 6; break;
2006        case 0x000d:
2007          DSP4.in_count = 42; break;
2008        case 0x000e:
2009          DSP4.in_count = 0; break;
2010        case 0x000f:
2011          DSP4.in_count = 46; break;
2012        case 0x0010:
2013          DSP4.in_count = 36; break;
2014        case 0x0011:
2015          DSP4.in_count = 8; break;
2016        default:
2017          DSP4.waiting4command = 1;
2018          break;
2019      }
2020    }
2021    else
2022    {
2023      DSP4.command = dsp4_byte;
2024      DSP4.half_command = 1;
2025    }
2026  }
2027  else
2028  {
2029    DSP4.parameters[DSP4.in_index] = dsp4_byte;
2030    DSP4.in_index++;
2031  }
2066         dsp4_vars.Logic = 0;
20322067
2033  if (!DSP4.waiting4command && DSP4.in_count == DSP4.in_index)
2034  {
2035    // Actually execute the command
2036    DSP4.waiting4command = 1;
2037    DSP4.out_index = 0;
2038    DSP4.in_index = 0;
20392068
2040    switch (DSP4.command)
2041    {
2042        // 16-bit multiplication
2043      case 0x0000:
2044      {
2045        INT16 multiplier, multiplicand;
2046        INT32 product;
2069         switch (dsp4.command)
2070         {
2071            case 0x0000:
2072               dsp4.in_count = 4; break;
2073            case 0x0001:
2074               dsp4.in_count = 44; break;
2075            case 0x0003:
2076               dsp4.in_count = 0; break;
2077            case 0x0005:
2078               dsp4.in_count = 0; break;
2079            case 0x0006:
2080               dsp4.in_count = 0; break;
2081            case 0x0007:
2082               dsp4.in_count = 34; break;
2083            case 0x0008:
2084               dsp4.in_count = 90; break;
2085            case 0x0009:
2086               dsp4.in_count = 14; break;
2087            case 0x000a:
2088               dsp4.in_count = 6; break;
2089            case 0x000b:
2090               dsp4.in_count = 6; break;
2091            case 0x000d:
2092               dsp4.in_count = 42; break;
2093            case 0x000e:
2094               dsp4.in_count = 0; break;
2095            case 0x000f:
2096               dsp4.in_count = 46; break;
2097            case 0x0010:
2098               dsp4.in_count = 36; break;
2099            case 0x0011:
2100               dsp4.in_count = 8; break;
2101            default:
2102               dsp4.waiting4command = 1;
2103               break;
2104         }
2105      }
2106      else
2107      {
2108         dsp4.command = dsp4_byte;
2109         dsp4.half_command = 1;
2110      }
2111   }
2112   else
2113   {
2114      dsp4.parameters[dsp4.in_index] = dsp4_byte;
2115      dsp4.in_index++;
2116   }
20472117
2048        multiplier = DSP4_READ_WORD();
2049        multiplicand = DSP4_READ_WORD();
2118   if (!dsp4.waiting4command && dsp4.in_count == dsp4.in_index)
2119   {
2120      // Actually execute the command
2121      dsp4.waiting4command = 1;
2122      dsp4.out_index = 0;
2123      dsp4.in_index = 0;
20502124
2051        DSP4_Multiply(multiplicand, multiplier, &product);
2125      switch (dsp4.command)
2126      {
2127            // 16-bit multiplication
2128         case 0x0000:
2129         {
2130            INT16 multiplier, multiplicand;
2131            INT32 product;
20522132
2053        DSP4_CLEAR_OUT();
2054        DSP4_WRITE_WORD((UINT16)(product));
2055        DSP4_WRITE_WORD((UINT16)(product >> 16));
2056      }
2057      break;
2133            multiplier = DSP4_READ_WORD();
2134            multiplicand = DSP4_READ_WORD();
20582135
2059      // single-player track projection
2060      case 0x0001:
2061        DSP4_OP01(); break;
2136            dsp4_Multiply(multiplicand, multiplier, &product);
20622137
2063      // single-player selection
2064      case 0x0003:
2065        DSP4_OP03(); break;
2138            DSP4_CLEAR_OUT();
2139            DSP4_WRITE_WORD((UINT16)(product));
2140            DSP4_WRITE_WORD((UINT16)(product >> 16));
2141         }
2142         break;
20662143
2067      // clear OAM
2068      case 0x0005:
2069        DSP4_OP05(); break;
2144         // single-player track projection
2145         case 0x0001:
2146            dsp4_OP01(); break;
20702147
2071      // transfer OAM
2072      case 0x0006:
2073        DSP4_OP06(); break;
2148         // single-player selection
2149         case 0x0003:
2150            dsp4_OP03(); break;
20742151
2075      // single-player track turnoff projection
2076      case 0x0007:
2077        DSP4_OP07(); break;
2152         // clear OAM
2153         case 0x0005:
2154            dsp4_OP05(); break;
20782155
2079      // solid polygon projection
2080      case 0x0008:
2081        DSP4_OP08(); break;
2156         // transfer OAM
2157         case 0x0006:
2158            dsp4_OP06(); break;
20822159
2083      // sprite projection
2084      case 0x0009:
2085        DSP4_OP09(); break;
2160         // single-player track turnoff projection
2161         case 0x0007:
2162            dsp4_OP07(); break;
20862163
2087      // unknown
2088      case 0x000A:
2089      {
2090        INT16 in2a;
2091        INT16 out1a, out2a, out3a, out4a;
2164         // solid polygon projection
2165         case 0x0008:
2166            dsp4_OP08(); break;
20922167
2093        /* in1a = */ DSP4_READ_WORD();
2094        in2a = DSP4_READ_WORD();
2095        /* in3a = */ DSP4_READ_WORD();
2168         // sprite projection
2169         case 0x0009:
2170            dsp4_OP09(); break;
20962171
2097        DSP4_OP0A(in2a, &out2a, &out1a, &out4a, &out3a);
2172         // unknown
2173         case 0x000A:
2174         {
2175            INT16 in2a;
2176            INT16 out1a, out2a, out3a, out4a;
20982177
2099        DSP4_CLEAR_OUT();
2100        DSP4_WRITE_WORD(out1a);
2101        DSP4_WRITE_WORD(out2a);
2102        DSP4_WRITE_WORD(out3a);
2103        DSP4_WRITE_WORD(out4a);
2104      }
2105      break;
2178            /* in1a = */ DSP4_READ_WORD();
2179            in2a = DSP4_READ_WORD();
2180            /* in3a = */ DSP4_READ_WORD();
21062181
2107      // set OAM
2108      case 0x000B:
2109      {
2110        INT16 sp_x = DSP4_READ_WORD();
2111        INT16 sp_y = DSP4_READ_WORD();
2112        INT16 sp_attr = DSP4_READ_WORD();
2113        UINT8 draw = 1;
2182            dsp4_OP0A(in2a, &out2a, &out1a, &out4a, &out3a);
21142183
2115        DSP4_CLEAR_OUT();
2184            DSP4_CLEAR_OUT();
2185            DSP4_WRITE_WORD(out1a);
2186            DSP4_WRITE_WORD(out2a);
2187            DSP4_WRITE_WORD(out3a);
2188            DSP4_WRITE_WORD(out4a);
2189         }
2190         break;
21162191
2117        DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, 0, 1);
2118      }
2119      break;
2192         // set OAM
2193         case 0x000B:
2194         {
2195            INT16 sp_x = DSP4_READ_WORD();
2196            INT16 sp_y = DSP4_READ_WORD();
2197            INT16 sp_attr = DSP4_READ_WORD();
2198            UINT8 draw = 1;
21202199
2121      // multi-player track projection
2122      case 0x000D:
2123        DSP4_OP0D(); break;
2200            DSP4_CLEAR_OUT();
21242201
2125      // multi-player selection
2126      case 0x000E:
2127        DSP4_OP0E(); break;
2202            dsp4_OP0B(&draw, sp_x, sp_y, sp_attr, 0, 1);
2203         }
2204         break;
21282205
2129      // single-player track projection with lighting
2130      case 0x000F:
2131        DSP4_OP0F(); break;
2206         // multi-player track projection
2207         case 0x000D:
2208            dsp4_OP0D(); break;
21322209
2133      // single-player track turnoff projection with lighting
2134      case 0x0010:
2135        DSP4_OP10(); break;
2210         // multi-player selection
2211         case 0x000E:
2212            dsp4_OP0E(); break;
21362213
2137      // unknown: horizontal mapping command
2138      case 0x0011:
2139      {
2140        INT16 a, b, c, d, m;
2214         // single-player track projection with lighting
2215         case 0x000F:
2216            dsp4_OP0F(); break;
21412217
2218         // single-player track turnoff projection with lighting
2219         case 0x0010:
2220            dsp4_OP10(); break;
21422221
2143        d = DSP4_READ_WORD();
2144        c = DSP4_READ_WORD();
2145        b = DSP4_READ_WORD();
2146        a = DSP4_READ_WORD();
2222         // unknown: horizontal mapping command
2223         case 0x0011:
2224         {
2225            INT16 a, b, c, d, m;
21472226
2148        DSP4_OP11(a, b, c, d, &m);
21492227
2150        DSP4_CLEAR_OUT();
2151        DSP4_WRITE_WORD(m);
2228            d = DSP4_READ_WORD();
2229            c = DSP4_READ_WORD();
2230            b = DSP4_READ_WORD();
2231            a = DSP4_READ_WORD();
21522232
2153        break;
2154      }
2233            dsp4_OP11(a, b, c, d, &m);
21552234
2156      default:
2157        break;
2158    }
2159  }
2235            DSP4_CLEAR_OUT();
2236            DSP4_WRITE_WORD(m);
2237
2238            break;
2239         }
2240
2241         default:
2242            break;
2243      }
2244   }
21602245}
21612246
2162static UINT8 DSP4_read( void )
2247static UINT8 dsp4_read( void )
21632248{
2164  UINT8 value;
2249   UINT8 value;
21652250
2166  if (DSP4.out_count)
2167  {
2168    value = (UINT8) DSP4.output[DSP4.out_index&0x1FF];
2169    DSP4.out_index++;
2170    if (DSP4.out_count == DSP4.out_index)
2171      DSP4.out_count = 0;
2172  }
2173  else
2174  {
2175    value = 0xff;
2176  }
2251   if (dsp4.out_count)
2252   {
2253      value = (UINT8) dsp4.output[dsp4.out_index&0x1FF];
2254      dsp4.out_index++;
2255      if (dsp4.out_count == dsp4.out_index)
2256         dsp4.out_count = 0;
2257   }
2258   else
2259   {
2260      value = 0xff;
2261   }
21772262
2178  return value;
2263   return value;
21792264}
src/mame/machine/snesdsp4.h
r7621r7622
55#define TRUE 1
66
77
8struct DSP4_t
8struct dsp4_t
99{
10  UINT8 waiting4command;
11  UINT8 half_command;
12  UINT16 command;
13  UINT32 in_count;
14  UINT32 in_index;
15  UINT32 out_count;
16  UINT32 out_index;
17  UINT8 parameters[512];
18  UINT8 output[512];
10   UINT8 waiting4command;
11   UINT8 half_command;
12   UINT16 command;
13   UINT32 in_count;
14   UINT32 in_index;
15   UINT32 out_count;
16   UINT32 out_index;
17   UINT8 parameters[512];
18   UINT8 output[512];
1919};
2020
21struct DSP4_vars_t
21struct dsp4_vars_t
2222{
23  // op control
24  INT8 DSP4_Logic;            // controls op flow
23   // op control
24   INT8 Logic;            // controls op flow
2525
2626
27  // projection format
28  INT16 lcv;                  // loop-control variable
29  INT16 distance;             // z-position INTo virtual world
30  INT16 raster;               // current raster line
31  INT16 segments;             // number of raster lines drawn
27   // projection format
28   INT16 lcv;                  // loop-control variable
29   INT16 distance;             // z-position into virtual world
30   INT16 raster;               // current raster line
31   INT16 segments;             // number of raster lines drawn
3232
33  // 1.15.16 or 1.15.0 [sign, INTeger, fraction]
34  INT32 world_x;              // line of x-projection in world
35  INT32 world_y;              // line of y-projection in world
36  INT32 world_dx;             // projection line x-delta
37  INT32 world_dy;             // projection line y-delta
38  INT16 world_ddx;            // x-delta increment
39  INT16 world_ddy;            // y-delta increment
40  INT32 world_xenv;           // world x-shaping factor
41  INT16 world_yofs;           // world y-vertical scroll
33   // 1.15.16 or 1.15.0 [sign, INTeger, fraction]
34   INT32 world_x;              // line of x-projection in world
35   INT32 world_y;              // line of y-projection in world
36   INT32 world_dx;             // projection line x-delta
37   INT32 world_dy;             // projection line y-delta
38   INT16 world_ddx;            // x-delta increment
39   INT16 world_ddy;            // y-delta increment
40   INT32 world_xenv;           // world x-shaping factor
41   INT16 world_yofs;           // world y-vertical scroll
4242
43  INT16 view_x1;              // current viewer-x
44  INT16 view_y1;              // current viewer-y
45  INT16 view_x2;              // future viewer-x
46  INT16 view_y2;              // future viewer-y
47  INT16 view_dx;              // view x-delta factor
48  INT16 view_dy;              // view y-delta factor
49  INT16 view_xofs1;           // current viewer x-vertical scroll
50  INT16 view_yofs1;           // current viewer y-vertical scroll
51  INT16 view_xofs2;           // future viewer x-vertical scroll
52  INT16 view_yofs2;           // future viewer y-vertical scroll
53  INT16 view_yofsenv;         // y-scroll shaping factor
54  INT16 view_turnoff_x;       // road turnoff data
55  INT16 view_turnoff_dx;      // road turnoff delta factor
43   INT16 view_x1;              // current viewer-x
44   INT16 view_y1;              // current viewer-y
45   INT16 view_x2;              // future viewer-x
46   INT16 view_y2;              // future viewer-y
47   INT16 view_dx;              // view x-delta factor
48   INT16 view_dy;              // view y-delta factor
49   INT16 view_xofs1;           // current viewer x-vertical scroll
50   INT16 view_yofs1;           // current viewer y-vertical scroll
51   INT16 view_xofs2;           // future viewer x-vertical scroll
52   INT16 view_yofs2;           // future viewer y-vertical scroll
53   INT16 view_yofsenv;         // y-scroll shaping factor
54   INT16 view_turnoff_x;       // road turnoff data
55   INT16 view_turnoff_dx;      // road turnoff delta factor
5656
5757
58  // drawing area
58   // drawing area
5959
60  INT16 viewport_cx;          // x-center of viewport window
61  INT16 viewport_cy;          // y-center of render window
62  INT16 viewport_left;        // x-left of viewport
63  INT16 viewport_right;       // x-right of viewport
64  INT16 viewport_top;         // y-top of viewport
65  INT16 viewport_bottom;      // y-bottom of viewport
60   INT16 viewport_cx;          // x-center of viewport window
61   INT16 viewport_cy;          // y-center of render window
62   INT16 viewport_left;        // x-left of viewport
63   INT16 viewport_right;       // x-right of viewport
64   INT16 viewport_top;         // y-top of viewport
65   INT16 viewport_bottom;      // y-bottom of viewport
6666
6767
68  // sprite structure
68   // sprite structure
6969
70  INT16 sprite_x;             // projected x-pos of sprite
71  INT16 sprite_y;             // projected y-pos of sprite
72  INT16 sprite_attr;          // obj attributes
73  UINT8 sprite_size;          // sprite size: 8x8 or 16x16
74  INT16 sprite_clipy;         // visible line to clip pixels off
75  INT16 sprite_count;
70   INT16 sprite_x;             // projected x-pos of sprite
71   INT16 sprite_y;             // projected y-pos of sprite
72   INT16 sprite_attr;          // obj attributes
73   UINT8 sprite_size;          // sprite size: 8x8 or 16x16
74   INT16 sprite_clipy;         // visible line to clip pixels off
75   INT16 sprite_count;
7676
77  // generic projection variables designed for
78  // two solid polygons + two polygon sides
77   // generic projection variables designed for
78   // two solid polygons + two polygon sides
7979
80  INT16 poly_clipLf[2][2];    // left clip boundary
81  INT16 poly_clipRt[2][2];    // right clip boundary
82  INT16 poly_ptr[2][2];       // HDMA structure poINTers
83  INT16 poly_raster[2][2];    // current raster line below horizon
84  INT16 poly_top[2][2];       // top clip boundary
85  INT16 poly_bottom[2][2];    // bottom clip boundary
86  INT16 poly_cx[2][2];        // center for left/right poINTs
87  INT16 poly_start[2];        // current projection poINTs
88  INT16 poly_plane[2];        // previous z-plane distance
80   INT16 poly_clipLf[2][2];    // left clip boundary
81   INT16 poly_clipRt[2][2];    // right clip boundary
82   INT16 poly_ptr[2][2];       // HDMA structure pointers
83   INT16 poly_raster[2][2];    // current raster line below horizon
84   INT16 poly_top[2][2];       // top clip boundary
85   INT16 poly_bottom[2][2];    // bottom clip boundary
86   INT16 poly_cx[2][2];        // center for left/right points
87   INT16 poly_start[2];        // current projection points
88   INT16 poly_plane[2];        // previous z-plane distance
8989
9090
91  // OAM
92  INT16 OAM_attr[16];         // OAM (size,MSB) data
93  INT16 OAM_index;            // index INTo OAM table
94  INT16 OAM_bits;             // offset INTo OAM table
91   // OAM
92   INT16 OAM_attr[16];         // OAM (size,MSB) data
93   INT16 OAM_index;            // index into OAM table
94   INT16 OAM_bits;             // offset into OAM table
9595
96  INT16 OAM_RowMax;           // maximum number of tiles per 8 aligned pixels (row)
97  INT16 OAM_Row[32];          // current number of tiles per row
96   INT16 OAM_RowMax;           // maximum number of tiles per 8 aligned pixels (row)
97   INT16 OAM_Row[32];          // current number of tiles per row
9898};
9999
100100#endif
src/mame/machine/snes.c
r7621r7622
365365   {
366366      if (offset == 0x2800 || offset == 0x2801)
367367      {
368         return srtc_mmio_read(space->machine, offset);
368         return srtc_read(space->machine, offset);
369369      }
370370   }
371371   else if (snes_has_addon_chip == HAS_SDD1)
r7621r7622
731731   {
732732      if (offset == 0x2800 || offset == 0x2801)
733733      {
734         srtc_mmio_write(space->machine, offset, data);
734         srtc_write(space->machine, offset, data);
735735         return;
736736      }
737737   }
r7621r7622
14431443      else if (snes_has_addon_chip == HAS_OBC1)
14441444         value = obc1_read(space, offset);
14451445      else if ((snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000))
1446         value = (address < 0x7000) ? DSP2_read() : 0x00;
1446         value = (address < 0x7000) ? dsp2_read() : 0x00;
14471447      else if ((snes_cart.mode == SNES_MODE_21) && (snes_has_addon_chip == HAS_DSP1) && (offset < 0x100000))
1448         value = (address < 0x7000) ? DSP1_getDr() : DSP1_getSr();
1448         value = (address < 0x7000) ? dsp1_get_dr() : dsp1_get_sr();
14491449      else if (snes_has_addon_chip == HAS_CX4)
14501450         value = CX4_read(address - 0x6000);
14511451      else if (snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC)
r7621r7622
14591459      }
14601460   }
14611461   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000))
1462      value = (address < 0xc000) ? DSP1_getDr() : DSP1_getSr();
1462      value = (address < 0xc000) ? dsp1_get_dr() : dsp1_get_sr();
14631463   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000))
1464      value = (address < 0xc000) ? DSP2_read() : 0x00;
1464      value = (address < 0xc000) ? dsp2_read() : 0x00;
14651465   else if ((snes_has_addon_chip == HAS_DSP3) && (offset >= 0x200000))
1466      value = DSP3_read(address);
1466      value = dsp3_read(address);
14671467   else
14681468      value = snes_ram[offset];
14691469
r7621r7622
14851485      if (snes_has_addon_chip == HAS_OBC1)
14861486         value = obc1_read (space, offset);
14871487      else if (snes_has_addon_chip == HAS_DSP2)
1488         value = (address < 0x7000) ? DSP2_read() : 0x00;
1488         value = (address < 0x7000) ? dsp2_read() : 0x00;
14891489      else if (snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC)
14901490      {
14911491         value = snes_ram[0x306000 + (offset & 0x1fff)];
r7621r7622
15041504   }
15051505   /* some dsp1 games use these banks 0x30 to 0x3f at address 0x8000 */
15061506   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1))
1507      value = (address < 0xc000) ? DSP1_getDr() : DSP1_getSr();
1507      value = (address < 0xc000) ? dsp1_get_dr() : dsp1_get_sr();
15081508   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2))
1509      value = (address < 0xc000) ? DSP2_read() : 0x00;
1509      value = (address < 0xc000) ? dsp2_read() : 0x00;
15101510   else if (snes_has_addon_chip == HAS_DSP3)
1511      value = DSP3_read(address);
1511      value = dsp3_read(address);
15121512   else if (snes_has_addon_chip == HAS_DSP4)
1513      value = (address < 0xc000) ? DSP4_read() : 0x80;
1513      value = (address < 0xc000) ? dsp4_read() : 0x80;
15141514   else
15151515      value = snes_ram[0x300000 + offset];
15161516
r7621r7622
15651565         value = snes_ram[0x600000 + offset];
15661566      /* some other dsp1 games use these banks 0x60 to 0x6f at address 0x0000 */
15671567      else if (snes_has_addon_chip == HAS_DSP1)
1568         value = (address >= 0x4000) ? DSP1_getSr() : DSP1_getDr();
1568         value = (address >= 0x4000) ? dsp1_get_sr() : dsp1_get_dr();
15691569      else
15701570      {
15711571         logerror( "snes_r_bank4: Unmapped external chip read: %04x\n", address );
r7621r7622
16451645      }
16461646   }
16471647   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000))
1648      value = (address < 0xc000) ? DSP1_getDr() : DSP1_getSr();
1648      value = (address < 0xc000) ? dsp1_get_dr() : dsp1_get_sr();
16491649   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000))
1650      value = (address < 0xc000) ? DSP2_read() : 0x00;
1650      value = (address < 0xc000) ? dsp2_read() : 0x00;
16511651   else if ((snes_has_addon_chip == HAS_DSP3) && (offset >= 0x200000))
1652      value = DSP3_read(address);
1652      value = dsp3_read(address);
16531653   else if ((snes_has_addon_chip == HAS_DSP4) && (offset >= 0x300000))
1654      value = (address < 0xc000) ? DSP4_read() : 0x80;
1654      value = (address < 0xc000) ? dsp4_read() : 0x80;
16551655   else
16561656      value = snes_ram[0x800000 + offset];
16571657
r7621r7622
17091709      else if (snes_has_addon_chip == HAS_OBC1)
17101710         obc1_write(space, offset, data);
17111711      else if ((snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000))
1712         DSP2_write(data);
1712         dsp2_write(data);
17131713      else if ((snes_cart.mode == SNES_MODE_21) && (snes_has_addon_chip == HAS_DSP1) && (offset < 0x100000))
1714         DSP1_setDr(data);
1714         dsp1_set_dr(data);
17151715      else if (snes_has_addon_chip == HAS_CX4)
17161716         CX4_write(space->machine, address - 0x6000, data);
17171717      else if (snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC)
r7621r7622
17221722         logerror( "snes_w_bank1: Attempt to write to reserved address: %x = %02x\n", offset, data );
17231723   }
17241724   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000))
1725      DSP1_setDr(data);
1725      dsp1_set_dr(data);
17261726   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000) && (address < 0xc000))
1727      DSP2_write(data);
1727      dsp2_write(data);
17281728   else if ((snes_has_addon_chip == HAS_DSP3) && (offset >= 0x200000))
1729      DSP3_write(address, data);
1729      dsp3_write(address, data);
17301730   else
17311731      logerror( "Attempt to write to ROM address: %X\n", offset );
17321732}
r7621r7622
17451745      if (snes_has_addon_chip == HAS_OBC1)
17461746         obc1_write(space, offset, data);
17471747      else if (snes_has_addon_chip == HAS_DSP2)
1748         DSP2_write(data);
1748         dsp2_write(data);
17491749      else if (snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC)
17501750      {
17511751         snes_ram[0x306000 + (offset & 0x1fff)] = data;
r7621r7622
17621762   }
17631763   /* some dsp1 games use these banks 0x30 to 0x3f at address 0x8000 */
17641764   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1))
1765      DSP1_setDr(data);
1765      dsp1_set_dr(data);
17661766   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (address < 0xc000))
1767      DSP2_write(data);
1767      dsp2_write(data);
17681768   else if (snes_has_addon_chip == HAS_DSP3)
1769      DSP3_write(address, data);
1769      dsp3_write(address, data);
17701770   else if ((snes_has_addon_chip == HAS_DSP4) && (address < 0xc000))
1771      DSP4_write(data);
1771      dsp4_write(data);
17721772   else
17731773      logerror("Attempt to write to ROM address: %X\n", offset + 0x300000);
17741774}
r7621r7622
17951795      }
17961796      else if (snes_has_addon_chip == HAS_DSP1)
17971797      {
1798         DSP1_setDr(data);
1798         dsp1_set_dr(data);
17991799      }
18001800      else
18011801      {
r7621r7622
18801880      }
18811881   }
18821882   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000))
1883      DSP1_setDr(data);
1883      dsp1_set_dr(data);
18841884   else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000) && (address < 0xc000))
1885      DSP2_write(data);
1885      dsp2_write(data);
18861886   else if ((snes_has_addon_chip == HAS_DSP3) && (offset >= 0x200000))
1887      DSP3_write(address, data);
1887      dsp3_write(address, data);
18881888   else if ((snes_has_addon_chip == HAS_DSP4) && (offset >= 0x300000) && (address < 0xc000))
1889      DSP4_write(data);
1889      dsp4_write(data);
18901890   else if (snes_has_addon_chip == HAS_SUPERFX && state->superfx != NULL)
18911891      logerror( "snes_w_bank6 hit (ROM) in Super FX mode, please fix me\n" );
18921892   else
r7621r7622
21032103   switch (snes_has_addon_chip)
21042104   {
21052105      case HAS_DSP1:
2106         DSP1_reset(machine);
2106         dsp1_init(machine);
21072107         break;
21082108
21092109      case HAS_DSP2:
2110         DSP2_reset();
2110         dsp2_init(machine);
21112111         break;
21122112
21132113      case HAS_DSP3:
2114         InitDSP3(machine);
2114         dsp3_init(machine);
21152115         break;
21162116
21172117      case HAS_DSP4:
2118         InitDSP4();
2118         dsp4_init(machine);
21192119         break;
21202120
21212121      case HAS_RTC:
2122         srtc_reset(machine);
2122         srtc_init(machine);
21232123         break;
21242124
21252125      case HAS_SDD1:
r7621r7622
21272127         break;
21282128
21292129      case HAS_OBC1:
2130         obc1_init();
2130         obc1_init(machine);
21312131         break;
21322132
21332133      case HAS_ST010:
src/mame/machine/snesst10.c
r7621r7622
1515
1616***************************************************************************/
1717
18typedef struct
18struct _snes_st010_state
1919{
2020   INT16 x1, y1, quadrant, theta, o1;
2121   UINT8 *ram;
22} _snes_st010_t;
22};
2323
24static _snes_st010_t snes_st010;
24static _snes_st010_state st010_state;
2525
2626static const INT16 st010_sin_table[256] = {
2727   0x0000,  0x0324,  0x0648,  0x096a,  0x0c8c,  0x0fab,  0x12c8,  0x15e2,
r7621r7622
163163
164164static UINT8 st010_readb( UINT16 address )
165165{
166   return snes_st010.ram[address & 0xfff];
166   return st010_state.ram[address & 0xfff];
167167}
168168
169169static UINT16 st010_readw( UINT16 address )
170170{
171   return (st010_readb(address + 0) <<  0) |
172         (st010_readb(address + 1) <<  8);
171   return (st010_readb(address + 0) <<  0) | (st010_readb(address + 1) <<  8);
173172}
174173
175174static UINT32 st010_readd( UINT16 address )
r7621r7622
182181
183182static void st010_writeb( UINT16 address, UINT8 data )
184183{
185   snes_st010.ram[address & 0xfff] = data;
184   st010_state.ram[address & 0xfff] = data;
186185}
187186
188187static void st010_writew( UINT16 address, UINT16 data )
r7621r7622
201200
202201//
203202
204static void st010_op_01_do_work(INT16 x0, INT16 y0) {
205  if((x0 < 0) && (y0 < 0)) {
206    snes_st010.x1 = -x0;
207    snes_st010.y1 = -y0;
208    snes_st010.quadrant = -0x8000;
209  } else if(x0 < 0) {
210    snes_st010.x1 = y0;
211    snes_st010.y1 = -x0;
212    snes_st010.quadrant = -0x4000;
213  } else if(y0 < 0) {
214    snes_st010.x1 = -y0;
215    snes_st010.y1 = x0;
216    snes_st010.quadrant = 0x4000;
217  } else {
218    snes_st010.x1 = x0;
219    snes_st010.y1 = y0;
220    snes_st010.quadrant = 0x0000;
221  }
203static void st010_op_01_do_work( INT16 x0, INT16 y0 )
204{
205   if ((x0 < 0) && (y0 < 0))
206   {
207      st010_state.x1 = -x0;
208      st010_state.y1 = -y0;
209      st010_state.quadrant = -0x8000;
210   }
211   else if (x0 < 0)
212   {
213      st010_state.x1 = y0;
214      st010_state.y1 = -x0;
215      st010_state.quadrant = -0x4000;
216   }
217   else if (y0 < 0)
218   {
219      st010_state.x1 = -y0;
220      st010_state.y1 = x0;
221      st010_state.quadrant = 0x4000;
222   }
223   else
224   {
225      st010_state.x1 = x0;
226      st010_state.y1 = y0;
227      st010_state.quadrant = 0x0000;
228   }
222229
223  while((snes_st010.x1 > 0x1f) || (snes_st010.y1 > 0x1f)) {
224    if(snes_st010.x1 > 1) { snes_st010.x1 >>= 1; }
225    if(snes_st010.y1 > 1) { snes_st010.y1 >>= 1; }
226  }
230   while((st010_state.x1 > 0x1f) || (st010_state.y1 > 0x1f))
231   {
232      if (st010_state.x1 > 1)
233         st010_state.x1 >>= 1;
234      if (st010_state.y1 > 1)
235         st010_state.y1 >>= 1;
236   }
227237
228  if(snes_st010.y1 == 0) { snes_st010.quadrant += 0x4000; }
238   if (st010_state.y1 == 0)
239      st010_state.quadrant += 0x4000;
229240
230  snes_st010.theta = (st010_arctan[snes_st010.y1][snes_st010.x1] << 8) ^ snes_st010.quadrant;
241   st010_state.theta = (st010_arctan[st010_state.y1][st010_state.x1] << 8) ^ st010_state.quadrant;
231242}
232243
233244//
234245
235static void st010_op_01( void ) {
236  INT16 x0 = st010_readw(0x0000);
237  INT16 y0 = st010_readw(0x0002);
246static void st010_op_01( void )
247{
248   INT16 x0 = st010_readw(0x0000);
249   INT16 y0 = st010_readw(0x0002);
238250
239  st010_op_01_do_work(x0, y0);
251   st010_op_01_do_work(x0, y0);
240252
241  st010_writew(0x0000, snes_st010.x1);
242  st010_writew(0x0002, snes_st010.y1);
243  st010_writew(0x0004, snes_st010.quadrant);
244//st010_writew(0x0006, y0);  //Overload's docs note this write occurs, SNES9x disagrees
245  st010_writew(0x0010, snes_st010.theta);
253   st010_writew(0x0000, st010_state.x1);
254   st010_writew(0x0002, st010_state.y1);
255   st010_writew(0x0004, st010_state.quadrant);
256   //st010_writew(0x0006, y0);  //Overload's docs note this write occurs, SNES9x disagrees
257   st010_writew(0x0010, st010_state.theta);
246258}
247259
248static void st010_op_02( void ) {
249  INT16 positions = st010_readw(0x0024);
250  UINT16 *places  = (UINT16*)(snes_st010.ram + 0x0040);
251  UINT16 *drivers = (UINT16*)(snes_st010.ram + 0x0080);
260static void st010_op_02( void )
261{
262   INT16 positions = st010_readw(0x0024);
263   UINT16 *places  = (UINT16*)(st010_state.ram + 0x0040);
264   UINT16 *drivers = (UINT16*)(st010_state.ram + 0x0080);
252265
253  UINT8 sorted;
254  UINT16 temp;
255  int i;
256  if(positions > 1) {
257    do {
258      sorted = 1;
259      for(i = 0; i < positions - 1; i++) {
260        if(places[i] < places[i + 1]) {
261          temp = places[i + 1];
262          places[i + 1] = places[i];
263          places[i] = temp;
266   UINT8 sorted;
267   UINT16 temp;
268   int i;
264269
265          temp = drivers[i + 1];
266          drivers[i + 1] = drivers[i];
267          drivers[i] = temp;
270   if (positions > 1)
271   {
272      do
273      {
274         sorted = 1;
275         for (i = 0; i < positions - 1; i++)
276         {
277            if (places[i] < places[i + 1])
278            {
279               temp = places[i + 1];
280               places[i + 1] = places[i];
281               places[i] = temp;
268282
269          sorted = 0;
270        }
271      }
272      positions--;
273    } while(!sorted);
274  }
283               temp = drivers[i + 1];
284               drivers[i + 1] = drivers[i];
285               drivers[i] = temp;
286
287               sorted = 0;
288            }
289         }
290         positions--;
291      } while(!sorted);
292   }
275293}
276294
277static void st010_op_03( void ) {
278  INT16 x0 = st010_readw(0x0000);
279  INT16 y0 = st010_readw(0x0002);
280  INT16 multiplier = st010_readw(0x0004);
281  INT32 x1, y1;
295static void st010_op_03( void )
296{
297   INT16 x0 = st010_readw(0x0000);
298   INT16 y0 = st010_readw(0x0002);
299   INT16 multiplier = st010_readw(0x0004);
300   INT32 x1, y1;
282301
283  x1 = x0 * multiplier << 1;
284  y1 = y0 * multiplier << 1;
302   x1 = x0 * multiplier << 1;
303   y1 = y0 * multiplier << 1;
285304
286  st010_writed(0x0010, x1);
287  st010_writed(0x0014, y1);
305   st010_writed(0x0010, x1);
306   st010_writed(0x0014, y1);
288307}
289308
290static void st010_op_04( void ) {
291  INT16 x = st010_readw(0x0000);
292  INT16 y = st010_readw(0x0002);
293  INT16 square;
294  //calculate the vector length of (x,y)
295  square = sqrt((double)(y * y + x * x));
309static void st010_op_04( void )
310{
311   INT16 x = st010_readw(0x0000);
312   INT16 y = st010_readw(0x0002);
313   INT16 square;
314   //calculate the vector length of (x,y)
315   square = sqrt((double)(y * y + x * x));
296316
297  st010_writew(0x0010, square);
317   st010_writew(0x0010, square);
298318}
299319
300320// same as op_01_do_work, but we are only interested in the angle!
301static void st010_op_05_do_work(INT16 x0, INT16 y0) {
302  INT16 x1, y1, quadrant;
303  if((x0 < 0) && (y0 < 0)) {
304    x1 = -x0;
305    y1 = -y0;
306    quadrant = -0x8000;
307  } else if(x0 < 0) {
308    x1 = y0;
309    y1 = -x0;
310    quadrant = -0x4000;
311  } else if(y0 < 0) {
312    x1 = -y0;
313    y1 = x0;
314    quadrant = 0x4000;
315  } else {
316    x1 = x0;
317    y1 = y0;
318    quadrant = 0x0000;
319  }
321static void st010_op_05_do_work( INT16 x0, INT16 y0 )
322{
323   INT16 x1, y1, quadrant;
324   if ((x0 < 0) && (y0 < 0))
325   {
326      x1 = -x0;
327      y1 = -y0;
328      quadrant = -0x8000;
329   }
330   else if (x0 < 0)
331   {
332      x1 = y0;
333      y1 = -x0;
334      quadrant = -0x4000;
335   }
336   else if (y0 < 0)
337   {
338      x1 = -y0;
339      y1 = x0;
340      quadrant = 0x4000;
341   }
342   else
343   {
344      x1 = x0;
345      y1 = y0;
346      quadrant = 0x0000;
347   }
320348
321  while((x1 > 0x1f) || (y1 > 0x1f)) {
322    if(x1 > 1) { x1 >>= 1; }
323    if(y1 > 1) { y1 >>= 1; }
324  }
349   while((x1 > 0x1f) || (y1 > 0x1f))
350   {
351      if (x1 > 1)
352         x1 >>= 1;
353      if (y1 > 1)
354         y1 >>= 1;
355   }
325356
326  if(y1 == 0) { quadrant += 0x4000; }
357   if (y1 == 0)
358      quadrant += 0x4000;
327359
328  snes_st010.o1 = (st010_arctan[y1][x1] << 8) ^ quadrant;
360   st010_state.o1 = (st010_arctan[y1][x1] << 8) ^ quadrant;
329361}
330362
331static void st010_op_05( void ) {
332  INT32 dx, dy;
333  UINT16 o1 = 0;
334  UINT8 wrap = 0;
363static void st010_op_05( void )
364{
365   INT32 dx, dy;
366   UINT16 o1 = 0;
367   UINT8 wrap = 0;
335368
336  //target (x,y) coordinates
337  INT16 ypos_max = st010_readw(0x00c0);
338  INT16 xpos_max = st010_readw(0x00c2);
369   //target (x,y) coordinates
370   INT16 ypos_max = st010_readw(0x00c0);
371   INT16 xpos_max = st010_readw(0x00c2);
339372
340  //current coordinates and direction
341  INT32 ypos = st010_readd(0x00c4);
342  INT32 xpos = st010_readd(0x00c8);
343  UINT16 rot = st010_readw(0x00cc);
373   //current coordinates and direction
374   INT32 ypos = st010_readd(0x00c4);
375   INT32 xpos = st010_readd(0x00c8);
376   UINT16 rot = st010_readw(0x00cc);
344377
345  //physics
346  UINT16 speed = st010_readw(0x00d4);
347  UINT16 accel = st010_readw(0x00d6);
348  UINT16 speed_max = st010_readw(0x00d8);
349  UINT16 old_speed;
378   //physics
379   UINT16 speed = st010_readw(0x00d4);
380   UINT16 accel = st010_readw(0x00d6);
381   UINT16 speed_max = st010_readw(0x00d8);
382   UINT16 old_speed;
350383
351  //special condition acknowledgement
352  INT16 system = st010_readw(0x00da);
353  INT16 flags = st010_readw(0x00dc);
384   //special condition acknowledgement
385   INT16 system = st010_readw(0x00da);
386   INT16 flags = st010_readw(0x00dc);
354387
355  //new target coordinates
356  INT16 ypos_new = st010_readw(0x00de);
357  INT16 xpos_new = st010_readw(0x00e0);
388   //new target coordinates
389   INT16 ypos_new = st010_readw(0x00de);
390   INT16 xpos_new = st010_readw(0x00e0);
358391
359  //mask upper bit
360  xpos_new &= 0x7fff;
392   //mask upper bit
393   xpos_new &= 0x7fff;
361394
362  //get the current distance
363  dx = xpos_max - (xpos >> 16);
364  dy = ypos_max - (ypos >> 16);
395   //get the current distance
396   dx = xpos_max - (xpos >> 16);
397   dy = ypos_max - (ypos >> 16);
365398
366  //quirk: clear and move in9
367  st010_writew(0x00d2, 0xffff);
368  st010_writew(0x00da, 0x0000);
399   //quirk: clear and move in9
400   st010_writew(0x00d2, 0xffff);
401   st010_writew(0x00da, 0x0000);
369402
370  //grab the target angle
371  st010_op_05_do_work(dy, dx);
372  o1 = (UINT16)snes_st010.o1;
403   //grab the target angle
404   st010_op_05_do_work(dy, dx);
405   o1 = (UINT16)st010_state.o1;
373406
374  //check for wrapping
375  if(abs(o1 - rot) > 0x8000) {
376    o1 += 0x8000;
377    rot += 0x8000;
378    wrap = 1;
379  }
407   //check for wrapping
408   if (abs(o1 - rot) > 0x8000)
409   {
410      o1 += 0x8000;
411      rot += 0x8000;
412      wrap = 1;
413   }
380414
381  old_speed = speed;
415   old_speed = speed;
382416
383  //special case
384  if(abs(o1 - rot) == 0x8000) {
385    speed = 0x100;
386  }
417   //special case
418   if (abs(o1 - rot) == 0x8000)
419   {
420      speed = 0x100;
421   }
422   //slow down for sharp curves
423   else if (abs(o1 - rot) >= 0x1000)
424   {
425      UINT32 slow = abs(o1 - rot);
426      slow >>= 4;  //scaling
427      speed -= slow;
428   }
429   //otherwise accelerate
430   else
431   {
432      speed += accel;
433      if (speed > speed_max)
434         speed = speed_max;  //clip speed
435   }
387436
388  //slow down for sharp curves
389  else if(abs(o1 - rot) >= 0x1000) {
390  UINT32 slow = abs(o1 - rot);
391    slow >>= 4;  //scaling
392    speed -= slow;
393  }
437   //prevent negative/positive overflow
438   if (abs(old_speed - speed) > 0x8000)
439   {
440      if (old_speed < speed)
441         speed = 0;
442      else
443         speed = 0xff00;
444   }
394445
395  //otherwise accelerate
396  else {
397    speed += accel;
398    if(speed > speed_max) {
399      speed = speed_max;  //clip speed
400    }
401  }
446   //adjust direction by so many degrees
447   //be careful of negative adjustments
448   if ((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80))
449   {
450      if (o1 < rot)
451         rot -= 0x280;
452      else if (o1 > rot)
453         rot += 0x280;
454   }
402455
403  //prevent negative/positive overflow
404  if(abs(old_speed - speed) > 0x8000) {
405    if(old_speed < speed) { speed = 0; }
406    else speed = 0xff00;
407  }
456   //turn off wrapping
457   if (wrap)
458      rot -= 0x8000;
408459
409  //adjust direction by so many degrees
410  //be careful of negative adjustments
411  if((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) {
412    if(o1 < rot) { rot -= 0x280; }
413    else if(o1 > rot) { rot += 0x280; }
414  }
460   //now check the distances (store for later)
461   dx = (xpos_max << 16) - xpos;
462   dy = (ypos_max << 16) - ypos;
463   dx >>= 16;
464   dy >>= 16;
415465
416  //turn off wrapping
417  if(wrap) { rot -= 0x8000; }
466   //if we're in so many units of the target, signal it
467   if ((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128)))
468   {
469      //announce our new destination and flag it
470      xpos_max = xpos_new & 0x7fff;
471      ypos_max = ypos_new;
472      flags |= 0x08;
473   }
418474
419  //now check the distances (store for later)
420  dx = (xpos_max << 16) - xpos;
421  dy = (ypos_max << 16) - ypos;
422  dx >>= 16;
423  dy >>= 16;
475   //update position
476   xpos -= (st010_cos(rot) * 0x400 >> 15) * (speed >> 8) << 1;
477   ypos -= (st010_sin(rot) * 0x400 >> 15) * (speed >> 8) << 1;
424478
425  //if we're in so many units of the target, signal it
426  if((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) {
427    //announce our new destination and flag it
428    xpos_max = xpos_new & 0x7fff;
429    ypos_max = ypos_new;
430    flags |= 0x08;
431  }
479   //quirk: mask upper byte
480   xpos &= 0x1fffffff;
481   ypos &= 0x1fffffff;
432482
433  //update position
434  xpos -= (st010_cos(rot) * 0x400 >> 15) * (speed >> 8) << 1;
435  ypos -= (st010_sin(rot) * 0x400 >> 15) * (speed >> 8) << 1;
436
437  //quirk: mask upper byte
438  xpos &= 0x1fffffff;
439  ypos &= 0x1fffffff;
440
441  st010_writew(0x00c0, ypos_max);
442  st010_writew(0x00c2, xpos_max);
443  st010_writed(0x00c4, ypos);
444  st010_writed(0x00c8, xpos);
445  st010_writew(0x00cc, rot);
446  st010_writew(0x00d4, speed);
447  st010_writew(0x00dc, flags);
483   st010_writew(0x00c0, ypos_max);
484   st010_writew(0x00c2, xpos_max);
485   st010_writed(0x00c4, ypos);
486   st010_writed(0x00c8, xpos);
487   st010_writew(0x00cc, rot);
488   st010_writew(0x00d4, speed);
489   st010_writew(0x00dc, flags);
448490}
449491
450static void st010_op_06( void ) {
451  INT16 multiplicand = st010_readw(0x0000);
452  INT16 multiplier = st010_readw(0x0002);
453  INT32 product;
492static void st010_op_06( void )
493{
494   INT16 multiplicand = st010_readw(0x0000);
495   INT16 multiplier = st010_readw(0x0002);
496   INT32 product;
454497
455  product = multiplicand * multiplier << 1;
498   product = multiplicand * multiplier << 1;
456499
457  st010_writed(0x0010, product);
500   st010_writed(0x0010, product);
458501}
459502
460static void st010_op_07( void ) {
461  INT16 theta = st010_readw(0x0000);
503static void st010_op_07( void )
504{
505   INT16 theta = st010_readw(0x0000);
462506
463  INT16 data;
464  int i, offset;
465  for(i = 0, offset = 0; i < 176; i++) {
466    data = st010_mode7_scale[i] * st010_cos(theta) >> 15;
467    st010_writew(0x00f0 + offset, data);
468    st010_writew(0x0510 + offset, data);
507   INT16 data;
508   int i, offset;
509   for (i = 0, offset = 0; i < 176; i++)
510   {
511      data = st010_mode7_scale[i] * st010_cos(theta) >> 15;
512      st010_writew(0x00f0 + offset, data);
513      st010_writew(0x0510 + offset, data);
469514
470    data = st010_mode7_scale[i] * st010_sin(theta) >> 15;
471    st010_writew(0x0250 + offset, data);
472    if(data) { data = ~data; }
473    st010_writew(0x03b0 + offset, data);
515      data = st010_mode7_scale[i] * st010_sin(theta) >> 15;
516      st010_writew(0x0250 + offset, data);
517      if (data)
518         data = ~data;
474519
475    offset += 2;
476  }
520      st010_writew(0x03b0 + offset, data);
521
522      offset += 2;
523   }
477524}
478525
479static void st010_op_08( void ) {
480  INT16 x0 = st010_readw(0x0000);
481  INT16 y0 = st010_readw(0x0002);
482  INT16 theta = st010_readw(0x0004);
483  INT16 x1, y1;
526static void st010_op_08( void )
527{
528   INT16 x0 = st010_readw(0x0000);
529   INT16 y0 = st010_readw(0x0002);
530   INT16 theta = st010_readw(0x0004);
531   INT16 x1, y1;
484532
485  x1 = (y0 * st010_sin(theta) >> 15) + (x0 * st010_cos(theta) >> 15);
486  y1 = (y0 * st010_cos(theta) >> 15) - (x0 * st010_sin(theta) >> 15);
533   x1 = (y0 * st010_sin(theta) >> 15) + (x0 * st010_cos(theta) >> 15);
534   y1 = (y0 * st010_cos(theta) >> 15) - (x0 * st010_sin(theta) >> 15);
487535
488  st010_writew(0x0010, x1);
489  st010_writew(0x0012, y1);
536   st010_writew(0x0010, x1);
537   st010_writew(0x0012, y1);
490538}
491539
492540// init, reset & handlers
r7621r7622
502550
503551   if ((address & 0xfff) == 0x0021 && (data & 0x80))
504552   {
505      switch (snes_st010.ram[0x0020])
553      switch (st010_state.ram[0x0020])
506554      {
507555         case 0x01: st010_op_01(); break;
508556         case 0x02: st010_op_02(); break;
r7621r7622
514562         case 0x08: st010_op_08(); break;
515563      }
516564
517      snes_st010.ram[0x0021] &= ~0x80;
565      st010_state.ram[0x0021] &= ~0x80;
518566   }
519567}
520568
521569
522570static void st010_init( running_machine* machine )
523571{
524   snes_st010.ram = (UINT8*)auto_alloc_array(machine, UINT8, 0x1000);
572   st010_state.ram = (UINT8*)auto_alloc_array_clear(machine, UINT8, 0x1000);
573
574   state_save_register_global(machine, st010_state.x1);
575   state_save_register_global(machine, st010_state.y1);
576   state_save_register_global(machine, st010_state.quadrant);
577   state_save_register_global(machine, st010_state.theta);
578   state_save_register_global(machine, st010_state.o1);
579
580   state_save_register_global_pointer(machine, st010_state.ram, 0x1000);
525581}
526582
527583static void st010_reset( void )
528584{
529   snes_st010.x1 = 0;
530   snes_st010.y1 = 0;
531   snes_st010.quadrant = 0;
532   snes_st010.theta = 0;
533   memset(snes_st010.ram, 0, 0x1000);
585   st010_state.x1 = 0;
586   st010_state.y1 = 0;
587   st010_state.quadrant = 0;
588   st010_state.theta = 0;
534589}
src/mame/machine/snesdsp1.c
r7621r7622
1212
1313***************************************************************************/
1414
15#define DSP1_VERSION 0x0102
15#define dsp1_VERSION 0x0102
1616
1717// The DSP-1 status register has 16 bits, but only
1818// the upper 8 bits can be accessed from an external device, so all these
1919// positions are referred to the upper byte (bits D8 to D15)
2020
21enum SrFlags {DRC=0x04, DRS=0x10, RQM=0x80};
21enum SrFlags { DRC = 0x04, DRS = 0x10, RQM = 0x80 };
2222
2323// According to Overload's docs, these are the meanings of the flags:
2424// DRC: The Data Register Control (DRC) bit specifies the data transfer length to and from the host CPU.
25//   0: Data transfer to and from the DSP-1 is 16 bits.
26//   1: Data transfer to and from the DSP-1 is 8 bits.
25//  0: Data transfer to and from the DSP-1 is 16 bits.
26//  1: Data transfer to and from the DSP-1 is 8 bits.
2727// DRS: The Data Register Status (DRS) bit indicates the data transfer status in the case of transfering 16-bit data.
28//   0: Data transfer has terminated.
29//   1: Data transfer in progress.
28//  0: Data transfer has terminated.
29//  1: Data transfer in progress.
3030// RQM: The Request for Master (RQM) indicates that the DSP1 is requesting host CPU for data read/write.
31//   0: Internal Data Register Transfer.
32//   1: External Data Register Transfer.
31//  0: Internal Data Register Transfer.
32//  1: External Data Register Transfer.
3333
34enum FsmMajorState {WAIT_COMMAND, READ_DATA, WRITE_DATA};
35enum MaxDataAccesses {MAX_READS=7, MAX_WRITES=1024};
34enum Fsm_Major_State { WAIT_COMMAND, READ_DATA, WRITE_DATA };
35enum Max_Data_Accesses { MAX_READS = 7, MAX_WRITES = 1024 };
3636
37struct DSP1_Command {
38        void (*callback)(INT16 *, INT16 *);
39        unsigned int reads;
40        unsigned int writes;
37struct dsp1_Command
38{
39   void (*callback)(INT16 *, INT16 *);
40   unsigned int reads;
41   unsigned int writes;
4142};
4243
44struct SharedData
45{
46   // some RAM variables shared between commands
47   INT16 MatrixA[3][3];          // attitude matrix A
48   INT16 MatrixB[3][3];
49   INT16 MatrixC[3][3];
50   INT16 CentreX, CentreY, CentreZ;   // center of projection
51   INT16 CentreZ_C, CentreZ_E;
52   INT16 VOffset;                     // vertical offset of the screen with regard to the centre of projection
53   INT16 Les, C_Les, E_Les;
54   INT16 SinAas, CosAas;
55   INT16 SinAzs, CosAzs;
56   INT16 SinAZS, CosAZS;
57   INT16 SecAZS_C1, SecAZS_E1;
58   INT16 SecAZS_C2, SecAZS_E2;
59   INT16 Nx, Ny, Nz;    // normal vector to the screen (norm 1, points toward the center of projection)
60   INT16 Gx, Gy, Gz;    // center of the screen (global coordinates)
61   INT16 Hx, Hy;        // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen)
62   INT16 Vx, Vy, Vz;    // vertical vector of the screen (norm 1, points toward the top of the screen)
63};
4364
65struct _snes_dsp1_state
66{
67   SharedData       shared;
68   UINT8            Sr;                       // status register
69   int              SrLowByteAccess;
70   UINT16           Dr;                       // "internal" representation of the data register
71   Fsm_Major_State  FsmMajorState;            // current major state of the FSM
72   UINT8            Command;                  // current command processed by the FSM
73   UINT8            DataCounter;              // #UINT16 read/writes counter used by the FSM
74   INT16            ReadBuffer[MAX_READS];
75   INT16            WriteBuffer[MAX_WRITES];
76   UINT8            Freeze;                   // need explanation?  ;)
77
78
79
4480//////////////////////////////////////////////////////////////////
4581
4682// Data ROM, as logged from a DSP-1B with the 0x1f command;
r7621r7622
5490// 257-points arccos table that, apparently, have been not used anywhere
5591// (maybe for the MaxAZS_Exp table?).
5692
57static UINT16 DSP1_DataRom[1024];
93   UINT16         DataRom[1024];
94};
5895
59static struct SharedData { // some RAM variables shared between commands
60        INT16 MatrixA[3][3];          // attitude matrix A
61        INT16 MatrixB[3][3];
62        INT16 MatrixC[3][3];
63        INT16 CentreX, CentreY, CentreZ;   // center of projection
64        INT16 CentreZ_C, CentreZ_E;
65        INT16 VOffset;                     // vertical offset of the screen with regard to the centre of projection
66        INT16 Les, C_Les, E_Les;
67        INT16 SinAas, CosAas;
68        INT16 SinAzs, CosAzs;
69        INT16 SinAZS, CosAZS;
70        INT16 SecAZS_C1, SecAZS_E1;
71        INT16 SecAZS_C2, SecAZS_E2;
72        INT16 Nx, Ny, Nz;    // normal vector to the screen (norm 1, points toward the center of projection)
73        INT16 Gx, Gy, Gz;    // center of the screen (global coordinates)
74        INT16 Hx, Hy;        // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen)
75        INT16 Vx, Vy, Vz;    // vertical vector of the screen (norm 1, points toward the top of the screen)
96static struct _snes_dsp1_state  dsp1_state;
7697
77} shared;
7898
79static UINT8 mSr;            // status register
80static int mSrLowByteAccess;
81static UINT16 mDr;           // "internal" representation of the data register
82static enum FsmMajorState mFsmMajorState;     // current major state of the FSM
83static UINT8 mCommand;                  // current command processed by the FSM
84static UINT8 mDataCounter;                 // #UINT16 read/writes counter used by the FSM
85static INT16 mReadBuffer[MAX_READS];
86static INT16 mWriteBuffer[MAX_WRITES];
87static UINT8 mFreeze;                   // need explanation?  ;)
99/* Prototypes */
88100
89static void DSP1_fsmStep(UINT8 read, UINT8 *data);            // FSM logic
101static void dsp1_fsm_step(UINT8 read, UINT8 *data);            // FSM logic
90102
91103// commands
92static void DSP1_memoryTest(INT16 *input, INT16 *output);
93static void DSP1_memoryDump(INT16 *input, INT16 *output);
94static void DSP1_memorySize(INT16 *input, INT16 *output);
95static void DSP1_multiply(INT16* input, INT16* output);
96static void DSP1_multiply2(INT16* input, INT16* output);
97static void DSP1_inverse(INT16 *input, INT16 *output);
98static void DSP1_triangle(INT16 *input, INT16 *output);
99static void DSP1_radius(INT16 *input, INT16 *output);
100static void DSP1_range(INT16 *input, INT16 *output);
101static void DSP1_range2(INT16 *input, INT16 *output);
102static void DSP1_distance(INT16 *input, INT16 *output);
103static void DSP1_rotate(INT16 *input, INT16 *output);
104static void DSP1_polar(INT16 *input, INT16 *output);
105static void DSP1_attitudeA(INT16 *input, INT16 *output);
106static void DSP1_attitudeB(INT16 *input, INT16 *output);
107static void DSP1_attitudeC(INT16 *input, INT16 *output);
108static void DSP1_objectiveA(INT16 *input, INT16 *output);
109static void DSP1_objectiveB(INT16 *input, INT16 *output);
110static void DSP1_objectiveC(INT16 *input, INT16 *output);
111static void DSP1_subjectiveA(INT16 *input, INT16 *output);
112static void DSP1_subjectiveB(INT16 *input, INT16 *output);
113static void DSP1_subjectiveC(INT16 *input, INT16 *output);
114static void DSP1_scalarA(INT16 *input, INT16 *output);
115static void DSP1_scalarB(INT16 *input, INT16 *output);
116static void DSP1_scalarC(INT16 *input, INT16 *output);
117static void DSP1_gyrate(INT16 *input, INT16 *output);
118static void DSP1_parameter(INT16 *input, INT16 *output);
119static void DSP1_raster(INT16 *input, INT16 *output);
120static void DSP1_target(INT16 *input, INT16 *output);
121static void DSP1_project(INT16 *input, INT16 *output);
104static void dsp1_memory_test(INT16 *input, INT16 *output);
105static void dsp1_memory_dump(INT16 *input, INT16 *output);
106static void dsp1_memory_size(INT16 *input, INT16 *output);
107static void dsp1_multiply(INT16* input, INT16* output);
108static void dsp1_multiply2(INT16* input, INT16* output);
109static void dsp1_inverse(INT16 *input, INT16 *output);
110static void dsp1_triangle(INT16 *input, INT16 *output);
111static void dsp1_radius(INT16 *input, INT16 *output);
112static void dsp1_range(INT16 *input, INT16 *output);
113static void dsp1_range2(INT16 *input, INT16 *output);
114static void dsp1_distance(INT16 *input, INT16 *output);
115static void dsp1_rotate(INT16 *input, INT16 *output);
116static void dsp1_polar(INT16 *input, INT16 *output);
117static void dsp1_attitudeA(INT16 *input, INT16 *output);
118static void dsp1_attitudeB(INT16 *input, INT16 *output);
119static void dsp1_attitudeC(INT16 *input, INT16 *output);
120static void dsp1_objectiveA(INT16 *input, INT16 *output);
121static void dsp1_objectiveB(INT16 *input, INT16 *output);
122static void dsp1_objectiveC(INT16 *input, INT16 *output);
123static void dsp1_subjectiveA(INT16 *input, INT16 *output);
124static void dsp1_subjectiveB(INT16 *input, INT16 *output);
125static void dsp1_subjectiveC(INT16 *input, INT16 *output);
126static void dsp1_scalarA(INT16 *input, INT16 *output);
127static void dsp1_scalarB(INT16 *input, INT16 *output);
128static void dsp1_scalarC(INT16 *input, INT16 *output);
129static void dsp1_gyrate(INT16 *input, INT16 *output);
130static void dsp1_parameter(INT16 *input, INT16 *output);
131static void dsp1_raster(INT16 *input, INT16 *output);
132static void dsp1_target(INT16 *input, INT16 *output);
133static void dsp1_project(INT16 *input, INT16 *output);
122134
123135// auxiliar functions
124static INT16 DSP1_sin(INT16 Angle);
125static INT16 DSP1_cos(INT16 Angle);
136static INT16 dsp1_sin(INT16 Angle);
137static INT16 dsp1_cos(INT16 Angle);
126138static void inverse(INT16 Coefficient, INT16 Exponent, INT16 *iCoefficient, INT16 *iExponent);
127static INT16 denormalizeAndClip(INT16 C, INT16 E);
139static INT16 denormalize_and_clip(INT16 C, INT16 E);
128140static void normalize(INT16 m, INT16 *Coefficient, INT16 *Exponent);
129static void normalizeDouble(INT32 Product, INT16 *Coefficient, INT16 *Exponent);
141static void normalize_double(INT32 Product, INT16 *Coefficient, INT16 *Exponent);
130142static INT16 shiftR(INT16 C, INT16 E);
131143
144// register saves
145static void dsp1_register_save(running_machine *machine);
146
132147//////////////////////////////////////////////////////////////////
133148
134149// The info on this table follows Overload's docs.
135150
136static const struct DSP1_Command mCommandTable[0x40] =
151static const struct dsp1_Command mCommandTable[0x40] =
137152{
138   {&DSP1_multiply, 2, 1},   //0x00
139   {&DSP1_attitudeA, 4, 0},    //0x01
140   {&DSP1_parameter, 7, 4},   //0x02
141   {&DSP1_subjectiveA, 3, 3},    //0x03
142   {&DSP1_triangle, 2, 2},   //0x04
143   {&DSP1_attitudeA, 4, 0},   //0x01
144   {&DSP1_project, 3, 3},   //0x06
145   {&DSP1_memoryTest, 1, 1},   //0x0f
146   {&DSP1_radius, 3, 2},   //0x08
147   {&DSP1_objectiveA, 3, 3},   //0x0d
148   {&DSP1_raster, 1, 4},   // 0x0a. This will normally work in continuous mode
149   {&DSP1_scalarA, 3, 1},   //0x0b
150   {&DSP1_rotate, 3, 2},   //0x0c
151   {&DSP1_objectiveA, 3, 3},   //0x0d
152   {&DSP1_target, 2, 2},   //0x0e
153   {&DSP1_memoryTest, 1, 1},   //0x0f
153   {&dsp1_multiply, 2, 1},   //0x00
154   {&dsp1_attitudeA, 4, 0},    //0x01
155   {&dsp1_parameter, 7, 4},   //0x02
156   {&dsp1_subjectiveA, 3, 3},    //0x03
157   {&dsp1_triangle, 2, 2},   //0x04
158   {&dsp1_attitudeA, 4, 0},   //0x01
159   {&dsp1_project, 3, 3},   //0x06
160   {&dsp1_memory_test, 1, 1},   //0x0f
161   {&dsp1_radius, 3, 2},   //0x08
162   {&dsp1_objectiveA, 3, 3},   //0x0d
163   {&dsp1_raster, 1, 4},   // 0x0a. This will normally work in continuous mode
164   {&dsp1_scalarA, 3, 1},   //0x0b
165   {&dsp1_rotate, 3, 2},   //0x0c
166   {&dsp1_objectiveA, 3, 3},   //0x0d
167   {&dsp1_target, 2, 2},   //0x0e
168   {&dsp1_memory_test, 1, 1},   //0x0f
154169
155   {&DSP1_inverse, 2, 2},   //0x10
156   {&DSP1_attitudeB, 4, 0},   //0x11
157   {&DSP1_parameter, 7, 4},   //0x02
158   {&DSP1_subjectiveB, 3, 3},   //0x13
159   {&DSP1_gyrate, 6, 3},   //0x14
160   {&DSP1_attitudeB, 4, 0},   //0x11
161   {&DSP1_project, 3, 3},   //0x06
162   {&DSP1_memoryDump, 1, 1024},   //0x1f
163   {&DSP1_range, 4, 1},   //0x18
164   {&DSP1_objectiveB, 3, 3},   //0x1d
165   {0, 0, 0},   // 0x1a; the chip freezes
166   {&DSP1_scalarB, 3, 1},   //0x1b
167   {&DSP1_polar, 6, 3},   //0x1c
168   {&DSP1_objectiveB, 3, 3},   //0x1d
169   {&DSP1_target, 2, 2},   //0x0e
170   {&DSP1_memoryDump, 1, 1024},   //0x1f
170   {&dsp1_inverse, 2, 2},   //0x10
171   {&dsp1_attitudeB, 4, 0},   //0x11
172   {&dsp1_parameter, 7, 4},   //0x02
173   {&dsp1_subjectiveB, 3, 3},   //0x13
174   {&dsp1_gyrate, 6, 3},   //0x14
175   {&dsp1_attitudeB, 4, 0},   //0x11
176   {&dsp1_project, 3, 3},   //0x06
177   {&dsp1_memory_dump, 1, 1024},   //0x1f
178   {&dsp1_range, 4, 1},   //0x18
179   {&dsp1_objectiveB, 3, 3},   //0x1d
180   {0, 0, 0},   // 0x1a; the chip freezes
181   {&dsp1_scalarB, 3, 1},   //0x1b
182   {&dsp1_polar, 6, 3},   //0x1c
183   {&dsp1_objectiveB, 3, 3},   //0x1d
184   {&dsp1_target, 2, 2},   //0x0e
185   {&dsp1_memory_dump, 1, 1024},   //0x1f
171186
172   {&DSP1_multiply2, 2, 1},   //0x20
173   {&DSP1_attitudeC, 4, 0},   //0x21
174   {&DSP1_parameter, 7, 4},   //0x02
175   {&DSP1_subjectiveC, 3, 3},   //0x23
176   {&DSP1_triangle, 2, 2},   //0x04
177   {&DSP1_attitudeC, 4, 0},   //0x21
178   {&DSP1_project, 3, 3},   //0x06
179   {&DSP1_memorySize, 1, 1},    //0x2f
180   {&DSP1_distance, 3, 1},   //0x28
181   {&DSP1_objectiveC, 3, 3},   //0x2d
182   {0, 0, 0},   // 0x1a; the chip freezes
183   {&DSP1_scalarC, 3, 1},   //0x2b
184   {&DSP1_rotate, 3, 2},   //0x0c
185   {&DSP1_objectiveC, 3, 3},   //0x2d
186   {&DSP1_target, 2, 2},   //0x0e
187   {&DSP1_memorySize, 1, 1},   //0x2f
187   {&dsp1_multiply2, 2, 1},   //0x20
188   {&dsp1_attitudeC, 4, 0},   //0x21
189   {&dsp1_parameter, 7, 4},   //0x02
190   {&dsp1_subjectiveC, 3, 3},   //0x23
191   {&dsp1_triangle, 2, 2},   //0x04
192   {&dsp1_attitudeC, 4, 0},   //0x21
193   {&dsp1_project, 3, 3},   //0x06
194   {&dsp1_memory_size, 1, 1},    //0x2f
195   {&dsp1_distance, 3, 1},   //0x28
196   {&dsp1_objectiveC, 3, 3},   //0x2d
197   {0, 0, 0},   // 0x1a; the chip freezes
198   {&dsp1_scalarC, 3, 1},   //0x2b
199   {&dsp1_rotate, 3, 2},   //0x0c
200   {&dsp1_objectiveC, 3, 3},   //0x2d
201   {&dsp1_target, 2, 2},   //0x0e
202   {&dsp1_memory_size, 1, 1},   //0x2f
188203
189   {&DSP1_inverse, 2, 2},   //0x10
190   {&DSP1_attitudeA, 4, 0},   //0x01
191   {&DSP1_parameter, 7, 4},   //0x02
192   {&DSP1_subjectiveA, 3, 3},   //0x03
193   {&DSP1_gyrate, 6, 3},   //0x14
194   {&DSP1_attitudeA, 4, 0},   //0x01
195   {&DSP1_project, 3, 3},   //0x06
196   {&DSP1_memoryDump, 1, 1024},   //0x1f
197   {&DSP1_range2, 4, 1},   //0x38
198   {&DSP1_objectiveA, 3, 3},   //0x0d
199   {0, 0, 0},   // 0x1a; the chip freezes
200   {&DSP1_scalarA, 3, 1},   //0x0b
201   {&DSP1_polar, 6, 3},   //0x1c
202   {&DSP1_objectiveA, 3, 3},   //0x0d
203   {&DSP1_target, 2, 2},   //0x0e
204   {&DSP1_memoryDump, 1, 1024},   //0x1f
204   {&dsp1_inverse, 2, 2},   //0x10
205   {&dsp1_attitudeA, 4, 0},   //0x01
206   {&dsp1_parameter, 7, 4},   //0x02
207   {&dsp1_subjectiveA, 3, 3},   //0x03
208   {&dsp1_gyrate, 6, 3},   //0x14
209   {&dsp1_attitudeA, 4, 0},   //0x01
210   {&dsp1_project, 3, 3},   //0x06
211   {&dsp1_memory_dump, 1, 1024},   //0x1f
212   {&dsp1_range2, 4, 1},   //0x38
213   {&dsp1_objectiveA, 3, 3},   //0x0d
214   {0, 0, 0},   // 0x1a; the chip freezes
215   {&dsp1_scalarA, 3, 1},   //0x0b
216   {&dsp1_polar, 6, 3},   //0x1c
217   {&dsp1_objectiveA, 3, 3},   //0x0d
218   {&dsp1_target, 2, 2},   //0x0e
219   {&dsp1_memory_dump, 1, 1024},   //0x1f
205220};
206221
207222//////////////////////////////////////////////////////////////////
208223
209static const INT16 DSP1_MaxAZS_Exp[16] = {
224static const INT16 dsp1_MaxAZS_Exp[16] = {
210225   0x38b4, 0x38b7, 0x38ba, 0x38be, 0x38c0, 0x38c4, 0x38c7, 0x38ca,
211226   0x38ce, 0x38d0, 0x38d4, 0x38d7, 0x38da, 0x38dd, 0x38e0, 0x38e4
212227};
213228
214229//////////////////////////////////////////////////////////////////
215230
216static const INT16 DSP1_SinTable[256] = {
231static const INT16 dsp1_sin_table[256] = {
217232   0x0000,  0x0324,  0x0647,  0x096a,  0x0c8b,  0x0fab,  0x12c8,  0x15e2,
218233   0x18f8,  0x1c0b,  0x1f19,  0x2223,  0x2528,  0x2826,  0x2b1f,  0x2e11,
219234   0x30fb,  0x33de,  0x36ba,  0x398c,  0x3c56,  0x3f17,  0x41ce,  0x447a,
r7621r7622
250265   //////////////////////////////////////////////////////////////////
251266
252267// Optimised for Performance
253static const INT16 DSP1_MulTable[256] = {
268static const INT16 dsp1_mul_table[256] = {
254269      0x0000,  0x0003,  0x0006,  0x0009,  0x000c,  0x000f,  0x0012,  0x0015,
255270      0x0019,  0x001c,  0x001f,  0x0022,  0x0025,  0x0028,  0x002b,  0x002f,
256271      0x0032,  0x0035,  0x0038,  0x003b,  0x003e,  0x0041,  0x0045,  0x0048,
r7621r7622
286301
287302//////////////////////////////////////////////////////////////////
288303
289static UINT8 DSP1_getSr(void)
304static UINT8 dsp1_get_sr( void )
290305{
291   mSrLowByteAccess = ~mSrLowByteAccess;
292   if (mSrLowByteAccess)
293   {
294      return 0;
295   }
296   else
297   {
298      return mSr;
299   }
306   dsp1_state.SrLowByteAccess = ~dsp1_state.SrLowByteAccess;
307
308   if (dsp1_state.SrLowByteAccess)
309      return 0;
310   else
311      return dsp1_state.Sr;
300312}
301313
302314//////////////////////////////////////////////////////////////////
303315
304static UINT8 DSP1_getDr(void)
316static UINT8 dsp1_get_dr( void )
305317{
306   UINT8 oDr;
318   UINT8 oDr;
307319
308   DSP1_fsmStep(1, &oDr);
309   return oDr;
320   dsp1_fsm_step(1, &oDr);
321   return oDr;
310322}
311323
312324//////////////////////////////////////////////////////////////////
313325
314static void DSP1_setDr(UINT8 iDr)
326static void dsp1_set_dr( UINT8 iDr )
315327{
316    DSP1_fsmStep(0, &iDr);
328   dsp1_fsm_step(0, &iDr);
317329}
318330
319331//////////////////////////////////////////////////////////////////
320332
321static void DSP1_reset(running_machine *machine)
333static void dsp1_init( running_machine *machine )
322334{
323335   UINT32 i;
324336   UINT8 *dspin = memory_region(machine, "addons");
325337
326   mSr = DRC|RQM;
327   mSrLowByteAccess = FALSE;
328   mDr = 0x0080;    // Only a supposition. Is this correct?
329   mFreeze = FALSE;
330   mFsmMajorState = WAIT_COMMAND;
331   memset(&shared, 0, sizeof(struct SharedData)); // another supposition
338   dsp1_state.Sr = DRC|RQM;
339   dsp1_state.SrLowByteAccess = FALSE;
340   dsp1_state.Dr = 0x0080;      // Only a supposition. Is this correct?
341   dsp1_state.Freeze = FALSE;
342   dsp1_state.FsmMajorState = WAIT_COMMAND;
343   memset(&dsp1_state.shared, 0, sizeof(struct SharedData)); // another supposition
332344
333345   // expand the DSP-1 data ROM
334   for (i = 0; i < 2048; i+=2)
346   for (i = 0; i < 2048; i += 2)
335347   {
336      DSP1_DataRom[i/2] = dspin[i]<<8 | dspin[i+1];
348      dsp1_state.DataRom[i / 2] = (dspin[i] << 8) | dspin[i + 1];
337349   }
350
351   dsp1_register_save(machine);
338352}
339353
340354//////////////////////////////////////////////////////////////////
r7621r7622
344358// is responsible for maintaining the binding between the
345359// "external" and "internal" representations of the DR (data register).
346360
347static void DSP1_fsmStep(UINT8 read, UINT8 *data)
361static void dsp1_fsm_step( UINT8 read, UINT8 *data )
348362{
349   if (0 == (mSr&RQM)) return;
350   // Now RQM would be cleared; however, as this code is not to be used in
351   // a multithread environment, we will simply fake RQM operation.
352   // (The only exception would be Op1A's freeze.)
363   if (0 == (dsp1_state.Sr & RQM))
364      return;
353365
354   // binding
355   if (read)
356   {
357      if (mSr&DRS)
358         *data = (UINT8)(mDr>>8);
359      else
360         *data = (UINT8)(mDr);
361   }
362   else
363   {
364      if (mSr&DRS)
365      {
366         mDr &= 0x00ff;
367         mDr |= *data<<8;
368      }
369      else
370      {
371         mDr &= 0xff00;
372         mDr |= *data;
373      }
374   }
366   // Now RQM would be cleared; however, as this code is not to be used in
367   // a multithread environment, we will simply fake RQM operation.
368   // (The only exception would be Op1A's freeze.)
375369
370   // binding
371   if (read)
372   {
373      if (dsp1_state.Sr & DRS)
374         *data = (UINT8)(dsp1_state.Dr >> 8);
375      else
376         *data = (UINT8)(dsp1_state.Dr);
377   }
378   else
379   {
380      if (dsp1_state.Sr & DRS)
381      {
382         dsp1_state.Dr &= 0x00ff;
383         dsp1_state.Dr |= *data << 8;
384      }
385      else
386      {
387         dsp1_state.Dr &= 0xff00;
388         dsp1_state.Dr |= *data;
389      }
390   }
376391
377   switch (mFsmMajorState)
378   {
379      case WAIT_COMMAND:
380         mCommand = (UINT8)(mDr);
381         if (!(mCommand & 0xc0))   // valid command?
382         {
383            switch(mCommand)
384            {
385               // freeze cases
386               case 0x1a:
387               case 0x2a:
388               case 0x3a:
389                  mFreeze = TRUE;
390                  break;
391               // normal cases
392               default:
393                  mDataCounter=0;
394                  mFsmMajorState = READ_DATA;
395                  mSr &= ~DRC;
396                  break;
397            }
398         }
399         break;
400      case READ_DATA:
401         mSr ^= DRS;
402         if (!(mSr&DRS))
403         {
404            mReadBuffer[mDataCounter++] = (INT16)(mDr);
405            if (mDataCounter >= mCommandTable[mCommand].reads)
406            {
407               (*mCommandTable[mCommand].callback)(mReadBuffer, mWriteBuffer);
408               if (0 != mCommandTable[mCommand].writes)  // any output?
409               {
410                  mDataCounter = 0;
411                  mDr = (UINT16)(mWriteBuffer[mDataCounter]);
412                  mFsmMajorState = WRITE_DATA;
413               }
414               else
415               {
416                  mDr = 0x0080;  // valid command completion
417                  mFsmMajorState = WAIT_COMMAND;
418                  mSr |= DRC;
419               }
420            }
421         }
422         break;
423      case WRITE_DATA:
424         mSr ^= DRS;
425         if (!(mSr&DRS))
426         {
427            ++mDataCounter;
428            if (mDataCounter >= mCommandTable[mCommand].writes)
429            {
430               if ((mCommand == 0x0a)&&(mDr != 0x8000))
431               {
432                  // works in continuous mode
433                  mReadBuffer[0]++;   // next raster line
434                  (*mCommandTable[mCommand].callback)(mReadBuffer, mWriteBuffer);
435                  mDataCounter = 0;
436                  mDr = (UINT16)(mWriteBuffer[mDataCounter]);
437               }
438               else
439               {
440                  mDr = 0x0080;  // valid command completion
441                  mFsmMajorState = WAIT_COMMAND;
442                  mSr |= DRC;
443               }
444            }
445            else
446            {
447               mDr = (UINT16)(mWriteBuffer[mDataCounter]);
448            }
449         }
450         break;
451   }
452392
393   switch (dsp1_state.FsmMajorState)
394   {
395   case WAIT_COMMAND:
396      dsp1_state.Command = (UINT8)(dsp1_state.Dr);
397      if (!(dsp1_state.Command & 0xc0))   // valid command?
398      {
399         switch(dsp1_state.Command)
400         {
401         // freeze cases
402         case 0x1a:
403         case 0x2a:
404         case 0x3a:
405            dsp1_state.Freeze = TRUE;
406            break;
453407
408         // normal cases
409         default:
410            dsp1_state.DataCounter = 0;
411            dsp1_state.FsmMajorState = READ_DATA;
412            dsp1_state.Sr &= ~DRC;
413            break;
414         }
415      }
416      break;
454417
455   // Now RQM would be set (except when executing Op1A -command equals 0x1a, 0x2a or 0x3a-).
456   if (mFreeze)
457      mSr &= ~RQM;
418   case READ_DATA:
419      dsp1_state.Sr ^= DRS;
420      if (!(dsp1_state.Sr & DRS))
421      {
422         dsp1_state.ReadBuffer[dsp1_state.DataCounter++] = (INT16)(dsp1_state.Dr);
423         if (dsp1_state.DataCounter >= mCommandTable[dsp1_state.Command].reads)
424         {
425            (*mCommandTable[dsp1_state.Command].callback)(dsp1_state.ReadBuffer, dsp1_state.WriteBuffer);
426            if (0 != mCommandTable[dsp1_state.Command].writes)  // any output?
427            {
428               dsp1_state.DataCounter = 0;
429               dsp1_state.Dr = (UINT16)(dsp1_state.WriteBuffer[dsp1_state.DataCounter]);
430               dsp1_state.FsmMajorState = WRITE_DATA;
431            }
432            else
433            {
434               dsp1_state.Dr = 0x0080;  // valid command completion
435               dsp1_state.FsmMajorState = WAIT_COMMAND;
436               dsp1_state.Sr |= DRC;
437            }
438         }
439      }
440      break;
441
442   case WRITE_DATA:
443      dsp1_state.Sr ^= DRS;
444      if (!(dsp1_state.Sr & DRS))
445      {
446         ++dsp1_state.DataCounter;
447         if (dsp1_state.DataCounter >= mCommandTable[dsp1_state.Command].writes)
448         {
449            if ((dsp1_state.Command == 0x0a) && (dsp1_state.Dr != 0x8000))
450            {
451               // works in continuous mode
452               dsp1_state.ReadBuffer[0]++;   // next raster line
453               (*mCommandTable[dsp1_state.Command].callback)(dsp1_state.ReadBuffer, dsp1_state.WriteBuffer);
454               dsp1_state.DataCounter = 0;
455               dsp1_state.Dr = (UINT16)(dsp1_state.WriteBuffer[dsp1_state.DataCounter]);
456            }
457            else
458            {
459               dsp1_state.Dr = 0x0080;  // valid command completion
460               dsp1_state.FsmMajorState = WAIT_COMMAND;
461               dsp1_state.Sr |= DRC;
462            }
463         }
464         else
465         {
466            dsp1_state.Dr = (UINT16)(dsp1_state.WriteBuffer[dsp1_state.DataCounter]);
467         }
468      }
469      break;
470   }
471
472
473
474   // Now RQM would be set (except when executing Op1A -command equals 0x1a, 0x2a or 0x3a-).
475   if (dsp1_state.Freeze)
476      dsp1_state.Sr &= ~RQM;
458477}
459478
460479//////////////////////////////////////////////////////////////////
461480
462static void DSP1_memoryTest(INT16 *input, INT16 *output)
481static void dsp1_memory_test( INT16 *input, INT16 *output )
463482{
464//   INT16 *Size = &input[0];
465   INT16 *Result = &output[0];
483//  INT16 *Size = &input[0];
484   INT16 *Result = &output[0];
466485
467   *Result = 0x0000;
486   *Result = 0x0000;
468487}
469488
470489//////////////////////////////////////////////////////////////////
471490
472static void DSP1_memoryDump(INT16 *input, INT16 *output)
491static void dsp1_memory_dump( INT16 *input, INT16 *output )
473492{
474   memcpy(output, DSP1_DataRom, 1024);
493   memcpy(output, dsp1_state.DataRom, 1024);
475494}
476495
477496//////////////////////////////////////////////////////////////////
478497
479static void DSP1_memorySize(INT16 *input, INT16 *output)
498static void dsp1_memory_size( INT16 *input, INT16 *output )
480499{
481   INT16* Size = &output[0];
500   INT16* Size = &output[0];
482501
483   *Size = 0x0100;
502   *Size = 0x0100;
484503}
485504
486505//////////////////////////////////////////////////////////////////
487506
488507// 16-bit multiplication
489508
490static void DSP1_multiply(INT16 *input, INT16 *output)
509static void dsp1_multiply( INT16 *input, INT16 *output )
491510{
492   INT16 Multiplicand = input[0];
493   INT16 Multiplier = input[1];
494   INT16* Product = &output[0];
511   INT16 Multiplicand = input[0];
512   INT16 Multiplier = input[1];
513   INT16* Product = &output[0];
495514
496   *Product = Multiplicand * Multiplier >> 15;
515   *Product = Multiplicand * Multiplier >> 15;
497516}
498517
499518//////////////////////////////////////////////////////////////////
500519
501520// 16-bit multiplication. 'Alternative' method. Can anyone check this carefully?
502521
503static void DSP1_multiply2(INT16 *input, INT16 *output)
522static void dsp1_multiply2( INT16 *input, INT16 *output )
504523{
505   INT16 Multiplicand = input[0];
506   INT16 Multiplier = input[1];
507   INT16* Product = &output[0];
524   INT16 Multiplicand = input[0];
525   INT16 Multiplier = input[1];
526   INT16* Product = &output[0];
508527
509   *Product = (Multiplicand * Multiplier >> 15)+1;
528   *Product = (Multiplicand * Multiplier >> 15) + 1;
510529}
511530
512531//////////////////////////////////////////////////////////////////
513532
514533// This command determines the inverse of a floating point decimal number.
515534
516static void DSP1_inverse(INT16 *input, INT16 *output)
535static void dsp1_inverse( INT16 *input, INT16 *output )
517536{
518   INT16 Coefficient = input[0];
519   INT16 Exponent = input[1];
520   INT16* iCoefficient = &output[0];
521   INT16* iExponent = &output[1];
537   INT16 Coefficient = input[0];
538   INT16 Exponent = input[1];
539   INT16* iCoefficient = &output[0];
540   INT16* iExponent = &output[1];
522541
523   inverse(Coefficient, Exponent, iCoefficient, iExponent);
542   inverse(Coefficient, Exponent, iCoefficient, iExponent);
524543}
525544
526545//////////////////////////////////////////////////////////////////
r7621r7622
530549// Y = Radius * sin(Angle)
531550// X = Radius * cos(Angle)
532551
533static void DSP1_triangle(INT16 *input, INT16 *output)
552static void dsp1_triangle( INT16 *input, INT16 *output )
534553{
535   INT16 Angle = input[0];
536   INT16 Radius = input[1];
537   INT16* Y = &output[0];
538   INT16* X = &output[1];
554   INT16 Angle = input[0];
555   INT16 Radius = input[1];
556   INT16* Y = &output[0];
557   INT16* X = &output[1];
539558
540   *Y = DSP1_sin(Angle) * Radius >> 15;
541   *X = DSP1_cos(Angle) * Radius >> 15;
559   *Y = dsp1_sin(Angle) * Radius >> 15;
560   *X = dsp1_cos(Angle) * Radius >> 15;
542561}
543562
544563//////////////////////////////////////////////////////////////////
r7621r7622
546565// Determines the squared norm of a vector (X,Y,Z)
547566// The output is Radius = X^2+Y^2+Z^2 (double integer)
548567
549static void DSP1_radius(INT16 *input, INT16 *output)
568static void dsp1_radius( INT16 *input, INT16 *output )
550569{
551   INT16 X = input[0];
552   INT16 Y = input[1];
553   INT16 Z = input[2];
554   INT16* RadiusLow = &output[0];
555   INT16* RadiusHigh = &output[1];
570   INT16 X = input[0];
571   INT16 Y = input[1];
572   INT16 Z = input[2];
573   INT16* RadiusLow = &output[0];
574   INT16* RadiusHigh = &output[1];
556575
557   INT32 Radius;
576   INT32 Radius;
558577
559   Radius = (X * X + Y * Y + Z * Z) << 1;
560   *RadiusLow = (INT16)(Radius);
561   *RadiusHigh = (INT16)(Radius>>16);
578   Radius = (X * X + Y * Y + Z * Z) << 1;
579   *RadiusLow = (INT16)(Radius);
580   *RadiusHigh = (INT16)(Radius >> 16);
562581}
563582
564583//////////////////////////////////////////////////////////////////
r7621r7622
567586// from a particular point, and so may be used to determine if a point is within the sphere or radius R.
568587// The output is D = X^2+Y^2+Z^2-R^2
569588
570static void DSP1_range(INT16 *input, INT16 *output)
589static void dsp1_range( INT16 *input, INT16 *output )
571590{
572   INT16 X = input[0];
573   INT16 Y = input[1];
574   INT16 Z = input[2];
575   INT16 Radius = input[3];
576   INT16* Range = &output[0];
591   INT16 X = input[0];
592   INT16 Y = input[1];
593   INT16 Z = input[2];
594   INT16 Radius = input[3];
595   INT16* Range = &output[0];
577596
578   *Range = (X * X + Y * Y + Z * Z - Radius * Radius) >> 15;
597   *Range = (X * X + Y * Y + Z * Z - Radius * Radius) >> 15;
579598}
580599
581600//////////////////////////////////////////////////////////////////
582601
583602// Vector size comparison. 'Alternative' method.
584603
585static void DSP1_range2(INT16 *input, INT16 *output)
604static void dsp1_range2( INT16 *input, INT16 *output )
586605{
587   INT16 X = input[0];
588   INT16 Y = input[1];
589   INT16 Z = input[2];
590   INT16 Radius = input[3];
591   INT16* Range = &output[0];
606   INT16 X = input[0];
607   INT16 Y = input[1];
608   INT16 Z = input[2];
609   INT16 Radius = input[3];
610   INT16* Range = &output[0];
592611
593   *Range = ((X * X + Y * Y + Z * Z - Radius * Radius) >> 15) + 1;
612   *Range = ((X * X + Y * Y + Z * Z - Radius * Radius) >> 15) + 1;
594613}
595614
596615//////////////////////////////////////////////////////////////////
r7621r7622
603622// c=sqrt(b) by using lineal interpolation between points of a
604623// look-up table and, finally, you output the result as c*2^n.
605624
606static void DSP1_distance(INT16 *input, INT16 *output)
625static void dsp1_distance( INT16 *input, INT16 *output )
607626{
608   INT16 X = input[0];
609   INT16 Y = input[1];
610   INT16 Z = input[2];
611   INT16* Distance = &output[0];
612   INT16 Pos, Node1, Node2;
627   INT16 X = input[0];
628   INT16 Y = input[1];
629   INT16 Z = input[2];
630   INT16* Distance = &output[0];
631   INT16 Pos, Node1, Node2;
613632
614   INT32 Radius = X * X + Y * Y + Z * Z;
633   INT32 Radius = X * X + Y * Y + Z * Z;
615634
616635
617   if (Radius == 0) Distance = 0;
618   else
619   {
620      INT16 C, E;
621      normalizeDouble(Radius, &C, &E);
622      if (E & 1) C = C * 0x4000 >> 15;
636   if (Radius == 0)
637      Distance = 0;
638   else
639   {
640      INT16 C, E;
641      normalize_double(Radius, &C, &E);
642      if (E & 1)
643      C = C * 0x4000 >> 15;
623644
624      Pos = C * 0x0040 >> 15;
645      Pos = C * 0x0040 >> 15;
625646
626      Node1 = DSP1_DataRom[0x00d5 + Pos];
627      Node2 = DSP1_DataRom[0x00d6 + Pos];
647      Node1 = dsp1_state.DataRom[0x00d5 + Pos];
648      Node2 = dsp1_state.DataRom[0x00d6 + Pos];
628649
629      *Distance = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1;
650      *Distance = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1;
630651
631#if DSP1_VERSION < 0x0102
632      if (Pos & 1) *Distance -= (Node2 - Node1);
652#if dsp1_VERSION < 0x0102
653      if (Pos & 1)
654         *Distance -= (Node2 - Node1);
633655#endif
634656      *Distance >>= (E >> 1);
635   }
657   }
636658}
637659
638660//////////////////////////////////////////////////////////////////
r7621r7622
642664// 'counterclockwise', but it's obviously wrong (surprise! :P)
643665//
644666// In matrix notation:
645// |X2|    |cos(Angle)   sin(Angle)| |X1|
646// |  | =  |                       | |  |
647// |Y2|    |-sin(Angle   cos(Angle)| |Y1|
667// |X2|    |cos(Angle)    sin(Angle)| |X1|
668// |  | =  |                        | |  |
669// |Y2|    |-sin(Angle    cos(Angle)| |Y1|
648670
649static void DSP1_rotate(INT16 *input, INT16 *output)
671static void dsp1_rotate( INT16 *input, INT16 *output )
650672{
651   INT16 Angle = input[0];
652   INT16 X1 = input[1];
653   INT16 Y1 = input[2];
654   INT16* X2 = &output[0];
655   INT16* Y2 = &output[1];
673   INT16 Angle = input[0];
674   INT16 X1 = input[1];
675   INT16 Y1 = input[2];
676   INT16* X2 = &output[0];
677   INT16* Y2 = &output[1];
656678
657   *X2 = (Y1 * DSP1_sin(Angle) >> 15) + (X1 * DSP1_cos(Angle) >> 15);
658   *Y2 = (Y1 * DSP1_cos(Angle) >> 15) - (X1 * DSP1_sin(Angle) >> 15);
679   *X2 = (Y1 * dsp1_sin(Angle) >> 15) + (X1 * dsp1_cos(Angle) >> 15);
680   *Y2 = (Y1 * dsp1_cos(Angle) >> 15) - (X1 * dsp1_sin(Angle) >> 15);
659681}
660682
661683//////////////////////////////////////////////////////////////////
r7621r7622
668690// command (but not with the "gyrate" command).
669691//
670692// In matrix notation:
671// |X2|   |1      0      0  | |cosRy   0   -sinRy| | cosRz  sinRz    0| |X1|
672// |Y2| = |0    cosRx  sinRx| |  0     1      0  | |-sinRz  cosRz    0| |Y1|
673// |Z2|   |0   -sinRx  cosRx| |sinRy   0    cosRy| |   0      0      1| |Z1|
693// |X2|   |1      0       0  | |cosRy   0   -sinRy| | cosRz  sinRz   0| |X1|
694// |Y2| = |0     cosRx  sinRx| |  0     1      0  | |-sinRz  cosRz   0| |Y1|
695// |Z2|   |0    -sinRx  cosRx| |sinRy   0    cosRy| |   0       0    1| |Z1|
674696
675static void DSP1_polar(INT16 *input, INT16 *output)
697static void dsp1_polar( INT16 *input, INT16 *output )
676698{
677   INT16 Az = input[0];
678   INT16 Ay = input[1];
679   INT16 Ax = input[2];
680   INT16 X1 = input[3];
681   INT16 Y1 = input[4];
682   INT16 Z1 = input[5];
683   INT16* X2 = &output[0];
684   INT16* Y2 = &output[1];
685   INT16* Z2 = &output[2];
699   INT16 Az = input[0];
700   INT16 Ay = input[1];
701   INT16 Ax = input[2];
702   INT16 X1 = input[3];
703   INT16 Y1 = input[4];
704   INT16 Z1 = input[5];
705   INT16* X2 = &output[0];
706   INT16* Y2 = &output[1];
707   INT16* Z2 = &output[2];
686708
687   INT16 X, Y, Z;
709   INT16 X, Y, Z;
688710
689   // Rotate Around Z
690   X = (Y1 * DSP1_sin(Az) >> 15) + (X1 * DSP1_cos(Az) >> 15);
691   Y = (Y1 * DSP1_cos(Az) >> 15) - (X1 * DSP1_sin(Az) >> 15);
692   X1 = X; Y1 = Y;
711   // Rotate Around Z
712   X = (Y1 * dsp1_sin(Az) >> 15) + (X1 * dsp1_cos(Az) >> 15);
713   Y = (Y1 * dsp1_cos(Az) >> 15) - (X1 * dsp1_sin(Az) >> 15);
714   X1 = X; Y1 = Y;
693715
694   // Rotate Around Y
695   Z = (X1 * DSP1_sin(Ay) >> 15) + (Z1 * DSP1_cos(Ay) >> 15);
696   X = (X1 * DSP1_cos(Ay) >> 15) - (Z1 * DSP1_sin(Ay) >> 15);
697   *X2 = X; Z1 = Z;
716   // Rotate Around Y
717   Z = (X1 * dsp1_sin(Ay) >> 15) + (Z1 * dsp1_cos(Ay) >> 15);
718   X = (X1 * dsp1_cos(Ay) >> 15) - (Z1 * dsp1_sin(Ay) >> 15);
719   *X2 = X; Z1 = Z;
698720
699   // Rotate Around X
700   Y = (Z1 * DSP1_sin(Ax) >> 15) + (Y1 * DSP1_cos(Ax) >> 15);
701   Z = (Z1 * DSP1_cos(Ax) >> 15) - (Y1 * DSP1_sin(Ax) >> 15);
702   *Y2 = Y; *Z2 = Z;
721   // Rotate Around X
722   Y = (Z1 * dsp1_sin(Ax) >> 15) + (Y1 * dsp1_cos(Ax) >> 15);
723   Z = (Z1 * dsp1_cos(Ax) >> 15) - (Y1 * dsp1_sin(Ax) >> 15);
724   *Y2 = Y; *Z2 = Z;
703725}
704726
705727//////////////////////////////////////////////////////////////////
706728
707729// Set up the elements of an "attitude matrix" (there are other ones):
708//           S | cosRz  sinRz    0| |cosRy   0   -sinRy| |1      0      0  |
709// MatrixA = - |-sinRz  cosRz    0| |  0     1      0  | |0    cosRx  sinRx|
710//           2 |   0      0      1| |sinRy   0    cosRy| |0   -sinRx  cosRx|
730//           S | cosRz  sinRz   0| |cosRy  0   -sinRy| |1     0      0  |
731// MatrixA = - |-sinRz  cosRz   0| |  0    1      0  | |0  cosRx   sinRx|
732//           2 |   0       0    1| |sinRy  0    cosRy| |0  -sinRx  cosRx|
711733// This matrix is thought to be used within the following framework:
712734// let's suppose we define positive rotations around a system of orthogonal axes in this manner:
713735// a rotation of +90 degrees around axis3 converts axis2 into axis1
r7621r7622
736758// input[2]: Ry
737759// input[3]: Rx
738760
739static void DSP1_attitudeA(INT16 *input, INT16 *output)
761static void dsp1_attitudeA( INT16 *input, INT16 *output )
740762{
741   INT16 S = input[0];
742   INT16 Rz = input[1];
743   INT16 Ry = input[2];
744   INT16 Rx = input[3];
763   INT16 S = input[0];
764   INT16 Rz = input[1];
765   INT16 Ry = input[2];
766   INT16 Rx = input[3];
745767
746   INT16 SinRz = DSP1_sin(Rz);
747   INT16 CosRz = DSP1_cos(Rz);
748   INT16 SinRy = DSP1_sin(Ry);
749   INT16 CosRy = DSP1_cos(Ry);
750   INT16 SinRx = DSP1_sin(Rx);
751   INT16 CosRx = DSP1_cos(Rx);
768   INT16 SinRz = dsp1_sin(Rz);
769   INT16 CosRz = dsp1_cos(Rz);
770   INT16 SinRy = dsp1_sin(Ry);
771   INT16 CosRy = dsp1_cos(Ry);
772   INT16 SinRx = dsp1_sin(Rx);
773   INT16 CosRx = dsp1_cos(Rx);
752774
753   S >>= 1;
775   S >>= 1;
754776
755   shared.MatrixA[0][0] = (S * CosRz >> 15) * CosRy >> 15;
756   shared.MatrixA[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15);
757   shared.MatrixA[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15);
777   dsp1_state.shared.MatrixA[0][0] = (S * CosRz >> 15) * CosRy >> 15;
778   dsp1_state.shared.MatrixA[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15);
779   dsp1_state.shared.MatrixA[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15);
758780
759   shared.MatrixA[1][0] = -((S * SinRz >> 15) * CosRy >> 15);
760   shared.MatrixA[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15);
761   shared.MatrixA[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15);
781   dsp1_state.shared.MatrixA[1][0] = -((S * SinRz >> 15) * CosRy >> 15);
782   dsp1_state.shared.MatrixA[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15);
783   dsp1_state.shared.MatrixA[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15);
762784
763   shared.MatrixA[2][0] = S * SinRy >> 15;
764   shared.MatrixA[2][1] = -((S * SinRx >> 15) * CosRy >> 15);
765   shared.MatrixA[2][2] = (S * CosRx >> 15) * CosRy >> 15;
785   dsp1_state.shared.MatrixA[2][0] = S * SinRy >> 15;
786   dsp1_state.shared.MatrixA[2][1] = -((S * SinRx >> 15) * CosRy >> 15);
787   dsp1_state.shared.MatrixA[2][2] = (S * CosRx >> 15) * CosRy >> 15;
766788}
767789
768790//////////////////////////////////////////////////////////////////
769791
770792// Same than 'attitudeA', but with a difference attitude matrix (matrixB)
771793
772static void DSP1_attitudeB(INT16 *input, INT16 *output)
794static void dsp1_attitudeB( INT16 *input, INT16 *output )
773795{
774   INT16 S = input[0];
775   INT16 Rz = input[1];
776   INT16 Ry = input[2];
777   INT16 Rx = input[3];
796   INT16 S = input[0];
797   INT16 Rz = input[1];
798   INT16 Ry = input[2];
799   INT16 Rx = input[3];
778800
779   INT16 SinRz = DSP1_sin(Rz);
780   INT16 CosRz = DSP1_cos(Rz);
781   INT16 SinRy = DSP1_sin(Ry);
782   INT16 CosRy = DSP1_cos(Ry);
783   INT16 SinRx = DSP1_sin(Rx);
784   INT16 CosRx = DSP1_cos(Rx);
801   INT16 SinRz = dsp1_sin(Rz);
802   INT16 CosRz = dsp1_cos(Rz);
803   INT16 SinRy = dsp1_sin(Ry);
804   INT16 CosRy = dsp1_cos(Ry);
805   INT16 SinRx = dsp1_sin(Rx);
806   INT16 CosRx = dsp1_cos(Rx);
785807
786   S >>= 1;
808   S >>= 1;
787809
788   shared.MatrixB[0][0] = (S * CosRz >> 15) * CosRy >> 15;
789   shared.MatrixB[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15);
790   shared.MatrixB[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15);
810   dsp1_state.shared.MatrixB[0][0] = (S * CosRz >> 15) * CosRy >> 15;
811   dsp1_state.shared.MatrixB[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15);
812   dsp1_state.shared.MatrixB[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15);
791813
792   shared.MatrixB[1][0] = -((S * SinRz >> 15) * CosRy >> 15);
793   shared.MatrixB[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15);
794   shared.MatrixB[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15);
814   dsp1_state.shared.MatrixB[1][0] = -((S * SinRz >> 15) * CosRy >> 15);
815   dsp1_state.shared.MatrixB[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15);
816   dsp1_state.shared.MatrixB[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15);
795817
796   shared.MatrixB[2][0] = S * SinRy >> 15;
797   shared.MatrixB[2][1] = -((S * SinRx >> 15) * CosRy >> 15);
798   shared.MatrixB[2][2] = (S * CosRx >> 15) * CosRy >> 15;
818   dsp1_state.shared.MatrixB[2][0] = S * SinRy >> 15;
819   dsp1_state.shared.MatrixB[2][1] = -((S * SinRx >> 15) * CosRy >> 15);
820   dsp1_state.shared.MatrixB[2][2] = (S * CosRx >> 15) * CosRy >> 15;
799821}
800822
801823//////////////////////////////////////////////////////////////////
802824
803825// Same than 'attitudeA', but with a difference attitude matrix (matrixC)
804826
805static void DSP1_attitudeC(INT16 *input, INT16 *output)
827static void dsp1_attitudeC( INT16 *input, INT16 *output )
806828{
807   INT16 S = input[0];
808   INT16 Rz = input[1];
809   INT16 Ry = input[2];
810   INT16 Rx = input[3];
829   INT16 S = input[0];
830   INT16 Rz = input[1];
831   INT16 Ry = input[2];
832   INT16 Rx = input[3];
811833
812   INT16 SinRz = DSP1_sin(Rz);
813   INT16 CosRz = DSP1_cos(Rz);
814   INT16 SinRy = DSP1_sin(Ry);
815   INT16 CosRy = DSP1_cos(Ry);
816   INT16 SinRx = DSP1_sin(Rx);
817   INT16 CosRx = DSP1_cos(Rx);
834   INT16 SinRz = dsp1_sin(Rz);
835   INT16 CosRz = dsp1_cos(Rz);
836   INT16 SinRy = dsp1_sin(Ry);
837   INT16 CosRy = dsp1_cos(Ry);
838   INT16 SinRx = dsp1_sin(Rx);
839   INT16 CosRx = dsp1_cos(Rx);
818840
819   S >>= 1;
841   S >>= 1;
820842
821   shared.MatrixC[0][0] = (S * CosRz >> 15) * CosRy >> 15;
822   shared.MatrixC[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15);
823   shared.MatrixC[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15);
843   dsp1_state.shared.MatrixC[0][0] = (S * CosRz >> 15) * CosRy >> 15;
844   dsp1_state.shared.MatrixC[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15);
845   dsp1_state.shared.MatrixC[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15);
824846
825   shared.MatrixC[1][0] = -((S * SinRz >> 15) * CosRy >> 15);
826   shared.MatrixC[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15);
827   shared.MatrixC[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15);
847   dsp1_state.shared.MatrixC[1][0] = -((S * SinRz >> 15) * CosRy >> 15);
848   dsp1_state.shared.MatrixC[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15);
849   dsp1_state.shared.MatrixC[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15);
828850
829   shared.MatrixC[2][0] = S * SinRy >> 15;
830   shared.MatrixC[2][1] = -((S * SinRx >> 15) * CosRy >> 15);
831   shared.MatrixC[2][2] = (S * CosRx >> 15) * CosRy >> 15;
851   dsp1_state.shared.MatrixC[2][0] = S * SinRy >> 15;
852   dsp1_state.shared.MatrixC[2][1] = -((S * SinRx >> 15) * CosRy >> 15);
853   dsp1_state.shared.MatrixC[2][2] = (S * CosRx >> 15) * CosRy >> 15;
832854}
833855
834856//////////////////////////////////////////////////////////////////
r7621r7622
839861// input[0]: X ; input[1]: Y ; input[2]: Z
840862// &output[0]: F ; &output[1]: L ; &output[2]: U
841863
842static void DSP1_objectiveA(INT16 *input, INT16 *output)
864static void dsp1_objectiveA( INT16 *input, INT16 *output )
843865{
844   INT16 X = input[0];
845   INT16 Y = input[1];
846   INT16 Z = input[2];
847   INT16* F = &output[0];
848   INT16* L = &output[1];
849   INT16* U = &output[2];
866   INT16 X = input[0];
867   INT16 Y = input[1];
868   INT16 Z = input[2];
869   INT16* F = &output[0];
870   INT16* L = &output[1];
871   INT16* U = &output[2];
850872
851   *F = (shared.MatrixA[0][0] * X >> 15) + (shared.MatrixA[1][0] * Y >> 15) + (shared.MatrixA[2][0] * Z >> 15);
852   *L = (shared.MatrixA[0][1] * X >> 15) + (shared.MatrixA[1][1] * Y >> 15) + (shared.MatrixA[2][1] * Z >> 15);
853   *U = (shared.MatrixA[0][2] * X >> 15) + (shared.MatrixA[1][2] * Y >> 15) + (shared.MatrixA[2][2] * Z >> 15);
873   *F = (dsp1_state.shared.MatrixA[0][0] * X >> 15) + (dsp1_state.shared.MatrixA[1][0] * Y >> 15) + (dsp1_state.shared.MatrixA[2][0] * Z >> 15);
874   *L = (dsp1_state.shared.MatrixA[0][1] * X >> 15) + (dsp1_state.shared.MatrixA[1][1] * Y >> 15) + (dsp1_state.shared.MatrixA[2][1] * Z >> 15);
875   *U = (dsp1_state.shared.MatrixA[0][2] * X >> 15) + (dsp1_state.shared.MatrixA[1][2] * Y >> 15) + (dsp1_state.shared.MatrixA[2][2] * Z >> 15);
854876}
855877
856878//////////////////////////////////////////////////////////////////
857879
858880// Same than 'objectiveA', but for the 'B' attitude
859881
860static void DSP1_objectiveB(INT16 *input, INT16 *output)
882static void dsp1_objectiveB( INT16 *input, INT16 *output )
861883{
862   INT16 X = input[0];
863   INT16 Y = input[1];
864   INT16 Z = input[2];
865   INT16* F = &output[0];
866   INT16* L = &output[1];
867   INT16* U = &output[2];
884   INT16 X = input[0];
885   INT16 Y = input[1];
886   INT16 Z = input[2];
887   INT16* F = &output[0];
888   INT16* L = &output[1];
889   INT16* U = &output[2];
868890
869   *F = (shared.MatrixB[0][0] * X >> 15) + (shared.MatrixB[1][0] * Y >> 15) + (shared.MatrixB[2][0] * Z >> 15);
870   *L = (shared.MatrixB[0][1] * X >> 15) + (shared.MatrixB[1][1] * Y >> 15) + (shared.MatrixB[2][1] * Z >> 15);
871   *U = (shared.MatrixB[0][2] * X >> 15) + (shared.MatrixB[1][2] * Y >> 15) + (shared.MatrixB[2][2] * Z >> 15);
891   *F = (dsp1_state.shared.MatrixB[0][0] * X >> 15) + (dsp1_state.shared.MatrixB[1][0] * Y >> 15) + (dsp1_state.shared.MatrixB[2][0] * Z >> 15);
892   *L = (dsp1_state.shared.MatrixB[0][1] * X >> 15) + (dsp1_state.shared.MatrixB[1][1] * Y >> 15) + (dsp1_state.shared.MatrixB[2][1] * Z >> 15);
893   *U = (dsp1_state.shared.MatrixB[0][2] * X >> 15) + (dsp1_state.shared.MatrixB[1][2] * Y >> 15) + (dsp1_state.shared.MatrixB[2][2] * Z >> 15);
872894}
873895
874896//////////////////////////////////////////////////////////////////
875897
876898// Same than 'objectiveA', but for the 'C' attitude
877899
878static void DSP1_objectiveC(INT16 *input, INT16 *output)
900static void dsp1_objectiveC( INT16 *input, INT16 *output )
879901{
880   INT16 X = input[0];
881   INT16 Y = input[1];
882   INT16 Z = input[2];
883   INT16* F = &output[0];
884   INT16* L = &output[1];
885   INT16* U = &output[2];
902   INT16 X = input[0];
903   INT16 Y = input[1];
904   INT16 Z = input[2];
905   INT16* F = &output[0];
906   INT16* L = &output[1];
907   INT16* U = &output[2];
886908
887   *F = (shared.MatrixC[0][0] * X >> 15) + (shared.MatrixC[1][0] * Y >> 15) + (shared.MatrixC[2][0] * Z >> 15);
888   *L = (shared.MatrixC[0][1] * X >> 15) + (shared.MatrixC[1][1] * Y >> 15) + (shared.MatrixC[2][1] * Z >> 15);
889   *U = (shared.MatrixC[0][2] * X >> 15) + (shared.MatrixC[1][2] * Y >> 15) + (shared.MatrixC[2][2] * Z >> 15);
909   *F = (dsp1_state.shared.MatrixC[0][0] * X >> 15) + (dsp1_state.shared.MatrixC[1][0] * Y >> 15) + (dsp1_state.shared.MatrixC[2][0] * Z >> 15);
910   *L = (dsp1_state.shared.MatrixC[0][1] * X >> 15) + (dsp1_state.shared.MatrixC[1][1] * Y >> 15) + (dsp1_state.shared.MatrixC[2][1] * Z >> 15);
911   *U = (dsp1_state.shared.MatrixC[0][2] * X >> 15) + (dsp1_state.shared.MatrixC[1][2] * Y >> 15) + (dsp1_state.shared.MatrixC[2][2] * Z >> 15);
890912}
891913
892914//////////////////////////////////////////////////////////////////
r7621r7622
897919// input[0]: F ; input[1]: L ; input[2]: U
898920// &output[0]: X ; &output[1]: Y ; &output[2]: Z
899921
900static void DSP1_subjectiveA(INT16 *input, INT16 *output)
922static void dsp1_subjectiveA( INT16 *input, INT16 *output )
901923{
902   INT16 F = input[0];
903   INT16 L = input[1];
904   INT16 U = input[2];
905   INT16* X = &output[0];
906   INT16* Y = &output[1];
907   INT16* Z = &output[2];
924   INT16 F = input[0];
925   INT16 L = input[1];
926   INT16 U = input[2];
927   INT16* X = &output[0];
928   INT16* Y = &output[1];
929   INT16* Z = &output[2];
908930
909   *X = (shared.MatrixA[0][0] * F >> 15) + (shared.MatrixA[0][1] * L >> 15) + (shared.MatrixA[0][2] * U >> 15);
910   *Y = (shared.MatrixA[1][0] * F >> 15) + (shared.MatrixA[1][1] * L >> 15) + (shared.MatrixA[1][2] * U >> 15);
911   *Z = (shared.MatrixA[2][0] * F >> 15) + (shared.MatrixA[2][1] * L >> 15) + (shared.MatrixA[2][2] * U >> 15);
931   *X = (dsp1_state.shared.MatrixA[0][0] * F >> 15) + (dsp1_state.shared.MatrixA[0][1] * L >> 15) + (dsp1_state.shared.MatrixA[0][2] * U >> 15);
932   *Y = (dsp1_state.shared.MatrixA[1][0] * F >> 15) + (dsp1_state.shared.MatrixA[1][1] * L >> 15) + (dsp1_state.shared.MatrixA[1][2] * U >> 15);
933   *Z = (dsp1_state.shared.MatrixA[2][0] * F >> 15) + (dsp1_state.shared.MatrixA[2][1] * L >> 15) + (dsp1_state.shared.MatrixA[2][2] * U >> 15);
912934}
913935
914936//////////////////////////////////////////////////////////////////
915937
916938// Same than 'subjectiveA', but for the 'B' attitude
917939
918static void DSP1_subjectiveB(INT16 *input, INT16 *output)
940static void dsp1_subjectiveB( INT16 *input, INT16 *output )
919941{
920   INT16 F = input[0];
921   INT16 L = input[1];
922   INT16 U = input[2];
923   INT16* X = &output[0];
924   INT16* Y = &output[1];
925   INT16* Z = &output[2];
942   INT16 F = input[0];
943   INT16 L = input[1];
944   INT16 U = input[2];
945   INT16* X = &output[0];
946   INT16* Y = &output[1];
947   INT16* Z = &output[2];
926948
927   *X = (shared.MatrixB[0][0] * F >> 15) + (shared.MatrixB[0][1] * L >> 15) + (shared.MatrixB[0][2] * U >> 15);
928   *Y = (shared.MatrixB[1][0] * F >> 15) + (shared.MatrixB[1][1] * L >> 15) + (shared.MatrixB[1][2] * U >> 15);
929   *Z = (shared.MatrixB[2][0] * F >> 15) + (shared.MatrixB[2][1] * L >> 15) + (shared.MatrixB[2][2] * U >> 15);
949   *X = (dsp1_state.shared.MatrixB[0][0] * F >> 15) + (dsp1_state.shared.MatrixB[0][1] * L >> 15) + (dsp1_state.shared.MatrixB[0][2] * U >> 15);
950   *Y = (dsp1_state.shared.MatrixB[1][0] * F >> 15) + (dsp1_state.shared.MatrixB[1][1] * L >> 15) + (dsp1_state.shared.MatrixB[1][2] * U >> 15);
951   *Z = (dsp1_state.shared.MatrixB[2][0] * F >> 15) + (dsp1_state.shared.MatrixB[2][1] * L >> 15) + (dsp1_state.shared.MatrixB[2][2] * U >> 15);
930952}
931953
932954//////////////////////////////////////////////////////////////////
933955
934956// Same than 'subjectiveA', but for the 'C' attitude
935957
936static void DSP1_subjectiveC(INT16 *input, INT16 *output)
958static void dsp1_subjectiveC(INT16 *input, INT16 *output)
937959{
938   INT16 F = input[0];
939   INT16 L = input[1];
940   INT16 U = input[2];
941   INT16* X = &output[0];
942   INT16* Y = &output[1];
943   INT16* Z = &output[2];
960   INT16 F = input[0];
961   INT16 L = input[1];
962   INT16 U = input[2];
963   INT16* X = &output[0];
964   INT16* Y = &output[1];
965   INT16* Z = &output[2];
944966
945   *X = (shared.MatrixC[0][0] * F >> 15) + (shared.MatrixC[0][1] * L >> 15) + (shared.MatrixC[0][2] * U >> 15);
946   *Y = (shared.MatrixC[1][0] * F >> 15) + (shared.MatrixC[1][1] * L >> 15) + (shared.MatrixC[1][2] * U >> 15);
947   *Z = (shared.MatrixC[2][0] * F >> 15) + (shared.MatrixC[2][1] * L >> 15) + (shared.MatrixC[2][2] * U >> 15);
967   *X = (dsp1_state.shared.MatrixC[0][0] * F >> 15) + (dsp1_state.shared.MatrixC[0][1] * L >> 15) + (dsp1_state.shared.MatrixC[0][2] * U >> 15);
968   *Y = (dsp1_state.shared.MatrixC[1][0] * F >> 15) + (dsp1_state.shared.MatrixC[1][1] * L >> 15) + (dsp1_state.shared.MatrixC[1][2] * U >> 15);
969   *Z = (dsp1_state.shared.MatrixC[2][0] * F >> 15) + (dsp1_state.shared.MatrixC[2][1] * L >> 15) + (dsp1_state.shared.MatrixC[2][2] * U >> 15);
948970}
949971
950972//////////////////////////////////////////////////////////////////
r7621r7622
958980// input[0]: X ; input[1]: Y ; input[2]: Z
959981// &output[0]: S
960982
961static void DSP1_scalarA(INT16 *input, INT16 *output)
983static void dsp1_scalarA( INT16 *input, INT16 *output )
962984{
963   INT16 X = input[0];
964   INT16 Y = input[1];
965   INT16 Z = input[2];
966   INT16* S = &output[0];
985   INT16 X = input[0];
986   INT16 Y = input[1];
987   INT16 Z = input[2];
988   INT16* S = &output[0];
967989
968   *S = (X * shared.MatrixA[0][0] + Y * shared.MatrixA[1][0] + Z * shared.MatrixA[2][0]) >> 15;
990   *S = (X * dsp1_state.shared.MatrixA[0][0] + Y * dsp1_state.shared.MatrixA[1][0] + Z * dsp1_state.shared.MatrixA[2][0]) >> 15;
969991}
970992
971993//////////////////////////////////////////////////////////////////
972994
973995// Same than 'scalarA', but for the 'B' attitude
974996
975static void DSP1_scalarB(INT16 *input, INT16 *output)
997static void dsp1_scalarB( INT16 *input, INT16 *output )
976998{
977   INT16 X = input[0];
978   INT16 Y = input[1];
979   INT16 Z = input[2];
980   INT16* S = &output[0];
999   INT16 X = input[0];
1000   INT16 Y = input[1];
1001   INT16 Z = input[2];
1002   INT16* S = &output[0];
9811003
982   *S = (X * shared.MatrixB[0][0] + Y * shared.MatrixB[1][0] + Z * shared.MatrixB[2][0]) >> 15;
1004   *S = (X * dsp1_state.shared.MatrixB[0][0] + Y * dsp1_state.shared.MatrixB[1][0] + Z * dsp1_state.shared.MatrixB[2][0]) >> 15;
9831005}
9841006
9851007//////////////////////////////////////////////////////////////////
9861008
9871009// Same than 'scalarA', but for the 'C' attitude
9881010
989static void DSP1_scalarC(INT16 *input, INT16 *output)
1011static void dsp1_scalarC( INT16 *input, INT16 *output )
9901012{
991   INT16 X = input[0];
992   INT16 Y = input[1];
993   INT16 Z = input[2];
994   INT16* S = &output[0];
1013   INT16 X = input[0];
1014   INT16 Y = input[1];
1015   INT16 Z = input[2];
1016   INT16* S = &output[0];
9951017
996   *S = (X * shared.MatrixC[0][0] + Y * shared.MatrixC[1][0] + Z * shared.MatrixC[2][0]) >> 15;
1018   *S = (X * dsp1_state.shared.MatrixC[0][0] + Y * dsp1_state.shared.MatrixC[1][0] + Z * dsp1_state.shared.MatrixC[2][0]) >> 15;
9971019}
9981020
9991021//////////////////////////////////////////////////////////////////
r7621r7622
10161038// opinion, a pretty severe implementation error. However, if you only use small "minor displacements", the error term
10171039// introduced by that incoherence should be almost negligible.
10181040
1019static void DSP1_gyrate(INT16 *input, INT16 *output)
1041static void dsp1_gyrate( INT16 *input, INT16 *output )
10201042{
1021   INT16 Az = input[0];
1022   INT16 Ax = input[1];
1023   INT16 Ay = input[2];
1024   INT16 U = input[3];
1025   INT16 F = input[4];
1026   INT16 L = input[5];
1027   INT16* Rz = &output[0];
1028   INT16* Rx = &output[1];
1029   INT16* Ry = &output[2];
1043   INT16 Az = input[0];
1044   INT16 Ax = input[1];
1045   INT16 Ay = input[2];
1046   INT16 U = input[3];
1047   INT16 F = input[4];
1048   INT16 L = input[5];
1049   INT16* Rz = &output[0];
1050   INT16* Rx = &output[1];
1051   INT16* Ry = &output[2];
10301052
1031   INT16 CSec, ESec, CSin, C, E;
1032   INT16 SinAy = DSP1_sin(Ay);
1033   INT16 CosAy = DSP1_cos(Ay);
1053   INT16 CSec, ESec, CSin, C, E;
1054   INT16 SinAy = dsp1_sin(Ay);
1055   INT16 CosAy = dsp1_cos(Ay);
10341056
1035   inverse(DSP1_cos(Ax), 0, &CSec, &ESec);
1057   inverse(dsp1_cos(Ax), 0, &CSec, &ESec);
10361058
1037   // Rotation Around Z
1038   normalizeDouble(U * CosAy - F * SinAy, &C, &E);
1059   // Rotation Around Z
1060   normalize_double(U * CosAy - F * SinAy, &C, &E);
10391061
1040   E = ESec - E;
1062   E = ESec - E;
10411063
1042   normalize(C * CSec >> 15, &C, &E);
1064   normalize(C * CSec >> 15, &C, &E);
10431065
1044   *Rz = Az + denormalizeAndClip(C, E);
1066   *Rz = Az + denormalize_and_clip(C, E);
10451067
1046   // Rotation Around X
1047   *Rx = Ax + (U * SinAy >> 15) + (F * CosAy >> 15);
1068   // Rotation Around X
1069   *Rx = Ax + (U * SinAy >> 15) + (F * CosAy >> 15);
10481070
1049   // Rotation Around Y
1050   normalizeDouble(U * CosAy + F * SinAy, &C, &E);
1071   // Rotation Around Y
1072   normalize_double(U * CosAy + F * SinAy, &C, &E);
10511073
1052   E = ESec - E;
1074   E = ESec - E;
10531075
1054   normalize(DSP1_sin(Ax), &CSin, &E);
1076   normalize(dsp1_sin(Ax), &CSin, &E);
10551077
1056   normalize(-(C * (CSec * CSin >> 15) >> 15), &C, &E);
1078   normalize(-(C * (CSec * CSin >> 15) >> 15), &C, &E);
10571079
1058   *Ry = Ay + denormalizeAndClip(C, E) + L;
1080   *Ry = Ay + denormalize_and_clip(C, E) + L;
10591081}
10601082
10611083//////////////////////////////////////////////////////////////////
r7621r7622
10741096// Vva-> raster line representing the horizon line
10751097// (Cx, Cy)-> coordinates of the projection of the center of the screen over the ground (ground coordinates)
10761098
1077static void DSP1_parameter(INT16 *input, INT16 *output)
1099static void dsp1_parameter( INT16 *input, INT16 *output )
10781100{
1079   INT16 Fx = input[0];
1080   INT16 Fy = input[1];
1081   INT16 Fz = input[2];
1082   INT16 Lfe = input[3];
1083   INT16 Les = input[4];
1084   INT16 Aas = input[5];
1085   INT16 Azs = input[6];
1086   INT16* Vof = &output[0];
1087   INT16* Vva = &output[1];
1088   INT16* Cx = &output[2];
1089   INT16* Cy = &output[3];
1101   INT16 Fx = input[0];
1102   INT16 Fy = input[1];
1103   INT16 Fz = input[2];
1104   INT16 Lfe = input[3];
1105   INT16 Les = input[4];
1106   INT16 Aas = input[5];
1107   INT16 Azs = input[6];
1108   INT16* Vof = &output[0];
1109   INT16* Vva = &output[1];
1110   INT16* Cx = &output[2];
1111   INT16* Cy = &output[3];
10901112
1091   INT16 CSec, C, E;
1092   INT16 LfeNx, LfeNy, LfeNz;
1093   INT16 LesNx, LesNy, LesNz;
1094   INT16 AZS, MaxAZS;
1113   INT16 CSec, C, E;
1114   INT16 LfeNx, LfeNy, LfeNz;
1115   INT16 LesNx, LesNy, LesNz;
1116   INT16 AZS, MaxAZS;
10951117
1096   // Copy Zenith angle for clipping
1097   AZS = Azs;
1118   // Copy Zenith angle for clipping
1119   AZS = Azs;
10981120
1099   // Store Les and his coefficient and exponent when normalized
1100   shared.Les = Les;
1101   shared.E_Les=0;
1102   normalize(Les, &shared.C_Les, &shared.E_Les);
1121   // Store Les and his coefficient and exponent when normalized
1122   dsp1_state.shared.Les = Les;
1123   dsp1_state.shared.E_Les = 0;
1124   normalize(Les, &dsp1_state.shared.C_Les, &dsp1_state.shared.E_Les);
11031125
1104   // Store Sine and Cosine of Azimuth and Zenith angle
1105   shared.SinAas = DSP1_sin(Aas);
1106   shared.CosAas = DSP1_cos(Aas);
1107   shared.SinAzs = DSP1_sin(Azs);
1108   shared.CosAzs = DSP1_cos(Azs);
1126   // Store Sine and Cosine of Azimuth and Zenith angle
1127   dsp1_state.shared.SinAas = dsp1_sin(Aas);
1128   dsp1_state.shared.CosAas = dsp1_cos(Aas);
1129   dsp1_state.shared.SinAzs = dsp1_sin(Azs);
1130   dsp1_state.shared.CosAzs = dsp1_cos(Azs);
11091131
1110   // normal vector to the screen (norm 1, points toward the center of projection)
1111   shared.Nx = shared.SinAzs * -shared.SinAas >> 15;
1112   shared.Ny = shared.SinAzs * shared.CosAas >> 15;
1113   shared.Nz = shared.CosAzs * 0x7fff >> 15;
1132   // normal vector to the screen (norm 1, points toward the center of projection)
1133   dsp1_state.shared.Nx = dsp1_state.shared.SinAzs * -dsp1_state.shared.SinAas >> 15;
1134   dsp1_state.shared.Ny = dsp1_state.shared.SinAzs * dsp1_state.shared.CosAas >> 15;
1135   dsp1_state.shared.Nz = dsp1_state.shared.CosAzs * 0x7fff >> 15;
11141136
1115   // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen)
1116   shared.Hx = shared.CosAas*0x7fff>>15;
1117   shared.Hy = shared.SinAas*0x7fff>>15;
1137   // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen)
1138   dsp1_state.shared.Hx = dsp1_state.shared.CosAas*0x7fff>>15;
1139   dsp1_state.shared.Hy = dsp1_state.shared.SinAas*0x7fff>>15;
11181140
1119   // vertical vector of the screen (norm 1, points toward the top of the screen)
1120   shared.Vx = shared.CosAzs*-shared.SinAas>>15;
1121   shared.Vy = shared.CosAzs*shared.CosAas>>15;
1122   shared.Vz = -shared.SinAzs*0x7fff>>15;
1141   // vertical vector of the screen (norm 1, points toward the top of the screen)
1142   dsp1_state.shared.Vx = dsp1_state.shared.CosAzs * -dsp1_state.shared.SinAas >> 15;
1143   dsp1_state.shared.Vy = dsp1_state.shared.CosAzs * dsp1_state.shared.CosAas >> 15;
1144   dsp1_state.shared.Vz = -dsp1_state.shared.SinAzs * 0x7fff>>15;
11231145
1124   LfeNx = Lfe*shared.Nx>>15;
1125   LfeNy = Lfe*shared.Ny>>15;
1126   LfeNz = Lfe*shared.Nz>>15;
1146   LfeNx = Lfe * dsp1_state.shared.Nx >> 15;
1147   LfeNy = Lfe * dsp1_state.shared.Ny >> 15;
1148   LfeNz = Lfe * dsp1_state.shared.Nz >> 15;
11271149
1128   // Center of Projection
1129   shared.CentreX = Fx+LfeNx;
1130   shared.CentreY = Fy+LfeNy;
1131   shared.CentreZ = Fz+LfeNz;
1150   // Center of Projection
1151   dsp1_state.shared.CentreX = Fx + LfeNx;
1152   dsp1_state.shared.CentreY = Fy + LfeNy;
1153   dsp1_state.shared.CentreZ = Fz + LfeNz;
11321154
1133   LesNx = Les*shared.Nx>>15;
1134   LesNy = Les*shared.Ny>>15;
1135   LesNz = Les*shared.Nz>>15;
1155   LesNx = Les * dsp1_state.shared.Nx >> 15;
1156   LesNy = Les * dsp1_state.shared.Ny >> 15;
1157   LesNz = Les * dsp1_state.shared.Nz >> 15;
11361158
1137   // center of the screen (global coordinates)
1138   shared.Gx=shared.CentreX-LesNx;
1139   shared.Gy=shared.CentreY-LesNy;
1140   shared.Gz=shared.CentreZ-LesNz;
1159   // center of the screen (global coordinates)
1160   dsp1_state.shared.Gx = dsp1_state.shared.CentreX - LesNx;
1161   dsp1_state.shared.Gy = dsp1_state.shared.CentreY - LesNy;
1162   dsp1_state.shared.Gz = dsp1_state.shared.CentreZ - LesNz;
11411163
1164   E = 0;
1165   normalize(dsp1_state.shared.CentreZ, &C, &E);
11421166
1143   E = 0;
1144   normalize(shared.CentreZ, &C, &E);
1167   dsp1_state.shared.CentreZ_C = C;
1168   dsp1_state.shared.CentreZ_E = E;
11451169
1146   shared.CentreZ_C = C;
1147   shared.CentreZ_E = E;
1170   // Determine clip boundary and clip Zenith angle if necessary
1171   // (Why to clip? Maybe to avoid the screen can only show sky with no ground? Only a guess...)
1172   MaxAZS = dsp1_MaxAZS_Exp[-E];
11481173
1149   // Determine clip boundary and clip Zenith angle if necessary
1150   // (Why to clip? Maybe to avoid the screen can only show sky with no ground? Only a guess...)
1151   MaxAZS = DSP1_MaxAZS_Exp[-E];
1174   if (AZS < 0)
1175   {
1176      MaxAZS = -MaxAZS;
1177      if (AZS < MaxAZS + 1)
1178         AZS = MaxAZS + 1;
1179   }
1180   else
1181   {
1182      if (AZS > MaxAZS)
1183         AZS = MaxAZS;
1184   }
11521185
1153   if (AZS < 0) {
1154      MaxAZS = -MaxAZS;
1155      if (AZS < MaxAZS + 1) AZS = MaxAZS + 1;
1156   } else {
1157      if (AZS > MaxAZS) AZS = MaxAZS;
1158   }
1186   // Store Sine and Cosine of clipped Zenith angle
1187   dsp1_state.shared.SinAZS = dsp1_sin(AZS);
1188   dsp1_state.shared.CosAZS = dsp1_cos(AZS);
11591189
1160   // Store Sine and Cosine of clipped Zenith angle
1161   shared.SinAZS = DSP1_sin(AZS);
1162   shared.CosAZS = DSP1_cos(AZS);
1190   // calculate the separation of (cx, cy) from the projection of
1191   // the 'centre of projection' over the ground... (CentreZ*tg(AZS))
1192   inverse(dsp1_state.shared.CosAZS, 0, &dsp1_state.shared.SecAZS_C1, &dsp1_state.shared.SecAZS_E1);
1193   normalize(C * dsp1_state.shared.SecAZS_C1 >> 15, &C, &E);
1194   E += dsp1_state.shared.SecAZS_E1;
1195   C = denormalize_and_clip(C, E) * dsp1_state.shared.SinAZS >> 15;
11631196
1164   // calculate the separation of (cx, cy) from the projection of
1165   // the 'centre of projection' over the ground... (CentreZ*tg(AZS))
1166   inverse(shared.CosAZS, 0, &shared.SecAZS_C1, &shared.SecAZS_E1);
1167   normalize(C * shared.SecAZS_C1 >> 15, &C, &E);
1168   E += shared.SecAZS_E1;
1169   C = denormalizeAndClip(C, E) * shared.SinAZS >> 15;
1197   // ... and then take into account the position of the centre of
1198   // projection and the azimuth angle
1199   dsp1_state.shared.CentreX += C * dsp1_state.shared.SinAas >> 15;
1200   dsp1_state.shared.CentreY -= C * dsp1_state.shared.CosAas >> 15;
11701201
1171   // ... and then take into account the position of the centre of
1172   // projection and the azimuth angle
1173   shared.CentreX += C * shared.SinAas >> 15;
1174   shared.CentreY -= C * shared.CosAas >> 15;
1202   *Cx = dsp1_state.shared.CentreX;
1203   *Cy = dsp1_state.shared.CentreY;
11751204
1176   *Cx = shared.CentreX;
1177   *Cy = shared.CentreY;
1205   // Raster number of imaginary center and horizontal line
1206   *Vof = 0;
11781207
1179   // Raster number of imaginary center and horizontal line
1180   *Vof = 0;
1208   if ((Azs != AZS) || (Azs == MaxAZS))
1209   {
1210      INT16 Aux;
11811211
1182   if ((Azs != AZS) || (Azs == MaxAZS))
1183   {
1184      INT16 Aux;
1212      // correct vof and vva when Azs is outside the 'non-clipping interval'
1213      // we have only some few Taylor coefficients, so we cannot guess which ones
1214      // are the approximated functions and, what is worse, we don't know why
1215      // the own clipping stuff (and, particularly, this correction) is done
1216      if (Azs == -32768)
1217      Azs = -32767;
11851218
1186      // correct vof and vva when Azs is outside the 'non-clipping interval'
1187      // we have only some few Taylor coefficients, so we cannot guess which ones
1188      // are the approximated functions and, what is worse, we don't know why
1189      // the own clipping stuff (and, particularly, this correction) is done
1190      if (Azs == -32768) Azs = -32767;
1219      C = Azs - MaxAZS;
1220      if (C >= 0)
1221         C--;
1222      Aux = ~(C << 2);
11911223
1192      C = Azs - MaxAZS;
1193      if (C >= 0) C--;
1194      Aux = ~(C << 2);
1224      // Vof += x+(1/3)*x^3, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000
1225      C = Aux * dsp1_state.DataRom[0x0328] >> 15;
1226      C = (C * Aux >> 15) + dsp1_state.DataRom[0x0327];
1227      *Vof -= (C * Aux >> 15) * Les >> 15;
11951228
1196      // Vof += x+(1/3)*x^3, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000
1197      C = Aux * DSP1_DataRom[0x0328] >> 15;
1198      C = (C * Aux >> 15) + DSP1_DataRom[0x0327];
1199      *Vof -= (C * Aux >> 15) * Les >> 15;
1229      // CosAZS *= 1+(1/2)*x^2+(5/24)*x^24, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000
1230      C = Aux * Aux >> 15;
1231      Aux = (C * dsp1_state.DataRom[0x0324] >> 15) + dsp1_state.DataRom[0x0325];
1232      dsp1_state.shared.CosAZS += (C * Aux >> 15) * dsp1_state.shared.CosAZS >> 15;
1233   }
12001234
1201      // CosAZS *= 1+(1/2)*x^2+(5/24)*x^24, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000
1202      C = Aux * Aux >> 15;
1203      Aux = (C * DSP1_DataRom[0x0324] >> 15) + DSP1_DataRom[0x0325];
1204      shared.CosAZS += (C * Aux >> 15) * shared.CosAZS >> 15;
1205   }
1235   // vertical offset of the screen with regard to the horizontal plane
1236   // containing the centre of projection
1237   dsp1_state.shared.VOffset = Les * dsp1_state.shared.CosAZS >> 15;
12061238
1207   // vertical offset of the screen with regard to the horizontal plane
1208   // containing the centre of projection
1209   shared.VOffset = Les * shared.CosAZS >> 15;
1239   // The horizon line (the line in the screen that is crossed by the horizon plane
1240   // -the horizontal plane containing the 'centre of projection'-),
1241   // will be at distance Les*cotg(AZS) from the centre of the screen. This is difficult
1242   // to explain but easily seen in a graph. To better see it, consider it in this way:
1243   // Les*tg(AZS-90), draw some lines and apply basic trigonometry. ;)
1244   inverse(dsp1_state.shared.SinAZS, 0, &CSec, &E);
1245   normalize(dsp1_state.shared.VOffset, &C, &E);
1246   normalize(C * CSec >> 15, &C, &E);
12101247
1211   // The horizon line (the line in the screen that is crossed by the horizon plane
1212   // -the horizontal plane containing the 'centre of projection'-),
1213   // will be at distance Les*cotg(AZS) from the centre of the screen. This is difficult
1214   // to explain but easily seen in a graph. To better see it, consider it in this way:
1215   // Les*tg(AZS-90), draw some lines and apply basic trigonometry. ;)
1216   inverse(shared.SinAZS, 0, &CSec, &E);
1217   normalize(shared.VOffset, &C, &E);
1218   normalize(C * CSec >> 15, &C, &E);
1248   if (C == -32768)
1249   {
1250      C >>= 1;
1251      E++;
1252   }
12191253
1220 if (C == -32768) { C >>= 1; E++; }
1254   *Vva = denormalize_and_clip(-C, E);
12211255
1222   *Vva = denormalizeAndClip(-C, E);
1223
1224   // Store Secant of clipped Zenith angle
1225   inverse(shared.CosAZS, 0, &shared.SecAZS_C2, &shared.SecAZS_E2);
1256   // Store Secant of clipped Zenith angle
1257   inverse(dsp1_state.shared.CosAZS, 0, &dsp1_state.shared.SecAZS_C2, &dsp1_state.shared.SecAZS_E2);
12261258}
12271259
12281260//////////////////////////////////////////////////////////////////
r7621r7622
12421274// SecAZS). By last, you have to consider the effect of the azimuth angle Aas, and you are done.
12431275//
12441276// Using matrix notation:
1245//                    |A     B|    Centre_ZS     | cos(Aas)   -sin(Aas)|   |1           0|
1246// ProjectionMatrix = |       | = ----------- *  |                     | * |             |
1247//                    |C     D|   Vs*sin(Azs)    |sin(Aas)     cos(Aas)|   |0    sec(Azs)|
1277//                    |A      B|     Centre_ZS    | cos(Aas)    -sin(Aas)|   | 1         0   |
1278// ProjectionMatrix = |        | = ----------- *  |                      | * |               |
1279//                    |C      D|    Vs*sin(Azs)   | sin(Aas)     cos(Aas)|   | 0     sec(Azs)|
12481280//
12491281// (**)
12501282// If Les=1, the vertical offset between the center
r7621r7622
12521284// offset is 1, the ratio of the projection over the ground respect to the
12531285// line on the screen is 1/cos(Azs).
12541286
1255static void DSP1_raster(INT16 *input, INT16 *output)
1287static void dsp1_raster( INT16 *input, INT16 *output )
12561288{
1257   INT16 Vs = input[0];
1258   INT16* An = &output[0];
1259   INT16* Bn = &output[1];
1260   INT16* Cn = &output[2];
1261   INT16* Dn = &output[3];
1289   INT16 Vs = input[0];
1290   INT16* An = &output[0];
1291   INT16* Bn = &output[1];
1292   INT16* Cn = &output[2];
1293   INT16* Dn = &output[3];
12621294
1263   INT16 C, E, C1, E1;
1295   INT16 C, E, C1, E1;
12641296
1265   inverse((Vs * shared.SinAzs >> 15) + shared.VOffset, 7, &C, &E);
1297   inverse((Vs * dsp1_state.shared.SinAzs >> 15) + dsp1_state.shared.VOffset, 7, &C, &E);
12661298
1267   E += shared.CentreZ_E;
1268   C1 = C * shared.CentreZ_C >> 15;
1299   E += dsp1_state.shared.CentreZ_E;
1300   C1 = C * dsp1_state.shared.CentreZ_C >> 15;
12691301
1270   E1 = E + shared.SecAZS_E2;
1302   E1 = E + dsp1_state.shared.SecAZS_E2;
12711303
1272   normalize(C1, &C, &E);
1273   C = denormalizeAndClip(C, E);
1304   normalize(C1, &C, &E);
1305   C = denormalize_and_clip(C, E);
12741306
1275   *An = C * shared.CosAas >> 15;
1276   *Cn = C * shared.SinAas >> 15;
1307   *An = C * dsp1_state.shared.CosAas >> 15;
1308   *Cn = C * dsp1_state.shared.SinAas >> 15;
12771309
1278   normalize(C1 * shared.SecAZS_C2 >> 15, &C, &E1);
1279   C = denormalizeAndClip(C, E1);
1310   normalize(C1 * dsp1_state.shared.SecAZS_C2 >> 15, &C, &E1);
1311   C = denormalize_and_clip(C, E1);
12801312
1281   *Bn = C * -shared.SinAas >> 15;
1282   *Dn = C * shared.CosAas >> 15;
1313   *Bn = C * -dsp1_state.shared.SinAas >> 15;
1314   *Dn = C * dsp1_state.shared.CosAas >> 15;
12831315}
12841316
12851317//////////////////////////////////////////////////////////////////
r7621r7622
12921324// H is positive rightward, but V is positive downward; this is why
12931325// the signs take that configuration
12941326
1295static void DSP1_target(INT16 *input, INT16 *output)
1327static void dsp1_target( INT16 *input, INT16 *output )
12961328{
1297   INT16 H = input[0];
1298   INT16 V = input[1];
1299   INT16* X = &output[0];
1300   INT16* Y = &output[1];
1329   INT16 H = input[0];
1330   INT16 V = input[1];
1331   INT16* X = &output[0];
1332   INT16* Y = &output[1];
13011333
1302   INT16 C, E, C1, E1;
1334   INT16 C, E, C1, E1;
13031335
1304   inverse((V * shared.SinAzs >> 15) + shared.VOffset, 8, &C, &E);
1336   inverse((V * dsp1_state.shared.SinAzs >> 15) + dsp1_state.shared.VOffset, 8, &C, &E);
13051337
1306   E += shared.CentreZ_E;
1307   C1 = C * shared.CentreZ_C >> 15;
1338   E += dsp1_state.shared.CentreZ_E;
1339   C1 = C * dsp1_state.shared.CentreZ_C >> 15;
13081340
1309   E1 = E + shared.SecAZS_E1;
1341   E1 = E + dsp1_state.shared.SecAZS_E1;
13101342
1311   H <<= 8;
1312   normalize(C1, &C, &E);
1313   C = denormalizeAndClip(C, E) * H >> 15;
1343   H <<= 8;
1344   normalize(C1, &C, &E);
1345   C = denormalize_and_clip(C, E) * H >> 15;
13141346
1315   *X = shared.CentreX + (C * shared.CosAas >> 15);
1316   *Y = shared.CentreY - (C * shared.SinAas >> 15);
1347   *X = dsp1_state.shared.CentreX + (C * dsp1_state.shared.CosAas >> 15);
1348   *Y = dsp1_state.shared.CentreY - (C * dsp1_state.shared.SinAas >> 15);
13171349
1318   V <<= 8;
1319   normalize(C1 * shared.SecAZS_C1 >> 15, &C, &E1);
1320   C = denormalizeAndClip(C, E1) * V >> 15;
1350   V <<= 8;
1351   normalize(C1 * dsp1_state.shared.SecAZS_C1 >> 15, &C, &E1);
1352   C = denormalize_and_clip(C, E1) * V >> 15;
13211353
1322   *X += C * -shared.SinAas >> 15;
1323   *Y += C * shared.CosAas >> 15;
1354   *X += C * -dsp1_state.shared.SinAas >> 15;
1355   *Y += C * dsp1_state.shared.CosAas >> 15;
13241356}
13251357
13261358//////////////////////////////////////////////////////////////////
r7621r7622
13291361// 'enlargement ratio' (M). The positive directions on the screen are as described
13301362// in the targe command. M is scaled down by 2^-7, that is, M==0x0100 means ratio 1:1
13311363
1332static void DSP1_project(INT16 *input, INT16 *output)
1364static void dsp1_project( INT16 *input, INT16 *output )
13331365{
1334   INT16 X = input[0];
1335   INT16 Y = input[1];
1336   INT16 Z = input[2];
1337   INT16* H = &output[0];
1338   INT16* V = &output[1];
1339   INT16* M = &output[2];
1366   INT16 X = input[0];
1367   INT16 Y = input[1];
1368   INT16 Z = input[2];
1369   INT16* H = &output[0];
1370   INT16* V = &output[1];
1371   INT16* M = &output[2];
13401372
1341   INT32 aux, aux4;
1342   INT16 E, E2, E3, E4, E5, refE, E6, E7;
1343   INT16 C2, C4, C6, C8, C9, C10, C11, C12, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26;
1344   INT16 Px, Py, Pz;
1373   INT32 aux, aux4;
1374   INT16 E, E2, E3, E4, E5, refE, E6, E7;
1375   INT16 C2, C4, C6, C8, C9, C10, C11, C12, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26;
1376   INT16 Px, Py, Pz;
13451377
1346   E4=E3=E2=E=E5=0;
1378   E4 = E3 = E2 = E = E5 = 0;
13471379
1348   normalizeDouble((INT32)(X)-shared.Gx, &Px, &E4);
1349   normalizeDouble((INT32)(Y)-shared.Gy, &Py, &E);
1350   normalizeDouble((INT32)(Z)-shared.Gz, &Pz, &E3);
1351   Px>>=1; E4--;   // to avoid overflows when calculating the scalar products
1352   Py>>=1; E--;
1353   Pz>>=1; E3--;
1380   normalize_double((INT32)(X) - dsp1_state.shared.Gx, &Px, &E4);
1381   normalize_double((INT32)(Y) - dsp1_state.shared.Gy, &Py, &E);
1382   normalize_double((INT32)(Z) - dsp1_state.shared.Gz, &Pz, &E3);
1383   Px >>= 1; E4--;   // to avoid overflows when calculating the scalar products
1384   Py >>= 1; E--;
1385   Pz >>= 1; E3--;
13541386
1355   refE = (E<E3)?E:E3;
1356   refE = (refE<E4)?refE:E4;
1387   refE = (E < E3) ? E : E3;
1388   refE = (refE < E4) ? refE : E4;
13571389
1358   Px=shiftR(Px,E4-refE);    // normalize them to the same exponent
1359   Py=shiftR(Py,E-refE);
1360   Pz=shiftR(Pz,E3-refE);
1390   Px = shiftR(Px, E4 - refE);    // normalize them to the same exponent
1391   Py = shiftR(Py, E  - refE);
1392   Pz = shiftR(Pz, E3 - refE);
13611393
1362   C11= -(Px*shared.Nx>>15);
1363   C8= -(Py*shared.Ny>>15);
1364   C9= -(Pz*shared.Nz>>15);
1365   C12=C11+C8+C9;   // this cannot overflow!
1394   C11 = -(Px * dsp1_state.shared.Nx >> 15);
1395   C8  = -(Py * dsp1_state.shared.Ny >> 15);
1396   C9  = -(Pz * dsp1_state.shared.Nz >> 15);
1397   C12 = C11 + C8 + C9;   // this cannot overflow!
13661398
1367   aux4=C12;   // de-normalization with 32-bits arithmetic
1368   refE = 16-refE;    // refE can be up to 3
1369   if (refE>=0)
1370      aux4 <<=(refE);
1371   else
1372      aux4 >>=-(refE);
1373   if (aux4==-1) aux4 = 0;      // why?
1374   aux4>>=1;
1399   aux4 = C12;   // de-normalization with 32-bits arithmetic
1400   refE = 16 - refE;    // refE can be up to 3
1401   if (refE >= 0)
1402      aux4 <<=  (refE);
1403   else
1404      aux4 >>= -(refE);
1405   if (aux4 == -1)
1406      aux4 = 0;      // why?
1407   aux4 >>= 1;
13751408
1376   aux = (UINT16)(shared.Les) + aux4;   // Les - the scalar product of P with the normal vector of the screen
1377   normalizeDouble(aux, &C10, &E2);
1378   E2 = 15-E2;
1409   aux = (UINT16)(dsp1_state.shared.Les) + aux4;   // Les - the scalar product of P with the normal vector of the screen
1410   normalize_double(aux, &C10, &E2);
1411   E2 = 15 - E2;
13791412
1380   inverse(C10, 0, &C4, &E4);
1381   C2=C4*shared.C_Les>>15;                 // scale factor
1413   inverse(C10, 0, &C4, &E4);
1414   C2 = C4 * dsp1_state.shared.C_Les >> 15;                 // scale factor
13821415
13831416
1384   // H
1385   E7=0;
1386   C16= (Px*shared.Hx>>15);
1387   C20= (Py*shared.Hy>>15);
1388   C17=C16+C20;   // scalar product of P with the normalized horizontal vector of the screen...
1417   // H
1418   E7 = 0;
1419   C16 = (Px * dsp1_state.shared.Hx >> 15);
1420   C20 = (Py * dsp1_state.shared.Hy >> 15);
1421   C17 = C16 + C20;   // scalar product of P with the normalized horizontal vector of the screen...
13891422
1390   C18=C17*C2>>15;    // ... multiplied by the scale factor
1391   normalize(C18, &C19, &E7);
1392   *H=denormalizeAndClip(C19, shared.E_Les-E2+refE+E7);
1423   C18 = C17 * C2 >> 15;    // ... multiplied by the scale factor
1424   normalize(C18, &C19, &E7);
1425   *H = denormalize_and_clip(C19, dsp1_state.shared.E_Les - E2 + refE + E7);
13931426
1394   // V
1395   E6=0;
1396   C21 = Px*shared.Vx>>15;
1397   C22 = Py*shared.Vy>>15;
1398   C23 = Pz*shared.Vz>>15;
1399   C24=C21+C22+C23;   // scalar product of P with the normalized vertical vector of the screen...
1427   // V
1428   E6 = 0;
1429   C21 = Px * dsp1_state.shared.Vx >> 15;
1430   C22 = Py * dsp1_state.shared.Vy >> 15;
1431   C23 = Pz * dsp1_state.shared.Vz >> 15;
1432   C24 = C21 + C22 + C23;   // scalar product of P with the normalized vertical vector of the screen...
14001433
1401   C26=C24*C2>>15;    // ... multiplied by the scale factor
1402   normalize(C26, &C25, &E6);
1403   *V=denormalizeAndClip(C25, shared.E_Les-E2+refE+E6);
1434   C26 = C24 * C2 >> 15;    // ... multiplied by the scale factor
1435   normalize(C26, &C25, &E6);
1436   *V = denormalize_and_clip(C25, dsp1_state.shared.E_Les - E2 + refE + E6);
14041437
1405   // M
1406   normalize(C2, &C6, &E4);
1407   *M=denormalizeAndClip(C6, E4+shared.E_Les-E2-7); // M is the scale factor divided by 2^7
1438   // M
1439   normalize(C2, &C6, &E4);
1440   *M = denormalize_and_clip(C6, E4 + dsp1_state.shared.E_Les - E2 - 7); // M is the scale factor divided by 2^7
14081441}
14091442
14101443//////////////////////////////////////////////////////////////////
r7621r7622
14131446// this is done by linear interpolation between
14141447// the points of a look-up table
14151448
1416static INT16 DSP1_sin(INT16 Angle)
1449static INT16 dsp1_sin( INT16 Angle )
14171450{
1418   INT32 S;
1451   INT32 S;
14191452
1420   if (Angle < 0) {
1421      if (Angle == -32768) return 0;
1422      return -DSP1_sin(-Angle);
1423   }
1424   S = DSP1_SinTable[Angle >> 8] + (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[0x40 + (Angle >> 8)] >> 15);
1425   if (S > 32767) S = 32767;
1426   return (INT16) S;
1453   if (Angle < 0)
1454   {
1455      if (Angle == -32768)
1456         return 0;
1457
1458      return -dsp1_sin(-Angle);
1459   }
1460   S = dsp1_sin_table[Angle >> 8] + (dsp1_mul_table[Angle & 0xff] * dsp1_sin_table[0x40 + (Angle >> 8)] >> 15);
1461   if (S > 32767)
1462      S = 32767;
1463   return (INT16) S;
14271464}
14281465
14291466//////////////////////////////////////////////////////////////////
r7621r7622
14311468// Calculate the cosine of the input parameter.
14321469// It's used the same method than in sin(INT16)
14331470
1434static INT16 DSP1_cos(INT16 Angle)
1471static INT16 dsp1_cos( INT16 Angle )
14351472{
1436   INT32 S;
1473   INT32 S;
14371474
1438   if (Angle < 0) {
1439      if (Angle == -32768) return -32768;
1440      Angle = -Angle;
1441   }
1442   S = DSP1_SinTable[0x40 + (Angle >> 8)] - (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[Angle >> 8] >> 15);
1443   if (S < -32768) S = -32767;
1444   return (INT16) S;
1475   if (Angle < 0)
1476   {
1477      if (Angle == -32768)
1478         return -32768;
1479      Angle = -Angle;
1480   }
1481   S = dsp1_sin_table[0x40 + (Angle >> 8)] - (dsp1_mul_table[Angle & 0xff] * dsp1_sin_table[Angle >> 8] >> 15);
1482   if (S < -32768)
1483      S = -32767;
1484   return (INT16) S;
14451485}
14461486
14471487//////////////////////////////////////////////////////////////////
r7621r7622
14551495// that verify Coefficient*y=1/2. This is why you have to correct the exponent by one
14561496// unit at the end.
14571497
1458static void inverse(INT16 Coefficient, INT16 Exponent, INT16 *iCoefficient, INT16 *iExponent)
1498static void inverse( INT16 Coefficient, INT16 Exponent, INT16 *iCoefficient, INT16 *iExponent )
14591499{
1460   // Step One: Division by Zero
1461   if (Coefficient == 0x0000)
1462   {
1463      *iCoefficient = 0x7fff;
1464      *iExponent = 0x002f;
1465   }
1466   else
1467   {
1468      INT16 Sign = 1;
1500   // Step One: Division by Zero
1501   if (Coefficient == 0x0000)
1502   {
1503      *iCoefficient = 0x7fff;
1504      *iExponent = 0x002f;
1505   }
1506   else
1507   {
1508      INT16 Sign = 1;
14691509
1470      // Step Two: Remove Sign
1471      if (Coefficient < 0)
1472      {
1473         if (Coefficient < -32767) Coefficient = -32767;
1474         Coefficient = -Coefficient;
1475         Sign = -1;
1476      }
1510      // Step Two: Remove Sign
1511      if (Coefficient < 0)
1512      {
1513         if (Coefficient < -32767)
1514            Coefficient = -32767;
1515         Coefficient = -Coefficient;
1516         Sign = -1;
1517      }
14771518
1478      // Step Three: Normalize
1479      while (Coefficient < 0x4000)
1480      {
1481         Coefficient <<= 1;
1482         Exponent--;
1483      }
1519      // Step Three: Normalize
1520      while (Coefficient < 0x4000)
1521      {
1522         Coefficient <<= 1;
1523         Exponent--;
1524      }
14841525
1485      // Step Four: Special Case
1486      if (Coefficient == 0x4000)
1487         if (Sign == 1) *iCoefficient = 0x7fff;
1488      else  {
1489         *iCoefficient = -0x4000;
1490         Exponent--;
1491      }
1492      else {
1493         // Step Five: Initial Guess
1494         INT16 i = DSP1_DataRom[((Coefficient - 0x4000) >> 7) + 0x0065];
1526      // Step Four: Special Case
1527      if (Coefficient == 0x4000)
1528         if (Sign == 1) *iCoefficient = 0x7fff;
1529      else  {
1530         *iCoefficient = -0x4000;
1531         Exponent--;
1532      }
1533      else {
1534         // Step Five: Initial Guess
1535         INT16 i = dsp1_state.DataRom[((Coefficient - 0x4000) >> 7) + 0x0065];
14951536
1496         // Step Six: Iterate Newton's Method
1497         i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1;
1498         i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1;
1537         // Step Six: Iterate Newton's Method
1538         i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1;
1539         i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1;
14991540
1500         *iCoefficient = i * Sign;
1501      }
1541         *iCoefficient = i * Sign;
1542      }
15021543
1503      *iExponent = 1 - Exponent;
1504   }
1544      *iExponent = 1 - Exponent;
1545   }
15051546}
15061547
15071548//////////////////////////////////////////////////////////////////
15081549
1509static INT16 denormalizeAndClip(INT16 C, INT16 E)
1550static INT16 denormalize_and_clip( INT16 C, INT16 E )
15101551{
1511   if (E > 0) {
1512      if (C > 0) return 32767; else if (C < 0) return -32767;
1513   } else {
1514      if (E < 0) return C * DSP1_DataRom[0x0031 + E] >> 15;
1515   }
1516   return C;
1552   if (E > 0)
1553   {
1554      if (C > 0)
1555         return 32767;
1556      else if (C < 0)
1557         return -32767;
1558   }
1559   else
1560   {
1561      if (E < 0)
1562         return C * dsp1_state.DataRom[0x0031 + E] >> 15;
1563   }
1564   return C;
15171565}
15181566
15191567//////////////////////////////////////////////////////////////////
r7621r7622
15231571// where the absolute value of Coefficient is >= 1/2
15241572// (Coefficient>=0x4000 or Coefficient <= (INT16)0xc001)
15251573
1526static void normalize(INT16 m, INT16 *Coefficient, INT16 *Exponent)
1574static void normalize( INT16 m, INT16 *Coefficient, INT16 *Exponent )
15271575{
1528   INT16 i = 0x4000;
1529   INT16 e = 0;
1576   INT16 i = 0x4000;
1577   INT16 e = 0;
15301578
1531   if (m < 0)
1532      while ((m & i) && i)
1533   {
1534      i >>= 1;
1535      e++;
1536   }
1537   else
1538      while (!(m & i) && i)
1539   {
1540      i >>= 1;
1541      e++;
1542   }
1579   if (m < 0)
1580      while ((m & i) && i)
1581      {
1582         i >>= 1;
1583         e++;
1584      }
1585   else
1586      while (!(m & i) && i)
1587      {
1588         i >>= 1;
1589         e++;
1590      }
15431591
1544   if (e > 0)
1545      *Coefficient = m * DSP1_DataRom[0x21 + e] << 1;
1546   else
1547      *Coefficient = m;
1592   if (e > 0)
1593      *Coefficient = m * dsp1_state.DataRom[0x21 + e] << 1;
1594   else
1595      *Coefficient = m;
15481596
1549   *Exponent -= e;
1597   *Exponent -= e;
15501598}
15511599
15521600//////////////////////////////////////////////////////////////////
15531601
15541602// Same than 'normalize' but with an INT32 input
15551603
1556static void normalizeDouble(INT32 Product, INT16 *Coefficient, INT16 *Exponent)
1604static void normalize_double( INT32 Product, INT16 *Coefficient, INT16 *Exponent )
15571605{
1558   INT16 n = Product & 0x7fff;
1559   INT16 m = Product >> 15;
1560   INT16 i = 0x4000;
1561   INT16 e = 0;
1606   INT16 n = Product & 0x7fff;
1607   INT16 m = Product >> 15;
1608   INT16 i = 0x4000;
1609   INT16 e = 0;
15621610
1563   if (m < 0)
1564      while ((m & i) && i)
1565   {
1566      i >>= 1;
1567      e++;
1568   }
1569   else
1570      while (!(m & i) && i)
1571   {
1572      i >>= 1;
1573      e++;
1574   }
1611   if (m < 0)
1612      while ((m & i) && i)
1613      {
1614         i >>= 1;
1615         e++;
1616      }
1617   else
1618      while (!(m & i) && i)
1619      {
1620         i >>= 1;
1621         e++;
1622      }
15751623
1576   if (e > 0)
1577   {
1578      *Coefficient = m * DSP1_DataRom[0x0021 + e] << 1;
1624   if (e > 0)
1625   {
1626      *Coefficient = m * dsp1_state.DataRom[0x0021 + e] << 1;
15791627
1580      if (e < 15)
1581         *Coefficient += n * DSP1_DataRom[0x0040 - e] >> 15;
1582      else
1583      {
1584         i = 0x4000;
1628      if (e < 15)
1629         *Coefficient += n * dsp1_state.DataRom[0x0040 - e] >> 15;
1630      else
1631      {
1632         i = 0x4000;
15851633
1586         if (m < 0)
1587            while ((n & i) && i)
1588         {
1589            i >>= 1;
1590            e++;
1591         }
1592         else
1593            while (!(n & i) && i)
1594         {
1595            i >>= 1;
1596            e++;
1597         }
1634         if (m < 0)
1635            while ((n & i) && i)
1636            {
1637               i >>= 1;
1638               e++;
1639            }
1640         else
1641            while (!(n & i) && i)
1642            {
1643               i >>= 1;
1644               e++;
1645            }
15981646
1599         if (e > 15)
1600            *Coefficient = n * DSP1_DataRom[0x0012 + e] << 1;
1601         else
1602            *Coefficient += n;
1603      }
1604   }
1605   else
1606      *Coefficient = m;
1647         if (e > 15)
1648            *Coefficient = n * dsp1_state.DataRom[0x0012 + e] << 1;
1649         else
1650            *Coefficient += n;
1651      }
1652   }
1653   else
1654      *Coefficient = m;
16071655
1608   *Exponent = e;
1656   *Exponent = e;
16091657}
16101658
16111659//////////////////////////////////////////////////////////////////
16121660
16131661// Shift to the right
16141662
1615static INT16 shiftR(INT16 C, INT16 E)
1663static INT16 shiftR( INT16 C, INT16 E )
16161664{
1617   return (C * DSP1_DataRom[0x0031 + E] >> 15);
1665   return (C * dsp1_state.DataRom[0x0031 + E] >> 15);
16181666}
1667
1668//////////////////////////////////////////////////////////////////
1669
1670// Save DSP1 variables
1671
1672static void dsp1_register_save( running_machine *machine )
1673{
1674   state_save_register_global(machine, dsp1_state.Sr);
1675   state_save_register_global(machine, dsp1_state.Dr);
1676   state_save_register_global(machine, dsp1_state.SrLowByteAccess);
1677   state_save_register_global(machine, dsp1_state.FsmMajorState);
1678   state_save_register_global(machine, dsp1_state.Command);
1679   state_save_register_global(machine, dsp1_state.DataCounter);
1680   state_save_register_global(machine, dsp1_state.Freeze);
1681   state_save_register_global_array(machine, dsp1_state.ReadBuffer);
1682   state_save_register_global_array(machine, dsp1_state.WriteBuffer);
1683   state_save_register_global_array(machine, dsp1_state.shared.MatrixA[0]);
1684   state_save_register_global_array(machine, dsp1_state.shared.MatrixA[1]);
1685   state_save_register_global_array(machine, dsp1_state.shared.MatrixA[2]);
1686   state_save_register_global_array(machine, dsp1_state.shared.MatrixB[0]);
1687   state_save_register_global_array(machine, dsp1_state.shared.MatrixB[1]);
1688   state_save_register_global_array(machine, dsp1_state.shared.MatrixB[2]);
1689   state_save_register_global_array(machine, dsp1_state.shared.MatrixC[0]);
1690   state_save_register_global_array(machine, dsp1_state.shared.MatrixC[1]);
1691   state_save_register_global_array(machine, dsp1_state.shared.MatrixC[2]);
1692   state_save_register_global(machine, dsp1_state.shared.CentreX);
1693   state_save_register_global(machine, dsp1_state.shared.CentreY);
1694   state_save_register_global(machine, dsp1_state.shared.CentreZ);
1695   state_save_register_global(machine, dsp1_state.shared.CentreZ_C);
1696   state_save_register_global(machine, dsp1_state.shared.CentreZ_E);
1697   state_save_register_global(machine, dsp1_state.shared.VOffset);
1698   state_save_register_global(machine, dsp1_state.shared.Les);
1699   state_save_register_global(machine, dsp1_state.shared.C_Les);
1700   state_save_register_global(machine, dsp1_state.shared.E_Les);
1701   state_save_register_global(machine, dsp1_state.shared.SinAas);
1702   state_save_register_global(machine, dsp1_state.shared.CosAas);
1703   state_save_register_global(machine, dsp1_state.shared.SinAzs);
1704   state_save_register_global(machine, dsp1_state.shared.CosAzs);
1705   state_save_register_global(machine, dsp1_state.shared.SinAZS);
1706   state_save_register_global(machine, dsp1_state.shared.CosAZS);
1707   state_save_register_global(machine, dsp1_state.shared.SecAZS_C1);
1708   state_save_register_global(machine, dsp1_state.shared.SecAZS_E1);
1709   state_save_register_global(machine, dsp1_state.shared.SecAZS_C2);
1710   state_save_register_global(machine, dsp1_state.shared.SecAZS_E2);
1711   state_save_register_global(machine, dsp1_state.shared.Nx);
1712   state_save_register_global(machine, dsp1_state.shared.Ny);
1713   state_save_register_global(machine, dsp1_state.shared.Nz);
1714   state_save_register_global(machine, dsp1_state.shared.Gx);
1715   state_save_register_global(machine, dsp1_state.shared.Gy);
1716   state_save_register_global(machine, dsp1_state.shared.Gz);
1717   state_save_register_global(machine, dsp1_state.shared.Hx);
1718   state_save_register_global(machine, dsp1_state.shared.Hy);
1719   state_save_register_global(machine, dsp1_state.shared.Vx);
1720   state_save_register_global(machine, dsp1_state.shared.Vy);
1721   state_save_register_global(machine, dsp1_state.shared.Vz);
1722}

Previous 15994 Revisions Next


© 1998-2018 The MESS Team